/**
* First let's hook up to the 'network_admin_menu' action and create an options
* page.
*
* Then we use the Settings API to create a section and register an option.
*
* You will notice the only difference with coding a normal page is the parent
* slug of our option page (must be 'settings.php') and the capability required
* for this page to be displayed (here 'manage_network_options').
*/
add_action('network_admin_menu', 'post3872_network_admin_menu');
function post3872_network_admin_menu() {
// Create our options page.
add_submenu_page('settings.php', __('My Network Options', 'post3872'),
__('My Plugin', 'post3872'), 'manage_network_options',
'post3872_network_options_page', 'post3872_network_options_page_callback');
// Create a section (we won't need a section header).
add_settings_section('default', __('Default Network Options'), false,
'post3872_network_options_page');
// Create and register our option (we make the option id very explicit because
// this is the key that will be used to store the options.
register_setting('post3872_network_options_page', 'post3872_network_option_1');
add_settings_field('post3872_network_option_1', __('Network option one', 'post3872'),
'post3872_network_option_1_callback', 'post3872_network_options_page',
'default');
}
/**
* Displays our only option. Nothing special here.
*/
function post3872_network_option_1_callback() { ?>
<label><input type="checkbox" name="post3872_network_option_1"
value="1" <?php checked(get_site_option('post3872_network_option_1')); ?> /> <?php
_e('Check this box if you want to activate network option one.', 'post3872') ?></label><?php
}
/**
* Displays the options page. The big difference here is where you post the data
* because, unlike for normal option pages, there is nowhere to process it by
* default so we have to create our own hook to process the saving of our options.
*/
function post3872_network_options_page_callback() {
if (isset($_GET['updated'])): ?>
<div id="message" class="updated notice is-dismissible"><p><?php _e('Options saved.') ?></p></div>
<?php endif; ?>
<div class="wrap">
<h1><?php _e('My Network Options', 'post3872'); ?></h1>
<form method="POST" action="edit.php?action=post3872_update_network_options"><?php
settings_fields('post3872_network_options_page');
do_settings_sections('post3872_network_options_page');
submit_button(); ?>
</form>
</div>
<?php
}
/**
* This function here is hooked up to a special action and necessary to process
* the saving of the options. This is the big difference with a normal options
* page.
*/
add_action('network_admin_edit_post3872_update_network_options', 'post3872_update_network_options');
function post3872_update_network_options() {
// Make sure we are posting from our options page. There's a little surprise
// here, on the options page we used the 'post3872_network_options_page'
// slug when calling 'settings_fields' but we must add the '-options' postfix
// when we check the referer.
check_admin_referer('post3872_network_options_page-options');
// This is the list of registered options.
global $new_whitelist_options;
$options = $new_whitelist_options['post3872_network_options_page'];
// Go through the posted data and save only our options. This is a generic
// way to do this, but you may want to address the saving of each option
// individually.
foreach ($options as $option) {
if (isset($_POST[$option])) {
// Save our option with the site's options.
// If we registered a callback function to sanitizes the option's
// value it will be called here (see register_setting).
update_site_option($option, $_POST[$option]);
} else {
// If the option is not here then delete it. It depends on how you
// want to manage your defaults however.
delete_site_option($option);
}
}
// At last we redirect back to our options page.
wp_redirect(add_query_arg(array('page' => 'post3872_network_options_page',
'updated' => 'true'), network_admin_url('settings.php')));
exit;
}
Thank you! You saved my life.
Very nice explanation.
You’re welcome :)
BTW, you don’t need to call
apply_filters('sanitize_option_' . $option_name, $_POST[$option]);
, because when callingupdate_site_option()
, this filter will also be called.you’re right, thanks :)
Thank you so much, your code worked perfectly!
I just want to say for the benefit of anyone else reading this that I am using WordPress 4.8 and I had to change the redirect target from settings.php to admin.php.
Thanks for the info Alex, I will update the code when I have 5mn :)
Pingback: The wacky world of network activated WordPress plugins in multisite
Hi Claude,
thanks for the really helpful post! :)
Regarding the redirect target: For me it works great with
settings.php
also in 4.8.Cheers,
Florian
Thanks Florian,
I think anything works, it just depends where you want to send people after they submitted the form :)
Your
add_filter('network_admin_menu', 'post3872_network_admin_menu');
line should probably beadd_action('network_admin_menu', 'post3872_network_admin_menu');
(since you’re not filtering anything).correct, thanks :)
Still working through trying to get this working. So far, it doesn’t seem that the options are saving.
Side note: As part of working through this, I noticed that core changed
$new_whitelist_options
to$new_allowed_options
here: https://core.trac.wordpress.org/changeset/48477Anyway, is this code working for others? I’ve hit a bit of a wall.
EDIT: Correction. This is working as-is. When trying to change the checkbox field to a text field, it doesn’t save.