Skip to content
72 changes: 64 additions & 8 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,30 @@ class WP_Theme_JSON_Gutenberg {
'fluid' => null,
'customFontSize' => null,
'dropCap' => null,
'fontFamilies' => null,
'fontFamilies' => array(
array(
'name' => null,
'slug' => null,
'fontFamily' => null,
'fontFace' => array(
array(
'ascentOverride' => null,
'descentOverride' => null,
'fontDisplay' => null,
'fontFamily' => null,
'fontFeatureSettings' => null,
'fontStyle' => null,
'fontStretch' => null,
'fontVariationSettings' => null,
'fontWeight' => null,
'lineGapOverride' => null,
'sizeAdjust' => null,
'src' => null,
'unicodeRange' => null,
),
),
),
),
'fontSizes' => null,
'fontStyle' => null,
'fontWeight' => null,
Expand Down Expand Up @@ -701,7 +724,7 @@ protected static function do_opt_in_into_settings( &$context ) {

unset( $context['appearanceTools'] );
}

/**
* Sanitizes the input according to the schemas.
*
Expand Down Expand Up @@ -796,6 +819,35 @@ protected static function sanitize( $input, $valid_block_names, $valid_element_n
$schema['settings'] = static::VALID_SETTINGS;
$schema['settings']['blocks'] = $schema_settings_blocks;

// For settings.typography.fontFamilies, make the $schema have all indexes present in the $input.
if ( isset( $input['settings']['typography']['fontFamilies'] ) ) {
// Do not handle the cases where the sanitization is called before font families are merged, since it will be handled again later.
if ( ! isset( $input['settings']['typography']['fontFamilies']['theme'] ) || ! isset( $input['settings']['typography']['fontFamilies']['custom'] ) ) {
foreach ( $input['settings']['typography']['fontFamilies'] as $font_family_key => $value ) {
$schema['settings']['typography']['fontFamilies'][ $font_family_key ] = static::VALID_SETTINGS['typography']['fontFamilies'][0];
// Do the same for fontFace.
if ( isset( $input['settings']['typography']['fontFamilies'][ $font_family_key ]['fontFace'] ) ) {
foreach ( $input['settings']['typography']['fontFamilies'][ $font_family_key ]['fontFace'] as $font_face_key => $value2 ) {
$schema['settings']['typography']['fontFamilies'][ $font_family_key ]['fontFace'][ $font_face_key ] = static::VALID_SETTINGS['typography']['fontFamilies'][0]['fontFace'][0];
}
}
}
} else {
foreach ( $input['settings']['typography']['fontFamilies']['theme'] as $font_family_key => $value ) {
$schema['settings']['typography']['fontFamilies']['theme'][ $font_family_key ] = static::VALID_SETTINGS['typography']['fontFamilies'][0];
// Do the same for fontFace.
if ( isset( $input['settings']['typography']['fontFamilies']['theme'][ $font_family_key ]['fontFace'] ) ) {
foreach ( $input['settings']['typography']['fontFamilies']['theme'][ $font_family_key ]['fontFace'] as $font_face_key => $value2 ) {
$schema['settings']['typography']['fontFamilies']['theme'][ $font_family_key ]['fontFace'][ $font_face_key ] = static::VALID_SETTINGS['typography']['fontFamilies'][0]['fontFace'][0];
}
}
}
if ( array_key_exists( 0, $schema['settings']['typography']['fontFamilies'] ) ) {
unset( $schema['settings']['typography']['fontFamilies'][0] );
}
}
}

// Remove anything that's not present in the schema.
foreach ( array( 'styles', 'settings' ) as $subtree ) {
if ( ! isset( $input[ $subtree ] ) ) {
Expand Down Expand Up @@ -3278,16 +3330,20 @@ public function get_data() {
$items = array();
if ( isset( $preset['theme'] ) ) {
foreach ( $preset['theme'] as $item ) {
$slug = $item['slug'];
unset( $item['slug'] );
$items[ $slug ] = $item;
if ( is_array( $item ) ) {
$slug = $item['slug'];
unset( $item['slug'] );
$items[ $slug ] = $item;
}
}
}
if ( isset( $preset['custom'] ) ) {
foreach ( $preset['custom'] as $item ) {
$slug = $item['slug'];
unset( $item['slug'] );
$items[ $slug ] = $item;
if ( is_array( $item ) ) {
$slug = $item['slug'];
unset( $item['slug'] );
$items[ $slug ] = $item;
}
}
}
$flattened_preset = array();
Expand Down
84 changes: 84 additions & 0 deletions phpunit/class-wp-theme-json-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,90 @@ public function test_remove_invalid_element_pseudo_selectors() {
$this->assertEqualSetsWithIndex( $expected, $actual );
}

public function test_sanitize_invalid_typography_settings() {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'settings' => array(
'typography' => array(
'fontFamilies' => array(
'badKey' => 'I am invalid',
'theme' => array(
'name' => 'Inter',
'slug' => 'inter',
'badKey' => 'I am invalid',
'fontFamily' => 'Inter',
'fontFace' => array(
array(
'anotherKey' => 'I am invalid',
'fontFamily' => 'Inter',
'fontStyle' => 'normal',
'fontWeight' => '400',
'src' => 'https://example.com/inter.ttf',
),
),
),
array(
'name' => 'Piazzolla',
'slug' => 'piazzolla',
'badKey' => 'I am invalid',
'fontFamily' => 'Piazzolla',
'fontFace' => array(
array(
'anotherKey' => 'I am invalid',
'fontFamily' => 'Piazzolla',
'fontStyle' => 'italic',
'fontWeight' => '400',
'src' => 'https://example.com/font.ttf',
),
),
),
),
'src' => 'https://example.com/font.ttf',
),
),
)
);

$sanitized_theme_json = $theme_json->get_data();
$expected = array(
'version' => 2,
'settings' => array(
'typography' => array(
'fontFamilies' => array(
array(
'fontFace' => array(
array(
'fontFamily' => 'Inter',
'fontStyle' => 'normal',
'fontWeight' => '400',
'src' => 'https://example.com/inter.ttf',
),
),
'fontFamily' => 'Inter',
'name' => 'Inter',
'slug' => 'inter',
),
array(
'fontFace' => array(
array(
'fontFamily' => 'Piazzolla',
'fontStyle' => 'italic',
'fontWeight' => '400',
'src' => 'https://example.com/font.ttf',
),
),
'fontFamily' => 'Piazzolla',
'name' => 'Piazzolla',
'slug' => 'piazzolla',
),
),
),
),
);
$this->assertSameSetsWithIndex( $expected, $sanitized_theme_json, 'Sanitized theme.json settings do not match.' );
}

public function test_get_element_class_name_button() {
$expected = 'wp-element-button';
$actual = WP_Theme_JSON_Gutenberg::get_element_class_name( 'button' );
Expand Down