0

Here's what I need to do, in laymen's terms:

For each wordpress user, find every meta key that starts with "FOO_" then combine all the meta values into a new key named "FOO_COMBINED"

My question refers to WordPress, but I think applies generally enough to PHP or SQL, that I hope this is the proper forum.

I generally understand, from related answers I found, that I need to do something like this:

function combine_keys() {

    $array = // the array of (all?) user meta

    foreach ($array as $key => $value) {
        if (substr($key, 0, 4) == "FOO_") {
            // grab the $value and append it to another key??
        }
    }

}

But I don't know how to translate this into WordPress functions. I know get_users() will get all users. And get_user_meta($user_id) will get all user meta for a specific user ID. But I don't know how to implement them into the above function. We have a lot of users, so it needs to be done efficiently.

My other question is when to call the function. The purpose of this is for exporting a CSV. I'm using a user export plugin, but I need to merge all FOO_ keys, with values separated by a line break, into a single key so we don't have to export a million FOO_ columns.

** UPDATE **

Here is my updated code trying to use implement the answer below. I put this into functions.php.

function combine_keys( $user_id ) {

    $array    = array();
    $all_meta = get_user_meta( $user_id );

    foreach( $all_meta as $key => $meta ) {
        if( preg_match('/^WORKSHOP_/', $key) )
            $array[$key] = $meta[0];
    }

    return $array;
}

add_action('personal_options_update', function( $user_id ){
    if ( current_user_can('edit_user', $user_id) )
        update_user_meta( $user_id, 'WORKSHOP_COMBINED', combine_keys( $user_id ) );

});

This works to create a new key (called WORKSHOP_COMBINED) and it sucessfully combines the values into an array like this:

a:2:{s:10:"WORKSHOP_5";s:43:"Test, May 15, 2015, Score: 80, Hours: 30 ";s:11:"WORKSHOP_30";s:68:"Middle School Civics & Economics, Jun 04, 2015, Score: 12, Hours: 43";}

But there are two problems:

  1. Everytime I update the profile, it ADDS another combined value to the WORKSHOP_COMBINED key, rather than replacing the value. Even though it says update_meta and not add_meta. Do you know why this is happening?

  2. I'd like to turn the array into a string. So instead of "return $array", I tried to implode it like this:

    $comma_separated = implode(",", $array); return $comma_separated;

But that returns nothing, and the value is empty. What have I done wrong? Thank you!

LBF
  • 1,133
  • 2
  • 14
  • 39

1 Answers1

0

Here it is:

function combine_keys( $user_id ) {

    $array    = array();
    $all_meta = get_user_meta( $user_id );

    foreach( $all_meta as $key => $meta ) {
        if( preg_match('/^FOO_/', $key) )
            $array[$key] = $meta[0];
    }

    return $array;
}

You can create the combined key like this:

foreach (get_users() as $user) {
    $combined_meta = combine_keys( $user->ID );
    update_user_meta( $user->ID, 'FOO_COMBINED', $combined_meta );
}

As for when to call it, you could do it right before exporting the CSV (maybe using a hook provided by the plugin), or you could schedule it when you want.

Or you could let the single user to save his personal combined key when he updates his profile:

add_action('personal_options_update', function( $user_id ){
    if ( current_user_can('edit_user', $user_id) )
        update_user_meta( $user_id, 'FOO_COMBINED', combine_keys( $user_id ) );
});

UPDATE

Answering the new questions:

  1. That happens because even FOO_COMBINED starts with FOO_, so it's added to the array (sorry, my fault :). Replacing the search pattern with /^FOO_(?!COMBINED)/ will exclude that key.
  2. It should be working, I don't see why it doesn't.

I've updated the code to meet your new requirements and tested it:

function combine_keys( $user_id ) {

    $array    = array();
    $all_meta = get_user_meta( $user_id );

    foreach( $all_meta as $key => $meta ) {
        if( preg_match('/^FOO_(?!COMBINED)/', $key) )
            $array[$key] = $meta[0];
    }

    return implode(',', $array);
}

add_action('personal_options_update', function( $user_id ){
    if ( current_user_can('edit_user', $user_id) )
        update_user_meta( $user_id, 'FOO_COMBINED', combine_keys( $user_id ) );

});
d79
  • 3,699
  • 1
  • 22
  • 36
  • @Lindsay Hi, have you by any chance tried yet? I'm curious to know if everything went as expected :) – d79 Apr 29 '15 at 19:08
  • Ok, so I tried and it sort of worked. I had two keys named "WORKSHOP_30" and "WORKSHOP_5". And the function created two new keys with the same values called "WORKSHOP_COMBINED_WORKSHOP_30" and "WORKSHOP_COMBINED_WORKSHOP_5". I used your first block of code and then your third block to call it during personal options update. Was that correct? – LBF Apr 30 '15 at 05:03
  • It's strange, I've just re-tested it and it works. Are you sure you used the exact same code? Have you included some for cycle? The line for updating should be `update_user_meta( $user_id, 'WORKSHOP_COMBINED', combine_keys( $user_id ) );`. – d79 Apr 30 '15 at 07:08
  • Ok, I got it to combine the keys... by deleting the meta and starting again. THANK YOU. However, I have a new issue, which I've updated in my code above. It's adding another combined value everytime I hit "update profile" rather than replacing. – LBF Apr 30 '15 at 15:34
  • I don't know why it's not working for me, but the new code is failing to create/update the key. I believe you that it works, so I don't know what's going wrong. Your original code still works (except for the doubling of values), so I went back to that and I changed the name of the new key so it didn't use WORKSHOP_, and that solved the repeating. However, I still can't get the implode to work. As soon as I add that, the value is empty. Crazy. Is there another method to turn it into a string? I'm going to mark this correct even though it's not totally working for me yet. Thanks for your help! – LBF May 01 '15 at 05:23
  • The only thing I can think is that the array created doesn't contain only strings (maybe also an array), so the `implode` fails. – d79 May 01 '15 at 15:21
  • I got it working (still using your original code). I deleted the old WORKSHOP_ keys entirely (not just the values). And then recreated them, and then ran the combine function. Now, it appears all is working. So there must have been something mixed up somewhere. Thanks for sticking with it, and for the great help. – LBF May 01 '15 at 15:36
  • Good, I'm glad to hear it and always happy to help :) – d79 May 01 '15 at 15:54