Ejecutando Agenor

En este apartado veremos como es que agenor llega a renderizar una pagina web simple, sin base de datos, lo haremos para entender el corazon del sistema mva. Quizas sea un poco extenso pero mejorara la comprension posterior del sistema.
Para el ejemplo, realizaremos la prueba en un xampp local y en la carpeta agenor esta nuestro sistema web, entonces nuestra Url base será http://localhost/agenor, al poner esa url en nuestro navegador web se ejecutaran una serie de archivos en el siguiente orden:

1>Archivo .htaccess

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteCond %(REQUEST_FILENAME) !-d
RewriteCond %(REQUEST_FILENAME) !-f
RewriteCond %(REQUEST_FILENAME) !-l

RewriteRule ^(.*)$ index.php?urlAgenor=$1 [QSA,L]

    <filesmatch ".(jpg|JPG|gif|GIF|png|PNG|css|CSS|ico|ICO|js|JS|svg|SVG|eot|EOT|json|JSON|ttf|TTF|woff|WOFF|txt|TXT)$">
        RewriteEngine Off
    </filesmatch>
</IfModule>
Al poner la url y ejecutar, al tener el modo rewrite activado se ejecutara el htacces del directorio raiz.
<IfModule mod_rewrite.c>
Esta primera sentencia verifica que el módulo mod_rewrite esté habilitado en el servidor web. Si no llega a estar disponible, nada se ejecutara y nuestro sistema no podra funcionar. Si esta disponible se ejecutara todo hasta el cierre del mismo </IfModule>
.
RewriteEngine On 
Esta linea habilita el motor de reescrituras de urls.

