• Resolved lukoie

    (@lukoie)


    What I’m triyng to achieve is working with the WP REST API and hooking the user meta data update.
    Here’s the link to the action reference:
    https://codex.wordpress.org/Plugin_API/Action_Reference/updated_%28meta_type%29_meta

    where it says:

    “This hook is called after a call to update_metadata succeeds. ”

    This is the code:

        add_action( 'updated_user_meta', 'second_otp', 10, 4 );
        
        function second_otp($meta_id, $object_id, $meta_key, $_meta_value) {
                    $otp = $_meta_value;
        			$message = "Your OTP =" . get_user_meta($object_id, "otp", true ) . get_user_meta($object_id, "nickname", true );
        			$to = 'myemail@msn.com';
        			$subject = 'OTP';
        			$body = $message;
        			$headers = array('Content-Type: text/html; charset=UTF-8');
        			wp_mail( $to, $subject, $body, $headers );	
        };

    But the action “updated_user_meta” is triggered BEFORE the meta field is written. E.g. if the user has the OTP=”1111″, and I send this json

        {
        	"id": "31",
          "roles": "verified",
          "meta": {"otp":"2222"}
        } 

    to the http://MYSITE/dev/index.php/wp-json/wp/v2/users/31/ endpoint
    I will get an email with the body:

    “Your OTP = 1111”

    Is there anything I haven’t counted, that would help me to email the new OTP of the user, that I’m sending via REST api, and not the old one?

Viewing 10 replies - 1 through 10 (of 10 total)
  • I’m surprised your function is getting called at all. If you look at the code here
    https://developer.wordpress.org/reference/classes/wp_rest_meta_fields/
    there are no filters or hooks called.

    The core code that does a normal meta update does call the hook you are using after the update.
    https://developer.wordpress.org/reference/functions/update_metadata/

    Moderator bcworkz

    (@bcworkz)

    Well, the API calls WP_REST_Meta_Fields::update_meta_value(), which in turn calls update_metadata(), so the action does fire for REST requests. Unimportant really, but I point this out for the sake of clarity. The action does indeed fire after a successful update.

    It looks like you are encountering a caching or race condition, thus the old value is being sent in email. I’ll wager that if you manually checked the value in the DB after sending the update, you’ll see the proper new value. Instead of using get_user_meta() to determine the value, simply use the passed $_meta_value. Once the cache or race has settled down, $_meta_value will indeed be the saved value. Trying to get it from the DB at this point is unreliable and it’s really a needless additional DB query.

    Thread Starter lukoie

    (@lukoie)

    It looks like we’re encountering the problem.
    the function in the functions.php is this:

    add_action( 'updated_user_meta', 'second_otp', 10, 4 );
    function second_otp($meta_id, $object_id, $meta_key, $_meta_value) {
    			error_log( $meta_id );
    			error_log( $object_id );
    			error_log( $meta_key );
    			error_log( $_meta_value );
    };

    and the rest POST is:

    {
    	"id": "31",
    	"meta": {"otp":"1O25"}
    }

    to the http://SITE.com/dev/index.php/wp-json/wp/v2/users/31/

    I’ve got these in logs:

    [17-Sep-2018 13:11:21 UTC] 73
    [17-Sep-2018 13:11:21 UTC] 1
    [17-Sep-2018 13:11:21 UTC] _application_passwords
    [17-Sep-2018 13:11:21 UTC] PHP Warning:  error_log() expects parameter 1 to be string, array given in /var/www/html/dev/wp-content/themes/twentyseventeen/functions.php on line 637

    which indicates that the function is getting user id 1 and not the 31!

    here’s the screenshot of the DB with this user meta:
    http://i63.tinypic.com/2u8fqqq.jpg

    • This reply was modified 7 years, 7 months ago by lukoie.
    • This reply was modified 7 years, 7 months ago by lukoie.
    Moderator bcworkz

    (@bcworkz)

    That hook can fire for any number of reasons unrelated to your request. You are looking for the update to “otp” but you are logging an update for “_application_passwords”. It appears to be related to your REST authentication. If you haven’t logged any other data, then apparently your update request failed. What JSON was returned from your POST request? There should be some sort of error indication.

    Did you check your DB to see if the value was changed or not? At this point it looks like your update is failing and you are getting confusing data in your action hook due to unrelated meta updates.

    Thread Starter lukoie

    (@lukoie)

    Thank you for your support, @bcworkz

    What JSON was returned from your POST request? There should be some sort of error indication.

    No, the response is 201, it’s all good.

    Did you check your DB to see if the value was changed or not?

    Yes, the changing works fine. Only the issue I have is with the triggering that meta data change on the WP side, so if user changes his metadata(otp), I send him the sms with that OTP on his phone number.

    At this point it looks like your update is failing and you are getting confusing data in your action hook due to unrelated meta updates.

    I’ve got this field showing on the user page as well. Everything is working fine with the metadata change.
    What I need to achieve is the triggering part, where the changed metadata(OTP) would send to this particular user’s email, or sends to his phone number.
    But instead I’m getting only first user’s data in the function’s parameters.

    Moderator bcworkz

    (@bcworkz)

    OK, at least everything else is working. But that blows my error theory.

    What’s odd is you are logging unrelated meta updates, but the one you are looking for seems to be missing in action. Would the meta data field your are updating happen to be a new DB entry? While update_metadata() will properly add such fields if new, it will not fire the updated_{%type}_data action. In such cases you need to hook added_{%type}_data instead.

    Thread Starter lukoie

    (@lukoie)

    No, mate, it is updating.
    For instance, if I have my “OTP”=”1111” i change it via rest to “2222”.

    • This reply was modified 7 years, 7 months ago by lukoie.
    Thread Starter lukoie

    (@lukoie)

    Anyone else, please?
    At least, confirm this behavior.

    Moderator bcworkz

    (@bcworkz)

    Not confirmed. I did my own API meta update on my test site after adding your logging callback to the ‘updated_user_meta’ action. The logged data shows the updated values, not the old values. I sent the POST request via Ajax, using cookie authentication. It shouldn’t matter how, the POSTed meta update data is identical in all cases.

    In your case something is corrupting your action hook’s passed data. The cause is usually errant plugin or theme code. Try using the health-check plugin’s troubleshooting mode. It will switch your theme (for your view only, others are unaffected) to twentyseventeen and deactivate all plugins. Temporarily add whatever test code you need to the theme’s functions.php. Try updating data via the API again and see if that makes a difference.

    It really should work in that default state. Assuming it does, use the troubleshooting admin bar item to revert your theme, then your plugins, one at a time, testing after each. When you see old data again, the last activated module is the cause.

    Thread Starter lukoie

    (@lukoie)

    Thank you.

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

The topic ‘WordPress hook fires before, not after the call’ is closed to new replies.