Cómo hacer un plugin de WordPress #3

En la última parte de este tutorial utilizaremos el poder de jQuery para crear un botón en la barra de herramientas que nos permitará utilizar el shortcode de manera más simple.

Si ya leyeron la primera parte y la segunda parte, pueden seguir con la última parte que contemplará la integración de un botón en el menú del editor de WordPress.

El botón en el menú

Para comenzar vamos a crear un botón en el menú del editor, el objetivo será que nos muestre un diálogo con configuraciones y luego nos integre un shortcode en el editor. Esto lo lograremos agregando 3 funciones a nuestro archivo "plugin.php".

La primera función permitirá registrar el botón solo si el usuario puede editar entradas o páginas, para esto agregaremos al final de nuestro archivo plugin.php el siguiente código:

function aPlaceHolderAddButton()
{
    if ( current_user_can('edit_posts') &&  current_user_can('edit_pages') )
    {
        add_filter('mce_external_plugins', 'aPlaceHolderButtonPlugin');
        add_filter('mce_buttons', 'aPlaceHolderRegisterButton');
    }
 }

Si analizamos la función se darán cuenta que en estamos creando filtros para el "TinyMCE" el plugin que utiliza wordpress para mostrar su editor WYSIWYG y que llama a dos funciones que tendremos que crear.

El primer filtro invoca a la función que permite agregar los plugins externos, es decir, los códigos escritos javascript (apoyados en jQuery) que se encontrarán en el archivo "aplaceholder.js"

 function aPlaceHolderButtonPlugin($plugin_array)
 {
    $plugin_array['aplaceholder'] = plugins_url('aplaceholder.js', __FILE__);
    return $plugin_array;
 }

El segundo filtro invoca a la función que registra el botón:

 function aPlaceHolderRegisterButton($buttons)
 {
    array_push($buttons, 'aplaceholder');
    return $buttons;
 }

esta función agrega a un arreglo nuestro botón llamado "aplaceholder" y lo retorna del mismo modo.

Luego, tenemos que habilitar nuestra función "aPlaceHolderAddButton" a la carga inicial de WordPress usando el hook "init":

add_action('init', 'aPlaceHolderAddButton');
El archivo javascript

Cuando ya tenemos todo lo necesario para que nuestro botón exista, usaremos la magia de Javascript y jQuery para agregarle la funcionalidad. Para lograr esto, crearemos un archivo nuevo en nuestro directorio del plugin llamado "aplaceholder.js". Si se dan cuenta, este archivo ya fue definido anteriormente en la función "aPlaceHolderButtonPlugin".

Para integrar la funcionalidad a este botón diviremos el problema en tres partes:

  1. Crear el botón en nuestro editor tinymce como plugin
  2. Agregar el botón (plugin) a los plugins del tinymce
  3. Agregar la interfaz de configuración del plugin que será invocada al presionar el botón

Para crear el botón en nuestro editor TinyMCE utilizaremos el método create que, por defecto, existe como variable dentro de WordPress:

(function() {

    tinymce.create('tinymce.plugins.aplaceholder', {
        init: function(ed, url) {
            ed.addButton('aplaceholder', {
                title: 'Add a Placeholder',
                image: url + '/placeholder.png',
                onclick: function() {
                    tb_show('aplaceholder', '#TB_inline?inlineId=aplaceholder-form');
                }
            });
        },
        createControl: function(n, cm) {
            return null;
        },
    });

})();

