The other day I was googling up information about coding options pages in the network administration dashboard of a WordPress multisite installation and I noticed that some people think they cannot use the Settings API with those pages. I also noticed there was no article showing how to do it, so here it is.
Following is the documented code you need to create a network options page using the WordPress Settings API. You can also go to GitHub and download a fully functional plugin that demonstrates that code, I added a normal options page in the plugin so that you can compare the code.
If you have any remark or question just use the comment section.
|
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
/** * 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; } |
Image Credits: Antonio Ruiz GarcÃa
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.phpalso 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_optionsto$new_allowed_optionshere: 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.