Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional sanitization for settings.typography.fontFamilies #53273

Closed
wants to merge 10 commits into from
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