diff --git a/gutenberg.php b/gutenberg.php index 3457ac3f6158a..a965592e1baf6 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -3,7 +3,7 @@ * Plugin Name: Gutenberg * Plugin URI: https://github.com/WordPress/gutenberg * Description: Printing since 1440. This is the development plugin for the new block editor in core. - * Requires at least: 5.8 + * Requires at least: 5.9 * Requires PHP: 5.6 * Version: 13.6.0-rc.1 * Author: Gutenberg Team @@ -26,7 +26,7 @@ function gutenberg_wordpress_version_notice() { echo '
'; /* translators: %s: Minimum required version */ - printf( __( 'Gutenberg requires WordPress %s or later to function properly. Please upgrade WordPress before activating Gutenberg.', 'gutenberg' ), '5.8' ); + printf( __( 'Gutenberg requires WordPress %s or later to function properly. Please upgrade WordPress before activating Gutenberg.', 'gutenberg' ), '5.9' ); echo '
- * $scope = '.a, .b .c';
- * $selector = '> .x, .y';
- * $merged = scope_selector( $scope, $selector );
- * // $merged is '.a > .x, .a .y, .b .c > .x, .b .c .y'
- *
- *
- * @param string $scope Selector to scope to.
- * @param string $selector Original selector.
- *
- * @return string Scoped selector.
- */
- protected static function scope_selector( $scope, $selector ) {
- $scopes = explode( ',', $scope );
- $selectors = explode( ',', $selector );
-
- $selectors_scoped = array();
- foreach ( $scopes as $outer ) {
- foreach ( $selectors as $inner ) {
- $selectors_scoped[] = trim( $outer ) . ' ' . trim( $inner );
- }
- }
-
- return implode( ', ', $selectors_scoped );
- }
-
- /**
- * Gets preset values keyed by slugs based on settings and metadata.
- *
- *
- * $settings = array(
- * 'typography' => array(
- * 'fontFamilies' => array(
- * array(
- * 'slug' => 'sansSerif',
- * 'fontFamily' => '"Helvetica Neue", sans-serif',
- * ),
- * array(
- * 'slug' => 'serif',
- * 'colors' => 'Georgia, serif',
- * )
- * ),
- * ),
- * );
- * $meta = array(
- * 'path' => array( 'typography', 'fontFamilies' ),
- * 'value_key' => 'fontFamily',
- * );
- * $values_by_slug = get_settings_values_by_slug();
- * // $values_by_slug === array(
- * // 'sans-serif' => '"Helvetica Neue", sans-serif',
- * // 'serif' => 'Georgia, serif',
- * // );
- *
- *
- * @param array $settings Settings to process.
- * @param array $preset_metadata One of the PRESETS_METADATA values.
- * @param array $origins List of origins to process.
- * @return array Array of presets where each key is a slug and each value is the preset value.
- */
- protected static function get_settings_values_by_slug( $settings, $preset_metadata, $origins ) {
- $preset_per_origin = _wp_array_get( $settings, $preset_metadata['path'], array() );
-
- $result = array();
- foreach ( $origins as $origin ) {
- if ( ! isset( $preset_per_origin[ $origin ] ) ) {
- continue;
- }
- foreach ( $preset_per_origin[ $origin ] as $preset ) {
- $slug = _wp_to_kebab_case( $preset['slug'] );
-
- $value = '';
- if ( isset( $preset_metadata['value_key'], $preset[ $preset_metadata['value_key'] ] ) ) {
- $value_key = $preset_metadata['value_key'];
- $value = $preset[ $value_key ];
- } elseif (
- isset( $preset_metadata['value_func'] ) &&
- is_callable( $preset_metadata['value_func'] )
- ) {
- $value_func = $preset_metadata['value_func'];
- $value = call_user_func( $value_func, $preset );
- } else {
- // If we don't have a value, then don't add it to the result.
- continue;
- }
-
- $result[ $slug ] = $value;
- }
- }
- return $result;
- }
-
- /**
- * Similar to get_settings_values_by_slug, but doesn't compute the value.
- *
- * @param array $settings Settings to process.
- * @param array $preset_metadata One of the PRESETS_METADATA values.
- * @param array $origins List of origins to process.
- * @return array Array of presets where the key and value are both the slug.
- */
- protected static function get_settings_slugs( $settings, $preset_metadata, $origins = null ) {
- if ( null === $origins ) {
- $origins = static::VALID_ORIGINS;
- }
-
- $preset_per_origin = _wp_array_get( $settings, $preset_metadata['path'], array() );
-
- $result = array();
- foreach ( $origins as $origin ) {
- if ( ! isset( $preset_per_origin[ $origin ] ) ) {
- continue;
- }
- foreach ( $preset_per_origin[ $origin ] as $preset ) {
- $slug = _wp_to_kebab_case( $preset['slug'] );
-
- // Use the array as a set so we don't get duplicates.
- $result[ $slug ] = $slug;
- }
- }
- return $result;
- }
-
- /**
- * Transform a slug into a CSS Custom Property.
- *
- * @param string $input String to replace.
- * @param string $slug The slug value to use to generate the custom property.
- * @return string The CSS Custom Property. Something along the lines of --wp--preset--color--black.
- */
- protected static function replace_slug_in_string( $input, $slug ) {
- return strtr( $input, array( '$slug' => $slug ) );
- }
-
- /**
- * Given the block settings, it extracts the CSS Custom Properties
- * for the presets and adds them to the $declarations array
- * following the format:
- *
- * ```php
- * array(
- * 'name' => 'property_name',
- * 'value' => 'property_value,
- * )
- * ```
- *
- * @param array $settings Settings to process.
- * @param array $origins List of origins to process.
- * @return array Returns the modified $declarations.
- */
- protected static function compute_preset_vars( $settings, $origins ) {
- $declarations = array();
- foreach ( static::PRESETS_METADATA as $preset_metadata ) {
- $values_by_slug = static::get_settings_values_by_slug( $settings, $preset_metadata, $origins );
- foreach ( $values_by_slug as $slug => $value ) {
- $declarations[] = array(
- 'name' => static::replace_slug_in_string( $preset_metadata['css_vars'], $slug ),
- 'value' => $value,
- );
- }
- }
-
- return $declarations;
- }
-
- /**
- * Given an array of settings, it extracts the CSS Custom Properties
- * for the custom values and adds them to the $declarations
- * array following the format:
- *
- * ```php
- * array(
- * 'name' => 'property_name',
- * 'value' => 'property_value,
- * )
- * ```
- *
- * @param array $settings Settings to process.
- * @return array Returns the modified $declarations.
- */
- protected static function compute_theme_vars( $settings ) {
- $declarations = array();
- $custom_values = _wp_array_get( $settings, array( 'custom' ), array() );
- $css_vars = static::flatten_tree( $custom_values );
- foreach ( $css_vars as $key => $value ) {
- $declarations[] = array(
- 'name' => '--wp--custom--' . $key,
- 'value' => $value,
- );
- }
-
- return $declarations;
- }
-
- /**
- * Given a tree, it creates a flattened one
- * by merging the keys and binding the leaf values
- * to the new keys.
- *
- * It also transforms camelCase names into kebab-case
- * and substitutes '/' by '-'.
- *
- * This is thought to be useful to generate
- * CSS Custom Properties from a tree,
- * although there's nothing in the implementation
- * of this function that requires that format.
- *
- * For example, assuming the given prefix is '--wp'
- * and the token is '--', for this input tree:
- *
- * {
- * 'some/property': 'value',
- * 'nestedProperty': {
- * 'sub-property': 'value'
- * }
- * }
- *
- * it'll return this output:
- *
- * {
- * '--wp--some-property': 'value',
- * '--wp--nested-property--sub-property': 'value'
- * }
- *
- * @param array $tree Input tree to process.
- * @param string $prefix Optional. Prefix to prepend to each variable. Default empty string.
- * @param string $token Optional. Token to use between levels. Default '--'.
- * @return array The flattened tree.
- */
- protected static function flatten_tree( $tree, $prefix = '', $token = '--' ) {
- $result = array();
- foreach ( $tree as $property => $value ) {
- $new_key = $prefix . str_replace(
- '/',
- '-',
- strtolower( _wp_to_kebab_case( $property ) )
- );
-
- if ( is_array( $value ) ) {
- $new_prefix = $new_key . $token;
- $result = array_merge(
- $result,
- static::flatten_tree( $value, $new_prefix, $token )
- );
- } else {
- $result[ $new_key ] = $value;
- }
- }
- return $result;
- }
-
- /**
- * Given a styles array, it extracts the style properties
- * and adds them to the $declarations array following the format:
- *
- * ```php
- * array(
- * 'name' => 'property_name',
- * 'value' => 'property_value,
- * )
- * ```
- *
- * @param array $styles Styles to process.
- * @param array $settings Theme settings.
- * @param array $properties Properties metadata.
- * @return array Returns the modified $declarations.
- */
- protected static function compute_style_properties( $styles, $settings = array(), $properties = null ) {
- if ( null === $properties ) {
- $properties = static::PROPERTIES_METADATA;
- }
-
- $declarations = array();
- if ( empty( $styles ) ) {
- return $declarations;
- }
-
- foreach ( $properties as $css_property => $value_path ) {
- $value = static::get_property_value( $styles, $value_path );
-
- // Look up protected properties, keyed by value path.
- // Skip protected properties that are explicitly set to `null`.
- if ( is_array( $value_path ) ) {
- $path_string = implode( '.', $value_path );
- if (
- array_key_exists( $path_string, static::PROTECTED_PROPERTIES ) &&
- _wp_array_get( $settings, static::PROTECTED_PROPERTIES[ $path_string ], null ) === null
- ) {
- continue;
- }
- }
-
- // Skip if empty and not "0" or value represents array of longhand values.
- $has_missing_value = empty( $value ) && ! is_numeric( $value );
- if ( $has_missing_value || is_array( $value ) ) {
- continue;
- }
-
- $declarations[] = array(
- 'name' => $css_property,
- 'value' => $value,
- );
- }
-
- return $declarations;
- }
-
- /**
- * Returns the style property for the given path.
- *
- * It also converts CSS Custom Property stored as
- * "var:preset|color|secondary" to the form
- * "--wp--preset--color--secondary".
- *
- * @param array $styles Styles subtree.
- * @param array $path Which property to process.
- * @return string Style property value.
- */
- protected static function get_property_value( $styles, $path ) {
- $value = _wp_array_get( $styles, $path, '' );
-
- if ( '' === $value || is_array( $value ) ) {
- return $value;
- }
-
- $prefix = 'var:';
- $prefix_len = strlen( $prefix );
- $token_in = '|';
- $token_out = '--';
- if ( 0 === strncmp( $value, $prefix, $prefix_len ) ) {
- $unwrapped_name = str_replace(
- $token_in,
- $token_out,
- substr( $value, $prefix_len )
- );
- $value = "var(--wp--$unwrapped_name)";
- }
-
- return $value;
- }
-
- /**
- * Builds metadata for the setting nodes, which returns in the form of:
- *
- * [
- * [
- * 'path' => ['path', 'to', 'some', 'node' ],
- * 'selector' => 'CSS selector for some node'
- * ],
- * [
- * 'path' => [ 'path', 'to', 'other', 'node' ],
- * 'selector' => 'CSS selector for other node'
- * ],
- * ]
- *
- * @param array $theme_json The tree to extract setting nodes from.
- * @param array $selectors List of selectors per block.
- * @return array
- */
- protected static function get_setting_nodes( $theme_json, $selectors = array() ) {
- $nodes = array();
- if ( ! isset( $theme_json['settings'] ) ) {
- return $nodes;
- }
-
- // Top-level.
- $nodes[] = array(
- 'path' => array( 'settings' ),
- 'selector' => static::ROOT_BLOCK_SELECTOR,
- );
-
- // Calculate paths for blocks.
- if ( ! isset( $theme_json['settings']['blocks'] ) ) {
- return $nodes;
- }
-
- foreach ( $theme_json['settings']['blocks'] as $name => $node ) {
- $selector = null;
- if ( isset( $selectors[ $name ]['selector'] ) ) {
- $selector = $selectors[ $name ]['selector'];
- }
-
- $nodes[] = array(
- 'path' => array( 'settings', 'blocks', $name ),
- 'selector' => $selector,
- );
- }
-
- return $nodes;
- }
-
- /**
- * Builds metadata for the style nodes, which returns in the form of:
- *
- * [
- * [
- * 'path' => [ 'path', 'to', 'some', 'node' ],
- * 'selector' => 'CSS selector for some node',
- * 'duotone' => 'CSS selector for duotone for some node'
- * ],
- * [
- * 'path' => ['path', 'to', 'other', 'node' ],
- * 'selector' => 'CSS selector for other node',
- * 'duotone' => null
- * ],
- * ]
- *
- * @param array $theme_json The tree to extract style nodes from.
- * @param array $selectors List of selectors per block.
- * @return array
- */
- protected static function get_style_nodes( $theme_json, $selectors = array() ) {
- $nodes = array();
- if ( ! isset( $theme_json['styles'] ) ) {
- return $nodes;
- }
-
- // Top-level.
- $nodes[] = array(
- 'path' => array( 'styles' ),
- 'selector' => static::ROOT_BLOCK_SELECTOR,
- );
-
- if ( isset( $theme_json['styles']['elements'] ) ) {
- foreach ( $theme_json['styles']['elements'] as $element => $node ) {
- $nodes[] = array(
- 'path' => array( 'styles', 'elements', $element ),
- 'selector' => static::ELEMENTS[ $element ],
- );
- }
- }
-
- // Blocks.
- if ( ! isset( $theme_json['styles']['blocks'] ) ) {
- return $nodes;
- }
-
- foreach ( $theme_json['styles']['blocks'] as $name => $node ) {
- $selector = null;
- if ( isset( $selectors[ $name ]['selector'] ) ) {
- $selector = $selectors[ $name ]['selector'];
- }
-
- $duotone_selector = null;
- if ( isset( $selectors[ $name ]['duotone'] ) ) {
- $duotone_selector = $selectors[ $name ]['duotone'];
- }
-
- $nodes[] = array(
- 'path' => array( 'styles', 'blocks', $name ),
- 'selector' => $selector,
- 'duotone' => $duotone_selector,
- );
-
- if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'] ) ) {
- foreach ( $theme_json['styles']['blocks'][ $name ]['elements'] as $element => $node ) {
- $nodes[] = array(
- 'path' => array( 'styles', 'blocks', $name, 'elements', $element ),
- 'selector' => $selectors[ $name ]['elements'][ $element ],
- );
- }
- }
- }
-
- return $nodes;
- }
-
- /**
- * Merge new incoming data.
- *
- * @param WP_Theme_JSON $incoming Data to merge.
- */
- public function merge( $incoming ) {
- $incoming_data = $incoming->get_raw_data();
- $this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data );
-
- /*
- * The array_replace_recursive algorithm merges at the leaf level,
- * but we don't want leaf arrays to be merged, so we overwrite it.
- *
- * For leaf values that are sequential arrays it will use the numeric indexes for replacement.
- * We rather replace the existing with the incoming value, if it exists.
- * This is the case of spacing.units.
- *
- * For leaf values that are associative arrays it will merge them as expected.
- * This is also not the behavior we want for the current associative arrays (presets).
- * We rather replace the existing with the incoming value, if it exists.
- * This happens, for example, when we merge data from theme.json upon existing
- * theme supports or when we merge anything coming from the same source twice.
- * This is the case of color.palette, color.gradients, color.duotone,
- * typography.fontSizes, or typography.fontFamilies.
- *
- * Additionally, for some preset types, we also want to make sure the
- * values they introduce don't conflict with default values. We do so
- * by checking the incoming slugs for theme presets and compare them
- * with the equivalent default presets: if a slug is present as a default
- * we remove it from the theme presets.
- */
- $nodes = static::get_setting_nodes( $incoming_data );
- $slugs_global = static::get_default_slugs( $this->theme_json, array( 'settings' ) );
- foreach ( $nodes as $node ) {
- $slugs_node = static::get_default_slugs( $this->theme_json, $node['path'] );
- $slugs = array_merge_recursive( $slugs_global, $slugs_node );
-
- // Replace the spacing.units.
- $path = array_merge( $node['path'], array( 'spacing', 'units' ) );
- $content = _wp_array_get( $incoming_data, $path, null );
- if ( isset( $content ) ) {
- _wp_array_set( $this->theme_json, $path, $content );
- }
-
- // Replace the presets.
- foreach ( static::PRESETS_METADATA as $preset ) {
- $override_preset = static::should_override_preset( $this->theme_json, $node['path'], $preset['override'] );
-
- foreach ( static::VALID_ORIGINS as $origin ) {
- $base_path = array_merge( $node['path'], $preset['path'] );
- $path = array_merge( $base_path, array( $origin ) );
- $content = _wp_array_get( $incoming_data, $path, null );
- if ( ! isset( $content ) ) {
- continue;
- }
-
- if ( 'theme' === $origin && $preset['use_default_names'] ) {
- foreach ( $content as &$item ) {
- if ( ! array_key_exists( 'name', $item ) ) {
- $name = static::get_name_from_defaults( $item['slug'], $base_path );
- if ( null !== $name ) {
- $item['name'] = $name;
- }
- }
- }
- }
-
- if (
- ( 'theme' !== $origin ) ||
- ( 'theme' === $origin && $override_preset )
- ) {
- _wp_array_set( $this->theme_json, $path, $content );
- } else {
- $slugs_for_preset = _wp_array_get( $slugs, $preset['path'], array() );
- $content = static::filter_slugs( $content, $slugs_for_preset );
- _wp_array_set( $this->theme_json, $path, $content );
- }
- }
- }
- }
- }
-
- /**
- * Converts all filter (duotone) presets into SVGs.
- *
- * @param array $origins List of origins to process.
- *
- * @return string SVG filters.
- */
- public function get_svg_filters( $origins ) {
- $blocks_metadata = static::get_blocks_metadata();
- $setting_nodes = static::get_setting_nodes( $this->theme_json, $blocks_metadata );
-
- $filters = '';
- foreach ( $setting_nodes as $metadata ) {
- $node = _wp_array_get( $this->theme_json, $metadata['path'], array() );
- if ( empty( $node['color']['duotone'] ) ) {
- continue;
- }
-
- $duotone_presets = $node['color']['duotone'];
-
- foreach ( $origins as $origin ) {
- if ( ! isset( $duotone_presets[ $origin ] ) ) {
- continue;
- }
- foreach ( $duotone_presets[ $origin ] as $duotone_preset ) {
- $filters .= gutenberg_get_duotone_filter_svg( $duotone_preset );
- }
- }
- }
-
- return $filters;
- }
-
- /**
- * Returns whether a presets should be overriden or not.
- *
- * @param array $theme_json The theme.json like structure to inspect.
- * @param array $path Path to inspect.
- * @param bool|array $override Data to compute whether to override the preset.
- * @return boolean
- */
- protected static function should_override_preset( $theme_json, $path, $override ) {
- if ( is_bool( $override ) ) {
- return $override;
- }
-
- // The relationship between whether to override the defaults
- // and whether the defaults are enabled is inverse:
- //
- // - If defaults are enabled => theme presets should not be overriden
- // - If defaults are disabled => theme presets should be overriden
- //
- // For example, a theme sets defaultPalette to false,
- // making the default palette hidden from the user.
- // In that case, we want all the theme presets to be present,
- // so they should override the defaults.
- if ( is_array( $override ) ) {
- $value = _wp_array_get( $theme_json, array_merge( $path, $override ) );
- if ( isset( $value ) ) {
- return ! $value;
- }
-
- // Search the top-level key if none was found for this node.
- $value = _wp_array_get( $theme_json, array_merge( array( 'settings' ), $override ) );
- if ( isset( $value ) ) {
- return ! $value;
- }
-
- return true;
- }
- }
-
- /**
- * Returns the default slugs for all the presets in an associative array
- * whose keys are the preset paths and the leafs is the list of slugs.
- *
- * For example:
- *
- * array(
- * 'color' => array(
- * 'palette' => array( 'slug-1', 'slug-2' ),
- * 'gradients' => array( 'slug-3', 'slug-4' ),
- * ),
- * )
- *
- * @param array $data A theme.json like structure.
- * @param array $node_path The path to inspect. It's 'settings' by default.
- *
- * @return array
- */
- protected static function get_default_slugs( $data, $node_path ) {
- $slugs = array();
-
- foreach ( static::PRESETS_METADATA as $metadata ) {
- $path = array_merge( $node_path, $metadata['path'], array( 'default' ) );
- $preset = _wp_array_get( $data, $path, null );
- if ( ! isset( $preset ) ) {
- continue;
- }
-
- $slugs_for_preset = array();
- $slugs_for_preset = array_map(
- function( $value ) {
- return isset( $value['slug'] ) ? $value['slug'] : null;
- },
- $preset
- );
- _wp_array_set( $slugs, $metadata['path'], $slugs_for_preset );
- }
-
- return $slugs;
- }
-
- /**
- * Get a `default`'s preset name by a provided slug.
- *
- * @param string $slug The slug we want to find a match from default presets.
- * @param array $base_path The path to inspect. It's 'settings' by default.
- *
- * @return string|null
- */
- protected function get_name_from_defaults( $slug, $base_path ) {
- $path = array_merge( $base_path, array( 'default' ) );
- $default_content = _wp_array_get( $this->theme_json, $path, null );
- if ( ! $default_content ) {
- return null;
- }
- foreach ( $default_content as $item ) {
- if ( $slug === $item['slug'] ) {
- return $item['name'];
- }
- }
- return null;
- }
-
- /**
- * Removes the preset values whose slug is equal to any of given slugs.
- *
- * @param array $node The node with the presets to validate.
- * @param array $slugs The slugs that should not be overriden.
- *
- * @return array The new node
- */
- protected static function filter_slugs( $node, $slugs ) {
- if ( empty( $slugs ) ) {
- return $node;
- }
-
- $new_node = array();
- foreach ( $node as $value ) {
- if ( isset( $value['slug'] ) && ! in_array( $value['slug'], $slugs, true ) ) {
- $new_node[] = $value;
- }
- }
-
- return $new_node;
- }
-
- /**
- * Removes insecure data from theme.json.
- *
- * @param array $theme_json Structure to sanitize.
- * @return array Sanitized structure.
- */
- public static function remove_insecure_properties( $theme_json ) {
- $sanitized = array();
-
- $theme_json = WP_Theme_JSON_Schema_Gutenberg::migrate( $theme_json );
-
- $valid_block_names = array_keys( static::get_blocks_metadata() );
- $valid_element_names = array_keys( static::ELEMENTS );
- $theme_json = static::sanitize( $theme_json, $valid_block_names, $valid_element_names );
-
- $blocks_metadata = static::get_blocks_metadata();
- $style_nodes = static::get_style_nodes( $theme_json, $blocks_metadata );
- foreach ( $style_nodes as $metadata ) {
- $input = _wp_array_get( $theme_json, $metadata['path'], array() );
- if ( empty( $input ) ) {
- continue;
- }
-
- $output = static::remove_insecure_styles( $input );
- if ( ! empty( $output ) ) {
- _wp_array_set( $sanitized, $metadata['path'], $output );
- }
- }
-
- $setting_nodes = static::get_setting_nodes( $theme_json );
- foreach ( $setting_nodes as $metadata ) {
- $input = _wp_array_get( $theme_json, $metadata['path'], array() );
- if ( empty( $input ) ) {
- continue;
- }
-
- $output = static::remove_insecure_settings( $input );
- if ( ! empty( $output ) ) {
- _wp_array_set( $sanitized, $metadata['path'], $output );
- }
- }
-
- if ( empty( $sanitized['styles'] ) ) {
- unset( $theme_json['styles'] );
- } else {
- $theme_json['styles'] = $sanitized['styles'];
- }
-
- if ( empty( $sanitized['settings'] ) ) {
- unset( $theme_json['settings'] );
- } else {
- $theme_json['settings'] = $sanitized['settings'];
- }
-
- return $theme_json;
- }
-
- /**
- * Processes a setting node and returns the same node
- * without the insecure settings.
- *
- * @param array $input Node to process.
- * @return array
- */
- protected static function remove_insecure_settings( $input ) {
- $output = array();
- foreach ( static::PRESETS_METADATA as $preset_metadata ) {
- foreach ( static::VALID_ORIGINS as $origin ) {
- $path_with_origin = array_merge( $preset_metadata['path'], array( $origin ) );
- $presets = _wp_array_get( $input, $path_with_origin, null );
- if ( null === $presets ) {
- continue;
- }
-
- $escaped_preset = array();
- foreach ( $presets as $preset ) {
- if (
- esc_attr( esc_html( $preset['name'] ) ) === $preset['name'] &&
- sanitize_html_class( $preset['slug'] ) === $preset['slug']
- ) {
- $value = null;
- if ( isset( $preset_metadata['value_key'], $preset[ $preset_metadata['value_key'] ] ) ) {
- $value = $preset[ $preset_metadata['value_key'] ];
- } elseif (
- isset( $preset_metadata['value_func'] ) &&
- is_callable( $preset_metadata['value_func'] )
- ) {
- $value = call_user_func( $preset_metadata['value_func'], $preset );
- }
-
- $preset_is_valid = true;
- foreach ( $preset_metadata['properties'] as $property ) {
- if ( ! static::is_safe_css_declaration( $property, $value ) ) {
- $preset_is_valid = false;
- break;
- }
- }
-
- if ( $preset_is_valid ) {
- $escaped_preset[] = $preset;
- }
- }
- }
-
- if ( ! empty( $escaped_preset ) ) {
- _wp_array_set( $output, $path_with_origin, $escaped_preset );
- }
- }
- }
- return $output;
- }
-
- /**
- * Processes a style node and returns the same node
- * without the insecure styles.
- *
- * @param array $input Node to process.
- * @return array
- */
- protected static function remove_insecure_styles( $input ) {
- $output = array();
- $declarations = static::compute_style_properties( $input );
-
- foreach ( $declarations as $declaration ) {
- if ( static::is_safe_css_declaration( $declaration['name'], $declaration['value'] ) ) {
- $path = static::PROPERTIES_METADATA[ $declaration['name'] ];
-
- // Check the value isn't an array before adding so as to not
- // double up shorthand and longhand styles.
- $value = _wp_array_get( $input, $path, array() );
- if ( ! is_array( $value ) ) {
- _wp_array_set( $output, $path, $value );
- }
- }
- }
- return $output;
- }
-
- /**
- * Checks that a declaration provided by the user is safe.
- *
- * @param string $property_name Property name in a CSS declaration, i.e. the `color` in `color: red`.
- * @param string $property_value Value in a CSS declaration, i.e. the `red` in `color: red`.
- * @return boolean
- */
- protected static function is_safe_css_declaration( $property_name, $property_value ) {
- $style_to_validate = $property_name . ': ' . $property_value;
- $filtered = esc_html( safecss_filter_attr( $style_to_validate ) );
- return ! empty( trim( $filtered ) );
- }
-
- /**
- * Returns the raw data.
- *
- * @return array Raw data.
- */
- public function get_raw_data() {
- return $this->theme_json;
- }
-
- /**
- * Transforms the given editor settings according the
- * add_theme_support format to the theme.json format.
- *
- * @param array $settings Existing editor settings.
- * @return array Config that adheres to the theme.json schema.
- */
- public static function get_from_editor_settings( $settings ) {
- $theme_settings = array(
- 'version' => static::LATEST_SCHEMA,
- 'settings' => array(),
- );
-
- // Deprecated theme supports.
- if ( isset( $settings['disableCustomColors'] ) ) {
- if ( ! isset( $theme_settings['settings']['color'] ) ) {
- $theme_settings['settings']['color'] = array();
- }
- $theme_settings['settings']['color']['custom'] = ! $settings['disableCustomColors'];
- }
-
- if ( isset( $settings['disableCustomGradients'] ) ) {
- if ( ! isset( $theme_settings['settings']['color'] ) ) {
- $theme_settings['settings']['color'] = array();
- }
- $theme_settings['settings']['color']['customGradient'] = ! $settings['disableCustomGradients'];
- }
-
- if ( isset( $settings['disableCustomFontSizes'] ) ) {
- if ( ! isset( $theme_settings['settings']['typography'] ) ) {
- $theme_settings['settings']['typography'] = array();
- }
- $theme_settings['settings']['typography']['customFontSize'] = ! $settings['disableCustomFontSizes'];
- }
-
- if ( isset( $settings['enableCustomLineHeight'] ) ) {
- if ( ! isset( $theme_settings['settings']['typography'] ) ) {
- $theme_settings['settings']['typography'] = array();
- }
- $theme_settings['settings']['typography']['lineHeight'] = $settings['enableCustomLineHeight'];
- }
-
- if ( isset( $settings['enableCustomUnits'] ) ) {
- if ( ! isset( $theme_settings['settings']['spacing'] ) ) {
- $theme_settings['settings']['spacing'] = array();
- }
- $theme_settings['settings']['spacing']['units'] = ( true === $settings['enableCustomUnits'] ) ?
- array( 'px', 'em', 'rem', 'vh', 'vw', '%' ) :
- $settings['enableCustomUnits'];
- }
-
- if ( isset( $settings['colors'] ) ) {
- if ( ! isset( $theme_settings['settings']['color'] ) ) {
- $theme_settings['settings']['color'] = array();
- }
- $theme_settings['settings']['color']['palette'] = $settings['colors'];
- }
-
- if ( isset( $settings['gradients'] ) ) {
- if ( ! isset( $theme_settings['settings']['color'] ) ) {
- $theme_settings['settings']['color'] = array();
- }
- $theme_settings['settings']['color']['gradients'] = $settings['gradients'];
- }
-
- if ( isset( $settings['fontSizes'] ) ) {
- $font_sizes = $settings['fontSizes'];
- // Back-compatibility for presets without units.
- foreach ( $font_sizes as $key => $font_size ) {
- if ( is_numeric( $font_size['size'] ) ) {
- $font_sizes[ $key ]['size'] = $font_size['size'] . 'px';
- }
- }
- if ( ! isset( $theme_settings['settings']['typography'] ) ) {
- $theme_settings['settings']['typography'] = array();
- }
- $theme_settings['settings']['typography']['fontSizes'] = $font_sizes;
- }
-
- // This allows to make the plugin work with WordPress 5.7 beta
- // as well as lower versions. The second check can be removed
- // as soon as the minimum WordPress version for the plugin
- // is bumped to 5.7.
- if ( isset( $settings['enableCustomSpacing'] ) ) {
- if ( ! isset( $theme_settings['settings']['spacing'] ) ) {
- $theme_settings['settings']['spacing'] = array();
- }
- $theme_settings['settings']['spacing']['padding'] = $settings['enableCustomSpacing'];
- }
-
- // Things that didn't land in core yet, so didn't have a setting assigned.
- // This should be removed when the plugin minimum WordPress version
- // is bumped to 5.9.
- //
- // Since WordPress 5.9, the CSS Custom Properties are enqueued for all themes,
- // so we no longer need to detect theme support for this.
- // Removing this code will have the effect of making link color
- // not visible for classic themes that opted-in and depended on the plugin
- // to show the UI control for link color to users.
- //
- // Do not port this to WordPress core.
- if ( current( (array) get_theme_support( 'experimental-link-color' ) ) ) {
- if ( ! isset( $theme_settings['settings']['color'] ) ) {
- $theme_settings['settings']['color'] = array();
- }
- $theme_settings['settings']['color']['link'] = true;
- }
-
- return $theme_settings;
- }
-
-}
diff --git a/lib/compat/wordpress-5.9/class-wp-theme-json-resolver-5-9.php b/lib/compat/wordpress-5.9/class-wp-theme-json-resolver-5-9.php
deleted file mode 100644
index b00c6e708c763..0000000000000
--- a/lib/compat/wordpress-5.9/class-wp-theme-json-resolver-5-9.php
+++ /dev/null
@@ -1,416 +0,0 @@
- true ) );
- if ( is_array( $decoded_file ) ) {
- $config = $decoded_file;
- }
- }
- return $config;
- }
-
- /**
- * Returns a data structure used in theme.json translation.
- *
- * @deprecated
- * @return array An array of theme.json fields that are translatable and the keys that are translatable
- */
- public static function get_fields_to_translate() {
- _deprecated_function( __METHOD__, '5.9.0' );
- return array();
- }
-
- /**
- * Given a theme.json structure modifies it in place
- * to update certain values by its translated strings
- * according to the language set by the user.
- *
- * @param array $theme_json The theme.json to translate.
- * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
- * Default 'default'.
- * @return array Returns the modified $theme_json_structure.
- */
- protected static function translate( $theme_json, $domain = 'default' ) {
- if ( null === static::$i18n_schema ) {
- $i18n_schema = wp_json_file_decode( __DIR__ . '/theme-i18n.json' );
- static::$i18n_schema = null === $i18n_schema ? array() : $i18n_schema;
- }
-
- return translate_settings_using_i18n_schema( static::$i18n_schema, $theme_json, $domain );
- }
-
- /**
- * Return core's origin config.
- *
- * @return WP_Theme_JSON_Gutenberg Entity that holds core data.
- */
- public static function get_core_data() {
- if ( null !== static::$core ) {
- return static::$core;
- }
-
- $config = static::read_json_file( __DIR__ . '/theme.json' );
- $config = static::translate( $config );
- static::$core = new WP_Theme_JSON_Gutenberg( $config, 'default' );
-
- return static::$core;
- }
-
- /**
- * Returns the theme's data.
- *
- * Data from theme.json will be backfilled from existing
- * theme supports, if any. Note that if the same data
- * is present in theme.json and in theme supports,
- * the theme.json takes precedence.
- *
- * @param array $deprecated Deprecated argument.
- * @return WP_Theme_JSON_Gutenberg Entity that holds theme data.
- */
- public static function get_theme_data( $deprecated = array() ) {
- if ( ! empty( $deprecated ) ) {
- _deprecated_argument( __METHOD__, '5.9' );
- }
- if ( null === static::$theme ) {
- $theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) );
- $theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) );
- static::$theme = new WP_Theme_JSON_Gutenberg( $theme_json_data );
-
- if ( wp_get_theme()->parent() ) {
- // Get parent theme.json.
- $parent_theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json', true ) );
- $parent_theme_json_data = static::translate( $parent_theme_json_data, wp_get_theme()->parent()->get( 'TextDomain' ) );
- $parent_theme = new WP_Theme_JSON_Gutenberg( $parent_theme_json_data );
-
- // Merge the child theme.json into the parent theme.json.
- // The child theme takes precedence over the parent.
- $parent_theme->merge( static::$theme );
- static::$theme = $parent_theme;
- }
- }
-
- /*
- * We want the presets and settings declared in theme.json
- * to override the ones declared via theme supports.
- * So we take theme supports, transform it to theme.json shape
- * and merge the static::$theme upon that.
- */
- $theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_default_block_editor_settings() );
- if ( ! static::theme_has_support() ) {
- if ( ! isset( $theme_support_data['settings']['color'] ) ) {
- $theme_support_data['settings']['color'] = array();
- }
-
- $default_palette = false;
- if ( current_theme_supports( 'default-color-palette' ) ) {
- $default_palette = true;
- }
- if ( ! isset( $theme_support_data['settings']['color']['palette'] ) ) {
- // If the theme does not have any palette, we still want to show the core one.
- $default_palette = true;
- }
- $theme_support_data['settings']['color']['defaultPalette'] = $default_palette;
-
- $default_gradients = false;
- if ( current_theme_supports( 'default-gradient-presets' ) ) {
- $default_gradients = true;
- }
- if ( ! isset( $theme_support_data['settings']['color']['gradients'] ) ) {
- // If the theme does not have any gradients, we still want to show the core ones.
- $default_gradients = true;
- }
- $theme_support_data['settings']['color']['defaultGradients'] = $default_gradients;
- }
- $with_theme_supports = new WP_Theme_JSON_Gutenberg( $theme_support_data );
- $with_theme_supports->merge( static::$theme );
-
- return $with_theme_supports;
- }
-
- /**
- * Returns the custom post type that contains the user's origin config
- * for the current theme or a void array if none are found.
- *
- * This can also create and return a new draft custom post type.
- *
- * @param WP_Theme $theme The theme object. If empty, it
- * defaults to the current theme.
- * @param bool $create_post Optional. Whether a new custom post
- * type should be created if none are
- * found. False by default.
- * @param array $post_status_filter Filter Optional. custom post type by
- * post status. ['publish'] by default,
- * so it only fetches published posts.
- * @return array Custom Post Type for the user's origin config.
- */
- public static function get_user_data_from_wp_global_styles( $theme, $create_post = false, $post_status_filter = array( 'publish' ) ) {
- if ( ! $theme instanceof WP_Theme ) {
- $theme = wp_get_theme();
- }
- $user_cpt = array();
- $post_type_filter = 'wp_global_styles';
- $args = array(
- 'numberposts' => 1,
- 'orderby' => 'date',
- 'order' => 'desc',
- 'post_type' => $post_type_filter,
- 'post_status' => $post_status_filter,
- 'tax_query' => array(
- array(
- 'taxonomy' => 'wp_theme',
- 'field' => 'name',
- 'terms' => $theme->get_stylesheet(),
- ),
- ),
- );
-
- $cache_key = sprintf( 'wp_global_styles_%s', md5( serialize( $args ) ) );
- $post_id = wp_cache_get( $cache_key );
-
- if ( (int) $post_id > 0 ) {
- return get_post( $post_id, ARRAY_A );
- }
-
- // Special case: '-1' is a results not found.
- if ( -1 === $post_id && ! $create_post ) {
- return $user_cpt;
- }
-
- $recent_posts = wp_get_recent_posts( $args );
- if ( is_array( $recent_posts ) && ( count( $recent_posts ) === 1 ) ) {
- $user_cpt = $recent_posts[0];
- } elseif ( $create_post ) {
- $cpt_post_id = wp_insert_post(
- array(
- 'post_content' => '{"version": ' . WP_Theme_JSON_Gutenberg::LATEST_SCHEMA . ', "isGlobalStylesUserThemeJSON": true }',
- 'post_status' => 'publish',
- 'post_title' => __( 'Custom Styles', 'default' ),
- 'post_type' => $post_type_filter,
- 'post_name' => 'wp-global-styles-' . urlencode( wp_get_theme()->get_stylesheet() ),
- 'tax_input' => array(
- 'wp_theme' => array( wp_get_theme()->get_stylesheet() ),
- ),
- ),
- true
- );
- $user_cpt = get_post( $cpt_post_id, ARRAY_A );
- }
- $cache_expiration = $user_cpt ? DAY_IN_SECONDS : HOUR_IN_SECONDS;
- wp_cache_set( $cache_key, $user_cpt ? $user_cpt['ID'] : -1, '', $cache_expiration );
-
- return $user_cpt;
- }
-
- /**
- * Returns the user's origin config.
- *
- * @return WP_Theme_JSON_Gutenberg Entity that holds styles for user data.
- */
- public static function get_user_data() {
- if ( null !== static::$user ) {
- return static::$user;
- }
-
- $config = array();
- $user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme() );
-
- if ( array_key_exists( 'post_content', $user_cpt ) ) {
- $decoded_data = json_decode( $user_cpt['post_content'], true );
-
- $json_decoding_error = json_last_error();
- if ( JSON_ERROR_NONE !== $json_decoding_error ) {
- trigger_error( 'Error when decoding a theme.json schema for user data. ' . json_last_error_msg() );
- return new WP_Theme_JSON_Gutenberg( $config, 'custom' );
- }
-
- // Very important to verify if the flag isGlobalStylesUserThemeJSON is true.
- // If is not true the content was not escaped and is not safe.
- if (
- is_array( $decoded_data ) &&
- isset( $decoded_data['isGlobalStylesUserThemeJSON'] ) &&
- $decoded_data['isGlobalStylesUserThemeJSON']
- ) {
- unset( $decoded_data['isGlobalStylesUserThemeJSON'] );
- $config = $decoded_data;
- }
- }
- static::$user = new WP_Theme_JSON_Gutenberg( $config, 'custom' );
-
- return static::$user;
- }
-
- /**
- * There are three sources of data (origins) for a site:
- * default, theme, and custom. The custom's has higher priority
- * than the theme's, and the theme's higher than defaults's.
- *
- * Unlike the getters {@link get_core_data},
- * {@link get_theme_data}, and {@link get_user_data},
- * this method returns data after it has been merged
- * with the previous origins. This means that if the same piece of data
- * is declared in different origins (user, theme, and core),
- * the last origin overrides the previous.
- *
- * For example, if the user has set a background color
- * for the paragraph block, and the theme has done it as well,
- * the user preference wins.
- *
- * @param string $origin Optional. To what level should we merge data.
- * Valid values are 'theme' or 'custom'.
- * Default is 'custom'.
- * @return WP_Theme_JSON_Gutenberg
- */
- public static function get_merged_data( $origin = 'custom' ) {
- if ( is_array( $origin ) ) {
- _deprecated_argument( __FUNCTION__, '5.9' );
- }
-
- $result = new WP_Theme_JSON_Gutenberg();
- $result->merge( static::get_core_data() );
- $result->merge( static::get_theme_data() );
-
- if ( 'custom' === $origin ) {
- $result->merge( static::get_user_data() );
- }
-
- return $result;
- }
-
- /**
- * Returns the ID of the custom post type
- * that stores user data.
- *
- * @return integer|null
- */
- public static function get_user_global_styles_post_id() {
- if ( null !== static::$user_custom_post_type_id ) {
- return static::$user_custom_post_type_id;
- }
-
- $user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme(), true );
-
- if ( array_key_exists( 'ID', $user_cpt ) ) {
- static::$user_custom_post_type_id = $user_cpt['ID'];
- }
-
- return static::$user_custom_post_type_id;
- }
-
- /**
- * Whether the current theme has a theme.json file.
- *
- * @return bool
- */
- public static function theme_has_support() {
- if ( ! isset( static::$theme_has_support ) ) {
- static::$theme_has_support = (
- is_readable( static::get_file_path_from_theme( 'theme.json' ) ) ||
- is_readable( static::get_file_path_from_theme( 'theme.json', true ) )
- );
- }
-
- return static::$theme_has_support;
- }
-
- /**
- * Builds the path to the given file and checks that it is readable.
- *
- * If it isn't, returns an empty string, otherwise returns the whole file path.
- *
- * @param string $file_name Name of the file.
- * @param bool $template Optional. Use template theme directory. Default false.
- * @return string The whole file path or empty if the file doesn't exist.
- */
- protected static function get_file_path_from_theme( $file_name, $template = false ) {
- $path = $template ? get_template_directory() : get_stylesheet_directory();
- $candidate = $path . '/' . $file_name;
-
- return is_readable( $candidate ) ? $candidate : '';
- }
-
- /**
- * Cleans the cached data so it can be recalculated.
- */
- public static function clean_cached_data() {
- static::$core = null;
- static::$theme = null;
- static::$user = null;
- static::$user_custom_post_type_id = null;
- static::$theme_has_support = null;
- static::$i18n_schema = null;
- }
-
-}
-
-add_action( 'switch_theme', array( 'WP_Theme_JSON_Resolver_Gutenberg', 'clean_cached_data' ) );
-add_action( 'start_previewing_theme', array( 'WP_Theme_JSON_Resolver_Gutenberg', 'clean_cached_data' ) );
diff --git a/lib/compat/wordpress-5.9/class-wp-theme-json-schema-gutenberg.php b/lib/compat/wordpress-5.9/class-wp-theme-json-schema-gutenberg.php
deleted file mode 100644
index 0fa833c68072c..0000000000000
--- a/lib/compat/wordpress-5.9/class-wp-theme-json-schema-gutenberg.php
+++ /dev/null
@@ -1,489 +0,0 @@
- 'border.color',
- 'border.customStyle' => 'border.style',
- 'border.customWidth' => 'border.width',
- 'typography.customFontStyle' => 'typography.fontStyle',
- 'typography.customFontWeight' => 'typography.fontWeight',
- 'typography.customLetterSpacing' => 'typography.letterSpacing',
- 'typography.customTextDecorations' => 'typography.textDecoration',
- 'typography.customTextTransforms' => 'typography.textTransform',
- );
-
- /**
- * Maps old properties to their new location within the schema's settings.
- * This will be applied at both the defaults and individual block levels.
- */
- const V1_TO_V2_RENAMED_PATHS = array(
- 'border.customRadius' => 'border.radius',
- 'spacing.customMargin' => 'spacing.margin',
- 'spacing.customPadding' => 'spacing.padding',
- 'typography.customLineHeight' => 'typography.lineHeight',
- );
-
- /**
- * Function that migrates a given theme.json structure to the last version.
- *
- * @param array $theme_json The structure to migrate.
- *
- * @return array The structure in the last version.
- */
- public static function migrate( $theme_json ) {
- // Can be removed when the plugin minimum required version is WordPress 5.8.
- // This doesn't need to land in WordPress core.
- if ( ! isset( $theme_json['version'] ) || 0 === $theme_json['version'] ) {
- $theme_json = self::migrate_v0_to_v1( $theme_json );
- }
-
- // Provide backwards compatibility for settings that did not land in 5.8
- // and have had their `custom` prefixed removed since.
- // Can be removed when the plugin minimum required version is WordPress 5.9.
- // This doesn't need to land in WordPress core.
- if ( 1 === $theme_json['version'] ) {
- $theme_json = self::migrate_v1_remove_custom_prefixes( $theme_json );
- }
-
- if ( 1 === $theme_json['version'] ) {
- $theme_json = self::migrate_v1_to_v2( $theme_json );
- }
-
- return $theme_json;
- }
-
- /**
- * Converts a v0 data structure into a v1 one.
- *
- * It expects input data to come in v0 form:
- *
- * {
- * 'root': {
- * 'settings': { ... },
- * 'styles': { ... }
- * }
- * 'core/paragraph': {
- * 'styles': { ... },
- * 'settings': { ... }
- * },
- * 'core/heading/h1': {
- * 'settings': { ... }
- * 'styles': { ... }
- * },
- * 'core/heading/h2': {
- * 'settings': { ... }
- * 'styles': { ... }
- * },
- * }
- *
- * And it will return v1 form:
- *
- * {
- * 'settings': {
- * 'border': { ... }
- * 'color': { ... },
- * 'typography': { ... },
- * 'spacing': { ... },
- * 'custom': { ... },
- * 'blocks': {
- * 'core/paragraph': { ... }
- * }
- * },
- * styles: {
- * border: { ... }
- * color: { ... },
- * typography: { ... },
- * spacing: { ... },
- * custom: { ... },
- * blocks: {
- * core/paragraph: { ... }
- * core/heading: {
- * elements: {
- * h1: { ... },
- * h2: { ... }
- * }
- * }
- * }
- * }
- * }
- *
- * @param array $old Data in v0 schema.
- *
- * @return array Data in v1 schema.
- */
- private static function migrate_v0_to_v1( $old ) {
- // Copy everything.
- $new = $old;
-
- // Overwrite the things that change.
- if ( isset( $old['settings'] ) ) {
- $new['settings'] = self::migrate_v0_to_v1_process_settings( $old['settings'] );
- }
- if ( isset( $old['styles'] ) ) {
- $new['styles'] = self::migrate_v0_to_v1_process_styles( $old['styles'] );
- }
-
- $new['version'] = 1;
-
- return $new;
- }
-
- /**
- * Processes the settings subtree.
- *
- * @param array $settings Array to process.
- *
- * @return array The settings in the new format.
- */
- private static function migrate_v0_to_v1_process_settings( $settings ) {
- $new = array();
- $blocks_to_consolidate = array(
- 'core/heading/h1' => 'core/heading',
- 'core/heading/h2' => 'core/heading',
- 'core/heading/h3' => 'core/heading',
- 'core/heading/h4' => 'core/heading',
- 'core/heading/h5' => 'core/heading',
- 'core/heading/h6' => 'core/heading',
- 'core/post-title/h1' => 'core/post-title',
- 'core/post-title/h2' => 'core/post-title',
- 'core/post-title/h3' => 'core/post-title',
- 'core/post-title/h4' => 'core/post-title',
- 'core/post-title/h5' => 'core/post-title',
- 'core/post-title/h6' => 'core/post-title',
- 'core/query-title/h1' => 'core/query-title',
- 'core/query-title/h2' => 'core/query-title',
- 'core/query-title/h3' => 'core/query-title',
- 'core/query-title/h4' => 'core/query-title',
- 'core/query-title/h5' => 'core/query-title',
- 'core/query-title/h6' => 'core/query-title',
- );
-
- $paths_to_override = array(
- array( 'color', 'palette' ),
- array( 'color', 'gradients' ),
- array( 'spacing', 'units' ),
- array( 'typography', 'fontSizes' ),
- array( 'typography', 'fontFamilies' ),
- array( 'custom' ),
- );
-
- // 'defaults' settings become top-level.
- if ( isset( $settings[ self::V0_ALL_BLOCKS_NAME ] ) ) {
- $new = $settings[ self::V0_ALL_BLOCKS_NAME ];
- unset( $settings[ self::V0_ALL_BLOCKS_NAME ] );
- }
-
- // 'root' settings override 'defaults'.
- if ( isset( $settings[ self::V0_ROOT_BLOCK_NAME ] ) ) {
- $new = array_replace_recursive( $new, $settings[ self::V0_ROOT_BLOCK_NAME ] );
-
- // The array_replace_recursive algorithm merges at the leaf level.
- // This means that when a leaf value is an array,
- // the incoming array won't replace the existing,
- // but the numeric indexes are used for replacement.
- //
- // These cases we hold into $paths_to_override
- // and need to replace them with the new data.
- foreach ( $paths_to_override as $path ) {
- $root_value = _wp_array_get(
- $settings,
- array_merge( array( self::V0_ROOT_BLOCK_NAME ), $path ),
- null
- );
- if ( null !== $root_value ) {
- _wp_array_set( $new, $path, $root_value );
- }
- }
-
- unset( $settings[ self::V0_ROOT_BLOCK_NAME ] );
- }
-
- if ( empty( $settings ) ) {
- return $new;
- }
-
- /*
- * At this point, it only contains block's data.
- * However, some block data we need to consolidate
- * into a different section, as it's the case for:
- *
- * - core/heading/h1, core/heading/h2, ... => core/heading
- * - core/post-title/h1, core/post-title/h2, ... => core/post-title
- * - core/query-title/h1, core/query-title/h2, ... => core/query-title
- *
- */
- $new['blocks'] = $settings;
- foreach ( $blocks_to_consolidate as $old_name => $new_name ) {
- // Unset the $old_name.
- unset( $new[ $old_name ] );
-
- // Consolidate the $new value.
- $block_settings = _wp_array_get( $settings, array( $old_name ), null );
- if ( null !== $block_settings ) {
- $new_path = array( 'blocks', $new_name );
- $new_settings = array();
- _wp_array_set( $new_settings, $new_path, $block_settings );
-
- $new = array_replace_recursive( $new, $new_settings );
- foreach ( $paths_to_override as $path ) {
- $block_value = _wp_array_get( $block_settings, $path, null );
- if ( null !== $block_value ) {
- _wp_array_set( $new, array_merge( $new_path, $path ), $block_value );
- }
- }
- }
- }
-
- return $new;
- }
-
- /**
- * Processes the styles subtree.
- *
- * @param array $styles Array to process.
- *
- * @return array The styles in the new format.
- */
- private static function migrate_v0_to_v1_process_styles( $styles ) {
- $new = array();
- $block_heading = array(
- 'core/heading/h1' => 'h1',
- 'core/heading/h2' => 'h2',
- 'core/heading/h3' => 'h3',
- 'core/heading/h4' => 'h4',
- 'core/heading/h5' => 'h5',
- 'core/heading/h6' => 'h6',
- );
- $blocks_to_consolidate = array(
- 'core/post-title/h1' => 'core/post-title',
- 'core/post-title/h2' => 'core/post-title',
- 'core/post-title/h3' => 'core/post-title',
- 'core/post-title/h4' => 'core/post-title',
- 'core/post-title/h5' => 'core/post-title',
- 'core/post-title/h6' => 'core/post-title',
- 'core/query-title/h1' => 'core/query-title',
- 'core/query-title/h2' => 'core/query-title',
- 'core/query-title/h3' => 'core/query-title',
- 'core/query-title/h4' => 'core/query-title',
- 'core/query-title/h5' => 'core/query-title',
- 'core/query-title/h6' => 'core/query-title',
- );
-
- // Styles within root become top-level.
- if ( isset( $styles[ self::V0_ROOT_BLOCK_NAME ] ) ) {
- $new = $styles[ self::V0_ROOT_BLOCK_NAME ];
- unset( $styles[ self::V0_ROOT_BLOCK_NAME ] );
-
- // Transform root.styles.color.link into elements.link.color.text.
- if ( isset( $new['color']['link'] ) ) {
- $new['elements']['link']['color']['text'] = $new['color']['link'];
- unset( $new['color']['link'] );
- }
- }
-
- if ( empty( $styles ) ) {
- return $new;
- }
-
- /*
- * At this point, it only contains block's data.
- * However, we still need to consolidate a few things:
- *
- * - link element => transform from link color property
- * - heading elements => consolidate multiple blocks (core/heading/h1, core/heading/h2)
- * into a single one (core/heading).
- */
- $new['blocks'] = $styles;
-
- // link elements.
- foreach ( $new['blocks'] as $block_name => $metadata ) {
- if ( isset( $metadata['color']['link'] ) ) {
- $new['blocks'][ $block_name ]['elements']['link']['color']['text'] = $metadata['color']['link'];
- unset( $new['blocks'][ $block_name ]['color']['link'] );
- }
- }
-
- /*
- * The heading block needs a special treatment:
- *
- * - if it has a link color => it needs to be moved to the blocks.core/heading
- * - the rest is consolidated into the corresponding element
- *
- */
- foreach ( $block_heading as $old_name => $new_name ) {
- if ( ! isset( $new['blocks'][ $old_name ] ) ) {
- continue;
- }
-
- _wp_array_set( $new, array( 'elements', $new_name ), $new['blocks'][ $old_name ] );
-
- if ( isset( $new['blocks'][ $old_name ]['elements'] ) ) {
- _wp_array_set( $new, array( 'blocks', 'core/heading', 'elements' ), $new['blocks'][ $old_name ]['elements'] );
- }
-
- unset( $new['blocks'][ $old_name ] );
-
- }
-
- /*
- * Port the styles from the old blocks to the new,
- * overriding the previous values.
- */
- foreach ( $blocks_to_consolidate as $old_name => $new_name ) {
- if ( ! isset( $new['blocks'][ $old_name ] ) ) {
- continue;
- }
-
- _wp_array_set( $new, array( 'blocks', $new_name ), $new['blocks'][ $old_name ] );
- unset( $new['blocks'][ $old_name ] );
-
- }
-
- return $new;
- }
-
- /**
- * Removes the custom prefixes for a few properties that only worked in the plugin:
- *
- * 'border.customColor' => 'border.color',
- * 'border.customStyle' => 'border.style',
- * 'border.customWidth' => 'border.width',
- * 'typography.customFontStyle' => 'typography.fontStyle',
- * 'typography.customFontWeight' => 'typography.fontWeight',
- * 'typography.customLetterSpacing' => 'typography.letterSpacing',
- * 'typography.customTextDecorations' => 'typography.textDecoration',
- * 'typography.customTextTransforms' => 'typography.textTransform',
- *
- * @param array $old Data to migrate.
- *
- * @return array Data without the custom prefixes.
- */
- private static function migrate_v1_remove_custom_prefixes( $old ) {
- // Copy everything.
- $new = $old;
-
- // Overwrite the things that change.
- if ( isset( $old['settings'] ) ) {
- $new['settings'] = self::rename_paths( $old['settings'], self::V1_RENAMED_PATHS );
- }
-
- return $new;
- }
-
- /**
- * Removes the custom prefixes for a few properties
- * that were part of v1:
- *
- * 'border.customRadius' => 'border.radius',
- * 'spacing.customMargin' => 'spacing.margin',
- * 'spacing.customPadding' => 'spacing.padding',
- * 'typography.customLineHeight' => 'typography.lineHeight',
- *
- * @param array $old Data to migrate.
- *
- * @return array Data without the custom prefixes.
- */
- private static function migrate_v1_to_v2( $old ) {
- // Copy everything.
- $new = $old;
-
- // Overwrite the things that changed.
- if ( isset( $old['settings'] ) ) {
- $new['settings'] = self::rename_paths( $old['settings'], self::V1_TO_V2_RENAMED_PATHS );
- }
-
- // Set the new version.
- $new['version'] = 2;
-
- return $new;
- }
-
- /**
- * Processes the settings subtree.
- *
- * @param array $settings Array to process.
- * @param array $paths_to_rename Paths to rename.
- *
- * @return array The settings in the new format.
- */
- private static function rename_paths( $settings, $paths_to_rename ) {
- $new_settings = $settings;
-
- // Process any renamed/moved paths within default settings.
- self::rename_settings( $new_settings, $paths_to_rename );
-
- // Process individual block settings.
- if ( isset( $new_settings['blocks'] ) && is_array( $new_settings['blocks'] ) ) {
- foreach ( $new_settings['blocks'] as &$block_settings ) {
- self::rename_settings( $block_settings, $paths_to_rename );
- }
- }
-
- return $new_settings;
- }
-
- /**
- * Processes a settings array, renaming or moving properties.
- *
- * @param array $settings Reference to settings either defaults or an individual block's.
- * @param array $paths_to_rename Paths to rename.
- */
- private static function rename_settings( &$settings, $paths_to_rename ) {
- foreach ( $paths_to_rename as $original => $renamed ) {
- $original_path = explode( '.', $original );
- $renamed_path = explode( '.', $renamed );
- $current_value = _wp_array_get( $settings, $original_path, null );
-
- if ( null !== $current_value ) {
- _wp_array_set( $settings, $renamed_path, $current_value );
- self::unset_setting_by_path( $settings, $original_path );
- }
- }
- }
-
- /**
- * Removes a property from within the provided settings by its path.
- *
- * @param array $settings Reference to the current settings array.
- * @param array $path Path to the property to be removed.
- *
- * @return void
- */
- private static function unset_setting_by_path( &$settings, $path ) {
- $tmp_settings = &$settings; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
- $last_key = array_pop( $path );
- foreach ( $path as $key ) {
- $tmp_settings = &$tmp_settings[ $key ];
- }
-
- unset( $tmp_settings[ $last_key ] );
- }
-}
diff --git a/lib/compat/wordpress-5.9/default-editor-styles.php b/lib/compat/wordpress-5.9/default-editor-styles.php
deleted file mode 100644
index ff796b53c02a7..0000000000000
--- a/lib/compat/wordpress-5.9/default-editor-styles.php
+++ /dev/null
@@ -1,41 +0,0 @@
- file_get_contents( $default_editor_styles_file ),
- ),
- );
-
- // Remove the default font addition from Core Code.
- $styles_without_core_styles = array();
- if ( isset( $settings['styles'] ) ) {
- foreach ( $settings['styles'] as $style ) {
- if (
- ! isset( $style['__unstableType'] ) ||
- 'core' !== $style['__unstableType']
- ) {
- $styles_without_core_styles[] = $style;
- }
- }
- }
- $settings['styles'] = $styles_without_core_styles;
-
- return $settings;
-}
-add_filter( 'block_editor_settings_all', 'gutenberg_extend_block_editor_settings_with_default_editor_styles' );
diff --git a/lib/compat/wordpress-5.9/default-theme-supports.php b/lib/compat/wordpress-5.9/default-theme-supports.php
deleted file mode 100644
index 0c204b46d0a5e..0000000000000
--- a/lib/compat/wordpress-5.9/default-theme-supports.php
+++ /dev/null
@@ -1,23 +0,0 @@
-
- Hello WordPress!
' - ); - } - - /** - * Test gutenberg_render_elements_support() with a paragraph containing a class. - */ - public function test_class_paragraph_link_color() { - $result = self::make_unique_id_one( - gutenberg_render_elements_support( - 'Hello WordPress!
', - array( - 'blockName' => 'core/paragraph', - 'attrs' => array( - 'style' => array( - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'red', - ), - ), - ), - ), - 'backgroundColor' => 'dark-gray', - ), - ) - ) - ); - $this->assertSame( - $result, - 'Hello WordPress!
' - ); - } - - /** - * Test gutenberg_render_elements_support() with a paragraph containing a anchor. - */ - public function test_anchor_paragraph_link_color() { - $result = self::make_unique_id_one( - gutenberg_render_elements_support( - 'Hello WordPress!
', - array( - 'blockName' => 'core/paragraph', - 'attrs' => array( - 'style' => array( - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => '#fff000', - ), - ), - ), - ), - ), - ) - ) - ); - $this->assertSame( - $result, - 'Hello WordPress!
' - ); - } - -} diff --git a/phpunit/class-wp-theme-json-schema-gutenberg-test.php b/phpunit/class-wp-theme-json-schema-gutenberg-test.php deleted file mode 100644 index 6f6c2a323409c..0000000000000 --- a/phpunit/class-wp-theme-json-schema-gutenberg-test.php +++ /dev/null @@ -1,522 +0,0 @@ - array( - 'defaults' => array( - 'color' => array( - 'palette' => array( - array( - 'name' => 'Black', - 'slug' => 'black', - 'color' => '#00000', - ), - array( - 'name' => 'White', - 'slug' => 'white', - 'color' => '#ffffff', - ), - array( - 'name' => 'Pale Pink', - 'slug' => 'pale-pink', - 'color' => '#f78da7', - ), - array( - 'name' => 'Vivid Red', - 'slug' => 'vivid-red', - 'color' => '#cf2e2', - ), - ), - 'custom' => false, - 'link' => false, - ), - 'typography' => array( - 'customFontStyle' => false, - 'customFontWeight' => false, - 'customTextDecorations' => false, - 'customTextTransforms' => false, - ), - ), - 'root' => array( - 'color' => array( - 'palette' => array( - array( - 'name' => 'Pale Pink', - 'slug' => 'pale-pink', - 'color' => '#f78da7', - ), - array( - 'name' => 'Vivid Red', - 'slug' => 'vivid-red', - 'color' => '#cf2e2e', - ), - ), - 'link' => true, - ), - 'border' => array( - 'customColor' => false, - 'customRadius' => false, - 'customStyle' => false, - 'customWidth' => false, - ), - ), - 'core/paragraph' => array( - 'typography' => array( - 'dropCap' => false, - ), - ), - ), - 'styles' => array( - 'root' => array( - 'color' => array( - 'background' => 'purple', - 'link' => 'red', - ), - ), - 'core/group' => array( - 'color' => array( - 'background' => 'red', - 'link' => 'yellow', - ), - 'spacing' => array( - 'padding' => array( - 'top' => '10px', - ), - ), - ), - ), - ); - - $actual = WP_Theme_JSON_Schema_Gutenberg::migrate( $theme_json_v0 ); - - $expected = array( - 'version' => self::LATEST_SCHEMA_VERSION, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'name' => 'Pale Pink', - 'slug' => 'pale-pink', - 'color' => '#f78da7', - ), - array( - 'name' => 'Vivid Red', - 'slug' => 'vivid-red', - 'color' => '#cf2e2e', - ), - ), - 'custom' => false, - 'link' => true, - ), - 'border' => array( - 'color' => false, - 'radius' => false, - 'style' => false, - 'width' => false, - ), - 'typography' => array( - 'fontStyle' => false, - 'fontWeight' => false, - 'textDecoration' => false, - 'textTransform' => false, - ), - 'blocks' => array( - 'core/paragraph' => array( - 'typography' => array( - 'dropCap' => false, - ), - ), - ), - ), - 'styles' => array( - 'color' => array( - 'background' => 'purple', - ), - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'background' => 'red', - ), - 'spacing' => array( - 'padding' => array( - 'top' => '10px', - ), - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'yellow', - ), - ), - ), - ), - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'red', - ), - ), - ), - ), - ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - function test_migrate_v1_remove_custom_prefixes() { - $theme_json_v1 = array( - 'version' => 1, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'name' => 'Pale Pink', - 'slug' => 'pale-pink', - 'color' => '#f78da7', - ), - array( - 'name' => 'Vivid Red', - 'slug' => 'vivid-red', - 'color' => '#cf2e2e', - ), - ), - 'custom' => false, - 'link' => true, - ), - 'border' => array( - 'customColor' => false, - 'customRadius' => false, - 'customStyle' => false, - 'customWidth' => false, - ), - 'typography' => array( - 'customFontStyle' => false, - 'customFontWeight' => false, - 'customLetterSpacing' => false, - 'customTextDecorations' => false, - 'customTextTransforms' => false, - ), - 'blocks' => array( - 'core/group' => array( - 'border' => array( - 'customColor' => true, - 'customRadius' => true, - 'customStyle' => true, - 'customWidth' => true, - ), - 'typography' => array( - 'customFontStyle' => true, - 'customFontWeight' => true, - 'customLetterSpacing' => true, - 'customTextDecorations' => true, - 'customTextTransforms' => true, - ), - ), - ), - ), - 'styles' => array( - 'color' => array( - 'background' => 'purple', - ), - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'background' => 'red', - ), - 'spacing' => array( - 'padding' => array( - 'top' => '10px', - ), - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'yellow', - ), - ), - ), - ), - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'red', - ), - ), - ), - ), - ); - - $actual = WP_Theme_JSON_Schema_Gutenberg::migrate( $theme_json_v1 ); - - $expected = array( - 'version' => self::LATEST_SCHEMA_VERSION, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'name' => 'Pale Pink', - 'slug' => 'pale-pink', - 'color' => '#f78da7', - ), - array( - 'name' => 'Vivid Red', - 'slug' => 'vivid-red', - 'color' => '#cf2e2e', - ), - ), - 'custom' => false, - 'link' => true, - ), - 'border' => array( - 'color' => false, - 'radius' => false, - 'style' => false, - 'width' => false, - ), - 'typography' => array( - 'fontStyle' => false, - 'fontWeight' => false, - 'letterSpacing' => false, - 'textDecoration' => false, - 'textTransform' => false, - ), - 'blocks' => array( - 'core/group' => array( - 'border' => array( - 'color' => true, - 'radius' => true, - 'style' => true, - 'width' => true, - ), - 'typography' => array( - 'fontStyle' => true, - 'fontWeight' => true, - 'letterSpacing' => true, - 'textDecoration' => true, - 'textTransform' => true, - ), - ), - ), - ), - 'styles' => array( - 'color' => array( - 'background' => 'purple', - ), - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'background' => 'red', - ), - 'spacing' => array( - 'padding' => array( - 'top' => '10px', - ), - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'yellow', - ), - ), - ), - ), - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'red', - ), - ), - ), - ), - ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - function test_migrate_v1_to_v2() { - $theme_json_v1 = array( - 'version' => 1, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'name' => 'Pale Pink', - 'slug' => 'pale-pink', - 'color' => '#f78da7', - ), - array( - 'name' => 'Vivid Red', - 'slug' => 'vivid-red', - 'color' => '#cf2e2e', - ), - ), - 'custom' => false, - 'link' => true, - ), - 'border' => array( - 'customColor' => false, - 'customRadius' => false, - 'customStyle' => false, - 'customWidth' => false, - ), - 'typography' => array( - 'customFontStyle' => false, - 'customFontWeight' => false, - 'customLetterSpacing' => false, - 'customTextDecorations' => false, - 'customTextTransforms' => false, - ), - 'blocks' => array( - 'core/group' => array( - 'border' => array( - 'customColor' => true, - 'customRadius' => true, - 'customStyle' => true, - 'customWidth' => true, - ), - 'typography' => array( - 'customFontStyle' => true, - 'customFontWeight' => true, - 'customLetterSpacing' => true, - 'customTextDecorations' => true, - 'customTextTransforms' => true, - ), - ), - ), - ), - 'styles' => array( - 'color' => array( - 'background' => 'purple', - ), - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'background' => 'red', - ), - 'spacing' => array( - 'padding' => array( - 'top' => '10px', - ), - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'yellow', - ), - ), - ), - ), - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'red', - ), - ), - ), - ), - ); - - $actual = WP_Theme_JSON_Schema_Gutenberg::migrate( $theme_json_v1 ); - - $expected = array( - 'version' => self::LATEST_SCHEMA_VERSION, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'name' => 'Pale Pink', - 'slug' => 'pale-pink', - 'color' => '#f78da7', - ), - array( - 'name' => 'Vivid Red', - 'slug' => 'vivid-red', - 'color' => '#cf2e2e', - ), - ), - 'custom' => false, - 'link' => true, - ), - 'border' => array( - 'color' => false, - 'radius' => false, - 'style' => false, - 'width' => false, - ), - 'typography' => array( - 'fontStyle' => false, - 'fontWeight' => false, - 'letterSpacing' => false, - 'textDecoration' => false, - 'textTransform' => false, - ), - 'blocks' => array( - 'core/group' => array( - 'border' => array( - 'color' => true, - 'radius' => true, - 'style' => true, - 'width' => true, - ), - 'typography' => array( - 'fontStyle' => true, - 'fontWeight' => true, - 'letterSpacing' => true, - 'textDecoration' => true, - 'textTransform' => true, - ), - ), - ), - ), - 'styles' => array( - 'color' => array( - 'background' => 'purple', - ), - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'background' => 'red', - ), - 'spacing' => array( - 'padding' => array( - 'top' => '10px', - ), - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'yellow', - ), - ), - ), - ), - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'red', - ), - ), - ), - ), - ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } -} diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 36f28873fc0ac..4ba9b65aa4f5b 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -8,33 +8,32 @@ class WP_Theme_JSON_Gutenberg_Test extends WP_UnitTestCase { - function test_get_settings() { + function test_get_stylesheet_handles_whitelisted_element_pseudo_selectors() { $theme_json = new WP_Theme_JSON_Gutenberg( array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'custom' => false, - ), - 'layout' => array( - 'contentSize' => 'value', - 'invalid/key' => 'value', - ), - 'invalid/key' => 'value', - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'custom' => false, - ), - 'invalid/key' => 'value', - ), - ), - ), - 'styles' => array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( 'elements' => array( 'link' => array( - 'color' => array( - 'text' => '#111', + 'color' => array( + 'text' => 'green', + 'background' => 'red', + ), + ':hover' => array( + 'color' => array( + 'text' => 'red', + 'background' => 'green', + ), + 'typography' => array( + 'textTransform' => 'uppercase', + 'fontSize' => '10em', + ), + ), + ':focus' => array( + 'color' => array( + 'text' => 'yellow', + 'background' => 'black', + ), ), ), ), @@ -42,78 +41,37 @@ function test_get_settings() { ) ); - $actual = $theme_json->get_settings(); + $base_styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; + + $element_styles = 'a{background-color: red;color: green;}a:hover{background-color: green;color: red;font-size: 10em;text-transform: uppercase;}a:focus{background-color: black;color: yellow;}'; - $expected = array( - 'color' => array( - 'custom' => false, - ), - 'layout' => array( - 'contentSize' => 'value', - ), - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'custom' => false, - ), - ), - ), - ); + $expected = $base_styles . $element_styles; - $this->assertEqualSetsWithIndex( $expected, $actual ); + $this->assertEquals( $expected, $theme_json->get_stylesheet() ); + $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); } - function test_get_settings_presets_are_keyed_by_origin() { - $default_origin = new WP_Theme_JSON_Gutenberg( + function test_get_stylesheet_handles_only_psuedo_selector_rules_for_given_property() { + $theme_json = new WP_Theme_JSON_Gutenberg( array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'white', - 'color' => 'white', - ), - ), - ), - 'invalid/key' => 'value', - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'white', - 'color' => 'white', - ), + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'elements' => array( + 'link' => array( + ':hover' => array( + 'color' => array( + 'text' => 'red', + 'background' => 'green', + ), + 'typography' => array( + 'textTransform' => 'uppercase', + 'fontSize' => '10em', ), ), - ), - ), - ), - ), - 'default' - ); - $no_origin = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'black', - 'color' => 'black', - ), - ), - ), - 'invalid/key' => 'value', - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'black', - 'color' => 'black', - ), + ':focus' => array( + 'color' => array( + 'text' => 'yellow', + 'background' => 'black', ), ), ), @@ -122,94 +80,77 @@ function test_get_settings_presets_are_keyed_by_origin() { ) ); - $actual_default = $default_origin->get_raw_data(); - $actual_no_origin = $no_origin->get_raw_data(); + $base_styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; + + $element_styles = 'a:hover{background-color: green;color: red;font-size: 10em;text-transform: uppercase;}a:focus{background-color: black;color: yellow;}'; + + $expected = $base_styles . $element_styles; + + $this->assertEquals( $expected, $theme_json->get_stylesheet() ); + $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); + } - $expected_default = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - 'default' => array( - array( - 'slug' => 'white', - 'color' => 'white', + function test_get_stylesheet_ignores_pseudo_selectors_on_non_whitelisted_elements() { + $theme_json = new WP_Theme_JSON_Gutenberg( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'elements' => array( + 'h4' => array( + 'color' => array( + 'text' => 'green', + 'background' => 'red', ), - ), - ), - ), - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'palette' => array( - 'default' => array( - array( - 'slug' => 'white', - 'color' => 'white', - ), + ':hover' => array( + 'color' => array( + 'text' => 'red', + 'background' => 'green', ), ), - ), - ), - ), - ), - ); - $expected_no_origin = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - 'theme' => array( - array( - 'slug' => 'black', - 'color' => 'black', - ), - ), - ), - ), - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'palette' => array( - 'theme' => array( - array( - 'slug' => 'black', - 'color' => 'black', - ), + ':focus' => array( + 'color' => array( + 'text' => 'yellow', + 'background' => 'black', ), ), ), ), ), - ), + ) ); - $this->assertEqualSetsWithIndex( $expected_default, $actual_default ); - $this->assertEqualSetsWithIndex( $expected_no_origin, $actual_no_origin ); + $base_styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; + + $element_styles = 'h4{background-color: red;color: green;}'; + + $expected = $base_styles . $element_styles; + + $this->assertEquals( $expected, $theme_json->get_stylesheet() ); + $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); } - function test_get_settings_appearance_true_opts_in() { + function test_get_stylesheet_ignores_non_whitelisted_pseudo_selectors() { $theme_json = new WP_Theme_JSON_Gutenberg( array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'appearanceTools' => true, - 'spacing' => array( - 'blockGap' => false, // This should override appearanceTools. - ), - 'blocks' => array( - 'core/paragraph' => array( - 'typography' => array( - 'lineHeight' => false, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'green', + 'background' => 'red', ), - ), - 'core/group' => array( - 'appearanceTools' => true, - 'typography' => array( - 'lineHeight' => false, // This should override appearanceTools. + ':hover' => array( + 'color' => array( + 'text' => 'red', + 'background' => 'green', + ), ), - 'spacing' => array( - 'blockGap' => null, + ':levitate' => array( + 'color' => array( + 'text' => 'yellow', + 'background' => 'black', + ), ), ), ), @@ -217,74 +158,47 @@ function test_get_settings_appearance_true_opts_in() { ) ); - $actual = $theme_json->get_settings(); - $expected = array( - 'border' => array( - 'width' => true, - 'style' => true, - 'radius' => true, - 'color' => true, - ), - 'color' => array( - 'link' => true, - ), - 'spacing' => array( - 'blockGap' => false, - 'margin' => true, - 'padding' => true, - ), - 'typography' => array( - 'lineHeight' => true, - ), - 'blocks' => array( - 'core/paragraph' => array( - 'typography' => array( - 'lineHeight' => false, - ), - ), - 'core/group' => array( - 'border' => array( - 'width' => true, - 'style' => true, - 'radius' => true, - 'color' => true, - ), - 'color' => array( - 'link' => true, - ), - 'spacing' => array( - 'blockGap' => false, - 'margin' => true, - 'padding' => true, - ), - 'typography' => array( - 'lineHeight' => false, - ), - ), - ), - ); + $base_styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - $this->assertEqualSetsWithIndex( $expected, $actual ); + $element_styles = 'a{background-color: red;color: green;}a:hover{background-color: green;color: red;}'; + + $expected = $base_styles . $element_styles; + + $this->assertEquals( $expected, $theme_json->get_stylesheet() ); + $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertStringNotContainsString( 'a:levitate{', $theme_json->get_stylesheet( array( 'styles' ) ) ); } - function test_get_settings_appearance_false_does_not_opt_in() { + function test_get_stylesheet_handles_priority_of_elements_vs_block_elements_pseudo_selectors() { $theme_json = new WP_Theme_JSON_Gutenberg( array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'appearanceTools' => false, - 'border' => array( - 'width' => true, - ), - 'blocks' => array( - 'core/paragraph' => array( - 'typography' => array( - 'lineHeight' => false, - ), - ), - 'core/group' => array( - 'typography' => array( - 'lineHeight' => false, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'blocks' => array( + 'core/group' => array( + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'green', + 'background' => 'red', + ), + ':hover' => array( + 'color' => array( + 'text' => 'red', + 'background' => 'green', + ), + 'typography' => array( + 'textTransform' => 'uppercase', + 'fontSize' => '10em', + ), + ), + ':focus' => array( + 'color' => array( + 'text' => 'yellow', + 'background' => 'black', + ), + ), + ), ), ), ), @@ -292,57 +206,45 @@ function test_get_settings_appearance_false_does_not_opt_in() { ) ); - $actual = $theme_json->get_settings(); - $expected = array( - 'appearanceTools' => false, - 'border' => array( - 'width' => true, - ), - 'blocks' => array( - 'core/paragraph' => array( - 'typography' => array( - 'lineHeight' => false, - ), - ), - 'core/group' => array( - 'typography' => array( - 'lineHeight' => false, - ), - ), - ), - ); + $base_styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - $this->assertEqualSetsWithIndex( $expected, $actual ); + $element_styles = '.wp-block-group a{background-color: red;color: green;}.wp-block-group a:hover{background-color: green;color: red;font-size: 10em;text-transform: uppercase;}.wp-block-group a:focus{background-color: black;color: yellow;}'; + + $expected = $base_styles . $element_styles; + + $this->assertEquals( $expected, $theme_json->get_stylesheet() ); + $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); } - function test_get_stylesheet_support_for_shorthand_and_longhand_values() { + function test_get_stylesheet_handles_whitelisted_block_level_element_pseudo_selectors() { $theme_json = new WP_Theme_JSON_Gutenberg( array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( - 'blocks' => array( - 'core/group' => array( - 'border' => array( - 'radius' => '10px', - ), - 'spacing' => array( - 'padding' => '24px', - 'margin' => '1em', + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'green', + 'background' => 'red', ), - ), - 'core/image' => array( - 'border' => array( - 'radius' => array( - 'topLeft' => '10px', - 'bottomRight' => '1em', + ':hover' => array( + 'color' => array( + 'text' => 'red', + 'background' => 'green', ), ), - 'spacing' => array( - 'padding' => array( - 'top' => '15px', - ), - 'margin' => array( - 'bottom' => '30px', + ), + ), + 'blocks' => array( + 'core/group' => array( + 'elements' => array( + 'link' => array( + ':hover' => array( + 'color' => array( + 'text' => 'yellow', + 'background' => 'black', + ), + ), ), ), ), @@ -351,1926 +253,14 @@ function test_get_stylesheet_support_for_shorthand_and_longhand_values() { ) ); - $styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-block-group{border-radius: 10px;margin: 1em;padding: 24px;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;padding-top: 15px;}'; - $this->assertEquals( $styles, $theme_json->get_stylesheet() ); - $this->assertEquals( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) ); - } + $base_styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - function test_get_stylesheet_skips_disabled_protected_properties() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'spacing' => array( - 'blockGap' => null, - ), - ), - 'styles' => array( - 'spacing' => array( - 'blockGap' => '1em', - ), - 'blocks' => array( - 'core/columns' => array( - 'spacing' => array( - 'blockGap' => '24px', - ), - ), - ), - ), - ) - ); - - $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - $this->assertEquals( $expected, $theme_json->get_stylesheet() ); - $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); - } - - function test_get_stylesheet_renders_enabled_protected_properties() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'spacing' => array( - 'blockGap' => true, - ), - ), - 'styles' => array( - 'spacing' => array( - 'blockGap' => '1em', - ), - ), - ) - ); - - $expected = 'body { margin: 0; }body{--wp--style--block-gap: 1em;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }'; - $this->assertEquals( $expected, $theme_json->get_stylesheet() ); - $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); - } - - function test_get_stylesheet() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'text' => 'value', - 'palette' => array( - array( - 'slug' => 'grey', - 'color' => 'grey', - ), - ), - ), - 'typography' => array( - 'fontFamilies' => array( - array( - 'slug' => 'small', - 'fontFamily' => '14px', - ), - array( - 'slug' => 'big', - 'fontFamily' => '41px', - ), - ), - ), - 'spacing' => array( - 'blockGap' => false, - ), - 'misc' => 'value', - 'blocks' => array( - 'core/group' => array( - 'custom' => array( - 'base-font' => 16, - 'line-height' => array( - 'small' => 1.2, - 'medium' => 1.4, - 'large' => 1.8, - ), - ), - ), - ), - ), - 'styles' => array( - 'color' => array( - 'text' => 'var:preset|color|grey', - ), - 'misc' => 'value', - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => '#111', - 'background' => '#333', - ), - ), - ), - 'blocks' => array( - 'core/group' => array( - 'border' => array( - 'radius' => '10px', - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => '#111', - ), - ), - ), - 'spacing' => array( - 'padding' => '24px', - ), - ), - 'core/heading' => array( - 'color' => array( - 'text' => '#123456', - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => '#111', - 'background' => '#333', - ), - 'typography' => array( - 'fontSize' => '60px', - ), - ), - ), - ), - 'core/post-date' => array( - 'color' => array( - 'text' => '#123456', - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'background' => '#777', - 'text' => '#555', - ), - ), - ), - ), - 'core/image' => array( - 'border' => array( - 'radius' => array( - 'topLeft' => '10px', - 'bottomRight' => '1em', - ), - ), - 'spacing' => array( - 'margin' => array( - 'bottom' => '30px', - ), - ), - ), - ), - ), - 'misc' => 'value', - ) - ); - - $variables = 'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}'; - $styles = 'body { margin: 0; }body{color: var(--wp--preset--color--grey);}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }a{background-color: #333;color: #111;}.wp-block-group{border-radius: 10px;padding: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;}'; - $presets = '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-small-font-family{font-family: var(--wp--preset--font-family--small) !important;}.has-big-font-family{font-family: var(--wp--preset--font-family--big) !important;}'; - $all = $variables . $styles . $presets; - $this->assertEquals( $all, $theme_json->get_stylesheet() ); - $this->assertEquals( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) ); - $this->assertEquals( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) ); - $this->assertEquals( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) ); - } - - function test_get_stylesheet_preset_classes_work_with_compounded_selectors() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'blocks' => array( - 'core/heading' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'white', - 'color' => '#fff', - ), - ), - ), - ), - ), - ), - ) - ); - - $this->assertEquals( - 'h1.has-white-color,h2.has-white-color,h3.has-white-color,h4.has-white-color,h5.has-white-color,h6.has-white-color{color: var(--wp--preset--color--white) !important;}h1.has-white-background-color,h2.has-white-background-color,h3.has-white-background-color,h4.has-white-background-color,h5.has-white-background-color,h6.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}h1.has-white-border-color,h2.has-white-border-color,h3.has-white-border-color,h4.has-white-border-color,h5.has-white-border-color,h6.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}', - $theme_json->get_stylesheet( array( 'presets' ) ) - ); - } - - function test_get_stylesheet_preset_rules_come_after_block_rules() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'grey', - 'color' => 'grey', - ), - ), - ), - ), - ), - ), - 'styles' => array( - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'text' => 'red', - ), - ), - ), - ), - ) - ); - - $styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-block-group{color: red;}'; - $presets = '.wp-block-group.has-grey-color{color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}'; - $variables = '.wp-block-group{--wp--preset--color--grey: grey;}'; - $all = $variables . $styles . $presets; - $this->assertEquals( $all, $theme_json->get_stylesheet() ); - $this->assertEquals( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) ); - $this->assertEquals( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) ); - $this->assertEquals( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) ); - } - - function test_get_stylesheet_generates_proper_classes_and_css_vars_from_slugs() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'grey', - 'color' => 'grey', - ), - array( - 'slug' => 'dark grey', - 'color' => 'grey', - ), - array( - 'slug' => 'light-grey', - 'color' => 'grey', - ), - array( - 'slug' => 'white2black', - 'color' => 'grey', - ), - ), - ), - 'custom' => array( - 'white2black' => 'value', - ), - ), - ) - ); - - $this->assertEquals( - '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-dark-grey-color{color: var(--wp--preset--color--dark-grey) !important;}.has-light-grey-color{color: var(--wp--preset--color--light-grey) !important;}.has-white-2-black-color{color: var(--wp--preset--color--white-2-black) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-dark-grey-background-color{background-color: var(--wp--preset--color--dark-grey) !important;}.has-light-grey-background-color{background-color: var(--wp--preset--color--light-grey) !important;}.has-white-2-black-background-color{background-color: var(--wp--preset--color--white-2-black) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-dark-grey-border-color{border-color: var(--wp--preset--color--dark-grey) !important;}.has-light-grey-border-color{border-color: var(--wp--preset--color--light-grey) !important;}.has-white-2-black-border-color{border-color: var(--wp--preset--color--white-2-black) !important;}', - $theme_json->get_stylesheet( array( 'presets' ) ) - ); - $this->assertEquals( - 'body{--wp--preset--color--grey: grey;--wp--preset--color--dark-grey: grey;--wp--preset--color--light-grey: grey;--wp--preset--color--white-2-black: grey;--wp--custom--white-2-black: value;}', - $theme_json->get_stylesheet( array( 'variables' ) ) - ); - - } - - public function test_get_stylesheet_preset_values_are_marked_as_important() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'grey', - 'color' => 'grey', - ), - ), - ), - ), - 'styles' => array( - 'blocks' => array( - 'core/paragraph' => array( - 'color' => array( - 'text' => 'red', - 'background' => 'blue', - ), - 'typography' => array( - 'fontSize' => '12px', - 'lineHeight' => '1.3', - ), - ), - ), - ), - ), - 'default' - ); - - $this->assertEquals( - 'body{--wp--preset--color--grey: grey;}body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }p{background-color: blue;color: red;font-size: 12px;line-height: 1.3;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}', - $theme_json->get_stylesheet() - ); - } - - function test_get_stylesheet_handles_whitelisted_element_pseudo_selectors() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'green', - 'background' => 'red', - ), - ':hover' => array( - 'color' => array( - 'text' => 'red', - 'background' => 'green', - ), - 'typography' => array( - 'textTransform' => 'uppercase', - 'fontSize' => '10em', - ), - ), - ':focus' => array( - 'color' => array( - 'text' => 'yellow', - 'background' => 'black', - ), - ), - ), - ), - ), - ) - ); - - $base_styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - - $element_styles = 'a{background-color: red;color: green;}a:hover{background-color: green;color: red;font-size: 10em;text-transform: uppercase;}a:focus{background-color: black;color: yellow;}'; - - $expected = $base_styles . $element_styles; - - $this->assertEquals( $expected, $theme_json->get_stylesheet() ); - $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); - } - - function test_get_stylesheet_handles_only_psuedo_selector_rules_for_given_property() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'elements' => array( - 'link' => array( - ':hover' => array( - 'color' => array( - 'text' => 'red', - 'background' => 'green', - ), - 'typography' => array( - 'textTransform' => 'uppercase', - 'fontSize' => '10em', - ), - ), - ':focus' => array( - 'color' => array( - 'text' => 'yellow', - 'background' => 'black', - ), - ), - ), - ), - ), - ) - ); - - $base_styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - - $element_styles = 'a:hover{background-color: green;color: red;font-size: 10em;text-transform: uppercase;}a:focus{background-color: black;color: yellow;}'; - - $expected = $base_styles . $element_styles; - - $this->assertEquals( $expected, $theme_json->get_stylesheet() ); - $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); - } - - function test_get_stylesheet_ignores_pseudo_selectors_on_non_whitelisted_elements() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'elements' => array( - 'h4' => array( - 'color' => array( - 'text' => 'green', - 'background' => 'red', - ), - ':hover' => array( - 'color' => array( - 'text' => 'red', - 'background' => 'green', - ), - ), - ':focus' => array( - 'color' => array( - 'text' => 'yellow', - 'background' => 'black', - ), - ), - ), - ), - ), - ) - ); - - $base_styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - - $element_styles = 'h4{background-color: red;color: green;}'; - - $expected = $base_styles . $element_styles; - - $this->assertEquals( $expected, $theme_json->get_stylesheet() ); - $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); - } - - function test_get_stylesheet_ignores_non_whitelisted_pseudo_selectors() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'green', - 'background' => 'red', - ), - ':hover' => array( - 'color' => array( - 'text' => 'red', - 'background' => 'green', - ), - ), - ':levitate' => array( - 'color' => array( - 'text' => 'yellow', - 'background' => 'black', - ), - ), - ), - ), - ), - ) - ); - - $base_styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - - $element_styles = 'a{background-color: red;color: green;}a:hover{background-color: green;color: red;}'; - - $expected = $base_styles . $element_styles; - - $this->assertEquals( $expected, $theme_json->get_stylesheet() ); - $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); - $this->assertStringNotContainsString( 'a:levitate{', $theme_json->get_stylesheet( array( 'styles' ) ) ); - } - - function test_get_stylesheet_handles_priority_of_elements_vs_block_elements_pseudo_selectors() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'blocks' => array( - 'core/group' => array( - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'green', - 'background' => 'red', - ), - ':hover' => array( - 'color' => array( - 'text' => 'red', - 'background' => 'green', - ), - 'typography' => array( - 'textTransform' => 'uppercase', - 'fontSize' => '10em', - ), - ), - ':focus' => array( - 'color' => array( - 'text' => 'yellow', - 'background' => 'black', - ), - ), - ), - ), - ), - ), - ), - ) - ); - - $base_styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - - $element_styles = '.wp-block-group a{background-color: red;color: green;}.wp-block-group a:hover{background-color: green;color: red;font-size: 10em;text-transform: uppercase;}.wp-block-group a:focus{background-color: black;color: yellow;}'; - - $expected = $base_styles . $element_styles; - - $this->assertEquals( $expected, $theme_json->get_stylesheet() ); - $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); - } - - function test_get_stylesheet_handles_whitelisted_block_level_element_pseudo_selectors() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'green', - 'background' => 'red', - ), - ':hover' => array( - 'color' => array( - 'text' => 'red', - 'background' => 'green', - ), - ), - ), - ), - 'blocks' => array( - 'core/group' => array( - 'elements' => array( - 'link' => array( - ':hover' => array( - 'color' => array( - 'text' => 'yellow', - 'background' => 'black', - ), - ), - ), - ), - ), - ), - ), - ) - ); - - $base_styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; - - $element_styles = 'a{background-color: red;color: green;}a:hover{background-color: green;color: red;}.wp-block-group a:hover{background-color: black;color: yellow;}'; - - $expected = $base_styles . $element_styles; - - $this->assertEquals( $expected, $theme_json->get_stylesheet() ); - $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); - } - - public function test_merge_incoming_data() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'custom' => false, - 'palette' => array( - array( - 'slug' => 'red', - 'color' => 'red', - ), - array( - 'slug' => 'green', - 'color' => 'green', - ), - ), - ), - 'blocks' => array( - 'core/paragraph' => array( - 'color' => array( - 'custom' => false, - ), - ), - ), - ), - 'styles' => array( - 'typography' => array( - 'fontSize' => '12', - ), - ), - ) - ); - - $add_new_block = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'blocks' => array( - 'core/list' => array( - 'color' => array( - 'custom' => false, - ), - ), - ), - ), - 'styles' => array( - 'blocks' => array( - 'core/list' => array( - 'typography' => array( - 'fontSize' => '12', - ), - 'color' => array( - 'background' => 'brown', - ), - ), - ), - ), - ); - - $add_key_in_settings = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'customGradient' => true, - ), - ), - ); - - $update_key_in_settings = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'custom' => true, - ), - ), - ); - - $add_styles = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'blocks' => array( - 'core/group' => array( - 'spacing' => array( - 'padding' => array( - 'top' => '12px', - ), - ), - ), - ), - ), - ); - - $add_key_in_styles = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'blocks' => array( - 'core/group' => array( - 'spacing' => array( - 'padding' => array( - 'bottom' => '12px', - ), - ), - ), - ), - ), - ); - - $add_invalid_context = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'blocks' => array( - 'core/para' => array( - 'typography' => array( - 'lineHeight' => '12', - ), - ), - ), - ), - ); - - $update_presets = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'blue', - 'color' => 'blue', - ), - ), - 'gradients' => array( - array( - 'slug' => 'gradient', - 'gradient' => 'gradient', - ), - ), - ), - 'typography' => array( - 'fontSizes' => array( - array( - 'slug' => 'fontSize', - 'size' => 'fontSize', - ), - ), - 'fontFamilies' => array( - array( - 'slug' => 'fontFamily', - 'fontFamily' => 'fontFamily', - ), - ), - ), - ), - ); - - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'custom' => true, - 'customGradient' => true, - 'palette' => array( - 'theme' => array( - array( - 'slug' => 'blue', - 'color' => 'blue', - ), - ), - ), - 'gradients' => array( - 'theme' => array( - array( - 'slug' => 'gradient', - 'gradient' => 'gradient', - ), - ), - ), - ), - 'typography' => array( - 'fontSizes' => array( - 'theme' => array( - array( - 'slug' => 'fontSize', - 'size' => 'fontSize', - ), - ), - ), - 'fontFamilies' => array( - 'theme' => array( - array( - 'slug' => 'fontFamily', - 'fontFamily' => 'fontFamily', - ), - ), - ), - ), - 'blocks' => array( - 'core/paragraph' => array( - 'color' => array( - 'custom' => false, - ), - ), - 'core/list' => array( - 'color' => array( - 'custom' => false, - ), - ), - ), - ), - 'styles' => array( - 'typography' => array( - 'fontSize' => '12', - ), - 'blocks' => array( - 'core/group' => array( - 'spacing' => array( - 'padding' => array( - 'top' => '12px', - 'bottom' => '12px', - ), - ), - ), - 'core/list' => array( - 'typography' => array( - 'fontSize' => '12', - ), - 'color' => array( - 'background' => 'brown', - ), - ), - ), - ), - ); - - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_new_block ) ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_key_in_settings ) ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $update_key_in_settings ) ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_styles ) ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_key_in_styles ) ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_invalid_context ) ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $update_presets ) ); - $actual = $theme_json->get_raw_data(); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - public function test_merge_incoming_data_empty_presets() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'duotone' => array( - array( - 'slug' => 'value', - 'colors' => array( 'red', 'green' ), - ), - ), - 'gradients' => array( - array( - 'slug' => 'gradient', - 'gradient' => 'gradient', - ), - ), - 'palette' => array( - array( - 'slug' => 'red', - 'color' => 'red', - ), - ), - ), - 'spacing' => array( - 'units' => array( 'px', 'em' ), - ), - 'typography' => array( - 'fontSizes' => array( - array( - 'slug' => 'size', - 'value' => 'size', - ), - ), - ), - ), - ) - ); - - $theme_json->merge( - new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'duotone' => array(), - 'gradients' => array(), - 'palette' => array(), - ), - 'spacing' => array( - 'units' => array(), - ), - 'typography' => array( - 'fontSizes' => array(), - ), - ), - ) - ) - ); - - $actual = $theme_json->get_raw_data(); - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'duotone' => array( - 'theme' => array(), - ), - 'gradients' => array( - 'theme' => array(), - ), - 'palette' => array( - 'theme' => array(), - ), - ), - 'spacing' => array( - 'units' => array(), - ), - 'typography' => array( - 'fontSizes' => array( - 'theme' => array(), - ), - ), - ), - ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - public function test_merge_incoming_data_null_presets() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'duotone' => array( - array( - 'slug' => 'value', - 'colors' => array( 'red', 'green' ), - ), - ), - 'gradients' => array( - array( - 'slug' => 'gradient', - 'gradient' => 'gradient', - ), - ), - 'palette' => array( - array( - 'slug' => 'red', - 'color' => 'red', - ), - ), - ), - 'spacing' => array( - 'units' => array( 'px', 'em' ), - ), - 'typography' => array( - 'fontSizes' => array( - array( - 'slug' => 'size', - 'value' => 'size', - ), - ), - ), - ), - ) - ); - - $theme_json->merge( - new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'custom' => false, - ), - 'spacing' => array( - 'margin' => false, - ), - 'typography' => array( - 'lineHeight' => false, - ), - ), - ) - ) - ); - - $actual = $theme_json->get_raw_data(); - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'custom' => false, - 'duotone' => array( - 'theme' => array( - array( - 'slug' => 'value', - 'colors' => array( 'red', 'green' ), - ), - ), - ), - 'gradients' => array( - 'theme' => array( - array( - 'slug' => 'gradient', - 'gradient' => 'gradient', - ), - ), - ), - 'palette' => array( - 'theme' => array( - array( - 'slug' => 'red', - 'color' => 'red', - ), - ), - ), - ), - 'spacing' => array( - 'margin' => false, - 'units' => array( 'px', 'em' ), - ), - 'typography' => array( - 'lineHeight' => false, - 'fontSizes' => array( - 'theme' => array( - array( - 'slug' => 'size', - 'value' => 'size', - ), - ), - ), - ), - ), - ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - public function test_merge_incoming_data_color_presets_with_same_slugs_as_default_are_removed() { - $defaults = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'defaultPalette' => true, - 'palette' => array( - array( - 'slug' => 'red', - 'color' => 'red', - 'name' => 'Red', - ), - array( - 'slug' => 'green', - 'color' => 'green', - 'name' => 'Green', - ), - ), - ), - 'blocks' => array( - 'core/paragraph' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'blue', - 'color' => 'blue', - 'name' => 'Blue', - ), - ), - ), - ), - ), - ), - ), - 'default' - ); - $theme = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'pink', - 'color' => 'pink', - 'name' => 'Pink', - ), - array( - 'slug' => 'green', - 'color' => 'green', - 'name' => 'Greenish', - ), - ), - ), - 'blocks' => array( - 'core/paragraph' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'blue', - 'color' => 'blue', - 'name' => 'Bluish', - ), - array( - 'slug' => 'yellow', - 'color' => 'yellow', - 'name' => 'Yellow', - ), - array( - 'slug' => 'green', - 'color' => 'green', - 'name' => 'Block Green', - ), - ), - ), - ), - ), - ), - ) - ); - - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - 'default' => array( - array( - 'slug' => 'red', - 'color' => 'red', - 'name' => 'Red', - ), - array( - 'slug' => 'green', - 'color' => 'green', - 'name' => 'Green', - ), - ), - 'theme' => array( - array( - 'slug' => 'pink', - 'color' => 'pink', - 'name' => 'Pink', - ), - ), - ), - 'defaultPalette' => true, - ), - 'blocks' => array( - 'core/paragraph' => array( - 'color' => array( - 'palette' => array( - 'default' => array( - array( - 'slug' => 'blue', - 'color' => 'blue', - 'name' => 'Blue', - ), - ), - 'theme' => array( - array( - 'slug' => 'yellow', - 'color' => 'yellow', - 'name' => 'Yellow', - ), - ), - ), - ), - ), - ), - ), - ); - - $defaults->merge( $theme ); - $actual = $defaults->get_raw_data(); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - public function test_merge_incoming_data_color_presets_with_same_slugs_as_default_are_not_removed_if_defaults_are_disabled() { - $defaults = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'defaultPalette' => true, // Emulate the defaults from core theme.json. - 'palette' => array( - array( - 'slug' => 'red', - 'color' => 'red', - 'name' => 'Red', - ), - array( - 'slug' => 'green', - 'color' => 'green', - 'name' => 'Green', - ), - ), - ), - 'blocks' => array( - 'core/paragraph' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'blue', - 'color' => 'blue', - 'name' => 'Blue', - ), - ), - ), - ), - ), - ), - ), - 'default' - ); - $theme = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'defaultPalette' => false, - 'palette' => array( - array( - 'slug' => 'pink', - 'color' => 'pink', - 'name' => 'Pink', - ), - array( - 'slug' => 'green', - 'color' => 'green', - 'name' => 'Greenish', - ), - ), - ), - 'blocks' => array( - 'core/paragraph' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'blue', - 'color' => 'blue', - 'name' => 'Bluish', - ), - array( - 'slug' => 'yellow', - 'color' => 'yellow', - 'name' => 'Yellow', - ), - array( - 'slug' => 'green', - 'color' => 'green', - 'name' => 'Block Green', - ), - ), - ), - ), - ), - ), - ) - ); - - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'defaultPalette' => false, - 'palette' => array( - 'default' => array( - array( - 'slug' => 'red', - 'color' => 'red', - 'name' => 'Red', - ), - array( - 'slug' => 'green', - 'color' => 'green', - 'name' => 'Green', - ), - ), - 'theme' => array( - array( - 'slug' => 'pink', - 'color' => 'pink', - 'name' => 'Pink', - ), - array( - 'slug' => 'green', - 'color' => 'green', - 'name' => 'Greenish', - ), - ), - ), - ), - 'blocks' => array( - 'core/paragraph' => array( - 'color' => array( - 'palette' => array( - 'default' => array( - array( - 'slug' => 'blue', - 'color' => 'blue', - 'name' => 'Blue', - ), - ), - 'theme' => array( - array( - 'slug' => 'blue', - 'color' => 'blue', - 'name' => 'Bluish', - ), - array( - 'slug' => 'yellow', - 'color' => 'yellow', - 'name' => 'Yellow', - ), - array( - 'slug' => 'green', - 'color' => 'green', - 'name' => 'Block Green', - ), - ), - ), - ), - ), - ), - ), - ); - - $defaults->merge( $theme ); - $actual = $defaults->get_raw_data(); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - public function test_merge_incoming_data_presets_use_default_names() { - $defaults = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'typography' => array( - 'fontSizes' => array( - array( - 'name' => 'Small', - 'slug' => 'small', - 'size' => '12px', - ), - array( - 'name' => 'Large', - 'slug' => 'large', - 'size' => '20px', - ), - ), - ), - ), - ), - 'default' - ); - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'typography' => array( - 'fontSizes' => array( - array( - 'slug' => 'small', - 'size' => '1.1rem', - ), - array( - 'slug' => 'large', - 'size' => '1.75rem', - ), - array( - 'name' => 'Huge', - 'slug' => 'huge', - 'size' => '3rem', - ), - ), - ), - ), - ), - 'theme' - ); - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'typography' => array( - 'fontSizes' => array( - 'theme' => array( - array( - 'name' => 'Small', - 'slug' => 'small', - 'size' => '1.1rem', - ), - array( - 'name' => 'Large', - 'slug' => 'large', - 'size' => '1.75rem', - ), - array( - 'name' => 'Huge', - 'slug' => 'huge', - 'size' => '3rem', - ), - ), - 'default' => array( - array( - 'name' => 'Small', - 'slug' => 'small', - 'size' => '12px', - ), - array( - 'name' => 'Large', - 'slug' => 'large', - 'size' => '20px', - ), - ), - ), - ), - ), - ); - $defaults->merge( $theme_json ); - $actual = $defaults->get_raw_data(); - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - - - function test_remove_insecure_properties_removes_unsafe_styles() { - $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'color' => array( - 'gradient' => 'url(\'data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PHNjcmlwdD5hbGVydCgnb2snKTwvc2NyaXB0PjxsaW5lYXJHcmFkaWVudCBpZD0nZ3JhZGllbnQnPjxzdG9wIG9mZnNldD0nMTAlJyBzdG9wLWNvbG9yPScjRjAwJy8+PHN0b3Agb2Zmc2V0PSc5MCUnIHN0b3AtY29sb3I9JyNmY2MnLz4gPC9saW5lYXJHcmFkaWVudD48cmVjdCBmaWxsPSd1cmwoI2dyYWRpZW50KScgeD0nMCcgeT0nMCcgd2lkdGg9JzEwMCUnIGhlaWdodD0nMTAwJScvPjwvc3ZnPg==\')', - 'text' => 'var:preset|color|dark-red', - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'gradient' => 'url(\'data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PHNjcmlwdD5hbGVydCgnb2snKTwvc2NyaXB0PjxsaW5lYXJHcmFkaWVudCBpZD0nZ3JhZGllbnQnPjxzdG9wIG9mZnNldD0nMTAlJyBzdG9wLWNvbG9yPScjRjAwJy8+PHN0b3Agb2Zmc2V0PSc5MCUnIHN0b3AtY29sb3I9JyNmY2MnLz4gPC9saW5lYXJHcmFkaWVudD48cmVjdCBmaWxsPSd1cmwoI2dyYWRpZW50KScgeD0nMCcgeT0nMCcgd2lkdGg9JzEwMCUnIGhlaWdodD0nMTAwJScvPjwvc3ZnPg==\')', - 'text' => 'var:preset|color|dark-pink', - 'background' => 'var:preset|color|dark-red', - ), - ), - ), - 'blocks' => array( - 'core/image' => array( - 'filter' => array( - 'duotone' => 'var:preset|duotone|blue-red', - ), - ), - 'core/cover' => array( - 'filter' => array( - 'duotone' => 'var(--wp--preset--duotone--blue-red, var(--fallback-unsafe))', - ), - ), - 'core/group' => array( - 'color' => array( - 'gradient' => 'url(\'data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PHNjcmlwdD5hbGVydCgnb2snKTwvc2NyaXB0PjxsaW5lYXJHcmFkaWVudCBpZD0nZ3JhZGllbnQnPjxzdG9wIG9mZnNldD0nMTAlJyBzdG9wLWNvbG9yPScjRjAwJy8+PHN0b3Agb2Zmc2V0PSc5MCUnIHN0b3AtY29sb3I9JyNmY2MnLz4gPC9saW5lYXJHcmFkaWVudD48cmVjdCBmaWxsPSd1cmwoI2dyYWRpZW50KScgeD0nMCcgeT0nMCcgd2lkdGg9JzEwMCUnIGhlaWdodD0nMTAwJScvPjwvc3ZnPg==\')', - 'text' => 'var:preset|color|dark-gray', - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'gradient' => 'url(\'data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PHNjcmlwdD5hbGVydCgnb2snKTwvc2NyaXB0PjxsaW5lYXJHcmFkaWVudCBpZD0nZ3JhZGllbnQnPjxzdG9wIG9mZnNldD0nMTAlJyBzdG9wLWNvbG9yPScjRjAwJy8+PHN0b3Agb2Zmc2V0PSc5MCUnIHN0b3AtY29sb3I9JyNmY2MnLz4gPC9saW5lYXJHcmFkaWVudD48cmVjdCBmaWxsPSd1cmwoI2dyYWRpZW50KScgeD0nMCcgeT0nMCcgd2lkdGg9JzEwMCUnIGhlaWdodD0nMTAwJScvPjwvc3ZnPg==\')', - 'text' => 'var:preset|color|dark-pink', - ), - ), - ), - ), - 'invalid/key' => array( - 'background' => 'green', - ), - ), - ), - ) - ); - - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'color' => array( - 'text' => 'var:preset|color|dark-red', - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'var:preset|color|dark-pink', - 'background' => 'var:preset|color|dark-red', - ), - ), - ), - 'blocks' => array( - 'core/image' => array( - 'filter' => array( - 'duotone' => 'var:preset|duotone|blue-red', - ), - ), - 'core/group' => array( - 'color' => array( - 'text' => 'var:preset|color|dark-gray', - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'var:preset|color|dark-pink', - ), - ), - ), - ), - ), - ), - ); - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - function test_remove_insecure_properties_removes_unsafe_styles_sub_properties() { - $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'border' => array( - 'radius' => array( - 'topLeft' => '6px', - 'topRight' => 'var(--top-right, var(--unsafe-fallback))', - 'bottomRight' => '6px', - 'bottomLeft' => '6px', - ), - ), - 'spacing' => array( - 'padding' => array( - 'top' => '1px', - 'right' => '1px', - 'bottom' => 'var(--bottom, var(--unsafe-fallback))', - 'left' => '1px', - ), - ), - 'elements' => array( - 'link' => array( - 'spacing' => array( - 'padding' => array( - 'top' => '2px', - 'right' => '2px', - 'bottom' => 'var(--bottom, var(--unsafe-fallback))', - 'left' => '2px', - ), - ), - ), - ), - 'blocks' => array( - 'core/group' => array( - 'border' => array( - 'radius' => array( - 'topLeft' => '5px', - 'topRight' => 'var(--top-right, var(--unsafe-fallback))', - 'bottomRight' => '5px', - 'bottomLeft' => '5px', - ), - ), - 'spacing' => array( - 'padding' => array( - 'top' => '3px', - 'right' => '3px', - 'bottom' => 'var(bottom, var(--unsafe-fallback))', - 'left' => '3px', - ), - ), - 'elements' => array( - 'link' => array( - 'spacing' => array( - 'padding' => array( - 'top' => '4px', - 'right' => '4px', - 'bottom' => 'var(--bottom, var(--unsafe-fallback))', - 'left' => '4px', - ), - ), - ), - ), - ), - ), - ), - ), - true - ); - - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'border' => array( - 'radius' => array( - 'topLeft' => '6px', - 'bottomRight' => '6px', - 'bottomLeft' => '6px', - ), - ), - 'spacing' => array( - 'padding' => array( - 'top' => '1px', - 'right' => '1px', - 'left' => '1px', - ), - ), - 'elements' => array( - 'link' => array( - 'spacing' => array( - 'padding' => array( - 'top' => '2px', - 'right' => '2px', - 'left' => '2px', - ), - ), - ), - ), - 'blocks' => array( - 'core/group' => array( - 'border' => array( - 'radius' => array( - 'topLeft' => '5px', - 'bottomRight' => '5px', - 'bottomLeft' => '5px', - ), - ), - 'spacing' => array( - 'padding' => array( - 'top' => '3px', - 'right' => '3px', - 'left' => '3px', - ), - ), - 'elements' => array( - 'link' => array( - 'spacing' => array( - 'padding' => array( - 'top' => '4px', - 'right' => '4px', - 'left' => '4px', - ), - ), - ), - ), - ), - ), - ), - ); - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - function test_remove_insecure_properties_removes_non_preset_settings() { - $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'custom' => true, - 'palette' => array( - 'custom' => array( - array( - 'name' => 'Red', - 'slug' => 'red', - 'color' => '#ff0000', - ), - array( - 'name' => 'Green', - 'slug' => 'green', - 'color' => '#00ff00', - ), - array( - 'name' => 'Blue', - 'slug' => 'blue', - 'color' => '#0000ff', - ), - ), - ), - ), - 'spacing' => array( - 'padding' => false, - ), - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'custom' => true, - 'palette' => array( - 'custom' => array( - array( - 'name' => 'Yellow', - 'slug' => 'yellow', - 'color' => '#ff0000', - ), - array( - 'name' => 'Pink', - 'slug' => 'pink', - 'color' => '#00ff00', - ), - array( - 'name' => 'Orange', - 'slug' => 'orange', - 'color' => '#0000ff', - ), - ), - ), - ), - 'spacing' => array( - 'padding' => false, - ), - ), - ), - ), - ) - ); - - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - 'custom' => array( - array( - 'name' => 'Red', - 'slug' => 'red', - 'color' => '#ff0000', - ), - array( - 'name' => 'Green', - 'slug' => 'green', - 'color' => '#00ff00', - ), - array( - 'name' => 'Blue', - 'slug' => 'blue', - 'color' => '#0000ff', - ), - ), - ), - ), - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'palette' => array( - 'custom' => array( - array( - 'name' => 'Yellow', - 'slug' => 'yellow', - 'color' => '#ff0000', - ), - array( - 'name' => 'Pink', - 'slug' => 'pink', - 'color' => '#00ff00', - ), - array( - 'name' => 'Orange', - 'slug' => 'orange', - 'color' => '#0000ff', - ), - ), - ), - ), - ), - ), - ), - ); - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - function test_remove_insecure_properties_removes_unsafe_preset_settings() { - $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - 'custom' => array( - array( - 'name' => 'Red/>ok', - 'slug' => 'red', - 'color' => '#ff0000', - ), - array( - 'name' => 'Green', - 'slug' => 'a" attr', - 'color' => '#00ff00', - ), - array( - 'name' => 'Blue', - 'slug' => 'blue', - 'color' => 'var(--color, var(--unsafe-fallback))', - ), - array( - 'name' => 'Pink', - 'slug' => 'pink', - 'color' => '#FFC0CB', - ), - ), - ), - ), - 'typography' => array( - 'fontFamilies' => array( - 'custom' => array( - array( - 'name' => 'Helvetica Arial/>test', - 'slug' => 'helvetica-arial', - 'fontFamily' => 'Helvetica Neue, Helvetica, Arial, sans-serif', - ), - array( - 'name' => 'Geneva', - 'slug' => 'geneva#asa', - 'fontFamily' => 'Geneva, Tahoma, Verdana, sans-serif', - ), - array( - 'name' => 'Cambria', - 'slug' => 'cambria', - 'fontFamily' => 'Cambria, Georgia, serif', - ), - array( - 'name' => 'Helvetica Arial', - 'slug' => 'helvetica-arial', - 'fontFamily' => 'var(--fontFamily, var(--unsafe-fallback))', - ), - ), - ), - ), - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'palette' => array( - 'custom' => array( - array( - 'name' => 'Red/>ok', - 'slug' => 'red', - 'color' => '#ff0000', - ), - array( - 'name' => 'Green', - 'slug' => 'a" attr', - 'color' => '#00ff00', - ), - array( - 'name' => 'Blue', - 'slug' => 'blue', - 'color' => 'var(--color, var(--unsafe--fallback))', - ), - array( - 'name' => 'Pink', - 'slug' => 'pink', - 'color' => '#FFC0CB', - ), - ), - ), - ), - ), - ), - ), - ) - ); - - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - 'custom' => array( - array( - 'name' => 'Pink', - 'slug' => 'pink', - 'color' => '#FFC0CB', - ), - ), - ), - ), - 'typography' => array( - 'fontFamilies' => array( - 'custom' => array( - array( - 'name' => 'Cambria', - 'slug' => 'cambria', - 'fontFamily' => 'Cambria, Georgia, serif', - ), - ), - ), - ), - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'palette' => array( - 'custom' => array( - array( - 'name' => 'Pink', - 'slug' => 'pink', - 'color' => '#FFC0CB', - ), - ), - ), - ), - ), - ), - ), - ); - $this->assertEqualSetsWithIndex( $expected, $actual ); - } + $element_styles = 'a{background-color: red;color: green;}a:hover{background-color: green;color: red;}.wp-block-group a:hover{background-color: black;color: yellow;}'; - function test_remove_insecure_properties_applies_safe_styles() { - $actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'color' => array( - 'text' => '#abcabc ', // Trailing space. - ), - ), - ), - true - ); + $expected = $base_styles . $element_styles; - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'color' => array( - 'text' => '#abcabc ', - ), - ), - ); - $this->assertEqualSetsWithIndex( $expected, $actual ); + $this->assertEquals( $expected, $theme_json->get_stylesheet() ); + $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); } function test_remove_invalid_element_pseudo_selectors() { @@ -2320,494 +310,6 @@ function test_remove_invalid_element_pseudo_selectors() { $this->assertEqualSetsWithIndex( $expected, $actual ); } - function test_get_custom_templates() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'customTemplates' => array( - array( - 'name' => 'page-home', - 'title' => 'Homepage template', - ), - ), - ) - ); - - $page_templates = $theme_json->get_custom_templates(); - - $this->assertEqualSetsWithIndex( - $page_templates, - array( - 'page-home' => array( - 'title' => 'Homepage template', - 'postTypes' => array( 'page' ), - ), - ) - ); - } - - function test_get_template_parts() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'templateParts' => array( - array( - 'name' => 'small-header', - 'title' => 'Small Header', - 'area' => 'header', - ), - ), - ) - ); - - $template_parts = $theme_json->get_template_parts(); - - $this->assertEqualSetsWithIndex( - $template_parts, - array( - 'small-header' => array( - 'title' => 'Small Header', - 'area' => 'header', - ), - ) - ); - } - - function test_get_from_editor_settings() { - $input = array( - 'disableCustomColors' => true, - 'disableCustomGradients' => true, - 'disableCustomFontSizes' => true, - 'enableCustomLineHeight' => true, - 'enableCustomUnits' => true, - 'colors' => array( - array( - 'slug' => 'color-slug', - 'name' => 'Color Name', - 'color' => 'colorvalue', - ), - ), - 'gradients' => array( - array( - 'slug' => 'gradient-slug', - 'name' => 'Gradient Name', - 'gradient' => 'gradientvalue', - ), - ), - 'fontSizes' => array( - array( - 'slug' => 'size-slug', - 'name' => 'Size Name', - 'size' => 'sizevalue', - ), - ), - ); - - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'custom' => false, - 'customGradient' => false, - 'gradients' => array( - array( - 'slug' => 'gradient-slug', - 'name' => 'Gradient Name', - 'gradient' => 'gradientvalue', - ), - ), - 'palette' => array( - array( - 'slug' => 'color-slug', - 'name' => 'Color Name', - 'color' => 'colorvalue', - ), - ), - ), - 'spacing' => array( - 'units' => array( 'px', 'em', 'rem', 'vh', 'vw', '%' ), - ), - 'typography' => array( - 'customFontSize' => false, - 'lineHeight' => true, - 'fontSizes' => array( - array( - 'slug' => 'size-slug', - 'name' => 'Size Name', - 'size' => 'sizevalue', - ), - ), - ), - ), - ); - - $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( $input ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - function test_get_editor_settings_no_theme_support() { - $input = array( - '__unstableEnableFullSiteEditingBlocks' => false, - 'disableCustomColors' => false, - 'disableCustomFontSizes' => false, - 'disableCustomGradients' => false, - 'enableCustomLineHeight' => false, - 'enableCustomUnits' => false, - 'imageSizes' => array( - array( - 'slug' => 'thumbnail', - 'name' => 'Thumbnail', - ), - array( - 'slug' => 'medium', - 'name' => 'Medium', - ), - array( - 'slug' => 'large', - 'name' => 'Large', - ), - array( - 'slug' => 'full', - 'name' => 'Full Size', - ), - ), - 'isRTL' => false, - 'maxUploadFileSize' => 123, - ); - - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'custom' => true, - 'customGradient' => true, - ), - 'spacing' => array( - 'units' => false, - ), - 'typography' => array( - 'customFontSize' => true, - 'lineHeight' => false, - ), - ), - ); - - $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( $input ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - function test_get_editor_settings_blank() { - $expected = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array(), - ); - $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( array() ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - function test_get_editor_settings_custom_units_can_be_disabled() { - add_theme_support( 'custom-units', array() ); - $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_default_block_editor_settings() ); - remove_theme_support( 'custom-units' ); - - $expected = array( - 'units' => array( array() ), - 'padding' => false, - ); - - $this->assertEqualSetsWithIndex( $expected, $actual['settings']['spacing'] ); - } - - function test_get_editor_settings_custom_units_can_be_enabled() { - add_theme_support( 'custom-units' ); - $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_default_block_editor_settings() ); - remove_theme_support( 'custom-units' ); - - $expected = array( - 'units' => array( 'px', 'em', 'rem', 'vh', 'vw', '%' ), - 'padding' => false, - ); - - $this->assertEqualSetsWithIndex( $expected, $actual['settings']['spacing'] ); - } - - function test_get_editor_settings_custom_units_can_be_filtered() { - add_theme_support( 'custom-units', 'rem', 'em' ); - $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( get_default_block_editor_settings() ); - remove_theme_support( 'custom-units' ); - - $expected = array( - 'units' => array( 'rem', 'em' ), - 'padding' => false, - ); - - $this->assertEqualSetsWithIndex( $expected, $actual['settings']['spacing'] ); - } - - function test_sanitization() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => 2, - 'styles' => array( - 'spacing' => array( - 'blockGap' => 'valid value', - ), - 'blocks' => array( - 'core/group' => array( - 'spacing' => array( - 'margin' => 'valid value', - 'blockGap' => 'invalid value', - ), - ), - ), - ), - ) - ); - - $actual = $theme_json->get_raw_data(); - $expected = array( - 'version' => 2, - 'styles' => array( - 'spacing' => array( - 'blockGap' => 'valid value', - ), - 'blocks' => array( - 'core/group' => array( - 'spacing' => array( - 'margin' => 'valid value', - ), - ), - ), - ), - ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - function test_export_data() { - $theme = new WP_Theme_JSON_Gutenberg( - array( - 'version' => 2, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'white', - 'color' => 'white', - 'label' => 'White', - ), - array( - 'slug' => 'black', - 'color' => 'black', - 'label' => 'Black', - ), - ), - ), - ), - ) - ); - $user = new WP_Theme_JSON_Gutenberg( - array( - 'version' => 2, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'white', - 'color' => '#fff', - 'label' => 'User White', - ), - array( - 'slug' => 'hotpink', - 'color' => 'hotpink', - 'label' => 'hotpink', - ), - ), - ), - ), - ), - 'custom' - ); - - $theme->merge( $user ); - $actual = $theme->get_data(); - $expected = array( - 'version' => 2, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'white', - 'color' => '#fff', - 'label' => 'User White', - ), - array( - 'slug' => 'black', - 'color' => 'black', - 'label' => 'Black', - ), - array( - 'slug' => 'hotpink', - 'color' => 'hotpink', - 'label' => 'hotpink', - ), - ), - ), - ), - ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - function test_export_data_deals_with_empty_user_data() { - $theme = new WP_Theme_JSON_Gutenberg( - array( - 'version' => 2, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'white', - 'color' => 'white', - 'label' => 'White', - ), - array( - 'slug' => 'black', - 'color' => 'black', - 'label' => 'Black', - ), - ), - ), - ), - ) - ); - - $actual = $theme->get_data(); - $expected = array( - 'version' => 2, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'white', - 'color' => 'white', - 'label' => 'White', - ), - array( - 'slug' => 'black', - 'color' => 'black', - 'label' => 'Black', - ), - ), - ), - ), - ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - function test_export_data_deals_with_empty_theme_data() { - $user = new WP_Theme_JSON_Gutenberg( - array( - 'version' => 2, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'white', - 'color' => '#fff', - 'label' => 'User White', - ), - array( - 'slug' => 'hotpink', - 'color' => 'hotpink', - 'label' => 'hotpink', - ), - ), - ), - ), - ), - 'custom' - ); - - $actual = $user->get_data(); - $expected = array( - 'version' => 2, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'white', - 'color' => '#fff', - 'label' => 'User White', - ), - array( - 'slug' => 'hotpink', - 'color' => 'hotpink', - 'label' => 'hotpink', - ), - ), - ), - ), - ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - - function test_export_data_deals_with_empty_data() { - $theme_v2 = new WP_Theme_JSON_Gutenberg( - array( - 'version' => 2, - ), - 'theme' - ); - $actual_v2 = $theme_v2->get_data(); - $expected_v2 = array( 'version' => 2 ); - $this->assertEqualSetsWithIndex( $expected_v2, $actual_v2 ); - - $theme_v1 = new WP_Theme_JSON_Gutenberg( - array( - 'version' => 1, - ), - 'theme' - ); - $actual_v1 = $theme_v1->get_data(); - $expected_v1 = array( 'version' => 2 ); - $this->assertEqualSetsWithIndex( $expected_v1, $actual_v1 ); - } - - function test_export_data_sets_appearance_tools() { - $theme = new WP_Theme_JSON_Gutenberg( - array( - 'version' => 2, - 'settings' => array( - 'appearanceTools' => true, - 'blocks' => array( - 'core/paragraph' => array( - 'appearanceTools' => true, - ), - ), - ), - ) - ); - - $actual = $theme->get_data(); - $expected = array( - 'version' => 2, - 'settings' => array( - 'appearanceTools' => true, - 'blocks' => array( - 'core/paragraph' => array( - 'appearanceTools' => true, - ), - ), - ), - ); - - $this->assertEqualSetsWithIndex( $expected, $actual ); - } - function test_get_element_class_name_button() { $expected = 'wp-element-button'; $actual = WP_Theme_JSON_Gutenberg::get_element_class_name( 'button' ); diff --git a/phpunit/functions-test.php b/phpunit/functions-test.php deleted file mode 100644 index 87dcf0c7e77ee..0000000000000 --- a/phpunit/functions-test.php +++ /dev/null @@ -1,91 +0,0 @@ - 1, - 'settings' => array( - 'typography' => array( - 'fontFamilies' => array( - 'fontFamily' => 'DM Sans, sans-serif', - 'slug' => 'dm-sans', - 'name' => 'DM Sans', - ), - ), - 'color' => array( - 'palette' => array( - array( - 'slug' => 'foreground', - 'color' => '#242321', - 'name' => 'Foreground', - ), - array( - 'slug' => 'background', - 'color' => '#FCFBF8', - 'name' => 'Background', - ), - array( - 'slug' => 'primary', - 'color' => '#71706E', - 'name' => 'Primary', - ), - array( - 'slug' => 'tertiary', - 'color' => '#CFCFCF', - 'name' => 'Tertiary', - ), - ), - ), - ), - ); - - // Sort the array. - wp_recursive_ksort( $theme_json ); - - // Expected result. - $expected_theme_json = array( - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'color' => '#242321', - 'name' => 'Foreground', - 'slug' => 'foreground', - ), - array( - 'color' => '#FCFBF8', - 'name' => 'Background', - 'slug' => 'background', - ), - array( - 'color' => '#71706E', - 'name' => 'Primary', - 'slug' => 'primary', - ), - array( - 'color' => '#CFCFCF', - 'name' => 'Tertiary', - 'slug' => 'tertiary', - ), - ), - ), - 'typography' => array( - 'fontFamilies' => array( - 'fontFamily' => 'DM Sans, sans-serif', - 'name' => 'DM Sans', - 'slug' => 'dm-sans', - ), - ), - ), - 'version' => 1, - ); - $this->assertEquals( $theme_json, $expected_theme_json ); - } -} diff --git a/phpunit/global-styles-test.php b/phpunit/global-styles-test.php deleted file mode 100644 index 39712522293db..0000000000000 --- a/phpunit/global-styles-test.php +++ /dev/null @@ -1,28 +0,0 @@ -assertEquals( $user_theme_json, $filtered_user_theme_json ); - } -} diff --git a/phpunit/navigation-test.php b/phpunit/navigation-test.php deleted file mode 100644 index d10f8cd24b835..0000000000000 --- a/phpunit/navigation-test.php +++ /dev/null @@ -1,94 +0,0 @@ -enable_editor_support(); - } - - public function tearDown() { - $this->enable_editor_support(); - } - - public function test_it_doesnt_disable_block_editor_for_non_navigation_post_types() { - $filtered_result = gutenberg_disable_block_editor_for_navigation_post_type( true, static::NON_NAVIGATION_POST_TYPE ); - $this->assertTrue( $filtered_result ); - } - - public function test_it_disables_block_editor_for_navigation_post_types() { - $filtered_result = gutenberg_disable_block_editor_for_navigation_post_type( true, static::NAVIGATION_POST_TYPE ); - $this->assertFalse( $filtered_result ); - } - - public function test_it_doesnt_disable_content_editor_for_non_navigation_type_posts() { - $post = $this->create_non_navigation_post(); - $this->assertTrue( $this->supports_block_editor() ); - - gutenberg_disable_content_editor_for_navigation_post_type( $post ); - - $this->assertTrue( $this->supports_block_editor() ); - } - - public function test_it_disables_content_editor_for_navigation_type_posts() { - $post = $this->create_navigation_post(); - $this->assertTrue( $this->supports_block_editor() ); - - gutenberg_disable_content_editor_for_navigation_post_type( $post ); - - $this->assertFalse( $this->supports_block_editor() ); - } - - public function test_it_enables_content_editor_for_non_navigation_type_posts_after_the_content_editor_form() { - $this->disable_editor_support(); - $post = $this->create_navigation_post(); - $this->assertFalse( $this->supports_block_editor() ); - - gutenberg_enable_content_editor_for_navigation_post_type( $post ); - - $this->assertTrue( $this->supports_block_editor() ); - } - - public function test_it_doesnt_enable_content_editor_for_non_navigation_type_posts_after_the_content_editor_form() { - $this->disable_editor_support(); - $post = $this->create_non_navigation_post(); - $this->assertFalse( $this->supports_block_editor() ); - - gutenberg_enable_content_editor_for_navigation_post_type( $post ); - - $this->assertFalse( $this->supports_block_editor() ); - } - - private function create_post( $type ) { - $post = new WP_Post( new StdClass() ); - $post->post_type = $type; - $post->filter = 'raw'; - return $post; - } - - private function create_non_navigation_post() { - return $this->create_post( static::NON_NAVIGATION_POST_TYPE ); - } - - private function create_navigation_post() { - return $this->create_post( static::NAVIGATION_POST_TYPE ); - } - - private function supports_block_editor() { - return post_type_supports( static::NAVIGATION_POST_TYPE, 'editor' ); - } - - private function enable_editor_support() { - add_post_type_support( static::NAVIGATION_POST_TYPE, 'editor' ); - } - - private function disable_editor_support() { - remove_post_type_support( static::NAVIGATION_POST_TYPE, 'editor' ); - } -} diff --git a/phpunit/translate-settings-using-i18n-schema.php b/phpunit/translate-settings-using-i18n-schema.php deleted file mode 100644 index f91cd84d6dad8..0000000000000 --- a/phpunit/translate-settings-using-i18n-schema.php +++ /dev/null @@ -1,97 +0,0 @@ - 'block title', - 'keywords' => array( 'block keyword' ), - 'styles' => array( - (object) array( 'label' => 'block style label' ), - ), - 'context' => (object) array( - '*' => (object) array( - 'variations' => array( - (object) array( - 'title' => 'block variation title', - 'description' => 'block variation description', - 'keywords' => array( 'block variation keyword' ), - ), - ), - ), - ), - ); - $settings = array( - 'title' => 'Notice', - 'keywords' => array( - 'alert', - 'message', - ), - 'styles' => array( - array( 'label' => 'Default' ), - array( 'label' => 'Other' ), - ), - 'context' => array( - 'namespace' => array( - 'variations' => array( - array( - 'title' => 'Error', - 'description' => 'Shows error.', - 'keywords' => array( 'failure' ), - ), - ), - ), - ), - ); - $result = translate_settings_using_i18n_schema( - $i18n_schema, - $settings, - $textdomain - ); - - unload_textdomain( $textdomain ); - remove_filter( 'locale', array( $this, 'filter_set_locale_to_polish' ) ); - - $this->assertSame( 'Powiadomienie', $result['title'] ); - $this->assertSameSets( array( 'ostrzeżenie', 'wiadomość' ), $result['keywords'] ); - $this->assertSame( - array( - array( - 'label' => 'Domyślny', - ), - array( - 'label' => 'Inny', - ), - ), - $result['styles'] - ); - $this->assertSame( - array( - array( - 'title' => 'Błąd', - 'description' => 'Wyświetla błąd.', - 'keywords' => array( 'niepowodzenie' ), - ), - ), - $result['context']['namespace']['variations'] - ); - } -}