latest stable versions: v150827 (changelog)

Old Forums (READ-ONLY): The community now lives at WP Sharks™. If you have an s2Member® Pro question, please use our new Support System.

Problems updating custom fields via a filter

Home Forums Community Forum Problems updating custom fields via a filter

This topic contains 9 replies, has 4 voices. Last updated by  Jason (Lead Developer) 4 years ago.

Topic Author Topic
Posted: Friday Dec 14th, 2012 at 7:54 am #34649

We’re trying to add some metadata to user accounts which we can pass through to Mailchimp, but we’re having difficulty working out exactly how to make the updates stick on the WP side. At the moment, we’ve got code attached to the ws_plugin__s2member_mailchimp_merge_array filter, and, to summarise it does the following:

  • Check the current values of the custom fields via:
$cFields = get_user_option('s2member_custom_fields', $uid);
  • Update them if necessary
  • Save them with:
  • update_user_option($uid, 's2member_custom_fields', $cFields);
  • Send them to Mailchimp via:
  • return array_merge($merge, array('F1' => $cFields['f1'], ... ));

    And although the correct data is sent to Mailchimp, it doesn’t stick in the WP user record. Within the filter, if we call get_user_option() again after calling update_user_option(), it returns the updated information. But when we go back to the list of users in the WP admin interface, it’s still got the old values.

    Have we missed something?

    Thanks.

    List Of Topic Replies

    Viewing 9 replies - 1 through 9 (of 9 total)
    Author Replies
    Author Replies
    Posted: Monday Dec 17th, 2012 at 7:57 pm #34872
    Bruce
    Username: Bruce
    Staff Member

    Hi Andy,

    Sorry about the delay.

    Can you post the entire code snippet that you’re using?

    Posted: Tuesday Dec 18th, 2012 at 4:35 am #34886

    Here’s the full code (note the verification I mentioned in the original post is all commented out):

    function tctc_merge_filter($merge, $vars) {
    	$uid = $vars['user_id'];
    	$cFields = get_user_option('s2member_custom_fields', $uid);
    	// echo '$cFields[course]: ', $cFields['course'], '<br />';
    	// echo '$cFields[start_date]: ', $cFields['start_date'], '<br />';
    	// echo '$cFields[institution]: ', $cFields['institution'], '<br />';
    	// echo '$cFields[department]: ', $cFields['department'], '<br />';
    	$needUpdate = false;
    	$today = date('Y-m-d'); // yyyy-mm-dd
    	if ($cFields['course'] == '') {
    		$cFields['course'] = 'Faculty';
    		$needUpdate = true;
    	}
    	if ($cFields['start_date'] == '' || strtotime($cFields['start_date']) < strtotime($today)) { // Start date is blank or in the past - bring it to today
    		$cFields['start_date'] = $today; // yyyy-mm-dd
    		$needUpdate = true;
    	}
    	if ($needUpdate) {
    		update_user_option($uid, 's2member_custom_fields', $cFields);
    		// echo 'fields updated<br />';
    	}
    	// echo '$cFields[course]: ', $cFields['course'], '<br />';
    	// echo '$cFields[start_date]: ', $cFields['start_date'], '<br />';
    	// echo '$cFields[institution]: ', $cFields['institution'], '<br />';
    	// echo '$cFields[department]: ', $cFields['department'], '<br />';
    	// $dFields = get_user_option('s2member_custom_fields', $uid);
    	// echo 'reloaded custom fields<br />';
    	// echo '$dFields[course]: ', $dFields['course'], '<br />';
    	// echo '$dFields[start_date]: ', $dFields['start_date'], '<br />';
    	// echo '$dFields[institution]: ', $dFields['institution'], '<br />';
    	// echo '$dFields[department]: ', $dFields['department'], '<br />';
    	return array_merge($merge, array(
    		'COURSE' => $cFields['course'],
    		'STARTDATE' => $cFields['start_date'],
    		'INST' => $cFields['institution'],
    		'DEPT' => $cFields['department']
    	));
    }
    Posted: Wednesday Dec 19th, 2012 at 8:05 am #35023
    [hilite pre_code]
    $today = date('Y-m-d'); // yyyy-mm-dd
    if ($cFields['course'] == '') {
    $cFields['course'] = 'Faculty';
    $needUpdate = true;
    }
    if ($cFields['start_date'] == '' || strtotime($cFields['start_date']) < strtotime($today)) { // Start date is blank or in the past - bring it to today $cFields['start_date'] = $today; // yyyy-mm-dd $needUpdate = true; } if ($needUpdate) { update_user_option($uid, 's2member_custom_fields', $cFields); // echo 'fields updated
    ';
    }
    [/hilite]

    The “course” field could be defaulted to Faculty in your definition of the field. [hilite path]Dashboard -› s2Member® -› General Options -› Registration/Profile Fields[/hilite]

    The “date” part I’d probably do like this:

    [hilite pre_code]
    // Start date is blank or in the past - bring it to today.
    if (empty($cFields['start_date']) || (strtotime($cFields['start_date']) < strtotime('today'))) { $cFields['start_date'] = date('Y-m-d'); // yyyy-mm-dd [/hilite] When you echoed “fields updated” in your test, did it echo or it didn’t happen?

    Posted: Thursday Dec 20th, 2012 at 6:53 am #35131

    Re the default fields – those options only seem to take effect if the field is visible to the user. This is pure metadata and is set to Invisible during and after registration. The default value is set in the options, but comes in as an empty string in this filter.

    Re the date – thanks, I’ll change that to call empty(). Out of interest, what’s the advantage of a second call to date() in the assignment, rather than just using $today, which is already assigned?

    More importantly, yes, the output included ‘fields updated’. To test, I created a user account with a ‘Start Date’ of 2012-12-19 and role of ‘Subscriber’. I then promoted that user to ‘s2 Level 1’ – here’s the full output when the debugging ‘echos’ are uncommented:

    $cFields[course]: Faculty
    $cFields[start_date]: 2012-12-19
    $cFields[institution]: my inst
    $cFields[department]: my dept
    fields updated
    $cFields[course]: Faculty
    $cFields[start_date]: 2012-12-20
    $cFields[institution]: my inst
    $cFields[department]: my dept
    reloaded custom fields
    $dFields[course]: Faculty
    $dFields[start_date]: 2012-12-20
    $dFields[institution]: my inst
    $dFields[department]: my dept

    What’s really odd is the last call to get_user_option() uses a different array ($dField[]) and does load the correct data. But it only seems to persist like that until the end of the function. The userlist on WP still shows 2012-12-19 for that user. I can change the ‘Start Date’ from the Edit User page on WP, and then it does stick.

    Posted: Saturday Dec 22nd, 2012 at 8:01 am #35308

    Re the default fields – those options only seem to take effect if the field is visible to the user. This is pure metadata and is set to Invisible during and after registration. The default value is set in the options, but comes in as an empty string in this filter.

    Okay.

    Re the date – thanks, I’ll change that to call empty(). Out of interest, what’s the advantage of a second call to date() in the assignment, rather than just using $today, which is already assigned?

    Ah, I didn’t even define [hilite mono]$today[/hilite], since it’d only be used in a single place.

    What’s really odd is the last call to get_user_option() uses a different array ($dField[]) and does load the correct data. But it only seems to persist like that until the end of the function. The userlist on WP still shows 2012-12-19 for that user. I can change the ‘Start Date’ from the Edit User page on WP, and then it does stick.

    Yes, that’s strange… Do you have object/database caching?

    Posted: Saturday Dec 22nd, 2012 at 9:01 am #35313

    Hmm – $today is defined in the existing script, and used in the date comparison (strtotime($today)) in the if statement. Just thought it sensible to do that rather than make 2 calls to date().

    Re caching – do you mean a plugin doing that? If so, no – just standard WP. Here’s a full list of the plugins we’re using:

    amr users
    Easy Table
    Export Users to CSV
    Nav Menu Roles
    s2Member + Pro
    Shortcode Exec PHP
    Sidebar Login
    Theme My Login
    ToolBar Removal
    Widgets on Pages
    WordPress Importer
    WP Show IDs

    I don’t think any of them do any caching. Also, I was just looking at the WP codex, and the notes for update_user_option() say this:

      User options are just like user metadata except that they have support for global blog options. If the ‘global’ parameter is false, which it is by default, it will prepend the WordPress table prefix to the option name.

    This probably explains why I couldn’t get anything to work when I originally had the code using ‘wp_s2member_custom_fields’ – it would have ended up as ‘wp_wp_s2member_custom_fields’!

    But from what I can see of that function, it should be working. Is there anything else I can check – on the db side for example?

    Thanks,

    David.

    Posted: Thursday Jan 3rd, 2013 at 8:29 am #36100
    Staff Member

    Thanks for the heads up on this thread.

    And although the correct data is sent to Mailchimp, it doesn’t stick in the WP user record. Within the filter, if we call get_user_option() again after calling update_user_option(), it returns the updated information. But when we go back to the list of users in the WP admin interface, it’s still got the old values.

    Have we missed something?

    It sounds to me like you’re using this filter for MailChimp, to not only affect the MailChimp MERGE vars, but also to update a user’s record at the same time. While it’s certainly possible to do this, I would’nt do it all inside a filter attaching to ws_plugin__s2member_mailchimp_merge_array, because that is merely a filter for a specific array of details being passed over to MailChimp.

    The reason you’re seeing details properly while in your custom function that’s working together with this filter, but they’re NOT sticking, is because WordPress and s2Member are actually still in the process of registering/updating the user’s account record with a completely different set of information, which does not include the custom data you’re attempting to save upon hooking into this filter.

    So the solution in a case like this, is to use the MailChimp filter only for what it’s designed for. Then use a Hook provided by WordPress or s2Member to actually save the data to the user’s account record, at the appropriate time (i.e. using a Hook that puts you right in the action, where WordPress/s2Member are actually handling the customer’s details).

    I recommend this hook to save user data during registration.

    Posted: Thursday Jan 3rd, 2013 at 9:18 am #36108

    Thanks for the analysis and advice – I would certainly agree we are trying to do more than the mailchimp filter is designed for, and so separating that code out makes sense.

    The only concern I now have is that those user fields are needed on the mailchimp side as well, so we need to be sure the custom fields are updated before any calls to the mailchimp api. I presume things would happen in the right order, but do you know for sure if ws_plugin__s2member_during_configure_user_registration_front_side is called before ws_plugin__s2member_mailchimp_merge_array? In general, is there an easy way to know in what order these filters are applied?

    Thanks again!

    PS – off topic: I can’t find the tag to put those filter names in ‘code hilite inline’ format as you did – the code tags always create a block for me – is there a trick? Tx!

    Posted: Saturday Jan 5th, 2013 at 1:28 am #36220
    Staff Member

    The only concern I now have is that those user fields are needed on the mailchimp side as well, so we need to be sure the custom fields are updated before any calls to the mailchimp api. I presume things would happen in the right order, but do you know for sure if ws_plugin__s2member_during_configure_user_registration_front_side is called before ws_plugin__s2member_mailchimp_merge_array? In general, is there an easy way to know in what order these filters are applied?

    The code sample and registration Hook I provided (ws_plugin__s2member_during_configure_user_registration_front_side) will accomplish that for you, as it DOES come before s2Member’s call to the MailChimp API. For future reference, it’s really a good idea to search the s2Member source code for the Hooks/Filters you’re using, and analyze the code itself. There are simply too many Hooks/Filters available, to try and document each of these and provide an execution order. Inspecting the code, even just briefly, should give you a better understanding in most cases. I recommend Advanced Find/Replace. Or if you have an editor like Dreamweaver, or something that provides a directory/file search, that would work for you.

    PS – off topic: I can’t find the tag to put those filter names in ‘code hilite inline’ format as you did – the code tags always create a block for me – is there a trick? Tx!

    We work with a slightly different set of tools than our customer’s do here. However, you can accomplish something similar using <tt>my inline code</tt>. You won’t get the syntax hiliting this way, but it’s better than nothing :-) In the future I’ll see if we can improve upon this for everyone. You can get syntax hiliting in code blocks, but our customers can’t do syntax hiliting inline yet.

    ~ Test with inline code sample using a tt tag. Customers can do this.

    Viewing 9 replies - 1 through 9 (of 9 total)

    This topic is closed to new replies. Topics with no replies for 2 weeks are closed automatically.

    Old Forums (READ-ONLY): The community now lives at WP Sharks™. If you have an s2Member® Pro question, please use our new Support System.

    Contacting s2Member: Please use our Support Center for bug reports, pre-sale questions & technical assistance.