Publi

Cómo crear un plugin para WordPress. Making of SimTerm: pantalla de configuración (segunda parte)

simterm
WordPress es un sistema gestor de contenidos muy utilizado mundialmente. Y uno de sus puntos fuertes es su capacidad para que cualquiera de nosotros lo pueda extender fácilmente. Aprovechando el mismo núcleo que proporciona WordPress con funciones y clases que nos permiten interactuar con la plataforma crearemos nuestras propias funcionalidades que harán de nuestra página o blog algo único.
Este post es la segunda parte, si prefieres empezar desde cero, te recomiendo visitar primero Cómo crear un plugin para WordPress. Making of SimTerm.

Esta vez nos centraremos en la configuración de nuestro plugin.

Configuración

Nuestro plugin necesitará algo de configuración por defecto para nuestros terminales, como serán el tema y la velocidad por defecto (iremos metiendo más opciones luego).

Para crear la configuración del plugin, vamos a utilizar la API de configuración de WordPress (WordPress Settings API) que está con nosotros desde hace algunos años y nos ayuda enormemente con este tema proporcionando sencillez a la hora de programarla y una capa de seguridad, con la que nos podemos olvidar de hacer muchas comprobaciones a los datos que nos llegan del usuario (no están de más, pero es un tostón hacerlo, y WordPress nos quita trabajo).

Para separar la configuración del propio plugin he creado el archivo simterm-settings.php que contendrá la clase SimTermSettings, será de tipo singleton y se encargará de presentar distintas vistas para la pantalla de configuración. Se ha creado una vista para cada tipo de campo, como detallaremos más adelante.

Antes de adentrarnos en la configuración, primero debemos añadir un par de acciones en la inicialización de nuestro plugin (aquella función init() de la primera parte), aunque lo importante es que esto se ejecute siempre, puede estar escrito directamente en el archivo PHP principal del plugin:

1
2
    add_action('admin_menu', array('Clase', 'register_settings_menu'));
    add_action('admin_init', array('Clase', 'settingsInit'));

Con estas dos funciones, lo primero es añadir un elemento de menú para nuestro plugin (al menos que la página de configuración aparezca), y con el segundo inicializamos la configuración del plugin (estableciendo qué cosas se van a configurar y cómo). En el ejemplo he puesto ‘Clase’, ya que el segundo parámetro de add_action() es un callback que llamará WordPress de manera independiente cuando sea necesario. Si vuestro plugin es orientado a objetos podréis pasar el objeto donde está ubicado el método a llamar para cada acción. En mi caso concreto, simterm.php contiene lo siguiente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
/**
 * Plugin Name: SimTerm
 * Plugin URI:  http://gaspar.totaki.com/en/php-project/simterm/
 * Description: Simulates terminal input/output for tutorials
 * Version: 0.1.0
 * Author: Gaspar Fernández
 * Author URI: https://poesiabinaria.net/
 * License: GPL3
 */


require_once('views.php'); // visto en la primera parte

class SimTermLoader
{
    protected static $st;

    function Init()
    {
    /* Incluimos nuestra clase */
    $path = plugin_dir_path(__FILE__);
    require_once($path.'simterm-core.php');
    self::$st = new SimTerm;

    add_action('admin_menu', array(self::$st->settings(), 'register_settings_menu'));
    add_action('admin_init', array('SimTermLoader', 'settingsInit'));
    }

    public function settingsInit()
    {
    $sett = self::$st->settings();
    $sett->register();
    }
};

SimTermLoader::Init();

En este caso, Init() crea una instancia de SimTerm, que está en el archivo simterm-core.php (vimos algo en la primera parte). Ahora, el objeto donde están register_settings_menu y register lo obtenemos de la llamada a settings() de SimTerm. Por ahora, la clase SimTerm contiene lo siguiente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
require_once('simterm-settings.php');

class SimTerm
{
    protected $settings;

    function __construct()
    {
    /* Inicialización básica de mi plugin
       (la que no tiene que ver con WordPress) */

    $this->settings = SimTermSettings::getInstance();
    }

    function settings()
    {
    return $this->settings;
    }
};

