Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add script and style REST APIs #21244

Open
wants to merge 45 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
a35cf09
Add script and style REST APIs
spacedmonkey Mar 29, 2020
34c4fff
Fix PHP
spacedmonkey Apr 5, 2020
fef5c04
Fix lints
spacedmonkey Apr 5, 2020
b769fe3
Update lib/class-wp-rest-dependencies-controller.php
spacedmonkey Apr 6, 2020
529dd66
Merge branch 'master' into feature/dependancy-api
spacedmonkey May 27, 2020
6bab6e9
Add embed links.
spacedmonkey May 27, 2020
cd40b89
Normalize data.
spacedmonkey Jun 10, 2020
e84e14f
More tweaks
spacedmonkey Jun 10, 2020
6d3b643
Change namespace.
spacedmonkey Jun 10, 2020
a833c52
Add valid permission checks.
spacedmonkey Jun 11, 2020
4d408e9
Merge branch 'master' into feature/dependancy-api
spacedmonkey Jul 16, 2020
1828bac
Merge branch 'master' into feature/dependancy-api
Oct 20, 2020
1d14106
Fix lib/load.php spacing
Oct 20, 2020
d3eaebf
Implement PR feedback regarding code readability and abstract methods
Oct 20, 2020
bc7b1de
Move adding links to block types into filter supported by Core
Oct 21, 2020
562342c
Updated comments
Oct 21, 2020
3760c29
Block types tests to ensure links for scripts / styles work correctly
Oct 21, 2020
5233f72
Fix phpcs linting
Oct 21, 2020
88ac877
Added tests for new controllers
Oct 23, 2020
8a6127e
Updated controllers to avoid get_core_assets() body code duplicated e…
Oct 23, 2020
e0bf62a
Fix typo in APi word
Oct 23, 2020
ec18a68
Fix CI issues
Oct 23, 2020
d4afbe8
Fix CI issues
Oct 23, 2020
aa852f5
Exclude asset from its dependencies list
Oct 23, 2020
01012ca
Update phpunit/class-rest-block-types-controller-test.php
lukaspawlik Oct 23, 2020
0c3982f
Update phpunit/class-rest-scripts-controller-test.php
lukaspawlik Oct 23, 2020
71b5e79
Address PR feedback
Oct 23, 2020
e0f5ec4
Refactor code as per PR feedback
Oct 23, 2020
3cf5f6e
Merge branch 'feature/dependency-api-tweaks' of github.com:spacedmonk…
Oct 23, 2020
9537a99
Update lib/rest-api.php
lukaspawlik Oct 23, 2020
d1d173d
Update lib/rest-api.php
lukaspawlik Oct 23, 2020
5c04954
Add dedicated test to check asset being excluded from its dependencie…
Oct 23, 2020
6a92e75
Reorder tests methods to follow best practices
Oct 23, 2020
4adbca7
Add new tests
Oct 23, 2020
8652186
Added more dependencies REST endpoints tests
Oct 23, 2020
7035c3e
Use dataProvider instead of loops
Oct 30, 2020
0f6c780
Update phpunit/class-rest-scripts-controller-test.php
lukaspawlik Oct 30, 2020
4a50d48
Update phpunit/class-rest-styles-controller-test.php
lukaspawlik Oct 30, 2020
aa4b637
Fixed tests
Oct 30, 2020
9c38284
Merge branch 'feature/dependency-api-tweaks' of github.com:spacedmonk…
Oct 30, 2020
6ebdf84
Fixed tests
Oct 30, 2020
c8db238
Merge branch 'master' into feature/dependency-api-tweaks
Oct 30, 2020
9bfe1ae
Merge branch 'master' into feature/dependancy-api
Oct 30, 2020
4170447
Merge branch 'feature/dependancy-api' into feature/dependency-api-tweaks
Oct 30, 2020
65b2d87
Merge pull request #1 from spacedmonkey/feature/dependency-api-tweaks
spacedmonkey Oct 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
288 changes: 288 additions & 0 deletions lib/class-wp-rest-dependencies-controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
<?php
/**
* Dependencies controller.
*
* @package gutenberg
*/

