Edición de «KumbiaPHP Framework Versión 1.0 Spirit»
De KumbiaPHP Framework Wiki
Advertencia: no has iniciado sesión. Tu dirección IP se hará pública si haces cualquier edición. Si inicias sesión o creas una cuenta, tus ediciones se atribuirán a tu nombre de usuario, además de otros beneficios.
Puedes deshacer la edición. Antes de deshacer la edición, comprueba la siguiente comparación para verificar que realmente es lo que quieres hacer, y entonces guarda los cambios para así efectuar la reversión.
Revisión actual | Tu texto | ||
Línea 1: | Línea 1: | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== Introducción == | == Introducción == | ||
En la [https://launchpad.net/kumbia/1.0 versión 1.0](<s>antigua 0.5.1</s>) el enfoque primordial que ha considerado el [[Team_Development_KumbiaPHP_Framework|Equipo de Desarrollo]] gira en torno al rendimiento del framework a nivel de velocidad y mantenibilidad del framework en este sentido hemos desacoplado el core de kumbiaphp framework en una nueva estructura obteniendo grandes resultados, de manera que las pruebas en base a esta versión nos indica que vamos en buen camino y ademas es bastante rápida con los cambios aplicados siempre con las mejores practicas de desarrollo. | En la [https://launchpad.net/kumbia/1.0 versión 1.0](<s>antigua 0.5.1</s>) el enfoque primordial que ha considerado el [[Team_Development_KumbiaPHP_Framework|Equipo de Desarrollo]] gira en torno al rendimiento del framework a nivel de velocidad y mantenibilidad del framework en este sentido hemos desacoplado el core de kumbiaphp framework en una nueva estructura obteniendo grandes resultados, de manera que las pruebas en base a esta versión nos indica que vamos en buen camino y ademas es bastante rápida con los cambios aplicados siempre con las mejores practicas de desarrollo. | ||
Línea 24: | Línea 18: | ||
Como se menciona al principio muchos de estos cambios son a nivel de '''core''', esto significa que haremos pocas adecuaciones para migrar nuestras aplicaciones que hayan sido desarrolladas con la [https://launchpad.net/kumbia/0.5 versión 0.5] para llevarlas hasta la [https://launchpad.net/kumbia/1.0 versión 1.0](<s>antigua 0.5.1</s>), esto con la finalidad de garantizar compatibilidad entre versiones. | Como se menciona al principio muchos de estos cambios son a nivel de '''core''', esto significa que haremos pocas adecuaciones para migrar nuestras aplicaciones que hayan sido desarrolladas con la [https://launchpad.net/kumbia/0.5 versión 0.5] para llevarlas hasta la [https://launchpad.net/kumbia/1.0 versión 1.0](<s>antigua 0.5.1</s>), esto con la finalidad de garantizar compatibilidad entre versiones. | ||
===¿Por qué Spirit?=== | ===¿Por qué Spirit?=== | ||
− | "Hemos llamado Spirit a la versión 1.0 porque Spirit, [http://es.wikipedia.org/wiki/Spirit nuestro robot de Marte], tiene como características principales, fuerza y velocidad. Fuerza, porque su comunidad cada vez mas grande hace que nuestro framework KumbiaPHP avance a pasos agigantados. Velocidad, porque nuestro core team que pertenece a otro planeta, continuamente esta aplicando las ultimas técnicas y haciendo que otros | + | "Hemos llamado Spirit a la versión 1.0 porque Spirit, [http://es.wikipedia.org/wiki/Spirit nuestro robot de Marte], tiene como características principales, fuerza y velocidad. Fuerza, porque su comunidad cada vez mas grande hace que nuestro framework KumbiaPHP avance a pasos agigantados. Velocidad, porque nuestro core team que pertenece a otro planeta, continuamente esta aplicando las ultimas técnicas y haciendo que otros frameworks se queden atrás día a día. En definitiva Spirit, hace que tus aplicaciones vuelen, resulten mas atractivas y fáciles de mantener." |
== Migración Rápida == | == Migración Rápida == | ||
En esta sección se explica de forma rápida y sencilla como migrar nuestras aplicaciones de la <s>versión [https://launchpad.net/kumbia/0.5 0.5]</s> a la [https://launchpad.net/kumbia/1.0 versión 1.0](<s>antigua 0.5.1</s>) en las próximas secciones se explican en detalle los cambios. | En esta sección se explica de forma rápida y sencilla como migrar nuestras aplicaciones de la <s>versión [https://launchpad.net/kumbia/0.5 0.5]</s> a la [https://launchpad.net/kumbia/1.0 versión 1.0](<s>antigua 0.5.1</s>) en las próximas secciones se explican en detalle los cambios. | ||
− | *Con la nueva | + | *Con la nueva estrucura de directorio migrar nuestras aplicaciones de la <s>versión [https://launchpad.net/kumbia/0.5 0.5]</s> es sumamente simple solo se ha copiar nuestra carpeta '''apps/default/''' (donde estan los controllers, models, views, etc) hacia el directorio '''app/''' de [[KumbiaPHP_Framework_Versi%C3%B3n_1.0_Spirit#Nueva_Estructura_de_Directorios |Nueva Estructura]] |
− | |||
− | |||
*Si has modificado el archivo '''views/index.phtml''' este fue ubicado en el directorio '''views/templates/default.phtml''', es decir que le debes aplicar los cambios que quieras. | *Si has modificado el archivo '''views/index.phtml''' este fue ubicado en el directorio '''views/templates/default.phtml''', es decir que le debes aplicar los cambios que quieras. | ||
Línea 38: | Línea 30: | ||
*Para inicializar tu aplicación se ha de utilizar el '''config/routes.ini''' agregando una regla de enrutamiento estático, por ejemplo: | *Para inicializar tu aplicación se ha de utilizar el '''config/routes.ini''' agregando una regla de enrutamiento estático, por ejemplo: | ||
− | ;con esta regla cada vez que inicie la aplicación http://localhost/kumbia/ irá hacia un controlador | + | ;con esta regla cada vez que inicie la aplicación http://localhost/kumbia/ irá hacia un controlador admin y una acción autenticar |
− | admin y una acción autenticar / = admin/autenticar | + | / = admin/autenticar |
Esto sustituye editar el archivo '''<s>apps/default/controllers/application.php</s>''' en su acción '''init()''', solo se ha de agregar en el '''routes.ini''' la ruta que hacemos en el método '''<s>init()</s>''' | Esto sustituye editar el archivo '''<s>apps/default/controllers/application.php</s>''' en su acción '''init()''', solo se ha de agregar en el '''routes.ini''' la ruta que hacemos en el método '''<s>init()</s>''' | ||
*Si en tus modelos utilizas el atributo '''$mode''' para establecer otros datos de conexión, debes reemplazarlo por '''$database''', [[KumbiaPHP_Framework_Versión_1.0_Spirit#databases.ini| ver mas]]. | *Si en tus modelos utilizas el atributo '''$mode''' para establecer otros datos de conexión, debes reemplazarlo por '''$database''', [[KumbiaPHP_Framework_Versión_1.0_Spirit#databases.ini| ver mas]]. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== Nueva Estructura de Directorios == | == Nueva Estructura de Directorios == | ||
− | + | Ahora KumbiaPHP incorpora la siguiente estructura de directorios, a continuación se detallan los elementos mas relevantes: | |
<pre> | <pre> | ||
− | + | . | |
|-- app | |-- app | ||
| |-- application.php | | |-- application.php | ||
| |-- config | | |-- config | ||
| |-- controllers | | |-- controllers | ||
− | + | | |-- helpers | |
− | |||
− | |||
− | |||
| |-- index.php | | |-- index.php | ||
− | |||
− | |||
| |-- model_base.php | | |-- model_base.php | ||
| |-- models | | |-- models | ||
Línea 131: | Línea 58: | ||
| `-- templates | | `-- templates | ||
|-- core | |-- core | ||
− | + | |-- console | |
− | + | |-- docs | |
− | + | |-- extensions | |
− | + | |-- helpers | |
− | + | |-- kumbia | |
− | + | |-- scaffolds | |
− | + | |-- tests | |
− | + | |-- vendors | |
− | + | `-- views | |
− | |||
− | |||
− | |||
− | |||
</pre> | </pre> | ||
− | Anteriormente [http://www.kumbiaphp.com KumbiaPHP] utilizaba un fichero | + | Anteriormente [http://www.kumbiaphp.com KumbiaPHP] utilizaba un fichero index.php el cual servía para enrutar a cada aplicación utilizando inversión de control, esto erá poco flexible y resultaba en un consumo inadecuado de recursos, por lo tanto en esta nueva versión se preparó una nueva estructura de directorios donde cada aplicación posee un directorio independiente con su index.php (Front Controller) correspondiente el cual se encarga de cargar las librerias del framework. |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Copiando el directorio app, tenemos toda la estructura para un nueva aplicación. Ya que podemos tener tantas aplicaciones como necesitemos con un único core. | |
− | + | Asimismo el nucleo, las extensiones de KumbiaPHP y otras herramientas que utilizarán las aplicaciones de manera global fueron agrupadas en el directorio core. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== config.ini == | == config.ini == | ||
− | Se agregan opciones para un manejo mas apropiado de la configuración del framework | + | Se agregan opciones para un manejo mas apropiado de la configuración del framework. |
+ | *'''databases''' cuando se necesite trabajar con el framework pero sin interactuar con una Base de Datos. | ||
+ | *'''models_autoload''' Auto carga de modelos, util para cuando se manejan muchos modelos no tener la necesidad de cargarlos todos en un momento, sino que se cargan se de acuerdo lo que se necesiten en el controller, todo esto se traduce en mejor rendimiento, [[KumbiaPHP_Framework_Versi%C3%B3n_1.0_Spirit#Carga_selectiva_de_modelos| leer mas]] | ||
*'''metadata_lifetime''' Tiempo de vida de la metadata cacheada. | *'''metadata_lifetime''' Tiempo de vida de la metadata cacheada. | ||
*'''database''' Base de datos a utilizar, especificada en databases.ini. | *'''database''' Base de datos a utilizar, especificada en databases.ini. | ||
*'''production''' Indica si se encuentra en producción. | *'''production''' Indica si se encuentra en producción. | ||
− | |||
− | |||
− | |||
− | <pre>;; | + | <pre> |
+ | ;; Configuración de Aplicación | ||
; Explicación de la Configuración: | ; Explicación de la Configuración: | ||
− | + | ; production: Indica si esta en producción | |
+ | ; database: base de datos a utilizar | ||
; name: Es el nombre de la aplicación | ; name: Es el nombre de la aplicación | ||
; timezone: Es la zona horaria que usará el framework | ; timezone: Es la zona horaria que usará el framework | ||
− | ; | + | ; interactive: Indica si la aplicación se encuentra en modo interactivo |
− | |||
; dbdate: Formato de Fecha por defecto de la Applicación | ; dbdate: Formato de Fecha por defecto de la Applicación | ||
− | |||
− | |||
; charset: codificacion de caracteres | ; charset: codificacion de caracteres | ||
− | ; | + | ; models_autoload: Habilita la autocarga de modelos |
; metadata_lifetime: Tiempo de vida de la metadata cacheada | ; metadata_lifetime: Tiempo de vida de la metadata cacheada | ||
− | ; locale: | + | ; locale: Localicazion |
− | |||
Línea 270: | Línea 104: | ||
; el contenido del directorio de cache de la aplicacion para que se renueve | ; el contenido del directorio de cache de la aplicacion para que se renueve | ||
; la metadata | ; la metadata | ||
+ | |||
[application] | [application] | ||
name = "KUMBIA PROJECT" | name = "KUMBIA PROJECT" | ||
− | + | timezone = "America/New_York" | |
production = Off | production = Off | ||
database = development | database = development | ||
Línea 280: | Línea 115: | ||
log_exceptions = On | log_exceptions = On | ||
charset = UTF-8 | charset = UTF-8 | ||
− | + | models_autoload = On | |
;metadata_lifetime = "+1 year" | ;metadata_lifetime = "+1 year" | ||
;locale = es_ES | ;locale = es_ES | ||
− | |||
</pre> | </pre> | ||
Línea 311: | Línea 145: | ||
host = localhost | host = localhost | ||
username = root | username = root | ||
− | password = | + | password = |
− | name = | + | name = innogest |
type = mysql | type = mysql | ||
Línea 318: | Línea 152: | ||
host = localhost | host = localhost | ||
username = root | username = root | ||
− | password = | + | password = |
name = test | name = test | ||
− | type = | + | type = mysql |
[test] | [test] | ||
host = localhost | host = localhost | ||
username = root | username = root | ||
− | password = | + | password = |
name = test | name = test | ||
− | type = | + | type = mysql |
</pre> | </pre> | ||
== boot.ini == | == boot.ini == | ||
− | En este archivo | + | En este archivo es donde el usuario carga las extensiones (librerías) que trae el framework o bien alguna que deseen agregar. |
− | + | En este archivo se agregan dos atributos '''kumbia''' y '''extensions''' para que la lectura del mismo sea mas rápida. | |
+ | |||
+ | Extensiones Propias de Kumbiaphp Framework | ||
+ | *logger | ||
+ | *auth | ||
+ | *date | ||
+ | *standard_form | ||
+ | *filter | ||
+ | *acl | ||
+ | *benchmark | ||
+ | *security | ||
+ | |||
+ | Extensiones externas al framework | ||
+ | *excel | ||
+ | *fpdf | ||
+ | *mail | ||
+ | *smarty | ||
+ | |||
+ | <pre> | ||
+ | ; Cargar los modulos de Kumbia en library/ | ||
+ | ; CONVENCIONES | ||
+ | ; La convención para la carga de extensiones (librerías) por medio | ||
+ | ; de este archivo es la siguiente: | ||
+ | ; kumbia = logger indica que en el directorio library/kumbia/logger | ||
+ | ; y a su vez este tiene un archivo logger.php kumbia incluira library/kumbia/logger/logger.php | ||
+ | ; lo mismo sucede para las extensiones externas al core del framework, solo que estas no estan | ||
+ | ; kumbia, sino en la variable extensions | ||
+ | |||
+ | ; kumbia: Modulos del framework que se cargaran library/kumbia | ||
+ | ; extensions: Modulos a cargar library/ | ||
+ | |||
+ | [modules] | ||
+ | kumbia = logger, filter | ||
+ | vendors = | ||
+ | </pre> | ||
== Router == | == Router == | ||
Línea 356: | Línea 224: | ||
Los [http://en.wikipedia.org/wiki/Template_(file_format) Template] son un tipo de archivo pre-formateado utilizado como base para otros archivos. | Los [http://en.wikipedia.org/wiki/Template_(file_format) Template] son un tipo de archivo pre-formateado utilizado como base para otros archivos. | ||
− | En este directorio esta la capa mas externa de nuestras vistas, para aclarar esta idea en esta es donde se coloca la estructura del documento XHTML (doctype, html, head, etc) en la forma como se trabaja en la <s>versión 0.5</s> esto es representado por el archivo <s>'''views/index.phtml'''</s> de esta forma no existe una flexibilidad de manera que podamos cambiar ese template, en la [https://launchpad.net/kumbia/1.0 versión 1.0] se crea un directorio '''views/templates/''' por defecto existe el archivo '''default.phtml''' pero podemos agregar cuantos se desee y poderlo cambiar desde nuestro controlador de la siguiente forma: | + | En este directorio esta la capa mas externa de nuestras vistas, para aclarar esta idea en esta es donde se coloca la estructura del documento XHTML (doctype, html, head, etc) en la forma como se trabaja en la <s>versión 0.5</s> esto es representado por el archivo <s>'''views/index.phtml'''</s> de esta forma no existe una flexibilidad de manera que podamos cambiar ese template, en la [https://launchpad.net/kumbia/1.0 versión 1.0] se crea un directorio '''views/templates/''' por defecto existe el archivo '''default.phtml''' pero podemos podemos agregar cuantos se desee y poderlo cambiar desde nuestro controlador de la siguiente forma: |
<source lang=php> | <source lang=php> | ||
Línea 366: | Línea 234: | ||
El atributo '''$template''' existe en la super clase '''Controller''' y tiene un valor por defecto (default) esto significa que el sistema de plantillas de KumbiaPHP Framework buscara dentro de directorio views/templates/ el valor que le demos, por defecto buscara '''default.phtml''' pero en otro caso que veamos conveniente podría ser otro template tal como se muestra en el ejemplo seria '''plantilla.phtml''' | El atributo '''$template''' existe en la super clase '''Controller''' y tiene un valor por defecto (default) esto significa que el sistema de plantillas de KumbiaPHP Framework buscara dentro de directorio views/templates/ el valor que le demos, por defecto buscara '''default.phtml''' pero en otro caso que veamos conveniente podría ser otro template tal como se muestra en el ejemplo seria '''plantilla.phtml''' | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
=== views/partials/ === | === views/partials/ === | ||
Línea 391: | Línea 248: | ||
</source> | </source> | ||
− | Como se aprecia este partials solo mostrará la fecha actual cuando sea invocado, pero como se menciono antes puede contener cualquier información para el usuario, pero aun falta hacer un llamado a este partials para que el mismo sea mostrado este llamado puede ser desde cualquier nivel del sistema de plantilla que ofrece el framework | + | Como se aprecia este partials solo mostrará la fecha actual cuando sea invocado, pero como se menciono antes puede contener cualquier información para el usuario, pero aun falta hacer un llamado a este partials para que el mismo sea mostrado este llamado puede ser desde cualquier nivel del sistema de plantilla que ofrece el framework y basta con hacer en la vista (Templates, views) lo siguiente. |
<source lang=php > | <source lang=php > | ||
− | <?php | + | <?php render_partial('fecha') ?> |
</source> | </source> | ||
Línea 400: | Línea 257: | ||
'''Describiendo la función de manera mas detallada:''' | '''Describiendo la función de manera mas detallada:''' | ||
<source lang=php > | <source lang=php > | ||
− | + | render_partial($partial, $time=false, $params=array()) | |
</source> | </source> | ||
Línea 406: | Línea 263: | ||
<source lang=php > | <source lang=php > | ||
− | <?php | + | <?php render_partial('fecha', '+4 days') ?> |
</source> | </source> | ||
Línea 412: | Línea 269: | ||
<source lang=php > | <source lang=php > | ||
− | <?php | + | <?php render_partial('fecha', false) ?> |
</source> | </source> | ||
− | También es posible pasar variables al partial utilizando parámetros con nombre o utilizando como argumento un array. Si estos parámetros se pasan en forma de array soporta cualquier tipo de dato (objecto, array, etc). | + | También es posible pasar variables al partial utilizando parámetros con nombre o utilizando como argumento un array. Si estos parámetros son se pasan en forma de array soporta cualquier tipo de dato (objecto, array, etc). |
<source lang=php > | <source lang=php > | ||
− | <?php | + | <?php render_partial('fecha', false, 'var: valor, var2: valor2') ?> |
</source> | </source> | ||
<source lang=php > | <source lang=php > | ||
− | <?php | + | <?php render_partial('fecha', false, array('var' => 'valor')) ?> |
</source> | </source> | ||
Línea 447: | Línea 304: | ||
</source> | </source> | ||
− | + | KumbiaPHP con la intención de ofrecer mayor comodidad tambien posible obtener una instancia de un modelo directamente haciendo uso del método '''[[KumbiaPHP_Framework_Versión_1.0_Spirit#Load::model.28.24model.29 |Load::model($modelo)]]'''. | |
<source lang=php > | <source lang=php > | ||
Línea 453: | Línea 310: | ||
$result = Load::model('usuario')->find(1); | $result = Load::model('usuario')->find(1); | ||
?> | ?> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</source> | </source> | ||
Línea 699: | Línea 345: | ||
==Cache== | ==Cache== | ||
− | El componente cache fué mejorado y ahora posee una implementación | + | El componente cache fué mejorado y ahora posee una implementación estática, para hacer uso de la cache es necesario tener permisos de escritura en el directorio "cache". Los métodos de la clase Cache son los siguientes: |
− | |||
− | |||
− | ===Cache:: | + | ===Cache::get($id, $group='default')=== |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
Obtiene los datos cacheados. Los elementos cacheados pueden agruparse en grupos, lo cual permite evitar colisiones entre elementos cacheados con igual $id. | Obtiene los datos cacheados. Los elementos cacheados pueden agruparse en grupos, lo cual permite evitar colisiones entre elementos cacheados con igual $id. | ||
Línea 728: | Línea 353: | ||
string '''$group''': grupo al cual pertenece el elemento cacheado (por defecto "default") | string '''$group''': grupo al cual pertenece el elemento cacheado (por defecto "default") | ||
− | < | + | <pre> |
− | $data = Cache:: | + | $data = Cache::get('data'); |
− | </ | + | </pre> |
− | ===save($value, $lifetime=null, $id=false, $group='default')=== | + | ===Cache::save($value, $lifetime=null, $id=false, $group='default')=== |
Guarda los datos a cachear. | Guarda los datos a cachear. | ||
mixed '''$value''': valor a cachear (automaticamente es serializado antes de guardar)<br> | mixed '''$value''': valor a cachear (automaticamente es serializado antes de guardar)<br> | ||
− | string '''$lifetime''': tiempo de vida de los datos (formato de [http:// | + | string '''$lifetime''': tiempo de vida de los datos (formato de [http://fr.php.net/manual/es/function.strtotime.php strtotime]), si es null, los datos no expiran nunca.<br> |
string '''$id''': identificador del elemento a almacenar, si no se especifica, se toma el id y grupo del ultimo get efectuado<br> | string '''$id''': identificador del elemento a almacenar, si no se especifica, se toma el id y grupo del ultimo get efectuado<br> | ||
string '''$group''': grupo al cual pertenece | string '''$group''': grupo al cual pertenece | ||
<source lang=php> | <source lang=php> | ||
− | <?php if($data = Cache:: | + | <?php if($data = Cache::get('data')): ?> |
<?php echo $data ?> | <?php echo $data ?> | ||
<?php else: ?> | <?php else: ?> | ||
Línea 748: | Línea 373: | ||
<?php | <?php | ||
$data = ob_get_contents(); | $data = ob_get_contents(); | ||
− | Cache:: | + | Cache::save($data, '+21 days'); |
ob_end_flush(); | ob_end_flush(); | ||
?> | ?> | ||
Línea 756: | Línea 381: | ||
<source lang=php> | <source lang=php> | ||
− | Cache:: | + | Cache::save('hola', null, 'data'); |
− | $data = Cache:: | + | $data = Cache::get('hola'); |
</source> | </source> | ||
Nota: el grupo "kumbia.*" esta reservado para el uso exclusivo de KumbiaPHP. | Nota: el grupo "kumbia.*" esta reservado para el uso exclusivo de KumbiaPHP. | ||
− | ===start($lifetime, $id, $group='default')=== | + | ===Cache::start($lifetime, $id, $group='default')=== |
− | Cachea capturando el buffer de salida, se debe utilizar en conjunto a "end()" para terminar la captura, si el elemento esta cacheado entonces lo retorna. | + | Cachea capturando el buffer de salida, se debe utilizar en conjunto a "Cache::end()" para terminar la captura, si el elemento esta cacheado entonces lo retorna. |
string '''$lifetime''': tiempo de vida de los datos (formato de strtotime), si es null, los datos no expiran nunca.<br> | string '''$lifetime''': tiempo de vida de los datos (formato de strtotime), si es null, los datos no expiran nunca.<br> | ||
Línea 770: | Línea 395: | ||
<source lang=php> | <source lang=php> | ||
− | <?php if($data = Cache:: | + | <?php if($data = Cache::start('+1 day','data')): ?> |
<?php echo $data ?> | <?php echo $data ?> | ||
<?php else: ?> | <?php else: ?> | ||
Hola | Hola | ||
− | <?php Cache:: | + | <?php Cache::end()?> |
<?php endif; ?> | <?php endif; ?> | ||
</source> | </source> | ||
− | ===end()=== | + | ===Cache::end()=== |
Guarda los datos en la cache tomados del buffer de salida. | Guarda los datos en la cache tomados del buffer de salida. | ||
− | ===clean($group=false)=== | + | ===Cache::clean($group=false)=== |
Limpia la cache. Si no se indica grupo limpia toda la cache. | Limpia la cache. Si no se indica grupo limpia toda la cache. | ||
<source lang=php> | <source lang=php> | ||
− | Cache:: | + | Cache::clean('default'); |
</source> | </source> | ||
− | ===remove($id, $group='default')=== | + | ===Cache::remove($id, $group='default')=== |
Elimina un elemento específico de la cache | Elimina un elemento específico de la cache | ||
<source lang=php> | <source lang=php> | ||
− | Cache:: | + | Cache::remove('data'); |
+ | </source> | ||
+ | |||
+ | ===Cache::active($active)=== | ||
+ | Activa el uso de la cache | ||
+ | |||
+ | <source lang=php> | ||
+ | Cache::active(true); | ||
</source> | </source> | ||
Línea 838: | Línea 470: | ||
Parametros con nombre:<br> | Parametros con nombre:<br> | ||
message: mensaje a mostrar<br> | message: mensaje a mostrar<br> | ||
− | field: nombre del campo | + | field: nombre del campo |
− | |||
− | |||
<source lang=php> | <source lang=php> | ||
Línea 846: | Línea 476: | ||
$this->validates_uniqueness_of('cedula', 'message: La cedula ya existe') | $this->validates_uniqueness_of('cedula', 'message: La cedula ya existe') | ||
$this->validates_uniqueness_of('cedula', array('message'=>'La cedula ya existe')) | $this->validates_uniqueness_of('cedula', array('message'=>'La cedula ya existe')) | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
... | ... | ||
</source> | </source> | ||
Línea 894: | Línea 515: | ||
===validates_length_of($field, $max, $min=0, $params=array())=== | ===validates_length_of($field, $max, $min=0, $params=array())=== | ||
− | Valida | + | Valida que el campo no sea nulo |
string '''$field''': campo a validar<br> | string '''$field''': campo a validar<br> | ||
Línea 913: | Línea 534: | ||
... | ... | ||
</source> | </source> | ||
+ | |||
===validates_inclusion_in($field, $list, $params=array())=== | ===validates_inclusion_in($field, $list, $params=array())=== | ||
Línea 966: | Línea 588: | ||
</source> | </source> | ||
+ | ===validates_format_of($field, $pattern, $params=array())=== | ||
+ | Valida que el campo coincida con el patron indicado | ||
+ | |||
+ | string '''$field''': campo a validar<br> | ||
+ | array '''$pattern''': expresion regular compatible con perl<br> | ||
+ | array '''$params''': array de parametros con nombre | ||
+ | |||
+ | Parametros con nombre:<br> | ||
+ | message: mensaje a mostrar<br> | ||
+ | field: nombre del campo | ||
+ | |||
+ | <source lang=php> | ||
+ | ... | ||
+ | $this->validates_format_of('seleccion', '/^\d{3}[A-Z]/') | ||
+ | ... | ||
+ | </source> | ||
Línea 1005: | Línea 643: | ||
===Production=== | ===Production=== | ||
− | Indicando en el config.ini '''"production = On"''', se entra en el modo de producción, en este la cache de kumbiaphp framework esta activada y se cachea información necesaria para agilizar la carga de la aplicación tal como la metadata de la base datos (información de tablas y campos), asimismo las vistas que el usuario desee cachear. | + | Indicando en el config.ini '''"production = On"''', se entra en el modo de producción, en este la cache de kumbiaphp framework esta activada y se cachea información necesaria para agilizar la carga de la aplicación tal como la metadata de la base datos (información de tablas y campos), asimismo las vistas que el usuario desee cachear. |
===Development=== | ===Development=== | ||
− | Indicando en el config.ini '''"production = Off"''', se entra en el modo de desarrollo, en este la cache de | + | Indicando en el config.ini '''"production = Off"''', se entra en el modo de desarrollo, en este la cache de kumbiaphp framework esta desactivada y cualquier cambio que se haga en los campos y tablas de la base de datos (adición de campos, etc), vistas de la aplicación que se cacheen, surtirán efecto inmediatamente. |
− | La | + | La cache de kumbiaphp framework se puede activar nuevamente utilizando el método active de la clase Cache. |
− | < | + | <pre> |
− | + | Cache::active(true); | |
− | </ | + | </pre> |
− | '''Cuando se cambia de modo, es necesario limpiar la cache que | + | '''Cuando se cambia de modo, es necesario limpiar la cache que kumbiaphp framework ha creado para que se pueda renovar los nuevos metadatos y vistas, esto se hace simplemente eliminando el contenido del directorio de cache para la aplicación, en el caso de la aplicación por defecto sería el directorio cache/default/.''' |
== Carga selectiva de modelos == | == Carga selectiva de modelos == | ||
En la [https://launchpad.net/kumbia/0.5.1 versión 1.0](<s>antigua 0.5.1</s>) se puede cargar solo los modelos que el controlador requiera, de esa manera se optimiza los procesos de la aplicación y consume menos recursos. Para utilizar la carga selectiva, es conveniente deshabilitar la autocarga de modelos en el config.ini con '''"models_autoload = Off"'''. | En la [https://launchpad.net/kumbia/0.5.1 versión 1.0](<s>antigua 0.5.1</s>) se puede cargar solo los modelos que el controlador requiera, de esa manera se optimiza los procesos de la aplicación y consume menos recursos. Para utilizar la carga selectiva, es conveniente deshabilitar la autocarga de modelos en el config.ini con '''"models_autoload = Off"'''. | ||
− | + | Para cargar los modelos en el controlador se utiliza el método estático '''"Load::models($modelo)"''' | |
− | |||
− | + | El parámetro '''$modelo''' puede ser un directorio y/o archivo, en el caso de ser el archivo debe ser igual al nombre del mismo. | |
− | |||
− | |||
<source lang=php > | <source lang=php > | ||
− | class UsuarioController extends ApplicationController | + | class UsuarioController extends ApplicationController { |
− | { | ||
public function index() | public function index() | ||
{ | { | ||
Línea 1040: | Línea 674: | ||
</source> | </source> | ||
− | Asimismo se puede indicar con el atributo de controlador $models | + | Asimismo se puede indicar con el atributo de controlador $models. |
<source lang=php > | <source lang=php > | ||
Línea 1053: | Línea 687: | ||
</source> | </source> | ||
− | + | '''Uso avanzado''' | |
<source lang=php > | <source lang=php > | ||
Línea 1069: | Línea 703: | ||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</source> | </source> | ||
Línea 1141: | Línea 731: | ||
Ademas se pueden utilizar los Helpers y Partials dentro de estos views. | Ademas se pueden utilizar los Helpers y Partials dentro de estos views. | ||
− | < | + | <pre> |
<?php echo link_to('pages/show/aviso', 'Ir Aviso') ?> | <?php echo link_to('pages/show/aviso', 'Ir Aviso') ?> | ||
− | </ | + | </pre> |
Mostrará un enlace que al hacer clic ira a dominio.com/pages/show/aviso | Mostrará un enlace que al hacer clic ira a dominio.com/pages/show/aviso | ||
+ | |||
+ | |||
== Nuevo Helper == | == Nuevo Helper == | ||
Línea 1164: | Línea 756: | ||
El componente Filter, es un componente que permite filtrar y validar datos de una manera intuitiva, facil y simple. | El componente Filter, es un componente que permite filtrar y validar datos de una manera intuitiva, facil y simple. | ||
− | Filter dispone de | + | Filter dispone de un método estático "Filter::get" el cuál permite filtrar el elemento indicado. |
=== Filter::get($s, $options=array()) === | === Filter::get($s, $options=array()) === | ||
− | '''$s ( | + | '''$s (string, array, object)''': array, objeto, o string a filtrar. |
<br> | <br> | ||
'''$options (array)''': array de configuración del filtro. | '''$options (array)''': array de configuración del filtro. | ||
− | Los filtros se aplican | + | Los filtros se aplican de manera recursiva en los arrays y objetos. |
Ejemplo: | Ejemplo: | ||
− | < | + | <pre> |
$value = Filter::get($s, 'htmlspecialchars', array('charset' => 'UTF-8')); | $value = Filter::get($s, 'htmlspecialchars', array('charset' => 'UTF-8')); | ||
− | </ | + | </pre> |
Asimismo se pueden aplicar filtros en cadena. | Asimismo se pueden aplicar filtros en cadena. | ||
− | < | + | <pre> |
$value = Filter::get($s, 'trim', 'addslashes'); | $value = Filter::get($s, 'trim', 'addslashes'); | ||
− | </ | + | </pre> |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Los filtros en cadena no aceptan opciones de configuración, tomando las opciones por defecto. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
=== Filtros === | === Filtros === | ||
Línea 1245: | Línea 806: | ||
<source lang=php> | <source lang=php> | ||
− | if(Filter:: | + | if(Filter::date($s, 'date')) { |
... | ... | ||
} | } | ||
Línea 1251: | Línea 812: | ||
==== digits ==== | ==== digits ==== | ||
− | Filtra la cadena eliminando los caracteres que | + | Filtra la cadena eliminando los caracteres que nos son digitos. |
<source lang=php> | <source lang=php> | ||
Línea 1335: | Línea 896: | ||
<source lang=php> | <source lang=php> | ||
− | $value = Filter::get(' | + | $value = Filter::get('a1.2', 'numeric'); |
</source> | </source> | ||
Línea 1375: | Línea 936: | ||
</source> | </source> | ||
− | Los filtros de usuario deben ubicarse en el directorio "app | + | Los filtros de usuario deben ubicarse en el directorio "app/filters". |
Por convenio la clase que corresponde al filtro debe llevar el sufijo "Filter" y el archivo debe llamarse igual que la clase pero en notación smallcase. | Por convenio la clase que corresponde al filtro debe llevar el sufijo "Filter" y el archivo debe llamarse igual que la clase pero en notación smallcase. | ||
Línea 1382: | Línea 943: | ||
Un filtro que permite obtener la extension de un archivo, pasandole como valor el nombre del archivo. | Un filtro que permite obtener la extension de un archivo, pasandole como valor el nombre del archivo. | ||
− | app | + | app/filters/file_extension_filter.php |
<source lang=php > | <source lang=php > | ||
/** | /** | ||
Línea 1420: | Línea 981: | ||
En el ejemplo anterior, los datos enviados en el array de campos "usuario", son filtrados con un trim, cargados por el constructor del objecto ActiveRecord y posteriormente se guarda en la base de datos. | En el ejemplo anterior, los datos enviados en el array de campos "usuario", son filtrados con un trim, cargados por el constructor del objecto ActiveRecord y posteriormente se guarda en la base de datos. | ||
− | == Carga Selectiva, Inyección de Dependencias y el Componente Load == | + | === Carga Selectiva, Inyección de Dependencias y el Componente Load === |
− | El componente '''Load''', esta diseñado especialmente para satisfacer las necesidades de Carga Selectiva e Inyección de Dependencias, con este componente disponemos de los elementos de [http://www.kumbiaphp.com KumbiaPHP Framework] (vendors, | + | El componente '''Load''', esta diseñado especialmente para satisfacer las necesidades de Carga Selectiva e Inyección de Dependencias, con este componente disponemos de los elementos de [http://www.kumbiaphp.com KumbiaPHP Framework] (vendors, extensions, models, helpers, etc) donde así lo necesite nuestra aplicación para tal fin se dispone de los siguientes métodos: |
+ | |||
+ | ==== Load::extensions($extension) ==== | ||
+ | Carga las extensiones complementarias de [http://www.kumbiaphp.com KumbiaPHP Framework], se pueden indicar cargar extensiones de manera simultánea indicándolas como argumentos múltiples del método. | ||
+ | |||
+ | <source lang=php> | ||
+ | Load::extensions('auth', 'benchmark', 'filter'); | ||
+ | </source> | ||
− | === Load:: | + | ==== Load::vendors($vendor) ==== |
+ | Carga las librerías de terceros, es decir las cuales el [[Team_Development_KumbiaPHP_Framework Equipo de Desarrollo]] no es responsable por su desarrollo, ubicadas en el directorio '''vendors'''. Se pueden indicar cargar librerías de manera simultánea indicándolas como argumentos múltiples del método. | ||
− | + | <source lang=php> | |
+ | //se cargara las librarias FPDF, ubicadas en mi_path/core/vendors/fpdf/fpdf.php | ||
+ | Load::extensions('fpdf/fpdf'); | ||
+ | </source> | ||
+ | |||
+ | ==== Load::helpers($helper) ==== | ||
+ | Carga los helpers para vistas, se pueden cargar varios de manera simultánea indicándolos como argumentos múltiples del método. Primero se buscará el helper en el directorio global '''core/helpers''', de no existir el helper se cargará del directorio de helpers de la aplicación. | ||
+ | |||
+ | <source lang=php> | ||
+ | Load::helpers('html', 'mi_helper'); | ||
+ | </source> | ||
+ | |||
+ | ==== Load::models($model) ==== | ||
+ | Carga los modelos, se pueden cargar varios de manera simultánea indicándolos como argumentos múltiples del método o mediante un array. Asimismo se pueden cargar directorios completos de modelos. | ||
+ | |||
+ | Si la carga se efectúa en el controlador, automaticamente una instancia del modelo es cargada en un atributo del controlador correspondiente al nombre del modelo en notación camelcase. | ||
+ | |||
+ | ''NOTA: El parámetro '''$model''' puede ser un directorio y/o archivo, en el caso de ser el archivo debe ser igual al nombre del mismo.'' | ||
<source lang=php > | <source lang=php > | ||
Línea 1432: | Línea 1018: | ||
public function index() | public function index() | ||
{ | { | ||
− | //Se | + | //Se cargan los modelos Usuario y DatosPersonales |
− | Load:: | + | //usuario.php y datos_personales.php |
+ | Load::models('usuario', 'datos_personales'); | ||
} | } | ||
} | } | ||
</source> | </source> | ||
− | ''' | + | Asimismo se puede indicar con el atributo de controlador $models y estos serán cargados en cada acción. |
+ | |||
+ | <source lang=php > | ||
+ | class UsuarioController extends ApplicationController { | ||
+ | |||
+ | //Se cargan los modelos Usuario y DatosPersonales | ||
+ | public $models = array('usuario', 'datos_personales'); | ||
+ | |||
+ | public function index() | ||
+ | {} | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Cargando un directorio de modelos | ||
<source lang=php > | <source lang=php > | ||
− | class UsuarioController extends ApplicationController | + | class UsuarioController extends ApplicationController { |
− | + | ||
public function index() | public function index() | ||
{ | { | ||
− | // | + | /** se cargan los modelos en: |
− | + | * mi_app/models/dir/* | |
− | Load:: | + | * mi_app/models/dir2/model1.php |
+ | * mi_app/models/model2.php | ||
+ | */ | ||
+ | Load::models('dir', 'dir2/model1', 'model2') | ||
} | } | ||
+ | |||
+ | } | ||
+ | </source> | ||
+ | |||
+ | ==== Load::all_models() ==== | ||
+ | Carga los modelos ubicados en la raíz del directorios '''models/'''. Si la carga se efectúa dentro del controlador, automáticamente se realiza una inyección de dependencias con instancias de los modelos cargadas en atributos del controlador con el nombre correspondiente al modelo. | ||
+ | |||
+ | <source lang=php line> | ||
+ | class UsuarioController extends ApplicationController | ||
+ | { | ||
+ | public function index() | ||
+ | { | ||
+ | Load::all_models(); | ||
+ | $this->usuario = $this->Usuario->find(); | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | ==== Load::model($model) ==== | ||
+ | Obtiene una instancia del modelo indicado, esto permite hacer uso de modelos en cualquier lugar de la aplicación de manera intuitiva. | ||
+ | |||
+ | '''NOTA: el nombre del modelo que recibe como parámetro este método debe ser pasado en notación smallcase''' | ||
+ | |||
+ | <source lang=php > | ||
+ | /** | ||
+ | * Construye una lista desplegable para países | ||
+ | **/ | ||
+ | function pais_select($id, $value=null) { | ||
+ | //carga el modelo models/pais.php | ||
+ | $Pais = Load::model('pais'); | ||
+ | |||
+ | $code = "<select name=\"$id\" id=\"$id\">"; | ||
+ | foreach($Pais->find() as $pais) { | ||
+ | $code .= "<option value=\"$pais->id\""; | ||
+ | if($pais->id == $value) { | ||
+ | $code .= ' selected="selected"'; | ||
+ | } | ||
+ | $nombre = Filter::get($pais->nombre, 'htmlspecialchars'); | ||
+ | $code .= ">$nombre</option>"; | ||
+ | } | ||
+ | $code .= '</select>'; | ||
+ | |||
+ | return $code; | ||
} | } | ||
+ | </source> | ||
+ | |||
+ | Uso avanzado... | ||
+ | |||
+ | <source lang=php > | ||
+ | ... | ||
+ | //busca el país con ID 1 | ||
+ | Load::model('pais')->find(1); | ||
+ | |||
+ | //carga el modelo ubicado en models/dir/user.php | ||
+ | Load::model('dir/user')->find(); | ||
+ | |||
+ | //carga el modelo ubicado en models/user_group.php | ||
+ | Load::model('user_group')->find(); | ||
+ | |||
+ | ... | ||
</source> | </source> | ||
Línea 1491: | Línea 1153: | ||
<source lang=php> | <source lang=php> | ||
− | Session::set('usuario', ' | + | Session::set('usuario', 'Administrado'); |
</source> | </source> | ||
Línea 1501: | Línea 1163: | ||
</source> | </source> | ||
− | === | + | ===unset_data($index, $namespace='default')=== |
Elimina el valor para un indice de la sesión actual. | Elimina el valor para un indice de la sesión actual. | ||
<source lang=php> | <source lang=php> | ||
− | Session:: | + | Session::unset_data('usuario'); |
</source> | </source> | ||
− | === | + | ===isset_data($index, $namespace='default')=== |
Verifica que este definido el indice en la sesión actual. | Verifica que este definido el indice en la sesión actual. | ||
<source lang=php> | <source lang=php> | ||
− | Session:: | + | Session::isset_data('id_usuario');//retorna false. |
</source> | </source> | ||
Línea 1518: | Línea 1180: | ||
NOTA: '''$namespace''' es un espacio individual en el cual se pueden contener las variables de sesión, permitiendo evitar colisiones con nombres de variables. | NOTA: '''$namespace''' es un espacio individual en el cual se pueden contener las variables de sesión, permitiendo evitar colisiones con nombres de variables. | ||
− | + | [[Categoría:PHP Framework Benchmarks]] | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | [[ | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− |