2

I've made my own profile plugin based on the tutorials here and here. But they are a little outdated so I had to fill in some gaps. Now, the plugin installs correctly, and if I click on it, I'm able to see the display options for every field. However, the fields are not displaying neither in the frontend, nor in the backend. What am I missing?

Here's my code for the profile_ei.php file.

<?php

defined('JPATH_BASE') or die;

/**
 * An example custom profile plugin.
 */
class PlgUserProfileEI extends JPlugin{
    /**
     * Date of birth.
     * @var    string
     */
    private $date = '';

    /**
     * Load the language file on instantiation.
     * @var    boolean
     * @since  3.1
     */
    protected $autoloadLanguage = true;

    /**
     * Constructor
     *
     * @param   object  &$subject  The object to observe
     * @param   array   $config    An array that holds the plugin configuration
     */
    public function __construct(& $subject, $config){
        parent::__construct($subject, $config);
        JFormHelper::addFieldPath(__DIR__ . '/fields');
    }

    /**
     * Runs on content preparation
     *
     * @param   string  $context  The context for the data
     * @param   object  $data     An object containing the data for the form.
     *
     * @return  boolean
     */
    public function onContentPrepareData($context, $data){
        // Check we are manipulating a valid form.
        if (!in_array($context, array('com_users.profile', 'com_users.user', 'com_users.registration', 'com_admin.profile'))){
            return true;
        }

        if (is_object($data)){
            $userId = isset($data->id) ? $data->id : 0;

            if (!isset($data->profile_ei) and $userId > 0){
                // Load the profile data from the database.
                $db = JFactory::getDbo();
                $db->setQuery(
                    'SELECT profile_key, profile_value FROM #__user_profiles' .
                        ' WHERE user_id = ' . (int) $userId . " AND profile_key LIKE 'profile_ei.%'" .
                        ' ORDER BY ordering'
                );

                try{
                    $results = $db->loadRowList();
                }
                catch (RuntimeException $e){
                    $this->_subject->setError($e->getMessage());

                    return false;
                }

                // Merge the profile data.
                $data->profile_ei = array();

                foreach ($results as $v){
                    $k = str_replace('profile_ei.', '', $v[0]);
                    $data->profile_ei[$k] = json_decode($v[1], true);

                    if ($data->profile_ei[$k] === null){
                        $data->profile_ei[$k] = $v[1];
                    }
                }
            }

            if (!JHtml::isRegistered('users.url')){
                JHtml::register('users.url', array(__CLASS__, 'url'));
            }

            if (!JHtml::isRegistered('users.calendar')){
                JHtml::register('users.calendar', array(__CLASS__, 'calendar'));
            }

            if (!JHtml::isRegistered('users.tos')){
                JHtml::register('users.tos', array(__CLASS__, 'tos'));
            }
        }

        return true;
    }

    /**
     * returns a anchor tag generated from a given value
     *
     * @param   string  $value  url to use
     *
     * @return mixed|string
     */
    public static function url($value){
        if (empty($value)){
            return JHtml::_('users.value', $value);
        }
        else{
            // Convert website url to utf8 for display
            $value = JStringPunycode::urlToUTF8(htmlspecialchars($value));

            if (substr($value, 0, 4) == "http"){
                return '<a href="' . $value . '">' . $value . '</a>';
            }
            else{
                return '<a href="http://' . $value . '">' . $value . '</a>';
            }
        }
    }

    /**
     * returns html markup showing a date picker
     *
     * @param   string  $value  valid date string
     *
     * @return  mixed
     */
    public static function calendar($value){
        if (empty($value)){
            return JHtml::_('users.value', $value);
        }
        else{
            return JHtml::_('date', $value, null, null);
        }
    }

    /**
     * return the translated strings yes or no depending on the value
     *
     * @param   boolean  $value  input value
     *
     * @return string
     */
    public static function tos($value){
        if ($value){
            return JText::_('JYES');
        }
        else{
            return JText::_('JNO');
        }
    }

