Taxonomy Abhängige Einstellungen – Teil 1

Während meiner Entwicklung an Dicentis bin ich auf das Problem gestoßen, dass ich für eine Custom Taxonomy eigene Einstellungen benötigte. Da dies meines Wissens nicht in WordPress von Haus aus möglich ist musste ich mir selber was einfallen lassen. Dieses vierteilige Tutorial soll dir zeigen, wie man für eine Taxonomy eigene Einstellungen erstellt.

Photo by:  Jeff Sheldon

 Ziel des Tutorials

Im Laufe des Tutorials werden wir ein Plugin entwickeln, welches mit der Taxonomy „Kategorie“, die man von den Posts her kennt, arbeitet und pro Kategorie eine eigene Einstellungsseite erstellt. In dem Beispiel wird das lediglich eine Einstellung als Textfeld (Message) sein, die wir dann im Frontend bei den Posts ausgeben.

Den gesamten Code findest du auf GitHub: tax-settings.

v1: eine Einstellung für alle Kategorien

v2: pro Kategorie eine Einstellung


Teil 1 – Normale Einstellungen

Um alle ins Boot zu holen, starte ich das Tutorial bei 0 und in diesem Teil erstellen wir zu aller erst eine einfach Einstellung mit der bekannten Settings API von WordPress. Wenn du bereits weißt wie man Einstellungen erstellt kannst du diesen Teil ruhig überspringen, da in diesem Post noch keine neuen Dinge vorkommen.

Schritt 1: Projekt Struktur

Die Projektstruktur für das Plugin, welches die Funktion implementieren soll, ist sehr einfach gehalten für das Tutorial und orientiert sich an dem WordPress-Plugin-Boilderplate von Tom McFarlin.

├── tax-settings/
│   ├── tax-settings.php
│   ├── admin/
|   │   ├── class-ts-settings.php
│   ├── includes/
|   │   ├── class-tax-settings.php
│   ├── public/
|   │   ├── class-ts-category-message.php
|   │   ├── css/
|   |   │   ├── ts-settings-public.css

tax-settings.php enthält den Plugin-Header, welches jedes Plugin benötigt und erstellt ein neues Objekt von class-tax-settings.php im OOP-Stil.

Der Ordner admin/ enthält die Dateien, welche für den Adminbereich wichtig sind. Das ist in diesem Fall, dass erstellen der Einstellungsseite.

Der Ordner includes/ enthält allgemeine Dateien, die das Plugin braucht und quasi als Controller fungieren.

Der Ordner public/ enthält Dateien, für das Frontend.

Schritt 2: class-tax-settings.php

 

class Tax_Settings {
    /**
     * Define the core functionality of the plugin.
     *
     * Load the dependencies and set the hooks for the Settings page and
     * the public-facing side of the site.
     *
     * @since    1.0.0
     */
    public function __construct() {
        $this->load_dependencies();
        $this->define_admin_hooks();
        $this->define_public_hooks();
    }

    /**
     * Load the required dependencies for this plugin.
     *
     * Include the following files that make up the plugin:
     *
     * - TS_Settings. Creates new Settings page
     * - TS_Category_Message. Defines all hooks for the public side of the site.
     *
     * @since    1.0.0
     * @access   private
     */
    private function load_dependencies() {
        /**
         * The class responsible for defining all actions that occur in the public-facing
         * side of the site.
         */
        require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-ts-category-message.php';

        /**
         * The class responsible for defining all actions that occur in the backend.
         */
        require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-ts-settings.php';

    }

    /**
     * Register all of the hooks related to the settings functionality
     * of the plugin.
     *
     * @since    1.0.0
     * @access   private
     */
    private function define_admin_hooks() {
        $settings = new TS_Settings();
        add_action( 'admin_init', array( $settings, 'admin_init' ) );
        add_action( 'admin_menu', array( $settings, 'add_menu' ) );
    }
    /**
     * Register all of the hooks related to the public-facing functionality
     * of the plugin.
     *
     * @since    1.0.0
     * @access   private
     */
    private function define_public_hooks() {
        $cat_message = new TS_Category_Message();
        add_action( 'wp_enqueue_scripts', array( $cat_message, 'enqueue_styles' ) );
        add_filter( 'the_content', array( $cat_message, 'show_message' ), 10, 1 );
    }

}

Die Klasse Tax_Settings macht 3 Dinge zu Anfang. Sie:

  1. bindet die entsprechenden Dateien mit require ein.
  2. fügt zwei Admin Hooks und
  3. fügt zwei Public Hooks ein.

