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
24 changes: 11 additions & 13 deletions src/wp-includes/abilities/class-wp-abilities-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,14 @@
/**
* Core class used to register settings-related abilities.
*
* Provides the read-only `core/settings-get` ability and the shared building blocks
* (exposed-settings discovery and schema generation) that are intended to also back a
* future write-oriented `core/settings-update` ability.
* Provides the read-only `core/settings-get` ability. Its schemas and results use
* the same set of settings, selected when the ability is registered.
*
* Unlike the other core abilities, which are self-contained closures registered directly
* in wp_register_core_abilities(), the settings abilities live in a dedicated class
* because they share state: the set of exposed settings is computed once at registration
* and reused by the input schema, the output schema, and the execute callback, and the
* same helpers are meant to be shared with the future write ability.
*
* The exposed settings are captured when the ability registers, the first time the abilities
* registry is used in a request. Settings registered later in that request are not exposed.
* Core registers its own settings in time, see _wp_register_initial_settings_for_abilities().
* Abilities are registered on `wp_abilities_api_init`, when the abilities registry
* is first used after `init`. Core settings and plugin settings with `show_in_abilities`
* must be registered on `init` or earlier so they are available at that point.
* Filters that change setting arguments must be attached before the settings are
* registered. Later changes are not reflected in an already registered ability.
*
* This class is part of WordPress' internal implementation of the core abilities and is
* not part of the public API. It may be changed or removed at any time without notice.
Expand All @@ -45,7 +40,10 @@ final class WP_Abilities_Settings {
private const CATEGORY = 'site';

/**
* Settings exposed through the Abilities API, computed once at registration.
* Settings available to the ability when it was registered.
*
* Keeping this set unchanged ensures that the ability returns only settings
* described by its schemas.
*
* @since 7.2.0
* @var array<string, array{option: string, group: string, schema: array<string, mixed>}>
Expand Down
4 changes: 2 additions & 2 deletions src/wp-includes/default-filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -549,14 +549,14 @@
// REST API actions.
add_action( 'init', 'rest_api_init' );
add_action( 'rest_api_init', 'rest_api_default_filters', 10, 1 );
add_action( 'rest_api_init', 'register_initial_settings', 10 );
// Register settings before either the REST API or the Abilities API needs their metadata.
add_action( 'init', 'register_initial_settings', 10 );
add_filter( 'rest_pre_update_setting', 'rest_restrict_privacy_policy_page_setting_update', 10, 2 );
add_action( 'rest_api_init', 'create_initial_rest_routes', 99 );
add_action( 'parse_request', 'rest_api_loaded' );

// Abilities API.
add_action( 'wp_abilities_api_categories_init', 'wp_register_core_ability_categories' );
add_action( 'wp_abilities_api_init', '_wp_register_initial_settings_for_abilities', 1 );
add_action( 'wp_abilities_api_init', 'wp_register_core_abilities' );

// Connectors API.
Expand Down
7 changes: 6 additions & 1 deletion src/wp-includes/l10n.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,12 @@ function get_locale() {
if ( wp_installing() ) {
$ms_locale = get_site_option( 'WPLANG' );
} else {
$ms_locale = get_option( 'WPLANG' );
/*
* A missing site language must fall back to the network language. An explicit
* false default prevents the registered WPLANG default from hiding that case
* when the locale is calculated after core settings have been registered.
*/
$ms_locale = get_option( 'WPLANG', false );
if ( false === $ms_locale ) {
$ms_locale = get_site_option( 'WPLANG' );
}
Expand Down
64 changes: 31 additions & 33 deletions src/wp-includes/option.php
Original file line number Diff line number Diff line change
Expand Up @@ -2738,15 +2738,23 @@ function set_site_transient( $transient, $value, $expiration = 0 ) {
/**
* Registers default settings available in WordPress.
*
* The settings registered here are primarily useful for the REST API and the
* Abilities API, so this does not encompass all settings available in WordPress.
* Registers metadata for core settings used by the REST API and the Abilities API.
* This runs on `init` so the metadata is available whichever API is used first.
* It does not cover every WordPress setting or change which options admin forms can save.
*
* @since 4.7.0
* @since 6.0.1 The `show_on_front`, `page_on_front`, and `page_for_posts` options were added.
* @since 7.2.0 The `wp_page_for_privacy_policy` option was registered, exposed as `page_for_privacy_policy`.
* @since 7.2.0 Added `show_in_abilities` support for the exposed settings.
* Registration runs on `init` without changing the admin allowed-options lists.
*
* @global array $new_allowed_options Additional options that admin settings forms may save.
*/
function register_initial_settings() {
global $new_allowed_options;

$allowed_options = $new_allowed_options;

register_setting(
'general',
'blogname',
Expand Down Expand Up @@ -2996,45 +3004,23 @@ function register_initial_settings() {
'description' => __( 'Allow people to submit comments on new posts.' ),
)
);
}

/**
* Registers the default settings when the Abilities API initializes.
*
* The default settings are registered on `rest_api_init`, which fires lazily and
* independently of `wp_abilities_api_init`: on cron, WP-CLI, or any request where
* abilities are used before the REST server loads, it may not have fired, or may be
* mid-fire at a priority before register_initial_settings() runs. This makes sure the
* settings exist before the core abilities read them. Registering them again later on
* `rest_api_init` is harmless.
*
* @since 7.2.0
* @access private
*
* @global array $new_allowed_options
*/
function _wp_register_initial_settings_for_abilities(): void {
global $new_allowed_options;

if ( did_action( 'rest_api_init' ) && ! doing_action( 'rest_api_init' ) ) {
return;
}

$allowed_options = $new_allowed_options;

register_initial_settings();

/*
* Registering a setting also allows it on the options screen of its group. Restore
* the list, so saving Settings > General does not try to save `admin_email`, which
* that screen sends as `new_admin_email`.
* Core settings screens define which options their forms may save. Registering metadata
* must preserve those lists. For example, the email form submits new_admin_email so that
* the address can be confirmed before admin_email changes.
*/
$new_allowed_options = $allowed_options;
}

/**
* Registers a setting and its data.
*
* Settings exposed through the Abilities API must be registered on `init` or earlier.
* Attach filters that change setting arguments before registering the setting.
* Abilities may read the settings as soon as `init` finishes, so later registrations
* trigger an incorrect usage notice but still register the setting for other consumers.
*
* @since 2.7.0
* @since 3.0.0 The `misc` option group was deprecated.
* @since 3.5.0 The `privacy` option group was deprecated.
Expand Down Expand Up @@ -3068,7 +3054,7 @@ function _wp_register_initial_settings_for_abilities(): void {
* When true, it uses the same name and schema as `$show_in_rest`.
* It may also be an array with 'name' and 'schema' keys, used instead of
* `$show_in_rest` rather than merged with it.
* Settings registered after abilities initialize are not exposed.
* Register the setting on `init` or earlier.
* @type mixed $default Default value when calling `get_option()`.
* }
*/
Expand Down Expand Up @@ -3112,6 +3098,18 @@ function register_setting( $option_group, $option_name, $args = array() ) {

$args = wp_parse_args( $args, $defaults );

if ( ! empty( $args['show_in_abilities'] ) && did_action( 'init' ) && ! doing_action( 'init' ) ) {
_doing_it_wrong(
__FUNCTION__,
sprintf(
/* translators: %s: Setting name. */
__( 'The setting "%s" is exposed to abilities and must be registered on the init action or earlier.' ),
$option_name
),
'7.2.0'
);
}

// Require an item schema when registering settings with an array type.
if ( false !== $args['show_in_rest'] && 'array' === $args['type'] && ( ! is_array( $args['show_in_rest'] ) || ! isset( $args['show_in_rest']['schema']['items'] ) ) ) {
_doing_it_wrong( __FUNCTION__, __( 'When registering an "array" setting to show in the REST API, you must specify the schema for each array item in "show_in_rest.schema.items".' ), '5.4.0' );
Expand Down
Loading
Loading