    /**
     * adds additional fields to the user editing form
     *
     * @param   JForm  $form  The form to be altered.
     * @param   mixed  $data  The associated data for the form.
     *
     * @return  boolean
     *
     */
    public function onContentPrepareForm($form, $data){
        if (!($form instanceof JForm)){
            $this->_subject->setError('JERROR_NOT_A_FORM');
            return false;
        }

        // Check we are manipulating a valid form.
        $name = $form->getName();

        if (!in_array($name, array('com_admin.profile', 'com_users.user', 'com_users.profile', 'com_users.registration'))){
            return true;
        }

        // Add the registration fields to the form.
        JForm::addFormPath(__DIR__ . '/profiles');
        $form->loadFile('profile', false);

        $fields = array(
            'first_name',
            'dob',
            'tos'
        );

        // Change fields description when displayed in front-end or back-end profile editing
        $app = JFactory::getApplication();

        if ($app->isSite() || $name == 'com_users.user' || $name == 'com_admin.profile'){

            $form->setFieldAttribute('first_name', 'description', 'PLG_USER_PROFILE_EI_FILL_FIELD_DESC_SITE', 'profile_ei');
            $form->setFieldAttribute('dob', 'description',              $form->setFieldAttribute('postal_code', 'description', 'PLG_USER_PROFILE_EI_FILL_FIELD_DESC_SITE', 'profile_ei');
            $form->setFieldAttribute('tos', 'description', 'PLG_USER_PROFILE_EI_FIELD_TOS_DESC_SITE', 'profile_ei');
        }

        $tosarticle = $this->params->get('register_tos_article');
        $tosenabled = $this->params->get('register-require_tos', 0);

        // We need to be in the registration form, field needs to be enabled and we need an article ID
        if ($name != 'com_users.registration' || !$tosenabled || !$tosarticle){
            // We only want the TOS in the registration form
            $form->removeField('tos', 'profile_ei');
        }
        else{
            // Push the TOS article ID into the TOS field.
            $form->setFieldAttribute('tos', 'article', $tosarticle, 'profile_ei');
        }

        foreach ($fields as $field){
            // Case using the users manager in admin
            if ($name == 'com_users.user'){
                // Remove the field if it is disabled in registration and profile
                if ($this->params->get('register-require_' . $field, 1) == 0 && $this->params->get('profile-require_' . $field, 1) == 0){
                    $form->removeField($field, 'profile_ei');
                }
            }
            // Case registration
            elseif ($name == 'com_users.registration'){
                // Toggle whether the field is required.
                if ($this->params->get('register-require_' . $field, 1) > 0){
                    $form->setFieldAttribute($field, 'required', ($this->params->get('register-require_' . $field) == 2) ? 'required' : '', 'profile_ei');
                }
                else{
                    $form->removeField($field, 'profile_ei');
                }
            }
            // Case profile in site or admin
            elseif ($name == 'com_users.profile' || $name == 'com_admin.profile'){
                // Toggle whether the field is required.
                if ($this->params->get('profile-require_' . $field, 1) > 0){
                    $form->setFieldAttribute($field, 'required', ($this->params->get('profile-require_' . $field) == 2) ? 'required' : '', 'profile_ei');
                }
                else{
                    $form->removeField($field, 'profile_ei');
                }
            }
        }

        return true;
    }

    /**
     * Method is called before user data is stored in the database
     *
     * @param   array    $user   Holds the old user data.
     * @param   boolean  $isnew  True if a new user is stored.
     * @param   array    $data   Holds the new user data.
     *
     * @return    boolean
     * @throws    InvalidArgumentException on invalid date.
     */
    public function onUserBeforeSave($user, $isnew, $data){
        // Check that the date is valid.
        if (!empty($data['profile_ei']['dob'])){
            try{
                $date = new JDate($data['profile_ei']['dob']);
                $this->date = $date->format('Y-m-d H:i:s');
            }
            catch (Exception $e){
                // Throw an exception if date is not valid.
                throw new InvalidArgumentException(JText::_('PLG_USER_PROFILE_EI_ERROR_INVALID_DOB'));
            }
        }

        return true;
    }

    /**
     * saves user profile data
     *
     * @param   array    $data    entered user data
     * @param   boolean  $isNew   true if this is a new user
     * @param   boolean  $result  true if saving the user worked
     * @param   string   $error   error message
     *
     * @return bool
     */
    public function onUserAfterSave($data, $isNew, $result, $error){
        $userId = JArrayHelper::getValue($data, 'id', 0, 'int');

        if ($userId && $result && isset($data['profile_ei']) && (count($data['profile_ei']))){
            try{
                // Sanitize the date
                $data['profile_ei']['dob'] = $this->date;

                $db = JFactory::getDbo();
                $query = $db->getQuery(true)
                    ->delete($db->quoteName('#__user_profiles'))
                    ->where($db->quoteName('user_id') . ' = ' . (int) $userId)
                    ->where($db->quoteName('profile_key') . ' LIKE ' . $db->quote('profile_ei.%'));
                $db->setQuery($query);
                $db->execute();

                $tuples = array();
                $order = 1;

                foreach ($data['profile_ei'] as $k => $v){
                    $tuples[] = '(' . $userId . ', ' . $db->quote('profile_ei.' . $k) . ', ' . $db->quote(json_encode($v)) . ', ' . ($order++) . ')';
                }

                $db->setQuery('INSERT INTO #__user_profiles VALUES ' . implode(', ', $tuples));
                $db->execute();
            }
            catch (RuntimeException $e){
                $this->_subject->setError($e->getMessage());

                return false;
            }
        }

        return true;
    }

    /**
     * Remove all user profile information for the given user ID
     *
     * Method is called after user data is deleted from the database
     *
     * @param   array    $user     Holds the user data
     * @param   boolean  $success  True if user was succesfully stored in the database
     * @param   string   $msg      Message
     *
     * @return  boolean
     */
    public function onUserAfterDelete($user, $success, $msg){
        if (!$success){
            return false;
        }

        $userId = JArrayHelper::getValue($user, 'id', 0, 'int');

        if ($userId){
            try{
                $db = JFactory::getDbo();
                $db->setQuery(
                    'DELETE FROM #__user_profiles WHERE user_id = ' . $userId .
                        " AND profile_key LIKE 'profile_ei.%'"
                );

                $db->execute();
            }
            catch (Exception $e){
                $this->_subject->setError($e->getMessage());

                return false;
            }
        }

        return true;
    }
}

The file manifest (profile_ei.xml) is this:

<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin" group="user" method="upgrade">
    <name>plg_user_profile_ei</name>
    <author>X Ltda.</author>
    <creationDate>May 2015</creationDate>
    <copyright>(C) X Ltda.</copyright>
    <license>GNU General Public License version 2 or later; see LICENSE.txt</license>
    <authorEmail>x@x.com</authorEmail>
    <authorUrl>www.x.com</authorUrl>
    <version>0.1.3</version>
    <description>PLG_USER_PROFILE_EI_XML_DESCRIPTION</description>
    <files>
        <filename plugin="profile_ei">profile_ei.php</filename>
        <folder>profiles</folder>
        <folder>fields</folder>
    </files>
    <languages>
        <language tag="en-GB">en-GB.plg_user_profile_ei.ini</language>
        <language tag="en-GB">en-GB.plg_user_profile_ei.sys.ini</language>
        <language tag="es-ES">es-ES.plg_user_profile_ei.ini</language>
        <language tag="es-ES">es-ES.plg_user_profile_ei.sys.ini</language>
    </languages>
    <config>
        <fields name="params">
            <fieldset name="basic" addfieldpath="/administrator/components/com_content/models/fields">
                <field name="register-require-user"
                    type="spacer"
                    class="text"
                    label="PLG_USER_PROFILE_EI_FIELD_NAME_REGISTER_REQUIRE_USER"
                />
                <field name="register-require_first_name"
                    type="list"
                    description="PLG_USER_PROFILE_EI_FIELD_FIRST_NAME_DESC"
                    label="PLG_USER_PROFILE_EI_FIELD_FIRST_NAME_LABEL"
                >
                    <option value="2">JOPTION_REQUIRED</option>
                    <option value="1">JOPTION_OPTIONAL</option>
                    <option value="0">JDISABLED</option>
                </field>                    

