Creando un plugin para WordPress

Creando un plugin para WordPress parte 3: Escribiendo el plugin

Ya tenemos la planificación de nuestro plugin hecha, lo siguiente es elegir el nombre. El nombre de nuestro plugin debe ser único, por lo tanto hemos de buscar dentro del repositorio de WordPress que no haya uno que se llame igual. También podemos mirar el listado completo aquí.

directorio plugins

Una vez decidido el nombre (para este ejemplo voy a usar my-plugin), crearemos una carpeta «my-plugin» y dentro de ella crearemos las subcarpetas:

  • admin, para los php con funcionalidad de back-end
  • css, para almacenar allí nuestras hojas de estilos
  • includes, para archivos php auxiliares
  • js, para almacenar nuestros scripts js
  • languages, para la internacionalización de nuestro plugin
  • public, para los php con funcionalidad de front-end

También en la raíz de nuestro plugin tendremos al menos un index.php vacío (Silence is golden), my-plugin.php, que es el fichero principal de nuestro plugin, y un uninstall.php que se ejecutará cuando un usuario borre nuestro plugin para realizar acciones de limpieza en BBDD.

En la raíz de nuestro plugin y en todas las subcarpetas que contengan archivos PHP crearemos un index.php con el siguiente contenido para evitar que un usuario ejecute la ruta desde un navegador y pudiera acceder al listado de ficheros:

<?php

// Silence is golden

Además, vamos a añadir a todos los archivos PHP de nuestro plugin la siguiente línea al principio del todo (o debajo del declare de strict_types y namespaces si los utilizas):

<?php

defined( 'ABSPATH' ) or die( 'No script kiddies please!' );

Esto es para evitar que un usuario pueda ejecutar un PHP introduciendo la ruta directamente en el navegador. Imaginad que tenéis un PHP que lanza un proceso, guarda info en BBDD o elimina información como el uninstall.php y un usuario malintencionado lo ejecuta simplemente escribiendo la ruta en el navegador, podría causarnos una gran avería.

Volvemos al archivo principal de nuestro plugin my-plugin.php. Debe llamarse como nuestro plugin y estar en la raíz. Éste archivo contendrá las cabeceras de información de nuestro plugin:

<?php
/*
Plugin Name: My Plugin
Plugin URI:  http://www.my-domain.com/my-plugin/
Description: Breve descripción del plugin
Version:     1.0
Author:      Pablo López
Author URI:  https://desarrollowp.com
License:     GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Domain Path: /languages
Text Domain: my-plugin
*/

defined( 'ABSPATH' ) or die( 'No script kiddies please!' );

También es muy recomendable añadir dos funciones muy útiles para plugins, que se ejecutan cuando un usuario activa o desactiva el plugin. No confundir con la acción «cuando un usuario elimina el plugin» que veremos más adelante:

<?php

function activate_my_plugin() {
    // Lo que quiero que haga el plugin cuando un usuario lo activa
}
register_activation_hook( __FILE__, 'activate_my_plugin' );

function deactivate_my_plugin() {
    // Lo que quiero que haga el plugin cuando un usuario lo desactiva
}
register_deactivation_hook( __FILE__, 'deactivate_my_plugin' );

Nos permiten realizar acciones cuando un usuario activa o desactiva el plugin.

A partir de éste punto es importante que te organices el código. Crea una función para cada cosa (usa nombre descriptivos) y coméntala. Así el día de mañana si tienes que modificar algo, o si trabajas en equipo y un compañero tiene que retomar tu trabajo, de un vistazo verá para que sirve cada función y lo que hace. Crea una función para cada proceso o acción que realice el plugin:

  • Definir el textdomain
  • Añadir secciones en el back-end
  • Registrar Custom Post Types
  • Creación de Metaboxes
  • Añadir tus propios CSS y JS (wp_enqueue_scripts())
  • Añadir configuraciones al personalizador
  • etc…

De este modo tendremos todo organizado y un código más limpio y mantenible.

Seguridad y Rendimiento

Aún quedan dos factores muy importantes que debemos tener en cuenta: seguridad y rendimiento. Respecto al primero, sobre todo si nuestro plugin hace un tratamiento de datos, debemos tener las siguientes precauciones:

  • Comprueba los permisos de usuario, y qué rol puede ejecutar las distintas acciones: current_user_can()
  • Valida cualquier dato introducido por el usuario: HTML5 + JS + PHP + funciones de WP
  • Sanitiza al guardar en BBDD
    • sanitize_title()
    • sanitize_text_field()
    • sanitize_email()
    • sanitize_user()
    • etc…
  • Escapa los datos cuando los muestres en pantalla:
    • esc_html()
    • esc_url()
    • esc_js()
    • esc_attr()
    • etc…
  • Usa nonces en los formularios

No nos podemos olvidar del rendimiento de nuestro plugin. Más ahora que está en auge cualquier acción que influya en el rendimiento y velocidad de tu sitio. Por lo tanto si tu plugin usa imágenes y tienes CSS y JS propio, es aconsejable que utilices gulp o grunt para tareas como:

  • Optimización de imágenes
  • Procesado de estilos (sass)
  • Concatenado de CSS y JS
  • Minificar archivos CSS y JS

Aunque tengamos varias hojas de estilos o varias librerías JS, podemos concatenarlas y minificarlas para sólo cargar dos archivos, reduciendo el número de peticiones HTTP y el peso de los mismos.

Sé aseado

Por último crea en la raíz un archivo uninstall.php para borrar las configuraciones, datos y tablas cuando un usuario lo desinstala, y de este modo no dejar rastros en BBDD. No confundir con las acciones que hemos visto anteriormente de activar/desactivar un plugin. Este fichero será ejecutado de manera automática cuando un usuario borra el plugin desde el panel de administración de WordPress.

En muchas ocasiones andas buscando un plugin para hacer algo concreto y terminas instalando 4 ó 5 para probar cual es el que mejor te encaja…y puedes dejar rastros que «engordan» tu BBDD almacenando datos y/o añadiendo tablas. Para no dejar rastros elimina todo lo que hayas creado con tu plugin:

<?php

// If uninstall is not called from WordPress, exit
if ( !defined( 'WP_UNINSTALL_PLUGIN' ) ) {
    exit();
}
 
delete_option( 'plugin_option_name' );
 
// For site options in Multisite
delete_site_option( $option_name );  
 
// Drop a custom db table
global $wpdb;
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}mytable" );

// Para borrar meta datos concretos por ejemplo de post_type=post
$args = array(
    'posts_per_page' => -1,
    'post_type' => 'post',
    'post_status' => 'any'
);
$posts = get_posts( $args );

foreach( $posts as $post ) {
    delete_post_meta( $post->ID, 'my_post_meta' );
}

// Para borrar los post de un post_type concreto incluyendo comentarios, meta datos y relaciones con otros post y taxonomias
$args = array(
    'posts_per_page' => -1,
    'post_type' => 'my_post_type',
    'post_status' => 'any'
);
$posts = get_posts( $args );

foreach( $posts as $post ) {
	wp_delete_post( $post->ID, true );
}

¿Te ha resultado útil esta información? 🍺

Si este post te ha resuelto un problema, invítame a un café o a una cerveza. Con este pequeño gesto me animas a seguir escribiendo.

Comentarios

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *:

  • El fin del tratamiento es únicamente la moderación de comentarios para evitar spam
  • La legitimación es tu consentimiento al comentar
  • No se comunicará ningún dato a terceros salvo por obligación legal
  • Tienes derecho al acceso, rectificación y eliminación de los comentarios