En esta llamada, estamos utilizando la API de TinyMCE para crear un plugin llamado "aplaceholder".
Según la documentación en el método "init" es donde debemos definir qué tipo de elemento es, acá estamos utilizando la función "addButton" con las configuraciones necesarias (title, image, onclick).

  • En "title" se define el titulo del botón en caso de no tener imagen y el texto que aparecerá cuando nos ponemos sobre el botón
  • En "image" daremos la imagen que se visualizará en el botón. Utilicen esta:
  • En "onclick" se escribe la función que se ejecutará cuando el usuario haga click sobre el botón. En este caso estoy usando una función medianamente conocida llamada "tb_show", esta función se utiliza para llamar diálogos usando el plugin "thickbox" que por defecto viene habilitado dentro de WordPress.
  • La sintaxis de tb_show pide como primer parámetro un identificador único para el diálogo y como segundo parámetro la configuración de qué elemento debe mostrarse como thickbox. En este caso particular le diremos que es un elemento en que se encuentra en la misma página de forma oculta y que su "ID" es "aplaceholder-form" (elemento que aún no existe pero lo crearemos después)

En cuánto al método "createControl", lo dejamos nulo pero definido.

El segundo paso es agregar este botón recién creado a nuestra barra de herramientas del editor, para lograr esto agregaremos debajo del código recién creado el siguiente código:

tinymce.PluginManager.add('aplaceholder', tinymce.plugins.aplaceholder);

Que no es más que la invocación del plugin recien creado. Cuando tenemos todo esto listo y hemos ido paso por paso veremos por fin el primer resultado:

(Ahora pueden presionarlo harto porque no hará nada, pero se ve bonito ahí en el toolbar)

El tercer paso y final, para nuestro botón, es crear el dialogo que mostrará el contenido a configurar. He decidido solamente agregar los atributos de ancho y alto, para no hacer el tutorial más complejo, pero si se sienten con ganas de aprender, pueden agregar más funciones.

