Korzystanie z Customize API

Dawno, dawno temu napisałem poradnik jak korzystać z settings API, jednak po ostatnich doniesieniach, jest on już nie do końca zgodny ze standardami. Dlatego postanowiłem napisać co nieco o Customize API.

W moim podejściu do tego tematu zastosuję metodę obiektową, która jest dużo bardziej czytelna i daje o wiele większe możliwości.

No to zaczynamy na początku tworzymy nowy plik, który będzie odpowiedzialny za nasze opcje

class ThemeOptionsAPI {
     protected static $instance;
     private $classes = array();

     public static function init() {
        if(is_null(self::$instance) AND self::$instance = new self) {
            return self::$instance;
        }
    }
}

i dołączamy go to pliku functions.php motywu

require_once('sciezka_do_pliku/theme-options-api.php');
ThemeOptionsAPI::init();

Teraz należy dodać klasę, która będzie przechowywała wszystkie opcje

class ThemeOptions {

    private $options = array();

    public function __construct() {
       $this->options = array();
    }

    public function getOptions() {
        return $this->options;
    }
    public function addOption(array $opt) {
        $this->options[] = $opt;
    }
}

Teraz do klasy ThemeOptionsAPI, należy dodać konstruktor

private function __construct() {
    $this->classes = array(
        'ThemeOptions' => get_template_directory().'sciezka_do_pliku/theme-options.php',
    );
    $this->theme_options_include_classes();
}

oraz metodę autloadera.

private function theme_options_include_classes() {
    if (function_exists("spl_autoload_register")) {
        if (function_exists("__autoload")) {
            spl_autoload_register("__autoload");
        }
        spl_autoload_register(array($this,'autoload'));
    } else {
        foreach ($this->classes() as $id => $path) {
            if (is_readable($path) && !class_exists($id)) {
                require_once($path);
            }
        }
    }
}
private function autoload($class) {
    if (isset($this->classes[$class]) && is_readable($this->classes[$class])) {
        require_once($this->classes[$class]);
    }
}

Etap początkowy można uznać za zakończony, teraz w konstruktorze klasy ThemeOptions, dodamy przykładowe pola.

$this->options = array(
    'section_id' => array(//ID sekcji
        'title' => 'Tytuł sekcji', //Tytuł sekcji
        'priority' => 35, //Priorytet
        'capability' => 'edit_theme_options',//Poziom uprawnień
        'description' => 'Opis sekcji', //Opis sekcji
        'fields' => array( //Tablica z polami
            'field_id' => array(//ID pola
                'label' => 'Field Label',//Etykieta
                'description' => 'Field Desc',//Opis pola
                'type'     => 'image',//Typ pola
                'default' => '',//Wartość domyślna
                'options' => array()//Tablica wartości
            )
        )
));

Opis pól:

  • ID sekcji: WordPress udostępnia domyślne sekcje:(title_tagline,colors,header_image,background_image,nav,static_front_page) ustawienie, któreś z wymienionych jako ID sekcji spowoduje wyświetlenie pól w któreś z nich, gdy ID sekcji będzie własne zostanie utworzona nowa sekcja
  • Priorytet: definiuje w jakim miejscu wyświetli się nowa sekcja, wyłącznie w przypadku tworzenie nowej sekcji
  • Poziom uprawnień: definiuje jakie uprawnienia powinien posiadać użytkownik aby móc edytować wartości w tej sekcji
  • Tablica z polami: zawiera tablicę pól jakie zostaną wyświetlone w danej sekcji
  • ID pola: wartość wstawiana jako id oraz name pola
  • type: Typ pola możliwe opcje takie same jak w przypadku znaczników HTML, dodatkowo Worpdress udostępnia własne typy(color,image,media)
  • Wartość domyślna: w przypadku gdy pole nie powinno być puste można ustawić wartość domyślna
  • Tablica wartości: w przypadku pól typu select, checkbox, radio tablica zawierająca dostępne wartości w postaci 'wartosc’ => 'etykieta’

Teraz należy wyświetlić uprzednio dodane opcje oraz pogrupować jej w sekcje,w tym celu w konstruktorze klasy ThemeOptionsAPI, należy dodać następującą linijkę:

add_action('customize_register',array($this,'theme_options_api_customize_register'));

oraz metodę theme_options_api_customize_register

public function theme_options_api_customize_register($wp_customize) {
    $this->customize = $wp_customize;
    $class = new ThemeOptions();
    $options = $class->getOptions();
    if(!empty($options)) {
        foreach ($options as $section_id => $section_opt) {
            $this->sectionID = $section_id;
            $this->addSection($section_id, $section_opt);
            $this->addFeilds($section_id, $section_opt['fields']);
            $this->options[$section_id] = array_keys($section_opt['fields']);
        }
    }
}

Powyższa metoda w pętli dodaje pobrane z tablicy pola oraz sekcje korzystając z odpowiednich metod, które zostaną opisane za chwilę.

