Con este título he tenido el honor y el privilegio de participar como ponente en la WordCamp Santander 2016.
El personalizador de WordPress apareció en la versión 3.4. Es un framework que permite previsualizar configuraciones de nuestro sitio. En el personalizador encontramos por defecto opciones de configuración como:
- Identidad del sitio (título, descripción, logo…)
- Gestión de Menús
- Gestión de Widgets
- Portada
Muchos temas y plugins utilizan el personalizador para ofrecer al usuario opciones de configuración propias como pueden ser:
- Colores y estilos
- API keys
- Layouts
- Claims
Consta de 4 Objetos:
- Panels: son elementos contenedores de Sections. Un nivel adicional de jerarquía
- Sections: son contenedores (UI) para Controls
- Controls: son elementos (UI) para establecer datos. Inputs de diferentes tipos
- Settings: son la asociación del Control con el dato que se almacena en BBDD.
¿Cómo empezamos?
Necesitamos crear una función en el archivo functions.php de nuestro tema o en nuestro plugin, y añadirla al hook customize_register
<?php
function themeslug_customize_register( $wp_customize ) {
// Do stuff with $wp_customize, the WP_Customize_Manager object.
}
add_action( 'customize_register', 'themeslug_customize_register' );
Importante
Es recomendable el uso de prefijos para cualquier ID de los objetos que vamos a crear a continuación para evitar conflictos
Cada objeto dispone de 3 métodos: add_, get_ y remove_
$wp_customize->add_panel();
$wp_customize->get_panel();
$wp_customize->remove_panel();
$wp_customize->add_section();
$wp_customize->get_section();
$wp_customize->remove_section();
$wp_customize->add_setting();
$wp_customize->get_setting();
$wp_customize->remove_setting();
$wp_customize->add_control();
$wp_customize->get_control();
$wp_customize->remove_control();
Podremos establecer el orden de nuestros elementos teniendo en cuenta que por defecto:
Lo siguiente es pensar que tipo de configuración queremos utilizar: theme_mod u option. La primera es para almacenar datos de configuración inherentes al tema. Es decir, todo lo que guardemos ahí servirá sólo para el tema que tenemos activo. Si mañana cambiamos de tema no podremos acceder a esta información.
Por el contrario, si lo que estamos haciendo es un plugin, es conveniente guardar nuestros datos en options, de este modo estarán disponibles sea cual sea el tema que esté activo.
Añadiendo un Panel
Usando el método add_panel
<?php
$wp_customize->add_panel( 'panel_id', array(
'priority' => 160,
'capability' => 'edit_theme_options',
'theme_supports' => '', // Rarely needed
'title' => __( 'Título Panel', 'your_textdomain' ),
'description' => __( 'Descripción Panel', 'your_textdomain' ),
) );
Añadiendo un Section
Usando el método add_section
<?php
$wp_customize->add_section( 'section_id', array(
'title' => __( 'Título Section', 'your_textdomain' ),
'description' => __( 'Descripción Section', 'your_textdomain' ),
'panel' => 'panel_id', // Not typically needed.
'priority' => 160,
'capability' => 'edit_theme_options',
'theme_supports' => '', // Rarely needed.
) );
Añadiendo un Setting
Usando el método add_setting. Estableceremos el nombre y el tipo de dato que guardaremos en BBDD. Podremos establecer un valor por defecto y además validar y sanitizar el dato antes de guardarlo
<?php
$wp_customize->add_setting( 'setting_id', array(
'type' => 'theme_mod', // or 'option'
'capability' => 'edit_theme_options',
'theme_supports' => '', // Rarely needed.
'default' => '', // Ej: #000000
'transport' => 'refresh', // or postMessage
'sanitize_callback' => '', // Ej: 'sanitize_hex_color'
'sanitize_js_callback' => '', // Basically to_json.
) );
Añadiendo un Control
Usando el método add_control. Al añadir el control lo asociamos al Setting. También indicamos a que Section pertenece, así como el tipo, título, descripción, etc…
<?php
$wp_customize->add_control( 'setting_id', array(
'type' => 'date',
'priority' => 10, // Within the section.
'section' => 'section_id', // Required, core or custom.
'label' => __( 'Fecha', 'your_textdomain' ),
'description' => __( 'Descripción', 'your_textdomain' ),
'input_attrs' => array(
'class' => 'my-custom-class-for-js',
'style' => 'border: 1px solid #900',
'placeholder' => __( 'dd/mm/yyyy', 'your_textdomain' ),
),
'active_callback' => 'is_front_page',
) );
Tipos de Controls
Podemos usar los siguientes tipos de controles:
- HTML inputs: text, hidden, number, range, url, tel, email, search, time, date, datetime, y week (Dependiendo de la compatibilidad del navegador)
- checkbox
- textarea
- radio (las opciones las pasaremos por el parámetro choices)
- select (las opciones las pasaremos por el parámetro choices)
- dropdown-pages
- controles personalizados
<?php
// Range
$wp_customize->add_control( 'setting_id', array(
'type' => 'range',
'section' => 'section_id',
'label' => __( 'Etiqueta', 'your_textdomain' ),
'input_attrs' => array(
'min' => 0,
'max' => 10,
'step' => 2,
),
) );
// Radio
$wp_customize->add_control( 'setting_id', array(
'type' => 'radio',
'section' => 'section_id',
'label' => __( 'Etiqueta', 'your_textdomain' ),
'choices' => array(
'on' => __( 'On', 'your_textdomain' ),
'off' => __( 'Off', 'your_textdomain' ),
),
) );
// Select
$categories = get_categories();
$cats = array();
foreach($categories as $category) {
$cats[$category->slug] = $category->name;
}
$wp_customize->add_control( 'setting_id', array(
'type' => 'select',
'section' => 'section_id',
'label' => __( 'Etiqueta', 'your_textdomain' ),
'choices' => $cats
) );
// Dropdown
$wp_customize->add_control( 'setting_id', array(
'type' => 'dropdown-pages',
'section' => 'section_id',
'label' => __( 'Etiqueta', 'your_textdomain' ),
) );
//Color picker
$wp_customize->add_control( new WP_Customize_Color_Control ( $wp_customize, 'setting_id', array(
'label' => __( 'Etiqueta', 'your_textdomain' ),
'section' => 'section_id', // Required, core or custom.
) );
//Media
$wp_customize->add_control( new WP_Customize_Media_Control ( $wp_customize, 'setting_id', array(
'mime_type' => 'image', // image, audio, video, application
'label' => __( 'Etiqueta', 'your_textdomain' ),
'section' => 'section_id', // Required, core or custom.
) );
Controles personalizados
Podemos crear Panels, Sections, Controls y Settings personalizados extendiendo las clases asociadas con cada objeto: WP_Customize_Panel, WP_Customize_Section, WP_Customize_Control y WP_Customize_Setting:
<?php
class WP_New_Menu_Customize_Control extends WP_Customize_Control {
public $type = 'new_menu';
public function render_content() {?>
<button class="button button-primary" id="create-new-menu-submit" tabindex="0"><?php _e( 'Create Menu', 'your_textdomain' ); ?></button>
<?php }
}
Validaciones
El personalizador nos permite validar y sanitizar nuestras opciones antes de guardar en base de datos
<?php
$wp_customize->add_setting( 'setting_id', array(
'sanitize_callback' => 'absint',
'validate_callback' => 'validate_established_year'
) );
function validate_established_year( $validity, $value ) {
$value = intval( $value );
if ( empty( $value ) || ! is_numeric( $value ) ) {
$validity->add( 'required', __( 'Año no válido', 'your_textdomain' ) );
} elseif ( $value < 1900 ) {
$validity->add( 'year_too_small', __( 'Menor de 1900', 'your_textdomain' ) );
} elseif ( $value > gmdate( 'Y' ) ) {
$validity->add( 'year_too_big', __( 'Mayor que actual', 'your_textdomain' ) );
}
return $validity;
}
Multi Idioma
Tanto WPML como Polylang (dos de los plugins más usados para multi-idioma en WordPress) disponen de la función icl_get_languages para obtener los idiomas activos de un sitio:
Array (
[es] => Array (
[id] => 1
[active] => 1
[native_name] => Español
[missing] => 1
[translated_name] =>
[language_code] => es
[country_flag_url] => http://wcs16.com/wp-content/plugins/polylang/flags/es.png
[url] => http://wcsantander16.com/es/
),
[en] => Array (
[id] => 2
[active] => 1
[native_name] => Inglés
[missing] => 1
[translated_name] =>
[language_code] => es
[country_flag_url] => http://wcs16.com/wp-content/plugins/polylang/flags/en.png
[url] => http://wcsantander16.com/en/
)
)
Teniendo un array de idiomas, crearemos nuestras opciones recorriendo el array y añadiendo dinámicamente nuestros IDs el sufijo _{$language_code}
<?php
function themeslug_customize_register( $wp_customize ) {
$langs = (function_exists('icl_get_languages')) ? icl_get_languages('skip_missing=N') : array( 'es' => array( 'language_code' => 'es'));
$wp_customize->add_section( 'section_id', array(
'title' => __( 'Título Section', 'your_textdomain' ),
'description' => __( 'Descripción Section', 'your_textdomain' ),
) );
foreach($langs as $lang) {
$wp_customize->add_setting( 'setting_id_' . $lang['language_code'], array(
'type' => 'theme_mod',
'capability' => 'edit_theme_options',
) );
$wp_customize->add_control( 'setting_id_' . $lang['language_code'], array(
'type' => 'text',
'section' => 'section_id',
'label' => __( 'Título', 'your_textdomain' ) . " " . $lang['native_name'],
) );
}
}
add_action( 'customize_register', 'themeslug_customize_register' );
Aquí tienes las Slides:
Aquí tienes el vídeo de la ponencia: