Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 43 additions & 11 deletions src/wp-admin/network/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,17 @@
}
}

// Ensure the network title (site_name) is not left empty.
$network_title_error = '';
if ( isset( $_POST['site_name'] ) ) {
$site_name = wp_unslash( $_POST['site_name'] );

if ( ! is_scalar( $site_name ) || '' === trim( (string) $site_name ) ) {
unset( $_POST['site_name'] );
$network_title_error = __( 'The network title cannot be empty. Please enter a title for your network.' );
}
}

foreach ( $options as $option_name ) {
if ( ! isset( $_POST[ $option_name ] ) ) {
continue;
Expand All @@ -131,21 +142,42 @@
*/
do_action( 'update_wpmu_options' );

wp_redirect( add_query_arg( 'updated', 'true', network_admin_url( 'settings.php' ) ) );
if ( $network_title_error ) {
set_transient( 'network_settings_errors', array( $network_title_error ), 30 );
wp_redirect( add_query_arg( 'updated', 'error', network_admin_url( 'settings.php' ) ) );
} else {
wp_redirect( add_query_arg( 'updated', 'true', network_admin_url( 'settings.php' ) ) );
}
exit;
}

require_once ABSPATH . 'wp-admin/admin-header.php';

if ( isset( $_GET['updated'] ) ) {
wp_admin_notice(
__( 'Settings saved.' ),
array(
'type' => 'success',
'dismissible' => true,
'id' => 'message',
)
);
if ( 'true' === $_GET['updated'] ) {
wp_admin_notice(
__( 'Settings saved.' ),
array(
'type' => 'success',
'dismissible' => true,
'id' => 'message',
)
);
} elseif ( 'error' === $_GET['updated'] ) {
$network_settings_errors = get_transient( 'network_settings_errors' );
delete_transient( 'network_settings_errors' );

$error_messages = is_array( $network_settings_errors ) ? $network_settings_errors : array( __( 'Some settings could not be saved.' ) );
foreach ( $error_messages as $error_message ) {
wp_admin_notice(
$error_message,
array(
'type' => 'error',
'dismissible' => true,
)
);
}
}
}
?>

Expand All @@ -155,10 +187,10 @@
<?php wp_nonce_field( 'siteoptions' ); ?>
<h2 id="wp-settings-section-operational-settings"><?php _e( 'Operational Settings' ); ?></h2>
<table class="form-table" role="presentation">
<tr>
<tr class="form-field form-required">
<th scope="row"><label for="site_name"><?php _e( 'Network Title' ); ?></label></th>
<td>
<input name="site_name" type="text" id="site_name" class="regular-text" value="<?php echo esc_attr( get_network()->site_name ); ?>" />
<input name="site_name" type="text" id="site_name" class="regular-text" value="<?php echo esc_attr( get_network()->site_name ); ?>" required aria-required="true" />
</td>
</tr>

Expand Down
61 changes: 51 additions & 10 deletions src/wp-admin/network/site-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,25 @@
do_action( 'wpmu_update_blog_options', $id );

restore_current_blog();

$update = 'updated';

/*
* sanitize_option() rejects invalid values (such as an empty, required
* Site Title) by registering a settings error and keeping the stored value.
* Carry those errors across the redirect so an error notice can be shown
* instead of a success message.
*/
$settings_errors = get_settings_errors();
if ( ! empty( $settings_errors ) ) {
set_transient( 'settings_errors', $settings_errors, 30 );
$update = 'not-updated';
}

wp_redirect(
add_query_arg(
array(
'update' => 'updated',
'update' => $update,
'id' => $id,
),
'site-settings.php'
Expand All @@ -72,10 +87,25 @@
exit;
}

$messages = array();
$error_messages = array();

if ( isset( $_GET['update'] ) ) {
$messages = array();
if ( 'updated' === $_GET['update'] ) {
$messages[] = __( 'Site options updated.' );
} elseif ( 'not-updated' === $_GET['update'] ) {
$settings_errors = get_transient( 'settings_errors' );
delete_transient( 'settings_errors' );

if ( is_array( $settings_errors ) ) {
foreach ( $settings_errors as $settings_error ) {
$error_messages[] = $settings_error['message'];
}
}

if ( empty( $error_messages ) ) {
$error_messages[] = __( 'Some settings could not be saved.' );
}
}
}

Expand Down Expand Up @@ -103,16 +133,27 @@
)
);

