La clase Agora

Introducción

Como se explica en la sección Introducción, todo Ágora se contiene en el archivo agora.php, el cual contiene una parte de configuración y la descripción de la clase estática Agora.  Para conocer la parte de configuración deberá leer la sección correspondiente en la sección Introducción, ya que aquí se detalla la funcionalidad de la clase Agora.

Recuerde que, al ser una clase estática, es posible utilizar Agora de tres formas diferentes, cada una con sus ventajas e inconvenientes:

  1. Llamándo diréctamente a los métodos, a través del operador ::.  Por ejemplo: echo Agora::filtroXSS ($resultado);.
  2. Creando un objeto.  Por ejemplo: $a = new Agora (); y después: echo $a->filtroXSS ($resultado);.
  3. Extendiendo la clase en otra: class MiClase extends Agora { ... }

Es muy recomendable que consulte, también, el ejemplo y el propio código fuente de agora.php.

Agora::config ()

La clase Agora define un método para facilitar el acceso a datos de configuración para su página web (no confundir con la configuración de Ágora).  La definición de este método es:


public static function config (string $aNombre, mixed $aDefecto = false): mixed
    

Este método toma los datos de un diccionario o array asociativo global llamado $config.  Este diccionario no está definido en agora.php.  Una buena idea es definir este diccionario con su contenido en un archivo (por ejemplo, en config.php) que después sea incluido junto con agora.php.  Si no se define el diccionario $config, o este no contiene el valor solicitado, el método devolverá el valor $aDefecto, por lo que no se producirá ningún error.

Filtro XSS

Ágora incluye un sencillo filtro contra ataques tipo XSS, el cual puede ser invocado por los métodos de acceso a GET, POST y huellas.  También puede invocarse directamente usando el método filtraXSS.

Como digo, este filtro es muy sencillo y se limita a sustituir algunos caracteres especiales para evitar la inyección de código HTML (por ejemplo, <script> y <iframe>) e incluso PHP.  A pesar de la sencillez del mismo, es bastante eficiente en muchos de los casos más comunes pero no en todos y mucho menos en los más sofisticados.  Aun así es bastante seguro utilizarlo cuando se muestre texto mediante echo ya que se mostrará tal cuál fue escrito, sin interpretar.  Esto también lo hace útil para mostrar código fuente HTML, PHP o de cualquier otro lenguaje sin temor a que sea interpretado en el cliente o por PHP.

Si necesita una protección mayor puede modificar o extender el método filtraXSS para que haga uso de algoritmos más complejos o bibliotecas especialidadas.  Las razones por la que no se ha hecho así desde el principio es que los filtros XSS más sofisticados suelen ser relativamente lentos, porque dependiendo del uso estos filtros pueden ser diferentes ya que no sirven los mismos filtros para HTML que para SQL, por ejemplo, y también porque el método usado ahora es rápido y razonablemente efectivo.

GET y POST

Aunque acceder a los parámetros GET y POST es bastante simple y seguro (siempre que PHP esté correctamente configurado), Ágora incluye tres métodos para acceder a estos: get, post y get_post.

Los tres reciben los mismos parámetros: primero el nombre del parámetro a consultar, y en segundo lugar un valor booleano para indicar si se desea que se filtre su contenido usando filtraXSS.  En cualquier caso, el método devolverá el valor del parámetro (o todos los valores, si se pasa el valor null) o el valor booleano false en el caso de que el valor solicitado no exista.

Huellas (cookies)

El uso de huellas o cookies es algo complejo.  Ágora define varios métodos para tratar de facilitar el trabajo:

Agora::ponParametroHuellas ($aParametro, $aValor)
Permite establecer varios parámetros referentes a huellas, a saber:
  • 'caducidad': Tiempo por defecto que se mantendrá el valor de la huella, en segundos.
  • 'dominio': Indica el dominio para las huellas.
  • 'ruta': Indica la ruta (path) para las huellas.
  • 'https': Indica si debe usarse el protocolo HTTPS.
  • 'javascript': Indica si se podrá o no acceder a los valores a través de JavaScript.