/**
* Extendable dependency class.
*
* Class WP_REST_Dependencies_Controller
*
* @see WP_REST_Controller
*/
class WP_REST_Dependencies_Controller extends WP_REST_Controller {

/**
* Dependencies core object.
*
* @var Object
*/
protected $object;


/**
* $editor_block_dependency
*
* @var string
*/
protected $editor_block_dependency = '';


/**
* $block_dependency
*
* @var string
*/
protected $block_dependency = '';

/**
* Register routes.
*/
public function register_routes() {
register_rest_route(
$this->namespace,
'/' . $this->rest_base,
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
'args' => $this->get_collection_params(),
),
'schema' => array( $this, 'get_item_schema' ),
)
);

$get_item_args = array(
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
);

register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/(?P<handle>[\w-]+)',
array(
'args' => array(
'handle' => array(
'description' => __( 'Unique identifier for the object.', 'gutenberg' ),
'type' => 'string',
),
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_item' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
'args' => $get_item_args,
),
'schema' => array( $this, 'get_public_item_schema' ),
)
);
}

/**
* Get list of dependencies.
*
* @param WP_REST_Request $request Request.
*
* @return array|WP_Error|WP_REST_Response
*/
public function get_items( $request ) {
$data = [];
$handle = $request['dependency'];
$filter = [];
if ( $handle ) {
$this->object->all_deps( $handle );
$filter = $this->object->to_do;
}

if ( $handle ) {
foreach ( $filter as $dependency_handle ) {
foreach ( $this->object->registered as $dependency ) {
if ( $dependency_handle === $dependency->handle ) {
$item = $this->prepare_item_for_response( $dependency, $request );
$data[] = $this->prepare_response_for_collection( $item );
}
}
}
} else {
foreach ( $this->object->registered as $dependency ) {
$item = $this->prepare_item_for_response( $dependency, $request );
$data[] = $this->prepare_response_for_collection( $item );
}
}

return $data;
}

/**
* Get a single depencies.
spacedmonkey marked this conversation as resolved.
Show resolved Hide resolved
*
* @param WP_REST_Request $request Request.
*
* @return array|mixed|WP_Error|WP_REST_Response
*/
public function get_item( $request ) {
if ( ! isset( $this->object->registered[ $request['handle'] ] ) ) {
return [];
}
$dependency = $this->object->registered[ $request['handle'] ];
$data = $this->prepare_item_for_response( $dependency, $request );

return $data;
}

/**
* Prepare item for response.
*
* @param mixed $dependency Dependency.
* @param WP_REST_Request $request Request.
*
* @return mixed|WP_Error|WP_REST_Response
*/
public function prepare_item_for_response( $dependency, $request ) {
$dependency->url = $this->get_url( $dependency->src, $dependency->ver, $dependency->handle );
$response = rest_ensure_response( (array) $dependency );
$dependencies = $this->prepare_links( $dependency );
$response->add_links( $dependencies );

return $response;
}

/**
* Permission check.
*
* @param WP_REST_Request $request Request.
*
* @return bool|true|WP_Error
*/
public function get_items_permissions_check( $request ) {
if ( $this->check_handle( $request['dependency'] ) ) {
return true;
spacedmonkey marked this conversation as resolved.
Show resolved Hide resolved
}

return current_user_can( 'manage_options' );
}

/**
* Permission check.
*
* @param WP_REST_Request $request Request.
*
* @return bool|true|WP_Error
*/
public function get_item_permissions_check( $request ) {
if ( $this->check_handle( $request['handle'] ) ) {
return true;
aristath marked this conversation as resolved.
Show resolved Hide resolved
}

return current_user_can( 'manage_options' );
}

