7

I've taken a direct clone of the User Profile plug-in for my Joomla 2.5.9 install.

I've renamed the plugin and the files accordingly to 'profiletest' similar to the old 1.6 tutorial.

I've added a new input to the form and everything works on the backend and the new entry shows up as expected in the registration form on the front end. However when you register I never see the #__user_profiles table updated.

Lots of code here but it's a copy of the User profile plug-in (/plugins/user/profile/). Here is the profiletest.php onUserAfterSave function:

function onUserAfterSave($data, $isNew, $result, $error)
{
    $userId = JArrayHelper::getValue($data, 'id', 0, 'int');


    if ($userId && $result && isset($data['profiletest']) && (count($data['profiletest'])))
    {
        try
        {
            //Sanitize the date
            if (!empty($data['profiletest']['dob']))
            {
                $date = new JDate($data['profiletest']['dob']);
                $data['profiletest']['dob'] = $date->format('Y-m-d');
            }

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

            if (!$db->query())
            {
                throw new Exception($db->getErrorMsg());
            }

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

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

            $db->setQuery('INSERT INTO #__user_profiles VALUES '.implode(', ', $tuples));

            if (!$db->query())
            {
                throw new Exception($db->getErrorMsg());
            }

        }
        catch (JException $e)
        {
            $this->_subject->setError($e->getMessage());
            return false;
        }
    }

    return true;
}

It never inserts anything into the DB because it never goes into this if statement:

if ($userId && $result && isset($data['profiletest']) && (count($data['profiletest'])))

Basically this condition fails: $data['profiletest']

Seems pretty basic as all I've changed in the plugin is 'profile' to 'profiletest'. However to solve this I think you need to see what my other function called onContentPrepareData. Although again it is not doing anything different other than the name change. Sorry for the long dump.

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;
        JLog::add('Do I get into onContentPrepareData?');


        if (!isset($data->profiletest) 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 'profiletest.%'" .
                ' ORDER BY ordering'
            );
            $results = $db->loadRowList();
            JLog::add('Do I get sql result: '.$results);
            // Check for a database error.
            if ($db->getErrorNum())
            {
                $this->_subject->setError($db->getErrorMsg());
                return false;
            }

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

            foreach ($results as $v)
            {
                $k = str_replace('profiletest.', '', $v[0]);
                $data->profiletest[$k] = json_decode($v[1], true);
                if ($data->profiletest[$k] === null)
                {
                    $data->profiletest[$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;
}

Again I notice I never get in here:

if (!isset($data->profiletest) and $userId > 0)

Which probably affects the onUserAfterSave function.

EDIT Here is the function onContentPrepareForm:

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(dirname(__FILE__) . '/profiles');
    $form->loadFile('profile', false);

    $fields = array(
        'address1',
        'address2',
        'city',
        'region',
        'country',
        'postal_code',
        'phone',
        'website',
        'favoritebook',
        'aboutme',
        'dob',
        'tos',
    );

    $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', 'profiletest');
    }
    else
    {
        // Push the TOS article ID into the TOS field.
        $form->setFieldAttribute('tos', 'article', $tosarticle, 'profiletest');
    }

    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, 'profiletest');
            }
        }
        // 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' : '', 'profiletest');
            }
            else
            {
                $form->removeField($field, 'profiletest');
            }
        }
        // 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' : '', 'profiletest');
            }
            else
            {
                $form->removeField($field, 'profiletest');
            }
        }
    }

    return true;
}

What am I doing wrong?

EDIT var_dump($data); exit(); just inside onUserAfterSave:

