REST API: Add additional fields to the themes controller.
When the themes controller was introduced it only returned a theme's supported features. This adds the majority of a theme's header information to the response. Props ockham, spacedmonkey. Fixes #49906. git-svn-id: https://develop.svn.wordpress.org/trunk@47921 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
602faebb0d
commit
4fb1e58c50
@ -115,10 +115,65 @@ class WP_REST_Themes_Controller extends WP_REST_Controller {
|
|||||||
$data = array();
|
$data = array();
|
||||||
$fields = $this->get_fields_for_response( $request );
|
$fields = $this->get_fields_for_response( $request );
|
||||||
|
|
||||||
if ( in_array( 'theme_supports', $fields, true ) ) {
|
if ( rest_is_field_included( 'stylesheet', $fields ) ) {
|
||||||
|
$data['stylesheet'] = $theme->get_stylesheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rest_is_field_included( 'template', $fields ) ) {
|
||||||
|
/**
|
||||||
|
* Use the get_template() method, not the 'Template' header, for finding the template.
|
||||||
|
* The 'Template' header is only good for what was written in the style.css, while
|
||||||
|
* get_template() takes into account where WordPress actually located the theme and
|
||||||
|
* whether it is actually valid.
|
||||||
|
*/
|
||||||
|
$data['template'] = $theme->get_template();
|
||||||
|
}
|
||||||
|
|
||||||
|
$plain_field_mappings = array(
|
||||||
|
'requires_php' => 'RequiresPHP',
|
||||||
|
'requires_wp' => 'RequiresWP',
|
||||||
|
'textdomain' => 'TextDomain',
|
||||||
|
'version' => 'Version',
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ( $plain_field_mappings as $field => $header ) {
|
||||||
|
if ( rest_is_field_included( $field, $fields ) ) {
|
||||||
|
$data[ $field ] = $theme->get( $header );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rest_is_field_included( 'screenshot', $fields ) ) {
|
||||||
|
// Using $theme->get_screenshot() with no args to get absolute URL.
|
||||||
|
$data['screenshot'] = $theme->get_screenshot() ?: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$rich_field_mappings = array(
|
||||||
|
'author' => 'Author',
|
||||||
|
'author_uri' => 'AuthorURI',
|
||||||
|
'description' => 'Description',
|
||||||
|
'name' => 'Name',
|
||||||
|
'tags' => 'Tags',
|
||||||
|
'theme_uri' => 'ThemeURI',
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ( $rich_field_mappings as $field => $header ) {
|
||||||
|
if ( rest_is_field_included( "{$field}.raw", $fields ) ) {
|
||||||
|
$data[ $field ]['raw'] = $theme->display( $header, false, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rest_is_field_included( "{$field}.rendered", $fields ) ) {
|
||||||
|
$data[ $field ]['rendered'] = $theme->display( $header );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rest_is_field_included( 'theme_supports', $fields ) ) {
|
||||||
$item_schemas = $this->get_item_schema();
|
$item_schemas = $this->get_item_schema();
|
||||||
$theme_supports = $item_schemas['properties']['theme_supports']['properties'];
|
$theme_supports = $item_schemas['properties']['theme_supports']['properties'];
|
||||||
foreach ( $theme_supports as $name => $schema ) {
|
foreach ( $theme_supports as $name => $schema ) {
|
||||||
|
if ( ! rest_is_field_included( "theme_supports.{$name}", $fields ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( 'formats' === $name ) {
|
if ( 'formats' === $name ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -192,6 +247,117 @@ class WP_REST_Themes_Controller extends WP_REST_Controller {
|
|||||||
'title' => 'theme',
|
'title' => 'theme',
|
||||||
'type' => 'object',
|
'type' => 'object',
|
||||||
'properties' => array(
|
'properties' => array(
|
||||||
|
'stylesheet' => array(
|
||||||
|
'description' => __( 'The theme\'s stylesheet. This uniquely identifies the theme.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'readonly' => true,
|
||||||
|
),
|
||||||
|
'template' => array(
|
||||||
|
'description' => __( 'The theme\'s template. If this is a child theme, this refers to the parent theme, otherwise this is the same as the theme\'s stylesheet.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'readonly' => true,
|
||||||
|
),
|
||||||
|
'author' => array(
|
||||||
|
'description' => __( 'The theme author.' ),
|
||||||
|
'type' => 'object',
|
||||||
|
'readonly' => true,
|
||||||
|
'properties' => array(
|
||||||
|
'raw' => array(
|
||||||
|
'description' => __( 'The theme author\'s name, as found in the theme header.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
),
|
||||||
|
'rendered' => array(
|
||||||
|
'description' => __( 'HTML for the theme author, transformed for display.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'author_uri' => array(
|
||||||
|
'description' => __( 'The website of the theme author.' ),
|
||||||
|
'type' => 'object',
|
||||||
|
'readonly' => true,
|
||||||
|
'properties' => array(
|
||||||
|
'raw' => array(
|
||||||
|
'description' => __( 'The website of the theme author, as found in the theme header.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'format' => 'uri',
|
||||||
|
),
|
||||||
|
'rendered' => array(
|
||||||
|
'description' => __( 'The website of the theme author, transformed for display.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'format' => 'uri',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'description' => array(
|
||||||
|
'description' => __( 'A description of the theme.' ),
|
||||||
|
'type' => 'object',
|
||||||
|
'readonly' => true,
|
||||||
|
'properties' => array(
|
||||||
|
'raw' => array(
|
||||||
|
'description' => __( 'The theme description, as found in the theme header.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
),
|
||||||
|
'rendered' => array(
|
||||||
|
'description' => __( 'The theme description, transformed for display.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'name' => array(
|
||||||
|
'description' => __( 'The name of the theme.' ),
|
||||||
|
'type' => 'object',
|
||||||
|
'readonly' => true,
|
||||||
|
'properties' => array(
|
||||||
|
'raw' => array(
|
||||||
|
'description' => __( 'The theme name, as found in the theme header.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
),
|
||||||
|
'rendered' => array(
|
||||||
|
'description' => __( 'The theme name, transformed for display.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'requires_php' => array(
|
||||||
|
'description' => __( 'The minimum PHP version required for the theme to work.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'readonly' => true,
|
||||||
|
),
|
||||||
|
'requires_wp' => array(
|
||||||
|
'description' => __( 'The minimum WordPress version required for the theme to work.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'readonly' => true,
|
||||||
|
),
|
||||||
|
'screenshot' => array(
|
||||||
|
'description' => __( 'The theme\'s screenshot URL.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'format' => 'uri',
|
||||||
|
'readonly' => true,
|
||||||
|
),
|
||||||
|
'tags' => array(
|
||||||
|
'description' => __( 'Tags indicating styles and features of the theme.' ),
|
||||||
|
'type' => 'object',
|
||||||
|
'readonly' => true,
|
||||||
|
'properties' => array(
|
||||||
|
'raw' => array(
|
||||||
|
'description' => __( 'The theme tags, as found in the theme header.' ),
|
||||||
|
'type' => 'array',
|
||||||
|
'items' => array(
|
||||||
|
'type' => 'string',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'rendered' => array(
|
||||||
|
'description' => __( 'The theme tags, transformed for display.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'textdomain' => array(
|
||||||
|
'description' => __( 'The theme\'s textdomain.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'readonly' => true,
|
||||||
|
),
|
||||||
'theme_supports' => array(
|
'theme_supports' => array(
|
||||||
'description' => __( 'Features supported by this theme.' ),
|
'description' => __( 'Features supported by this theme.' ),
|
||||||
'type' => 'object',
|
'type' => 'object',
|
||||||
@ -458,6 +624,28 @@ class WP_REST_Themes_Controller extends WP_REST_Controller {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
'theme_uri' => array(
|
||||||
|
'description' => __( 'The URI of the theme\'s webpage.' ),
|
||||||
|
'type' => 'object',
|
||||||
|
'readonly' => true,
|
||||||
|
'properties' => array(
|
||||||
|
'raw' => array(
|
||||||
|
'description' => __( 'The URI of the theme\'s webpage, as found in the theme header.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'format' => 'uri',
|
||||||
|
),
|
||||||
|
'rendered' => array(
|
||||||
|
'description' => __( 'The URI of the theme\'s webpage, transformed for display.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'format' => 'uri',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'version' => array(
|
||||||
|
'description' => __( 'The theme\'s current version.' ),
|
||||||
|
'type' => 'string',
|
||||||
|
'readonly' => true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
15
tests/phpunit/data/themedir1/rest-api/style.css
Normal file
15
tests/phpunit/data/themedir1/rest-api/style.css
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
Theme Name: REST Theme
|
||||||
|
Theme URI: http://wordpress.org/?search=1&term=2
|
||||||
|
Description: The 9' foot tall theme.
|
||||||
|
Version: 1.6
|
||||||
|
Author: Michael Heilemann
|
||||||
|
Author URI: http://binarybonsai.com/?search=1&term=2
|
||||||
|
Tags: holiday, custom-menu
|
||||||
|
Template: default
|
||||||
|
Requires at least: 5.3
|
||||||
|
Requires PHP: 5.6
|
||||||
|
Text Domain: rest-api
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
@ -125,6 +125,7 @@ class WP_Test_REST_Themes_Controller extends WP_Test_REST_Controller_Testcase {
|
|||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
wp_set_current_user( self::$contributor_id );
|
wp_set_current_user( self::$contributor_id );
|
||||||
|
switch_theme( 'rest-api' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -150,7 +151,20 @@ class WP_Test_REST_Themes_Controller extends WP_Test_REST_Controller_Testcase {
|
|||||||
|
|
||||||
$this->check_get_theme_response( $response );
|
$this->check_get_theme_response( $response );
|
||||||
$fields = array(
|
$fields = array(
|
||||||
|
'author',
|
||||||
|
'author_uri',
|
||||||
|
'description',
|
||||||
|
'name',
|
||||||
|
'requires_php',
|
||||||
|
'requires_wp',
|
||||||
|
'screenshot',
|
||||||
|
'stylesheet',
|
||||||
|
'tags',
|
||||||
|
'template',
|
||||||
|
'textdomain',
|
||||||
'theme_supports',
|
'theme_supports',
|
||||||
|
'theme_uri',
|
||||||
|
'version',
|
||||||
);
|
);
|
||||||
$this->assertEqualSets( $fields, array_keys( $data[0] ) );
|
$this->assertEqualSets( $fields, array_keys( $data[0] ) );
|
||||||
}
|
}
|
||||||
@ -207,8 +221,44 @@ class WP_Test_REST_Themes_Controller extends WP_Test_REST_Controller_Testcase {
|
|||||||
$response = self::perform_active_theme_request( 'OPTIONS' );
|
$response = self::perform_active_theme_request( 'OPTIONS' );
|
||||||
$data = $response->get_data();
|
$data = $response->get_data();
|
||||||
$properties = $data['schema']['properties'];
|
$properties = $data['schema']['properties'];
|
||||||
$this->assertEquals( 1, count( $properties ) );
|
$this->assertEquals( 14, count( $properties ) );
|
||||||
|
|
||||||
|
$this->assertArrayHasKey( 'author', $properties );
|
||||||
|
$this->assertArrayHasKey( 'raw', $properties['author']['properties'] );
|
||||||
|
$this->assertArrayHasKey( 'rendered', $properties['author']['properties'] );
|
||||||
|
|
||||||
|
$this->assertArrayHasKey( 'author_uri', $properties );
|
||||||
|
$this->assertArrayHasKey( 'raw', $properties['author_uri']['properties'] );
|
||||||
|
$this->assertArrayHasKey( 'rendered', $properties['author_uri']['properties'] );
|
||||||
|
|
||||||
|
$this->assertArrayHasKey( 'description', $properties );
|
||||||
|
$this->assertArrayHasKey( 'raw', $properties['description']['properties'] );
|
||||||
|
$this->assertArrayHasKey( 'rendered', $properties['description']['properties'] );
|
||||||
|
|
||||||
|
$this->assertArrayHasKey( 'name', $properties );
|
||||||
|
$this->assertArrayHasKey( 'raw', $properties['name']['properties'] );
|
||||||
|
$this->assertArrayHasKey( 'rendered', $properties['name']['properties'] );
|
||||||
|
|
||||||
|
$this->assertArrayHasKey( 'requires_php', $properties );
|
||||||
|
$this->assertArrayHasKey( 'requires_wp', $properties );
|
||||||
|
$this->assertArrayHasKey( 'screenshot', $properties );
|
||||||
|
$this->assertArrayHasKey( 'stylesheet', $properties );
|
||||||
|
|
||||||
|
$this->assertArrayHasKey( 'tags', $properties );
|
||||||
|
$this->assertArrayHasKey( 'raw', $properties['tags']['properties'] );
|
||||||
|
$this->assertArrayHasKey( 'items', $properties['tags']['properties']['raw'] );
|
||||||
|
$this->assertArrayHasKey( 'rendered', $properties['tags']['properties'] );
|
||||||
|
|
||||||
|
$this->assertArrayHasKey( 'template', $properties );
|
||||||
|
$this->assertArrayHasKey( 'textdomain', $properties );
|
||||||
$this->assertArrayHasKey( 'theme_supports', $properties );
|
$this->assertArrayHasKey( 'theme_supports', $properties );
|
||||||
|
|
||||||
|
$this->assertArrayHasKey( 'theme_uri', $properties );
|
||||||
|
$this->assertArrayHasKey( 'raw', $properties['theme_uri']['properties'] );
|
||||||
|
$this->assertArrayHasKey( 'rendered', $properties['theme_uri']['properties'] );
|
||||||
|
|
||||||
|
$this->assertArrayHasKey( 'version', $properties );
|
||||||
|
|
||||||
$theme_supports = $properties['theme_supports']['properties'];
|
$theme_supports = $properties['theme_supports']['properties'];
|
||||||
$this->assertEquals( 20, count( $theme_supports ) );
|
$this->assertEquals( 20, count( $theme_supports ) );
|
||||||
$this->assertArrayHasKey( 'align-wide', $theme_supports );
|
$this->assertArrayHasKey( 'align-wide', $theme_supports );
|
||||||
@ -233,6 +283,148 @@ class WP_Test_REST_Themes_Controller extends WP_Test_REST_Controller_Testcase {
|
|||||||
$this->assertArrayHasKey( 'wp-block-styles', $theme_supports );
|
$this->assertArrayHasKey( 'wp-block-styles', $theme_supports );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 49906
|
||||||
|
*/
|
||||||
|
public function test_theme_author() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'author', $result[0] );
|
||||||
|
$this->assertSame( 'Michael Heilemann', $result[0]['author']['raw'] );
|
||||||
|
$this->assertSame(
|
||||||
|
'<a href="http://binarybonsai.com/?search=1&term=2">Michael Heilemann</a>',
|
||||||
|
$result[0]['author']['rendered']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 49906
|
||||||
|
*/
|
||||||
|
public function test_theme_author_uri() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'author_uri', $result[0] );
|
||||||
|
$this->assertSame( 'http://binarybonsai.com/?search=1&term=2', $result[0]['author_uri']['raw'] );
|
||||||
|
$this->assertSame( 'http://binarybonsai.com/?search=1&term=2', $result[0]['author_uri']['rendered'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 49906
|
||||||
|
*/
|
||||||
|
public function test_theme_description() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'description', $result[0] );
|
||||||
|
$this->assertSame(
|
||||||
|
'The 9\' foot tall theme.',
|
||||||
|
$result[0]['description']['raw']
|
||||||
|
);
|
||||||
|
$this->assertSame(
|
||||||
|
'The 9′ foot tall theme.',
|
||||||
|
$result[0]['description']['rendered']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 49906
|
||||||
|
*/
|
||||||
|
public function test_theme_requires_php() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'requires_php', $result[0] );
|
||||||
|
$this->assertSame( '5.6', $result[0]['requires_php'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 49906
|
||||||
|
*/
|
||||||
|
public function test_theme_requires_wp() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'requires_wp', $result[0] );
|
||||||
|
$this->assertSame( '5.3', $result[0]['requires_wp'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 49906
|
||||||
|
*/
|
||||||
|
public function test_theme_name() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'name', $result[0] );
|
||||||
|
$this->assertSame( 'REST Theme', $result[0]['name']['raw'] );
|
||||||
|
$this->assertSame( 'REST Theme', $result[0]['name']['rendered'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 49906
|
||||||
|
*/
|
||||||
|
public function test_theme_screenshot() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'screenshot', $result[0] );
|
||||||
|
$this->assertSame( '', $result[0]['screenshot'] ); // No screenshot for default theme
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 49906
|
||||||
|
*/
|
||||||
|
public function test_theme_stylesheet() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'stylesheet', $result[0] );
|
||||||
|
$this->assertSame( 'rest-api', $result[0]['stylesheet'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 49906
|
||||||
|
*/
|
||||||
|
public function test_theme_tags() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'tags', $result[0] );
|
||||||
|
$this->assertSame( array( 'holiday', 'custom-menu' ), $result[0]['tags']['raw'] );
|
||||||
|
$this->assertSame( 'holiday, custom-menu', $result[0]['tags']['rendered'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 49906
|
||||||
|
*/
|
||||||
|
public function test_theme_template() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'template', $result[0] );
|
||||||
|
$this->assertSame( 'default', $result[0]['template'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 49906
|
||||||
|
*/
|
||||||
|
public function test_theme_textdomain() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'textdomain', $result[0] );
|
||||||
|
$this->assertSame( 'rest-api', $result[0]['textdomain'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_theme_theme_uri() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'theme_uri', $result[0] );
|
||||||
|
$this->assertSame( 'http://wordpress.org/?search=1&term=2', $result[0]['theme_uri']['raw'] );
|
||||||
|
$this->assertSame( 'http://wordpress.org/?search=1&term=2', $result[0]['theme_uri']['rendered'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ticket 49906
|
||||||
|
*/
|
||||||
|
public function test_theme_version() {
|
||||||
|
$response = self::perform_active_theme_request();
|
||||||
|
$result = $response->get_data();
|
||||||
|
$this->assertArrayHasKey( 'version', $result[0] );
|
||||||
|
$this->assertSame( '1.6', $result[0]['version'] );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ticket 49037
|
* @ticket 49037
|
||||||
*/
|
*/
|
||||||
|
@ -163,6 +163,7 @@ class Tests_Theme_ThemeDir extends WP_UnitTestCase {
|
|||||||
'Theme with Spaces in the Directory',
|
'Theme with Spaces in the Directory',
|
||||||
'Internationalized Theme',
|
'Internationalized Theme',
|
||||||
'camelCase',
|
'camelCase',
|
||||||
|
'REST Theme',
|
||||||
);
|
);
|
||||||
|
|
||||||
sort( $theme_names );
|
sort( $theme_names );
|
||||||
|
Loading…
Reference in New Issue
Block a user