diff --git a/includes/create-theme/theme-readme.php b/includes/create-theme/theme-readme.php index ae303bde..2da3b57c 100644 --- a/includes/create-theme/theme-readme.php +++ b/includes/create-theme/theme-readme.php @@ -97,6 +97,9 @@ public static function create( $theme ) { // Adds the Images section $readme_content = self::add_or_update_section( 'Images', $image_credits, $readme_content ); + // Sanitize the readme content + $readme_content = self::sanitize( $readme_content ); + return $readme_content; } @@ -229,6 +232,9 @@ public static function update( $theme, $readme_content = '' ) { // Update image credits section. $readme_content = self::add_or_update_section( 'Images', $image_credits, $readme_content ); + // Sanitize the readme content. + $readme_content = self::sanitize( $readme_content ); + return $readme_content; } @@ -339,4 +345,16 @@ public static function get_sections() { return $sections; } + /** + * Sanitize the readme content. + * + * @param string $readme_content The readme content. + * @return string The sanitized readme content. + */ + private static function sanitize( $readme_content ) { + // Replaces DOS line endings with Unix line endings + $readme_content = str_replace( "\r\n", '', $readme_content ); + return $readme_content; + } + } diff --git a/tests/CbtThemeReadme/base.php b/tests/CbtThemeReadme/base.php index 2200c4dd..1acd9e97 100644 --- a/tests/CbtThemeReadme/base.php +++ b/tests/CbtThemeReadme/base.php @@ -61,4 +61,18 @@ public function tear_down() { // Restore the original active theme. switch_theme( $this->orig_active_theme_slug ); } + + /** + * Removes the newlines from a string. + * + * This is useful to make it easier to search for strings in the readme content. + * Removes both DOS and Unix newlines. + * + * @param string $string + * @return string + */ + public function remove_newlines( $string ) { + return str_replace( array( "\r\n", "\n" ), '', $string ); + } + } diff --git a/tests/CbtThemeReadme/create.php b/tests/CbtThemeReadme/create.php index 7f9b6798..6faff42c 100644 --- a/tests/CbtThemeReadme/create.php +++ b/tests/CbtThemeReadme/create.php @@ -17,8 +17,11 @@ class CBT_ThemeReadme_Create extends CBT_Theme_Readme_UnitTestCase { public function test_create( $data ) { $readme = CBT_Theme_Readme::create( $data ); + // Check sanitazion before altering the content. + $this->assertStringNotContainsString( "\r\n", $readme, 'The readme content contains DOS newlines.' ); + // Removes the newlines from the readme content to make it easier to search for strings. - $readme_without_newlines = str_replace( "\n", '', $readme ); + $readme_without_newlines = $this->remove_newlines( $readme ); $expected_name = '== ' . $data['name'] . ' =='; $expected_description = '== Description ==' . $data['description']; @@ -30,10 +33,16 @@ public function test_create( $data ) { $expected_license = 'License: ' . $data['license']; $expected_license_uri = 'License URI: ' . $data['license_uri']; $expected_font_credits = '== Fonts ==' . - ( isset( $data['font_credits'] ) ? $data['font_credits'] : '' ); + ( isset( $data['font_credits'] ) + ? $this->remove_newlines( $data['font_credits'] ) + : '' + ); $expected_image_credits = '== Images ==' . - ( isset( $data['image_credits'] ) ? $data['image_credits'] : '' ); - $expected_recommended_plugins = '== Recommended Plugins ==' . $data['recommended_plugins']; + ( isset( $data['image_credits'] ) + ? $this->remove_newlines( $data['image_credits'] ) + : '' + ); + $expected_recommended_plugins = '== Recommended Plugins ==' . $this->remove_newlines( $data['recommended_plugins'] ); $this->assertStringContainsString( $expected_name, $readme_without_newlines, 'The expected name is missing.' ); $this->assertStringContainsString( $expected_author, $readme_without_newlines, 'The expected author is missing.' ); @@ -161,6 +170,27 @@ public function data_test_create() { 'font_credits' => 'Font credit example text', ), ), + /* + * This string contains DOS newlines. + * It uses double quotes to make PHP interpret the newlines as newlines and not as string literals. + */ + 'With DOS newlines' => array( + 'data' => array( + 'name' => 'My Theme', + 'description' => 'New theme description', + 'uri' => 'https://example.com', + 'author' => 'New theme author', + 'author_uri' => 'https://example.com/author', + 'copyright_year' => '2077', + 'wp_version' => '12.12', + 'required_php_version' => '10.0', + 'license' => 'GPLv2 or later', + 'license_uri' => 'https://www.gnu.org/licenses/gpl-2.0.html', + 'image_credits' => "New image credits \r\n New image credits 2", + 'recommended_plugins' => "Plugin1 \r\n Plugin2 \r\n Plugin3", + 'font_credits' => "Font1 \r\n Font2 \r\n Font3", + ), + ), // TODO: Add more test cases. ); } diff --git a/tests/CbtThemeReadme/update.php b/tests/CbtThemeReadme/update.php index 158736fd..d6ca9012 100644 --- a/tests/CbtThemeReadme/update.php +++ b/tests/CbtThemeReadme/update.php @@ -18,13 +18,16 @@ public function test_update( $data ) { $readme_content = CBT_Theme_Readme::get_content(); $readme = CBT_Theme_Readme::update( $data, $readme_content ); + // Check sanitazion before altering the content. + $this->assertStringNotContainsString( "\r\n", $readme, 'The readme content contains DOS newlines.' ); + // Removes the newlines from the readme content to make it easier to search for strings. - $readme_without_newlines = str_replace( "\n", '', $readme ); + $readme_without_newlines = $this->remove_newlines( $readme ); $expected_author = 'Contributors: ' . $data['author']; $expected_wp_version = 'Tested up to: ' . $data['wp_version'] ?? CBT_Theme_Utils::get_current_wordpress_version(); - $expected_image_credits = '== Images ==' . $data['image_credits']; - $expected_recommended_plugins = '== Recommended Plugins ==' . $data['recommended_plugins']; + $expected_image_credits = '== Images ==' . $this->remove_newlines( $data['image_credits'] ); + $expected_recommended_plugins = '== Recommended Plugins ==' . $this->remove_newlines( $data['recommended_plugins'] ); $this->assertStringContainsString( $expected_author, $readme_without_newlines, 'The expected author is missing.' ); $this->assertStringContainsString( $expected_wp_version, $readme_without_newlines, 'The expected WP version is missing.' ); @@ -33,7 +36,7 @@ public function test_update( $data ) { // Assertion specific to font credits. if ( isset( $data['font_credits'] ) ) { - $expected_font_credits = '== Fonts ==' . $data['font_credits']; + $expected_font_credits = '== Fonts ==' . $this->remove_newlines( $data['font_credits'] ); $this->assertStringContainsString( $expected_font_credits, $readme_without_newlines, 'The expected font credits are missing.' ); } } @@ -59,7 +62,20 @@ public function data_test_update() { 'recommended_plugins' => 'New recommended plugins', ), ), - // TODO: Add more test cases. + /* + * This string contains DOS newlines. + * It uses double quotes to make PHP interpret the newlines as newlines and not as string literals. + */ + 'Remove DOS newlines' => array( + 'data' => array( + 'description' => 'New theme description', + 'author' => 'New theme author', + 'wp_version' => '12.12', + 'image_credits' => "New image credits \r\n New image credits 2", + 'recommended_plugins' => "Plugin1 \r\n Plugin2 \r\n Plugin3", + 'font_credits' => "Font1 \r\n Font2 \r\n Font3", + ), + ), ); } }