array(20) { ["isRoot"]=> NULL ["id"]=> int(1291) ["name"]=> string(4) "test" ["username"]=> string(4) "test" ["email"]=> string(22) "test@test.com" ["password"]=> string(65) "5757d7ea6f205f0ee9102e41f66939b4:7dTHzEolpDFKa9P2wmZ4SYSjJSedWFXe" ["password_clear"]=> string(4) "test" ["usertype"]=> NULL ["block"]=> NULL ["sendEmail"]=> int(0) ["registerDate"]=> string(19) "2013-03-05 17:00:40" ["lastvisitDate"]=> NULL ["activation"]=> NULL ["params"]=> string(2) "{}" ["groups"]=> array(1) { [0]=> string(1) "2" } ["guest"]=> int(1) ["lastResetTime"]=> NULL ["resetCount"]=> NULL ["aid"]=> int(0) ["password2"]=> string(4) "test" }
Tom
  • 2,604
  • 11
  • 57
  • 96
  • Can you clarify are you aiming to replace the profile plugin or extend it? Also add the rest of your plugins files via a link or pastebin? – Craig Mar 03 '13 at 22:22
  • @cppl I want to have my own plugin that does everything of the user profile plugin but is extended to add a few things I need. I will try to add a pastebin but it is identical to the user profile plugin. I only changed `profile` with `profiletest`. Once that is working then I can start adding my code. – Tom Mar 04 '13 at 16:53

4 Answers4

3

So the key function here is actually the one that you are not including: onContentPrepareForm. This is the function that builds the form that the user fills out. You have not updated the field names within this, so the checks in the code that you have included fail.

If you go to the registration page with your plugin turned on, you should see all of the fields for the profile plugin. If you inspect any of the fields (let's use Address 1), it should have a name like so: jform[profile][address1]. We want this to be jform[profiletype][address1] and then your code will work.

Before getting to that though, let me explain the code a bit. The $data variable should have all the information from the form that was submitted. This matches everything that has jform at the start of the name, since that is the standard control used for the registration form by Joomla.

$data will then contain some individual items and the array profile. To update that name, find the file that was at plugins/user/profile/profiles/profile.xml and change the fields name from profile to profiletype. Now when submitted $data will contain the array element profiletype and the rest of the queries will run.

David Fritsch
  • 3,711
  • 2
  • 16
  • 25
  • Thanks for the response. I do indeed see: `jform[profiletype][address1]`. My fields in `profiles/profile.xml` does have `fields name=profiletest`. Any other ideas? I've added `onContentPrepareForm` but again this is just a copy with changes of `profile` to `profiletest` – Tom Mar 05 '13 at 03:05
  • mistake in my comment. I'm using `profiletest` not `profiletype` – Tom Mar 05 '13 at 04:02
  • Ok. So if you load a registration form on your site, you see the fields and they have the right name. Then you should check that the $data contains the array on save. Just inside the `onUserAfterSave` function add `var_dump($data); exit()`. Does this show an array called `profiletest`? – David Fritsch Mar 05 '13 at 16:01
  • Yes there is a big array with many fields in it. But no array called profiletest. I posted the array in the question above. Just looks like the stuff from the default registration. – Tom Mar 05 '13 at 17:01
  • Definitely just the stuff from the default registration. I'm really not sure in this case. If you can see the form and filled out all the profile fields and they have the right name, the data should be in that variable. The only other piece I could guess is to check if for some reason the fields are split between two form tags. That seems very unlikely though. Are you just testing this on localhost or is there a place I could see the form? – David Fritsch Mar 05 '13 at 17:43
  • It is on a dev site that is locked down unfortunately. The form is the same. Although the other entries look like this: `jform[name]` and the extra ones like address1 look like `jform[profiletest][address1]`. I think that is expected. Thanks for trying. – Tom Mar 05 '13 at 18:38
1

First of all use JDump or var_dump() the array $data->profiletest to check you have data. If not then I guess you will need to go analyse the onContentPrepareForm method. If not then go and check the UserID is pulling in a valid result. One of the two must be giving a invalid result to 'fail' the if statement. Once you've done that post back here with the results :)

George Wilson
  • 5,595
  • 5
  • 29
  • 42
  • `userId` gives the valid result so it is `$data->profiletest` that is not set. The problem is trying to figure out why...any ideas? I posted the `onContentPrepareForm` – Tom Mar 05 '13 at 03:08
  • @Tom When you've done the `var_dump` there it doesn't look like you've actually got any of new user fields in the data array at all. Which means at some point in the `onContentPrepareForm` you must not be picking up the data from the form. Do your newly created fields have the expected name structure of `jform[profiletest][address1]` etc. etc.? – George Wilson Mar 06 '13 at 13:40
  • Yes, if you look at the html source I do have the expected name structure: `jform[profiletest][address1]` etc. – Tom Mar 06 '13 at 14:44
  • Just noticed on the tuto you're using their is no `if (!isset($data->profiletest) and $userId > 0)` in the `onContentPrepareData` function!! It checks for the id and then goes straight into the DB query – George Wilson Mar 06 '13 at 16:25
  • Yes, but that is based on 1.6. Either way I took it out and it does go further but will just fail again at `if ($userId && $result && isset($data['profiletest']) && (count($data['profiletest'])))` in `onUserAfterSave`. I can take that out but it doesn't have any data at that point so the problem has to be `onContentPrepareForm` or `onContentPrepareData` – Tom Mar 06 '13 at 18:50
  • Thing is the Form must be being prepared because the extra fields are showing – George Wilson Mar 06 '13 at 21:15
  • did you remember to change the fieldset names in the profile.xml file? – George Wilson Mar 08 '13 at 09:32
  • If not I have created the profile plugin with the profiletest sub'd in which works and you can go through each file with a file comparer to try and work out where you've gone wrong :) – George Wilson Mar 08 '13 at 09:41
  • So it worked for you? Can you post the code somewhere so I can compare? – Tom Mar 09 '13 at 01:22
  • Yup - just to check - did you change the fields/fieldsets in profile.xml? – George Wilson Mar 09 '13 at 03:02
  • http://georgesjunk.co.uk/plugins/user/profiletest.zip Thats the zip of my version. Note the langauge files are missing. I just zipped up the core - but I hope you can do that on your own! – George Wilson Mar 09 '13 at 03:04
  • Well I tried and still no luck. What works for you? Do you see an entry in your #__user_profiles table? I had to change one thing in your zip (other than adding language files). You had `profiletest.php` in profiletest.xml. I changed that to `profiletest.php` otherwise it will not install (because of the collision with the Joomla core user profile plugin). Have you removed the Joomla user profile plugin to get this to work? – Tom Mar 09 '13 at 04:35
  • No haven't removed the core user profile. Nice catch about the `plugin=profile` bit. But I changed that and it still worked nicely for me. Yes I do see an entry in the #_user_profiles table. Only thing I might be doing different to you is installing the plugin through the discover method rather than the straight install method – George Wilson Mar 09 '13 at 13:18
  • Just tried installing through the straight install method and worked fine for me. Have you tried installing my version on a blank version of Joomla? Perhaps theirs some kind of wacky conflict going on somewhere – George Wilson Mar 09 '13 at 13:25
  • Must be a conflict. I guess I need to reset things. Thanks for the help. – Tom Mar 09 '13 at 14:03
  • Did you try on a blank copy then? No worries for the help though! – George Wilson Mar 09 '13 at 20:48
  • No not yet. Too much work at this point. Thanks to you, by process of elimination it has to be environmental. So I'll have to get to this. I'm going to write this up once I get it done. – Tom Mar 10 '13 at 18:25
  • No worries :) Sorry I couldn't help you to get it working. Glad to be of help though. – George Wilson Mar 10 '13 at 21:03