if ( ! empty( $error_messages ) ) {
foreach ( $error_messages as $msg ) {
wp_admin_notice(
$msg,
array(
'type' => 'error',
'dismissible' => true,
)
);
}
}

if ( ! empty( $messages ) ) {
$notice_args = array(
'type' => 'success',
'dismissible' => true,
'id' => 'message',
wp_admin_notice(
$messages[0],
array(
'type' => 'success',
'dismissible' => true,
'id' => 'message',
)
);

foreach ( $messages as $msg ) {
wp_admin_notice( $msg, $notice_args );
}
}
?>
<form method="post" action="site-settings.php?action=update-site">
Expand Down
4 changes: 2 additions & 2 deletions src/wp-admin/options-general.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@

<table class="form-table" role="presentation">

<tr>
<tr class="form-field form-required">
<th scope="row"><label for="blogname"><?php _e( 'Site Title' ); ?></label></th>
<td><input name="blogname" type="text" id="blogname" value="<?php form_option( 'blogname' ); ?>" class="regular-text" /></td>
<td><input name="blogname" type="text" id="blogname" value="<?php form_option( 'blogname' ); ?>" class="regular-text" required aria-required="true" /></td>
</tr>

<?php
Expand Down
5 changes: 5 additions & 0 deletions src/wp-includes/formatting.php
Original file line number Diff line number Diff line change
Expand Up @@ -4996,6 +4996,11 @@ function sanitize_option( $option, $value ) {
$error = $value->get_error_message();
} else {
$value = esc_html( $value );

// 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.' );
}
Comment thread
himanshupathak95 marked this conversation as resolved.
}
break;

Expand Down
6 changes: 5 additions & 1 deletion src/wp-includes/option.php
Original file line number Diff line number Diff line change
Expand Up @@ -2746,7 +2746,11 @@ function register_initial_settings() {
'blogname',
array(
'show_in_rest' => array(
'name' => 'title',
'name' => 'title',
'schema' => array(
'minLength' => 1,
'pattern' => '\S',
),
),
'type' => 'string',
'label' => __( 'Title' ),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,14 @@ public function update_item( $request ) {
);
}

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 )
);
}

delete_option( $args['option_name'] );
} else {
update_option( $args['option_name'], $request[ $name ] );
Expand Down
30 changes: 30 additions & 0 deletions tests/phpunit/tests/rest-api/rest-settings-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,36 @@ public function test_update_item_with_invalid_type() {
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
}

/**
* @ticket 65718
*
* @dataProvider data_update_item_with_invalid_title
*/
public function test_update_item_with_invalid_title( $invalid_title ) {
wp_set_current_user( self::$administrator );
$original_title = get_option( 'blogname' );

$request = new WP_REST_Request( 'PUT', '/wp/v2/settings' );
$request->set_param( 'title', $invalid_title );
$response = rest_get_server()->dispatch( $request );

$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
$this->assertSame( $original_title, get_option( 'blogname' ) );
}

/**
* Data provider.
*
* @return array[]
*/
public function data_update_item_with_invalid_title() {
return array(
'empty string' => array( '' ),
'whitespace only' => array( ' ' ),
'null' => array( null ),
);
}

public function test_update_item_with_integer() {
wp_set_current_user( self::$administrator );
$request = new WP_REST_Request( 'PUT', '/wp/v2/settings' );
Expand Down
2 changes: 2 additions & 0 deletions tests/qunit/fixtures/wp-api-generated.js
Original file line number Diff line number Diff line change
Expand Up @@ -11134,6 +11134,8 @@ mockedApiResponse.Schema = {
"title": "Title",
"description": "Site title.",
"type": "string",
"minLength": 1,
"pattern": "\\S",
"required": false
},
"description": {
Expand Down
Loading