¿En qué podemos ayudarte?
Estructura de un plugin de WordPress
Para crear un plugin de WordPress es suficiente con crear un archivo nombre-del-plugin.php con la siguiente que incluya la cabecera siguiente
<?php
/*
Plugin Name: <Nombre del plugin (con este nombre aparecerá en la lista)>
Plugin URI: <URL del plugin (puede ser la del autor)>
Description: <Descripción breve del plugin y sus funcionalidades>
Version:<Versión del plugin>
Author:<Autor del plugin>
Author URI:<URL del autor del plugin>
License:<Licencia con la que se distribuye el plugin. La más frecuente es GPL>
Text domain: <nombre-del-plugin (para agrupar los textos traducibles del plugin)>
*/
Ese es el formato establecido por los desarrolladores de WordPress. Plugin Name es el único elemento obligatorio, pero lo mejor es completar todos los apartados
Podemos subirlo directamente a la carpeta /wp-content/plugins o comprimirlo en formato zip e instalarlo según el procedimiento habitual. A partir de ese momento lo veremos entre los plugins instalados y podremos gestionarlo como haríamos con cualquier otro plugin.
Para tareas sencillas puede ser suficiente con un único archivo, pero es mucho mñas frecuente que el plugin esté formado por varios archivos de diferentes tipos. En ese caso crearemos una carpeta y colocaremos dentro los archivos necesario. La guía de buenas prácticas de la documentación de WordPress sugiere la siguiente estructura:
/nombre-del-plugin
nombre-del-plugin.php
uninstall.php
/languages
/includes
/admin
/js
/css
/images
/public
/js
/css
/images
Donde
- nombre-del-plugin.php : Es el archivo principal del plugin y el único que incluirá la cabecera. Si no es así WordPress pensará que estamos instalando varios plugins
- uninstall.php: Es el archivo que se encargará de las tareas de limpieza cuando el plugin sea eliminado. Es llamado automaticamente por WordPress cuando eliminamos el plugin.
- languages: Si daremos soporte a varios idiomas, en esta carpeta colocaremos los archivos necesarios
- includes: Carpeta con archivos auxiliares. Suelen ser incorporados mediante la instrucción include de PHP
- admin: Aquí colocaremos los archivos que gestionarán el funcionamiento del plugin dentro del panel de administración de Wrodpress
- public: Aquí colocaremos los archivos que se encargan del front-end del plugin
Las carpetas admin y public contienen subcarpetas para los tipos de archivos más habituales.
Esta estructura no es obligatoria. Como desarrolladores tenemos total libertad para organizar nuestros archivos de la fomra que creamos más conveniente, pero seguir el estándar facilita las tareas de mantenimiento y el trabajo en grupo. Lógicamente, si no necesitamos una carpeta no tenemos por qué crearla.
Hooks (Ganchos) de WordPress importantes para un plugin
WordPress es un ejemplo casi perfecto de "caja negra". En un sistema de este tipo no necesitamos conocer sus detalles internos.Tenemos puntos de entrada predefinidos y podemos prever el resultado dependiendo de los datos introducidos.
WordPress pone a nuestra disposición puntos de entrada a los que podemos acoplar nuestro código y de esta forma nos permite modificar su comportamiento, sin necesidar de tocar su código interno. Son los famosos hooks y existen dos tipos de ellos:
- filtros: Permiten modificar el contenido antes que sea mostrado al usuario. Por ejemplo, podemos personalizar un mensaje añadiendo el nombre del usuario
- actions: Permiten la realización de determinadas acciones o tareas complementarias, normalmente en segundo plano. Por ejemplo, enviar una notificación al administrador cuando se guarda un comentario.
Hay dos hooks de uso común en un plugin:
- register_activation_hook: Es de tipo action y sirve por ejemplo para crear y almacenar las opciones por defecto del plugin cuando activamos el plugin (no cuando lo instalamos)
- register_deactivation_hook: Es otra action que se ejecuta cuando desactivamos el plugin. Aunque el nombre pueda confundirnos, su función no es revertir las acciones del hook de activación (esa es la tarea de uninstall.php). Este hook está pensado para borrar caches, eliminar opciones temporales y en general hacer limpieza de los datos generados por el funcioamiento del plugin.
Por ejemplo: register_activation_hook crea una tabla para almacenar las entradas favoritas de los usuarios, register_deactivation_hook elimina los registros de la tabla y uninstall.php borra la tabla de la base de datos.
WordPress tiene mas de 2.000 hooks, que podemos consultar en hook.io. Cuales usemos dependerá de los objetivos de nuestro plugin. Incluso es posible que no necesitemos implementar las funciones de activación, desactivación y/o desinstalación.
Plugin para eliminar roles
Veamos como funciona en un plugin sencillo que nos permitirá eliminar los roles que no necesitemos en WordPress. Aunque es sencillo, nos permitirá ver diferentes elementos en acción. Este plugin tendrá las siguientes características:
- Mostrará la lista de los roles existentes en nuestra instalación y el número de usuarios que tienen asignado
- Si no es uno de los roles nativos de WordPress (suscriptor, colaborador, autor, editor, administrador), permitirá eliminarlo siempre y cuando no tengan usuarios asignados
- Solo será visible para usuarios administradores, desde el back.end
Comenzaremos creando la carpeta rjc-delete-roles y dentro de ella el archivo rjc-delete-roles.php. Su contenido inicial será el siguiente:
<?php
/*
Plugin Name: RJCardenas - Delete WordPress roles
Plugin URI: https://wwww.rjcardenas.com
Description: Plugin para borrar roles de usuario
Version: 1.0
Author: Rolando Cárdenas
Author URI: https://wwww.rjcardenas.com
License: GPLv2
Text domain: rjc-delete-roles
*/
defined('ABSPATH') or die("Por aquí no vamos a ninguna parte");
define('RJC_DIR',plugin_dir_path(__FILE__));
La penúltima línea evita que un usuario malintencionado pueda ejecutar directamente el archivo escribiendo su ruta en el navegador. Una medida básica de seguridad es incluirla al inicio de todos los archivos del plugin. También hemos definido la constante RJC_DIR que contendrá la ruta completa a la carpeta del plugin en nuestra instalación.
Ya podemos comprimir la carpeta en un zip e instalar el plugin. Inmediatamente nos aparece en la lista.
Su activación no tiene efectos, porque aún no le hemos añadido ninguna funcionalidad. Comencemos por crear la página de administración.
Página de administración
Vamos a añadir las funcionalidades requeridas, comenzando la página de visualización que colgaremos del menú Herramientas, Para ello añadimos el siguiente bloque de código a rjc-delete-roles.php
add_action( 'admin_menu', 'rjc_menu_administrador' );
function rjc_menu_administrador() {
add_submenu_page('tools.php','Gestión de Roles','RJC Eliminar roles','administrator',RJC_DIR.'/admin/gestionar.php');
}
Hemos usado la función add_submenu_page(string $parent_slug, string $page_title, string $menu_title, string $capability, string $menu_slug, callable $function = '') donde:
- $parent_slug: Elslug del menu padre o el nombre del archivo php correspondiente. Para las elementos estandard Wordpres tenemos:
- Escritorio; 'index.php'
- Entradas: 'edit.php'
- Medios: 'uploads.php'
- Páginas: ‘edit.php?post_type=page’
- Comentarios: ‘edit-comments.php’
- Tipos de Entradas Personalizadas: ‘edit.php?post_type=slug-entrada-personalizada’
- Apariencia: ‘themes.php’
- Plugins: ‘plugins.php’
- Usuarios: ‘users.php’
- Herramientas: ‘tools.php’
- Ajustes: ‘options-general.php’
- $page_title: El título que tendrá la página en la pestaña del navegador
- $menu_title: El texto que aparecerá en el menu lateral
- $capability: Los permisos que debe tener el usuario para poder ver este menú
- $menu_slug: Slug o archivo php correspondiente a la opción. Debe ser único
- $function: Es el único parámetro opcional. No es necesario si la página se crea o se enlaza desde la opción anterior
Código del plugin
Ahora debemos, crear el archivo rjc-delete-roles/admin/gestionar.php, el cual se encargará de mostrar los roles existentes y proceder a su eliminación selectiva. Su contenido es el siguiente:
<?php
defined('ABSPATH') or die("Por aquí no vamos a ninguna parte");
if (!current_user_can ('administrator')) {wp_die (__('No tienes suficientes permisos para acceder a esta página.', 'rjc-delete-roles'));}
if (isset($_REQUEST['rol']) && $_REQUEST['rol']!=='administrator') {remove_role($_REQUEST['rol']);}
$roles=[];
$lista='';
foreach (get_editable_roles() as $key => $rol) {
$roles[]=['slug'=>$key,'rol'=>$rol['name']];
$users = count(get_users(['role'=>$key]));
$Ok=($users<1 && !in_array($key, ['administrator','editor','author','subscriber','contributor']));
$url='tools.php?page='.urlencode ($_REQUEST['page']).'&rol='.$key;
if (!$Ok) {$Elimina='';} else {$Elimina='<a href="'.$url.'">Eliminar</a>';}
$lista.='<tr><td>'.$key.'</td><td>'.$rol['name'].'</td><td>'.$users.'</td><td>'.$Elimina.'</td>';
}
?>
<div class="wrap">
<h2><?php _e('Gestionar roles','rjc-delete-roles') ?></h2>
<table class="wp-list-table widefat fixed striped media">
<thead><tr><th>Slug</th><th>Rol</th><th>Usuarios</th><th>Acción</th></tr></thead>
<tbody><?php echo $lista; ?></tbody>
</table>
</div>
Su funcionamiento es simple. Primero comprobamos que no estamos ante una llamada directa y a continuación usamos la función current_user_can para determinar si el usuario actual tiene permisos de administrador. Si no se cumplen estas condiciones abortamos.
Seguidamente verificamos los parámetros de entrada y si se nos indica un rol diferente de "administrator" procedemos a su eliminación usando la función remove_role.
Utilizamos get_editable_roles. para obtener los roles existente y para cada uno de ellos obtenemos la cantidad de usuarios que lo tienen asignado, para lo cual usamos get_users. Si no es uno de los roles nativos y no tiene usuarios asignados, se genera la url correspondiente con el enlace para eliminarlo.
En el código se muestran dos funciones útiles si queremos que nuestro código tenga capacidades multilenguage:
- __('Texto a traducir','dominio-de-texto') : Esta función recibe 2 argumentos, una cadena de texto y dominio de texto. Al ejecutar esta función WordPress buscará si existe una traducción disponible en el idioma actual. Si es así devolvera el texto traducido y si no la encuentra usará el texto original. El dominio sirve para identificar el contexto de nuestros textos y diferenciarlos de los utilizados por otros plugins o temas.
- _e('Texto a traducir','dominio-de-texto') : Es similar a la anterior, solo que el resultado se muestra directamente en pantalla.
Usando estas y otras funciones de traducción de WordPress podermos dar soporte a varios idiomas. Lo haremos utilizando Poedit para crear los archivos PO/MO correspondientes, mediante la traducción de cadenas de WPML o con cualquier otra herramienta que consideremos más apropiada.
El resto del código muestra los resultados organizados en una tabla y con esto ya tenemos el plugin listo para ser utilizado.
Conclusión
Como hemos visto desarrollar un plugin en WordPress es muy sencillo. Basta con crear un archivo con una cabecera específica, aunque lo más común es que utilizemos varios archivos, dependiendo de las tareas que realizará el plugin.
El plugin que hemos desarrollado puede ser útil cuando no necesitamos una gestion completa de los roles y capacidades de WordPress. Puede servir como punto de partida si necesitamos implementar nuevas funcionalidades. Usar un plugin nos garantiza que nuestras modificaciones seguirán disponibles si cambiamos el tema activo en nuestra instalación.
El plugin que acabamos de crear está disponible aquí.