mirror of
https://github.com/WordPress/create-block-theme.git
synced 2025-10-03 16:11:13 +08:00
Refactor Theme_Readme (readme.txt) PHP class (#626)
* refactor ThemeReadme class * update phpunit tests config to make it more similar to core * Add tests for ThemeReadme class public methods * simplify copyright text creation * Fix cloned theme reference to original theme * updates comment * Theme_Reade::update receives a parameter with the readme content. * remove not so useful write method * Moved readme data fetching logic from utils to readme class and fleshed it out to get all sections. * Fetch and use the readme data in the metadata panel (for recomended plugins) --------- Co-authored-by: Jason Crist <jcrist@pbking.com>
This commit is contained in:
parent
6273f0228c
commit
7aed6ce339
17 changed files with 710 additions and 233 deletions
|
@ -149,7 +149,7 @@ class Create_Block_Theme_Admin {
|
|||
// Add readme.txt.
|
||||
$zip->addFromStringToTheme(
|
||||
'readme.txt',
|
||||
Theme_Readme::build_readme_txt( $theme )
|
||||
Theme_Readme::create( $theme )
|
||||
);
|
||||
|
||||
// Augment style.css
|
||||
|
@ -198,7 +198,6 @@ class Create_Block_Theme_Admin {
|
|||
$theme['recommended_plugins'] = sanitize_textarea_field( $theme['recommended_plugins'] );
|
||||
$theme['slug'] = $theme_slug;
|
||||
$theme['template'] = '';
|
||||
$theme['original_theme'] = wp_get_theme()->get( 'Name' );
|
||||
$theme['text_domain'] = $theme_slug;
|
||||
|
||||
// Use previous theme's tags if custom tags are empty.
|
||||
|
@ -218,7 +217,7 @@ class Create_Block_Theme_Admin {
|
|||
// Add readme.txt.
|
||||
$zip->addFromStringToTheme(
|
||||
'readme.txt',
|
||||
Theme_Readme::build_readme_txt( $theme )
|
||||
Theme_Readme::create( $theme )
|
||||
);
|
||||
|
||||
// Augment style.css
|
||||
|
@ -267,7 +266,7 @@ class Create_Block_Theme_Admin {
|
|||
$theme['tags_custom'] = sanitize_text_field( $theme['tags_custom'] );
|
||||
$theme['image_credits'] = sanitize_textarea_field( $theme['image_credits'] );
|
||||
$theme['recommended_plugins'] = sanitize_textarea_field( $theme['recommended_plugins'] );
|
||||
$theme['is_parent_theme'] = true;
|
||||
$theme['is_child_theme'] = true;
|
||||
$theme['text_domain'] = $child_theme_slug;
|
||||
$theme['template'] = $parent_theme_slug;
|
||||
$theme['slug'] = $child_theme_slug;
|
||||
|
@ -282,7 +281,7 @@ class Create_Block_Theme_Admin {
|
|||
// Add readme.txt.
|
||||
$zip->addFromStringToTheme(
|
||||
'readme.txt',
|
||||
Theme_Readme::build_readme_txt( $theme )
|
||||
Theme_Readme::create( $theme )
|
||||
);
|
||||
|
||||
// Add style.css.
|
||||
|
@ -357,7 +356,7 @@ class Create_Block_Theme_Admin {
|
|||
// Add readme.txt.
|
||||
file_put_contents(
|
||||
$blank_theme_path . DIRECTORY_SEPARATOR . 'readme.txt',
|
||||
Theme_Readme::build_readme_txt( $theme )
|
||||
Theme_Readme::create( $theme )
|
||||
);
|
||||
|
||||
// Add new metadata.
|
||||
|
|
|
@ -7,9 +7,10 @@ class Theme_Create {
|
|||
);
|
||||
|
||||
public static function clone_current_theme( $theme ) {
|
||||
|
||||
$theme['version'] = '1.0';
|
||||
$theme['tags_custom'] = implode( ', ', wp_get_theme()->get( 'Tags' ) );
|
||||
// Default values for cloned themes
|
||||
$theme['is_cloned_theme'] = true;
|
||||
$theme['version'] = '1.0';
|
||||
$theme['tags_custom'] = implode( ', ', wp_get_theme()->get( 'Tags' ) );
|
||||
|
||||
// Create theme directory.
|
||||
$new_theme_path = get_theme_root() . DIRECTORY_SEPARATOR . $theme['slug'];
|
||||
|
@ -33,7 +34,11 @@ class Theme_Create {
|
|||
Theme_Utils::clone_theme_to_folder( $new_theme_path, $theme['slug'], $theme['name'] );
|
||||
Theme_Templates::add_templates_to_local( 'all', $new_theme_path, $theme['slug'], $template_options );
|
||||
file_put_contents( path_join( $new_theme_path, 'theme.json' ), MY_Theme_JSON_Resolver::export_theme_data( 'all' ) );
|
||||
file_put_contents( path_join( $new_theme_path, 'readme.txt' ), Theme_Readme::build_readme_txt( $theme ) );
|
||||
|
||||
// Create the text of readme.txt file and write it to the file.
|
||||
$readme_content = Theme_Readme::create( $theme );
|
||||
file_put_contents( path_join( $new_theme_path, 'readme.txt' ), $readme_content );
|
||||
|
||||
file_put_contents( path_join( $new_theme_path, 'style.css' ), Theme_Styles::update_style_css( file_get_contents( path_join( $new_theme_path, 'style.css' ) ), $theme ) );
|
||||
|
||||
if ( $theme['subfolder'] ) {
|
||||
|
@ -61,7 +66,7 @@ class Theme_Create {
|
|||
// Add readme.txt.
|
||||
file_put_contents(
|
||||
$new_theme_path . DIRECTORY_SEPARATOR . 'readme.txt',
|
||||
Theme_Readme::build_readme_txt( $theme )
|
||||
Theme_Readme::create( $theme )
|
||||
);
|
||||
|
||||
// Add style.css.
|
||||
|
@ -109,7 +114,7 @@ class Theme_Create {
|
|||
// Add readme.txt.
|
||||
file_put_contents(
|
||||
$blank_theme_path . DIRECTORY_SEPARATOR . 'readme.txt',
|
||||
Theme_Readme::build_readme_txt( $theme )
|
||||
Theme_Readme::create( $theme )
|
||||
);
|
||||
|
||||
// Add new metadata.
|
||||
|
|
|
@ -1,132 +1,145 @@
|
|||
<?php
|
||||
|
||||
class Theme_Readme {
|
||||
|
||||
/**
|
||||
* Build a readme.txt file for CHILD/GRANDCHILD themes.
|
||||
* Get the path to the readme.txt file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function file_path() {
|
||||
return path_join( get_stylesheet_directory(), 'readme.txt' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content of the readme.txt file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_content() {
|
||||
$path = self::file_path();
|
||||
if ( ! file_exists( $path ) ) {
|
||||
return '';
|
||||
}
|
||||
return file_get_contents( $path );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates readme.txt text content from theme data.
|
||||
*
|
||||
* @param array $theme The theme data.
|
||||
* {
|
||||
* @type string $name The theme name.
|
||||
* @type string $description The theme description.
|
||||
* @type string $uri The theme URI.
|
||||
* @type string $author The theme author.
|
||||
* @type string $author_uri The theme author URI.
|
||||
* @type string $copyright_year The copyright year.
|
||||
* @type string $image_credits The image credits.
|
||||
* @type string $recommended_plugins The recommended plugins.
|
||||
* @type bool $is_child_theme Whether the theme is a child theme.
|
||||
* }
|
||||
*
|
||||
* @return string The readme content.
|
||||
*/
|
||||
public static function build_readme_txt( $theme ) {
|
||||
$slug = $theme['slug'];
|
||||
$name = $theme['name'];
|
||||
$description = $theme['description'];
|
||||
$uri = $theme['uri'];
|
||||
$author = $theme['author'];
|
||||
$author_uri = $theme['author_uri'];
|
||||
$copy_year = gmdate( 'Y' );
|
||||
$wp_version = get_bloginfo( 'version' );
|
||||
$image_credits = $theme['image_credits'] ?? '';
|
||||
$recommended_plugins = $theme['recommended_plugins'] ?? '';
|
||||
$is_parent_theme = $theme['is_parent_theme'] ?? false;
|
||||
$original_theme = $theme['original_theme'] ?? '';
|
||||
public static function create( $theme ) {
|
||||
$name = $theme['name'];
|
||||
$description = $theme['description'] ?? '';
|
||||
$uri = $theme['uri'] ?? '';
|
||||
$author = $theme['author'] ?? '';
|
||||
$author_uri = $theme['author_uri'] ?? '';
|
||||
$copy_year = $theme['copyright_year'] ?? gmdate( 'Y' );
|
||||
$wp_version = $theme['wp_version'] ?? get_bloginfo( 'version' );
|
||||
$required_php_version = $theme['required_php_version'] ?? '5.7';
|
||||
$license = $theme['license'] ?? 'GPLv2 or later';
|
||||
$license_uri = $theme['license_uri'] ?? 'http://www.gnu.org/licenses/gpl-2.0.html';
|
||||
$image_credits = $theme['image_credits'] ?? '';
|
||||
$recommended_plugins = $theme['recommended_plugins'] ?? '';
|
||||
$is_child_theme = $theme['is_child_theme'] ?? false;
|
||||
|
||||
// Handle copyright section.
|
||||
$new_copyright_section = $is_parent_theme || $original_theme ? true : false;
|
||||
$original_theme_credits = $new_copyright_section ? self::original_theme_credits( $name, $is_parent_theme ) : '';
|
||||
$copyright_section = self::copyright_section( $new_copyright_section, $original_theme_credits, $name, $copy_year, $author, $image_credits );
|
||||
// Generates the copyright section text.
|
||||
$copyright_section_content = self::get_copyright_text( $theme );
|
||||
|
||||
// Handle recommended plugins section.
|
||||
$recommended_plugins_section = self::recommended_plugins_section( $recommended_plugins ) ?? '';
|
||||
// Create empty readme content
|
||||
$readme_content = '';
|
||||
|
||||
return "=== {$name} ===
|
||||
// Adds the Theme section.
|
||||
$theme_section_content = "
|
||||
Contributors: {$author}
|
||||
Requires at least: 6.0
|
||||
Tested up to: {$wp_version}
|
||||
Requires PHP: 5.7
|
||||
License: GPLv2 or later
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
== Description ==
|
||||
|
||||
{$description}
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 1.0 =
|
||||
* Initial release
|
||||
{$recommended_plugins_section}
|
||||
{$copyright_section}
|
||||
Requires PHP: {$required_php_version}
|
||||
License: {$license}
|
||||
License URI: {$license_uri}
|
||||
";
|
||||
$readme_content = self::add_or_update_section( $name, $theme_section_content, $readme_content );
|
||||
|
||||
// Adds the Decription section
|
||||
$readme_content = self::add_or_update_section( 'Description', $description, $readme_content );
|
||||
|
||||
// Adds the Changelog section
|
||||
$initial_changelog = '
|
||||
= 1.0.0 =
|
||||
* Initial release
|
||||
';
|
||||
$readme_content = self::add_or_update_section( 'Changelog', $initial_changelog, $readme_content );
|
||||
|
||||
// Adds the recommended plugins section
|
||||
$readme_content = self::add_or_update_section( 'Recommended Plugins', $recommended_plugins, $readme_content );
|
||||
|
||||
// Adds the Copyright section
|
||||
$readme_content = self::add_or_update_section( 'Copyright', $copyright_section_content, $readme_content );
|
||||
|
||||
// Adds the Images section
|
||||
$readme_content = self::add_or_update_section( 'Images', $image_credits, $readme_content );
|
||||
|
||||
return $readme_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build string for original theme credits.
|
||||
* Used in readme.txt of cloned themes.
|
||||
* Get the theme data from the installed theme.
|
||||
*
|
||||
* @param string $new_name New theme name.
|
||||
* @return string
|
||||
* @return array The theme data.
|
||||
* {
|
||||
* @type string $name The theme name.
|
||||
* @type string $uri The theme URI.
|
||||
* @type string $author The theme author.
|
||||
* @type string $license The theme license.
|
||||
* @type string $license_uri The theme license URI.
|
||||
* }
|
||||
*/
|
||||
static function original_theme_credits( $new_name, $is_parent_theme = false ) {
|
||||
if ( ! $new_name ) {
|
||||
return;
|
||||
}
|
||||
|
||||
private static function get_active_theme_data() {
|
||||
$original_name = wp_get_theme()->get( 'Name' ) ?? '';
|
||||
$original_uri = wp_get_theme()->get( 'ThemeURI' ) ?? '';
|
||||
$original_author = wp_get_theme()->get( 'Author' ) ?? '';
|
||||
$original_readme = get_stylesheet_directory() . '/readme.txt' ?? '';
|
||||
$original_license = '';
|
||||
$original_license_uri = '';
|
||||
$readme_content = file_exists( $original_readme ) ? file_get_contents( $original_readme ) : '';
|
||||
$original_license = self::get_prop( 'License' );
|
||||
$original_license_uri = self::get_prop( 'License URI' );
|
||||
|
||||
if ( ! $readme_content ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get license from original theme readme.txt
|
||||
if ( str_contains( $readme_content, 'License:' ) ) {
|
||||
$starts = strpos( $readme_content, 'License:' ) + strlen( 'License:' );
|
||||
$ends = strpos( $readme_content, 'License URI:', $starts );
|
||||
$original_license = trim( substr( $readme_content, $starts, $ends - $starts ) );
|
||||
}
|
||||
|
||||
// Get license URI from original theme readme.txt
|
||||
if ( str_contains( $readme_content, 'License URI:' ) ) {
|
||||
$starts = strpos( $readme_content, 'License URI:' ) + strlen( 'License URI:' );
|
||||
$ends = strpos( $readme_content, '== Description ==', $starts );
|
||||
$original_license_uri = trim( substr( $readme_content, $starts, $ends - $starts ) );
|
||||
}
|
||||
|
||||
if ( empty( $original_license ) || empty( $original_license_uri ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$theme_credit_content = sprintf(
|
||||
/* translators: 1: New Theme name, 2: Original Theme Name. 3. Original Theme URI. 4. Original Theme Author. 5. Original Theme License. 6. Original Theme License URI. */
|
||||
__( '%1$s is based on %2$s (%3$s), (C) %4$s, [%5$s](%6$s)', 'create-block-theme' ),
|
||||
$new_name,
|
||||
$original_name,
|
||||
$original_uri,
|
||||
$original_author,
|
||||
$original_license,
|
||||
$original_license_uri
|
||||
return array(
|
||||
'name' => $original_name,
|
||||
'uri' => $original_uri,
|
||||
'author' => $original_author,
|
||||
'license' => $original_license,
|
||||
'license_uri' => $original_license_uri,
|
||||
);
|
||||
|
||||
if ( $is_parent_theme ) {
|
||||
$theme_credit_content = sprintf(
|
||||
/* translators: 1: New Theme name, 2: Parent Theme Name. 3. Parent Theme URI. 4. Parent Theme Author. 5. Parent Theme License. 6. Parent Theme License URI. */
|
||||
__( '%1$s is a child theme of %2$s (%3$s), (C) %4$s, [%5$s](%6$s)', 'create-block-theme' ),
|
||||
$new_name,
|
||||
$original_name,
|
||||
$original_uri,
|
||||
$original_author,
|
||||
$original_license,
|
||||
$original_license_uri
|
||||
);
|
||||
}
|
||||
|
||||
return $theme_credit_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build copyright section.
|
||||
* Used in readme.txt of cloned themes or child themes.
|
||||
* Build default copyright text for a theme.
|
||||
*
|
||||
* @return string
|
||||
* @param string $name The theme name.
|
||||
* @param string $copy_year The current year.
|
||||
* @param string $author The theme author.
|
||||
* @return string The default copyright text.
|
||||
*/
|
||||
static function copyright_section( $new_copyright_section, $original_theme_credits, $name, $copy_year, $author, $image_credits ) {
|
||||
// Default copyright section.
|
||||
$copyright_section = "== Copyright ==
|
||||
private static function get_copyright_text( $theme ) {
|
||||
$name = $theme['name'];
|
||||
$year = $theme['copy_year'] ?? gmdate( 'Y' );
|
||||
$author = $theme['author'] ?? '';
|
||||
|
||||
{$name} WordPress Theme, (C) {$copy_year} {$author}
|
||||
$text = "
|
||||
{$name} WordPress Theme, (C) {$year} {$author}
|
||||
{$name} is distributed under the terms of the GNU GPL.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
@ -137,123 +150,184 @@ the Free Software Foundation, either version 2 of the License, or
|
|||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.";
|
||||
GNU General Public License for more details.
|
||||
";
|
||||
|
||||
// If a new copyright section is required, then build ones based on the current theme.
|
||||
if ( $new_copyright_section ) {
|
||||
$copyright_section_intro = '== Copyright ==';
|
||||
$is_child_theme = $theme['is_child_theme'] ?? false;
|
||||
$is_cloned_theme = $theme['is_cloned_theme'] ?? false;
|
||||
|
||||
// Get current theme readme.txt
|
||||
$current_readme = get_stylesheet_directory() . '/readme.txt' ?? '';
|
||||
$current_readme_content = file_exists( $current_readme ) ? file_get_contents( $current_readme ) : '';
|
||||
/*
|
||||
* If the theme is a child theme or a cloned theme, add a reference to the parent theme.
|
||||
*
|
||||
* Example: "My Child Theme is a child theme of My Parent Theme (https://example.org/themes/my-parent-theme), (C) the WordPress team, [GPLv2 or later](http://www.gnu.org/licenses/gpl-2.0.html)"
|
||||
*/
|
||||
if ( $is_child_theme || $is_cloned_theme ) {
|
||||
$original_theme = self::get_active_theme_data();
|
||||
|
||||
if ( ! $current_readme_content ) {
|
||||
return;
|
||||
}
|
||||
$reference_string = $is_child_theme
|
||||
? '%1$s is a child theme of %2$s (%3$s), (C) %4$s, [%5$s](%6$s)'
|
||||
: '%1$s is based on %2$s (%3$s), (C) %4$s, [%5$s](%6$s)';
|
||||
|
||||
// Copy copyright section from current theme readme.txt
|
||||
if ( str_contains( $current_readme_content, $copyright_section_intro ) ) {
|
||||
$copyright_section_start = strpos( $current_readme_content, $copyright_section_intro );
|
||||
$copyright_section = substr( $current_readme_content, $copyright_section_start );
|
||||
$reference = sprintf(
|
||||
$reference_string,
|
||||
$name,
|
||||
$original_theme['name'],
|
||||
$original_theme['uri'],
|
||||
$original_theme['author'],
|
||||
$original_theme['license'],
|
||||
$original_theme['license_uri']
|
||||
);
|
||||
|
||||
if ( $original_theme_credits ) {
|
||||
$new_copyright_section = str_replace( $copyright_section_intro . "\n", '', $copyright_section );
|
||||
$copyright_section = $copyright_section_intro . "\n\n" . $original_theme_credits . "\n" . $new_copyright_section;
|
||||
}
|
||||
}
|
||||
$text .= "\n\n" . $reference;
|
||||
}
|
||||
|
||||
if ( $image_credits ) {
|
||||
$copyright_section = $copyright_section . "\n" . $image_credits;
|
||||
}
|
||||
|
||||
return $copyright_section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Recommended Plugins section.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static function recommended_plugins_section( $recommended_plugins, $updated_readme = '' ) {
|
||||
$recommended_plugins_section = '';
|
||||
|
||||
if ( ! $recommended_plugins ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$section_start = "\n== Recommended Plugins ==\n";
|
||||
|
||||
// Remove existing Recommended Plugins section.
|
||||
if ( $updated_readme && str_contains( $updated_readme, $section_start ) ) {
|
||||
$pattern = '/\s+== Recommended Plugins ==\s+(.*?)(?=(\n\=\=)|$)/s';
|
||||
preg_match_all( $pattern, $updated_readme, $matches );
|
||||
$current_section = $matches[0][0];
|
||||
$updated_readme = str_replace( $current_section, '', $updated_readme );
|
||||
}
|
||||
|
||||
$recommended_plugins_section = $section_start . "\n" . $recommended_plugins . "\n";
|
||||
|
||||
if ( $updated_readme ) {
|
||||
return $updated_readme . $recommended_plugins_section;
|
||||
}
|
||||
|
||||
return $recommended_plugins_section;
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update current readme.txt file, rather than building a new one.
|
||||
*
|
||||
* @param array $theme The theme data.
|
||||
* {
|
||||
* @type string $description The theme description.
|
||||
* @type string $author The theme author.
|
||||
* @type string $image_credits The image credits.
|
||||
* @type string $recommended_plugins The recommended plugins.
|
||||
* }
|
||||
* @param string $readme_content readme.txt content.
|
||||
* @return string
|
||||
*/
|
||||
public static function update_readme_txt( $theme ) {
|
||||
$description = $theme['description'];
|
||||
$author = $theme['author'];
|
||||
$wp_version = get_bloginfo( 'version' );
|
||||
public static function update( $theme, $readme_content = '' ) {
|
||||
// Theme data.
|
||||
$description = $theme['description'] ?? '';
|
||||
$author = $theme['author'] ?? '';
|
||||
$wp_version = $theme['wp_version'] ?? get_bloginfo( 'version' );
|
||||
$image_credits = $theme['image_credits'] ?? '';
|
||||
$recommended_plugins = $theme['recommended_plugins'] ?? '';
|
||||
$updated_readme = '';
|
||||
$current_readme = get_stylesheet_directory() . '/readme.txt' ?? '';
|
||||
$readme_content = file_exists( $current_readme ) ? file_get_contents( $current_readme ) : '';
|
||||
|
||||
if ( ! $readme_content ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$updated_readme = $readme_content;
|
||||
|
||||
// Update description.
|
||||
if ( $description ) {
|
||||
$pattern = '/(== Description ==)(.*?)(\n\n=|$)/s';
|
||||
preg_match_all( $pattern, $updated_readme, $matches );
|
||||
$current_description = $matches[0][0];
|
||||
$updated_readme = str_replace( $current_description, "== Description ==\n\n{$description}\n\n=", $updated_readme );
|
||||
}
|
||||
$readme_content = self::add_or_update_section( 'Description', $description, $readme_content );
|
||||
|
||||
// Update Author/Contributors.
|
||||
if ( $author ) {
|
||||
$pattern = '/(Contributors:)(.*?)(\n|$)/s';
|
||||
preg_match_all( $pattern, $updated_readme, $matches );
|
||||
$current_uri = $matches[0][0];
|
||||
$updated_readme = str_replace( $current_uri, "Contributors: {$author}\n", $updated_readme );
|
||||
}
|
||||
$readme_content = self::add_or_update_prop( 'Contributors', $author, $readme_content );
|
||||
|
||||
// Update "Tested up to" version.
|
||||
if ( $wp_version ) {
|
||||
$pattern = '/(Tested up to:)(.*?)(\n|$)/s';
|
||||
preg_match_all( $pattern, $updated_readme, $matches );
|
||||
$current_uri = $matches[0][0];
|
||||
$updated_readme = str_replace( $current_uri, "Tested up to: {$wp_version}\n", $updated_readme );
|
||||
$readme_content = self::add_or_update_prop( 'Tested up to', $wp_version, $readme_content );
|
||||
|
||||
// Update recommended plugins section.
|
||||
$readme_content = self::add_or_update_section( 'Recommended Plugins', $recommended_plugins, $readme_content );
|
||||
|
||||
// Update image credits section.
|
||||
$readme_content = self::add_or_update_section( 'Images', $image_credits, $readme_content );
|
||||
|
||||
return $readme_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a section to the readme.txt file.
|
||||
*
|
||||
* @param string $section_title Section to write.
|
||||
* @param string $section_content New content to write.
|
||||
* @param string $current_content Current content to manipulate.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function add_or_update_section( $section_title, $section_content, $readme_content = '' ) {
|
||||
// If the section content is empty, return the current content. This avoids adding empty sections.
|
||||
if ( empty( $section_content ) ) {
|
||||
return $readme_content;
|
||||
}
|
||||
|
||||
if ( $recommended_plugins ) {
|
||||
$updated_readme = self::recommended_plugins_section( $recommended_plugins, $updated_readme );
|
||||
$section_content = trim( $section_content, "\r" );
|
||||
$section_content = trim( $section_content, "\n" );
|
||||
|
||||
// Regular expression to find the section, handling both '==' and '==='
|
||||
$pattern = '/(={2,3}\s*' . preg_quote( $section_title, '/' ) . '\s*={2,3})(.*?)(?=(={2,3}|$))/s';
|
||||
$replacement = "== $section_title ==\n\n$section_content\n\n";
|
||||
|
||||
// Check if the section exists
|
||||
if ( preg_match( $pattern, $readme_content ) ) {
|
||||
// Replace the existing section content
|
||||
$updated_content = preg_replace( $pattern, $replacement, $readme_content );
|
||||
} else {
|
||||
// Remove any trailing whitespace, newlines or carriage returns from current content
|
||||
$readme_content = rtrim( $readme_content );
|
||||
|
||||
// Ensure two newlines before appending new section
|
||||
if ( ! empty( $readme_content ) ) {
|
||||
$readme_content .= "\n\n\n";
|
||||
}
|
||||
|
||||
// Append new section if not found
|
||||
$updated_content = $readme_content . $replacement;
|
||||
}
|
||||
|
||||
if ( $image_credits ) {
|
||||
$updated_readme = $updated_readme . "\n\n" . $image_credits;
|
||||
}
|
||||
return $updated_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or updates a property in the readme content.
|
||||
*
|
||||
* @param string $prop_name The name of the property.
|
||||
* @param string $prop_value The value of the property.
|
||||
* @param string $readme_content The content of the readme file.
|
||||
* @return string The updated readme content.
|
||||
*/
|
||||
private static function add_or_update_prop( $prop_name, $prop_value, $readme_content ) {
|
||||
if ( empty( $prop_value ) ) {
|
||||
return $readme_content;
|
||||
}
|
||||
$pattern = '/(' . preg_quote( $prop_name, '/' ) . ')(.*?)(\n|$)/s';
|
||||
preg_match_all( $pattern, $readme_content, $matches );
|
||||
$current_uri = $matches[0][0];
|
||||
$updated_readme = str_replace( $current_uri, "{$prop_name}: {$prop_value}\n", $readme_content );
|
||||
return $updated_readme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get property value from the readme content.
|
||||
*
|
||||
* @return string The property value
|
||||
*/
|
||||
private static function get_prop( $property, $readme_content = '' ) {
|
||||
if ( empty( $readme_content ) ) {
|
||||
$readme_content = self::get_content();
|
||||
}
|
||||
|
||||
// Build the regular expression pattern to match the line
|
||||
$pattern = '/^' . preg_quote( $property, '/' ) . ': (.*)$/m';
|
||||
|
||||
// Use preg_match to find a matching line
|
||||
if ( preg_match( $pattern, $readme_content, $matches ) ) {
|
||||
// Return the capturing group which contains the value after the colon
|
||||
return trim( $matches[1] );
|
||||
} else {
|
||||
// Return null if no match is found
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static function get_sections() {
|
||||
|
||||
$readme_content = self::get_content();
|
||||
$sections = array();
|
||||
|
||||
// Regular expression to find the section, handling both '==' and '==='
|
||||
$pattern = '/(={2,3}\s*(.*?)\s*={2,3})(.*?)(?=(={2,3}|$))/s';
|
||||
|
||||
// Find all sections
|
||||
preg_match_all( $pattern, $readme_content, $matches, PREG_SET_ORDER );
|
||||
|
||||
// Loop through the matches
|
||||
foreach ( $matches as $match ) {
|
||||
$section_title = str_replace( '-', '_', sanitize_title( $match[2] ) );
|
||||
$section_content = trim( $match[3] );
|
||||
|
||||
// Add the section to the sections array
|
||||
$sections[ $section_title ] = $section_content;
|
||||
}
|
||||
|
||||
return $sections;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -91,26 +91,6 @@ class Theme_Utils {
|
|||
}
|
||||
}
|
||||
|
||||
public static function get_readme_data() {
|
||||
$readme_location = get_template_directory() . '/readme.txt';
|
||||
|
||||
if ( ! file_exists( $readme_location ) ) {
|
||||
throw new Exception( 'No readme file found' );
|
||||
}
|
||||
|
||||
$readme_file_contents = file_get_contents( $readme_location );
|
||||
|
||||
$readme_file_details = array();
|
||||
|
||||
// Handle Recommended Plugins.
|
||||
$pattern = '/== Recommended Plugins ==\s+(.*?)(\s+==|$)/s';
|
||||
preg_match_all( $pattern, $readme_file_contents, $matches );
|
||||
$readme_file_details['recommendedPlugins'] = $matches[1][0] ?? '';
|
||||
|
||||
return $readme_file_details;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Relocate the theme to a new folder and activate the newly relocated theme.
|
||||
*/
|
||||
|
|
|
@ -165,7 +165,8 @@ class Create_Block_Theme_API {
|
|||
|
||||
function rest_get_readme_data( $request ) {
|
||||
try {
|
||||
$readme_data = Theme_Utils::get_readme_data();
|
||||
$readme_data = Theme_Readme::get_sections();
|
||||
|
||||
return new WP_REST_Response(
|
||||
array(
|
||||
'status' => 'SUCCESS',
|
||||
|
@ -201,7 +202,8 @@ class Create_Block_Theme_API {
|
|||
|
||||
function rest_create_child_theme( $request ) {
|
||||
|
||||
$theme = $this->sanitize_theme_data( $request->get_params() );
|
||||
$theme = $this->sanitize_theme_data( $request->get_params() );
|
||||
$theme['is_child_theme'] = true;
|
||||
//TODO: Handle screenshots
|
||||
$screenshot = null;
|
||||
|
||||
|
@ -281,7 +283,7 @@ class Create_Block_Theme_API {
|
|||
// Add readme.txt.
|
||||
$zip->addFromStringToTheme(
|
||||
'readme.txt',
|
||||
Theme_Readme::build_readme_txt( $theme )
|
||||
Theme_Readme::create( $theme )
|
||||
);
|
||||
|
||||
// Build style.css with new theme metadata
|
||||
|
@ -329,7 +331,7 @@ class Create_Block_Theme_API {
|
|||
// Add readme.txt.
|
||||
$zip->addFromStringToTheme(
|
||||
'readme.txt',
|
||||
Theme_Readme::build_readme_txt( $theme )
|
||||
Theme_Readme::create( $theme )
|
||||
);
|
||||
|
||||
// Build style.css with new theme metadata
|
||||
|
@ -407,16 +409,16 @@ class Create_Block_Theme_API {
|
|||
* Update the theme metadata and relocate the theme.
|
||||
*/
|
||||
function rest_update_theme( $request ) {
|
||||
$theme = $request->get_params();
|
||||
$theme = $this->sanitize_theme_data( $request->get_params() );
|
||||
|
||||
// Update the metadata of the theme in the style.css file
|
||||
$style_css = file_get_contents( get_stylesheet_directory() . '/style.css' );
|
||||
$style_css = Theme_Styles::update_style_css( $style_css, $theme );
|
||||
file_put_contents( get_stylesheet_directory() . '/style.css', $style_css );
|
||||
file_put_contents(
|
||||
get_stylesheet_directory() . '/readme.txt',
|
||||
Theme_Readme::update_readme_txt( $theme )
|
||||
);
|
||||
|
||||
$readme_content = Theme_Readme::get_content();
|
||||
$readme_content = Theme_Readme::update( $theme, $readme_content );
|
||||
file_put_contents( Theme_Readme::file_path(), $readme_content );
|
||||
|
||||
// Replace Screenshot
|
||||
if ( wp_get_theme()->get_screenshot() !== $theme['screenshot'] ) {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
>
|
||||
<testsuites>
|
||||
<testsuite name="testing">
|
||||
<directory prefix="test-" suffix=".php">./tests/</directory>
|
||||
<directory suffix=".php">./tests/</directory>
|
||||
<exclude>./tests/test-sample.php</exclude>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
|
|
@ -26,7 +26,7 @@ import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { postUpdateThemeMetadata } from '../resolvers';
|
||||
import { postUpdateThemeMetadata, fetchReadmeData } from '../resolvers';
|
||||
|
||||
const ALLOWED_SCREENSHOT_MEDIA_TYPES = [
|
||||
'image/png',
|
||||
|
@ -53,6 +53,7 @@ export const ThemeMetadataEditorModal = ( { onRequestClose } ) => {
|
|||
|
||||
useSelect( async ( select ) => {
|
||||
const themeData = select( 'core' ).getCurrentTheme();
|
||||
const readmeData = await fetchReadmeData();
|
||||
setTheme( {
|
||||
name: themeData.name.raw,
|
||||
description: themeData.description.raw,
|
||||
|
@ -62,6 +63,7 @@ export const ThemeMetadataEditorModal = ( { onRequestClose } ) => {
|
|||
author_uri: themeData.author_uri.raw,
|
||||
tags_custom: themeData.tags.rendered,
|
||||
screenshot: themeData.screenshot,
|
||||
recommended_plugins: readmeData.recommended_plugins,
|
||||
subfolder:
|
||||
themeData.stylesheet.lastIndexOf( '/' ) > 1
|
||||
? themeData.stylesheet.substring(
|
||||
|
|
|
@ -29,6 +29,30 @@ export async function fetchThemeJson() {
|
|||
}
|
||||
}
|
||||
|
||||
export async function fetchReadmeData() {
|
||||
const fetchOptions = {
|
||||
path: '/create-block-theme/v1/get-readme-data',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await apiFetch( fetchOptions );
|
||||
if ( ! response?.data || 'SUCCESS' !== response?.status ) {
|
||||
throw new Error(
|
||||
`Failed to fetch readme data: ${
|
||||
response?.message || response?.status
|
||||
}`
|
||||
);
|
||||
}
|
||||
return response?.data;
|
||||
} catch ( e ) {
|
||||
// @todo: handle error
|
||||
}
|
||||
}
|
||||
|
||||
export async function postCreateThemeVariation( name ) {
|
||||
return apiFetch( {
|
||||
path: '/create-block-theme/v1/create-variation',
|
||||
|
|
50
tests/CbtThemeReadme/addOrUpdateSection.php
Normal file
50
tests/CbtThemeReadme/addOrUpdateSection.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* Test the add_or_update_section method of the Theme_Readme class.
|
||||
*
|
||||
* @package Create_Block_Theme
|
||||
* @covers Theme_Readme::add_or_update_section
|
||||
* @group readme
|
||||
*
|
||||
*/
|
||||
class CBT_ThemeReadme_AddOrUpdateSection extends CBT_Theme_Readme_UnitTestCase {
|
||||
public function test_add_or_update_section() {
|
||||
$section_title = 'Test Section';
|
||||
$section_content = 'Test content abc123';
|
||||
|
||||
// Add a new section.
|
||||
$readme = Theme_Readme::add_or_update_section( $section_title, $section_content );
|
||||
|
||||
// Check if the section was added.
|
||||
$this->assertStringContainsString( $section_title, $readme, 'The section title is missing.' );
|
||||
$this->assertStringContainsString( $section_content, $readme, 'The section content is missing' );
|
||||
|
||||
// Update the section.
|
||||
$section_content_updated = 'Updated content xyz890';
|
||||
|
||||
$readme = Theme_Readme::add_or_update_section( $section_title, $section_content_updated );
|
||||
|
||||
// Check if the old content was updated.
|
||||
$this->assertStringNotContainsString( $section_content, $readme, 'The old content is still present.' );
|
||||
|
||||
// Check if the new content was added.
|
||||
$this->assertStringContainsString( $section_title, $readme, 'The section title is missing.' );
|
||||
$this->assertStringContainsString( $section_content_updated, $readme, 'The updated content is missing.' );
|
||||
|
||||
// Check if that the section title was added only once.
|
||||
$section_count = substr_count( $readme, $section_title );
|
||||
$this->assertEquals( 1, $section_count, 'The section title was added more than once.' );
|
||||
}
|
||||
|
||||
public function test_add_or_update_section_with_no_content() {
|
||||
$section_title = 'Test Section';
|
||||
$section_content = '';
|
||||
|
||||
// Empty section should not be added.
|
||||
$readme = Theme_Readme::add_or_update_section( $section_title, $section_content );
|
||||
$this->assertStringNotContainsString( $section_title, $readme, 'The title of an empty section should not be added.' );
|
||||
}
|
||||
}
|
64
tests/CbtThemeReadme/base.php
Normal file
64
tests/CbtThemeReadme/base.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
/**
|
||||
* Base test case for Theme Readme tests.
|
||||
*
|
||||
* @package Create_Block_Theme
|
||||
*/
|
||||
abstract class CBT_Theme_Readme_UnitTestCase extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Stores the original active theme slug in order to restore it in tear down.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $orig_active_theme_slug;
|
||||
|
||||
/**
|
||||
* Stores the custom test theme directory.
|
||||
*
|
||||
* @var string|null;
|
||||
*/
|
||||
private $test_theme_dir;
|
||||
|
||||
/**
|
||||
* Stores the original readme.txt content.
|
||||
*
|
||||
* @var string|null;
|
||||
*/
|
||||
private $orig_readme_content;
|
||||
|
||||
/**
|
||||
* Sets up tests.
|
||||
*/
|
||||
public function set_up() {
|
||||
parent::set_up();
|
||||
|
||||
// Store the original active theme.
|
||||
$this->orig_active_theme_slug = get_option( 'stylesheet' );
|
||||
|
||||
// Create a test theme directory.
|
||||
$this->test_theme_dir = DIR_TESTDATA . '/themes/';
|
||||
|
||||
// Register test theme directory.
|
||||
register_theme_directory( $this->test_theme_dir );
|
||||
|
||||
// Switch to the test theme.
|
||||
switch_theme( 'test-theme-readme' );
|
||||
|
||||
// Store the original readme.txt content.
|
||||
$this->orig_readme_content = Theme_Readme::get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down tests.
|
||||
*/
|
||||
public function tear_down() {
|
||||
parent::tear_down();
|
||||
|
||||
// Restore the original readme.txt content.
|
||||
file_put_contents( Theme_Readme::file_path(), $this->orig_readme_content );
|
||||
|
||||
// Restore the original active theme.
|
||||
switch_theme( $this->orig_active_theme_slug );
|
||||
}
|
||||
}
|
115
tests/CbtThemeReadme/create.php
Normal file
115
tests/CbtThemeReadme/create.php
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* Test the create method of the Theme_Readme class.
|
||||
*
|
||||
* @package Create_Block_Theme
|
||||
* @covers Theme_Readme::create
|
||||
* @group readme
|
||||
*/
|
||||
class CBT_ThemeReadme_Create extends CBT_Theme_Readme_UnitTestCase {
|
||||
|
||||
/**
|
||||
* @dataProvider data_test_create
|
||||
*/
|
||||
public function test_create( $data ) {
|
||||
$readme = Theme_Readme::create( $data );
|
||||
|
||||
// Removes the newlines from the readme content to make it easier to search for strings.
|
||||
$readme_without_newlines = str_replace( "\n", '', $readme );
|
||||
|
||||
$expected_name = '== ' . $data['name'] . ' ==';
|
||||
$expected_description = '== Description ==' . $data['description'];
|
||||
$expected_uri = 'Theme URI: ' . $data['uri'];
|
||||
$expected_author = 'Contributors: ' . $data['author'];
|
||||
$expected_author_uri = 'Author URI: ' . $data['author_uri'];
|
||||
$expected_wp_version = 'Tested up to: ' . $data['wp_version'] ?? get_bloginfo( 'version' );
|
||||
$expected_php_version = 'Requires PHP: ' . $data['required_php_version'];
|
||||
$expected_license = 'License: ' . $data['license'];
|
||||
$expected_license_uri = 'License URI: ' . $data['license_uri'];
|
||||
$expected_image_credits = '== Images ==' . $data['image_credits'];
|
||||
$expected_recommended_plugins = '== Recommended Plugins ==' . $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.' );
|
||||
$this->assertStringContainsString( $expected_wp_version, $readme_without_newlines, 'The expected WP version is missing.' );
|
||||
$this->assertStringContainsString( $expected_image_credits, $readme_without_newlines, 'The expected image credits are missing.' );
|
||||
$this->assertStringContainsString( $expected_recommended_plugins, $readme_without_newlines, 'The expected recommended plugins are missing.' );
|
||||
|
||||
// Assetion specific to child themes.
|
||||
if ( isset( $data['is_child_theme'] ) && $data['is_child_theme'] ) {
|
||||
$this->assertStringContainsString(
|
||||
$data['name'] . ' is a child theme of Test Readme Theme (https://example.org/themes/test-readme-theme), (C) the WordPress team, [GPLv2 or later](http://www.gnu.org/licenses/gpl-2.0.html)',
|
||||
$readme_without_newlines,
|
||||
'The expected reference to the parent theme is missing.'
|
||||
);
|
||||
}
|
||||
|
||||
// Assetion specific to child themes.
|
||||
if ( isset( $data['is_cloned_theme'] ) && $data['is_cloned_theme'] ) {
|
||||
$this->assertStringContainsString(
|
||||
$data['name'] . ' is based on Test Readme Theme (https://example.org/themes/test-readme-theme), (C) the WordPress team, [GPLv2 or later](http://www.gnu.org/licenses/gpl-2.0.html)',
|
||||
$readme_without_newlines,
|
||||
'The expected reference to the parent theme is missing.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function data_test_create() {
|
||||
return array(
|
||||
'complete data for a nomal theme' => 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' => 'The images were taken from https://example.org and have a CC0 license.',
|
||||
'recommended_plugins' => 'The theme is best used with the following plugins: Plugin 1, Plugin 2, Plugin 3.',
|
||||
),
|
||||
),
|
||||
'complete data for a child theme' => array(
|
||||
'data' => array(
|
||||
'name' => 'My Child Theme',
|
||||
'description' => 'New child theme description',
|
||||
'uri' => 'https://example.com',
|
||||
'author' => 'New theme author',
|
||||
'author_uri' => 'https://example.com/author',
|
||||
'copyright_year' => '2078',
|
||||
'wp_version' => '13.13',
|
||||
'required_php_version' => '11.0',
|
||||
'license' => 'GPLv2 or later',
|
||||
'license_uri' => 'https://www.gnu.org/licenses/gpl-2.0.html',
|
||||
'image_credits' => 'The images were taken from https://example.org and have a CC0 license.',
|
||||
'recommended_plugins' => 'The theme is best used with the following plugins: Plugin 1, Plugin 2, Plugin 3.',
|
||||
'is_child_theme' => true,
|
||||
),
|
||||
),
|
||||
'complete data for a cloned theme' => array(
|
||||
'data' => array(
|
||||
'name' => 'My Cloned Theme',
|
||||
'description' => 'New cloned theme description',
|
||||
'uri' => 'https://example.com',
|
||||
'author' => 'New theme author',
|
||||
'author_uri' => 'https://example.com/author',
|
||||
'copyright_year' => '2079',
|
||||
'wp_version' => '14.14',
|
||||
'required_php_version' => '12.0',
|
||||
'license' => 'GPLv2 or later',
|
||||
'license_uri' => 'https://www.gnu.org/licenses/gpl-2.0.html',
|
||||
'image_credits' => 'The images were taken from https://example.org and have a CC0 license.',
|
||||
'recommended_plugins' => 'The theme is best used with the following plugins: Plugin 1, Plugin 2, Plugin 3.',
|
||||
'is_cloned_theme' => true,
|
||||
),
|
||||
),
|
||||
// TODO: Add more test cases.
|
||||
);
|
||||
}
|
||||
}
|
20
tests/CbtThemeReadme/filePath.php
Normal file
20
tests/CbtThemeReadme/filePath.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* Test the file_path method of the Theme_Readme class.
|
||||
*
|
||||
* @package Create_Block_Theme
|
||||
* @covers Theme_Readme::file_path
|
||||
* @group readme
|
||||
*/
|
||||
class CBT_ThemeReadme_FilePath extends CBT_Theme_Readme_UnitTestCase {
|
||||
public function test_file_path() {
|
||||
$result = Theme_Readme::file_path();
|
||||
$expected = get_stylesheet_directory() . '/readme.txt';
|
||||
$this->assertEquals( $expected, $result );
|
||||
|
||||
$this->assertEquals( 'test-theme-readme', get_option( 'stylesheet' ) );
|
||||
}
|
||||
}
|
18
tests/CbtThemeReadme/getContent.php
Normal file
18
tests/CbtThemeReadme/getContent.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* Test the get_content method of the Theme_Readme class.
|
||||
*
|
||||
* @package Create_Block_Theme
|
||||
* @covers Theme_Readme::get_content
|
||||
* @group readme
|
||||
*/
|
||||
class CBT_ThemeReadme_GetContent extends CBT_Theme_Readme_UnitTestCase {
|
||||
public function test_get_content() {
|
||||
$result = Theme_Readme::get_content();
|
||||
$expected = file_get_contents( Theme_Readme::file_path() );
|
||||
$this->assertEquals( $expected, $result );
|
||||
}
|
||||
}
|
49
tests/CbtThemeReadme/update.php
Normal file
49
tests/CbtThemeReadme/update.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__ . '/base.php';
|
||||
|
||||
/**
|
||||
* Test the update method of the Theme_Readme class.
|
||||
*
|
||||
* @package Create_Block_Theme
|
||||
* @covers Theme_Readme::update
|
||||
* @group readme
|
||||
*/
|
||||
class CBT_ThemeReadme_Update extends CBT_Theme_Readme_UnitTestCase {
|
||||
|
||||
/**
|
||||
* @dataProvider data_test_update
|
||||
*/
|
||||
public function test_update( $data ) {
|
||||
$readme_content = Theme_Readme::get_content();
|
||||
$readme = Theme_Readme::update( $data, $readme_content );
|
||||
|
||||
// Removes the newlines from the readme content to make it easier to search for strings.
|
||||
$readme_without_newlines = str_replace( "\n", '', $readme );
|
||||
|
||||
$expected_author = 'Contributors: ' . $data['author'];
|
||||
$expected_wp_version = 'Tested up to: ' . $data['wp_version'] ?? get_bloginfo( 'version' );
|
||||
$expected_image_credits = '== Images ==' . $data['image_credits'];
|
||||
$expected_recommended_plugins = '== Recommended Plugins ==' . $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.' );
|
||||
$this->assertStringContainsString( $expected_image_credits, $readme_without_newlines, 'The expected image credits are missing.' );
|
||||
$this->assertStringContainsString( $expected_recommended_plugins, $readme_without_newlines, 'The expected recommended plugins are missing.' );
|
||||
}
|
||||
|
||||
public function data_test_update() {
|
||||
return array(
|
||||
'complete data' => array(
|
||||
'data' => array(
|
||||
'description' => 'New theme description',
|
||||
'author' => 'New theme author',
|
||||
'wp_version' => '12.12',
|
||||
'image_credits' => 'New image credits',
|
||||
'recommended_plugins' => 'New recommended plugins',
|
||||
),
|
||||
),
|
||||
// TODO: Add more test cases.
|
||||
);
|
||||
}
|
||||
}
|
54
tests/data/themes/test-theme-readme/readme.txt
Normal file
54
tests/data/themes/test-theme-readme/readme.txt
Normal file
|
@ -0,0 +1,54 @@
|
|||
=== Test Readme Theme ===
|
||||
Contributors: wordpressdotorg
|
||||
Requires at least: 6.5
|
||||
Tested up to: 6.5
|
||||
Requires PHP: 7.0
|
||||
Stable tag: 2.1
|
||||
License: GPLv2 or later
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
|
||||
== Description ==
|
||||
|
||||
Test Readme Theme is a test theme created with the sole purpose of testing the Create_Block_Theme_Readme class.
|
||||
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 1.0 =
|
||||
* Initial release
|
||||
|
||||
= 1.1 =
|
||||
* Added new feature
|
||||
|
||||
= 2.0 =
|
||||
* Added new major feature
|
||||
|
||||
= 2.1 =
|
||||
* Added new feature
|
||||
|
||||
|
||||
== Copyright ==
|
||||
|
||||
Test Readme Theme WordPress Theme, (C) 2023 WordPress.org
|
||||
Test Readme Theme is distributed under the terms of the GNU GPL.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
=== Images ===
|
||||
|
||||
License: CC0 https://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
museum.webp - https://www.rawpixel.com/image/3297419/free-photo-image-interior-hallway-architecture
|
||||
tourist-and-building.webp - https://www.rawpixel.com/image/5928004/photo-image-public-domain-hand-person
|
||||
|
||||
|
15
tests/data/themes/test-theme-readme/style.css
Normal file
15
tests/data/themes/test-theme-readme/style.css
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
Theme Name: Test Readme Theme
|
||||
Theme URI: https://example.org/themes/test-readme-theme
|
||||
Author: the WordPress team
|
||||
Author URI: https://wordpress.org
|
||||
Description: Test Readme Theme is a theme for testing the readme.txt file reading/writing capabilities of the Create Block Theme plugin.
|
||||
Requires at least: 6.4
|
||||
Tested up to: 6.4
|
||||
Requires PHP: 7.0
|
||||
Version: 1.0
|
||||
License: GNU General Public License v2 or later
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
Text Domain: testreadmetheme
|
||||
Tags: one-column, custom-colors, custom-menu, custom-logo, editor-style, featured-images, full-site-editing, block-patterns, rtl-language-support, sticky-post, threaded-comments, translation-ready, wide-blocks, block-styles, style-variations, accessibility-ready, blog, portfolio, news
|
||||
*/
|
6
tests/data/themes/test-theme-readme/theme.json
Normal file
6
tests/data/themes/test-theme-readme/theme.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/theme.json",
|
||||
"version": 2,
|
||||
"styles": {},
|
||||
"settings": {}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue