Skip to content

Commit 6973cf8

Browse files
Update escaping function (#683)
* Update escaping function * update tests * add method specific for attributes * update tests * Updates to only use wp_kses_post when strings contain html * remove wp_kses_post as escaping function * update tests --------- Co-authored-by: Grant Kinney <[email protected]>
1 parent bbe5ca5 commit 6973cf8

7 files changed

+185
-72
lines changed

includes/create-theme/theme-locale.php

+36-4
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,58 @@
55
class CBT_Theme_Locale {
66

77
/**
8-
* Escape a string for localization.
8+
* Escape text for localization.
99
*
1010
* @param string $string The string to escape.
1111
* @return string The escaped string.
1212
*/
13-
public static function escape_string( $string ) {
13+
private static function escape_text_content( $string ) {
1414
// Avoid escaping if the text is not a string.
1515
if ( ! is_string( $string ) ) {
1616
return $string;
1717
}
1818

19+
// Check if string is empty.
20+
if ( '' === $string ) {
21+
return $string;
22+
}
23+
1924
// Check if the text is already escaped.
2025
if ( str_starts_with( $string, '<?php' ) ) {
2126
return $string;
2227
}
2328

2429
$string = addcslashes( $string, "'" );
30+
2531
return "<?php esc_html_e('" . $string . "', '" . wp_get_theme()->get( 'TextDomain' ) . "');?>";
2632
}
2733

34+
/**
35+
* Escape an html element attribute for localization.
36+
*
37+
* @param string $string The string to escape.
38+
* @return string The escaped string.
39+
*/
40+
private static function escape_attribute( $string ) {
41+
// Avoid escaping if the text is not a string.
42+
if ( ! is_string( $string ) ) {
43+
return $string;
44+
}
45+
46+
// Check if string is empty.
47+
if ( '' === $string ) {
48+
return $string;
49+
}
50+
51+
// Check if the text is already escaped.
52+
if ( str_starts_with( $string, '<?php' ) ) {
53+
return $string;
54+
}
55+
56+
$string = addcslashes( $string, "'" );
57+
return "<?php esc_attr_e('" . $string . "', '" . wp_get_theme()->get( 'TextDomain' ) . "');?>";
58+
}
59+
2860
/**
2961
* Get a replacement pattern for escaping the text from the html content of a block.
3062
*
@@ -109,7 +141,7 @@ public static function escape_text_content_of_blocks( $blocks ) {
109141
return preg_replace_callback(
110142
$pattern,
111143
function( $matches ) {
112-
return $matches[1] . self::escape_string( $matches[2] ) . $matches[3];
144+
return $matches[1] . self::escape_text_content( $matches[2] ) . $matches[3];
113145
},
114146
$content
115147
);
@@ -125,7 +157,7 @@ function( $matches ) {
125157
return preg_replace_callback(
126158
$pattern,
127159
function( $matches ) {
128-
return 'alt="' . self::escape_string( $matches[1] ) . '"';
160+
return 'alt="' . self::escape_attribute( $matches[1] ) . '"';
129161
},
130162
$content
131163
);

includes/create-theme/theme-patterns.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static function escape_alt_for_pattern( $html ) {
3838
public static function escape_text_for_pattern( $text ) {
3939
if ( $text && trim( $text ) !== '' ) {
4040
$escaped_text = addslashes( $text );
41-
return "<?php echo esc_attr_e( '" . $escaped_text . "', '" . wp_get_theme()->get( 'Name' ) . "' ); ?>";
41+
return "<?php esc_attr_e('" . $escaped_text . "', '" . wp_get_theme()->get( 'Name' ) . "');?>";
4242
}
4343
}
4444

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
require_once __DIR__ . '/base.php';
3+
4+
/**
5+
* Tests for the CBT_Theme_Locale::escape_attribute method.
6+
*
7+
* @package Create_Block_Theme
8+
* @covers CBT_Theme_Locale::escape_attribute
9+
* @group locale
10+
*/
11+
class CBT_Theme_Locale_EscapeAttribute extends CBT_Theme_Locale_UnitTestCase {
12+
13+
protected function call_private_method( $method_name, $args = array() ) {
14+
$reflection = new ReflectionClass( 'CBT_Theme_Locale' );
15+
$method = $reflection->getMethod( $method_name );
16+
$method->setAccessible( true );
17+
return $method->invokeArgs( null, $args );
18+
}
19+
20+
public function test_escape_attribute() {
21+
$string = 'This is a test attribute.';
22+
$escaped_string = $this->call_private_method( 'escape_attribute', array( $string ) );
23+
$expected_string = "<?php esc_attr_e('This is a test attribute.', '" . wp_get_theme()->get( 'TextDomain' ) . "');?>";
24+
$this->assertEquals( $expected_string, $escaped_string );
25+
}
26+
27+
public function test_escape_attribute_with_single_quote() {
28+
$string = "This is a test attribute with a single quote '";
29+
$escaped_string = $this->call_private_method( 'escape_attribute', array( $string ) );
30+
$expected_string = "<?php esc_attr_e('This is a test attribute with a single quote \\'', '" . wp_get_theme()->get( 'TextDomain' ) . "');?>";
31+
$this->assertEquals( $expected_string, $escaped_string );
32+
}
33+
34+
public function test_escape_attribute_with_double_quote() {
35+
$string = 'This is a test attribute with a double quote "';
36+
$escaped_string = $this->call_private_method( 'escape_attribute', array( $string ) );
37+
$expected_string = "<?php esc_attr_e('This is a test attribute with a double quote \"', '" . wp_get_theme()->get( 'TextDomain' ) . "');?>";
38+
$this->assertEquals( $expected_string, $escaped_string );
39+
}
40+
41+
public function test_escape_attribute_with_empty_string() {
42+
$string = '';
43+
$escaped_string = $this->call_private_method( 'escape_attribute', array( $string ) );
44+
$this->assertEquals( $string, $escaped_string );
45+
}
46+
47+
public function test_escape_attribute_with_already_escaped_string() {
48+
$string = "<?php esc_attr_e('This is already escaped.', '" . wp_get_theme()->get( 'TextDomain' ) . "');?>";
49+
$escaped_string = $this->call_private_method( 'escape_attribute', array( $string ) );
50+
$this->assertEquals( $string, $escaped_string );
51+
}
52+
53+
public function test_escape_attribute_with_non_string() {
54+
$string = null;
55+
$escaped_string = $this->call_private_method( 'escape_attribute', array( $string ) );
56+
$this->assertEquals( $string, $escaped_string );
57+
}
58+
}

tests/CbtThemeLocale/escapeString.php

-48
This file was deleted.
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
require_once __DIR__ . '/base.php';
4+
5+
/**
6+
* Tests for the CBT_Theme_Locale::escape_text_content method.
7+
*
8+
* @package Create_Block_Theme
9+
* @covers CBT_Theme_Locale::escape_text_content
10+
* @group locale
11+
*/
12+
class CBT_Theme_Locale_EscapeTextContent extends CBT_Theme_Locale_UnitTestCase {
13+
14+
protected function call_private_method( $method_name, $args = array() ) {
15+
$reflection = new ReflectionClass( 'CBT_Theme_Locale' );
16+
$method = $reflection->getMethod( $method_name );
17+
$method->setAccessible( true );
18+
return $method->invokeArgs( null, $args );
19+
}
20+
21+
public function test_escape_text_content() {
22+
$string = 'This is a test text.';
23+
$escaped_string = $this->call_private_method( 'escape_text_content', array( $string ) );
24+
$this->assertEquals( "<?php esc_html_e('This is a test text.', 'test-locale-theme');?>", $escaped_string );
25+
}
26+
27+
public function test_escape_text_content_with_single_quote() {
28+
$string = "This is a test text with a single quote '";
29+
$escaped_string = $this->call_private_method( 'escape_text_content', array( $string ) );
30+
$this->assertEquals( "<?php esc_html_e('This is a test text with a single quote \\'', 'test-locale-theme');?>", $escaped_string );
31+
}
32+
33+
public function test_escape_text_content_with_double_quote() {
34+
$string = 'This is a test text with a double quote "';
35+
$escaped_string = $this->call_private_method( 'escape_text_content', array( $string ) );
36+
$this->assertEquals( "<?php esc_html_e('This is a test text with a double quote \"', 'test-locale-theme');?>", $escaped_string );
37+
}
38+
39+
public function test_escape_text_content_with_html() {
40+
$string = '<p>This is a test text with HTML.</p>';
41+
$escaped_string = $this->call_private_method( 'escape_text_content', array( $string ) );
42+
$this->assertEquals( "<?php esc_html_e('<p>This is a test text with HTML.</p>', 'test-locale-theme');?>", $escaped_string );
43+
}
44+
45+
public function test_escape_text_content_with_already_escaped_string() {
46+
$string = "<?php esc_html_e('This is a test text.', 'test-locale-theme');?>";
47+
$escaped_string = $this->call_private_method( 'escape_text_content', array( $string ) );
48+
$this->assertEquals( $string, $escaped_string );
49+
}
50+
51+
public function test_escape_text_content_with_non_string() {
52+
$string = null;
53+
$escaped_string = $this->call_private_method( 'escape_text_content', array( $string ) );
54+
$this->assertEquals( $string, $escaped_string );
55+
}
56+
}

tests/CbtThemeLocale/escapeTextContentOfBlocks.php

+3-7
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public function data_test_escape_text_content_of_blocks() {
130130
<!-- /wp:image -->',
131131
'expected_markup' =>
132132
'<!-- wp:image {"sizeSlug":"large","linkDestination":"none","className":"is-style-rounded"} -->
133-
<figure class="wp-block-image size-large is-style-rounded"><img src="http://localhost/wp1/wp-content/themes/twentytwentyfour/assets/images/windows.webp" alt="<?php esc_html_e(\'Windows of a building in Nuremberg, Germany\', \'test-locale-theme\');?>"/></figure>
133+
<figure class="wp-block-image size-large is-style-rounded"><img src="http://localhost/wp1/wp-content/themes/twentytwentyfour/assets/images/windows.webp" alt="<?php esc_attr_e(\'Windows of a building in Nuremberg, Germany\', \'test-locale-theme\');?>"/></figure>
134134
<!-- /wp:image -->',
135135
),
136136

@@ -143,7 +143,7 @@ public function data_test_escape_text_content_of_blocks() {
143143
<!-- /wp:cover -->',
144144
'expected_markup' =>
145145
'<!-- wp:cover {"url":"http://localhost/wp1/wp-content/uploads/2024/05/image.jpeg","id":39,"alt":"Alternative text for cover image","dimRatio":50,"customOverlayColor":"#1d2b2f","layout":{"type":"constrained"}} -->
146-
<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim" style="background-color:#1d2b2f"></span><img class="wp-block-cover__image-background wp-image-39" alt="<?php esc_html_e(\'Alternative text for cover image\', \'test-locale-theme\');?>" src="http://localhost/wp1/wp-content/uploads/2024/05/image.jpeg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} -->
146+
<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim" style="background-color:#1d2b2f"></span><img class="wp-block-cover__image-background wp-image-39" alt="<?php esc_attr_e(\'Alternative text for cover image\', \'test-locale-theme\');?>" src="http://localhost/wp1/wp-content/uploads/2024/05/image.jpeg" data-object-fit="cover"/><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"Write title…","fontSize":"large"} -->
147147
<p class="has-text-align-center has-large-font-size"><?php esc_html_e(\'This is a cover caption\', \'test-locale-theme\');?></p>
148148
<!-- /wp:paragraph --></div></div>
149149
<!-- /wp:cover -->',
@@ -158,7 +158,7 @@ public function data_test_escape_text_content_of_blocks() {
158158
<!-- /wp:media-text -->',
159159
'expected_markup' =>
160160
'<!-- wp:media-text {"mediaId":39,"mediaLink":"http://localhost/wp1/image/","mediaType":"image"} -->
161-
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img src="http://localhost/wp1/wp-content/uploads/2024/05/image.jpeg" alt="<?php esc_html_e(\'This is alt text\', \'test-locale-theme\');?>" class="wp-image-39 size-full"/></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"Content…"} -->
161+
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img src="http://localhost/wp1/wp-content/uploads/2024/05/image.jpeg" alt="<?php esc_attr_e(\'This is alt text\', \'test-locale-theme\');?>" class="wp-image-39 size-full"/></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"Content…"} -->
162162
<p><?php esc_html_e(\'Media text content test.\', \'test-locale-theme\');?></p>
163163
<!-- /wp:paragraph --></div></div>
164164
<!-- /wp:media-text -->',
@@ -189,7 +189,3 @@ public function data_test_escape_text_content_of_blocks() {
189189
);
190190
}
191191
}
192-
193-
194-
195-

0 commit comments

Comments
 (0)