                <field name="spacer1" type="spacer"
                    hr="true"
                />

                <field name="profile-require-user" type="spacer" class="text"
                    label="PLG_USER_PROFILE_EI_FIELD_NAME_PROFILE_REQUIRE_USER"
                />

                <field name="profile-require_first_name" type="list"
                    description="PLG_USER_PROFILE_EI_FIELD_FIRST_NAME_DESC"
                    label="PLG_USER_PROFILE_EI_FIELD_FIRST_NAME_LABEL"
                >
                    <option value="2">JOPTION_REQUIRED</option>
                    <option value="1">JOPTION_OPTIONAL</option>
                    <option value="0">JDISABLED</option>
                </field>
            </fieldset>
        </fields>
    </config>
</extension>

and the form file (profiles/profile.xml) looks like this:

<?xml version="1.0" encoding="utf-8"?>
<form>
    <fields name="profile_ei">
        <fieldset name="profile_ei"
            label="PLG_USER_PROFILE_EI_SLIDER_LABEL"
        >
            <field
                name="first_name"
                type="text"
                id="first_name"
                description="PLG_USER_PROFILE_EI_FIELD_FIRST_NAME_DESC"
                filter="string"
                label="PLG_USER_PROFILE_EI_FIELD_FIRST_NAME_LABEL"
                size="30"
            />

