diff --git a/composer.json b/composer.json
index dd49d8b1..1740d150 100644
--- a/composer.json
+++ b/composer.json
@@ -1,39 +1,41 @@
{
- "name": "bigbite/themer",
- "description": "",
- "type": "wordpress-plugin",
- "version": "1.0.0",
- "repositories": [
- {
- "url": "git@github.com:bigbite/phpcs-config.git",
- "type": "vcs"
- }
- ],
- "require": {
- "automattic/jetpack-autoloader": "^2.10.1"
- },
- "require-dev": {
- "dealerdirect/phpcodesniffer-composer-installer": "0.7.2",
- "wp-coding-standards/wpcs": "2.3.0"
- },
- "autoload": {
- "files": [
- "inc/constants.php",
- "inc/utils.php",
- "inc/class-admin.php",
- "inc/setup.php"
- ],
- "psr-4": {
- "Big_Bite\\themer\\": "inc/"
- },
- "classmap": [ "inc/" ]
- },
- "scripts": {},
- "config": {
- "preferred-install": "dist",
- "allow-plugins": {
- "automattic/jetpack-autoloader": true,
- "dealerdirect/phpcodesniffer-composer-installer": true
- }
- }
- }
+ "name": "bigbite/themer",
+ "description": "",
+ "type": "wordpress-plugin",
+ "version": "1.0.0",
+ "repositories": [
+ {
+ "url": "git@github.com:bigbite/phpcs-config.git",
+ "type": "vcs"
+ }
+ ],
+ "require": {
+ "automattic/jetpack-autoloader": "^2.10.1"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "0.7.2",
+ "wp-coding-standards/wpcs": "3.1.0"
+ },
+ "autoload": {
+ "files": [
+ "inc/constants.php",
+ "inc/utils.php",
+ "inc/class-admin.php",
+ "inc/setup.php"
+ ],
+ "psr-4": {
+ "Big_Bite\\themer\\": "inc/"
+ },
+ "classmap": [
+ "inc/"
+ ]
+ },
+ "scripts": {},
+ "config": {
+ "preferred-install": "dist",
+ "allow-plugins": {
+ "automattic/jetpack-autoloader": true,
+ "dealerdirect/phpcodesniffer-composer-installer": true
+ }
+ }
+}
diff --git a/composer.lock b/composer.lock
index 7919f8f5..dabc20bf 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "f3b38fae00f385ffe87fe2b531179a7b",
+ "content-hash": "a3d2bb2e96d50660f0a136afb06b72b9",
"packages": [
{
"name": "automattic/jetpack-autoloader",
@@ -145,6 +145,172 @@
},
"time": "2022-02-04T12:51:07+00:00"
},
+ {
+ "name": "phpcsstandards/phpcsextra",
+ "version": "1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/PHPCSExtra.git",
+ "reference": "11d387c6642b6e4acaf0bd9bf5203b8cca1ec489"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/11d387c6642b6e4acaf0bd9bf5203b8cca1ec489",
+ "reference": "11d387c6642b6e4acaf0bd9bf5203b8cca1ec489",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4",
+ "phpcsstandards/phpcsutils": "^1.0.9",
+ "squizlabs/php_codesniffer": "^3.8.0"
+ },
+ "require-dev": {
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.3.2",
+ "phpcsstandards/phpcsdevcs": "^1.1.6",
+ "phpcsstandards/phpcsdevtools": "^1.2.1",
+ "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0"
+ },
+ "type": "phpcodesniffer-standard",
+ "extra": {
+ "branch-alias": {
+ "dev-stable": "1.x-dev",
+ "dev-develop": "1.x-dev"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Juliette Reinders Folmer",
+ "homepage": "https://github.com/jrfnl",
+ "role": "lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors"
+ }
+ ],
+ "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.",
+ "keywords": [
+ "PHP_CodeSniffer",
+ "phpcbf",
+ "phpcodesniffer-standard",
+ "phpcs",
+ "standards",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues",
+ "security": "https://github.com/PHPCSStandards/PHPCSExtra/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHPCSExtra"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ }
+ ],
+ "time": "2023-12-08T16:49:07+00:00"
+ },
+ {
+ "name": "phpcsstandards/phpcsutils",
+ "version": "1.0.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/PHPCSUtils.git",
+ "reference": "87b233b00daf83fb70f40c9a28692be017ea7c6c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/87b233b00daf83fb70f40c9a28692be017ea7c6c",
+ "reference": "87b233b00daf83fb70f40c9a28692be017ea7c6c",
+ "shasum": ""
+ },
+ "require": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0",
+ "php": ">=5.4",
+ "squizlabs/php_codesniffer": "^3.10.0 || 4.0.x-dev@dev"
+ },
+ "require-dev": {
+ "ext-filter": "*",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.3.2",
+ "phpcsstandards/phpcsdevcs": "^1.1.6",
+ "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0"
+ },
+ "type": "phpcodesniffer-standard",
+ "extra": {
+ "branch-alias": {
+ "dev-stable": "1.x-dev",
+ "dev-develop": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "PHPCSUtils/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Juliette Reinders Folmer",
+ "homepage": "https://github.com/jrfnl",
+ "role": "lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors"
+ }
+ ],
+ "description": "A suite of utility functions for use with PHP_CodeSniffer",
+ "homepage": "https://phpcsutils.com/",
+ "keywords": [
+ "PHP_CodeSniffer",
+ "phpcbf",
+ "phpcodesniffer-standard",
+ "phpcs",
+ "phpcs3",
+ "standards",
+ "static analysis",
+ "tokens",
+ "utility"
+ ],
+ "support": {
+ "docs": "https://phpcsutils.com/",
+ "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues",
+ "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHPCSUtils"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ }
+ ],
+ "time": "2024-05-20T13:34:27+00:00"
+ },
{
"name": "squizlabs/php_codesniffer",
"version": "3.10.1",
@@ -227,30 +393,38 @@
},
{
"name": "wp-coding-standards/wpcs",
- "version": "2.3.0",
+ "version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/WordPress/WordPress-Coding-Standards.git",
- "reference": "7da1894633f168fe244afc6de00d141f27517b62"
+ "reference": "9333efcbff231f10dfd9c56bb7b65818b4733ca7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62",
- "reference": "7da1894633f168fe244afc6de00d141f27517b62",
+ "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/9333efcbff231f10dfd9c56bb7b65818b4733ca7",
+ "reference": "9333efcbff231f10dfd9c56bb7b65818b4733ca7",
"shasum": ""
},
"require": {
+ "ext-filter": "*",
+ "ext-libxml": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlreader": "*",
"php": ">=5.4",
- "squizlabs/php_codesniffer": "^3.3.1"
+ "phpcsstandards/phpcsextra": "^1.2.1",
+ "phpcsstandards/phpcsutils": "^1.0.10",
+ "squizlabs/php_codesniffer": "^3.9.0"
},
"require-dev": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6",
+ "php-parallel-lint/php-console-highlighter": "^1.0.0",
+ "php-parallel-lint/php-parallel-lint": "^1.3.2",
"phpcompatibility/php-compatibility": "^9.0",
- "phpcsstandards/phpcsdevtools": "^1.0",
- "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
+ "phpcsstandards/phpcsdevtools": "^1.2.0",
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0"
},
"suggest": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically."
+ "ext-iconv": "For improved results",
+ "ext-mbstring": "For improved results"
},
"type": "phpcodesniffer-standard",
"notification-url": "https://packagist.org/downloads/",
@@ -267,6 +441,7 @@
"keywords": [
"phpcs",
"standards",
+ "static analysis",
"wordpress"
],
"support": {
@@ -274,15 +449,21 @@
"source": "https://github.com/WordPress/WordPress-Coding-Standards",
"wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki"
},
- "time": "2020-05-13T23:57:56+00:00"
+ "funding": [
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "custom"
+ }
+ ],
+ "time": "2024-03-25T16:39:00+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": [],
+ "stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
- "platform": [],
- "platform-dev": [],
- "plugin-api-version": "2.3.0"
+ "platform": {},
+ "platform-dev": {},
+ "plugin-api-version": "2.6.0"
}
diff --git a/inc/class-admin.php b/inc/class-admin.php
index 3c7267af..b4b96280 100644
--- a/inc/class-admin.php
+++ b/inc/class-admin.php
@@ -23,7 +23,7 @@ public function __construct() {
*
* @return void
*/
- public function enqueue_assets() : void {
+ public function enqueue_assets(): void {
$plugin_name = basename( THEMER_DIR );
$asset_file = include THEMER_DIR . '/build/index.asset.php';
@@ -51,7 +51,7 @@ public function enqueue_assets() : void {
*
* @return void
*/
- public function create_admin_screen() : void {
+ public function create_admin_screen(): void {
add_theme_page(
__( 'Styles Editor' ),
'Styles Editor',
diff --git a/inc/class-rest-api.php b/inc/class-rest-api.php
index 386c6b74..bb54bed0 100644
--- a/inc/class-rest-api.php
+++ b/inc/class-rest-api.php
@@ -44,6 +44,16 @@ public function register_routes() {
'themer/v1',
'/export',
array(
+ 'args' => array(
+ 'include' => array(
+ 'description' => __( 'Array of theme.json data types to be merged', 'mediapress' ),
+ 'type' => 'array',
+ 'items' => array(
+ 'type' => 'string',
+ 'enum' => array( 'core', 'block', 'theme', 'user' ),
+ ),
+ ),
+ ),
'methods' => 'GET',
'callback' => array( $this, 'get_theme_json' ),
'permission_callback' => fn() => is_user_logged_in() && current_user_can( 'edit_theme_options' ),
@@ -117,19 +127,41 @@ public function can_load_theme_json() {
/**
* Returns an updated theme.json with merged and flattened layers
*
- * @return WP_REST_Response|WP_Error
+ * @param WP_REST_Request $request The request object.
+ * @return WP_REST_Response|WP_Error The theme.json data or an error if it cannot be located.
*/
- public function get_theme_json(): WP_REST_Response|WP_Error {
- $all_theme_json_layers = WP_Theme_JSON_Resolver::get_merged_data();
+ public function get_theme_json( $request ): WP_REST_Response|WP_Error {
+ $include = $request->get_param( 'include' );
+ $include_core_data = in_array( 'core', $include, true );
+ $include_block_data = in_array( 'block', $include, true );
- if ( ! $all_theme_json_layers instanceof WP_Theme_JSON ) {
- return new WP_Error( 'no_theme_json', __( 'Unable to locate existing theme.json data', 'themer' ) );
+ $include_theme_data = in_array( 'theme', $include, true );
+
+ $include_user_data = in_array( 'user', $include, true );
+
+ $theme_json = new WP_Theme_JSON();
+
+ if ( $include_core_data ) {
+ $theme_json->merge( WP_Theme_JSON_Resolver::get_core_data() );
+ }
+
+ if ( $include_block_data ) {
+ $theme_json->merge( WP_Theme_JSON_Resolver::get_block_data() );
}
- $theme_json_raw_data = new WP_Theme_JSON( $all_theme_json_layers->get_raw_data() );
- $theme_json_flattened = $theme_json_raw_data->get_data();
+ if ( $include_theme_data ) {
+ $theme_json->merge( WP_Theme_JSON_Resolver::get_theme_data() );
+ }
+
+ if ( $include_user_data ) {
+ $theme_json->merge( WP_Theme_JSON_Resolver::get_user_data() );
+ }
+
+ if ( ! $theme_json instanceof WP_Theme_JSON ) {
+ return new WP_Error( 'no_theme_json', __( 'Unable to locate existing theme.json data', 'themer' ) );
+ }
- return rest_ensure_response( $theme_json_flattened );
+ return rest_ensure_response( $theme_json->get_data() );
}
/**
diff --git a/inc/constants.php b/inc/constants.php
index 54bc0ef9..82b5db70 100644
--- a/inc/constants.php
+++ b/inc/constants.php
@@ -8,5 +8,5 @@
namespace Big_Bite\themer;
if ( ! defined( 'THEMER_DIR' ) ) {
- define( 'THEMER_DIR', rtrim( \dirname( __FILE__, 2 ), '/' ) );
+ define( 'THEMER_DIR', rtrim( \dirname( __DIR__, 1 ), '/' ) );
}
diff --git a/inc/setup.php b/inc/setup.php
index 930b6a89..70ee8601 100644
--- a/inc/setup.php
+++ b/inc/setup.php
@@ -12,7 +12,7 @@
*
* @return void
*/
-function setup() : void {
+function setup(): void {
new Admin();
new Rest_API();
}
diff --git a/plugin.php b/plugin.php
index 44db5eba..bfd4ad3a 100644
--- a/plugin.php
+++ b/plugin.php
@@ -22,6 +22,6 @@
exit;
}
-require_once rtrim( \dirname( __FILE__ ) ) . '/vendor/autoload_packages.php';
+require_once rtrim( __DIR__ ) . '/vendor/autoload_packages.php';
add_action( 'plugins_loaded', __NAMESPACE__ . '\\setup', 0 );
diff --git a/src/editor/components/ButtonExport.js b/src/editor/components/ButtonExport.js
index 4e730338..b63d3809 100644
--- a/src/editor/components/ButtonExport.js
+++ b/src/editor/components/ButtonExport.js
@@ -1,8 +1,12 @@
import { __ } from '@wordpress/i18n';
-import apiFetch from '@wordpress/api-fetch';
import { MenuItem } from '@wordpress/components';
import { download } from '@wordpress/icons';
+import {
+ downloadThemeJSON,
+ downloadCustomisations,
+} from '../../utils/download-json';
+
/**
* Renders the button to export theme.json
*/
@@ -10,48 +14,32 @@ const ButtonExport = () => {
const isExportSupported =
window.isSecureContext && 'showSaveFilePicker' in window;
- /**
- * Fetch theme JSON object
- */
- const fetchThemeJSON = async () => {
- try {
- const response = await apiFetch( { path: '/themer/v1/export' } );
- saveThemeJSON( JSON.stringify( response, null, '\t' ) );
- } catch ( error ) {
- console.error( error ); // eslint-disable-line no-console -- Output of caught error
- }
- };
-
- /**
- * Save JSON blob to a file
- *
- * @param {Object} data theme.json data
- */
- const saveThemeJSON = async ( data ) => {
- const blob = new Blob( [ data ], { type: 'application/json' } ); // eslint-disable-line no-undef -- Blob available in browser environment
-
- const handle = await window.showSaveFilePicker( {
- suggestedName: 'theme.json',
- } );
- const stream = await handle.createWritable();
-
- await stream.write( blob );
- await stream.close();
- };
-
if ( ! isExportSupported ) {
return;
}
return (
-
+ <>
+
+
+ >
);
};
diff --git a/src/utils/download-json.js b/src/utils/download-json.js
new file mode 100644
index 00000000..8698ce8e
--- /dev/null
+++ b/src/utils/download-json.js
@@ -0,0 +1,33 @@
+import apiFetch from '@wordpress/api-fetch';
+
+import saveFile from './save-file';
+
+/**
+ * Fetch theme JSON object
+ */
+const downloadThemeJSON = async () => {
+ try {
+ const response = await apiFetch( {
+ path: '/themer/v1/export?include[]=block&include[]=theme&include[]=user',
+ } );
+ saveFile( 'theme.json', JSON.stringify( response, null, '\t' ) );
+ } catch ( error ) {
+ console.error( error ); // eslint-disable-line no-console -- Output of caught error
+ }
+};
+
+/**
+ * Fetch theme JSON object
+ */
+const downloadCustomisations = async () => {
+ try {
+ const response = await apiFetch( {
+ path: '/themer/v1/export?include[]=user',
+ } );
+ saveFile( 'style.json', JSON.stringify( response, null, '\t' ) );
+ } catch ( error ) {
+ console.error( error ); // eslint-disable-line no-console -- Output of caught error
+ }
+};
+
+export { downloadThemeJSON, downloadCustomisations };
diff --git a/src/utils/save-file.js b/src/utils/save-file.js
new file mode 100644
index 00000000..d1704418
--- /dev/null
+++ b/src/utils/save-file.js
@@ -0,0 +1,19 @@
+/**
+ * Save JSON blob to a file
+ *
+ * @param {string} filename filename
+ * @param {Object} data theme.json data
+ */
+const saveFile = async ( filename, data ) => {
+ const blob = new Blob( [ data ], { type: 'application/json' } ); // eslint-disable-line no-undef -- Blob available in browser environment
+
+ const handle = await window.showSaveFilePicker( {
+ suggestedName: filename,
+ } );
+ const stream = await handle.createWritable();
+
+ await stream.write( blob );
+ await stream.close();
+};
+
+export default saveFile;