diff --git a/src/wp-admin/options.php b/src/wp-admin/options.php index b45cbb00387ce..2c16b6930a23a 100644 --- a/src/wp-admin/options.php +++ b/src/wp-admin/options.php @@ -267,16 +267,41 @@ if ( 'general' === $option_page ) { // Handle custom date/time formats. + $invalid_date_time_format = false; + if ( ! empty( $_POST['date_format'] ) && isset( $_POST['date_format_custom'] ) && '\c\u\s\t\o\m' === wp_unslash( $_POST['date_format'] ) ) { - $_POST['date_format'] = $_POST['date_format_custom']; + $date_format_custom = trim( wp_unslash( $_POST['date_format_custom'] ) ); + + if ( '' === $date_format_custom ) { + $_POST['date_format'] = get_option( 'date_format' ); + $invalid_date_time_format = true; + } else { + $_POST['date_format'] = $date_format_custom; + } } if ( ! empty( $_POST['time_format'] ) && isset( $_POST['time_format_custom'] ) && '\c\u\s\t\o\m' === wp_unslash( $_POST['time_format'] ) ) { - $_POST['time_format'] = $_POST['time_format_custom']; + $time_format_custom = trim( wp_unslash( $_POST['time_format_custom'] ) ); + + if ( '' === $time_format_custom ) { + $_POST['time_format'] = get_option( 'time_format' ); + $invalid_date_time_format = true; + } else { + $_POST['time_format'] = $time_format_custom; + } + } + + if ( $invalid_date_time_format ) { + add_settings_error( + 'general', + 'invalid_date_time_format', + __( 'Please configure a valid date and time format.' ), + 'error' + ); } // Map UTC+- timezones to gmt_offsets and set timezone_string to empty. diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index 498d676f5c20f..761306ff90c0c 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -4957,6 +4957,10 @@ function sanitize_option( $option, $value ) { } else { $value = strip_tags( $value ); $value = wp_kses_data( $value ); + + if ( ( 'date_format' === $option || 'time_format' === $option ) && '' === $value ) { + $error = __( 'Please configure a valid date and time format.' ); + } } break; diff --git a/tests/phpunit/tests/option/sanitizeOption.php b/tests/phpunit/tests/option/sanitizeOption.php index 68597b8acdaea..deaf2c170721a 100644 --- a/tests/phpunit/tests/option/sanitizeOption.php +++ b/tests/phpunit/tests/option/sanitizeOption.php @@ -175,4 +175,43 @@ public function data_sanitize_option_permalink_structure() { array( new WP_Error( 'wpdb_get_table_charset_failure' ), false, false ), // @ticket 53986 ); } + + /** + * @ticket 65281 + * + * @covers ::sanitize_option + * @covers ::get_settings_errors + * + * @dataProvider data_sanitize_option_date_time_format + */ + public function test_sanitize_option_date_time_format( $option_name, $provided, $expected, $valid ) { + global $wp_settings_errors; + + $old_wp_settings_errors = (array) $wp_settings_errors; + + update_option( $option_name, $expected ); + + $actual = sanitize_option( $option_name, $provided ); + $errors = get_settings_errors( $option_name ); + + $wp_settings_errors = $old_wp_settings_errors; + + if ( $valid ) { + $this->assertEmpty( $errors ); + } else { + $this->assertNotEmpty( $errors ); + $this->assertSame( 'invalid_' . $option_name, $errors[0]['code'] ); + } + + $this->assertSame( $expected, $actual ); + } + + public function data_sanitize_option_date_time_format() { + return array( + array( 'date_format', 'F j, Y', 'F j, Y', true ), + array( 'date_format', '', 'Y-m-d', false ), + array( 'time_format', 'g:i a', 'g:i a', true ), + array( 'time_format', '', 'g:i a', false ), + ); + } }