Adds minimum WordPress version to theme metadata (#715)

* Add a field for required wordpress version.

* Add a minimum required version if none exists.

* Sanitize the requires_wp attribute.

* Use SelectControl instead of TextControl and rename attribute to requires_wp.

* Update includes/create-theme/theme-styles.php

Co-authored-by: Grant Kinney <creativecoder@users.noreply.github.com>

* Try generating the minimum versions instead.

* Ensure Required WP version is updated when readme is updated.

* Use current wordpress version if none is provided.

* Use a dynamic value for Requires at least when theme readme and style.css are created.

* Make variable names consistent.

* Check for empty string and use current wordpress version as fallback.

* Add minimum version to additional metadata panel.

---------

Co-authored-by: Grant Kinney <creativecoder@users.noreply.github.com>
This commit is contained in:
Jeff Ong 2024-09-20 12:33:50 -04:00 committed by GitHub
parent fbf99339d2
commit cdede9a46c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 89 additions and 4 deletions

View file

@ -466,6 +466,7 @@ class CBT_Theme_API {
$sanitized_theme['subfolder'] = sanitize_text_field( $theme['subfolder'] ?? '' );
$sanitized_theme['version'] = sanitize_text_field( $theme['version'] ?? '' );
$sanitized_theme['screenshot'] = sanitize_text_field( $theme['screenshot'] ?? '' );
$sanitized_theme['requires_wp'] = sanitize_text_field( $theme['requires_wp'] ?? '' );
$sanitized_theme['recommended_plugins'] = sanitize_textarea_field( $theme['recommended_plugins'] ?? '' );
$sanitized_theme['font_credits'] = sanitize_textarea_field( $theme['font_credits'] ?? '' );
$sanitized_theme['image_credits'] = sanitize_textarea_field( $theme['image_credits'] ?? '' );

View file

@ -38,6 +38,13 @@ class CBT_Editor_Tools {
'create-block-theme-slot-fill',
);
global $wp_version;
wp_add_inline_script(
'create-block-theme-slot-fill',
'const WP_VERSION = "' . $wp_version . '";',
'before'
);
// Enable localization in the plugin sidebar.
wp_set_script_translations( 'create-block-theme-slot-fill', 'create-block-theme' );
}

View file

@ -50,6 +50,7 @@ class CBT_Theme_Readme {
$author_uri = $theme['author_uri'] ?? '';
$copy_year = $theme['copyright_year'] ?? gmdate( 'Y' );
$wp_version = $theme['wp_version'] ?? CBT_Theme_Utils::get_current_wordpress_version();
$requires_wp = ( '' === $theme['requires_wp'] ) ? CBT_Theme_Utils::get_current_wordpress_version() : $theme['requires_wp'];
$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';
@ -67,7 +68,7 @@ class CBT_Theme_Readme {
// Adds the Theme section.
$theme_section_content = "
Contributors: {$author}
Requires at least: 6.0
Requires at least: {$requires_wp}
Tested up to: {$wp_version}
Requires PHP: {$required_php_version}
License: {$license}
@ -210,6 +211,7 @@ GNU General Public License for more details.
$description = $theme['description'] ?? '';
$author = $theme['author'] ?? '';
$wp_version = $theme['wp_version'] ?? CBT_Theme_Utils::get_current_wordpress_version();
$requires_wp = ( '' === $theme['requires_wp'] ) ? CBT_Theme_Utils::get_current_wordpress_version() : $theme['requires_wp'];
$image_credits = $theme['image_credits'] ?? '';
$recommended_plugins = $theme['recommended_plugins'] ?? '';
$font_credits = $theme['font_credits'] ?? '';
@ -220,6 +222,9 @@ GNU General Public License for more details.
// Update Author/Contributors.
$readme_content = self::add_or_update_prop( 'Contributors', $author, $readme_content );
// Update Required WordPress version.
$readme_content = self::add_or_update_prop( 'Requires at least', $requires_wp, $readme_content );
// Update "Tested up to" version.
$readme_content = self::add_or_update_prop( 'Tested up to', $wp_version, $readme_content );

View file

@ -25,7 +25,7 @@ class CBT_Theme_Styles {
$author = stripslashes( $theme['author'] );
$author_uri = $theme['author_uri'];
$wp_version = CBT_Theme_Utils::get_current_wordpress_version();
$wp_min = $current_theme->get( 'RequiresWP' );
$requires_wp = ( '' === $theme['requires_wp'] ) ? CBT_Theme_Utils::get_current_wordpress_version() : $theme['requires_wp'];
$version = $theme['version'];
$requires_php = $current_theme->get( 'RequiresPHP' );
$text_domain = $theme['slug'];
@ -46,7 +46,7 @@ Theme URI: {$uri}
Author: {$author}
Author URI: {$author_uri}
Description: {$description}
Requires at least: {$wp_min}
Requires at least: {$requires_wp}
Tested up to: {$wp_version}
Requires PHP: {$requires_php}
Version: {$version}
@ -67,6 +67,7 @@ Tags: {$tags}
$uri = $theme['uri'];
$author = stripslashes( $theme['author'] );
$author_uri = $theme['author_uri'];
$requires_wp = ( '' === $theme['requires_wp'] ) ? CBT_Theme_Utils::get_current_wordpress_version() : $theme['requires_wp'];
$wp_version = CBT_Theme_Utils::get_current_wordpress_version();
$text_domain = sanitize_title( $name );
if ( isset( $theme['template'] ) ) {
@ -85,7 +86,7 @@ Theme URI: {$uri}
Author: {$author}
Author URI: {$author_uri}
Description: {$description}
Requires at least: 6.0
Requires at least: {$requires_wp}
Tested up to: {$wp_version}
Requires PHP: 5.7
Version: {$version}

View file

@ -14,6 +14,7 @@ import {
__experimentalText as Text,
PanelBody,
Button,
SelectControl,
TextControl,
TextareaControl,
} from '@wordpress/components';
@ -28,6 +29,9 @@ import {
createClonedTheme,
createChildTheme,
} from '../resolvers';
import { generateWpVersions } from '../utils/generate-versions';
const WP_MINIMUM_VERSIONS = generateWpVersions( WP_VERSION ); // eslint-disable-line no-undef
export const CreateThemePanel = ( { createType } ) => {
const { createErrorNotice } = useDispatch( noticesStore );
@ -47,6 +51,7 @@ export const CreateThemePanel = ( { createType } ) => {
author: '',
author_uri: '',
tags_custom: '',
requires_wp: '',
subfolder,
} );
@ -195,6 +200,20 @@ export const CreateThemePanel = ( { createType } ) => {
'create-block-theme'
) }
/>
<SelectControl
label={ __(
'Minimum WordPress version',
'create-block-theme'
) }
value={ theme.requires_wp }
options={ WP_MINIMUM_VERSIONS.map( ( version ) => ( {
label: version,
value: version,
} ) ) }
onChange={ ( value ) => {
setTheme( { ...theme, requires_wp: value } );
} }
/>
</details>
<br />
{ createType === 'createClone' && (

View file

@ -18,6 +18,7 @@ import {
FormTokenField,
Modal,
Button,
SelectControl,
TextControl,
TextareaControl,
ExternalLink,
@ -29,6 +30,7 @@ import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
*/
import { postUpdateThemeMetadata, fetchReadmeData } from '../resolvers';
import { getFontsCreditsText } from '../utils/fonts';
import { generateWpVersions } from '../utils/generate-versions';
const ALLOWED_SCREENSHOT_MEDIA_TYPES = [
'image/png',
@ -39,12 +41,15 @@ const ALLOWED_SCREENSHOT_MEDIA_TYPES = [
'image/avif',
];
const WP_MINIMUM_VERSIONS = generateWpVersions( WP_VERSION ); // eslint-disable-line no-undef
export const ThemeMetadataEditorModal = ( { onRequestClose } ) => {
const [ theme, setTheme ] = useState( {
name: '',
description: '',
uri: '',
version: '',
requires_wp: '',
author: '',
author_uri: '',
tags_custom: '',
@ -65,6 +70,7 @@ export const ThemeMetadataEditorModal = ( { onRequestClose } ) => {
description: themeData.description.raw,
uri: themeData.theme_uri.raw,
version: themeData.version,
requires_wp: themeData.requires_wp,
author: themeData.author.raw,
author_uri: themeData.author_uri.raw,
tags_custom: themeData.tags.rendered,
@ -212,6 +218,20 @@ export const ThemeMetadataEditorModal = ( { onRequestClose } ) => {
'create-block-theme'
) }
/>
<SelectControl
label={ __(
'Minimum WordPress version',
'create-block-theme'
) }
value={ theme.requires_wp }
options={ WP_MINIMUM_VERSIONS.map( ( version ) => ( {
label: version,
value: version,
} ) ) }
onChange={ ( value ) => {
setTheme( { ...theme, requires_wp: value } );
} }
/>
<FormTokenField
label={ __( 'Theme tags', 'create-block-theme' ) }
value={

View file

@ -0,0 +1,21 @@
export function generateWpVersions( versionString ) {
const version = versionString.split( '-' )[ 0 ];
let [ major, minor ] = version.split( '.' ).slice( 0, 2 ).map( Number );
const versions = [];
// Iterate through the versions from current to 5.9
while ( major > 5 || ( major === 5 && minor >= 9 ) ) {
versions.push( `${ major }.${ minor }` );
// Decrement minor version
if ( minor === 0 ) {
minor = 9; // Wrap around if minor is 0, decrement the major version
major--;
} else {
minor--;
}
}
return versions;
}

View file

@ -28,6 +28,7 @@ class CBT_ThemeReadme_Create extends CBT_Theme_Readme_UnitTestCase {
$expected_uri = 'Theme URI: ' . $data['uri'];
$expected_author = 'Contributors: ' . $data['author'];
$expected_author_uri = 'Author URI: ' . $data['author_uri'];
$expected_requires_wp = 'Requires at least: ' . $data['requires_wp'] ?? CBT_Theme_Utils::get_current_wordpress_version();
$expected_wp_version = 'Tested up to: ' . $data['wp_version'] ?? CBT_Theme_Utils::get_current_wordpress_version();
$expected_php_version = 'Requires PHP: ' . $data['required_php_version'];
$expected_license = 'License: ' . $data['license'];
@ -46,6 +47,7 @@ class CBT_ThemeReadme_Create extends CBT_Theme_Readme_UnitTestCase {
$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_requires_wp, $readme_without_newlines, 'The expected Requires at least version is missing.' );
$this->assertStringContainsString( $expected_wp_version, $readme_without_newlines, 'The expected WP version is missing.' );
$this->assertStringContainsString( $expected_recommended_plugins, $readme_without_newlines, 'The expected recommended plugins are missing.' );
@ -94,6 +96,7 @@ class CBT_ThemeReadme_Create extends CBT_Theme_Readme_UnitTestCase {
'author_uri' => 'https://example.com/author',
'copyright_year' => '2077',
'wp_version' => '12.12',
'requires_wp' => '12.12',
'required_php_version' => '10.0',
'license' => 'GPLv2 or later',
'license_uri' => 'https://www.gnu.org/licenses/gpl-2.0.html',
@ -110,6 +113,7 @@ class CBT_ThemeReadme_Create extends CBT_Theme_Readme_UnitTestCase {
'author' => 'New theme author',
'author_uri' => 'https://example.com/author',
'copyright_year' => '2078',
'requires_wp' => '12.12',
'wp_version' => '13.13',
'required_php_version' => '11.0',
'license' => 'GPLv2 or later',
@ -128,6 +132,7 @@ class CBT_ThemeReadme_Create extends CBT_Theme_Readme_UnitTestCase {
'author' => 'New theme author',
'author_uri' => 'https://example.com/author',
'copyright_year' => '2079',
'requires_wp' => '12.12',
'wp_version' => '14.14',
'required_php_version' => '12.0',
'license' => 'GPLv2 or later',
@ -146,6 +151,7 @@ class CBT_ThemeReadme_Create extends CBT_Theme_Readme_UnitTestCase {
'author' => 'New theme author',
'author_uri' => 'https://example.com/author',
'copyright_year' => '2077',
'requires_wp' => '12.12',
'wp_version' => '12.12',
'required_php_version' => '10.0',
'license' => 'GPLv2 or later',
@ -162,6 +168,7 @@ class CBT_ThemeReadme_Create extends CBT_Theme_Readme_UnitTestCase {
'author' => 'New theme author',
'author_uri' => 'https://example.com/author',
'copyright_year' => '2077',
'requires_wp' => '12.12',
'wp_version' => '12.12',
'required_php_version' => '10.0',
'license' => 'GPLv2 or later',
@ -182,6 +189,7 @@ class CBT_ThemeReadme_Create extends CBT_Theme_Readme_UnitTestCase {
'author' => 'New theme author',
'author_uri' => 'https://example.com/author',
'copyright_year' => '2077',
'requires_wp' => '12.12',
'wp_version' => '12.12',
'required_php_version' => '10.0',
'license' => 'GPLv2 or later',

View file

@ -48,6 +48,7 @@ class CBT_ThemeReadme_Update extends CBT_Theme_Readme_UnitTestCase {
'description' => 'New theme description',
'author' => 'New theme author',
'wp_version' => '12.12',
'requires_wp' => '',
'image_credits' => 'New image credits',
'recommended_plugins' => 'New recommended plugins',
'font_credits' => 'Example font credits text',
@ -58,6 +59,7 @@ class CBT_ThemeReadme_Update extends CBT_Theme_Readme_UnitTestCase {
'description' => 'New theme description',
'author' => 'New theme author',
'wp_version' => '12.12',
'requires_wp' => '',
'image_credits' => 'New image credits',
'recommended_plugins' => 'New recommended plugins',
),
@ -71,6 +73,7 @@ class CBT_ThemeReadme_Update extends CBT_Theme_Readme_UnitTestCase {
'description' => 'New theme description',
'author' => 'New theme author',
'wp_version' => '12.12',
'requires_wp' => '',
'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",