Enforce non-empty constraints for Site Title and Network Title across all contexts - #12706
Conversation
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
There was a problem hiding this comment.
Pull request overview
This PR prevents administrators from saving an empty Site Title (blogname) or Network Title (site_name) through the relevant admin screens, aligning edit behavior with creation-time requirements (notably in Multisite).
Changes:
- Add server-side validation in
sanitize_option()to reject empty/whitespace-onlyblognameupdates (retaining the stored value and registering a settings error). - Mark Site Title / Network Title inputs as required in the General Settings and Network Settings forms.
- In Multisite site settings, carry
sanitize_option()settings errors across the redirect to display an error notice instead of a success message.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/wp-includes/formatting.php | Rejects empty Site Title updates during option sanitization and registers a settings error. |
| src/wp-admin/options-general.php | Marks “Site Title” as a required field in the General Settings UI. |
| src/wp-admin/network/site-settings.php | Persists settings errors across redirect and displays error notices when site options aren’t saved. |
| src/wp-admin/network/settings.php | Prevents saving an empty Network Title, shows an error notice, and marks the field as required. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/wp-includes/formatting.php:5003
- This change introduces new behavior for
sanitize_option( 'blogname', ... )(rejecting empty/whitespace-only values and registering a settings error), but there’s no PHPUnit coverage asserting the new validation and the expectedget_settings_errors( 'blogname' )result. Adding a unit test will help prevent regressions in both the returned value (should remain the previously stored option) and the presence/content of the settings error.
// The site title (blogname) cannot be empty.
if ( 'blogname' === $option && '' === trim( $value ) ) {
$error = __( 'The site title cannot be empty. Please enter a title for your site.' );
}
…in REST API settings controller
4306da9 to
e9dcd79
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (5)
src/wp-includes/formatting.php:5003
- The new
blognameempty/whitespace rejection insanitize_option()is security-/UX-critical behavior and should be covered by PHPUnit tests. There’s already a dedicatedsanitize_option()test suite (tests/phpunit/tests/option/sanitizeOption.php) that includesblognamecases; it should be extended with cases like''and' 'to assert the stored value is preserved and a settings error is registered.
// The site title (blogname) cannot be empty.
if ( 'blogname' === $option && '' === trim( $value ) ) {
$error = __( 'The site title cannot be empty. Please enter a title for your site.' );
}
src/wp-admin/network/site-settings.php:98
- This read/delete needs to use the same site-settings-specific transient key as the save path above; otherwise it will continue to clash with the Settings API’s global
settings_errorstransient and can display unrelated errors.
$settings_errors = get_transient( 'settings_errors' );
delete_transient( 'settings_errors' );
src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php:206
- The custom
rest_invalid_paramerror for anullsite title doesn’t includeparamsdata, so API clients can’t reliably associate the error with thetitleparameter. Otherrest_invalid_paramresponses (e.g. request arg validation) include aparamsmap; matching that shape improves consistency and client UX.
return new WP_Error(
'rest_invalid_param',
__( 'The site title cannot be empty. Please enter a title for your site.' ),
array( 'status' => 400 )
);
src/wp-includes/formatting.php:5003
- This adds an empty-title guard for
blogname, butupdate_network_option()also routes network options throughsanitize_option();site_name(Network Title) can still be set to an empty/whitespace value via programmatic updates (or other admin flows) because it isn’t validated here. To actually enforce “Network Title cannot be empty” across contexts,sanitize_option()should reject emptysite_nametoo (with a dedicated message), similar toblogname.
// The site title (blogname) cannot be empty.
if ( 'blogname' === $option && '' === trim( $value ) ) {
$error = __( 'The site title cannot be empty. Please enter a title for your site.' );
}
src/wp-admin/network/site-settings.php:74
- Using the generic
settings_errorstransient here can collide with the Settings API’s own redirect flow (e.g.wp-admin/options.phpalso writessettings_errors). If another settings save happens in a different tab between redirect and load, this page could show the wrong errors (or none). Consider using a site-settings-specific transient key (optionally including the site ID and user ID) and update the matchingget_transient()/delete_transient()calls below.
This issue also appears on line 97 of the same file.
set_transient( 'settings_errors', $settings_errors, 30 );
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
src/wp-includes/formatting.php:5003
- This change adds a new rejection path for empty/whitespace
blognameinsanitize_option(), but there is currently no PHPUnit coverage for this behavior (the existingTests_Option_SanitizeOptiononly covers validblognamecases). Adding tests would help prevent regressions forupdate_option( 'blogname', '' )and whitespace-only values.
// The site title (blogname) cannot be empty.
if ( 'blogname' === $option && '' === trim( $value ) ) {
$error = __( 'The site title cannot be empty. Please enter a title for your site.' );
}
src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php:207
- The new
rest_invalid_paramWP_Error forblognamenull is missing the usualparamsfield (used elsewhere for invalid parameter responses). Adding it makes the error response more consistent and lets clients map the message to thetitleparam.
if ( 'blogname' === $args['option_name'] ) {
return new WP_Error(
'rest_invalid_param',
__( 'The site title cannot be empty. Please enter a title for your site.' ),
array( 'status' => 400 )
);
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Trac ticket: https://core.trac.wordpress.org/ticket/65718
The site title (
blogname) is enforced as required during multisite site creation, but could be cleared to an empty string via admin paths or the REST API after creation. Also resolves a related issue where the Network Title (site_name) could be saved empty.minLength: 1andpattern: \Sto thetitle(blogname) schema inregister_initial_settings()so that empty submissions via the block editor correctly return a 400 Bad Request validation error rather than silently failing.WP_REST_Settings_Controller::update_item()to preventtitle: nullfrom mapping todelete_option('blogname'), which bypassed option sanitization completely.blognamewithinsanitize_option()to reject empty values during directupdate_option()or CLI calls, registering a standard settings error.site_namenetwork option before the save loop inwp-admin/network/settings.php, and hardened the payload check against non-scalar inputs.