Netzwerk-Einstellungen via WordPress-API hinzufügen

In einem älteren Plugin habe ich bereits Netzwerk-Einstellungen manuell in WordPress eingebaut. Doch wie geht das über die WordPress-API? Auch dafür gibt es glücklicherweise einen Weg, und dieser ist ziemlich elegant.

In meinem Fall ging es darum, bereits vorhandene Seiteneinstellungen auch über die Netzwerk-Einstellungen zu konfigurieren, um eine Art Vorauswahl zu schaffen. Dadurch hatte ich schon Seiteneinstellungen via add_settings_field() hinzugefügt. Diese wollte ich natürlich nicht nochmal separat hinzufügen müssen.

Für die Anleitung selbst setze ich entsprechende Grundkenntnisse voraus, dass man bereits weiß, wie Einstellungen für das Backend erstellt werden.

Einstellungen hinzufügen

Zuerst brauchen wir überhaupt irgendwelche Einstellungen. Diese werden ganz normal hinzugefügt.

/**
 * Register my settings.
 */
function register_my_settings() {
   register_setting( 'my_option_group', 'my_option_name' );
   
   add_settings_section(
      'my_option_section',
      __( 'My Option Section Title', 'my-plugin' ),
      null,
      'my_option_group'
   );
   
   add_settings_field(
      'my_field',
      __( 'My Field', 'my-plugin' ),
      'my_field_callback',
      'my_option_group',
      'my_option_section',
      [ 'label_for' => 'my_field', ]
   );
}

add_action( 'admin_init', 'register_my_settings' );

/**
 * Text input field callback.
 * @param $args array
 */
function my_field_callback( array $args ) {
   // get the value of the setting we've registered with register_setting()
   $options = my_plugin_get_option( 'my_option_name' );
   // output the field
   ?>
<input type="text" id="<?php echo esc_attr( $args['label_for'] ); ?>" name="my_option_name[<?php echo esc_attr( $args['label_for'] ); ?>]" class="regular-text"<?php echo ( isset( $options[ $args['label_for'] ] ) ? ' value="' . $options[ $args['label_for'] ] . '"' : '' ); ?>>
   <?php
}

Einstellungs-Seite

Die Netzwerk-Einstellungen selbst brauchen auch eine Seite, auf der die Einstellungen angezeigt werden. In meinem Fall füge ich diese als Untermenü-Punkt zu dem bereits vorhandenen Hauptmenü-Punkt „Einstellungen“ hinzu.

/**
* Add sub menu item in network options menu.
*/
function my_option_network_options_page() {
   // add top level menu page
   add_submenu_page(
      'settings.php',
      __( 'My Options', 'my-plugin' ),
      __( 'My Options', 'my-plugin' ),
      'manage_network_options',
      'my_option',
      'my_plugin_options_page_html'
   );
}

add_action( 'network_admin_menu', 'my_option_network_options_page' );

/**
* Sub menu item:
* callback functions
*/
function my_plugin_options_page_html() {
   // check user capabilities
   if ( ! current_user_can( 'manage_options' ) ) return;
   
   if ( is_network_admin() && isset( $_GET['updated'] ) ) : ?>
<div id="message" class="updated notice is-dismissible">
   <p><?php _e( 'Options saved.', 'my-plugin' ) ?></p>
</div>
<?php endif; ?>

<div class="wrap">
   <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
   
   <form action="edit.php?action=my_plugin_network_options_update" method="post">
   <?php
   // output security fields for the registered setting
   settings_fields( 'my_option_group' );
   // output setting sections and their fields
   do_settings_sections( 'my_option_group' );
   // output save settings button
   submit_button( __( 'Save Settings', 'my-plugin' ) ); 
   ?>
   </form>
</div>
<?php
}

Zuerst wird die Seite als Untermenü-Punkt hinzugefügt. Die Fallback-Funktion prüft dann zuerst einmal, ob man überhaupt das Recht hat, Netzwerk-Einstellungen zu verwalten.

