Making WordPress.org


Ignore:
Timestamp:
03/30/2017 10:48:04 PM (8 years ago)
Author:
iandunn
Message:

WordCamp Helpers: Add helper to register meta fields on specific API endpoints

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/helper-functions.php

    r4575 r5219  
    289289    return absint( $duration_days );
    290290}
     291
     292/**
     293 * Register post meta so that it only appears on a specific REST API endpoint
     294 *
     295 * As of WordPress 4.7, there's no way to register a meta field for a specific post type. Registering a
     296 * field registers it for all post types, and registering it with `show_in_rest => true` exposes it in all
     297 * API endpoints. Doing that could lead to unintentional privacy leaks. There's no officially-supported
     298 * way to avoid that, other than using `register_rest_field()`.
     299 *
     300 * See https://core.trac.wordpress.org/ticket/38323
     301 *
     302 * `register_rest_field()` isn't an ideal solution for post meta, though, because it's logically
     303 * inconsistent; i.e., meta fields would not show up in the `meta` tree of the response, where other meta
     304 * fields are located, and where a client would expect to find them. Instead, meta fields would show up as
     305 * top-level fields in the response, as if they were first-class `post` object fields, or as if they were
     306 * arbitrary fields (which is what `register_rest_field()` is really intended for).
     307 *
     308 * Having meta fields at the top-level also clutters the post item, making it harder to read, and annoying
     309 * the crap out of grumpy, old, anal-retentive developers like @iandunn.
     310 *
     311 * So, in order to safely add meta fields in the `meta` tree where they belong, but without exposing them
     312 * on endpoints where they don't belong, an ugly workaround is used. `register_meta()` is only called
     313 * for `wcb_session` meta fields during API requests for the `sessions` endpoint. During all other API
     314 * and non-API requests, it is not called.
     315 *
     316 * This only works if you don't need the meta registered in non-API contexts, but that's usually true.
     317 *
     318 * @todo Once #38323 is resolved, this can be removed and the calling functions can be updated to use
     319 *       whatever the officially supported solution turns out to be.
     320 *
     321 * @param string $meta_type   Type of object this meta is registered to. 'post', 'user', 'term', etc
     322 * @param array  $meta_fields An array index by the field slug, with values to be passed to `register_meta()` as
     323 *                            `$args`. For example, `array( '_wcpt_session_slides' => array( 'single' => true ) )`
     324 * @param string $endpoint    The full path of the endpoint. For example, '/wp-json/wp/v2/sessions/'
     325 */
     326function wcorg_register_meta_only_on_endpoint( $meta_type, $meta_fields, $endpoint ) {
     327    $is_correct_endpoint_request = false !== strpos( $_SERVER['REQUEST_URI'], $endpoint );
     328
     329    if ( ! $is_correct_endpoint_request ) {
     330        return;
     331    }
     332
     333    foreach ( $meta_fields as $field_key => $arguments ) {
     334        $arguments = array_merge( $arguments, array( 'show_in_rest' => true ) );
     335
     336        register_meta( $meta_type, $field_key, $arguments );
     337    }
     338}
Note: See TracChangeset for help on using the changeset viewer.