Tiempo de lectura: 5 min
Entrega 2: El Panel de Administración y la Gestión Multinstancia
En la primera entrega vimos los cimientos del plugin: la estructura principal con la clase IndagaAgenda, la seguridad inicial para bloquear accesos directos y la creación nativa de la tabla en la base de datos.
En este segundo bloque me centro en cómo está construido el panel de administración en el backend de WordPress (ubicado en Ajustes > Agenda Indaga), explicando el menú nativo, la estructura modular por pestañas y el control de las distintas instancias o grupos de eventos.
1. Registro del Menú en el Panel de Administración
Para integrar la interfaz dentro del escritorio de WordPress sin cargar librerías adicionales, utilizo la API nativa de menús a través del gancho admin_menu:
public function registrar_menu_admin() {
add_menu_page(
'Agenda Indaga', // Título de la página
'Agenda Indaga', // Título del menú
'manage_options', // Capacidad / Permiso requerido
'indaga-agenda', // Slug único del menú
array( $this, 'renderizar_panel_admin' ), // Función de callback
'dashicons-calendar-alt', // Icono nativo de Dashicons
6 // Posición en la barra lateral
);
}
Puntos clave:
manage_options: Garantizo que solo las cuentas con perfil de administración puedan acceder a este panel de control.dashicons-calendar-alt: Aprovecho la librería de iconos nativa de WordPress (Dashicons), manteniendo el plugin sin dependencias externas.
2. Estructura Modular por Pestañas
Para que la experiencia de uso sea limpia e intuitiva, organizo el panel de administración en tres pestañas bien diferenciadas usando la navegación nativa de WordPress (nav-tab-wrapper):
- Gestión e Instancias: Control global de los eventos y de las instancias creadas.
- Instrucciones y Shortcodes: Guía rápida para saber cómo insertar los shortcodes.
- Ficha Técnica: Resumen de especificaciones del desarrollo.
El cambio entre pestañas se gestiona capturando el parámetro tab mediante la URL (p. ej., ?page=indaga-agenda&tab=instrucciones), sanitizándolo adecuadamente:
$tab = isset( $_GET['tab'] ) ? sanitize_text_field( $_GET['tab'] ) : 'gestion';
?>
<h2 class="nav-tab-wrapper">
<a href="?page=indaga-agenda&tab=gestion" class="nav-tab <?php echo $tab === 'gestion' ? 'nav-tab-active' : ''; ?>">Gestión e Instancias</a>
<a href="?page=indaga-agenda&tab=instrucciones" class="nav-tab <?php echo $tab === 'instrucciones' ? 'nav-tab-active' : ''; ?>">Instrucciones y Shortcodes</a>
<a href="?page=indaga-agenda&tab=tecnica" class="nav-tab <?php echo $tab === 'tecnica' ? 'nav-tab-active' : ''; ?>">Ficha Técnica</a>
</h2>
3. Procesamiento Seguro de Acciones (Eliminación con Nonces)
Antes de pintar la vista o consultar los datos, verifico si se ha enviado alguna petición desde los formularios de administración (por ejemplo, para eliminar un evento suelto o una instancia completa).
La seguridad aquí descansa en dos pilares: comprobación de permisos y validación de Nonce para evitar ataques CSRF:
if ( isset( $_POST['indaga_agenda_nonce'] ) && wp_verify_nonce( $_POST['indaga_agenda_nonce'], 'indaga_agenda_admin_action' ) ) {
// Eliminación de un evento individual
if ( isset( $_POST['accion'] ) && $_POST['accion'] === 'eliminar_evento' && !empty( $_POST['evento_id'] ) ) {
$evento_id = absint( $_POST['evento_id'] );
$wpdb->delete( $tabla, array( 'id' => $evento_id ), array( '%d' ) );
$mensaje = '<div class="updated notice"><p>Evento eliminado correctamente.</p></div>';
// Eliminación de una instancia completa (y todos sus eventos asociados)
} elseif ( isset( $_POST['accion'] ) && $_POST['accion'] === 'eliminar_instancia' && !empty( $_POST['grupo_id'] ) ) {
$grupo_id = sanitize_text_field( $_POST['grupo_id'] );
$wpdb->delete( $tabla, array( 'grupo_id' => $grupo_id ), array( '%s' ) );
$mensaje = '<div class="updated notice"><p>Instancia completa y todos sus eventos asociados eliminados correctamente.</p></div>';
}
}
wp_verify_nonce(): Garantiza que la petición se ha originado legítimamente dentro del panel y por un usuario autorizado.absint()ysanitize_text_field(): Aseguran que los datos recibidos sean enteros positivos o cadenas limpias sin código malicioso.
4. Consulta Agrupada para la Gestión Multinstancia
El valor diferencial de la versión 1.3.0 es el soporte multinstancia. Mediante una consulta SQL optimizada con agrupamiento (GROUP BY), obtengo la lista de todas las agendas o grupos existentes en la base de datos sin necesidad de tablas auxiliares:
$instancias = $wpdb->get_results(
"SELECT grupo_id, COUNT(*) as total_eventos, MIN(fecha_inicio) as primer_evento
FROM $tabla
GROUP BY grupo_id
ORDER BY grupo_id ASC"
);
Con esto puedo renderizar una tabla clara que indica el nombre del grupo, cuántos eventos almacena y qué shortcode exacto debe copiarse para mostrar esa agenda concreta en el frontend:
<?php foreach ( $instancias as $inst ): ?>
<tr>
<td><strong><?php echo esc_html( $inst->grupo_id ); ?></strong></td>
<td><?php echo esc_html( $inst->total_eventos ); ?> evento(s)</td>
<td><code>Acceso restringido: no tienes permisos para gestionar los eventos de esta agenda. Iniciar sesión</code></td>
<td><code>
</code></td>
<td>
<form method="POST" style="display:inline;" onsubmit="return confirm('¿Estás seguro de eliminar esta instancia completa y todos sus eventos?');">
<?php wp_nonce_field( 'indaga_agenda_admin_action', 'indaga_agenda_nonce' ); ?>
<input type="hidden" name="accion" value="eliminar_instancia">
<input type="hidden" name="grupo_id" value="<?php echo esc_attr( $inst->grupo_id ); ?>">
<button type="submit" class="button button-small button-link-delete">Eliminar Instancia</button>
</form>
</td>
</tr>
<?php endforeach; ?>
Con esto queda cubierto todo el funcionamiento del panel de administración y el control multinstancia desde el backend.
En la siguiente entrega abordaremos la tercera parte del cuaderno técnico: los Shortcodes de Frontend (indaga_agenda y calendario_agenda) (entre corchetes), analizando el formulario de alta de eventos y el calendario mensual interactivo programado en JavaScript nativo.
Hasta pronto!