Im Falle des erfolgreichen Speicherns erhält man die Nachricht „Options saved.“ über eine ausblendbare Informationsmeldung.

Über settings_fields() wird automatisch die Callback-Funktion jeder Einstellung aufgerufen, die sich in der Gruppe my_option_group befindet. Über do_settings_sections() werden dem Formular dann noch notwendige Inhalte wie der nonce als versteckte Eingabefelder hinzugefügt. Als letztes kommt dann noch eine Absende-Schaltfläche hinzu.

Netzwerk-Einstellungen speichern

Was jetzt noch fehlt, ist die Funktion zum Abspeichern, die auch im Formular selbst über die Action aufgerufen wird (my_plugin_network_options_update).

/**
 * Update network options.
 */
function my_plugin_network_options_update() {
   // make sure we are posting from our options page
   check_admin_referer( 'my_option_group-options' );
   
   // list of registered options
   global $new_whitelist_options;
   $options = $new_whitelist_options['my_option_group'];
   
   foreach ( $options as $option ) {
      if ( isset( $_POST[ $option ] ) ) {
         update_site_option( $option, $_POST[ $option ] );
      }
   }
   
   // redirect to network options page
   wp_redirect( add_query_arg( [
      'page' => 'my_option',
      'updated' => 'true'
   ], network_admin_url( 'settings.php' ) ) );
   exit;
}

add_action( 'network_admin_edit_my_plugin_network_options_update', 'my_plugin_network_options_update' );

Hier testen wir zuerst, ob der Referrer korrekt ist. Dieser ist eine Zusammensetzung zwischen der zu Beginn angegebenen option_group innerhalb von register_setting() und dem Begriff -options.

Danach wird angegeben, dass nur Optionen unserer option_group beachtet werden und diese werden dann eine nach dem anderen gespeichert.

Zu guter Letzt erfolgt dann noch eine Weiterleitung auf unsere bestehende Netzwerk-Einstellungsseite mit dem Parameter updated=true, schließlich wollen wir ja, dass die davor hinterlegte ausblendbare Informationsmeldung auch erscheint.

Seiten-Einstellungen = Netzwerk-Einstellungen?

Da normale Seiteneinstellungen identisch zu Netzwerk-Einstellungen angelegt werden können, liegt der einzige Unterschied in der Ausgabe im Frontend sowie in der Callback-Funktion der jeweiligen Option/Setting. Hierbei muss man lediglich unterscheiden, ob man die Option der jeweiligen Seite oder die Setting des jeweiligen Netzwerks erhalten möchte, also entweder get_option oder get_site_option.

Ich habe mir dafür eine Wrapper-Funktion geschrieben, die das macht:

/**
 * Get an option or a site option with the same name.
 * The site option is received if there is no option
 * with the same name.
 * 
 * @param string $option The option you want to get
 * @return mixed|void
 */
function my_plugin_get_option( $option ) {
   if ( ! is_string( $option ) ) return;
   
   if ( ! is_network_admin() ) {
      // try receive option
      $options = get_option( $option );
      
      if ( ! $options ) {
         $options = get_site_option( $option );
      }
   }
   else {
      $options = get_site_option( $option );
   }
   
   return $options;
}

In unserem Fall muss man danach nur noch die Callback-Funktion der Option anpassen, genauer gesagt folgende Zeile ändern:

$options = get_option( 'my_option_name' );

Zu:

$options = my_plugin_get_option( 'my_option_name' );

Fazit

Wenn man weiß, wie man normale Optionen im Backend einfügt, ist es bis zu den Netzwerk-Einstellungen gar nicht mehr so weit. Lediglich um das Abspeichern muss man sich selbst kümmern, alles andere ist bereits vorgefertigt. Mit ein bisschen Fleiß geht es aber schnell. 😅

Das Ergebnis:

Eigene Netzwerk-Einstellungen im WordPress-Backend

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.