Search

@creativedutchmen - Nope. No error, ETM installed or not installed. Of course I realize that although bauhouse and I were getting an error on the same line of extension.driver.php, what caused the errors might be different. I got the error when I tried to open System/Preferences to select my Active Members Section after I created it.

Well, the reason for the error is the same - Members now supports ETM, so it adds a dropdown menu to select event filters. However, because listing these filters uses the EmailTemplateManager class, and this class is not always defined, it would pop up the errors you and bauhouse had.

Ofcourse, by removing the functionality (which you have done, essentially, because the emailtemplatemanager extension does not exist), everything goes back to what it was before ETM was supported by Members, hence: no error.

The fix I proposed (and has been pulled) fixes the problem, while also keeping the functionality intact.

Nice work Brendo. Can't wait till this is released :D

Yep, I pushed a fix earlier today

Ah, works great now.. I suppose I should have tried to use the latest files before posting..

I do seem to be having problems with the login form from the readme.. It's giving me "Invalid Expression" errors for the name value on the inputs. Forgive the ignorance, but is "element_name" supposed to be anything specific? I've tried a couple variations of what I think it could be with no success.

Here's the full error:

XSLTProcessor::importStylesheet(): Invalid expression
XSLTProcessor::importStylesheet(): Attribute 'name': Failed to compile the expression 'Member: Username element_name' in the AVT.
XSLTProcessor::importStylesheet(): Invalid expression
XSLTProcessor::importStylesheet(): Attribute 'name': Failed to compile the expression 'Member: Password element_name' in the AVT.
XSLTProcessor::transformToXml(): No stylesheet associated to this object

You need to replace the curly braces (shown in the extension documentation) and the text they contain with the element name for each of the member fields required for authentication.

If you had two fields, Username and Password, the element names would be username and password. So the form would look like this:

<form method="post" autocomplete='off'>
    <label>Username
        <input name="fields[username]" type="text" />
    </label>
    <label>Password
        <input name="fields[password]" type="password" />
    </label>
    <input name="redirect" type="hidden" value="{$root}/account/" />
    <input name="member-action[login]" type="submit" value="Login" />
</form>

Ah! I feel totally foolish.. I tried that in one of my attempts, except I still kept the curly braces in.. :|

Thanks!

I think it would be helpful if the salt was not required. This would allow myself and others to convert an existing membership database. As is, all users would be required to create new passwords and/or utilize the forgot password because it's not possible to update a current password stored using sha1 to incorporate the salt.

What would be considered the most practical way to get information on the logged in user? Such as their permissions, username, avatar, etc. Creating a datasource with a filter for $member-id, I assume?

If that's the case, how would one go about getting that datasource to return nothing if the user is logged out? Right now, if I'm logged out, the datasource pulls all entries from the Members section, as the $member-id param no longer exists.

That's a good point. I limit the result XML to a single entry for now.

Oh. I've got it. Use Parameter Enumerators.

{$member-id:0}

The default value will be 0 if $member-id is not set. There is no member that will have an id of 0.

Ah, perfect! Thank you yet again..

Symphony is seriously so underrated, I love this system.

Timezone field

Has anyone already created a front end form to create Member entries with this extension? I'm wondering how others have gone about building a select field for the Member: Timezone field. The Members extension provides timezone options from different regions as options for the select box. To do this on the front end, I suppose we would need an XML data source to populate the select element with options.

I'd rather not reinvent the wheel if someone has already created this XML.

Umm. Never mind. The event creates the form options automatically in the example front-end form markup.

Edit: Ignore the following. The example HTML is not correct.

On second thought, to be able to handle field validation and apply a selected attribute to the option, it would be helpful to have the XML for the timezones. The following template works to turn the example XML into a static data source.

<?xml version='1.0' encoding='utf-8'?>
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>

<xsl:output method='xml' version='1.0' encoding='utf-8' indent='yes'/>

<xsl:template match="/">
    <timezones>
        <xsl:apply-templates />
    </timezones>
</xsl:template>

