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 all 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
423 changes: 423 additions & 0 deletions lib/class-wp-rest-dependencies-controller.php

Large diffs are not rendered by default.

64 changes: 64 additions & 0 deletions lib/class-wp-rest-scripts-controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?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 = '__experimental';
$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() {
if ( null === $this->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' );
$this->core_assets = array_values( $handles );
}

return $this->core_assets;
}
}
52 changes: 52 additions & 0 deletions lib/class-wp-rest-styles-controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
/**
* Styles controller.
*
* @package gutenberg
*/

/**
* Class WP_REST_Styles_Controller
*/
class WP_REST_Styles_Controller extends WP_REST_Dependencies_Controller {

/**
* WP_REST_Styles_Controller constructor.
*/
public function __construct() {
$this->namespace = '__experimental';
$this->rest_base = 'styles';
$this->editor_block_dependency = 'editor_style';
$this->block_dependency = 'style';
$this->object = wp_styles();
}

/**
* Helper to get Style URL.
*
* @param string $src Style URL.
* @param string $ver Version URL.
* @param string $handle Handle name.
*
* @return string
*/
public function get_url( $src, $ver, $handle ) {
return $this->object->_css_href( $src, $ver, $handle );
}

/**
* Get core assets.
*
* @return array
*/
public function get_core_assets() {
if ( null === $this->core_assets ) {
$wp_styles = new WP_Styles();
wp_default_styles( $wp_styles );
$handles = wp_list_pluck( $wp_styles->registered, 'handle' );
$this->core_assets = array_values( $handles );
}

return $this->core_assets;
}
}
9 changes: 9 additions & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ function gutenberg_is_experiment_enabled( $name ) {
if ( ! class_exists( 'WP_REST_Menu_Locations_Controller' ) ) {
require_once dirname( __FILE__ ) . '/class-wp-rest-menu-locations-controller.php';
}
if ( ! class_exists( 'WP_REST_Dependencies_Controller' ) ) {
require_once dirname( __FILE__ ) . '/class-wp-rest-dependencies-controller.php';
}
if ( ! class_exists( 'WP_REST_Scripts_Controller' ) ) {
require_once dirname( __FILE__ ) . '/class-wp-rest-scripts-controller.php';
}
if ( ! class_exists( 'WP_REST_Styles_Controller' ) ) {
require_once dirname( __FILE__ ) . '/class-wp-rest-styles-controller.php';
}
if ( ! class_exists( 'WP_Rest_Customizer_Nonces' ) ) {
require_once dirname( __FILE__ ) . '/class-wp-rest-customizer-nonces.php';
}
Expand Down
60 changes: 60 additions & 0 deletions lib/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,20 @@ function wp_api_nav_menus_taxonomy_args( $args, $taxonomy ) {
}
add_filter( 'register_taxonomy_args', 'wp_api_nav_menus_taxonomy_args', 10, 2 );

/**
* Registers the scripts and styles area REST API routes.
*/
function gutenberg_register_script_style() {
// Scripts.
$controller = new WP_REST_Scripts_Controller();
$controller->register_routes();

// Styles.
$controller = new WP_REST_Styles_Controller();
$controller->register_routes();
}
add_action( 'rest_api_init', 'gutenberg_register_script_style' );

/**
* Shim for get_sample_permalink() to add support for auto-draft status.
*
Expand Down Expand Up @@ -355,3 +369,49 @@ function gutenberg_term_search_handler( $search_handlers ) {
return $search_handlers;
}
add_filter( 'wp_rest_search_handlers', 'gutenberg_term_search_handler', 10, 5 );

/**
* Adds style/script links to Block Types API endpoint response.
*
* @param \WP_REST_Response $response API response.
* @param \WP_Block_Type $block_type Block type.
*
* @return \WP_REST_Response Modified API response.
*/
function gutenberg_add_assets_links_to_block_type( $response, $block_type ) {
$links = array();
$scripts = array( 'editor_script', 'script' );
foreach ( $scripts as $script ) {
if ( ! isset( $block_type->$script ) ) {
continue;
}
$expected_handle = $block_type->$script;
if ( wp_script_is( $expected_handle, 'registered' ) ) {
$links[ 'https://api.w.org/' . $script ] = array(
'href' => rest_url( sprintf( '%s/%s/%s', '__experimental', 'scripts', $expected_handle ) ),
'embeddable' => true,
);
}
}

$styles = array( 'editor_style', 'style' );
foreach ( $styles as $style ) {
if ( ! isset( $block_type->$style ) ) {
continue;
}
$expected_handle = $block_type->$style;
if ( wp_style_is( $expected_handle, 'registered' ) ) {
$links[ 'https://api.w.org/' . $style ] = array(
'href' => rest_url( sprintf( '%s/%s/%s', '__experimental', 'styles', $expected_handle ) ),
'embeddable' => true,
);
}
}

if ( ! empty( $links ) ) {
$response->add_links( $links );
}

return $response;
}
add_filter( 'rest_prepare_block_type', 'gutenberg_add_assets_links_to_block_type', 10, 2 );
150 changes: 150 additions & 0 deletions phpunit/class-rest-block-types-controller-test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
<?php
/**
* REST API: REST_Block_Types_Controller_Test class
*
* @package WordPress
* @subpackage REST_API
*/

/**
* Tests for REST API for Widgets.
*
* @see WP_Test_REST_Controller_Testcase
*/
class REST_Block_Types_Controller_Test extends WP_Test_REST_TestCase {
/**
* @var int
*/
protected static $admin_id;

/**
* Create fake data before our tests run.
*
* @param WP_UnitTest_Factory $factory Helper that lets us create fake data.
*/
public static function wpSetUpBeforeClass( $factory ) {
self::$admin_id = $factory->user->create(
array(
'role' => 'administrator',
)
);
wp_register_script( 'core-assets-test-script', home_url( '/assets/test-script.js' ) );
wp_register_script( 'core-assets-test-editor-script', home_url( '/assets/test-editor-script.js' ) );
wp_register_style( 'core-assets-test-style', home_url( '/assets/test-style.css' ) );
wp_register_style( 'core-assets-test-editor-style', home_url( '/assets/test-editor-style.css' ) );
}

/**
* Tear down after class tests are done.
*/
public static function wpTearDownAfterClass() {
self::delete_user( self::$admin_id );
unregister_block_type( 'core/assets-test' );
}

/**
* Test whether test block type contains scripts/styles links.
*
* @dataProvider dataProviderTestCases
*/
public function test_links_in_block( $block_name, $block_parameters ) {
wp_set_current_user( self::$admin_id );
register_block_type( $block_name, $block_parameters );
$endpoint = sprintf( '/wp/v2/block-types/%s', $block_name );
$request = new WP_REST_Request( 'GET', $endpoint );
$response = rest_get_server()->dispatch( $request );
$links = $response->get_links();
$this->assertEquals( 200, $response->get_status() );
foreach ( $block_parameters as $block_parameter => $parameter_value ) {
$links_key = sprintf( 'https://api.w.org/%s', $block_parameter );
if ( empty( $parameter_value ) ) {
$this->assertArrayNotHasKey( $links_key, $links );
} else {
$this->assertArrayHasKey( $links_key, $links );
$this->assertNotEmpty( $links[ $links_key ] );
}
}
}

/**
* Provide test cases.
*
* @return array[]
*/
public function dataProviderTestCases() {
return array(
array(
'core/assets-test-1',
array(
'script' => '',
'style' => '',
'editor_script' => '',
'editor_style' => '',
),
),
array(
'core/assets-test-2',
array(
'script' => 'core-assets-test-script',
'style' => '',
'editor_script' => '',
'editor_style' => '',
),
),
array(
'core/assets-test-3',
array(
'script' => '',
'style' => 'core-assets-test-style',
'editor_script' => '',
'editor_style' => '',
),
),
array(
'core/assets-test-4',
array(
'script' => '',
'style' => '',
'editor_script' => 'core-assets-test-editor-script',
'editor_style' => '',
),
),
array(
'core/assets-test-5',
array(
'script' => '',
'style' => '',
'editor_script' => '',
'editor_style' => 'core-assets-test-editor-style',
),
),
array(
'core/assets-test-6',
array(
'script' => '',
'style' => 'core-assets-test-style',
'editor_script' => '',
'editor_style' => 'core-assets-test-editor-style',
),
),
array(
'core/assets-test-7',
array(
'script' => 'core-assets-test-script',
'style' => 'core-assets-test-style',
'editor_script' => 'core-assets-test-editor-script',
'editor_style' => 'core-assets-test-editor-style',
),
),
array(
'core/assets-test-8',
array(
'script' => 'core-assets-test-script',
'style' => '',
'editor_script' => 'core-assets-test-editor-script',
'editor_style' => 'core-assets-test-editor-style',
),
),
);
}
}
Loading