---
title: "Cuaderno Técnico: Plugin «Agenda Indaga» (v1.3.0), parte I"
description: "Valencia, 21/10/2026, G.B. Empiezo una serie de cuadernos técnicos para explicar paso a paso los plugins de Indaga.net . Es una forma práctica de documentar el proceso, compartir el aprendizaje y, de..."
url: https://indaga.net/cuaderno-tecnico-plugin-agenda-indaga-v1-3-0-parte-i/
date: 2026-10-21
modified: 2026-10-20
author: "Directorio Indaga"
categories: ["Recursos y Utilidades", "WordPress"]
tags: ["agenda indaga", "blog", "cuadernos técnicos", "plugins indaga", "plugins wordpress", "wordpress"]
type: post
lang: es
---

# Cuaderno Técnico: Plugin «Agenda Indaga» (v1.3.0), parte I

Valencia, 21/10/2026, G.B.

Empiezo una serie de cuadernos técnicos para explicar paso a paso los plugins de **Indaga.net**. Es una forma práctica de documentar el proceso, compartir el aprendizaje y, de paso, ver de un vistazo qué se puede mejorar o dónde falló algo en su día. Aquí va la primera parte del plugin **Agenda Indaga**.

## Bloque 1: Cabecera, Seguridad y Estructura de la Clase Principal

Todo buen plugin de WordPress empieza con una cabecera limpia y un pequeño control de seguridad para evitar que nadie acceda al archivo directamente desde el navegador.

### 1. Cabecera del Plugin e Identificación

En las primeras líneas definimos los metadatos que lee WordPress en el listado de plugins. Destaca el uso del dominio de texto (`indaga-agenda`) y la especificación de autoría de **Indaga.net**:

```
<?php
/**
* Plugin Name: Agenda Indaga
* Plugin URI: https://indaga.net
* Description: Plugin nativo de agenda y eventos con soporte multinstancia avanzada...
* Version: 1.3.0
* Author: Guillermo Beltrán Pilato (Indaga.net)
* Author URI: https://indaga.net
* License: GPLv2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: indaga-agenda
*/
```

### 2. Bloqueo de Acceso Directo

La seguridad en WordPress empieza por proteger los archivos individuales frente a peticiones HTTP directas que no pasen por el núcleo del CMS. Si la constante global `ABSPATH` no está definida, abortamos la ejecución de inmediato:

```
if ( ! defined( 'ABSPATH' ) ) {
exit; // Seguridad: Evitar acceso directo
}
```

### 3. Patrón Singleton (`IndagaAgenda`)

Para evitar duplicidad de instancias y mantener el código ordenado y eficiente en memoria, implementamos el patrón **Singleton**. Esto garantiza que la clase solo se cargue una vez:

```
class IndagaAgenda {
private static $instance = null;

public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}

private function __construct() {
// Aquí engancharemos nuestros hooks de activación, menús y shortcodes
register_activation_hook( __FILE__, array( $this, 'activar_plugin' ) );
add_action( 'admin_menu', array( $this, 'registrar_menu_admin' ) );
add_shortcode( 'indaga_agenda', array( $this, 'renderizar_shortcode_agenda' ) );
add_shortcode( 'calendario_agenda', array( $this, 'renderizar_shortcode_calendario' ) );
}
}

// Inicializamos el plugin
IndagaAgenda::get_instance();
```

## Bloque 2: Creación Nativa de la Base de Datos (`activar_plugin`)

Una de las premisas clave de los plugins en Indaga.net es **cero dependencias externas**: toda la información reside en nuestras propias tablas optimizadas dentro de la base de datos de WordPress.

Cuando el usuario activa el plugin por primera vez, se dispara el gancho (`register_activation_hook`) que ejecuta el siguiente método:

```
public function activar_plugin() {
global $wpdb;
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );

$tabla = $wpdb->prefix . 'indaga_agenda';
$charset_collate = $wpdb->get_charset_collate();

$sql = "CREATE TABLE $tabla (
id mediumint(9) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
grupo_id varchar(50) DEFAULT 'default' NOT NULL,
titulo varchar(255) NOT NULL,
descripcion text NOT NULL,
fecha_inicio datetime NOT NULL,
fecha_fin datetime NOT NULL,
categoria varchar(50) DEFAULT 'general' NOT NULL,
observaciones text DEFAULT '',
PRIMARY KEY (id),
KEY user_id (user_id),
KEY grupo_id (grupo_id),
KEY fecha_inicio (fecha_inicio)
) $charset_collate;";

dbDelta( $sql );
update_option( 'indaga_agenda_version', '1.3.0' );
}
```

### ¿Qué ocurre paso a paso en este método?

1. **`global $wpdb;`**: Cargamos la clase global de WordPress para interactuar de forma segura con la base de datos.
2. **`$wpdb->prefix`**: Añadimos el prefijo personalizado de las tablas de tu instalación de WordPress (por defecto solía ser `wp_`, resultando en `wp_indaga_agenda`), garantizando compatibilidad con cualquier entorno.
3. **`dbDelta( $sql );`**: Es la función nativa recomendada de WordPress. Compara si la tabla ya existe o si necesita actualizar su esquema sin destruir los datos ya almacenados.
4. **Campos clave (`grupo_id`)**: Este campo es el corazón del **soporte multinstancia avanzada**, ya que nos permite filtrar y agrupar múltiples agendas independientes dentro de una misma tabla.

*Continuaré*…