Como vemos, ya que SimTermSettings es un singleton, con la llamada de SimTerm::settings() obtendremos la instancia de dicho singleton. La clase SimTermSettings, por el momento vacía está así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
class SimTermSettings
{
    private static $instance;
    public static function getInstance()
    {
    if (self::$instance === null)
        self::$instance = new SimTermSettings();

    return self::$instance;
    }

    protected function __construct()
    {
    }

    private function __clone()
    {
    }

    private function __wakeup()
    {
    }
};

Comentamos ahora lo que tiene que hacer la función a la que llamamos en la acción admin_menu:

1
2
3
4
5
6
7
8
9
10
<?php
    public function register_settings_menu()
    {
    add_options_page('SimTerm Settings', 'SimTerm settings', 'administrator', 'simterm-settings',array($this, 'globalSettingsPage'));
    }

    public function globalSettingsPage()
    {
    echo SimTermView::render('globalsettings');
    }

Lo importante es add_options_page($titulo_de_la_pagina, $titulo_del_menu, $permisos, $slug, $callback) con el que se inserta el elemento en el menú de WordPress. Si preferimos un enlace más grande y no dentro de Ajustes podemos utilizar add_menu_page() con el que podemos poner hasta un icono.
Lo importante es que cuando se pulsa, se cargará la vista que está en views/globalsettings (mirar la clase SimTermView, para ver cómo va todo). Esta vista la pondré más adelante.

Por otro lado, tenemos el método register(), que explicaremos a continuación.

Empezamos con las opciones

Lo más básico para crear opciones de WordPress es:

No voy a detallar el funcionamiento de estas llamadas porque ya está muy bien documentado en el Codex de WordPress (ver los enlaces). Aunque voy a poner el caso concreto de SimTerm aquí para tener una idea y un ejemplo concreto de uso.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<?php
    public function register()
    {
    /* Settings registration  */
    register_setting('simterm-settings',
             'simterm-default-theme');
    register_setting('simterm-settings',
             'simterm-delay-time',
             array($this, 'number_sanitize'));
    register_setting('simterm-settings',
             'simterm-command-prepend');
    register_setting('simterm-settings',
             'simterm-type-prepend');
    /* Config sections  */
    add_settings_section('simterm-global-settings',
                 'SimTerm Configuration',
                 array($this, 'globalConfiguration'),
                 'simterm-settings');

    /* Config fields */
    add_option('simterm-type-prepend', '>');
    add_option('simterm-command-prepend', '$#');
    add_option('simterm-default-delay', '400');
    add_option('simterm-default-theme', 'light');

    add_settings_field('simterm-default-theme',
               'Theme to use',
               array($this, 'config_default_theme'),
               'simterm-settings',
               'simterm-global-settings');
    add_settings_field('simterm-default-delay',
               'Delay between lines',
               array($this, 'config_default_delay'),
               'simterm-settings',
               'simterm-global-settings');
    add_settings_field('simterm-command-prepend',
               'Command prepend character',
               array($this, 'config_command_prepend'),
               'simterm-settings',
               'simterm-global-settings');
    add_settings_field('simterm-type-prepend',
               'Type prepend character',
               array($this, 'config_type_prepend'),
               'simterm-settings',
               'simterm-global-settings');
    }

    public function number_sanitize($value)
    {
    return (is_numeric($value))?$value:0;
    }

    public function globalConfiguration()
    {
    echo wpautop( "This are some options you can change." );
    }
    public function config_default_theme()
    {
    /* In the future, this themes may be extensions of this plugin  */
    echo SimTermView::render('settings/select', array('fieldId'=>'simterm-default-theme',
                              'options' => array('regular' => 'Regular',
                                         'dark' => 'Dark',
                                         'light' => 'Light',
                                         'blue' => 'Blue'),
    ));
    }

    public function config_default_delay()
    {

    echo SimTermView::render('settings/text', array('fieldId'=>'simterm-default-delay',
                            'fieldText' => 'Delay in milliseconds'
    ));
    }

    public function config_command_prepend()
    {
    echo SimTermView::render('settings/text', array('fieldId'=>'simterm-command-prepend',
                            'fieldText' => 'Any of these characters may prepend a command input'
    ));
    }

    public function config_type_prepend()
    {
    echo SimTermView::render('settings/text', array('fieldId'=>'simterm-type-prepend',
                            'fieldText' => 'Any of these characters may prepend a type input'
    ));
    }

