I'm trying to update a core WordPress option, image_default_link_type
, from my plugin's settings page, but WordPress is refusing to update it. The options registered by the plugin itself are updated. Here is a minimal example:
add_action( 'init', 'wpse_register_plugin_settings' );
add_action( 'admin_menu', 'wpse_add_plugin_admin_menu_entry' );
/**
* Register a plugin setting.
*/
function wpse_register_plugin_settings() {
add_settings_field(
'my_plugin_settings',
__( 'Settings', 'my-plugin' ),
'wpse_display_settings_field',
'my-plugin-admin-options',
);
register_setting(
'my-plugin-admin-options',
'my_plugin_setting',
);
}
/**
* Callback function for the plugin settings section.
*/
function wpse_display_settings_field() {
require_once plugin_dir_path( 'my-plugin' ) . 'partials/admin/settings/section-display.php';
}
/**
* Add the settings page as an entry in the admin menu.
*/
function wpse_add_plugin_admin_menu_entry() {
add_options_page(
__( 'My Plugin Settings', 'my-plugin' ),
__( 'My Plugin', 'my-plugin' ),
'manage_options',
'my-plugin-setting-page-slug',
'wpse_output_plugin_settings_page'
);
}
/**
* Callback function for the plugin settings page.
*/
function wpse_output_plugin_settings_page() {
// Check user has permissions.
if ( ! current_user_can( 'manage_options' ) ) {
wp_die(
'<h1>' . esc_html__( 'You need a higher level of permission.', 'my-plugin' ) . '</h1>' .
'<p>' . esc_html__( 'Sorry, you are not allowed to use the plugin admin settings.', 'my-plugin' ) . '</p>',
403
);
}
require_once plugin_dir_path( 'my-plugin' ) . 'partials/admin/settings/display.php';
}
Contents of section-display.php
:
<label for="my_plugin_setting">
<input type="checkbox" name="my_plugin_setting" id="my_plugin_setting" value="1" <?php checked( get_option( 'my_plugin_setting' ) ); ?> />
<?php esc_html_e( 'Some setting', 'my-plugin' ); ?>
</label>
<br/>
<select name="image_default_link_type">
<!-- some options -->
</select>
Contents of display.php
:
<?php
/**
* Plugin settings.
*/
?>
<div class="wrap">
<h2><?php esc_html_e( 'My Plugin Settings', 'my-plugin' ); ?></h2>
<div>
<form method="post" action="options.php">
<?php settings_fields( 'my-plugin-admin-options' ); ?>
<?php do_settings_sections( 'my-plugin-admin-options' ); ?>
<?php submit_button( esc_html__( 'Save Changes' ) ); ?>
</form>
</div>
</div>
WordPress seems to be blocking the setting from being updated. How can I enable updates to core options via my plugin's settings page?
I'm trying to update a core WordPress option, image_default_link_type
, from my plugin's settings page, but WordPress is refusing to update it. The options registered by the plugin itself are updated. Here is a minimal example:
add_action( 'init', 'wpse_register_plugin_settings' );
add_action( 'admin_menu', 'wpse_add_plugin_admin_menu_entry' );
/**
* Register a plugin setting.
*/
function wpse_register_plugin_settings() {
add_settings_field(
'my_plugin_settings',
__( 'Settings', 'my-plugin' ),
'wpse_display_settings_field',
'my-plugin-admin-options',
);
register_setting(
'my-plugin-admin-options',
'my_plugin_setting',
);
}
/**
* Callback function for the plugin settings section.
*/
function wpse_display_settings_field() {
require_once plugin_dir_path( 'my-plugin' ) . 'partials/admin/settings/section-display.php';
}
/**
* Add the settings page as an entry in the admin menu.
*/
function wpse_add_plugin_admin_menu_entry() {
add_options_page(
__( 'My Plugin Settings', 'my-plugin' ),
__( 'My Plugin', 'my-plugin' ),
'manage_options',
'my-plugin-setting-page-slug',
'wpse_output_plugin_settings_page'
);
}
/**
* Callback function for the plugin settings page.
*/
function wpse_output_plugin_settings_page() {
// Check user has permissions.
if ( ! current_user_can( 'manage_options' ) ) {
wp_die(
'<h1>' . esc_html__( 'You need a higher level of permission.', 'my-plugin' ) . '</h1>' .
'<p>' . esc_html__( 'Sorry, you are not allowed to use the plugin admin settings.', 'my-plugin' ) . '</p>',
403
);
}
require_once plugin_dir_path( 'my-plugin' ) . 'partials/admin/settings/display.php';
}
Contents of section-display.php
:
<label for="my_plugin_setting">
<input type="checkbox" name="my_plugin_setting" id="my_plugin_setting" value="1" <?php checked( get_option( 'my_plugin_setting' ) ); ?> />
<?php esc_html_e( 'Some setting', 'my-plugin' ); ?>
</label>
<br/>
<select name="image_default_link_type">
<!-- some options -->
</select>
Contents of display.php
:
<?php
/**
* Plugin settings.
*/
?>
<div class="wrap">
<h2><?php esc_html_e( 'My Plugin Settings', 'my-plugin' ); ?></h2>
<div>
<form method="post" action="options.php">
<?php settings_fields( 'my-plugin-admin-options' ); ?>
<?php do_settings_sections( 'my-plugin-admin-options' ); ?>
<?php submit_button( esc_html__( 'Save Changes' ) ); ?>
</form>
</div>
</div>
WordPress seems to be blocking the setting from being updated. How can I enable updates to core options via my plugin's settings page?
Share Improve this question asked Jan 4, 2021 at 12:23 SeanSean 6677 silver badges17 bronze badges1 Answer
Reset to default 2The file wp-admin/options.php
handles updates to options submitted via the admin area and filters the submitted option values against a list of allowed options for the option page that submitted the request.
The allowed list (called a "whitelist" before WordPress 5.5) uses the value of the variable $option_page
to determine the settings that are allowed to be updated. The $option_page
value will be set to whatever was specified as the argument to settings_fields()
when the options page was output, which in your case is my-plugin-admin-options
.
The core option image_default_link_type
is only allowed to be updated when $option_page
is media
. That's why it doesn't get updated by your plugin's settings page. You noticed that your own plugin's settings were updated without any issue - this is because register_setting
adds the option name to the allowed list for the specified $option_page
automatically.
The solution is to add a filter on allowed_options
(WordPress 5.5+) or whitelist_options
(WordPress < 5.5) that adds the core option to the list of allowed options for the current $option_page
:
add_filter( 'allowed_options', 'wpse_allow_image_default_link_type_update' );
/**
* Allow core `image_default_link_type` setting to be updated from the
* plugin settings page.
*
* @global $option_page
*/
function wpse_allow_image_default_link_type_update( $allowed_options ) {
global $option_page;
if ( 'my-plugin-admin-options' === $option_page ) {
$allowed_options['my-plugin-admin-options'][] = 'image_default_link_type';
}
return $allowed_options;
}