/**
* Prepare links.
*
* @param object $dependency Dependency.
*
* @return array
*/
protected function prepare_links( $dependency ) {
$base = sprintf( '%s/%s', $this->namespace, $this->rest_base );
// Entity meta.
$links = array(
'self' => array(
'href' => rest_url( trailingslashit( $base ) . $dependency->handle ),
),
'collection' => array(
'href' => rest_url( $base ),
),
'deps' => array(
'href' => rest_url( trailingslashit( $base ) . '?dependency=' . $dependency->handle ),
),
);

return $links;
}

/**
* Get collection params.
*
* @return array
*/
public function get_collection_params() {
$query_params = parent::get_collection_params();
$query_params['context']['default'] = 'view';

$query_params['dependency'] = array(
'description' => __( 'Dependency.', 'gutenberg' ),
'type' => 'string',
);

return $query_params;
}

/**
* Check handle exists and is viewable.
*
* @param string $handle script / style handle.
*
* @return bool
*/
protected function check_handle( $handle ) {

if ( ! $handle ) {
return false;
}

// All core assets should be public.
if ( in_array( $handle, $this->get_core_assets(), true ) ) {
return true;
}

// All block public assets should also be public.
if ( in_array( $handle, $this->block_asset( $this->block_dependency ), true ) ) {
return true;
}

// All block edit assets should check if user is logged in and has the ability to using the editor.
if ( in_array( $handle, $this->block_asset( $this->editor_block_dependency ), true ) ) {
return current_user_can( 'edit_posts' );
}

return false;
}

/**
* Get core assets.
*
* @return array
*/
public function get_core_assets() {
/* translators: %s: Method name. */
_doing_it_wrong( sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'gutenberg' ), __METHOD__ ), 'x.x' );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this just be an abstract method?


return array();
}

/**
* Block asset.
*
* @param string $field Field to pluck from list of objects.
*
* @return array
*/
protected function block_asset( $field ) {
if ( ! $field ) {
return array();
}

$block_registry = WP_Block_Type_Registry::get_instance();
$blocks = $block_registry->get_all_registered();
$handles = wp_list_pluck( $blocks, $field );
$handles = array_values( $handles );
$handles = array_filter( $handles );

return $handles;
}

}
61 changes: 61 additions & 0 deletions lib/class-wp-rest-scripts-controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php
/**
* Scripts controller.
*
* @package gutenberg
*/

/**
* Class WP_REST_Scripts_Controller
*/
class WP_REST_Scripts_Controller extends WP_REST_Dependencies_Controller {
/**
* WP_REST_Scripts_Controller constructor.
*/
public function __construct() {
$this->namespace = 'wp/v2';
$this->rest_base = 'scripts';
$this->editor_block_dependency = 'editor_script';
$this->block_dependency = 'script';
$this->object = wp_scripts();
}

/**
* Helper to get Script URL.
*
* @param string $src Script URL.
* @param string $ver Version URL.
* @param string $handle Handle name.
*
* @return string
*/
public function get_url( $src, $ver, $handle ) {
if ( ! is_bool( $src ) && ! preg_match( '|^(https?:)?//|', $src ) && ! ( $this->object->content_url && 0 === strpos( $src, $this->object->content_url ) ) ) {
$src = $this->object->base_url . $src;
}
if ( ! empty( $ver ) ) {
$src = add_query_arg( 'ver', $ver, $src );
}

/** This filter is documented in wp-includes/class.wp-scripts.php */
$src = esc_url( apply_filters( 'script_loader_src', $src, $handle ) );

return esc_url( $src );
}

/**
* Get core assets.
*
* @return array
*/
public function get_core_assets() {
$wp_scripts = new WP_Scripts();
wp_default_scripts( $wp_scripts );
wp_default_packages_vendor( $wp_scripts );
wp_default_packages_scripts( $wp_scripts );
$handles = wp_list_pluck( $wp_scripts->registered, 'handle' );
$handles = array_values( $handles );

return $handles;
}
}
Loading