Für das Tutorial werden zwei Action Hooks für den Adminbereich verwendet. admin_init wird verwendet um die Einstellungen mit der Settings API zu laden (nächster Schritt) und admin_menu fügt diese neue Seite auch im Adminbereich in ein Menü ein, damit wir es aufrufen können.

Tax-Settings: Screenshot der Einstellung im Backend
Tax-Settings: Screenshot der Einstellung im Backend

Schritt 3: Einstellungen erstellen

Bevor wir eine Nachricht im Frontend darstellen können müssen wir diese als Option in der Datenbank abspeichern. Dazu erstellen wir erstmal eine einfache Seite unter Einstellungen. (in Schritt 2 haben wir dazu den admin_menu hook definiert).

<?php

/**
 * The file that defines the settings page for the plugin
 *
 * A class that creates a new settings page and settings for the plugin and links.
 *
 * @since 1.0.0
 * @package Tax-Settings
 * @subpackage Tax-Settings/admin
 * @author Hans-Hege Buerger
 */
class TS_Settings {

 /**
 * Method which calls responsible methods to setup settings
 *
 * @since 1.0.0
 */
 public function admin_init() {
 $this->register_settings();
 $this->add_sections();
 $this->add_fields();
 }

 /**
 * This method registers one option for this plugin: 'ts_options'.
 * The method 'validate_options' is set for validation.
 *
 * @since 1.0.0
 * @access private
 */
 private function register_settings() {
 // register settings for new show
 register_setting(
 'ts_options',
 'ts_options',
 array( $this, 'validate_options' )
 );
 }

 /**
 * This method adds a new section 'ts_settings_sec'.
 *
 * @since 1.0.0
 * @access private
 */
 private function add_sections() {
 add_settings_section(
 'ts_settings_sec', // ID
 'Category Settings', // Name
 array( $this, 'category_settings_description' ), // Callback for description
 'ts_set' // Page
 );
 }

 /**
 * This method add one new settings field to the section 'ts_settings_sec'
 *
 * @since 1.0.0
 * @access private
 */
 private function add_fields() {
 add_settings_field(
 'ts_category_message', // ID
 'Message', // Title
 array( $this, 'category_message' ), // Callback
 'ts_set', // Page
 'ts_settings_sec' // Settings ID
 );
 }

 /**
 * Callback function which displays a description for
 * section 'ts_settings_sec'
 * 
 * @since 1.0.0
 */
 public function category_settings_description() { ?>
 <p>These setting is global and is used by all categories if no local settings are defined.</p>
 <?php }

 /**
 * Callback function to display the input field for
 * the predefined settings field
 * 
 * @since 1.0.0
 */
 public function category_message() {
 $options = get_option( 'ts_options' ); ?>
 <input id="ts_message"
 name="ts_options[ts_category_message]"
 size="40"
 type="text"
 value="<?php echo esc_attr($options['ts_category_message']) ?>" />
 <?php }

 /**
 * Validate function to make sure only sanitized settings are saved in DB
 *
 * @since 1.0.0
 *
 * @param array $input settings data / user input
 * @return array sanitized settings
 */
 public function validate_options( $input ) {
 $valid = array();

 $valid['ts_category_message'] = sanitize_text_field( $input['ts_category_message'] );

 return $valid;
 }

 /**
 * Method to add a new settings page as subpage
 *
 * @since 1.0.0
 */
 public function add_menu() {
 add_options_page(
 'Taxonomy Settings',
 'Taxonomy Settings',
 'manage_options', // capabilities
 'ts_settings', // slug
 array( $this, 'render_settings_page' )
 );
 }

 /**
 * Callback function to render the actual settings page.
 *
 * @since 1.0.0
 */
 public function render_settings_page() {
 if ( ! current_user_can( 'manage_options' ) ) {
 wp_die( 'You do not have sufficient permissions to access this page.' );
 } ?>

 <h2>Taxonomy Settings</h2>
 <div class="wrap">
 <div id="icon-tools" class="icon32"></div>
 <form method="POST" action="options.php">
 <?php settings_fields( 'ts_options' ); ?>
 <?php do_settings_sections( 'ts_set' ); ?>

 <?php submit_button(); ?>
 </form>
 </div>
 <?php }
}

Diese Klasse macht 3 Dinge. Sie:

  1. registriert neue Einstellungen und fügt dazu ein Sektion und ein Feld hinzu.
  2. linkt diese neue Einstellungsseite im Adminmenü.
  3. rendert die Seite wenn sie im Adminbereich aufgerufen wird.

Wenn du diesen Code nicht verstehst dann findest du auf Tut+ eine sehr gute Serie zu dem Thema: The Complete Guide To The WordPress Settings API