Pueden pasarse todos los valores a la vez en forma de diccionario, si se desea.  Para conocer mejor las consecuencias de cada parámetro, consulte la documentación acerca de huellas, como por ejemplo la función PHP setcoockie.
Agora::tomaParametroHuellas ($aParametro)
Devuelve el valor del parámetro de configuración indicado o, si no se indica ningún parámetro, todos los parámetros en forma de diccionario.
Agora::ponHuella ($aNombre, $aValor, $aCaducidad)
Establece o modifica una huella.  La caducidad viene dada en tiempo UNIX;  Es decir, si se quiere que la huella dure un día deberá usarse el valor time () + (24 * 60 * 60), mientras que un valor de 0 hará que las huella se elimine al cerrar el navegador.
Agora::tomaHuella ($aNombre, $aFiltraXSS)
Devuelve el valor de la huella (o todas, si el nombre es el valor NULL) o el valor booleano FALSE si esta no existe.  El parámetro $aFitraXSS indica si pasar o no el filtro XSS; si no se indica entonces devolverá el valor sin filtrar.
Agora::eliminaHuella ($aNombre)
Elimina la huella indicada independientemente de cuál sea su caducidad.  Si como nombre se le pasa una lista, entonces eliminará todas las huellas indicadas en la misma.
Agora::limpiaHuellas ()
Elimina todas las huellas a las que tenga acceso.

Vistas

El uso de vistas es una de las características más potentes definidas en Ágora.  Una vista no es más que un archivo PHP, por lo que es similar al uso de los archivos incluidos y requeridos, solo que con las siguientes características:

El método para la carga de vistas se define como:


public static function cargaVista (string $aVista, array $aVars, bool $aDevolver): string
    

El nombre de la vista es el mismo que el del archivo, solo que sin extensión.  Si se desea, se puede crear una gerarquía de vistas creando subdirectorios dentro del directorio que contiene las vistas.  En tal caso, basta con indicar el subdirectorio donde se encuentra la vista.  Por ejemplo:


  Agora::cargaVista (
    'noticias/articulo',
    array ('titulo'=> $tituloArticulo, 'texto' => $textoArticulo)
  );
    

Esa línea buscará el archivo articulo.php dentro del subdirectorio noticias dentro, a su vez, del directorio definido por AG_DIR_VISTAS.

Pueden cargarse tantas vistas como se desee y en el orden que se desee.  Por ejemplo:


<?php
  include_once ('agora.php');
  require_once ('lib/stuff.php');

  try {
    Agora::cargaVista ('cabecera', array ('titulo' => 'Noticias'));

    $listaNoticias = obtieneListaNoticias ();
    foreach ($listaNoticias as $noticia):
      Agora::cargaVista ('noticias/resumen', array (
	'titulo' => $noticia->titulo,
	'autor' => $noticia->autor,
	'fecha' => $noticia->fecha,
	'texto' => $noticia->texto
      ));
    endforeach;
    Agora::cargaVista ('pie');
  }
  catch (\Exception $error) {
    echo "<p><strong>Se capturó una excepción:</strong><br />{$error->getMessage ()}</p>";
  }
    

Donde el archivo noticias/resumen.php podría ser:


<article>
  <header>
   <h2><?= $titulo ?></h2>
   <p class="autor">por <?= $autor ?></p>
   <p class="fecha"><?= $fecha ?></p>
  </header>
<?php
  foreach (Agora::fitraXSS ($texto) as $parrafo)
    echo "<p>$parrafo</p>";
</article>
    

Como se ve, dentro de las vistas puede usarse código PHP e incluso acceder a los métodos de la clase Agora.  Aunque esto puede ser de mucha utilidad, también supone un agujero de seguridad, por lo que no es recomendable permitir a terceras personas que definan y usen vistas a su antojo.