Wcześniej należy dodać jeszcze trzy prywatne pola do klasy ThemeOptionsAPI

private $customize = null;
private $options = array();
private $sectionID = null;

Kolejnym krokiem jest dodanie wypomnianych metod dodających pola oraz sekcje.

private function addSection($section_id,array $section_opt) {
    $default_sections = array('title_tagline','colors','header_image','background_image','nav','static_front_page');
    if(!in_array($section_id, $default_sections)) {
        if(isset($section_opt['fields'])) {
            unset($section_opt['fields']);
        }
        $this->customize->add_section($section_id, $section_opt);
    }
}

private function addFeilds($section_id,array $fields) {
    if(!empty($fields)) {
        foreach($fields as $id => $field) {
            $this->addField($id, $field);
        }
    }
}

Powyższe metody nie mają skomplikowanej struktury dlatego też nie zostaną dokładnie opisane, a wszystkie wątpliwości rozwieją przeprowadzane przez siebie testy.

Jednym z ostatnich kroków jest zapis utworzonych przez nas opcji do bazy, w tym celu należy utworzyć metodę storeInDB

private function storeInDB($id, array $field) {
    $default = isset($field['default']) ? $field['default'] : '';
    $capability = isset($field['capability']) ? $field['capability'] : 'edit_theme_options';
    $this->customize->add_setting($id, //No need to use a SERIALIZED name, as `theme_mod` settings already live under one db record
        array(
            'default' => $default, //Wartość domyślna
            'type' => 'theme_mod', //dostępne wartości theme_mod, option
            'capability' => $capability, //Poziom uprawnień
            'transport' => 'postMessage', //Sposób w jaki zapisywać ustawienia refresh,postMessage
        ) 
    );
}

W tej metodzie tak samo jak w poprzedniej najlepszym wytłumaczeniem będą testy, param transport określa w jaki sposób powinny być zapisywane ustawienia, ustawienie go na postMessage umożliwi podgląd zmian „na żywo”

No i w końcu przyszedł czas na najważniejszą metodę w całej klasie czyli wyświetlenie pól umożliwiających edycję szablonu.

private function addField($id, array $field) {
    $this->storeInDB($id, $field);
    $default_type = array(
        'color' => 'WP_Customize_Color_Control',
        'image' => 'WP_Customize_Image_Control',
        'media' => 'WP_Customize_Upload_Control',
    );
    $priority = isset($field['priority']) && is_numeric($field['priority']) ? $field['priority'] : '';
    $options = isset($field['options']) && is_array($field['options']) ? $field['options'] : array();

    if(key_exists($field['type'], $default_type)) {
        $class = new $default_type[$field['type']](
            $this->customize,$id, 
            array(
                'label' => $field['label'],
                'section' => $this->sectionID,
                'priority' => $priority,
            )
        );
        $this->customize->add_control($class);
    } else {
        $class = array(
            'label' => $field['label'],
            'section' => $this->sectionID,
            'type' => $field['type'],
            'choices' => $options,
        );
        $this->customize->add_control($id,$class);
    }
}

I to wszystko opcje powinny się wyświetlać w sekcjach jakie zostały zdefiniowane. Dodatkowo do podglądu zmiany w ustawieniach „na żywo”, należy dołączyć plik JavaScript z następującą zawartością:

(function($) {
    wp.customize('YOUR_SETTING_ID', function(value) {
    value.bind( function(newval) {
            //Do stuff (newval variable contains your "new" setting data)
        });
    });
})(jQuery);

W celu dołączenia pliku w konstruktorze klasy ThemeOptionsAPI należy dodać następującą linijkę:

add_action(’customize_controls_enqueue_scripts’,array($this,’theme_options_api_customizer_live_preview’));

oraz metodę, która zarejestruje skrypt oraz doda do niego w postaci tablicy wszystkie zarejestrowane pola wraz z przypisanymi do nich sekcjami, co pozwoli na łatwy dostęp do konkretnych wartości

public function theme_options_api_customizer_live_preview() {
    wp_register_script('theme_options_api_script',get_template_directory.'sciezka_do_pliku/theme-customize.js');
    wp_localize_script('theme_options_api_script','thme_options_fields',$this->options);
    wp_enqueue_script('theme_options_api_script');
}

Teraz to już na prawdę wszystko, starałem się tłumaczyć w taki sposób aby wszystko było jasne; ale też bez przepisywania codexa. Wydaj mi się, że napisany w ten sposób kod pozwoli ograniczyć jego ilość do minimum pozostając czytelnym.

W razie wątpliwości, pytań, sugestii wszystkie komentarze są mile widziane


Opublikowano

w

przez

Komentarze

2 odpowiedzi na „Korzystanie z Customize API”

  1. Awatar Antoni

    Dzięki za ten poradnik!

  2. Awatar Janunsz Kamiński

    Bardzo ciekawy poradnik!