0

I think you have a problem here: 'profiletest.%' You shouldn't put the php concatenate operator inside the quote, it is treating that as part of the string. Personally, I usually concatenate the % before writing the query. But $db->quote('profiletest.'.$k).' which you have later is more along the lines of what you want.

Elin
  • 6,507
  • 3
  • 25
  • 47
  • I only changed `profile` with `profiletest` otherwise it is core Joomla code. I've changed nothing else. Either way it doesn't matter as I never get to the code that you are talking about. The if statements way above the code you mention never is true. So I don't think what you are suggesting will do anything. – Tom Feb 23 '13 at 14:21
0

Since $data['profiletest'] fails

The change of name from profile to profiletest has not been registered in xml

please make the following changes if u haven't.

In plugins\user\profile\profiles\profile.xml

change <fields name="profile"> to <fields name="profiletest">

Also in user\profile\profile.xml

change <filename plugin="profile">profile.php</filename>

to

<filename plugin="profile">profiletest.php</filename>
Arun Unnikrishnan
  • 2,339
  • 2
  • 25
  • 39
  • Yes I did, although tutorials always seem to show this file: `user\profile\profile.xml` should be `user\profile\profiletest.xml` and this will have: `profiletest.php`. I did try but still no luck. – Tom Mar 09 '13 at 01:41