Módulos

El uso de módulos es otra de las características más potentes de Ágora.  Un módulo es un archivo PHP que contiene un conjunto de procedimientos, funciones o clases.  De forma similara las vistas, los módulos se buscan dentro de la rama de directorios a partir de la ruta definida en la constante de configuración AG_DIR_MODULOS, independientemente de la configuración de PHP.

El método que carga el módulo se define como:


public static function &cargaModulo (string $aNombreModulo, string $aNombreObjeto): mixed
    

El nombre del módulo es el mismo del archivo solo que sin la extensión, y al igual que con las vistas puede definirse una gerarquía de módulos mediante el uso de subdirectorios.

Si el archivo del módulo define una clase con el mismo que el nombre de módulo, Ágora puede crear un objeto con dicha clase que podrá ser accedida posteriormente a través del método Agora::objetoModulo ($aNombre).  Por ejemplo, si el módulo se llama usuario, entonces la clase se llamará Usuario o USUARIO y el objeto se llamará 'usuario'.  La clase no tiene por qué extender Agora, y puede definirse como se desee.  Si no se indica ningún nombre de objeto, se usará el nombre del módulo.  Si como nombre de objeto se indica el valor false, entonces no se creará ningún objeto, lo que permite cargar cualquier archivo PHP tenga o no una clase de módulo definida en él.

Como se ha dicho, se accede al objeto a través de Agora::objetoModulo, pero el método cargaModulo también devuelve una referencia al mismo objeto.  Si se crea un objeto de clase Agora o una clase que la extienda, se podrá acceder directamente al objeto como si fuera una propiedad; por ejemplo: echo $a->usuario->nombre  Consulte el ejemplo y los comentarios del archivo agora.php para más detalles.

Por último, y al igual que con las vistas vistas, no es recomendable permitir a terceras personas que definan y usen módulos ya que puede suponer un problema de seguridad grave.

Errores y redirecciones

Ágora incluye algunos métodos extra que facilitan la devolución de estados de error y cabeceras de redirección.  Para que los siguientes métodos funcionen, estos deben usarse antes de devolver cualquier dato al cliente.

Para devolver una página de documento no encontrado, con su correspondiente cabecera HTTP, se puede usar el método enviaError404, el cual se define así:


public static function enviaError404 (string $aURL, mixed $aMensaje): void
      

Para que funcione correctamente, hay que definir una vista llamada error404.  Si desea utilizar otra plantilla diferente, puede hacerle definiendo la constante AG_VISTA_404 antes de incluir Àgora.  Así mismo, el mensaje puede ser una lista, cada uno de cuyos elementos de formateará como un párrafo diferente.

De forma similar, puede devolver un estado de error usando el método enviaError:


public static function enviaError (mixed $aMensaje, int $aCodigo, string $aNombre): void
      

Si no se indica el parámetro $aCodigo entonces enviará un código de error 500.

En este caso, la vista utilizada se llama error, que puede cambiarse mediante la constante AG_VISTA_ERROR.  Si $Codigo es un código de error HTTP, entonces este método definirá $Nombre con el valor esperado.

Para hacer una redirección, debería usarse el siguiente método:


public static function Redirige (string $aURL, int $aRazon): void
      

El parámetro $aRazon es opcional, siendo por defecto el código HTTP 307.

Para un ajuste fino, puede enviarse una cabecera HTTP llamando al método enviaCabeceraHTTP.  Ojo, no confundir con la función PHP header.  En su lugar, hay que pasarle a enviaCabeceraHTTP el número de estado HTTP y este enviará las cabeceras apropiadas para el mismo.

Notas

Un diccionario es una lista (array) en la que sus índices no son numéricos, sino que pueden ser cadenas de caracteres.
Personalmente prefiero el término huella al inglés cookie ya que describe bastante mejor qué hace (dejar marcas en el cliente).  Es una preferencia personal.