<xsl:template match="select/option">
    <timezone><xsl:value-of select="." /></timezone>
</xsl:template>

</xsl:stylesheet>

I've realized the example markup is not correct. The value attribute should not be the same as the text node value of the option element. For example, the option for Vancouver should be this:

<option value="America/Vancouver" selected="selected">Vancouver -07:00</option>

rather than this:

<option value="Vancouver -07:00">Vancouver -07:00</option>

Saving to a front end form containing Members extension fields results in a Symphony Fatal Database Error:

Symphony Fatal Database Error
Column 'strength' cannot be null
An error occurred while attempting to execute the following query
INSERT INTO `sym_entries_data_150` (`entry_id`, `password`, `recovery-code`, `length`, `strength`, `reset`, `expires`) VALUES ('1', 'THE-HASH-VALUE-GOES-HERE', NULL, '7', NULL, 'no', NULL)

This occurs even though the password field is not part of the form.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:import href="../utilities/intranet.xsl"/>

<xsl:variable name="event-action" select="'edit-member'"/>
<xsl:variable name="event" select="/data/events/*[name()=$event-action]"/>

<xsl:template match="data">
    <section class="main">
        <div class="content">
            <xsl:for-each select="member-info/entry">
                <h2 class="heading">Edit Profile for <xsl:value-of select="username"/></h2>
                <xsl:if test="$event[@result = 'success']">
                    <div id="system-message">
                        <p class="success">Your profile has been updated.</p>
                    </div>
                </xsl:if>
                <form method="post" action="{$current-url}">
                    <fieldset>
                        <p>
                            <xsl:if test="$event/name">
                                <xsl:attribute name="class">error</xsl:attribute>
                            </xsl:if>
                            <label for="name">Full Name</label>
                            <input id="name" name="fields[name]" type="text" value="{name}" />
                        </p>
                        <p>
                            <xsl:if test="$event/email-address">
                                <xsl:attribute name="class">error</xsl:attribute>
                            </xsl:if>
                            <label for="email">Email</label>
                            <input id="email" name="fields[email-address]" type="text" value="{email-address}" />
                        </p>
                        <p>
                            <label for="location">Country</label>
                            <select id="location" name="fields[location]">
                                <xsl:for-each select="/data/location/item">
                                    <option value="{@value}">
                                        <xsl:if test="@value = /data/member-info/entry/location">
                                            <xsl:attribute name="selected">selected</xsl:attribute>
                                        </xsl:if>
                                        <xsl:value-of select="."/>
                                    </option>
                                </xsl:for-each>
                            </select>
                        </p>
                        <p>
                            <xsl:if test="$event/city">
                                <xsl:attribute name="class">error</xsl:attribute>
                            </xsl:if>
                            <label for="city">City</label>
                            <input id="city" name="fields[city]" type="text" value="{city}" />
                        </p>
                        <p>
                            <label for="timezone">Timezone</label>
                            <select id="timezone" name="fields[timezone]">
                                <xsl:for-each select="/data/timezones/timezone">
                                    <option value="{@value}">
                                        <xsl:if test="@value = /data/member-info/entry/timezone/name">
                                            <xsl:attribute name="selected">selected</xsl:attribute>
                                        </xsl:if>
                                        <xsl:value-of select="."/>
                                    </option>
                                </xsl:for-each>
                            </select>
                        </p>
                        <p>
                            <xsl:if test="$event/website">
                                <xsl:attribute name="class">error</xsl:attribute>
                            </xsl:if>
                            <label for="website">Website</label>
                            <input id="website" name="fields[website]" type="text" value="{website}" />
                        </p>
                        <p class="option">
                            <label for="opt-in">Opt-in</label>
                            <span>
                                <input name="fields[email-opt-in]" value="no" type="hidden"/>
                                <input id="opt-in" name="fields[email-opt-in]" value="yes" type="checkbox">
                                    <xsl:if test="email-opt-in = 'Yes'">
                                        <xsl:attribute name="checked">checked</xsl:attribute>
                                    </xsl:if>
                                </input>
                                <xsl:text> Send me email when there is important Symphony news.</xsl:text>
                            </span>
                        </p>
                        <p class="option">
                            <label>Picture</label>
                            <span>To change your profile picture, sign up at <a href="http://gravatar.com/">Gravatar</a> with the same email address you provided here.</span>
                        </p>
                        <input name="id" type="hidden" value="{@id}"/>
                        <div id="submission">
                            <input id="submit" name="action[{$event-action}]" type="submit" value="Save" class="button"/>
                            <a id="cancel" href="{$root}/members/{username}/" class="button">Cancel and go back</a>
                        </div>
                    </fieldset>
                </form>
            </xsl:for-each>
        </div>
    </section>