Entonces, para agregar el diálogo usaremos el shortcut de document ready de jQuery (¿voy muy rápido?) para agregar nuestro formulario al elemento body y ocultarlo después le daremos la funcionalidad para que se agregue al editor. ¿Veámoslo por parte?

  1. Agregar el shortcut de jQuery para document.ready

    jQuery(function() {
    });
  2. Dentro de este shortcut crearemos la variable "form" que tendrá el HTML del formulario:

    var form = jQuery('<div id="aplaceholder-form">
                        <table id="aplaceholder-table" class="form-table">
                            <tr>
                                <th><label for="aplaceholder-width">Width</label></th>
                                <td>
                                    <input type="text" id="aplaceholder-width" name="width" placeholder="200" /><br />
                                    <small>specify the width </small>
                                </td>
                            </tr>
                            <tr>
                                <th><label for="aplaceholder-height">Height</label></th>
                                <td>
                                    <input type="text" id="aplaceholder-height" name="height" placeholder="200"/><br />
                                    <small>specify the height </small>
                                </td>
                            </tr>
                        </table>
                        <p class="submit">
                            <input type="button" id="aplaceholder-submit" class="button-primary" value="Insertar Placeholder" name="submit" />
                        </p>
                        </div>');

    Si analizamos bien, en este formulario (que no contiene un elemento form) cada elemento de formulario tiene como "id" el prefijo "aplaceholder". Esto nos será útil para que cuando presionemos el botón "aplaceholder-submit" se puedan obtener los valores.
    Ojo con los saltos de línea que son reemplazados con backslash "" para evitar tener que concatenar texto.

  3. El siguiente paso es identificar la tabla que contiene nuestro elementos y dejarla en una variable para utilizarla después.

    var table = form.find('table');
  4. Luego agregamos nuestro "form" al body usando "appendTo" y lo ocultamos con "hide".

    form.appendTo('body').hide();
  5. A continuación agregaremos la función de "submit" que tendrá el input de id "aplaceholder-submit" para que cuando sea presionado agregue al editor el contenido con las configuraciones:

    form.find('#aplaceholder-submit').click(function() {
                var shortcode = '[aplaceholder';
                if (table.find('#aplaceholder-width').val() != '') {
                    shortcode += ' width='+table.find('#aplaceholder-width').val();
                }
                if (table.find('#aplaceholder-height').val() != '') {
                    shortcode += ' height='+table.find('#aplaceholder-height').val();
                }
                shortcode += '][/aplaceholder]';
    
                // agrega el contenido al editor activo
                tinyMCE.activeEditor.execCommand('mceInsertContent', 0, shortcode);
    
                // cierra el thickbox
                tb_remove();
     });

    Si analizan bien el código, lo que hacemos es crear la variable "shortcode" que se agrega al editor. A esta variable se le va concatenando los valores de "aplaceholder-width" y "aplaceholder-height" si es que éste valor está definido. Si ningun valor se define solo agregará el código sin atributos.

Luego, al juntar todo el código, lo veremos así:

(function() {
    tinymce.create('tinymce.plugins.aplaceholder', {
        init: function(ed, url) {
            ed.addButton('aplaceholder', {
                title: 'Add a Placeholder',
                image: url + '/placeholder.png',
                onclick: function() {
                    tb_show('aplaceholder', '#TB_inline?inlineId=aplaceholder-form');
                }
            });
        },
        createControl: function(n, cm) {
            return null;
        },
    });

    tinymce.PluginManager.add('aplaceholder', tinymce.plugins.aplaceholder);

    jQuery(function() {

        var form = jQuery('<div id="aplaceholder-form">
                    <table id="aplaceholder-table" class="form-table">
                        <tr>
                            <th><label for="aplaceholder-width">Width</label></th>
                            <td>
                                <input type="text" id="aplaceholder-width" name="width" placeholder="200" /><br />
                                <small>specify the width </small>
                            </td>
                        </tr>
                        <tr>
                            <th><label for="aplaceholder-height">Height</label></th>
                            <td>
                                <input type="text" id="aplaceholder-height" name="height" placeholder="200"/><br />
                                <small>specify the height </small>
                            </td>
                        </tr>
                    </table>
                    <p class="submit">
                        <input type="button" id="aplaceholder-submit" class="button-primary" value="Insertar Placeholder" name="submit" />
                    </p>
                    </div>');

        var table = form.find('table');
        form.appendTo('body').hide();

        form.find('#aplaceholder-submit').click(function() {
            var shortcode = '[aplaceholder';
            if (table.find('#aplaceholder-width').val() != '') {
                shortcode += ' width='+table.find('#aplaceholder-width').val();
            }
            if (table.find('#aplaceholder-height').val() != '') {
                shortcode += ' height='+table.find('#aplaceholder-height').val();
            }
            shortcode += '][/aplaceholder]';

            // agrega el contenido al editor activo
            tinyMCE.activeEditor.execCommand('mceInsertContent', 0, shortcode);

            // cierra el thickbox
            tb_remove();
        });
    });
})();

Y al presionar nuestro botón veremos algo como esto:

¡Esto es todo!

Conclusiones y agradecimientos

Luego de hacer este tutorial me di cuenta de varias cosas que quizas ustedes también notaron. Una de ellas fue que la complejidad del plugin está directamente relacionada a los objetivos que tengamos en mente. Mientras más características necesitemos crear, más es la complejidad del plugin y más es el tiempo de desarrollo.

Otro punto importante a destacar es que no es tanto el PHP que debemos saber, solo tenemos que tener en cuenta qué funciones de WordPress usar y, a grandes rasgos, cómo funcionan para que nuestro plugin funcione correctamente.

También debo agregar que sin jQuery nada de lo visual hubiese sido posible. El uso de funciones nativas como jQuery y plugins como TinyMCE o Thickbox nos ayudó bastante a lograr mucho con tan poco.

Finalmente agradezco a quienes han compartido este tutorial, a quienes han avanzado leyendo esto y quiero dar saludo especial a equistene que fue el que tuvo la idea inicial (Ojalá que te sirva y que ocupes la cuestión de plugin)

Eso es todo, ahora pueden descargarlo desde acá y visitar los capitulos anteriores:

Blog, Tutorial, Tutorial PHP
12 minutos