1

Hi guys so I have some data hitting my WP from an external company at /wp-json/wp/v2/jobs/ to be imported as a post.

This data contains JSON that needs to be imported, however it tried to set taxonomies using strings e.g. "Manager" rather than the term_id which would be say "381". This means I get an error returned.

{
    "code": "rest_invalid_param",
    "message": "Invalid parameter(s): job_location, job_industry, job_sector",
    "data": {
        "status": 400,
        "params": {
            "job_location": "job_location[0] is not of type integer.",
            "job_industry": "job_industry[0] is not of type integer.",
            "job_sector": "job_sector[0] is not of type integer."
        }
    }
}

So what I want is when they post this value to us, for example:

"job_sector":"Manager"

I want to instead loop through our taxonomies, and find the ID for this "Manager" job_sector, rebuild the JSON and THEN have WP import the data I pass, error free with the proper ID.

Can anyone help on how I can intercept the JSON and pass it along in the proper format?

I tried "rest_pre_dispatch" but this seems to be only editing the result sent back to them, it has already been processed by WP.

EDIT: Here is my code:

 function wpse281916_rest_check_referer( $result, $server, $request ) {
     if ( null !== $result ) {
         // Core starts with a null value.
         // If it is no longer null, another callback has claimed this request.
         // Up to you how to handle - for this example we will just return early.
         return $result;
     }

     $array = json_decode($result, true);
     $term = get_term_by('name',$array["job_sector"],'job_sector');
     $term = json_decode(json_encode($term),true);
     $termid = $term['term_id'];   
     $array['job_sector'] = $termid;
     $result = json_encode($array);
     return $result;
 }

// add the filter
add_filter( 'rest_pre_dispatch', 'wpse281916_rest_check_referer', 10, 3 );

EDIT2: After suggestion

    function wpse281916_rest_check_referer( $result, $server, $request ) {
        if ( null !== $result ) {
            // Core starts with a null value.
            // If it is no longer null, another callback has claimed this request.
            // Up to you how to handle - for this example we will just return early.
            return $result;
        }

        $array = json_decode($request, true);
        $term = get_term_by('name',$array["job_sector"],'job_sector');
        $term = json_decode(json_encode($term),true);
        $termid = $term['term_id'];
        $array['job_sector'] = $termid;
        $request = json_encode($array);
        return null;
    }

   // add the filter
   add_filter( 'rest_pre_dispatch', 'wpse281916_rest_check_referer', 10, 3 );
2
  • As an aside, you can figure out the ID via the REST API using the job_sector endpoints
    – Tom J Nowell
    Oct 24, 2018 at 16:05
  • @TomJNowell Thanks! How would I start going about doing that? Oct 24, 2018 at 16:15

2 Answers 2

1
+50

Using the rest_pre_dispatch hook is probably the most straightforward way to go, but you need to be careful about putting your new request data back into the WP_REST_Request object properly.

You were reassigning the WP_REST_Request object to an array of request data. Those changes are not persisted because the parameter is not passed by reference. Instead, you want to modify the WP_REST_Request object.

You can assign a parameter to the request object using array like syntax, or by using WP_REST_Request::set_param( $param_name, $param_value ).

You should also check to make sure you are only running this code on the correct route. I'd also move the priority to fire the hook earlier since you essentially are saying that this change should apply to everything happening on this request.

function wpse281916_rest_check_referer( $result, $server, $request ) {

    if ( '/wp/v2/jobs' !== $request->get_route() || 'POST' !== $request->get_method()) {
        return $result;
    }

    $job_sector = $request['job_sector'];

    if ( null === $job_sector ) {
        return $result;
    }

    $term = get_term_by( 'name', $job_sector, 'job_sector' );

    if ( $term && ! is_wp_error( $term ) ) {
        $request['job_sector'] = $term->term_id;
    } else {
        $request['job_sector'] = 0;
    }

    return $result;
}

// add the filter
add_filter( 'rest_pre_dispatch', 'wpse281916_rest_check_referer', 0, 3 );
6
  • Hi Timonthy, thanks for this the job seems to be going in but I get a blank response in postman and the software needs to get the right response or it wont know its been updated do you know why it would be blank? It seems $result is returning blank after I set the sector "$request['job_sector'] = $term->term_id;" but if I return $response before this point I get the proper response. Any ideas? Oct 29, 2018 at 13:41
  • Are you modifying $result? The result returned from rest_pre_dispatch must be an empty value like null. That tells WordPress to continue processing the request and actually let the jobs route process your request. If you return the response now, you'll get a proper response back, but the job won't have actually been created. Oct 29, 2018 at 16:19
  • Thanks for this, I aren't modifying result, but when I post in postman I get blank back, where as when I post without this custom script I get back all the post info that has been created - EDIT: I also just noticed in postman I get "500 Internal Server Error" top right! Oct 29, 2018 at 16:31
  • If I remove all our custom code I get a response and a 201 Created which is correct, but with that custom code I get blank and a 500 :( Oct 29, 2018 at 16:47
  • That typically indicates a PHP error. Could you check your error logs? Should be in wp-content/debug.log. You may have to add define( 'WP_DEBUG_LOG', true ); to your wp-config.php file. Codex Oct 29, 2018 at 17:09
2

Seems like you looking for the rest_pre_dispatch hook.

This hook allows hijacking the request before dispatching by returning a non-empty. The returned value will be used to serve the request instead.

From the docs:

$result

(mixed) Response to replace the requested version with. Can be anything a normal endpoint can return, or null to not hijack the request.

Seems like to you have to modify the $request and return null in order to no hijack the default response.

5
  • It seems that this only lets me edit the response back for the request, it doesnt let me change their INITIAL JSON - BEFORE wordpress tried to import any of the data. Oct 25, 2018 at 9:16
  • Could you add the full code in question?
    – BenB
    Oct 25, 2018 at 13:44
  • Added my code! :) Oct 26, 2018 at 11:29
  • 1
    Added to my answer :)
    – BenB
    Oct 26, 2018 at 15:24
  • Amended my code is that what you meant? Doesnt work :( Oct 26, 2018 at 16:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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