WordPress.org

Make WordPress Core

Changeset 38832


Ignore:
Timestamp:
10/20/16 02:54:12 (8 months ago)
Author:
rachelbaker
Message:

REST API: Introduce the Content API endpoints.

REST API endpoints for your WordPress content. These endpoints provide machine-readable external access to your WordPress site with a clear, standards-driven interface, allowing new and innovative apps for interacting with your site. These endpoints support all of the following:

  • Posts: Read and write access to all post data, for all types of post-based data, including pages and media.
  • Comments: Read and write access to all comment data. This includes pingbacks and trackbacks.
  • Terms: Read and write access to all term data.
  • Users: Read and write access to all user data. This includes public access to some data for post authors.
  • Meta: Read and write access to metadata for posts, comments, terms, and users, on an opt-in basis from plugins.
  • Settings: Read and write access to settings, on an opt-in basis from plugins and core. This enables API management of key site content values that are technically stored in options, such as site title and byline.

Love your REST API, WordPress! The infrastructure says, "Let's do lunch!" but the content API endpoints say, "You're paying!"

Props rmccue, rachelbaker, danielbachhuber, joehoyle, adamsilverstein, afurculita, ahmadawais, airesvsg, alisspers, antisilent, apokalyptik, artoliukkonen, attitude, boonebgorges, bradyvercher, brianhogg, caseypatrickdriscoll, chopinbach, chredd, christianesperar, chrisvanpatten, claudiolabarbera, claudiosmweb, cmmarslender, codebykat, coderkevin, codfish, codonnell822, daggerhart, danielpunkass, davidbhayes, delphinus, desrosj, dimadin, dotancohen, DrewAPicture, Dudo1985, duncanjbrown, eherman24, eivhyl, eliorivero, elyobo, en-alis, ericandrewlewis, ericpedia, evansobkowicz, fjarrett, frozzare, georgestephanis, greatislander, guavaworks, hideokamoto, hkdobrev, hubdotcom, hurtige, iandunn, ircrash, ironpaperweight, iseulde, Japh, jaredcobb, JDGrimes, jdolan, jdoubleu, jeremyfelt, jimt, jjeaton, jmusal, jnylen0, johanmynhardt, johnbillion, jonathanbardo, jorbin, joshkadis, JPry, jshreve, jtsternberg, JustinSainton, kacperszurek, kadamwhite, kalenjohnson, kellbot, kjbenk, kokarn, krogsgard, kuchenundkakao, kuldipem, kwight, lgedeon, lukepettway, mantismamita, markoheijnen, matrixik, mattheu, mauteri, maxcutler, mayukojpn, michael-arestad, miyauchi, mjbanks, modemlooper, mrbobbybryant, NateWr, nathanrice, netweb, NikV, nullvariable, oskosk, oso96_2000, oxymoron, pcfreak30, pento, peterwilsoncc, Pezzab, phh, pippinsplugins, pjgalbraith, pkevan, pollyplummer, pushred, quasel, QWp6t, schlessera, schrapel, Shelob9, shprink, simonlampen, Soean, solal, tapsboy, tfrommen, tharsheblows, thenbrent, tierra, tlovett1, tnegri, tobych, Toddses, toro_unit, traversal, vanillalounge, vishalkakadiya, wanecek, web2style, webbgaraget, websupporter, westonruter, whyisjake, wonderboymusic, wpsmith, xknown, zyphonic.
Fixes #38373.

