[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/rest-api/endpoints/ -> class-wp-rest-block-directory-controller.php (source)

   1  <?php
   2  /**
   3   * REST API: WP_REST_Block_Directory_Controller class
   4   *
   5   * @package WordPress
   6   * @subpackage REST_API
   7   * @since 5.5.0
   8   */
   9  
  10  /**
  11   * Controller which provides REST endpoint for the blocks.
  12   *
  13   * @since 5.5.0
  14   *
  15   * @see WP_REST_Controller
  16   */
  17  class WP_REST_Block_Directory_Controller extends WP_REST_Controller {
  18  
  19      /**
  20       * Constructs the controller.
  21       */
  22  	public function __construct() {
  23          $this->namespace = 'wp/v2';
  24          $this->rest_base = 'block-directory';
  25      }
  26  
  27      /**
  28       * Registers the necessary REST API routes.
  29       */
  30  	public function register_routes() {
  31          register_rest_route(
  32              $this->namespace,
  33              '/' . $this->rest_base . '/search',
  34              array(
  35                  array(
  36                      'methods'             => WP_REST_Server::READABLE,
  37                      'callback'            => array( $this, 'get_items' ),
  38                      'permission_callback' => array( $this, 'get_items_permissions_check' ),
  39                      'args'                => $this->get_collection_params(),
  40                  ),
  41                  'schema' => array( $this, 'get_public_item_schema' ),
  42              )
  43          );
  44      }
  45  
  46      /**
  47       * Checks whether a given request has permission to install and activate plugins.
  48       *
  49       * @since 5.5.0
  50       *
  51       * @param WP_REST_Request $request Full details about the request.
  52       * @return true|WP_Error True if the request has permission, WP_Error object otherwise.
  53       */
  54  	public function get_items_permissions_check( $request ) {
  55          if ( ! current_user_can( 'install_plugins' ) || ! current_user_can( 'activate_plugins' ) ) {
  56              return new WP_Error(
  57                  'rest_block_directory_cannot_view',
  58                  __( 'Sorry, you are not allowed to browse the block directory.' ),
  59                  array( 'status' => rest_authorization_required_code() )
  60              );
  61          }
  62  
  63          return true;
  64      }
  65  
  66      /**
  67       * Search and retrieve blocks metadata
  68       *
  69       * @since 5.5.0
  70       *
  71       * @param WP_REST_Request $request Full details about the request.
  72       * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
  73       */
  74  	public function get_items( $request ) {
  75          require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
  76          require_once ABSPATH . 'wp-admin/includes/plugin.php';
  77  
  78          $response = plugins_api(
  79              'query_plugins',
  80              array(
  81                  'block'    => $request['term'],
  82                  'per_page' => $request['per_page'],
  83                  'page'     => $request['page'],
  84              )
  85          );
  86  
  87          if ( is_wp_error( $response ) ) {
  88              $response->add_data( array( 'status' => 500 ) );
  89  
  90              return $response;
  91          }
  92  
  93          $result = array();
  94  
  95          foreach ( $response->plugins as $plugin ) {
  96              // If the API returned a plugin with empty data for 'blocks', skip it.
  97              if ( empty( $plugin['blocks'] ) ) {
  98                  continue;
  99              }
 100  
 101              $data     = $this->prepare_item_for_response( $plugin, $request );
 102              $result[] = $this->prepare_response_for_collection( $data );
 103          }
 104  
 105          return rest_ensure_response( $result );
 106      }
 107  
 108      /**
 109       * Parse block metadata for a block, and prepare it for an API response.
 110       *
 111       * @since 5.5.0
 112       * @since 5.9.0 Renamed `$plugin` to `$item` to match parent class for PHP 8 named parameter support.
 113       *
 114       * @param array           $item    The plugin metadata.
 115       * @param WP_REST_Request $request Request object.
 116       * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 117       */
 118  	public function prepare_item_for_response( $item, $request ) {
 119          // Restores the more descriptive, specific name for use within this method.
 120          $plugin = $item;
 121  
 122          // There might be multiple blocks in a plugin. Only the first block is mapped.
 123          $block_data = reset( $plugin['blocks'] );
 124  
 125          // A data array containing the properties we'll return.
 126          $block = array(
 127              'name'                => $block_data['name'],
 128              'title'               => ( $block_data['title'] ? $block_data['title'] : $plugin['name'] ),
 129              'description'         => wp_trim_words( $plugin['short_description'], 30, '...' ),
 130              'id'                  => $plugin['slug'],
 131              'rating'              => $plugin['rating'] / 20,
 132              'rating_count'        => (int) $plugin['num_ratings'],
 133              'active_installs'     => (int) $plugin['active_installs'],
 134              'author_block_rating' => $plugin['author_block_rating'] / 20,
 135              'author_block_count'  => (int) $plugin['author_block_count'],
 136              'author'              => wp_strip_all_tags( $plugin['author'] ),
 137              'icon'                => ( isset( $plugin['icons']['1x'] ) ? $plugin['icons']['1x'] : 'block-default' ),
 138              'last_updated'        => gmdate( 'Y-m-d\TH:i:s', strtotime( $plugin['last_updated'] ) ),
 139              'humanized_updated'   => sprintf(
 140                  /* translators: %s: Human-readable time difference. */
 141                  __( '%s ago' ),
 142                  human_time_diff( strtotime( $plugin['last_updated'] ) )
 143              ),
 144          );
 145  
 146          $this->add_additional_fields_to_object( $block, $request );
 147  
 148          $response = new WP_REST_Response( $block );
 149          $response->add_links( $this->prepare_links( $plugin ) );
 150  
 151          return $response;
 152      }
 153  
 154      /**
 155       * Generates a list of links to include in the response for the plugin.
 156       *
 157       * @since 5.5.0
 158       *
 159       * @param array $plugin The plugin data from WordPress.org.
 160       * @return array
 161       */
 162  	protected function prepare_links( $plugin ) {
 163          $links = array(
 164              'https://api.w.org/install-plugin' => array(
 165                  'href' => add_query_arg( 'slug', urlencode( $plugin['slug'] ), rest_url( 'wp/v2/plugins' ) ),
 166              ),
 167          );
 168  
 169          $plugin_file = $this->find_plugin_for_slug( $plugin['slug'] );
 170  
 171          if ( $plugin_file ) {
 172              $links['https://api.w.org/plugin'] = array(
 173                  'href'       => rest_url( 'wp/v2/plugins/' . substr( $plugin_file, 0, - 4 ) ),
 174                  'embeddable' => true,
 175              );
 176          }
 177  
 178          return $links;
 179      }
 180  
 181      /**
 182       * Finds an installed plugin for the given slug.
 183       *
 184       * @since 5.5.0
 185       *
 186       * @param string $slug The WordPress.org directory slug for a plugin.
 187       * @return string The plugin file found matching it.
 188       */
 189  	protected function find_plugin_for_slug( $slug ) {
 190          require_once ABSPATH . 'wp-admin/includes/plugin.php';
 191  
 192          $plugin_files = get_plugins( '/' . $slug );
 193  
 194          if ( ! $plugin_files ) {
 195              return '';
 196          }
 197  
 198          $plugin_files = array_keys( $plugin_files );
 199  
 200          return $slug . '/' . reset( $plugin_files );
 201      }
 202  
 203      /**
 204       * Retrieves the theme's schema, conforming to JSON Schema.
 205       *
 206       * @since 5.5.0
 207       *
 208       * @return array Item schema data.
 209       */
 210  	public function get_item_schema() {
 211          if ( $this->schema ) {
 212              return $this->add_additional_fields_schema( $this->schema );
 213          }
 214  
 215          $this->schema = array(
 216              '$schema'    => 'http://json-schema.org/draft-04/schema#',
 217              'title'      => 'block-directory-item',
 218              'type'       => 'object',
 219              'properties' => array(
 220                  'name'                => array(
 221                      'description' => __( 'The block name, in namespace/block-name format.' ),
 222                      'type'        => 'string',
 223                      'context'     => array( 'view' ),
 224                  ),
 225                  'title'               => array(
 226                      'description' => __( 'The block title, in human readable format.' ),
 227                      'type'        => 'string',
 228                      'context'     => array( 'view' ),
 229                  ),
 230                  'description'         => array(
 231                      'description' => __( 'A short description of the block, in human readable format.' ),
 232                      'type'        => 'string',
 233                      'context'     => array( 'view' ),
 234                  ),
 235                  'id'                  => array(
 236                      'description' => __( 'The block slug.' ),
 237                      'type'        => 'string',
 238                      'context'     => array( 'view' ),
 239                  ),
 240                  'rating'              => array(
 241                      'description' => __( 'The star rating of the block.' ),
 242                      'type'        => 'number',
 243                      'context'     => array( 'view' ),
 244                  ),
 245                  'rating_count'        => array(
 246                      'description' => __( 'The number of ratings.' ),
 247                      'type'        => 'integer',
 248                      'context'     => array( 'view' ),
 249                  ),
 250                  'active_installs'     => array(
 251                      'description' => __( 'The number sites that have activated this block.' ),
 252                      'type'        => 'integer',
 253                      'context'     => array( 'view' ),
 254                  ),
 255                  'author_block_rating' => array(
 256                      'description' => __( 'The average rating of blocks published by the same author.' ),
 257                      'type'        => 'number',
 258                      'context'     => array( 'view' ),
 259                  ),
 260                  'author_block_count'  => array(
 261                      'description' => __( 'The number of blocks published by the same author.' ),
 262                      'type'        => 'integer',
 263                      'context'     => array( 'view' ),
 264                  ),
 265                  'author'              => array(
 266                      'description' => __( 'The WordPress.org username of the block author.' ),
 267                      'type'        => 'string',
 268                      'context'     => array( 'view' ),
 269                  ),
 270                  'icon'                => array(
 271                      'description' => __( 'The block icon.' ),
 272                      'type'        => 'string',
 273                      'format'      => 'uri',
 274                      'context'     => array( 'view' ),
 275                  ),
 276                  'last_updated'        => array(
 277                      'description' => __( 'The date when the block was last updated.' ),
 278                      'type'        => 'string',
 279                      'format'      => 'date-time',
 280                      'context'     => array( 'view' ),
 281                  ),
 282                  'humanized_updated'   => array(
 283                      'description' => __( 'The date when the block was last updated, in fuzzy human readable format.' ),
 284                      'type'        => 'string',
 285                      'context'     => array( 'view' ),
 286                  ),
 287              ),
 288          );
 289  
 290          return $this->add_additional_fields_schema( $this->schema );
 291      }
 292  
 293      /**
 294       * Retrieves the search params for the blocks collection.
 295       *
 296       * @since 5.5.0
 297       *
 298       * @return array Collection parameters.
 299       */
 300  	public function get_collection_params() {
 301          $query_params = parent::get_collection_params();
 302  
 303          $query_params['context']['default'] = 'view';
 304  
 305          $query_params['term'] = array(
 306              'description' => __( 'Limit result set to blocks matching the search term.' ),
 307              'type'        => 'string',
 308              'required'    => true,
 309              'minLength'   => 1,
 310          );
 311  
 312          unset( $query_params['search'] );
 313  
 314          /**
 315           * Filters REST API collection parameters for the block directory controller.
 316           *
 317           * @since 5.5.0
 318           *
 319           * @param array $query_params JSON Schema-formatted collection parameters.
 320           */
 321          return apply_filters( 'rest_block_directory_collection_params', $query_params );
 322      }
 323  }


Generated: Fri Apr 26 01:00:03 2024 Cross-referenced by PHPXref 0.7.1