</xsl:template>

</xsl:stylesheet>

Try this commit bauhouse. I've improved the getExampleFormMarkup function so that it will output the same markup that's used in the backend.

As for your recent post, was this Member created from the Frontend or the backend?

It's odd that even though no password field in the form, the length is still apparently 7.

This member was created in the backend. I was using the form above to test editing an existing member entry.

I'm finding that the Member: Update Password filter always redirects to the root URL on success (see line 231 of the SymphonyMember class):

if(isset($_REQUEST['redirect'])) {
    redirect($_REQUEST['redirect']);
}
else {
    redirect(URL);
}

I would expect that there should be no redirect unless specified:

if(isset($_REQUEST['redirect'])) {
    redirect($_REQUEST['redirect']);
}

brendo, thanks for updating the example form markup. That's working well now.

The update password field is working great with the above modification. A problem, if there are a number of required fields, is the need for several hidden fields for these required fields. So, the following form results in errors because of required fields:

<xsl:template match="member-info/entry" mode="update-password">
    <form method="post">
        <fieldset>
            <p>
                <xsl:if test="$event/password">
                    <xsl:attribute name="class">error</xsl:attribute>
                </xsl:if>
                <label for="password">Password</label>
                <input id="password" name="fields[password][password]" type="password" />
            </p>
            <p>
                <xsl:if test="$event/password">
                    <xsl:attribute name="class">error</xsl:attribute>
                </xsl:if>
                <label for="confirm-password">Confirm Password</label>
                <input id="confirm-password" name="fields[password][confirm]" type="password" />
            </p>
            <div id="submission">
                <input name="id" type="hidden" value="{@id}" />
                <input id="submit" name="action[{$event-action}]" type="submit" value="Change Password" class="button"/>
                <a id="cancel" href="{$root}/members/{username}/" class="button">Cancel and go back</a>
            </div>
        </fieldset>
    </form>
</xsl:template>

Hidden fields must be added:

<xsl:template match="member-info/entry" mode="update-password">
    <form method="post">
        <fieldset>
            <p>
                <xsl:if test="$event/password">
                    <xsl:attribute name="class">error</xsl:attribute>
                </xsl:if>
                <label for="password">Password</label>
                <input id="password" name="fields[password][password]" type="password" />
            </p>
            <p>
                <xsl:if test="$event/password">
                    <xsl:attribute name="class">error</xsl:attribute>
                </xsl:if>
                <label for="confirm-password">Confirm Password</label>
                <input id="confirm-password" name="fields[password][confirm]" type="password" />
            </p>
            <div id="submission">
                <input name="id" type="hidden" value="{@id}" />
                <input name="fields[name]" type="hidden" value="{name}" />
                <input name="fields[username]" type="hidden" value="{username}" />
                <input name="fields[email-address]" type="hidden" value="{email-address}" />
                <input name="fields[role]" type="hidden" value="{role/@id}" />
                <input id="submit" name="action[{$event-action}]" type="submit" value="Change Password" class="button"/>
                <a id="cancel" href="{$root}/members/{username}/" class="button">Cancel and go back</a>
            </div>
        </fieldset>
    </form>
</xsl:template>

Would it make sense to have an option to bypass required fields when updating the password? This seems a little more cumbersome compared to the old implementation.

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details