WordPress.org

Make WordPress Core

Ticket #41459: 41459.2.diff

File 41459.2.diff, 15.8 KB (added by spacedmonkey, 2 years ago)
  • src/wp-includes/rest-api/endpoints/class-wp-rest-networks-controller.php

     
     1<?php
     2/**
     3 * REST API: WP_REST_Networks_Controller class
     4 *
     5 * @package WordPress
     6 * @subpackage REST_API
     7 * @since 4.9.0
     8 */
     9
     10/**
     11 * Core controller used to access networks via the REST API.
     12 *
     13 * @since 4.9.0
     14 *
     15 * @see WP_REST_Controller
     16 */
     17class WP_REST_Networks_Controller extends WP_REST_Controller {
     18
     19        /**
     20         * Instance of a network meta fields object.
     21         *
     22         * @since 4.9.0
     23         * @var WP_REST_Network_Meta_Fields
     24         */
     25        protected $meta;
     26
     27        /**
     28         * Constructor.
     29         *
     30         * @since 4.9.0
     31         */
     32        public function __construct() {
     33                $this->namespace = 'wp/v2';
     34                $this->rest_base = 'networks';
     35
     36                $this->meta = new WP_REST_Network_Meta_Fields();
     37        }
     38
     39        /**
     40         * Registers the routes for the objects of the controller.
     41         *
     42         * @since 4.9.0
     43         */
     44        public function register_routes() {
     45
     46                register_rest_route( $this->namespace, '/' . $this->rest_base, array(
     47                        array(
     48                                'methods'             => WP_REST_Server::READABLE,
     49                                'callback'            => array( $this, 'get_items' ),
     50                                'permission_callback' => array( $this, 'get_items_permissions_check' ),
     51                                'args'                => $this->get_collection_params(),
     52                        ),
     53                        'schema' => array( $this, 'get_public_item_schema' ),
     54                ) );
     55
     56                register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
     57                        'args'   => array(
     58                                'id' => array(
     59                                        'description' => __( 'Unique identifier for the object.' ),
     60                                        'type'        => 'integer',
     61                                ),
     62                        ),
     63                        array(
     64                                'methods'             => WP_REST_Server::READABLE,
     65                                'callback'            => array( $this, 'get_item' ),
     66                                'permission_callback' => array( $this, 'get_item_permissions_check' ),
     67                                'args'                => array(
     68                                        'context' => $this->get_context_param( array( 'default' => 'view' ) ),
     69                                ),
     70                        ),
     71                        'schema' => array( $this, 'get_public_item_schema' ),
     72                ) );
     73        }
     74
     75        /**
     76         * Checks if a given request has access to read networks.
     77         *
     78         * @since 4.9.0
     79         *
     80         * @param WP_REST_Request $request Full details about the request.
     81         *
     82         * @return WP_Error|bool True if the request has read access, error object otherwise.
     83         */
     84        public function get_items_permissions_check( $request ) {
     85                return current_user_can( 'manage_options' );
     86        }
     87
     88        /**
     89         * Retrieves a list of network items.
     90         *
     91         * @since 4.9.0
     92         *
     93         * @param WP_REST_Request $request Full details about the request.
     94         *
     95         * @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
     96         */
     97        public function get_items( $request ) {
     98
     99                // Retrieve the list of registered collection query parameters.
     100                $registered = $this->get_collection_params();
     101
     102                /*
     103                 * This array defines mappings between public API query parameters whose
     104                 * values are accepted as-passed, and their internal WP_Network_Query parameter
     105                 * name equivalents (some are the same). Only values which are also
     106                 * present in $registered will be set.
     107                 */
     108                $parameter_mappings = array(
     109                        'domain'         => 'domain__in',
     110                        'domain_exclude' => 'domain__not_in',
     111                        'exclude'        => 'network__not_in',
     112                        'include'        => 'network__in',
     113                        'offset'         => 'offset',
     114                        'order'          => 'order',
     115                        'path'           => 'path__in',
     116                        'path_exclude'   => 'path__not_in',
     117                        'per_page'       => 'number',
     118                        'search'         => 'search'
     119                );
     120
     121                $prepared_args = array();
     122
     123                /*
     124                 * For each known parameter which is both registered and present in the request,
     125                 * set the parameter's value on the query $prepared_args.
     126                 */
     127                foreach ( $parameter_mappings as $api_param => $wp_param ) {
     128                        if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) {
     129                                $prepared_args[ $wp_param ] = $request[ $api_param ];
     130                        }
     131                }
     132
     133                // Ensure certain parameter values default to empty strings.
     134                foreach ( array( 'search' ) as $param ) {
     135                        if ( ! isset( $prepared_args[ $param ] ) ) {
     136                                $prepared_args[ $param ] = '';
     137                        }
     138                }
     139
     140                $prepared_args['no_found_rows'] = false;
     141
     142
     143                /**
     144                 * Filters arguments, before passing to WP_Network_Query, when querying networks via the REST API.
     145                 *
     146                 * @since 4.9.0
     147                 *
     148                 * @link https://developer.wordpress.org/reference/classes/wp_network_query/
     149                 *
     150                 * @param array $prepared_args Array of arguments for WP_Network_Query.
     151                 * @param WP_REST_Request $request The current request.
     152                 */
     153                $prepared_args = apply_filters( 'rest_network_query', $prepared_args, $request );
     154
     155                $query        = new WP_Network_Query;
     156                $query_result = $query->query( $prepared_args );
     157
     158                $networks = array();
     159
     160                foreach ( $query_result as $network ) {
     161                        $data       = $this->prepare_item_for_response( $network, $request );
     162                        $networks[] = $this->prepare_response_for_collection( $data );
     163                }
     164
     165                $total_networks = (int) $query->found_networks;
     166                $max_pages      = (int) $query->max_num_pages;
     167
     168                if ( $total_networks < 1 ) {
     169                        // Out-of-bounds, run the query again without LIMIT for total count.
     170                        unset( $prepared_args['number'], $prepared_args['offset'] );
     171
     172                        $query                  = new WP_Network_Query;
     173                        $prepared_args['count'] = true;
     174
     175                        $total_networks = $query->query( $prepared_args );
     176                        $max_pages      = ceil( $total_networks / $request['per_page'] );
     177                }
     178
     179                $response = rest_ensure_response( $networks );
     180                $response->header( 'X-WP-Total', $total_networks );
     181                $response->header( 'X-WP-TotalPages', $max_pages );
     182
     183                $base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ) );
     184
     185                if ( $request['page'] > 1 ) {
     186                        $prev_page = $request['page'] - 1;
     187
     188                        if ( $prev_page > $max_pages ) {
     189                                $prev_page = $max_pages;
     190                        }
     191
     192                        $prev_link = add_query_arg( 'page', $prev_page, $base );
     193                        $response->link_header( 'prev', $prev_link );
     194                }
     195
     196                if ( $max_pages > $request['page'] ) {
     197                        $next_page = $request['page'] + 1;
     198                        $next_link = add_query_arg( 'page', $next_page, $base );
     199
     200                        $response->link_header( 'next', $next_link );
     201                }
     202
     203                return $response;
     204        }
     205
     206        /**
     207         * Get the network, if the ID is valid.
     208         *
     209         * @since 4.9.2
     210         *
     211         * @param int $id Supplied ID.
     212         *
     213         * @return WP_Network|WP_Error Network object if ID is valid, WP_Error otherwise.
     214         */
     215        protected function get_network( $id ) {
     216                $error = new WP_Error( 'rest_network_invalid_id', __( 'Invalid network ID.' ), array( 'status' => 404 ) );
     217                if ( (int) $id <= 0 ) {
     218                        return $error;
     219                }
     220
     221                $id      = (int) $id;
     222                $network = get_network( $id );
     223                if ( empty( $network ) ) {
     224                        return $error;
     225                }
     226
     227                return $network;
     228        }
     229
     230        /**
     231         * Checks if a given request has access to read the network.
     232         *
     233         * @since 4.9.0
     234         *
     235         * @param WP_REST_Request $request Full details about the request.
     236         *
     237         * @return WP_Error|bool True if the request has read access for the item, error object otherwise.
     238         */
     239        public function get_item_permissions_check( $request ) {
     240                if ( ! current_user_can( 'manage_network' ) ) {
     241                        return new WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to view netwrosk' ), array( 'status' => rest_authorization_required_code() ) );
     242                }
     243
     244                $network = $this->get_network( $request['id'] );
     245                if ( is_wp_error( $network ) ) {
     246                        return $network;
     247                }
     248
     249                if ( ! empty( $request['context'] ) && 'edit' === $request['context'] ) {
     250                        return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit networks.' ), array( 'status' => rest_authorization_required_code() ) );
     251                }
     252
     253                return true;
     254        }
     255
     256        /**
     257         * Retrieves a network.
     258         *
     259         * @since 4.9.0
     260         *
     261         * @param WP_REST_Request $request Full details about the request.
     262         *
     263         * @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
     264         */
     265        public function get_item( $request ) {
     266                $network = $this->get_network( $request['id'] );
     267                if ( is_wp_error( $network ) ) {
     268                        return $network;
     269                }
     270
     271                $data     = $this->prepare_item_for_response( $network, $request );
     272                $response = rest_ensure_response( $data );
     273
     274                return $response;
     275        }
     276
     277        /**
     278         * Prepares a single network output for response.
     279         *
     280         * @since 4.9.0
     281         *
     282         * @param WP_Network $network Network object.
     283         * @param WP_REST_Request $request Request object.
     284         *
     285         * @return WP_REST_Response Response object.
     286         */
     287        public function prepare_item_for_response( $network, $request ) {
     288                $data = array(
     289                        'id'            => (int) $network->id,
     290                        'site_id'       => (int) $network->blog_id,
     291                        'domain'        => $network->domain,
     292                        'path'          => $network->path,
     293                        'cookie_domain' => $network->cookie_domain,
     294                        'site_name'     => $network->site_name,
     295                );
     296
     297                $schema = $this->get_item_schema();
     298
     299                if ( ! empty( $schema['properties']['meta'] ) ) {
     300                        $data['meta'] = $this->meta->get_value( $network->id, $request );
     301                }
     302
     303                $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
     304                $data    = $this->add_additional_fields_to_object( $data, $request );
     305                $data    = $this->filter_response_by_context( $data, $context );
     306
     307                // Wrap the data in a response object.
     308                $response = rest_ensure_response( $data );
     309
     310
     311                /**
     312                 * Filters a network returned from the API.
     313                 *
     314                 * Allows modification of the network right before it is returned.
     315                 *
     316                 * @since 4.9.0
     317                 *
     318                 * @param WP_REST_Response $response The response object.
     319                 * @param WP_Network $network The original network object.
     320                 * @param WP_REST_Request $request Request used to generate the response.
     321                 */
     322                return apply_filters( 'rest_prepare_network', $response, $network, $request );
     323        }
     324
     325        /**
     326         * Retrieves the network's schema, conforming to JSON Schema.
     327         *
     328         * @since 4.9.0
     329         *
     330         * @return array
     331         */
     332        public function get_item_schema() {
     333                $schema = array(
     334                        '$schema'    => 'http://json-schema.org/schema#',
     335                        'title'      => 'network',
     336                        'type'       => 'object',
     337                        'properties' => array(
     338                                'id'            => array(
     339                                        'description' => __( 'Unique identifier for the object.' ),
     340                                        'type'        => 'integer',
     341                                        'context'     => array( 'view', 'edit' ),
     342                                        'readonly'    => true,
     343                                ),
     344                                'site_id'       => array(
     345                                        'description' => __( 'The ID of the network\'s main site.' ),
     346                                        'type'        => 'integer',
     347                                        'context'     => array( 'view', 'edit' ),
     348                                ),
     349                                'domain'        => array(
     350                                        'description' => __( 'Domain of the network.' ),
     351                                        'type'        => 'string',
     352                                        'context'     => array( 'view', 'edit' ),
     353                                ),
     354                                'path'          => array(
     355                                        'description' => __( 'Path of the network.' ),
     356                                        'type'        => 'string',
     357                                        'context'     => array( 'view', 'edit' ),
     358                                ),
     359                                'cookie_domain' => array(
     360                                        'description' => __( 'Domain used to set cookies for the network.' ),
     361                                        'type'        => 'string',
     362                                        'context'     => array( 'view', 'edit' ),
     363                                ),
     364                                'site_name'     => array(
     365                                        'description' => __( 'Name of the network.' ),
     366                                        'type'        => 'string',
     367                                        'context'     => array( 'view', 'edit' ),
     368                                )
     369                        ),
     370                );
     371
     372                $schema['properties']['meta'] = $this->meta->get_field_schema();
     373
     374                return $this->add_additional_fields_schema( $schema );
     375        }
     376
     377        /**
     378         * Retrieves the query params for collections.
     379         *
     380         * @since 4.9.0
     381         *
     382         * @return array Networks collection parameters.
     383         */
     384        public function get_collection_params() {
     385                $query_params = parent::get_collection_params();
     386
     387                $query_params['context']['default'] = 'view';
     388
     389                $query_params['exclude'] = array(
     390                        'description' => __( 'Ensure result set excludes specific IDs.' ),
     391                        'type'        => 'array',
     392                        'items'       => array(
     393                                'type' => 'integer',
     394                        ),
     395                        'default'     => array(),
     396                );
     397
     398                $query_params['include'] = array(
     399                        'description' => __( 'Limit result set to specific IDs.' ),
     400                        'type'        => 'array',
     401                        'items'       => array(
     402                                'type' => 'integer',
     403                        ),
     404                        'default'     => array(),
     405                );
     406
     407                $query_params['offset'] = array(
     408                        'description' => __( 'Offset the result set by a specific number of items.' ),
     409                        'type'        => 'integer',
     410                );
     411
     412                $query_params['order'] = array(
     413                        'description' => __( 'Order sort attribute ascending or descending.' ),
     414                        'type'        => 'string',
     415                        'default'     => 'desc',
     416                        'enum'        => array(
     417                                'asc',
     418                                'desc',
     419                        ),
     420                );
     421
     422                $query_params['orderby'] = array(
     423                        'description' => __( 'Sort collection by object attribute.' ),
     424                        'type'        => 'string',
     425                        'default'     => 'id',
     426                        'enum'        => array(
     427                                'id',
     428                                'domain',
     429                                'path',
     430                                'domain_length',
     431                                'path_length',
     432                                'network__in'
     433                        ),
     434                );
     435
     436                /**
     437                 * Filter collection parameters for the networks controller.
     438                 *
     439                 * This filter registers the collection parameter, but does not map the
     440                 * collection parameter to an internal WP_Network_Query parameter. Use the
     441                 * `rest_network_query` filter to set WP_Network_Query parameters.
     442                 *
     443                 * @since 4.9.0
     444                 *
     445                 * @param array $query_params JSON Schema-formatted collection parameters.
     446                 */
     447                return apply_filters( 'rest_network_collection_params', $query_params );
     448        }
     449}
  • src/wp-includes/rest-api/fields/class-wp-rest-network-meta-fields.php

    Property changes on: src/wp-includes/rest-api/endpoints/class-wp-rest-networks-controller.php
    ___________________________________________________________________
    Added: svn:executable
    ## -0,0 +1 ##
    +*
    \ No newline at end of property
     
     1<?php
     2/**
     3 * REST API: WP_REST_Network_Meta_Fields class
     4 *
     5 * @package WordPress
     6 * @subpackage REST_API
     7 * @since 4.9.0
     8 */
     9
     10/**
     11 * Core class to manage network meta via the REST API.
     12 *
     13 * @since 4.9.0
     14 *
     15 * @see WP_REST_Meta_Fields
     16 */
     17class WP_REST_Network_Meta_Fields extends WP_REST_Meta_Fields {
     18
     19        /**
     20         * Retrieves the object type for network meta.
     21         *
     22         * @since 4.9.0
     23         *
     24         * @return string The meta type.
     25         */
     26        protected function get_meta_type() {
     27                return 'site';
     28        }
     29
     30        /**
     31         * Retrieves the type for register_rest_field() in the context of networks.
     32         *
     33         * @since 4.9.0
     34         *
     35         * @return string The REST field type.
     36         */
     37        public function get_rest_field_type() {
     38                return 'site';
     39        }
     40}
  • src/wp-includes/rest-api.php

    Property changes on: src/wp-includes/rest-api/fields/class-wp-rest-network-meta-fields.php
    ___________________________________________________________________
    Added: svn:executable
    ## -0,0 +1 ##
    +*
    \ No newline at end of property
     
    232232        // Settings.
    233233        $controller = new WP_REST_Settings_Controller;
    234234        $controller->register_routes();
     235
     236        if ( is_multisite() ) {
     237                // Networks.
     238                $controller = new WP_REST_Networks_Controller;
     239                $controller->register_routes();
     240        }
    235241}
    236242
    237243/**
  • src/wp-settings.php

     
    240240require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-term-meta-fields.php' );
    241241require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-user-meta-fields.php' );
    242242
     243if ( is_multisite() ) {
     244        require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-networks-controller.php' );
     245        require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-network-meta-fields.php' );
     246}
     247
    243248$GLOBALS['wp_embed'] = new WP_Embed();
    244249
    245250// Load multisite-specific files.