Korzystanie z Customize API
- Piotr Bartczak
- 26 lis 2015
- 4 minut(y) czytania
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
Comments