[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/rest-api/endpoints/ -> class-wp-rest-global-styles-revisions-controller.php (source)

   1  <?php
   2  /**
   3   * REST API: WP_REST_Global_Styles_Revisions_Controller class
   4   *
   5   * @package WordPress
   6   * @subpackage REST_API
   7   * @since 6.3.0
   8   */
   9  
  10  /**
  11   * Core class used to access global styles revisions via the REST API.
  12   *
  13   * @since 6.3.0
  14   *
  15   * @see WP_REST_Controller
  16   */
  17  class WP_REST_Global_Styles_Revisions_Controller extends WP_REST_Revisions_Controller {
  18      /**
  19       * Parent controller.
  20       *
  21       * @since 6.6.0
  22       * @var WP_REST_Controller
  23       */
  24      private $parent_controller;
  25  
  26      /**
  27       * The base of the parent controller's route.
  28       *
  29       * @since 6.3.0
  30       * @var string
  31       */
  32      protected $parent_base;
  33  
  34      /**
  35       * Parent post type.
  36       *
  37       * @since 6.6.0
  38       * @var string
  39       */
  40      protected $parent_post_type;
  41  
  42      /**
  43       * Constructor.
  44       *
  45       * @since 6.3.0
  46       * @since 6.6.0 Extends class from WP_REST_Revisions_Controller.
  47       *
  48       * @param string $parent_post_type Post type of the parent.
  49       */
  50  	public function __construct( $parent_post_type = 'wp_global_styles' ) {
  51          parent::__construct( $parent_post_type );
  52          $post_type_object  = get_post_type_object( $parent_post_type );
  53          $parent_controller = $post_type_object->get_rest_controller();
  54  
  55          if ( ! $parent_controller ) {
  56              $parent_controller = new WP_REST_Global_Styles_Controller( $parent_post_type );
  57          }
  58  
  59          $this->parent_controller = $parent_controller;
  60          $this->rest_base         = 'revisions';
  61          $this->parent_base       = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name;
  62          $this->namespace         = ! empty( $post_type_object->rest_namespace ) ? $post_type_object->rest_namespace : 'wp/v2';
  63      }
  64  
  65      /**
  66       * Registers the controller's routes.
  67       *
  68       * @since 6.3.0
  69       * @since 6.6.0 Added route to fetch individual global styles revisions.
  70       */
  71  	public function register_routes() {
  72          register_rest_route(
  73              $this->namespace,
  74              '/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base,
  75              array(
  76                  'args'   => array(
  77                      'parent' => array(
  78                          'description' => __( 'The ID for the parent of the revision.' ),
  79                          'type'        => 'integer',
  80                      ),
  81                  ),
  82                  array(
  83                      'methods'             => WP_REST_Server::READABLE,
  84                      'callback'            => array( $this, 'get_items' ),
  85                      'permission_callback' => array( $this, 'get_items_permissions_check' ),
  86                      'args'                => $this->get_collection_params(),
  87                  ),
  88                  'schema' => array( $this, 'get_public_item_schema' ),
  89              )
  90          );
  91  
  92          register_rest_route(
  93              $this->namespace,
  94              '/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base . '/(?P<id>[\d]+)',
  95              array(
  96                  'args'   => array(
  97                      'parent' => array(
  98                          'description' => __( 'The ID for the parent of the global styles revision.' ),
  99                          'type'        => 'integer',
 100                      ),
 101                      'id'     => array(
 102                          'description' => __( 'Unique identifier for the global styles revision.' ),
 103                          'type'        => 'integer',
 104                      ),
 105                  ),
 106                  array(
 107                      'methods'             => WP_REST_Server::READABLE,
 108                      'callback'            => array( $this, 'get_item' ),
 109                      'permission_callback' => array( $this, 'get_item_permissions_check' ),
 110                      'args'                => array(
 111                          'context' => $this->get_context_param( array( 'default' => 'view' ) ),
 112                      ),
 113                  ),
 114                  'schema' => array( $this, 'get_public_item_schema' ),
 115              )
 116          );
 117      }
 118  
 119      /**
 120       * Returns decoded JSON from post content string,
 121       * or a 404 if not found.
 122       *
 123       * @since 6.3.0
 124       *
 125       * @param string $raw_json Encoded JSON from global styles custom post content.
 126       * @return Array|WP_Error
 127       */
 128  	protected function get_decoded_global_styles_json( $raw_json ) {
 129          $decoded_json = json_decode( $raw_json, true );
 130  
 131          if ( is_array( $decoded_json ) && isset( $decoded_json['isGlobalStylesUserThemeJSON'] ) && true === $decoded_json['isGlobalStylesUserThemeJSON'] ) {
 132              return $decoded_json;
 133          }
 134  
 135          return new WP_Error(
 136              'rest_global_styles_not_found',
 137              __( 'Cannot find user global styles revisions.' ),
 138              array( 'status' => 404 )
 139          );
 140      }
 141  
 142      /**
 143       * Returns paginated revisions of the given global styles config custom post type.
 144       *
 145       * The bulk of the body is taken from WP_REST_Revisions_Controller->get_items,
 146       * but global styles does not require as many parameters.
 147       *
 148       * @since 6.3.0
 149       *
 150       * @param WP_REST_Request $request The request instance.
 151       * @return WP_REST_Response|WP_Error
 152       */
 153  	public function get_items( $request ) {
 154          $parent = $this->get_parent( $request['parent'] );
 155  
 156          if ( is_wp_error( $parent ) ) {
 157              return $parent;
 158          }
 159  
 160          $global_styles_config = $this->get_decoded_global_styles_json( $parent->post_content );
 161  
 162          if ( is_wp_error( $global_styles_config ) ) {
 163              return $global_styles_config;
 164          }
 165  
 166          if ( wp_revisions_enabled( $parent ) ) {
 167              $registered = $this->get_collection_params();
 168              $query_args = array(
 169                  'post_parent'    => $parent->ID,
 170                  'post_type'      => 'revision',
 171                  'post_status'    => 'inherit',
 172                  'posts_per_page' => -1,
 173                  'orderby'        => 'date ID',
 174                  'order'          => 'DESC',
 175              );
 176  
 177              $parameter_mappings = array(
 178                  'offset'   => 'offset',
 179                  'page'     => 'paged',
 180                  'per_page' => 'posts_per_page',
 181              );
 182  
 183              foreach ( $parameter_mappings as $api_param => $wp_param ) {
 184                  if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) {
 185                      $query_args[ $wp_param ] = $request[ $api_param ];
 186                  }
 187              }
 188  
 189              $revisions_query = new WP_Query();
 190              $revisions       = $revisions_query->query( $query_args );
 191              $offset          = isset( $query_args['offset'] ) ? (int) $query_args['offset'] : 0;
 192              $page            = (int) $query_args['paged'];
 193              $total_revisions = $revisions_query->found_posts;
 194  
 195              if ( $total_revisions < 1 ) {
 196                  // Out-of-bounds, run the query again without LIMIT for total count.
 197                  unset( $query_args['paged'], $query_args['offset'] );
 198                  $count_query = new WP_Query();
 199                  $count_query->query( $query_args );
 200  
 201                  $total_revisions = $count_query->found_posts;
 202              }
 203  
 204              if ( $revisions_query->query_vars['posts_per_page'] > 0 ) {
 205                  $max_pages = (int) ceil( $total_revisions / (int) $revisions_query->query_vars['posts_per_page'] );
 206              } else {
 207                  $max_pages = $total_revisions > 0 ? 1 : 0;
 208              }
 209              if ( $total_revisions > 0 ) {
 210                  if ( $offset >= $total_revisions ) {
 211                      return new WP_Error(
 212                          'rest_revision_invalid_offset_number',
 213                          __( 'The offset number requested is larger than or equal to the number of available revisions.' ),
 214                          array( 'status' => 400 )
 215                      );
 216                  } elseif ( ! $offset && $page > $max_pages ) {
 217                      return new WP_Error(
 218                          'rest_revision_invalid_page_number',
 219                          __( 'The page number requested is larger than the number of pages available.' ),
 220                          array( 'status' => 400 )
 221                      );
 222                  }
 223              }
 224          } else {
 225              $revisions       = array();
 226              $total_revisions = 0;
 227              $max_pages       = 0;
 228              $page            = (int) $request['page'];
 229          }
 230  
 231          $response = array();
 232  
 233          foreach ( $revisions as $revision ) {
 234              $data       = $this->prepare_item_for_response( $revision, $request );
 235              $response[] = $this->prepare_response_for_collection( $data );
 236          }
 237  
 238          $response = rest_ensure_response( $response );
 239  
 240          $response->header( 'X-WP-Total', (int) $total_revisions );
 241          $response->header( 'X-WP-TotalPages', (int) $max_pages );
 242  
 243          $request_params = $request->get_query_params();
 244          $base_path      = rest_url( sprintf( '%s/%s/%d/%s', $this->namespace, $this->parent_base, $request['parent'], $this->rest_base ) );
 245          $base           = add_query_arg( urlencode_deep( $request_params ), $base_path );
 246  
 247          if ( $page > 1 ) {
 248              $prev_page = $page - 1;
 249  
 250              if ( $prev_page > $max_pages ) {
 251                  $prev_page = $max_pages;
 252              }
 253  
 254              $prev_link = add_query_arg( 'page', $prev_page, $base );
 255              $response->link_header( 'prev', $prev_link );
 256          }
 257          if ( $max_pages > $page ) {
 258              $next_page = $page + 1;
 259              $next_link = add_query_arg( 'page', $next_page, $base );
 260  
 261              $response->link_header( 'next', $next_link );
 262          }
 263  
 264          return $response;
 265      }
 266  
 267      /**
 268       * Prepares the revision for the REST response.
 269       *
 270       * @since 6.3.0
 271       * @since 6.6.0 Added resolved URI links to the response.
 272       *
 273       * @param WP_Post         $post    Post revision object.
 274       * @param WP_REST_Request $request Request object.
 275       * @return WP_REST_Response|WP_Error Response object.
 276       */
 277  	public function prepare_item_for_response( $post, $request ) {
 278          $parent               = $this->get_parent( $request['parent'] );
 279          $global_styles_config = $this->get_decoded_global_styles_json( $post->post_content );
 280  
 281          if ( is_wp_error( $global_styles_config ) ) {
 282              return $global_styles_config;
 283          }
 284  
 285          $fields     = $this->get_fields_for_response( $request );
 286          $data       = array();
 287          $theme_json = null;
 288  
 289          if ( ! empty( $global_styles_config['styles'] ) || ! empty( $global_styles_config['settings'] ) ) {
 290              $theme_json           = new WP_Theme_JSON( $global_styles_config, 'custom' );
 291              $global_styles_config = $theme_json->get_raw_data();
 292              if ( rest_is_field_included( 'settings', $fields ) ) {
 293                  $data['settings'] = ! empty( $global_styles_config['settings'] ) ? $global_styles_config['settings'] : new stdClass();
 294              }
 295              if ( rest_is_field_included( 'styles', $fields ) ) {
 296                  $data['styles'] = ! empty( $global_styles_config['styles'] ) ? $global_styles_config['styles'] : new stdClass();
 297              }
 298          }
 299  
 300          if ( rest_is_field_included( 'author', $fields ) ) {
 301              $data['author'] = (int) $post->post_author;
 302          }
 303  
 304          if ( rest_is_field_included( 'date', $fields ) ) {
 305              $data['date'] = $this->prepare_date_response( $post->post_date_gmt, $post->post_date );
 306          }
 307  
 308          if ( rest_is_field_included( 'date_gmt', $fields ) ) {
 309              $data['date_gmt'] = $this->prepare_date_response( $post->post_date_gmt );
 310          }
 311  
 312          if ( rest_is_field_included( 'id', $fields ) ) {
 313              $data['id'] = (int) $post->ID;
 314          }
 315  
 316          if ( rest_is_field_included( 'modified', $fields ) ) {
 317              $data['modified'] = $this->prepare_date_response( $post->post_modified_gmt, $post->post_modified );
 318          }
 319  
 320          if ( rest_is_field_included( 'modified_gmt', $fields ) ) {
 321              $data['modified_gmt'] = $this->prepare_date_response( $post->post_modified_gmt );
 322          }
 323  
 324          if ( rest_is_field_included( 'parent', $fields ) ) {
 325              $data['parent'] = (int) $parent->ID;
 326          }
 327  
 328          $context             = ! empty( $request['context'] ) ? $request['context'] : 'view';
 329          $data                = $this->add_additional_fields_to_object( $data, $request );
 330          $data                = $this->filter_response_by_context( $data, $context );
 331          $response            = rest_ensure_response( $data );
 332          $resolved_theme_uris = WP_Theme_JSON_Resolver::get_resolved_theme_uris( $theme_json );
 333  
 334          if ( ! empty( $resolved_theme_uris ) ) {
 335              $response->add_links(
 336                  array(
 337                      'https://api.w.org/theme-file' => $resolved_theme_uris,
 338                  )
 339              );
 340          }
 341  
 342          return $response;
 343      }
 344  
 345      /**
 346       * Retrieves the revision's schema, conforming to JSON Schema.
 347       *
 348       * @since 6.3.0
 349       * @since 6.6.0 Merged parent and parent controller schema data.
 350       *
 351       * @return array Item schema data.
 352       */
 353  	public function get_item_schema() {
 354          if ( $this->schema ) {
 355              return $this->add_additional_fields_schema( $this->schema );
 356          }
 357  
 358          $schema               = parent::get_item_schema();
 359          $parent_schema        = $this->parent_controller->get_item_schema();
 360          $schema['properties'] = array_merge( $schema['properties'], $parent_schema['properties'] );
 361  
 362          unset(
 363              $schema['properties']['guid'],
 364              $schema['properties']['slug'],
 365              $schema['properties']['meta'],
 366              $schema['properties']['content'],
 367              $schema['properties']['title']
 368          );
 369  
 370              $this->schema = $schema;
 371  
 372          return $this->add_additional_fields_schema( $this->schema );
 373      }
 374  
 375      /**
 376       * Retrieves the query params for collections.
 377       * Removes params that are not supported by global styles revisions.
 378       *
 379       * @since 6.6.0
 380       *
 381       * @return array Collection parameters.
 382       */
 383  	public function get_collection_params() {
 384          $query_params = parent::get_collection_params();
 385          unset(
 386              $query_params['exclude'],
 387              $query_params['include'],
 388              $query_params['search'],
 389              $query_params['order'],
 390              $query_params['orderby']
 391          );
 392          return $query_params;
 393      }
 394  }


Generated : Sat Dec 21 08:20:01 2024 Cross-referenced by PHPXref