        </fieldset>
    </fields>
</form>

PS: I didn't include the complete code because SE wouldn't allow it and it looks pretty much the same.

  • Can you add your xml form definition you are using to the question? I've written many user plugins for clients and the form definition will help us resolve the issue. – Brian Bolli May 14 '15 at 2:07
  • @BrianBolli:I just added the xml files. I agree with you, but I just don't see it. Maybe a pair of fresh eyes can help. – mattosmat May 14 '15 at 3:17
  • I would suggest making full use of var_dump($variable) to start debugging your code. It's a little off-putting having to read through 411 lines of PHP in your question :/ – Lodder May 14 '15 at 8:51
  • @Lodder: I really wouldn't know how to do it, since I have little experience with plugins and I don't know how they render. I think I might be confusing profile and profile_ei in the php file, but I don't know where to look. :( – mattosmat May 14 '15 at 11:16
3
+100

There are two mistakes in your code.

1) The following piece of code is broken, I guess two lines got overwritten.

$form->setFieldAttribute('dob', 'description',              $form->setFieldAttribute('postal_code', 'description', 'PLG_USER_PROFILE_EI_FILL_FIELD_DESC_SITE', 'profile_ei');

This should be

$form->setFieldAttribute('dob', 'description', 'PLG_USER_PROFILE_EI_FILL_FIELD_DESC_SITE', 'profile_ei');
$form->setFieldAttribute('postal_code', 'description', 'PLG_USER_PROFILE_EI_FILL_FIELD_DESC_SITE', 'profile_ei');

2) Your plugin name is profile_ei, however you named your class name as ProfileEI (missing underscore)

class PlgUserProfileEI extends JPlugin{

should be

class PlgUserProfile_EI extends JPlugin{
  • You're right! The first mistake you point out was just something that got messed up when I pasted my code. The real problem was the second one! – mattosmat May 16 '15 at 13:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.