WP_Theme_JSON::sanitize │ protected static │ WP 5.8.0
Sanitizes the input according to the schemas.
Method of the class: WP_Theme_JSON{}
No Hooks.
Returns
Array. The sanitized output.
Usage
$result = WP_Theme_JSON::sanitize( $input, $valid_block_names, $valid_element_names, $valid_variations );
- $input(array) (required)
- Structure to sanitize.
- $valid_block_names(array) (required)
- List of valid block names.
- $valid_element_names(array) (required)
- List of valid element names.
- $valid_variations(array) (required)
- List of valid variations per block.
Changelog
| Since 5.8.0 | Introduced. |
| Since 5.9.0 | Added the $valid_block_names and $valid_element_name parameters. |
| Since 6.3.0 | Added the $valid_variations parameter. |
| Since 6.6.0 | Updated schema to allow extended block style variations. |
WP_Theme_JSON::sanitize() WP Theme JSON::sanitize code WP 7.1
protected static function sanitize( $input, $valid_block_names, $valid_element_names, $valid_variations ) {
$output = array();
if ( ! is_array( $input ) ) {
return $output;
}
// Preserve only the top most level keys.
$output = array_intersect_key( $input, array_flip( static::VALID_TOP_LEVEL_KEYS ) );
/*
* Remove any rules that are annotated as "top" in VALID_STYLES constant.
* Some styles are only meant to be available at the top-level (e.g.: blockGap),
* hence, the schema for blocks & elements should not have them.
*/
$styles_non_top_level = static::VALID_STYLES;
foreach ( array_keys( $styles_non_top_level ) as $section ) {
// array_key_exists() needs to be used instead of isset() because the value can be null.
if ( array_key_exists( $section, $styles_non_top_level ) && is_array( $styles_non_top_level[ $section ] ) ) {
foreach ( array_keys( $styles_non_top_level[ $section ] ) as $prop ) {
if ( 'top' === $styles_non_top_level[ $section ][ $prop ] ) {
unset( $styles_non_top_level[ $section ][ $prop ] );
}
}
}
}
// Build the schema based on valid block & element names.
$schema = array();
$schema_styles_elements = array();
$responsive_media_queries = static::get_viewport_media_queries( $input['settings']['viewport'] ?? null );
/*
* Set allowed element pseudo selectors and responsive breakpoint states.
* Target data structure in schema:
* e.g.
* - top level elements: `$schema['styles']['elements']['link'][':hover']`.
* - block level elements: `$schema['styles']['blocks']['core/button']['elements']['link'][':hover']`.
* - block responsive elements: `$schema['styles']['blocks']['core/button']['@tablet']['elements']['link'][':hover']`.
*/
foreach ( $valid_element_names as $element ) {
$schema_styles_elements[ $element ] = $styles_non_top_level;
if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element ] ) ) {
foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element ] as $pseudo_selector ) {
$schema_styles_elements[ $element ][ $pseudo_selector ] = $styles_non_top_level;
}
}
// Add responsive breakpoint states for elements.
foreach ( array_keys( $responsive_media_queries ) as $breakpoint_state ) {
$schema_styles_elements[ $element ][ $breakpoint_state ] = $styles_non_top_level;
}
}
$schema_styles_blocks = array();
$schema_settings_blocks = array();
/*
* Generate a schema for blocks.
* - Block styles can contain `elements`, `variations`, and responsive breakpoint state definitions.
* - Variations definitions cannot be nested.
* - Variations can contain styles for inner `blocks`, `elements`, and responsive breakpoint states.
* - Variation inner `blocks` styles can contain `elements` and responsive breakpoint states.
*
* As each variation needs both a `blocks` schema and responsive `blocks` schemas
* for further nested inner `blocks`, the overall schema is generated in multiple passes.
*/
foreach ( $valid_block_names as $block ) {
$schema_settings_blocks[ $block ] = static::VALID_SETTINGS;
// `viewport` and `blockVisibility` are global-only settings and cannot be set per block for now.
unset( $schema_settings_blocks[ $block ]['viewport'] );
unset( $schema_settings_blocks[ $block ]['blockVisibility'] );
$schema_styles_blocks[ $block ] = $styles_non_top_level;
$schema_styles_blocks[ $block ]['elements'] = $schema_styles_elements;
// Add responsive breakpoint states for all blocks.
foreach ( array_keys( $responsive_media_queries ) as $breakpoint_state ) {
$schema_styles_blocks[ $block ][ $breakpoint_state ] = $styles_non_top_level;
$schema_styles_blocks[ $block ][ $breakpoint_state ]['elements'] = $schema_styles_elements;
if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] ) ) {
foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo_selector ) {
$schema_styles_blocks[ $block ][ $breakpoint_state ][ $pseudo_selector ] = $styles_non_top_level;
}
}
}
// Add pseudo-selectors for blocks that support them
if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] ) ) {
foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo_selector ) {
$schema_styles_blocks[ $block ][ $pseudo_selector ] = $styles_non_top_level;
}
}
// Add custom states for blocks that support them (e.g. '-current' for navigation).
if ( isset( static::VALID_BLOCK_CUSTOM_STATES[ $block ] ) ) {
foreach ( static::VALID_BLOCK_CUSTOM_STATES[ $block ] as $custom_state ) {
$custom_state_schema = $styles_non_top_level;
/*
* The same pseudo-selectors valid for the block at the top level
* are also valid within each custom state.
*/
if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] ) ) {
foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo ) {
$custom_state_schema[ $pseudo ] = $styles_non_top_level;
}
}
$schema_styles_blocks[ $block ][ $custom_state ] = $custom_state_schema;
}
}
}
$block_style_variation_styles = static::VALID_STYLES;
$block_style_variation_styles['blocks'] = $schema_styles_blocks;
$block_style_variation_styles['elements'] = $schema_styles_elements;
foreach ( $valid_block_names as $block ) {
// Build the schema for each block style variation.
$style_variation_names = array();
if (
! empty( $input['styles']['blocks'][ $block ]['variations'] ) &&
is_array( $input['styles']['blocks'][ $block ]['variations'] ) &&
isset( $valid_variations[ $block ] )
) {
$style_variation_names = array_intersect(
array_keys( $input['styles']['blocks'][ $block ]['variations'] ),
$valid_variations[ $block ]
);
}
$schema_styles_variations = array();
if ( ! empty( $style_variation_names ) ) {
foreach ( $style_variation_names as $variation_name ) {
$variation_schema = $block_style_variation_styles;
// Add responsive breakpoint states to block style variations.
foreach ( array_keys( $responsive_media_queries ) as $breakpoint_state ) {
$variation_schema[ $breakpoint_state ] = $styles_non_top_level;
$variation_schema[ $breakpoint_state ]['elements'] = $schema_styles_elements;
$variation_schema[ $breakpoint_state ]['blocks'] = $schema_styles_blocks;
if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] ) ) {
foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo_selector ) {
$variation_schema[ $breakpoint_state ][ $pseudo_selector ] = $styles_non_top_level;
}
}
}
// Add pseudo-selectors to variations for blocks that support them
if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] ) ) {
foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo_selector ) {
$variation_schema[ $pseudo_selector ] = $styles_non_top_level;
}
}
$schema_styles_variations[ $variation_name ] = $variation_schema;
}
}
$schema_styles_blocks[ $block ]['variations'] = $schema_styles_variations;
}
$schema['styles'] = static::VALID_STYLES;
$schema['styles']['blocks'] = $schema_styles_blocks;
$schema['styles']['elements'] = $schema_styles_elements;
$schema['settings'] = static::VALID_SETTINGS;
$schema['settings']['blocks'] = $schema_settings_blocks;
$schema['settings']['typography']['fontFamilies'] = static::schema_in_root_and_per_origin( static::FONT_FAMILY_SCHEMA );
// Remove anything that's not present in the schema.
foreach ( array( 'styles', 'settings' ) as $subtree ) {
if ( ! isset( $input[ $subtree ] ) ) {
continue;
}
if ( ! is_array( $input[ $subtree ] ) ) {
unset( $output[ $subtree ] );
continue;
}
$result = static::remove_keys_not_in_schema( $input[ $subtree ], $schema[ $subtree ] );
if ( 'settings' === $subtree && array_key_exists( 'viewport', $input[ $subtree ] ) ) {
$result['viewport'] = static::sanitize_viewport_settings( $input[ $subtree ]['viewport'] );
}
if ( empty( $result ) ) {
unset( $output[ $subtree ] );
} else {
$output[ $subtree ] = static::resolve_custom_css_format( $result );
}
}
return $output;
}