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 == | ||
Línea 30: | Línea 24: | ||
*Con la nueva estructura 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]] | *Con la nueva estructura 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 == | ||
Línea 119: | Línea 51: | ||
| | `-- scaffolds | | | `-- scaffolds | ||
| |-- index.php | | |-- index.php | ||
− | | |-- | + | | |-- libraries |
| |-- locale | | |-- locale | ||
| |-- model_base.php | | |-- model_base.php | ||
Línea 137: | Línea 69: | ||
| | `-- scaffolds | | | `-- scaffolds | ||
| |-- kumbia | | |-- kumbia | ||
− | | |-- | + | | |-- libraries |
| |-- tests | | |-- tests | ||
| |-- vendors | | |-- vendors | ||
| `-- views | | `-- views | ||
| |-- errors | | |-- errors | ||
− | |||
| `-- templates | | `-- templates | ||
</pre> | </pre> | ||
Línea 173: | Línea 104: | ||
|views||Estan agrupados las vistas de los controladores (controllers). Por defecto se encuentran los directorios '''templates/''', '''pages/''', '''partials/''' y '''errors/''' | |views||Estan agrupados las vistas de los controladores (controllers). Por defecto se encuentran los directorios '''templates/''', '''pages/''', '''partials/''' y '''errors/''' | ||
|- | |- | ||
− | |extensions||En este directorio se ubican las extensiones para nuestra aplicación, una extensión te permite adicionar nuevas características que serán utilizadas | + | |extensions||En este directorio se ubican las extensiones para nuestra aplicación, una extensión te permite adicionar nuevas características que serán utilizadas he integradas a la aplicación por medio de las librerias que proporciona [http://www.kumbiaphp.com KumbiaPHP] |
|- | |- | ||
− | | | + | |libraries||En este directorio se pueden colocar clases propias con fines específicos o librerías externas al framework (vendors). Estas para ser utilizadas en los controladores (controllers) y/o Modelos (models). |
|- | |- | ||
− | |temp||Este directorio contiene las carpetas y archivos creados cuando | + | |temp||Este directorio contiene las carpetas y archivos creados cuando KumbiaPHP está cacheando un template, view o partial y cuando realiza operaciones de logs. '''Este directorio necesita permisos de escritura'''. |
|- | |- | ||
|public||Agrupa las imágenes, css, javascript y files que serán utilizados por nuestra aplicación | |public||Agrupa las imágenes, css, javascript y files que serán utilizados por nuestra aplicación | ||
Línea 193: | Línea 124: | ||
[[Archivo:Application_kumbiaphp_framework.png|center|thumb|200px|application.php]] | [[Archivo:Application_kumbiaphp_framework.png|center|thumb|200px|application.php]] | ||
− | Como se aprecia en la imagen existe una estrecha relación entre ''' | + | Como se aprecia en la imagen existe una estrecha relación entre '''apllication.php''' y los controladores disponibles en el directorio controllers/. Esta relación se basa principalmente en que las variables y metodos creados en el '''ApplicationController''' (application.php), estarán disponibles para ser usados en cualquier controlador que tengamos en nuestra aplicación. |
En esta clase se encuentran dos métodos principales, dichos métodos se comportan como un filtro antes y después de ejecutar un controller. | En esta clase se encuentran dos métodos principales, dichos métodos se comportan como un filtro antes y después de ejecutar un controller. | ||
Línea 231: | Línea 162: | ||
|kumbia|| En este directorio se ubica el núcleo de [http://www.kumbiaphp.com KumbiaPHP] | |kumbia|| En este directorio se ubica el núcleo de [http://www.kumbiaphp.com KumbiaPHP] | ||
|- | |- | ||
− | | | + | |libraries|| En este directorio se encuentran las librerias compartidas por todas las aplicaciones, las cuales el [http://wiki.kumbiaphp.com/Team_Development_KumbiaPHP_Framework Equipo de Desarrollo] se responsabiliza por su mantenimiento. |
|- | |- | ||
|tests||En este directorio se ubican las pruebas unitarias para [http://www.kumbiaphp.com KumbiaPHP] | |tests||En este directorio se ubican las pruebas unitarias para [http://www.kumbiaphp.com KumbiaPHP] | ||
Línea 241: | Línea 172: | ||
Se agregan opciones para un manejo mas apropiado de la configuración del framework, para la aplicación. | Se agregan opciones para un manejo mas apropiado de la configuración del framework, para la aplicación. | ||
+ | *'''models_autoload''' Auto carga de modelos, útil 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. | ||
*'''cache_driver''' driver que se utilizara para el manejo de cache. KumbiaPHP cuenta con tres (3) driver: file, sqlite y memsqlite. | *'''cache_driver''' driver que se utilizara para el manejo de cache. KumbiaPHP cuenta con tres (3) driver: file, sqlite y memsqlite. | ||
− | *'''locale''' | + | *'''locale''' Localicazión |
− | |||
<pre>;; Configuracion de Aplicacion | <pre>;; Configuracion de Aplicacion | ||
Línea 260: | Línea 191: | ||
; log_exceptions: muestra las excepciones en pantalla (On|off) | ; log_exceptions: muestra las excepciones en pantalla (On|off) | ||
; charset: codificacion de caracteres | ; charset: codificacion de caracteres | ||
+ | ; models_autoload: Habilita la autocarga de modelos | ||
; cache_driver: driver para la cache (file, sqlite, memsqlite) | ; cache_driver: driver para la cache (file, sqlite, memsqlite) | ||
; metadata_lifetime: Tiempo de vida de la metadata cacheada | ; metadata_lifetime: Tiempo de vida de la metadata cacheada | ||
− | ; locale: | + | ; locale: Localicazion |
− | |||
Línea 280: | Línea 211: | ||
log_exceptions = On | log_exceptions = On | ||
charset = UTF-8 | charset = UTF-8 | ||
+ | models_autoload = On | ||
cache_driver = file | cache_driver = file | ||
;metadata_lifetime = "+1 year" | ;metadata_lifetime = "+1 year" | ||
;locale = es_ES | ;locale = es_ES | ||
− | |||
</pre> | </pre> | ||
Línea 311: | Línea 242: | ||
host = localhost | host = localhost | ||
username = root | username = root | ||
− | password = | + | password = |
− | name = | + | name = innogest |
type = mysql | type = mysql | ||
Línea 318: | Línea 249: | ||
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. |
− | + | ||
+ | Extensiones Propias de Kumbiaphp Framework | ||
+ | *session | ||
+ | *logger | ||
+ | *auth | ||
+ | *date | ||
+ | *filter | ||
+ | *acl | ||
+ | *benchmark | ||
+ | *security | ||
+ | |||
+ | Extensiones externas al framework | ||
+ | *excel | ||
+ | *fpdf | ||
+ | *phpmailer | ||
+ | *libchart | ||
+ | |||
+ | <pre> | ||
+ | ; LIBRERIAS DISPONIBLES | ||
+ | ; Librerias Propias de KumbiaPHP Framework (libraries) | ||
+ | ; * session | ||
+ | ; * logger | ||
+ | ; * auth | ||
+ | ; * date | ||
+ | ; * filter | ||
+ | ; * acl | ||
+ | ; * benchmark | ||
+ | ; * security | ||
+ | ; | ||
+ | ; Cargadores en libraries para librerias de terceros (vendors) | ||
+ | ; * excel | ||
+ | ; * fpdf | ||
+ | ; * phpmailer | ||
+ | ; * libchart | ||
+ | |||
+ | |||
+ | [modules] | ||
+ | libraries = logger | ||
+ | </pre> | ||
== Router == | == Router == | ||
Línea 356: | Línea 325: | ||
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 391: | Línea 360: | ||
</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, en la'''versión 0.5''' se hacia uso de la funcion "render_partial", sin embargo con la finalidad de obtener | + | 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, en la'''versión 0.5''' se hacia uso de la funcion "render_partial", sin embargo con la finalidad de obtener myor orden e intuitividad, esta función se encapsulo en la clase '''View''', y basta con hacer en la vista (Templates, views) lo siguiente. |
<source lang=php > | <source lang=php > | ||
Línea 415: | Línea 384: | ||
</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 > | ||
Línea 447: | Línea 416: | ||
</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 455: | Línea 424: | ||
</source> | </source> | ||
− | === View::content()=== | + | === View::content() en las vistas de acciones === |
− | Este método de la clase '''View''' viene a remplazar la función '''content | + | Este método de la clase '''View''' viene a remplazar la función '''content''', esta se utiliza para indicar donde KumbiaPHP debe renderizar el contenido almacenado en el buffer de salida. |
− | Su uso para las vistas de las acciones esta | + | Su uso para las vistas de las acciones esta intimamente ligado a los '''echo''' o '''print''' que efectue el usuario, asimismo determina el lugar donde se mostrarán los los mensajes '''Flash''' provenientes de ActiveRecord o los propios. Ejemplo: |
<source lang=php > | <source lang=php > | ||
Línea 481: | Línea 450: | ||
===View::helpers($helper)=== | ===View::helpers($helper)=== | ||
− | Un '''''helpers''''' representa una ayuda a nivel de las vistas (view), esto quiere decir siendo consistente con el m'''V'''c solo deben ser utilizados en las | + | Un '''''helpers''''' representa una ayuda a nivel de las vistas (view), esto quiere decir siendo consistente con el m'''V'''c solo deben ser utilizados en las vitas. |
Los '''''helpers''''' estan ubicados en '''miapp/extensions/helpers/''', en ese directorio pueden existir tantos helpers como necesitemos [http://www.kumbiaphp.com KumbiaPHP], pero tambien pueden existir helpers en '''core/extensions/helpers/''' en estos casos el framework da prioridad a los helpers ubicados en el directorio de la aplicación, esto quiere decir que si existen dos archivos con el mismo nombre en los directorios helpers antes descrito [http://www.kumbiaphp.com KumbiaPHP] cargara el que se encuentra ubicado en el directorio de la aplicación (app). | Los '''''helpers''''' estan ubicados en '''miapp/extensions/helpers/''', en ese directorio pueden existir tantos helpers como necesitemos [http://www.kumbiaphp.com KumbiaPHP], pero tambien pueden existir helpers en '''core/extensions/helpers/''' en estos casos el framework da prioridad a los helpers ubicados en el directorio de la aplicación, esto quiere decir que si existen dos archivos con el mismo nombre en los directorios helpers antes descrito [http://www.kumbiaphp.com KumbiaPHP] cargara el que se encuentra ubicado en el directorio de la aplicación (app). | ||
Línea 512: | Línea 481: | ||
echo $code; | echo $code; | ||
+ | } | ||
} | } | ||
</source> | </source> | ||
Línea 518: | Línea 488: | ||
<source lang=php > | <source lang=php > | ||
− | |||
//Esta es una vista cualquiera | //Esta es una vista cualquiera | ||
Línea 526: | Línea 495: | ||
//Hacemos uso del helpers, con esto tendremos un select en el view | //Hacemos uso del helpers, con esto tendremos un select en el view | ||
− | MiHelpers::paisSelect(1) | + | <?php MiHelpers::paisSelect(1) ?> |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</source> | </source> | ||
Línea 699: | Línea 532: | ||
==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::get($id, $group='default')=== | |
− | |||
− | ===Cache:: | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
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 540: | ||
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 560: | ||
<?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 568: | ||
<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 582: | ||
<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 657: | ||
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 663: | ||
$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 702: | ||
===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 721: | ||
... | ... | ||
</source> | </source> | ||
+ | |||
===validates_inclusion_in($field, $list, $params=array())=== | ===validates_inclusion_in($field, $list, $params=array())=== | ||
Línea 966: | Línea 775: | ||
</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 830: | ||
===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 861: | ||
</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 874: | ||
</source> | </source> | ||
− | + | '''Uso avanzado''' | |
<source lang=php > | <source lang=php > | ||
Línea 1069: | Línea 890: | ||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</source> | </source> | ||
Línea 1141: | Línea 918: | ||
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 943: | ||
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, | + | Los filtros en cadena no aceptan opciones de configuración, tomando las opciones por defecto. |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
=== Filtros === | === Filtros === | ||
Línea 1245: | Línea 993: | ||
<source lang=php> | <source lang=php> | ||
− | if(Filter:: | + | if(Filter::date($s, 'date')) { |
... | ... | ||
} | } | ||
Línea 1251: | Línea 999: | ||
==== 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 1083: | ||
<source lang=php> | <source lang=php> | ||
− | $value = Filter::get(' | + | $value = Filter::get('a1.2', 'numeric'); |
</source> | </source> | ||
Línea 1375: | Línea 1123: | ||
</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 1130: | ||
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 1168: | ||
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::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 1189: | ||
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 = htmlspecialchars($pais->nombre); | ||
+ | $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 1324: | ||
<source lang=php> | <source lang=php> | ||
− | Session::set('usuario', ' | + | Session::set('usuario', 'Administrado'); |
</source> | </source> | ||
Línea 1501: | Línea 1334: | ||
</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 1351: | ||
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]] | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | [[ | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− |