RewriteCond %(REQUEST_FILENAME) !-d
RewriteCond %(REQUEST_FILENAME) !-f
RewriteCond %(REQUEST_FILENAME) !-l
Estas tres condiciones son sobre archivos, establece que si no existe el directorio(d), y no existe el archivo(f), y no existe un enlace simbolico(l), si todos ellos dan verdadero entonces se ejecuta la condicion de mas abajo.
RewriteRule ^(.*)$ index.php?urlAgenor=$1 [QSA,L]
Ejecuta las reglas del archivo .htacces, lo único que hace es que dada una dirección web, extraerá todo lo que no sea parte de la url base(http://localhost/agenor) y lo pondrá en una variable GET llamada urlAgenor. Por ejemplo si ponemos en la barra de direcciones del navegador http://localhost/agenor/index/Index/acerca, la variable Get urlAgenor será igual a index/Index/acerca y luego envia a dicha direccion o sea a index.php.- [QSA] Append Query String: es para agregar un query string al final de la expresión (URL). [L] Last rule: establece que es la ultima sentencia que se ejecuta.

<filesmatch ".(jpg|JPG|gif|GIF|png|PNG|css|CSS|ico|ICO|js|JS|svg|SVG|eot|EOT|json|JSON|ttf|TTF|woff|WOFF|txt|TXT)$">
    RewriteEngine Off
</filesmatch> 
Establece que para todos los tipos de extenciones de archivos enumerados, no se ejecuten las sentencias de reescritura, es decir apaga el motor de reescritura para dichos archivos.
</IfModule>
Cierra el bloque de condiciones.
Como mencionamos el archivo .htaccess pasa la posta al archivo index.php.

2>Archivo index.php

Como vimos el .htaccess terminaba redireccionando siempre a index.php, portando una variable get con el resto de la direccion web, miremos entonces el archivo.
<?php
error_reporting
(E_ALL E_STRICT);
//Inicio la Aplicacion
require_once 'ConfigSystem.php';
require_once 
DIR_LIB DS 'mva' DS 'AutoLoader.php';
// Registro el Autoloader
// Encargado de Levantar Automaticamente las Clases Instanciadas.
spl_autoload_register(array('AutoLoader''autoload'));
//Cargo donde se encuentra la aplicacion o modulos y donde  van las Librerias Externas o de Terceros.
// Esto es para obtener una mejor lectura de que cosa es nuestra y cual de terceros.
AutoLoader::setIncludePath(DIR_COREDIR_LIBDIR_APPDIR_EXTERNAS);
// Registro el capturador de errores asi como el de Excepciones.
set_error_handler(array('\agenor\mva\CaptureException''errorHandler'));
set_exception_handler(array('\agenor\mva\CaptureException''exceptionHandler'));
// Obtenemos el Enrutador Principal.
\agenor\mva\Router::getInstance()->run(new \agenor\mva\RequestGet(), array('application'));

require_once 'ConfigSystem.php'; 
Levanta el archivo de configuracion del sistema (lo vermos luego de index.php).

require_once DIR_LIB . 'mva' . DS . 'AutoLoader.php';
Carga la clase Autoloader, que es la encargada de llamar automaticamente a todas las clases que instanciemos dentro de nuestra aplicacion.

spl_autoload_register(array('AutoLoader', 'autoload'));
Registra la clase autoloader, con esto el sistema sabe que cada vez que se instancia una clase, se debera ir a la clase registrada como autoload para descubrir su ruta e incluirla en el sistema.

AutoLoader::setIncludePath(DIR_APP, DIR_EXTERNAS);
Inlcuimos en el path de php, el directorio donde encontrar nuestra aplicacionDIR_APP, las librerias de terceros DIR_EXTERNASy todas aquellas que podramos necesitar. Simplemente los directorios se separan por comas para seguir añadiendo paths.

set_error_handler(array('agenor\mva\CaptureException', 'errorHandler'));
set_exception_handler(array('agenor\mva\CaptureException', 'exceptionHandler')); 
Con esas dos sentencias incluimos los manejadores de errores y excepciones, cada vez que se produce un error entra en accion la clase CaptureException y el metodo errorHandler, si es una exepcion la clase es la misma pero el metodo que se ejecutara sera exceptionHandler.

\agenor\mva\Router::getInstance()->run(new \agenor\mva\Request(), array('application')); 
Aqui obtenemos una instancia del Router, y ejecutamos su metodo run para hacer andar al sistema, le pasamos como parametros el objeto Request que contiene todos los datos que nos envia el usuario y un arreglo con todos los archivos de configuracion que se deberan levantar.

3>Archivo ConfigSystem.php

<?php
################################################################################
# (1) DEFINICION GENERALES DEL SISTEMA                                         #
################################################################################
# Tenemos dos modos 
# debug : se utiliza cuando se crea la aplicacion
# web   : se utiliza cuando ya se encuentra operativa la misma.
define('APPLICATION_ENV''web');
define('DEBUG_URL',        false);
//define('BENCHMARKING',     false);

/** Caracter que se usa para separar directorios segun el sistema operativo.*/
define('DS'DIRECTORY_SEPARATOR);
/** Ruta completa de la raiz de la aplicacion o sitio.*/
define('DIR_BASE'realpath(dirname(__FILE__)) . DS );
/** Ruta completa donde se encuentra el core de agenor.*/
define('DIR_LIB'DIR_BASE 'agenor' DS );
define('DIR_CORE'DIR_BASE DS);
/** Nombre del directorio donde se encuentran los modulos del sistema.*/
define('MODULOS''application');
/** Ruta completa donde se encuentran los modulos del sistema o sitio. */
define('DIR_APP'DIR_BASE MODULOS DS);
/** Directorio de Librerias Externas */
define('DIR_EXTERNAS'DIR_BASE 'libs_external' DS);
/** URL base del sitio */
define('URL_BASE'str_replace('\\'''$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF'])));
/** Tipo de url http o https */
define("URL_HTTP", (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']    == 'on')? 'https://' 'http://');
define('DIR_CONFIG_APP',        'configs');
define('URL_ERROR'URL_HTTP URL_BASE '/index/Index/err'); // Url para pasar un error generico.
################################################################################
# (2) DEFINICION PARA MODULOS                                                  #
################################################################################
define('DEFAULT_MODULE',        'index');
define('DEFAULT_ADAPTER',       'Index');
define('DEFAULT_ACTION',        'index');
define('DIR_ADAPTERS',          'adapters');
define('DIR_MODELS',            'models');
define('DIR_VIEWS',             'views');
define('DIR_CONFIGS',           'configs');
define('VIEW_ERROR',            'error');
define('POST_FIX_ADAPTER',      'Adapter');
/** Guarda si se escribe en el log cuando no exista la accion pero si la plantilla 
 *  se renderiza la plantilla sin el controlador esperando que sea solo contenido estatico.
 */
define('DEBUG_ACCION'false);

En este archivo se configuran las constantes mas importantes del sistema y que repercute en el nombre de los directorios asi como archivos de los modulos.

En la seccion 1 encontramos:
APPLICATION_ENV
Permite dos valores (web/debug), es el modo en que se ejecutara la aplicacion, web cuando ya la tenemos en el sitio y debug cuando estamos en desarrollo de la misma.

DEBUG_URL
Booleano que nos dice si se mostraran o no los archivos que va cargando el sistema.

DS
Utilizamos esta abreviacion para no tener que poner DIRECTORY_SEPARATOR, que es el caracter que se utiliza segun el sistema operativo para separar una ruta de archivo.

DIR_BASE
Contiene la ruta completa a la raiz de la aplicacion, no es una url es un path de directorio, puede ser c:\xampp\htdocs\agenor o /var/www/html/agenor.

DIR_LIB
Ruta completa o path donde se encuentra el core de agenor.

MODULOS
Contiene el nombre del directorio donde se encuentran los modulos de la aplicacion, no es una ruta completa.

DIR_APP
Ruta completa al directorio de los modulos de la aplicacion.

DIR_EXTERNAS
Ruta completa al directorio que contiene las librerias externas o de terceros. Ej.: PHPExcel, Doctrine, Dompdf etc.

URL_BASE
Contiene la url base del sitio como ser www.tusito.com o localhost/agenor.

URL_HTTP
Contiene si es una peticion http o https.

DIR_CONFIG_APP
Es el directorio de configuraciones generales del sistema y debe estar en el raíz del sitio.

En la seccion 2 encontramos:
DEFAULT_MODULE
Establece cual es el modulo que se ejecutara por defecto es decir cuando solo ponemos la url base, se ejecuta en este caso el modulo index.

DEFAULT_ADAPTER
Adaptador que se ejecutara por defecto cuando ponemos la url base solamento o url base + modulo, con esta configuracion el adaptador sera Index, y esto hace que dicho adaptador deba existir en todos los modulos.

DEFAULT_ACTION
Accion que se ejecutara cuando ponemos o solo url base o url base + modulo o url base + modulo + adaptador, en este caso se ejecutara el metodo indexAction. Esto tambien hace que el metodo deba existir en todos los adaptadores y no se recomienda cambiar esta configuracion dado que por contrato los adaptadores deben contener un metodo indexAction. Si no se quiere ese metodo por defecto lo conveniente seria extender todos nuestros adaptadores de uno creado por nosotros abstracto y crear un metodo abstracto que deba ser sobreescrito.

DIR_ADAPTERS
Contiene el nombre del directorio en el cual se incluiran los adaptadores del sistema, el mismo debe estar presente en todos los modulos.

DIR_MODELS
Contiene el nombre del directorio en el cual se incluiran los modelos del sistema, el mismo debe estar presente en todos los modulos.

DIR_VIEWS
Contiene el nombre del directorio en el cual se incluiran las vistas del sistema, el mismo debe estar presente en todos los modulos.

DIR_CONFIGS
Contiene el nombre del directorio en el cual se incluiran los archivos de configuracion del sistema.

VIEW_ERROR
Configura la plantilla por error que se ejecutara.

POST_FIX_ADAPTER
configura el post-fijo o sea como terminara el nombre del Adaptador, esto quiere decir que por defecto todo Adaptador culminara con la palabra Adapter en su nombre.

DEBUG_ACCION
Una particularidad de Agenor, es que una vista, siempre que sea estática puede ser levantada solamente con estar en el directorio de views/phtml, Como este hecho produce un error que no se mostrara en el sistema, se dejó una constante de configuración que nos permita o no según queramos escribir en el log de errores del sistema dicho acontecimiento. Entonces por true se escribe en el log del sistema y por false obviamos esta situacion.

4>Continuamos con el arranque ...

Habiamos quedado en :
\agenor\mva\Router::getInstance()->run(new \agenor\mva\Request(), array('application'));

\agenor\mva\Router::getInstance()
Con esta sentencia obtenemos una instancia de la Clase Router que es el que se encarga de redireccionarnos hacia la ejecucion de nuestro metodo. Si es la primera vez que obtenemos la instancia entonces el Registry nos guarda la variable de entorno APPLICATION_ENV con el nombre de de environment.
\agenor\mva\Registry::set('environment', APPLICATION_ENV);

Seguidamente hacemos:
...->run(new \agenor\mva\Request(), array('application'));
Lo que significa que del Router ejecutamos el metodo run y enviamos dos parametros, un objeto Request y un arreglo conteniendo los archivos de configuracion que se deben levantar.
1er Parametro : agenor\mva\Request contiene todos los datos pasados por el usuario por la url. El objeto Request sera guardado en el Registry bajo el nombre de Request.
2ndo Parametro : es un arreglo que contiene cada uno de los archivos de configuracion que se deben levantar, en este caso el archivo a levantar sera application.php y nos quedara guardado en el Registry con el nombre de application es decir nombre de archivo sin la extencion.

Una vez procesada la URL por el objeto Request y cargados los archivos de configuracion, el sistema intenta levantar el bootstrap de la aplicacion o BootstrapApplication que se encuentra en la raiz del sitio.
En el caso que exista el archivo ejecutara cada uno de los metodos que comienzan con _start y en caso de retornar algun valor, este se guardara en el Registry, si el metodo se llama _startVista entonces nuestro Registry lo cargara con nombre Vista.

Luego se enrutara al modulo pedido en la url, y buscara el directorio DIR_CONFIGS (configs) y comenzara a cargar todos los archivos .php del directorio. Cada uno de estos archivos sera guardado en el Registry con su nombre sin la extencion.

Luego de cargados los archivos de configuracion del Modulo, intenta cargar el Bootstrap del modulo, realizando las mismas acciones que con el BootstrapApplication.

Luego el Router sigue su rutina hasta lograr ejecutar la accion solicitada,
1 - Ejecuta los plugins de Inicio que se definieron.
2 - Ejecuta el metodo init del Adaptador solicitado si existe.
3 - Ejecuta el metodo solicitado por la url.
4 - Si el usuario no lo hizo el sistema renderiza la vista que corresponda.
6 - Ejecuta el metodo post del Adaptador solicitado si existe.
7 - Ejecuta los plugins de Cierre que se definieron.

Y con ese ultimo paso el router finaliza su tarea y nuestra rutina se deberia haber ejecutado.

  NOTA :
En algunos casos es conveniente nombrar a los archivos de configuracion con una sintaxis que no sea facil de repetirse, como por ejemplo nombre del moduo guion bajo y nombre de archivo.


Por ultimo aclarar que todos los datos guardados en el Registry, que actua como contendor global pueden ser accedidos de cualquier parte de la aplicacion de la siguiente forma:
$recurso = \agenor\mva\Registry::get('nombre_del_recurso');