Schritt 4: Anzeigen der Nachricht im Frontend

Für das Darstellen der Nachricht im Frontend wurden zwei Action Hooks in Schritt 2 für das Frontend verwendet: the_content und wp_enqueue_scripts. Der zweite Hook ist der vorgesehene Weg wie man in WordPress eigene JavaScripts und CSSs einbinden soll. Der erste Hook wird verwendet um den Content eines Post zu bekommen, damit die Nachricht, die als Option gespeichert wurde, am Anfang des Posts darstellen zu können.

<?php

/**
 * The Public Class
 *
 * This Class is responsible to display the message in posts in the frontend.
 *
 * @since 1.0.0
 * @package Tax-Settings
 * @subpackage Tax-Settings/public
 * @author Hans-Hege Buerger
 */
class TS_Category_Message {
 /**
 * Method which gets the content of a post and prepends the message
 *
 * @since 1.0.0
 *
 * @param string $content original content
 * @return string if single then altered content
 */
 public function show_message( $content ) {
 if ( is_single() ) {
 $text = $this->get_cat_text();
 $banner = sprintf( "<blockquote class='ts-banner'>%s</blockquote>", esc_attr( $text ) );
 $content = $banner . $content;
 }
 return $content;
 }

 /**
 * Method to enqueue a custom style.
 *
 * @since 1.0.0
 */
 public function enqueue_styles() {
 wp_enqueue_style( 'tax-settings', plugin_dir_url( __FILE__ ) . 'css/ts-settings-public.css' );
 }

 /**
 * Custom method to get the category message from the database
 *
 * @since 1.0.0
 * @return string category message
 */
 public function get_cat_text() {
 $options = get_option('ts_options');

 if ( !empty( $options ) and isset( $options['ts_category_message'] )) {
 return $options['ts_category_message'];
 }

 return '';
 }
}

Die Klasse TS_Category_Message kümmert sich um die Darstellung der Nachricht. Die Methode show_message holt sich den Text aus der Datenbank und hängt diese an den Anfang des Posts. Allerdings nur wenn der Post Type stimmt. Daher wird mit IF gefragt, ob der dargestellte Bereich vom Type Single ist.

Tax-Settings: Screenshot vom Hello World Post mit Nachricht
Tax-Settings: Screenshot vom Hello World Post mit Nachricht

Fazit

In diesem ersten Teil haben wir ein kleines Plugin geschrieben, dass mit einer Option einen Text speichert und diesen dann in jedem Post als erstes anzeigt.

Auf GitHub findest du den ganzen Code. Du kannst den ganzen Ordner der version 1 einfach in einer WordPress Installation als Plugin installieren.

Als nächstes …

In den kommenden Tutorials werden wir dieses Basis Plugin erweitern und so gestalten, dass man pro Kategorie eine eigene Nachricht als Option speichern kann.

Veröffentlicht von Hans-Helge

Der studierte Informatiker arbeitet als Entwickler und Trainer bei ChurchTools und betreut neben eigenen Projekten einige andere Webseiten u.A. im ehrenamtlichen Bereich.

Beteilige dich an der Unterhaltung

4 Kommentare

  1. Ich halte einen eigene Settings-Seite für den falschen Ort um Einstellungen/Daten für eine Taxonomy festzulegen.
    Die Einstellungen sollten dort gemacht werden wo die Taxonomy selber angelegt/bearbeitet wird. Man kann sich dort rein hängen. Die Daten werden per Options-API gespeichert aber es ist viel nutzerfreundlicher.

    „{$taxonomy}_add_form_fields“ ist der Suchbegriff dafür.

    1. Das stimmt. Es gibt „{$taxonomy}_add_form_fields“. Allerdings bin ich nicht 100%tig deiner Meinung.

      Sicherlich ist es gut die hooks und Möglichkeiten zu nutzen, die WP einen bietet. Und ich bin auch der Meinung in erster Linie sollte man die Funktionen nutzen und nicht (erneut) selbst implementieren. Aber es gibt auch Fälle in denen es nicht die beste Art ist (für bestimmte Use cases).

      In meinem speziellen Fall geht es nicht nur um 1 Taxonomy sondern um 3. Wenn ich in jeder Taxonomy neue Felder hinzufügen würde hätte ich 4 Settings pages (3x Tax + 1 general). Das ist von User Experience Sicht der falsche Ansatz und daher trickse ich hier lieber etwas und implementiere den Teil anders.

Schreibe einen Kommentar

Schreibe einen Kommentar zu Ralf Wiechers Antworten abbrechen

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