En este caso registramos las siguientes configuraciones:

  • simterm-default-theme : Será el tema por defecto que coja el terminal. En principio habrá pocos temas, así que estarán codificados directamente en estos archivos. Si todo marcha bien y terminamos con 200 plugins habrá que pensar algo nuevo.
  • simterm-delay-time : Será la espera entre línea y línea. En el futuro habrá más opciones para esto.
  • simterm-command-prepend : Será el carácter que introducirá un comando (pondremos el prompt, que suele ser un dólar).
  • simterm-type-prepend : Será el carácter que introducirá una petición al usuario, pondremos un signo mayor que (>)

Todas las configuraciones pertenecen a simterm-settings, que lo creamos para la ocasión. El último parámetro de register_setting() es un callback que filtrará el dato obtenido de base de datos e impedirá que entren datos no válidos (o por ejemplo si agrupamos varios datos en una misma cadena de caracteres, o tenemos que hacer cualquier otro tratamiento)

Con respecto a las secciones, sólo tendremos una sección (por el momento), y principalmente llamará a la función globalConfiguration() que pondrá un texto en pantalla. Podríamos cargar una vista para poner más cosas, en el futuro creo que así será. Más adelante, definimos las opciones por defecto de cada una de las opciones de configuración. Y, por último, definimos los campos de formulario que se cargarán para cada opción de configuración definida y el texto introductorio de las mismas. En este caso, a add_settings_field le pasaremos:

  • Opción a modificar
  • Texto de introducción
  • Callback del campo (que como vemos, todas las funciones llaman a vistas (que pondré más adelante)
  • Página de configuración
  • Sección
  • Podemos pasar un array de argumentos para el callback y hacer funciones más genéricas.

Es cierto que podemos prescindir del tema de las plantillas de las vistas, fijaos como los callbacks lo único que hacen es presentar ciertas plantillas, código que podemos escribir directamente en dichas funciones PHP. Pero por manía mía desde hace años, y por tener algo más de flexibilidad y mejor mantenimiento me gusta tener todo lo relacionado con las vistas en otro lugar y por separado.

Y ya lo tenemos, generaremos una pantalla de configuración como esta:
Screenshot 28-07-2016-210714

Las vistas utilizadas

Adjunto también las vistas utilizadas, porque, aunque miréis el código fuente del plugin, tal vez éste haya cambiado con respecto a esta guía.

views/globalsettings.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div class="section panel">
    <h1>SimTerm Options</h1>
    <form method="post" enctype="multipart/form-data" action="options.php">
        <?php
    settings_fields('simterm-settings');
        do_settings_sections('simterm-settings');
        ?>
        <p class="submit">  
            <input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" />  
        </p>  
       
    </form>
   
    <p>SimTerm by <a href="http://gaspar.totaki.com">Gaspar Fernández</a> using Show Your Terms by <a href="http://kandebonfim.com">Kande Bonfim</a>.</p>
</div>

views/settings/text.php

1
2
3
4
5
6
7
8
9
<label for="<?php echo $fieldId;?>">
   <input id="<?php echo $fieldId;?>" type="text" value="<?php echo get_option( $fieldId ); ?>" name="<?php echo $fieldId;?>" />
   <div class="settings-text-expl">
   <?php
    if (isset($fieldText))
      echo $fieldText;
   ?>
</div>
</label>

views/settings/select.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<select id="<?php echo $fieldId;?>" value="1" name="<?php echo $fieldId;?>">
   <?php
   if (isset($options))
     {
       $default = get_option( $fieldId, true );
       foreach ($options as $optionKey => $optionValue)
     {
       echo '<option value="'.$optionKey.'" '.selected($optionKey==$default).'>'.$optionValue.'</option>';
     }
     }
   else
     echo 'No options';
?>
</select>

Tercera parte

La tercera parte, que se publicará el día 29. Estará enfocada a la inclusión de recursos y a los shortcodes. Y aún queda mucho por recorrer.

También podría interesarte....

Leave a Reply