Location:
trunk
Files:
38 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/default-filters.php

    r38829 r38832  
    375375// REST API actions. 
    376376add_action( 'init',          'rest_api_init' ); 
    377 add_action( 'rest_api_init', 'rest_api_default_filters', 10, 1 ); 
     377add_action( 'rest_api_init', 'rest_api_default_filters',   10, 1 ); 
     378add_action( 'rest_api_init', 'register_initial_settings',  10 ); 
     379add_action( 'rest_api_init', 'create_initial_rest_routes', 99 ); 
    378380add_action( 'parse_request', 'rest_api_loaded' ); 
    379381 
  • trunk/src/wp-includes/functions.php

    r38814 r38832  
    34313431 
    34323432/** 
     3433 * Clean up an array, comma- or space-separated list of slugs. 
     3434 * 
     3435 * @since 4.7.0 
     3436 * 
     3437 * @param  array|string $list List of slugs. 
     3438 * @return array Sanitized array of slugs. 
     3439 */ 
     3440function wp_parse_slug_list( $list ) { 
     3441    if ( ! is_array( $list ) ) { 
     3442        $list = preg_split( '/[\s,]+/', $list ); 
     3443    } 
     3444 
     3445    foreach ( $list as $key => $value ) { 
     3446        $list[ $key ] = sanitize_title( $value ); 
     3447    } 
     3448 
     3449    return array_unique( $list ); 
     3450} 
     3451 
     3452/** 
    34333453 * Extract a slice of an array, given a list of keys. 
    34343454 * 
  • trunk/src/wp-includes/option.php

    r38818 r38832  
    17091709 
    17101710/** 
     1711 * Register default settings available in WordPress. 
     1712 * 
     1713 * The settings registered here are primarily useful for the REST API, so this 
     1714 * does not encompass all settings available in WordPress. 
     1715 * 
     1716 * @since 4.7.0 
     1717 */ 
     1718function register_initial_settings() { 
     1719    register_setting( 'general', 'blogname', array( 
     1720        'show_in_rest' => array( 
     1721            'name' => 'title', 
     1722        ), 
     1723        'type'         => 'string', 
     1724        'description'  => __( 'Site title.' ), 
     1725    ) ); 
     1726 
     1727    register_setting( 'general', 'blogdescription', array( 
     1728        'show_in_rest' => array( 
     1729            'name' => 'description', 
     1730        ), 
     1731        'type'         => 'string', 
     1732        'description'  => __( 'Site description.' ), 
     1733    ) ); 
     1734 
     1735    register_setting( 'general', 'siteurl', array( 
     1736        'show_in_rest' => array( 
     1737            'name'    => 'url', 
     1738            'schema'  => array( 
     1739                'format' => 'uri', 
     1740            ), 
     1741        ), 
     1742        'type'         => 'string', 
     1743        'description'  => __( 'Site URL.' ), 
     1744    ) ); 
     1745 
     1746    register_setting( 'general', 'admin_email', array( 
     1747        'show_in_rest' => array( 
     1748            'name'    => 'email', 
     1749            'schema'  => array( 
     1750                'format' => 'email', 
     1751            ), 
     1752        ), 
     1753        'type'         => 'string', 
     1754        'description'  => __( 'This address is used for admin purposes. If you change this we will send you an email at your new address to confirm it. The new address will not become active until confirmed.' ), 
     1755    ) ); 
     1756 
     1757    register_setting( 'general', 'timezone_string', array( 
     1758        'show_in_rest' => array( 
     1759            'name' => 'timezone', 
     1760        ), 
     1761        'type'         => 'string', 
     1762        'description'  => __( 'A city in the same timezone as you.' ), 
     1763    ) ); 
     1764 
     1765    register_setting( 'general', 'date_format', array( 
     1766        'show_in_rest' => true, 
     1767        'type'         => 'string', 
     1768        'description'  => __( 'A date format for all date strings.' ), 
     1769    ) ); 
     1770 
     1771    register_setting( 'general', 'time_format', array( 
     1772        'show_in_rest' => true, 
     1773        'type'         => 'string', 
     1774        'description'  => __( 'A time format for all time strings.' ), 
     1775    ) ); 
     1776 
     1777    register_setting( 'general', 'start_of_week', array( 
     1778        'show_in_rest' => true, 
     1779        'type'         => 'number', 
     1780        'description'  => __( 'A day number of the week that the week should start on.' ), 
     1781    ) ); 
     1782 
     1783    register_setting( 'general', 'WPLANG', array( 
     1784        'show_in_rest' => array( 
     1785            'name' => 'language', 
     1786        ), 
     1787        'type'         => 'string', 
     1788        'description'  => __( 'WordPress locale code.' ), 
     1789        'default'      => 'en_US', 
     1790    ) ); 
     1791 
     1792    register_setting( 'writing', 'use_smilies', array( 
     1793        'show_in_rest' => true, 
     1794        'type'         => 'boolean', 
     1795        'description'  => __( 'Convert emoticons like :-) and :-P to graphics on display.' ), 
     1796        'default'      => true, 
     1797    ) ); 
     1798 
     1799    register_setting( 'writing', 'default_category', array( 
     1800        'show_in_rest' => true, 
     1801        'type'         => 'number', 
     1802        'description'  => __( 'Default category.' ), 
     1803    ) ); 
     1804 
     1805    register_setting( 'writing', 'default_post_format', array( 
     1806        'show_in_rest' => true, 
     1807        'type'         => 'string', 
     1808        'description'  => __( 'Default post format.' ), 
     1809    ) ); 
     1810 
     1811    register_setting( 'reading', 'posts_per_page', array( 
     1812        'show_in_rest' => true, 
     1813        'type'         => 'number', 
     1814        'description'  => __( 'Blog pages show at most.' ), 
     1815        'default'      => 10, 
     1816    ) ); 
     1817} 
     1818 
     1819/** 
    17111820 * Register a setting and its data. 
    17121821 * 
  • trunk/src/wp-includes/post.php

    r38829 r38832  
    3434        'delete_with_user' => true, 
    3535        'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'trackbacks', 'custom-fields', 'comments', 'revisions', 'post-formats' ), 
     36        'show_in_rest' => true, 
     37        'rest_base' => 'posts', 
     38        'rest_controller_class' => 'WP_REST_Posts_Controller', 
    3639    ) ); 
    3740 
     
    5255        'delete_with_user' => true, 
    5356        'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'page-attributes', 'custom-fields', 'comments', 'revisions' ), 
     57        'show_in_rest' => true, 
     58        'rest_base' => 'pages', 
     59        'rest_controller_class' => 'WP_REST_Posts_Controller', 
    5460    ) ); 
    5561 
     
    7783        'delete_with_user' => true, 
    7884        'supports' => array( 'title', 'author', 'comments' ), 
     85        'show_in_rest' => true, 
     86        'rest_base' => 'media', 
     87        'rest_controller_class' => 'WP_REST_Attachments_Controller', 
    7988    ) ); 
    8089    add_post_type_support( 'attachment:audio', 'thumbnail' ); 
  • trunk/src/wp-includes/rest-api.php

    r38806 r38832  
    7272 
    7373/** 
     74 * Registers a new field on an existing WordPress object type. 
     75 * 
     76 * @since 4.7.0 
     77 * 
     78 * @global array $wp_rest_additional_fields Holds registered fields, organized 
     79 *                                          by object type. 
     80 * 
     81 * @param string|array $object_type Object(s) the field is being registered 
     82 *                                  to, "post"|"term"|"comment" etc. 
     83 * @param string $attribute         The attribute name. 
     84 * @param array  $args { 
     85 *     Optional. An array of arguments used to handle the registered field. 
     86 * 
     87 *     @type string|array|null $get_callback    Optional. The callback function used to retrieve the field 
     88 *                                              value. Default is 'null', the field will not be returned in 
     89 *                                              the response. 
     90 *     @type string|array|null $update_callback Optional. The callback function used to set and update the 
     91 *                                              field value. Default is 'null', the value cannot be set or 
     92 *                                              updated. 
     93 *     @type string|array|null $schema          Optional. The callback function used to create the schema for 
     94 *                                              this field. Default is 'null', no schema entry will be returned. 
     95 * } 
     96 */ 
     97function register_rest_field( $object_type, $attribute, $args = array() ) { 
     98    $defaults = array( 
     99        'get_callback'    => null, 
     100        'update_callback' => null, 
     101        'schema'          => null, 
     102    ); 
     103 
     104    $args = wp_parse_args( $args, $defaults ); 
     105 
     106    global $wp_rest_additional_fields; 
     107 
     108    $object_types = (array) $object_type; 
     109 
     110    foreach ( $object_types as $object_type ) { 
     111        $wp_rest_additional_fields[ $object_type ][ $attribute ] = $args; 
     112    } 
     113} 
     114 
     115/** 
    74116 * Registers rewrite rules for the API. 
    75117 * 
     
    123165 
    124166    add_filter( 'rest_pre_dispatch', 'rest_handle_options_request', 10, 3 ); 
     167} 
     168 
     169/** 
     170 * Registers default REST API routes. 
     171 * 
     172 * @since 4.7.0 
     173 */ 
     174function create_initial_rest_routes() { 
     175    foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { 
     176        $class = ! empty( $post_type->rest_controller_class ) ? $post_type->rest_controller_class : 'WP_REST_Posts_Controller'; 
     177 
     178        if ( ! class_exists( $class ) ) { 
     179            continue; 
     180        } 
     181        $controller = new $class( $post_type->name ); 
     182        if ( ! is_subclass_of( $controller, 'WP_REST_Controller' ) ) { 
     183            continue; 
     184        } 
     185 
     186        $controller->register_routes(); 
     187 
     188        if ( post_type_supports( $post_type->name, 'revisions' ) ) { 
     189            $revisions_controller = new WP_REST_Revisions_Controller( $post_type->name ); 
     190            $revisions_controller->register_routes(); 
     191        } 
     192    } 
     193 
     194    // Post types. 
     195    $controller = new WP_REST_Post_Types_Controller; 
     196    $controller->register_routes(); 
     197 
     198    // Post statuses. 
     199    $controller = new WP_REST_Post_Statuses_Controller; 
     200    $controller->register_routes(); 
     201 
     202    // Taxonomies. 
     203    $controller = new WP_REST_Taxonomies_Controller; 
     204    $controller->register_routes(); 
     205 
     206    // Terms. 
     207    foreach ( get_taxonomies( array( 'show_in_rest' => true ), 'object' ) as $taxonomy ) { 
     208        $class = ! empty( $taxonomy->rest_controller_class ) ? $taxonomy->rest_controller_class : 'WP_REST_Terms_Controller'; 
     209 
     210        if ( ! class_exists( $class ) ) { 
     211            continue; 
     212        } 
     213        $controller = new $class( $taxonomy->name ); 
     214        if ( ! is_subclass_of( $controller, 'WP_REST_Controller' ) ) { 
     215            continue; 
     216        } 
     217 
     218        $controller->register_routes(); 
     219    } 
     220 
     221    // Users. 
     222    $controller = new WP_REST_Users_Controller; 
     223    $controller->register_routes(); 
     224 
     225    // Comments. 
     226    $controller = new WP_REST_Comments_Controller; 
     227    $controller->register_routes(); 
     228 
     229    // Settings. 
     230    $controller = new WP_REST_Settings_Controller; 
     231    $controller->register_routes(); 
    125232} 
    126233 
     
    684791    return array( $local, $utc ); 
    685792} 
     793 
     794/** 
     795 * Returns a contextual HTTP error code for authorization failure. 
     796 * 
     797 * @since 4.7.0 
     798 * 
     799 * @return integer 401 if the user is not logged in, 403 if the user is logged in. 
     800 */ 
     801function rest_authorization_required_code() { 
     802    return is_user_logged_in() ? 403 : 401; 
     803} 
     804 
     805/** 
     806 * Validate a request argument based on details registered to the route. 
     807 * 
     808 * @since 4.7.0 
     809 * 
     810 * @param  mixed            $value 
     811 * @param  WP_REST_Request  $request 
     812 * @param  string           $param 
     813 * @return WP_Error|boolean 
     814 */ 
     815function rest_validate_request_arg( $value, $request, $param ) { 
     816    $attributes = $request->get_attributes(); 
     817    if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) { 
     818        return true; 
     819    } 
     820    $args = $attributes['args'][ $param ]; 
     821 
     822    if ( ! empty( $args['enum'] ) ) { 
     823        if ( ! in_array( $value, $args['enum'], true ) ) { 
     824            return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: list of valid values */ __( '%1$s is not one of %2$s.' ), $param, implode( ', ', $args['enum'] ) ) ); 
     825        } 
     826    } 
     827 
     828    if ( 'integer' === $args['type'] && ! is_numeric( $value ) ) { 
     829        return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: type name */ __( '%1$s is not of type %2$s.' ), $param, 'integer' ) ); 
     830    } 
     831 
     832    if ( 'boolean' === $args['type'] && ! rest_is_boolean( $value ) ) { 
     833        return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: type name */ __( '%1$s is not of type %2$s.' ), $value, 'boolean' ) ); 
     834    } 
     835 
     836    if ( 'string' === $args['type'] && ! is_string( $value ) ) { 
     837        return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: type name */ __( '%1$s is not of type %2$s.' ), $param, 'string' ) ); 
     838    } 
     839 
     840    if ( isset( $args['format'] ) ) { 
     841        switch ( $args['format'] ) { 
     842            case 'date-time' : 
     843                if ( ! rest_parse_date( $value ) ) { 
     844                    return new WP_Error( 'rest_invalid_date', __( 'The date you provided is invalid.' ) ); 
     845                } 
     846                break; 
     847 
     848            case 'email' : 
     849                if ( ! is_email( $value ) ) { 
     850                    return new WP_Error( 'rest_invalid_email', __( 'The email address you provided is invalid.' ) ); 
     851                } 
     852                break; 
     853            case 'ipv4' : 
     854                if ( ! rest_is_ip_address( $value ) ) { 
     855                    return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not a valid IP address.' ), $value ) ); 
     856                } 
     857                break; 
     858        } 
     859    } 
     860 
     861    if ( in_array( $args['type'], array( 'numeric', 'integer' ), true ) && ( isset( $args['minimum'] ) || isset( $args['maximum'] ) ) ) { 
     862        if ( isset( $args['minimum'] ) && ! isset( $args['maximum'] ) ) { 
     863            if ( ! empty( $args['exclusiveMinimum'] ) && $value <= $args['minimum'] ) { 
     864                return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be greater than %2$d (exclusive)' ), $param, $args['minimum'] ) ); 
     865            } elseif ( empty( $args['exclusiveMinimum'] ) && $value < $args['minimum'] ) { 
     866                return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be greater than %2$d (inclusive)' ), $param, $args['minimum'] ) ); 
     867            } 
     868        } elseif ( isset( $args['maximum'] ) && ! isset( $args['minimum'] ) ) { 
     869            if ( ! empty( $args['exclusiveMaximum'] ) && $value >= $args['maximum'] ) { 
     870                return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be less than %2$d (exclusive)' ), $param, $args['maximum'] ) ); 
     871            } elseif ( empty( $args['exclusiveMaximum'] ) && $value > $args['maximum'] ) { 
     872                return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be less than %2$d (inclusive)' ), $param, $args['maximum'] ) ); 
     873            } 
     874        } elseif ( isset( $args['maximum'] ) && isset( $args['minimum'] ) ) { 
     875            if ( ! empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) { 
     876                if ( $value >= $args['maximum'] || $value <= $args['minimum'] ) { 
     877                    return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: minimum number, 3: maximum number */ __( '%1$s must be between %2$d (exclusive) and %3$d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) ); 
     878                } 
     879            } elseif ( empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) { 
     880                if ( $value >= $args['maximum'] || $value < $args['minimum'] ) { 
     881                    return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: minimum number, 3: maximum number */ __( '%1$s must be between %2$d (inclusive) and %3$d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) ); 
     882                } 
     883            } elseif ( ! empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) { 
     884                if ( $value > $args['maximum'] || $value <= $args['minimum'] ) { 
     885                    return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: minimum number, 3: maximum number */ __( '%1$s must be between %2$d (exclusive) and %3$d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) ); 
     886                } 
     887            } elseif ( empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) { 
     888                if ( $value > $args['maximum'] || $value < $args['minimum'] ) { 
     889                    return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: minimum number, 3: maximum number */ __( '%1$s must be between %2$d (inclusive) and %3$d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) ); 
     890                } 
     891            } 
     892        } 
     893    } 
     894 
     895    return true; 
     896} 
     897 
     898/** 
     899 * Sanitize a request argument based on details registered to the route. 
     900 * 
     901 * @since 4.7.0 
     902 * 
     903 * @param  mixed            $value 
     904 * @param  WP_REST_Request  $request 
     905 * @param  string           $param 
     906 * @return mixed 
     907 */ 
     908function rest_sanitize_request_arg( $value, $request, $param ) { 
     909    $attributes = $request->get_attributes(); 
     910    if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) { 
     911        return $value; 
     912    } 
     913    $args = $attributes['args'][ $param ]; 
     914 
     915    if ( 'integer' === $args['type'] ) { 
     916        return (int) $value; 
     917    } 
     918 
     919    if ( 'boolean' === $args['type'] ) { 
     920        return rest_sanitize_boolean( $value ); 
     921    } 
     922 
     923    if ( isset( $args['format'] ) ) { 
     924        switch ( $args['format'] ) { 
     925            case 'date-time' : 
     926                return sanitize_text_field( $value ); 
     927 
     928            case 'email' : 
     929                /* 
     930                 * sanitize_email() validates, which would be unexpected 
     931                 */ 
     932                return sanitize_text_field( $value ); 
     933 
     934            case 'uri' : 
     935                return esc_url_raw( $value ); 
     936 
     937            case 'ipv4' : 
     938                return sanitize_text_field( $value ); 
     939        } 
     940    } 
     941 
     942    return $value; 
     943} 
     944 
     945/** 
     946 * Parse a request argument based on details registered to the route. 
     947 * 
     948 * Runs a validation check and sanitizes the value, primarily to be used via 
     949 * the `sanitize_callback` arguments in the endpoint args registration. 
     950 * 
     951 * @since 4.7.0 
     952 * 
     953 * @param  mixed            $value 
     954 * @param  WP_REST_Request  $request 
     955 * @param  string           $param 
     956 * @return mixed 
     957 */ 
     958function rest_parse_request_arg( $value, $request, $param ) { 
     959    $is_valid = rest_validate_request_arg( $value, $request, $param ); 
     960 
     961    if ( is_wp_error( $is_valid ) ) { 
     962        return $is_valid; 
     963    } 
     964 
     965    $value = rest_sanitize_request_arg( $value, $request, $param ); 
     966 
     967    return $value; 
     968} 
     969 
     970/** 
     971 * Determines if a IPv4 address is valid. 
     972 * 
     973 * Does not handle IPv6 addresses. 
     974 * 
     975 * @since 4.7.0 
     976 * 
     977 * @param  string $ipv4 IP 32-bit address. 
     978 * @return string|false The valid IPv4 address, otherwise false. 
     979 */ 
     980function rest_is_ip_address( $ipv4 ) { 
     981    $pattern = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/'; 
     982 
     983    if ( ! preg_match( $pattern, $ipv4 ) ) { 
     984        return false; 
     985    } 
     986 
     987    return $ipv4; 
     988} 
     989 
     990/** 
     991 * Changes a boolean-like value into the proper boolean value. 
     992 * 
     993 * @since 4.7.0 
     994 * 
     995 * @param bool|string|int $value The value being evaluated. 
     996 * @return boolean Returns the proper associated boolean value. 
     997 */ 
     998function rest_sanitize_boolean( $value ) { 
     999    // String values are translated to `true`; make sure 'false' is false. 
     1000    if ( is_string( $value )  ) { 
     1001        $value = strtolower( $value ); 
     1002        if ( in_array( $value, array( 'false', '0' ), true ) ) { 
     1003            $value = false; 
     1004        } 
     1005    } 
     1006 
     1007    // Everything else will map nicely to boolean. 
     1008    return (boolean) $value; 
     1009} 
     1010 
     1011/** 
     1012 * Determines if a given value is boolean-like. 
     1013 * 
     1014 * @since 4.7.0 
     1015 * 
     1016 * @param bool|string $maybe_bool The value being evaluated. 
     1017 * @return boolean True if a boolean, otherwise false. 
     1018 */ 
     1019function rest_is_boolean( $maybe_bool ) { 
     1020    if ( is_bool( $maybe_bool ) ) { 
     1021        return true; 
     1022    } 
     1023 
     1024    if ( is_string( $maybe_bool ) ) { 
     1025        $maybe_bool = strtolower( $maybe_bool ); 
     1026 
     1027        $valid_boolean_values = array( 
     1028            'false', 
     1029            'true', 
     1030            '0', 
     1031            '1', 
     1032        ); 
     1033 
     1034        return in_array( $maybe_bool, $valid_boolean_values, true ); 
     1035    } 
     1036 
     1037    if ( is_int( $maybe_bool ) ) { 
     1038        return in_array( $maybe_bool, array( 0, 1 ), true ); 
     1039    } 
     1040 
     1041    return false; 
     1042} 
     1043 
     1044/** 
     1045 * Retrieves the avatar urls in various sizes based on a given email address. 
     1046 * 
     1047 * @since 4.7.0 
     1048 * 
     1049 * @see get_avatar_url() 
     1050 * 
     1051 * @param string $email Email address. 
     1052 * @return array $urls Gravatar url for each size. 
     1053 */ 
     1054function rest_get_avatar_urls( $email ) { 
     1055    $avatar_sizes = rest_get_avatar_sizes(); 
     1056 
     1057    $urls = array(); 
     1058    foreach ( $avatar_sizes as $size ) { 
     1059        $urls[ $size ] = get_avatar_url( $email, array( 'size' => $size ) ); 
     1060    } 
     1061 
     1062    return $urls; 
     1063} 
     1064 
     1065/** 
     1066 * Retrieves the pixel sizes for avatars. 
     1067 * 
     1068 * @since 4.7.0 
     1069 * 
     1070 * @return array List of pixel sizes for avatars. Default `[ 24, 48, 96 ]`. 
     1071 */ 
     1072function rest_get_avatar_sizes() { 
     1073    /** 
     1074     * Filter the REST avatar sizes. 
     1075     * 
     1076     * Use this filter to adjust the array of sizes returned by the 
     1077     * `rest_get_avatar_sizes` function. 
     1078     * 
     1079     * @since 4.4.0 
     1080     * 
     1081     * @param array $sizes An array of int values that are the pixel sizes for avatars. 
     1082     *                     Default `[ 24, 48, 96 ]`. 
     1083     */ 
     1084    return apply_filters( 'rest_avatar_sizes', array( 24, 48, 96 ) ); 
     1085} 
  • trunk/src/wp-includes/script-loader.php

    r38827 r38832  
    499499    $scripts->add( 'media-audiovideo', "/wp-includes/js/media-audiovideo$suffix.js", array( 'media-editor' ), false, 1 ); 
    500500    $scripts->add( 'mce-view', "/wp-includes/js/mce-view$suffix.js", array( 'shortcode', 'jquery', 'media-views', 'media-audiovideo' ), false, 1 ); 
     501 
     502    $scripts->add( 'wp-api', "/wp-includes/js/wp-api$suffix.js", array( 'jquery', 'backbone', 'underscore' ), false, 1 ); 
     503    did_action( 'init' ) && $scripts->localize( 'wp-api', 'wpApiSettings', array( 
     504        'root'          => esc_url_raw( get_rest_url() ), 
     505        'nonce'         => wp_create_nonce( 'wp_rest' ), 
     506        'versionString' => 'wp/v2/', 
     507    ) ); 
    501508 
    502509    if ( is_admin() ) { 
  • trunk/src/wp-includes/taxonomy.php

    r38779 r38832  
    6868            'assign_terms' => 'assign_categories', 
    6969        ), 
     70        'show_in_rest' => true, 
     71        'rest_base' => 'categories', 
     72        'rest_controller_class' => 'WP_REST_Terms_Controller', 
    7073    ) ); 
    7174 
     
    8487            'assign_terms' => 'assign_post_tags', 
    8588        ), 
     89        'show_in_rest' => true, 
     90        'rest_base' => 'tags', 
     91        'rest_controller_class' => 'WP_REST_Terms_Controller', 
    8692    ) ); 
    8793 
  • trunk/src/wp-settings.php

    r38747 r38832  
    219219require( ABSPATH . WPINC . '/rest-api/class-wp-rest-response.php' ); 
    220220require( ABSPATH . WPINC . '/rest-api/class-wp-rest-request.php' ); 
     221require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-controller.php' ); 
     222require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-posts-controller.php' ); 
     223require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-attachments-controller.php' ); 
     224require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-post-types-controller.php' ); 
     225require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-post-statuses-controller.php' ); 
     226require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-revisions-controller.php' ); 
     227require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-taxonomies-controller.php' ); 
     228require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-terms-controller.php' ); 
     229require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-users-controller.php' ); 
     230require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-comments-controller.php' ); 
     231require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-settings-controller.php' ); 
     232require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-meta-fields.php' ); 
     233require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-comment-meta-fields.php' ); 
     234require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-post-meta-fields.php' ); 
     235require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-term-meta-fields.php' ); 
     236require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-user-meta-fields.php' ); 
    221237 
    222238$GLOBALS['wp_embed'] = new WP_Embed(); 
  • trunk/tests/phpunit/includes/bootstrap.php

    r38454 r38832  
    4040define( 'WP_MEMORY_LIMIT', -1 ); 
    4141define( 'WP_MAX_MEMORY_LIMIT', -1 ); 
     42 
     43define( 'REST_TESTS_IMPOSSIBLY_HIGH_NUMBER', 99999999 ); 
    4244 
    4345$PHP_SELF = $GLOBALS['PHP_SELF'] = $_SERVER['PHP_SELF'] = '/index.php'; 
     
    8991require dirname( __FILE__ ) . '/testcase.php'; 
    9092require dirname( __FILE__ ) . '/testcase-rest-api.php'; 
     93require dirname( __FILE__ ) . '/testcase-rest-controller.php'; 
     94require dirname( __FILE__ ) . '/testcase-rest-post-type-controller.php'; 
    9195require dirname( __FILE__ ) . '/testcase-xmlrpc.php'; 
    9296require dirname( __FILE__ ) . '/testcase-ajax.php'; 
  • trunk/tests/phpunit/includes/utils.php

    r36525 r38832  
    454454    return $i; 
    455455} 
     456 
     457function test_rest_expand_compact_links( $links ) { 
     458    if ( empty( $links['curies'] ) ) { 
     459        return $links; 
     460    } 
     461    foreach ( $links as $rel => $links_array ) { 
     462        if ( ! strpos( $rel, ':' ) ) { 
     463            continue; 
     464        } 
     465 
     466        $name = explode( ':', $rel ); 
     467 
     468        $curie = wp_list_filter( $links['curies'], array( 'name' => $name[0] ) ); 
     469        $full_uri = str_replace( '{rel}', $name[1], $curie[0]['href'] ); 
     470        $links[ $full_uri ] = $links_array; 
     471        unset( $links[ $rel ] ); 
     472    } 
     473    return $links; 
     474} 
  • trunk/tests/phpunit/tests/rest-api.php

    r38790 r38832  
    2727        $this->assertTrue( class_exists( 'WP_REST_Request' ) ); 
    2828        $this->assertTrue( class_exists( 'WP_REST_Response' ) ); 
     29        $this->assertTrue( class_exists( 'WP_REST_Posts_Controller' ) ); 
    2930    } 
    3031 
     
    3536    function test_init_action_added() { 
    3637        $this->assertEquals( 10, has_action( 'init', 'rest_api_init' ) ); 
     38    } 
     39 
     40    public function test_add_extra_api_taxonomy_arguments() { 
     41        $taxonomy = get_taxonomy( 'category' ); 
     42        $this->assertTrue( $taxonomy->show_in_rest ); 
     43        $this->assertEquals( 'categories', $taxonomy->rest_base ); 
     44        $this->assertEquals( 'WP_REST_Terms_Controller', $taxonomy->rest_controller_class ); 
     45 
     46        $taxonomy = get_taxonomy( 'post_tag' ); 
     47        $this->assertTrue( $taxonomy->show_in_rest ); 
     48        $this->assertEquals( 'tags', $taxonomy->rest_base ); 
     49        $this->assertEquals( 'WP_REST_Terms_Controller', $taxonomy->rest_controller_class ); 
     50    } 
     51 
     52    public function test_add_extra_api_post_type_arguments() { 
     53        $post_type = get_post_type_object( 'post' ); 
     54        $this->assertTrue( $post_type->show_in_rest ); 
     55        $this->assertEquals( 'posts', $post_type->rest_base ); 
     56        $this->assertEquals( 'WP_REST_Posts_Controller', $post_type->rest_controller_class ); 
     57 
     58        $post_type = get_post_type_object( 'page' ); 
     59        $this->assertTrue( $post_type->show_in_rest ); 
     60        $this->assertEquals( 'pages', $post_type->rest_base ); 
     61        $this->assertEquals( 'WP_REST_Posts_Controller', $post_type->rest_controller_class ); 
     62 
     63        $post_type = get_post_type_object( 'attachment' ); 
     64        $this->assertTrue( $post_type->show_in_rest ); 
     65        $this->assertEquals( 'media', $post_type->rest_base ); 
     66        $this->assertEquals( 'WP_REST_Attachments_Controller', $post_type->rest_controller_class ); 
    3767    } 
    3868 
Note: See TracChangeset for help on using the changeset viewer.