Está en la página 1de 50

Manual para Desarrolladores

VERSIONAMIENTO
Versin Versin de Elastix 1 2.3.0 Fecha 16-Ene-2012 Elaborado por Ing. Alberto Santos Detalles Documentacin Inicial

Introduccin
El presente manual es una gua para desarrolladores en la utilizacin del Framework Elastix para la creacin de nuevos mdulos. En este manual se explicar como se puede crear un mdulo Elastix, Fundamentos Bsicos del Framework Elastix, y cmo llegar a convertir nuestro nuevo mdulo en un Addon de Elastix.

1. Creacin de un nuevo mdulo Elastix


Para la creacin de un nuevo mdulo de Elastix usaremos el addon Developer, disponible en el mdulo de Addons de Elastix. 1.1 Instalacin del Addon Developer
Ingresamos a la interfaz Elastix como usuario administrador y vamos a la pestaa de Addons, una vez que termine de cargar los addons disponibles buscamos el que diga Developer.


Imagen 1.- Identificacin del addon Developer.

Ya identificado el addon damos click en el botn Install respectivo. Luego de esto se inicia el proceso de instalacin del addon, por lo que se debe esperar unos minutos hasta que finalice la instalacin.


Imagen 2.- Finalizacin de la instalacin del addon Developer.

Luego de esto salimos de la interfaz y volvemos a ingresar como administrador. Debemos ver una nueva pestaa de men con el nombre Developer.

1.2 Utilizando el Elastix Developer El addon Developer nos permitir crear de manera transparente para nosotros el esqueleto inicial de cdigo necesario para elaborar un mdulo de Elastix, lo que puede constituir un ahorro de horas en muchos casos. El addon para desarrolladores tiene tres submens pero el que nos interesa se llama Constructor de Mdulos o Build Module y es el primer submen. La funcin del constructor de mdulos es generar el esqueleto de cdigo del nuevo mdulo que estamos creando, para que luego podamos continuar con el desarrollo extendiendo este cdigo inicial. Al crear un modulo desde aqu, se generar lo siguiente:

El men (o los mens) dentro de la interfaz Web de Elastix. Es decir que ya no tendremos que modificar manualmente la base de datos menu.db. El cdigo esqueleto, el cual se encontrar dentro de una carpeta cuyo nombre ser igual al ID del mdulo. Esta carpeta ser ubicada a su vez dentro de la carpeta /var/www/html/modules que es donde residen todos los mdulos de Elastix. Es decir que ya no tenemos que crear manualmente esta carpeta. Pantallas prototipo. Estas pantallas pueden ser de tres tipos: formulario, reporte y enmarcado.

Veamos ahora cmo luce el constructor de mdulos.

Imagen 3.- El constructor de mdulos incluido en el addon Developer

Como podemos observar, el constructor de mdulos se encuentra dividido en tres partes: Informacin General. Localizacin. Descripcin del mdulo.

Informacin General Esta seccin nos permite definir el nombre e identificador nico del mdulo, as como tambin los datos de la persona que crea el modulo para comentarlas en las cabeceras de cada archivo de programacin en PHP. Tambin nos permite

configurar el nivel de accesibilidad que tendr el mdulo a travs del parmetro Permisos de Grupo.

Imagen 4.- Seccin de informacin general dentro del constructor de mdulos

Localizacin En esta seccin se configura el lugar, dentro del men general, donde vamos a ubicar el nuevo mdulo. Por omisin esta seccin luce como la siguiente figura.


Imagen 5.- Seccin donde se configura la ubicacin del mdulo

Si decimos que el mdulo es de nivel 3 entonces aparecern automticamente nuevos campos para ingresar los identificadores de los mens padres de nivel 1 y nivel 2.

Imagen 6.- Aparecen nuevos campos si se dice que el mdulo ser de nivel 3

Para clarificar el significado de los campos mostrados en esta seccin veamos la siguiente tabla.
Nombre campo Nivel del Mdulo Descripcin Aqu definimos el nivel de jerarqua del modulo. Aqu definimos si vamos a colocar el nuevo mdulo bajo un men de nivel 1 existente o se tendr que crear uno nuevo. Para colocar el nuevo mdulo bajo un men previamente existente escogemos S y de manera automtica se desplegar un listado con los mdulos de nivel 1 existentes.

Existe Padre Nivel 1?


Si escogemos No crearemos un nuevo men de nivel 1 sobre la marcha. Por esta razn aparecern dos campos adicionales para especificar el nombre y el identificador. Definimos el nombre del mdulo padre. La primera letra con mayscula. Definimos el identificador del mdulo padre. Todo con minsculas y no se permiten espacios. Esta opcin aparecer si escogimos un nivel 3 en el campo Nivel del Mdulo. De manera similar a lo que ocurre con el campo Existe Padre Nivel 1, si se escoge No aparecern dos campos ms. Nombre Padre Nivel 2 Id Padre Nivel 2 Definimos el nombre del mdulo padre de nivel 2. La primera letra con mayscula. Definimos el identificador del mdulo padre de nivel 2. Todo con minsculas y no se permiten espacios.

Nombre Padre Nivel 1 Id Padre Nivel 1

Existe Padre Nivel 2?

Descripcin del mdulo Esta ltima seccin es la ms interesante pues es aqu donde se crea el contenido mismo del mdulo. A continuacin se explica qu significan los tres tipos de mdulos que se pueden crear. Formulario: Sirve para recolectar datos del usuario. El constructor de mdulos cuenta con soporte para los tipos de campos HTML ms comunes como son: texto, seleccin, fecha, rea de texto, casilla de verificacin, radio, contrasea, oculto y archivo. Reporte: Un reporte muestra datos organizados en forma de una tabla donde se incluyen automticamente algunos controles tiles como botones para navegacin. Luego de generar el cdigo necesario con el constructor de mdulos ya es ms sencillo enlazar el reporte con una base de datos para mostrar informacin til. Enmarcado: Embebe un URL arbitrario en la pantalla. Muy til cuando queremos integrar aplicaciones externas en la interfaz Web de Elastix. Un ejemplo de esto es la integracin de vtigerCRM.

Imagen 7.- Creacin de una pantalla tipo Formulario

Con los botones ">>", "<<" podemos aadir o quitar los campos a insertar en nuestro formulario. Al guardar los datos establecidos para el nuevo mdulo se crear el siguiente rbol de directorios (exceptuando para los mdulos tipo enmarcado, en cuyo caso el mdulo ser simplemente un link al URL proporcionado) en la ruta documentRoot/modules donde documentRoot es /var/www/html para Elastix. Como se puede notar, un modulo tiene la misma arquitectura general del framework, arquitectura web MVC2. Por ende se define a esto como un MVC2 dentro de otro MVC2, una definicin de recursividad de grado 2. Esto nos permite de forma inmediata hacer una similitud entre las carpetas que tienen las siguientes relaciones: themes es la capa vista. index.php es la capa control. libs es la capa modelo.

1.3 Breve descripcin de cada carpeta que se crea dentro del mdulo configs Por default esta carpeta se crea con un archivo denominado default.conf.php, este archivo debe contener las configuraciones bsicas del mdulo.
Almacena dentro de este archivo variables de configuracin que sern muy usadas a lo largo del mdulo, por ejemplo DSN

A continuacin se mostrarn dos DSNs usados en Elastix:

Sqlite3: sqlite3:///$arrConf[elastix_dbdir]/base.db Mysql: se puede usar la funcin generarDSNSistema la cual ya nos devuelve el string de conexin. A continuacin se detallar un poco esta funcin que la podemos encontrar en /var/www/html/libs/misc.lib.php

/** * Funcin para construir un DSN para conectarse a varias bases de datos * frecuentemente utilizadas en Elastix. Para cada base de datos reconocida, se * busca la clave en /etc/elastix.conf o en /etc/amportal.conf segn corresponda. * * @param string $sNombreUsuario Nombre de usuario para interrogar * @param string $sNombreDB Nombre de base de datos para DSN * @param string $ruta_base Ruta base para inclusin de libreras * * @return mixed NULL si no se reconoce usuario, o el DSN con clave resuelta */ function generarDSNSistema($sNombreUsuario, $sNombreDB, $ruta_base='')

help Dentro de esta carpeta encontraremos un archivo llamado id_modulo.hlp. Este es el archivo que se encarga de mostrar la ayuda embebida del mdulo.
Es recomendable que una vez que hayas terminado tu mdulo por completo, elabores la ayuda embebida que no es otra cosa que una especie de manual de usuario, indicando las diferentes opciones que ofrece este mdulo. Es recomendable que sea escrita en ingls.

A continuacin se mostrar un ejemplo muy sencillo de como puede lucir el cdigo dentro de este archivo. Esta ayuda slo mostrar el ttulo del mdulo seguido de una breve descripcin y una imagen que se encuentra en la ruta indicada.
<html> <header> <link rel="stylesheet" href="/themes/{$THEMENAME}/styles.css"> <link rel="stylesheet" href="/themes/{$THEMENAME}/help.css"> </header> <body>


<h1>{$node_name}</h1> <p align="Justify">This is the embedded help for my module.</p> <div><img src="../modules/{$node_id}/images/image.png" border="0"></div> <div>Figure 1</div><br/> </body> </html>

images Dentro de esta carpeta se guardarn todas las imgenes propias del mdulo, por ejemplo cono, imgenes usadas para la ayuda embebida, etc. lang Como ya sabemos el Framework Elastix soporta traduccin de idiomas!! Pues bien, como es de suponer dentro de esta carpeta se almacenan las traducciones para nuestro mdulo. Cada traduccin para cada idioma se almacena en un archivo diferente, de acuerdo a la siguiente tabla:
Archivo bg.lang br.lang ca.lang cn.lang da.lang de.lang en.lang el.lang es.lang fa.lang fr.lang it.lang hu.lang hr.lang pl.lang ro.lang ru.lang sl.lang sv.lang ko.lang ja.lang sr.lang Idioma Blgaro Portugus Cataln Chino Simplificado Dans Alemn Ingls Griego Espaol Persa Francs Italiano Hngaro Croata Polaco Rumano Ruso Esloveno Sueco Coreano Japons Serbio


Se recomienda que se creen al menos dos archivos de traducciones, uno con el idioma nativo del desarrollador y otro en ingls

Por lo tanto, si queremos hacer la traduccin de nuestro mdulo al espaol tenemos que crear un archivo dentro de esta carpeta llamado es.lang. Este archivo bsicamente consiste de un slo arreglo, en el cual la clave es la palabra a traducir y el valor es la clave traducida. Por ejemplo:
<?php global $arrLangModule; $arrLangModule=array( "Module" => "Mdulo", "This is a test module" => "Este es un mdulo prueba, ); ?>

Es recomendable que las claves en nuestro arreglo de traducciones sean en ingls

libs Como ya se mencion anteriormente esta es nuestra capa de modelo. Dentro de esta carpeta habr una librera que es la que se encargar de hacer consultas a bases de datos, modificar archivos, etc.
Todos los querys que se realicen deben de ser parametrizados, esto evitar la inyeccin de cdigo SQL arbitrario a nuestra base. Ms adelante se explicar con mayor detalle como hacerlo.

Recuerda que nuestro servicio de apache corre usando el usuario asterisk, por ende slo tendremos acceso a archivos y carpetas a los cuales asterisk tenga acceso. No podrs leer o escribir sobre un archivo o carpeta por ejemplo que tenga solo permisos para root.
No hagas uso de comandos de consola que necesitan de privilegios root. Esto puede conllevar a que nuestro script o librera se convierta en un potencial hueco de seguridad.

Pero y que pasa si nuestro script o librera necesita obligadamente usar comandos que requieren privilegios de root? Es ah donde entra en accin nuestro script elastix-helper. 1.4 Uso de elastix-helper elastix-helper es un script ubicado en /usr/bin el cual permite ejecutar scripts privilegiados que se encuentran dentro de la carpeta: /usr/share/elastix/privileged. Es aqu donde ubicaremos al script que realizar tareas que necesiten privilegios de root, este script debe ser propietario root y pertenecer al grupo root adems tener permisos 755. Para poder usarlo debemos ejecutar el siguiente cdigo en la funcin que deseemos de nuestra librera.
exec("/usr/bin/elastix-helper script_privileged parameter", $output, $ret);

script_privileged es el nombre del script privilegiado ubicado en la ruta ya mencionada anteriormente. parameter es el parmetro que se le pasar al script script_privileged, se le puede pasar ms de un parmetro, simplemente se los separa con espacios, as como tambin pueden no pasarse parmetros. Si el valor de $ret es 0 quiere decir que no hubieron problemas.

themes Esta carpeta es la capa de vista. Al interior de esta carpeta encontraremos otra carpeta llamada default la cual contendr todas las vistas que podr tener el mdulo. Por ejemplo, un mdulo puede contener como vista principal una grilla, por lo que se necesitar una vista (un archivo tpl) que contendr los filtros para la grilla (en caso de haberlos, caso contrario no se necesitara un archivo tpl), y tambin podra ser que al presionar un botn se muestre un formulario, por lo que necesitaramos otro archivo tpl que contendr los campos del formulario. A continuacin mostraremos una plantilla tpica de una vista para tpl y otra para un formulario.

Plantilla tpica de un mdulo con vista grilla


<table width="99%" border="0" cellspacing="0" cellpadding="0" align="center"> <tr class="letra12"> <td width="12%" align="left"><input class="button" type="submit" name="new" value="{$New}"></td> <td width="10%" align="left">&nbsp;&nbsp;</td> <td width="10%" align="right"> {$filter_type.LABEL}:&nbsp;&nbsp;{$filter_type.INPUT}&nbsp;&nbsp; {$filter_txt.INPUT} <input class="button" type="submit" name="show" value="{$SHOW}" /> </td> </tr> </table>

Como se puede observar en este mdulo de grilla se consta con un botn New y con un filtrado. Plantilla tpica de un mdulo con vista formulario
<table width="99%" border="0" cellspacing="0" cellpadding="4" align="center"> <tr class="letra12"> <td align="left"><input class="button" type="submit" name="save" value="{$SAVE}"></td> </tr> </table> <br /> <div class="tabForm" style="font-size: 16px; height: auto;" width="100%"> <table style="font-size: 16px;" width="100%" cellspacing="0" cellpadding="8"> <tr class="letra12"> <td align="left" width="130px"><b>{$manufacturer.LABEL}: </b></td> <td align="left">{$manufacturer.INPUT}</td> </tr> </table> </div>

Para este formulario se consta con un botn Save y con un campo al cual se le denomin manufacturer. Estas son plantillas bsicas, en realidad uno lo puede hacer tan complejo como uno quiera. Si queremos incluir javascripts en nuetro mdulo, simplemente debemos crear una carpeta llamada js dentro de themes/default y colocar ahi los javascripts que queramos (deben tener extensin .js), as mismo si queremos incluir css hay que crear una carpeta llamada css dentro de themes/default y colocar ahi los css que queramos (deben tener extensin .css), el framework se encargar de incluir estos

archivos automticamente. index.php El archivo index.php del mdulo representa la capa de control, el framework se encarga de redirigir la peticin a este archivo llamando a la funcin _moduleContent. Este archivo es el que se encarga de comunicar con la capa de vista y de modelo. Si hemos usado el developer para la creacin del mdulo, podremos observar que este archivo ya viene escrito con una plantilla por default, y sobre esta plantilla podemos hacer las modificaciones que queramos de acuerdo a la necesidad de nuestro mdulo.

2. Usando el Framework Elastix


Bien, hasta ahora ya tenemos creado nuestro mdulo con una configuracin bsica pero todava no tenemos un claro conocimiento de las diferentes facilidades y libreras que nos ofrece el framework Elastix. A continuacin se detallarn algunas libreras y clases con sus funciones ms importantes. Todas estas libreras se encuentran debajo de /var/www/html/libs 2.1 Librera misc.lib.php En esta librera encontraremos funciones de diversos tipos, no es necesaria incluirla en el mdulo ya que el framework Elastix se encarga de esa tarea. Listaremos las funciones de mayor relevancia y las que probablemente ms necesitaremos usar. function _tr($s)

Esta es la funcin que utilizamos para realizar la traduccin de algn texto. Recibe como parmetro un string que es el texto a traducir. La funcin trabaja de la siguiente manera: Busca el string pasado como parmetro en las claves del arreglo de lenguajes del framework y del mdulo (archivo .lang dentro de la carpeta lang del mdulo, escoger el archivo correspondiente al lenguaje que este configurado en el servidor

Elastix), en caso de encontrarla la funcin devuelve el valor del arreglo para esa clave, caso contrario devuelve el mismo string pasado como parmetro.

Ejemplo: Si tenemos seleccionado espaol como lenguaje y queremos la traduccin de Hi this is my first module (definida previamente en el archivo es.lang), simplemente hacemos lo siguiente:
$translate = _tr(Hi this is my first module);

function getParameter($parameter)

Esta funcin la utilizaremos cuando queremos obtener un parmetro que ha sido enviado por POST or por GET. Busca el parmetro en el arreglo $_POST, en caso de existir devuelve $_POST[$parameter], de no existir, lo busca en el arreglo $_GET, si existe devuelve $_GET[$parameter], si no existe en $_POST ni en $_GET esta funcin devuelve NULL. Ejemplo: Supongamos que tenemos un mdulo con un botn que dice guardar y el nombre del botn es save y queremos saber si ese botn fue presionado, tendramos que hacer lo siguiente:
if(getParameter(save))

De esta manera entrar en if si el botn de guardar fue presionado. function obtenerClaveCyrusAdmin($ruta_base='')

Esta funcin devuelve la clave de admin para el Cyrus. El parmetro $ruta_base debe ser pasado como /var/www/html/ si llamamos a esta funcin fuera de esa ruta. Esta funcin parsea el archivo /etc/elastix.conf y busca la palabra clave cyrususerpwd, en caso de encontrarla devuelve su valor, caso contrario devuelve palosanto que es la clave por omisin.

function obtenerClaveAMIAdmin($ruta_base='')

Esta funcin retorna la clave para AMI (Asterisk Manager Interface) del usuario admin. El parmetro $ruta_base debe ser pasado como /var/www/html/ si llamamos a esta funcin fuera de esa ruta. Esta funcin busca la clave en el archivo /etc/elastix.conf, si se encuentra la palabra clave amiadminpwd se retorna el valor de esa clave, caso contrario se retorna elastix456 que es la clave AMI por default en Elastix. function generarDSNSistema($sNombreUsuario, $sNombreDB, $ruta_base='')

Ya nos habamos topado antes en este manual con esta funcin. Pero afianzaremos ms lo que se dijo acerca de esta til funcin. Como ya lo habamos mencionado antes esta funcin retorna el DSN (Data Source Name) para una conexin con el motor de bases de datos mysql. El parmetro $ruta_base debe ser pasado como /var/www/html/ si llamamos a esta funcin fuera de esa ruta. El parmetro $sNombreUsuario es el usuario con el cual nos conectaremos a mysql, puede ser root o asteriskuser. El parmetro $sNombreDB es el nombre de la base de datos mysql a la cual nos vamos a conectar. function writeLOG($logFILE, $log)

Esta funcin permite escribir en un log. El parmetro $logFILE es el nombre del archivo log, ste se ubicar debajo de /var/log/elastix. El parmetro $log es el texto que se escribir en el log. Si el archivo $logFILE no existe lo crea, y si ya existe, aade al final del archivo el texto $log. Una vez ms es importante recordar que el servicio httpd que usa Elastix tiene como usuario a asterisk por lo tanto slo podr escribir sobre archivos a los cuales asterisk tenga permiso. En el caso de que $logFILE no exista, no hay problema ya que asterisk es propietario de la carpeta /var/log/elastix por lo que podr

crear archivos ah sin inconvenientes. Ejemplo: Si queremos escribir Ha ingresado al mdulo de prueba en un log llamado miModulo.log tendramos que hacer lo siguiente:
writeLOG(miModulo.log,Ha ingresado al mdulo de prueba);

De esta forma se crear el log miModulo.log (de no existir) conteniendo lo siguiente:


[Jan 19 14:48:11] Ha ingresado al mdulo de prueba

La fecha a la izquierda es la fecha del servidor al momento de escribir el mensaje en el log.

2.2 Clase paloSantoDB.class.php Esta clase se encarga de crear un objeto con la conexin a una base de datos. El objetivo de esta clase es encapsular o abstraerse del proceso de conexin a la base de datos, de tal forma que el desarrollador simplemente tenga que instanciar esta clase y pueda realizar las consultas (queries) que desee. Esta clase tampoco es necesario incluirla en nuestro mdulo, ya que el framework Elastix se encarga de ello. Para instanciar la clase se le debe pasar el DSN de la base de datos. Ejemplo: Supongamos que queremos instanciar una clase de paloDB en nuestro mdulo para crear una conexin a la base de datos mysql llamada miBase a la cual slo tiene acceso el usuario root. Tendramos que hacer lo siguiente:
$dsn = generarDSNSistema(root,miBase); $pDB = new paloDB($dsn);

Una vez instanciada esta clase recuerda pasarla por referencia a las funciones requeridas, esto ser muy importante sobre todo cuando trabajemos con transacciones.

A continuacin se detallarn algunas de sus funciones. function genQuery($query, $param = NULL)

Es el procedimiento para ejecutar una sentencia SQL que no devuelve filas ni resultados. En caso de error se asigna a la variable de clase $this->errMsg. Slo es usado para hacer manipulacin de los datos de la base. El parmetro $query es el string que contiene al query que se va a ejecutar. El parmetro $param es un arreglo que slamente es pasado a esta funcin cuando se realizan queries parametrizados, es aconsejable que todo query sea parametrizado, sobre todo cuando existen variables que son ingresadas al servidor por el cliente. Ejemplo: Supongamos que queremos insertar en la tabla miTabla un nuevo registro con los campos campo1 y campo2, con los valores $value1 y $value2 respectivamente y que llegan al servidor mediante el cliente. Tendramos que realizar lo siguiente (supongamos que ya tenemos instanciada la clase con el DSN a la base correspondiente en la variable $pDB).
$query = INSERT INTO miTabla (campo1,campo2) VALUES (?,?); $arrParam = array($value1, $value2); $result = $pDB->genQuery($query,$arrParam); if($result == FALSE) echo _tr(Query Error). .$pDB->errMsg; else echo _tr(Query successfully executed);

Es muy importante el orden que se coloca en el arreglo $arrParam ya que de acuerdo a ese orden se van asignando los valores en el query. function fetchTable($query, $arr_colnames = FALSE, $param = NULL)

Es el procedimiento que recupera todas las filas resultado de una peticin SQL que devuelve una o ms filas. Los parmetros $query y $param tienen los mismos propsitos que los descritos en

la funcin anterior. El parmetro $arr_colnames ser FALSE si deseamos que cada tupla tenga como ndice un nmero incremental, si es TRUE cada tupla tendr como ndice el nombre de la columna. Ejemplo: Supongamos que deseamos imprimir en pantalla los valores de la columna campo1 de la tabla miTabla cuando el campo2 tiene como valor $value2, as mismo asumamos que ya contamos con el objeto $pDB.
$query = SELECT campo1 FROM miTabla WHERE campo2=?; $arrParam = array($value2); $result = $pDB->fetchTable($query,TRUE,$arrParam); if($result === FALSE) echo _tr(Query Error). .$pDB->errMsg; else{ if(count($result) > 0){ foreach($result as $value){ echo $value[campo1].<br />; } } else echo _tr(There is no data for the criteria search); }

Siempre que usemos las funciones fetchTable o getFirstRowQuery descrita ms adelante, debemos comparar el valor devuelto de estas funciones con una triple igualdad ===, recuerda que estas funciones pueden devolver tambin arreglos vacos que son evaluados como FALSE tambin, usando === no solo comparamos por valor sino por tipo de dato tambin.

function getFirstRowQuery($query, $arr_colnames = FALSE, $param = NULL)

Procedimiento para recuperar una sola fila del query que devuelve una o ms filas. Devuelve una fila con campos si el query devuelve al menos una fila, caso contrario devuelve un arreglo vaco o FALSE en caso de error. Los parmetros $query, $arr_colnames y $param tienen los mismos propsitos que

los descritos en la funcin fetchTable. Ejemplo: Supongamos que queremos imprimir en pantalla la cantidad de registros en la tabla miTabla cuyo campo1 tiene como valor $value1
$query = SELECT COUNT(*) FROM miTabla WHERE campo1=?; $arrParam = array($value1); $result = $pDB-> getFirstRowQuery($query,FALSE,$arrParam); if($result === FALSE) echo _tr(Query Error). .$pDB->errMsg; else echo $result[0];

function beginTransaction()

Procedimiento para iniciar una transaccin. Recuerda una transaccin es usada, cuando deseamos que en caso de que ocurra algn evento inesperado o no deseado regrese la base a su estado anterior. function rollBack()

Procedimiento de rollBack para una transaccin. function commit()

Procedimiento de commit para una transaccin. Ejemplo: Supongamos que queremos crear una funcin que inserte los valores $value1 y $value2 en los campos campo1 y campo2 respectivamente*, en la tabla miTabla1 (la cual tiene como id el campo id que es autoincremental). Luego de esto deseamos insertar en la tabla miTabla2 el id del registro recin ingresado en miTabla1 en el campo id_miTabla1 y en el campo fecha la fecha actual.
*Nota: no puede haber otro registro que tenga exactamente los mismos valores tanto en campo1 como en campo2


function insertRegister($value1, $value2, &$pDB, &$errMsg) { $pDB->beginTransaction(); $query1 = INSERT INTO miTabla1 (campo1,campo2) VALUES (?,?); $arrParam1 = array($value1, $value2); $result1 = $pDB->genQuery($query1,$arrParam1); if($result1 == FALSE){ $pDB-> rollBack(); $errMsg = $pDB->errMsg; return FALSE; } else{ $query2 = INSERT INTO miTabla2 (id_miTabla1,fecha) VALUES((SELECT id FROM miTabla1 WHERE campo1=? AND campo2=?),?);

$arrParam2 = array($value1,$value2,date('Y-m-d H:i:s')); $result2 = $pDB->genQuery($query2,$arrParam2); if($result2 == FALSE){ $pDB->rollBack(); $errMsg = $pDB->errMsg; return FALSE;

} else{ $pDB->commit(); return TRUE; } } }

Observemos que el objeto $pDB fue pasado por referencia a la funcin, lo cual es necesario para que la transaccin tenga el comportamiento deseado.
NOTA: Ten en cuenta que existen motores de bases de datos que no soportan transacciones como es el caso del motor MyISAM de mysql, en estos casos se debe asegurar que la tabla que queremos que funcione con transacciones tenga un motor compatible con transacciones como InnoDB o BDB.

2.3 Clase paloSantoACL.class.php Esta clase se encarga de administrar los controles de acceso para los diferentes tipos de usuarios. El framework Elastix la incluye automticamente.

Para instanciar la clase se debe pasar el string DSN para la conexin a la base de datos acl.db o tambin se le puede pasar un objeto que sea una instancia de la clase paloDB que se le haya pasado el DSN para acl.db. La variable $arrConf['elastix_dsn']['acl'] contiene ya el DSN para acl.db, esta variable es creada por el framework. Por lo tanto si queremos instanciar a esta clase dentro de nuestro mdulo haramos lo siguiente:
global $arrConf; $pACL = new paloACL($arrConf['elastix_dsn']['acl']);

Esta clase es algo delicada y podra llegar a comprometer el sistema si es mal usada. Es recomendable que se use solamente las funciones descritas a continuacin y dejar a los mdulos de Elastix por default que se encarguen de las dems tareas de administracin de usuarios. function getUserExtension($username)

Procedimiento para obtener la extensin de un usuario mediante su username. Como ya es de imaginarse, el parmetro $username es el nombre del usuario al cual deseamos obtener su extensin asociada.

Ejemplo: Supongamos que queremos obtener la extensin asociada al usuario logoneado.


//El usuario logoneado se almacena en la $_SESSION[elastix_user] $username = $_SESSION[elastix_user]; $extension = $pACL->getUserExtension($username); variable de sesin

function isUserAdministratorGroup($username)

Procedimiento para saber si un usuario pertenece al grupo administrador. As mismo el parmetro $username es el nombre del usuario al cual deseamos saber si pertenece o no al grupo administrador. Ejemplo:

Si deseamos que nuestro mdulo haga ciertas tareas si el usuario logoneado es del grupo administrador y otras si no, podramos hacer lo siguiente:
$username = $_SESSION[elastix_user]; if($pACL->isUserAdministratorGroup($username)){ //Do some task for administrators } else{ //Do some task for non administrators }

2.4 Clase paloSantoConfig.class.php Esta clase es muy til sobre todo para parsear archivos de configuracin, permitindonos leer o escribir sobre los mismos. Esta clase si es necesario incluirla en nuestro mdulo en caso de requerir de ella.
include_once libs/paloSantoConfig.class.php;

Esta clase tiene el siguiente constructor: function paloConfig($directorio, $archivo, $separador="", $separador_regexp="", $usuario_proceso=NULL)

Donde $directorio es la ruta donde se encuentra el archivo, $archivo es el archivo a parsear, $separador es el string que separa la palabra clave con su valor, $separador_regexp es una expresin regular para interpretarla como separador, $usuario_proceso es el usuario que inicia el proceso. Como se puede observar solo $directorio y $archivo son parmetros requeridos, el resto son opcionales y tienen valores por omisin. Supongamos tenemos el archivo de configuracin /etc/miModulo.conf el cual contiene lo siguiente:
user = usuario password = 12345 email = usuario@dominio.com privileges = all

Ahora vamos a instanciar a la clase paloConfig para parsear este archivo.


$pConfig = new paloConfig(/etc,miModulo.conf, = ,\s*=\s*);

De esta forma iremos a parsear el archivo /etc/miModulo.conf el cual tiene como separador el signo = y puede o no estar acompaado de espacios en blanco a los lados. Ahora detallaremos las principales funciones de la clase paloConfig. function leer_configuracion($bComentarios=true)

Este procedimiento inicia la lectura del archivo almacenndola en un arreglo asociativo que se devuelve como respuesta. Si el parmetro $bComentarios es FALSE entonces slo se encontrar en el arreglo los valores que no son comentarios, y el arreglo de vuelta tendr como ndices las palabras claves del archivo, pero si es TRUE entonces en el arreglo devuelto se encontrar tanto comentarios como valores de configuracin, y los ndices de ste sern numricos. function escribir_configuracion($arr_reemplazos, $overwrite=FALSE)

Este procedimiento sirve para escribir en el archivo de configuracin. El parmetro $arr_reemplazos es un arreglo que contiene los cambios a realizar, donde el ndice del arreglo representa la palabra clave a modificar en el archivo, si en el archivo se encuentra la palabra clave entonces la modifica y si no la encuentra la agrega. Si el parmetro $overwrite es FALSE entonces se harn los cambios contenidos en $arr_reemplazos pero se mantendr intacto el resto del archivo, pero si es TRUE entonces el archivo ser sobre escrito por $arr_reemplazos function privado_get_valor($lista, $clave)

Procedimiento que devuelve el valor de una palabra clave del archivo. El parmetro $lista es el arreglo que contiene el archivo de configuracin. El parmetro $clave es la palabra clave a buscar en el archivo.

Ejemplo: Supongamos que tenemos el archivo /etc/miModulo.conf con la misma informacin que ya se describi ms arriba, y queremos hacer lo siguiente: si password es igual a 12345 entonces la cambiamos a new12345.


include_once libs/paloSantoConfig.class.php; $pConfig = new paloConfig(/etc,miModulo.conf, = ,\s*=\s*); $content = $pConfig->leer_configuracion(FALSE); $password = $pConfig->privado_get_valor($content,password); if($password == 12345){ $arrReplaces = array(password => new12345); $pConfig->escribir_configuracion($arrReplaces); }

2.5 Clase paloSantoForm.class.php Esta clase nos sirve para manejar de una manera sencilla los mdulos tipo formulario. Es necesaria incluirla en nuestro mdulo en caso de desear usarla. El constructor de esta clase tiene la siguiente forma: function paloForm(&$smarty, $arrFormElements)

Donde $smarty es una instancia de smarty, (la cual es pasada a la funcin _moduleContent de nuestro mdulo) y $arrFormElements es un arreglo de arreglos que contiene los elementos del formulario. En el arreglo principal, los ndices representan el id del elemento y en el arreglo secundario debe siempre existir un ndice llamado INPUT_TYPE el cual indica el tipo del elemento que se quiere. El valor de INPUT_TYPE puede ser uno de los siguientes: TEXTAREA, TEXT, CHECKBOX, PASSWORD, HIDDEN, FILE, RADIO, SELECT o DATE. Donde cada una de estas palabras representa el elemento que se desea. A continuacin se mostrarn ejemplos para cada uno de estos de tipos de elementos. Al final de estos ejemplos se explicar sobre los dems elementos del arreglo.

TEXTAREA Ejemplo: Se desea un textarea cuyo label sea descripcin y que tenga 6 columnas y 4 filas.
$arrFormElements = array( "description" => array( "LABEL" "REQUIRED" "INPUT_TYPE" "INPUT_EXTRA_PARAM" "VALIDATION_TYPE"

=> => => => =>

_tr("Description"), "yes", "TEXTAREA", array("style" => width:400px"), "text",


"VALIDATION_EXTRA_PARAM" "ROWS" "COLS" ), ); => "", => "4", => "6"

TEXT Ejemplo: Se desea un input para ingresar el nombre de un cliente.


$arrFormElements = array( "name" => array( "LABEL" "REQUIRED" "INPUT_TYPE" "INPUT_EXTRA_PARAM" "VALIDATION_TYPE" "VALIDATION_EXTRA_PARAM" ), );

=> => => => => =>

_tr("Name"), "yes", "TEXT", array("style" => width:200px"), "text", ""

CHECKBOX Ejemplo: Se desea un checkbox que diga Enable.


$arrFormElements = array( "enable" => array( "LABEL" "REQUIRED" "INPUT_TYPE" "INPUT_EXTRA_PARAM" "VALIDATION_TYPE" "VALIDATION_EXTRA_PARAM" ), );

=> => => => => =>

_tr("Enable"), "yes", "CHECKBOX", " ", "text", ""

NOTA: Al crear elementos de este tipo, el framework automticamente crea dos elementos, uno es el checkbox propiamente dicho y el otro es un hidden que cuyo valor es on en caso de estar activado el checkbox u off caso contrario. Por lo

tanto si en nuestro mdulo queremos saber si el checkbox fue activado o no, tendramos que hacer lo siguiente:
$enable = getParameter(enable); if($enable == on){ //Do something } else{ //Do something }

PASSWORD Ejemplo: Se desea un campo para que el usuario ingrese una contrasea.
$arrFormElements = array( "password" => array( "LABEL" "REQUIRED" "INPUT_TYPE" "INPUT_EXTRA_PARAM" "VALIDATION_TYPE" "VALIDATION_EXTRA_PARAM" ), );

=> _tr("Password"), => "yes", => "PASSWORD", =>array("style" => width:200px"), => "text", => ""

HIDDEN Ejemplo: Se desea tener un campo oculto para almacenar el id de un usuario.


$arrFormElements = array( "id" => array( "LABEL" "REQUIRED" "INPUT_TYPE" "INPUT_EXTRA_PARAM" "VALIDATION_TYPE" "VALIDATION_EXTRA_PARAM" ), );

=> => => => => =>

" ", "yes", "HIDDEN", " ", "text", ""

FILE

Ejemplo: Se desea un campo para poder pasar la ruta de un archivo.


$arrFormElements = array( "file" => array( "LABEL" "REQUIRED" "INPUT_TYPE" "INPUT_EXTRA_PARAM" "VALIDATION_TYPE" "VALIDATION_EXTRA_PARAM" ), );

=> => => => => =>

_tr("File"), "yes", "FILE", " ", "filename", ""

RADIO Ejemplo: Se desea 2 radio buttons para indicar el gnero de una persona.
$gender = array(m => _tr(Male), f $arrFormElements = array( "gender" => array( "LABEL" => "REQUIRED" => "INPUT_TYPE" => "INPUT_EXTRA_PARAM" => "VALIDATION_TYPE" => "VALIDATION_EXTRA_PARAM" => ), ); => _tr(Female)); _tr("Gender"), "yes", "RADIO", $gender, "text", ""

SELECT Ejemplo: Se desea un combo para seleccionar el mtodo de pago que va a realizar un cliente, siendo las opciones efectivo, tarjeta de crdito, cheque, transferencia bancaria.
$paymentMethod = array(cash => _tr(Cash), credit_card => _tr(Credit Card), check => _tr(Check),bank_transfer => _tr(Bank Transfer)); $arrFormElements = array( "paymentMethod" => array("LABEL" => _tr("Payment Method"), "REQUIRED" => "yes", "INPUT_TYPE" => "SELECT", "INPUT_EXTRA_PARAM" => $paymentMethod, "VALIDATION_TYPE" => "text",


"VALIDATION_EXTRA_PARAM" ), ); => ""

DATE Ejemplo: Se desea un campo para ingresar la fecha en la cual se realiz un pago.
$arrFormElements = array( "paymentDate" => array( "LABEL" "REQUIRED" => "INPUT_TYPE" => "INPUT_EXTRA_PARAM" => "VALIDATION_TYPE" => "VALIDATION_EXTRA_PARAM" => ), );

=> _tr("Payment Date"), "yes", "DATE", "", "ereg", "^[[:digit:]]{1,2}[[:space:]]+[[:alnum:]] {3}[[:space:]]+[[:digit:]]{4}$"

El formato por default de la fecha es el da en dos dgitos, luego espacio seguido del mes en formato de tres letras, luego espacio y el ao en cuatro dgitos. Si se desea cambiar este formato simplemente habra que colocar en INPUT_EXTRA_PARAM el nuevo formato, y si deseamos tambin poder ingresar la hora colocamos TIME => true.

Por ejemplo si queremos que el formato sea yyyy-mm-dd h:m:s


"INPUT_EXTRA_PARAM"=>array(TIME=> true, FORMAT => %Y-%m-%d %H:%M:%S),

Como se pudo observar en los ejemplos anteriores existen ndices que coincidan en todos y otros que simplemente eran propios del tipo de elemento, como por ejemplo el ndice COLS en el TEXTAREA. Ahora explicaremos sobre los ndices comunes u obligatorios. LABEL: El valor de este ndice, como su nombre lo indica, ser la etiqueta descriptiva que se muestra junto al elemento. REQUIRED: El valor de este ndice puede ser yes o no, si es yes entonces este campo es obligatorio para poder guardar el formulario, caso contrario este puede quedar en blanco. INPUT_TYPE: Tipo de elemento, ya descrito previamente.

INPUT_EXTRA_PARAM: Parmetros adicionales al input, pueden ser estilos o atributos extras. Estos deben pasarse como arreglo, caso contrario debe ser un string vaco. VALIDATION_TYPE: Indica el tipo de validacin que se le va a aplicar al valor ingresado por el usuario. Los valores pueden ser los siguientes: text - El usuario puede ingresar cualquier cosa. ereg - Se debe pasar en VALIDATION_EXTRA_PARAM una expresin regular, y se le permitir ingresar al usuario slo un texto que coincida con le expresin regular ingresada. filename - Se valida que lo que se ingrese en ese campo sea el nombre de un archivo. domain - Se valida que lo que se ingrese en ese campo se el nombre de un dominio. filepath - Se valida que lo que se ingrese en ese campo sea una ruta a un archivo. ip - Se valida que lo que se ingrese en ese campo sea una direccin ip. mask - Se valida que lo que se ingrese en ese campo sea una mscara de red. ip/mask - Se valida que lo que se ingrese en ese campo sea una direccin ip seguido de / y la mscara de red en formato decimal. numeric - Se valida que lo que se ingrese en ese campo sea un nmero. float - Se valida que lo que se ingresa en ese campo sea un nmero flotante (decimal con el punto como separador). numeric_array - Se valida que lo que se ingresa en ese campo sea un arreglo cuyos elementos sean nmeros. ereg_array - Se valida que lo que se ingresa en ese campo sea un arreglo con valores que deben coincidir con la expresin regular pasada en VALIDATION_EXTRA_PARAM. email - Se valida que lo que se ingresa en ese campo sea una direccin de correo electrnico.

VALIDATION_EXTRA_PARAM: Se pasa un parmetro adicional en caso de que lo requiera VALIDATION_TYPE, como para el caso de ereg.

A continuacin se describirn las funciones que ofrece esta clase. function fetchForm($templateName, $title, $arrPreFilledValues = array())

Esta funcin genera una cadena que contiene un formulario HTML. Para hacer esto, toma una plantilla de formulario (que es la pasada en el parmetro $templateName) e inserta en ella los elementos de formulario. El parmetro $title es el ttulo que tendr el formulario y el parmetro $arrPreFilledValues es un arreglo que contiene valores por defecto para el formulario, donde el ndice es el id del elemento y el valor es el (valga la redundancia) valor que tendra ese campo por defecto. function validateForm($arrCollectedVars)

Esta funcin devuelve TRUE en caso de que los datos ingresados en el formulario fueron correctos, caso contrario FALSE. El parmetro $arrCollectedVars contiene los valores ingresados en el formulario.

Ejemplo: Supongamos que deseamos un mdulo tipo formulario, el cual tenga los campos: Nombre que es una caja de texto, Apellido que es una caja de texto, Gnero que es un radio button que puede ser masculino o femenino, Email que es una caja de texto y Estado Civil que puede ser Soltero, Viudo, Casado, Divorciado o Unin Libre. Todos estos campos son requeridos. Tambin hay un botn Save que al presionar se validan los datos ingresados, en caso de haber un error se mantiene persistencia en los datos y se indica el error, caso contrario se muestra un mensaje indicando los datos ingresados. File themes/default/form.tpl
<table width="100%" border="0" cellspacing="0" cellpadding="4" align="center"> <tr class="letra12"> <td align="left"> <input class="button" type="submit" name="save" value="{$SAVE}"> </td> <td align="right" nowrap><span class="letra12"><span class="required">*</span> {$REQUIRED_FIELD}</span></td> </tr>


</table> <table class="tabForm" style="font-size: 16px;" width="100%" > <tr class="letra12"> <td align="left" width="130px"><b>{$name.LABEL}: <span class="required">*</span></b></td> <td align="left">{$name.INPUT}</td> </tr> <tr class="letra12"> <td align="left"><b>{$last_name.LABEL}: <span class="required">*</span></b></td> <td align="left">{$last_name.INPUT}</td> </tr> <tr class="letra12"> <td align="left"><b>{$gender.LABEL}: <span class="required">*</span></b></td> <td align="left">{$gender.INPUT}</td> </tr> <tr class="letra12"> <td align="left"><b>{$email.LABEL}: <span class="required">*</span></b></td> <td align="left">{$email.INPUT}</td> </tr> <tr class="letra12"> <td align="left"><b>{$marital_status.LABEL}: <span class="required">*</span></b></td> <td align="left">{$marital_status.INPUT}</td> </tr> </table>

File index.php
<?php include_once "libs/paloSantoForm.class.php"; function _moduleContent(&$smarty, $module_name) { //include module files include_once "modules/$module_name/configs/default.conf.php"; //include file language agree to elastix configuration //if file language not exists, then include language by default (en) $lang=get_language(); $base_dir=dirname($_SERVER['SCRIPT_FILENAME']); $lang_file="modules/$module_name/lang/$lang.lang"; if (file_exists("$base_dir/$lang_file")) include_once "$lang_file"; else include_once "modules/$module_name/lang/en.lang";


//global variables global $arrConf; global $arrConfModule; global $arrLang; global $arrLangModule; $arrConf = array_merge($arrConf,$arrConfModule); $arrLang = array_merge($arrLang,$arrLangModule); //folder path for custom templates $templates_dir=(isset($arrConf['templates_dir']))? $arrConf['templates_dir']:'themes'; $local_templates_dir="$base_dir/modules/$module_name/".$templates_dir.'/'. $arrConf['theme']; //conexion resource //$pDB = new paloDB($arrConf['dsn_conn_database']); $pDB = ""; //In this case we do not use a database //actions $action = getAction(); $content = ""; switch($action){ case "save": $content = saveTestModule($smarty, $module_name, $local_templates_dir); break; default: // view_form $content = viewFormTestModule($smarty, $module_name, $local_templates_dir); break; } return $content; } function viewFormTestModule($smarty, $module_name, $local_templates_dir) { $arrFormTestModule = createFieldForm(); $oForm = new paloForm($smarty,$arrFormTestModule); //begin, Form data persistence to errors and other events. $_DATA = $_POST; $smarty->assign("SAVE", _tr("Save")); $smarty->assign("REQUIRED_FIELD", _tr("Required field")); $smarty->assign("icon", "images/list.png"); $htmlForm = $oForm->fetchForm("$local_templates_dir/form.tpl",_tr("Test


Module"), $_DATA); $content = "<form method='POST' style='margin-bottom:0;' action='?menu=$module_name'>".$htmlForm."</form>"; return $content; } function saveTestModule($smarty, $module_name, $local_templates_dir) { $arrFormTestModule = createFieldForm(); $oForm = new paloForm($smarty,$arrFormTestModule); if(!$oForm->validateForm($_POST)){ // Validation basic, not empty and VALIDATION_TYPE $smarty->assign("mb_title", _tr("Validation Error")); $arrErrores = $oForm->arrErroresValidacion; $strErrorMsg = "<b>"._tr("The following fields contain errors").":</b><br/>"; if(is_array($arrErrores) && count($arrErrores) > 0){ foreach($arrErrores as $k=>$v) $strErrorMsg .= "$k, "; } $smarty->assign("mb_message", $strErrorMsg); return viewFormTestModule($smarty, $module_name, $local_templates_dir); } else{ //Here are extra validations $name = getParameter("name"); $last_name = getParameter("last_name"); $gender = getParameter("gender"); $email = getParameter("email"); $marital_status = getParameter("marital_status"); if(!in_array($gender,array("male","female"))){ $smarty->assign("mb_title", _tr("Validation Error")); $smarty->assign("mb_message", _tr("The gender can only be \"male\" or \"female\"")); return viewFormTestModule($smarty, $module_name, $local_templates_dir); } elseif(!in_array($marital_status,array("single","widowed","marr ied","divorced","cohabiting"))){ $smarty->assign("mb_title", _tr("Validation Error")); $smarty->assign("mb_message", _tr("The marital status can only be \"single\", \"widowed\", \"married\", \"divorced\" or \"cohabiting\"")); return viewFormTestModule($smarty, $module_name, $local_templates_dir); }


else{ $smarty->assign("mb_title", _tr("Message")); $message = _tr("The following data was entered").":<br />"; $message .= "<b>"._tr("Name").":</b> ".htmlentities($name)."<br /><b>"._tr("Last Name").":</b> ".htmlentities($last_name)."<br /><b>"._tr("Gender").":</b> ".htmlentities($gender)."<br /><b>"._tr("Email").":</b> ".htmlentities($email)."<br /><b>"._tr("Marital Status").":</b> ".htmlentities($marital_status); $smarty->assign("mb_message",$message); } } return viewFormTestModule($smarty, $module_name, $local_templates_dir); } function createFieldForm() { $gender = array("male" => _tr("Male"), "female" => _tr("Female")); $marital_status = array("single" => _tr("Single"), "widowed" => _tr("Widowed"), "married" => _tr("Married"), "divorced" => _tr("Divorced"), "cohabiting" => _tr("Cohabiting")); $arrFields = array( "name" => array("LABEL" "REQUIRED" "INPUT_TYPE" "INPUT_EXTRA_PARAM" "VALIDATION_TYPE" "VALIDATION_EXTRA_PARAM" ), "last_name" => array("LABEL" "REQUIRED" "INPUT_TYPE" "INPUT_EXTRA_PARAM" "VALIDATION_TYPE" "VALIDATION_EXTRA_PARAM" ), "gender" => array("LABEL" "REQUIRED" "INPUT_TYPE" "INPUT_EXTRA_PARAM" "VALIDATION_TYPE" "VALIDATION_EXTRA_PARAM" ), "email" => array("LABEL" "REQUIRED" "INPUT_TYPE" "INPUT_EXTRA_PARAM"

=> => => => => => => => => => => => => => => => => => => => => =>

_tr("Name"), "yes", "TEXT", "", "text", "" _tr("Last Name"), "yes", "TEXT", "", "text", "" _tr("Gender"), "yes", "RADIO", $gender, "text", "" _tr("Email"), "yes", "TEXT", "",


"VALIDATION_TYPE" "VALIDATION_EXTRA_PARAM" ), "marital_status" => array("LABEL" "REQUIRED" "INPUT_TYPE" "INPUT_EXTRA_PARAM" "VALIDATION_TYPE" "VALIDATION_EXTRA_PARAM" ), => "email", => "" => => => => => _tr("Marital Status"), "yes", "SELECT", $marital_status, "text",

=> ""

);
return $arrFields; } function getAction() { if(getParameter("save")) return "save"; else return "report"; } ?>

Imagen 8.- Vista del mdulo tipo formulario segn el cdigo descrito anteriormente

2.6 Clase paloSantoGrid.class.php Esta clase nos sirve para manejar de una manera sencilla los mdulos tipo grilla. Es necesaria incluirla en nuestro mdulo en caso de desear usarla. El constructor de esta clase tiene la siguiente forma: function paloSantoGrid($smarty)

Donde $smarty es una instancia de smarty (la cual es pasada a la funcin _moduleContent de nuestro mdulo). Esta clase cuenta con las siguientes funciones: function addNew($task="add", $alt="New Row", $asLink=false)

Esta funcin permite agregar un elemento a la grilla cuya funcionalidad es la de aadir un nuevo dato mostrado en la grilla. El parmtro $task ser el atributo name del elemento, el parmetro $alt es el label que se mostrar para el elemento y el parmetro $asLink es TRUE si el elemento ser un link caso contrario ser un input tipo submit. function customAction($task="task", $alt="Custom Action", $img="", $asLink=false)

Esta funcin permite agregar un elemento a la grilla. El parmtro $task ser el atributo name del elemento, el parmetro $alt es el label que se mostrar para el elemento, el parmetro $asLink es TRUE si el elemento ser un link caso contrario ser un input tipo submit y el parmetro $img es la ruta a una imagen que ser el cono representativo del elemento. function deleteList($msg="", $task="remove", $alt="Delete Selected", $asLink=false)

Esta funcin permite agregar un elemento a la grilla cuya funcionalidad es la de eliminar uno o ms datos mostrado en la grilla. El parmetro $msg ser el mensaje de confirmacin que aparecer, el parmtro $task ser el atributo name del elemento, el parmetro $alt es el label que se mostrar para el elemento y el parmetro $asLink es TRUE si el elemento ser un link caso contrario ser un input tipo submit. function addLinkAction($href="action=add", $alt="New Row", $icon=null, $onclick=null)

Esta funcin permite agregar un elemento a la grilla tipo link. El parmetro $href es hacia dnde apunta el link, el parmetro $alt es el label que se mostrar para el elemento, el parmetro $icon es la ruta a una imagen que ser el cono representativo del elemento y el parmetro $onclick es el evento que se va a vincular

al hacer click en dicho link (opcional). function addSubmitAction($task="add", $alt="New Row", $icon=null, $onclick=null)

Esta funcin permite agregar un elemento a la grilla tipo submit. El parmetro $task es el atributo name del elemento, el parmetro $alt es el label que se mostrar para el elemento, el parmetro $icon es la ruta a una imagen que ser el cono representativo del elemento y el parmetro $onclick es el evento que se va a vincular al hacer click en dicho elemento (opcional). function addButtonAction($name="add", $alt="New Row", $icon=null, $onclick="javascript:click()")

Esta funcin permite agregar un elemento a la grilla tipo botn. El parmetro $name es el atributo name del elemento, el parmetro $alt es el label que se mostrar para el elemento, el parmetro $icon es la ruta a una imagen que ser el cono representativo del elemento y el parmetro $onclick es el evento que se va a vincular al hacer click en dicho elemento (opcional). function addInputTextAction($name_input="add", $label="New Row", $value_input="", $task="add", $onkeypress_text=null)

Esta funcin permite agregar un elemento a la grilla tipo input text. El parmetro $name_input es el atributo name del elemento, el parmetro $label es el label que se mostrar para el elemento, el parmetro $value_input es el valor por default del input, el parmetro $task es la accin que se enva al servidor al presionar el botn asociado a la caja de texto y el parmetro $onkeypress_text es el evento que se asociar a la caja de texto cada vez que se presiona una tecla. function addComboAction($name_select="cmb", $label="New Row", $data=array(), $selected=null, $task="add", $onchange_select=null)

Esta funcin permite agregar un elemento a la grilla tipo combo box. El parmetro $name_select es el atributo name del elemento, el parmetro $label es el label que se mostrar para el elemento, el parmetro $data es un arreglo con los datos del combo, el parmetro $selected es el elemento seleccionado por default, el parmetro $task es la accin que se enva al servidor al presionar el botn asociado al combo y el parmetro $onchange_select es el evento que se asociar al

combo cada vez que se cambia el valor del combo. function addHTMLAction($html)

Esta funcin permite agregar un nuevo elemento tipo html a la grilla. El parmetro $html es el cdigo html a aadir. function addFilterControl($msg, &$arrData, $arrFilter = array(), $always_activated=false)

Esta funcin permite agregar un controlador de filtro en la grilla (mensajes en color prpura aparecen cuando el filtro es aplicado). El parmetro $msg es el mensaje que aparecer al aplicar el filtro, el parmetro $arrData es el arreglo con los datos, este nos sirve para saber si el filtro est siendo aplicado o no, el parmetro $arrFilter es un arreglo que nos sirve para asociar dos o ms filtros como uno slo, donde la clave del arreglo es el nombre del elemento del filtro y el valor es el valor default que tendr. Y el parmetro $always_activated ser true si deseamos que siempre se muestre el controlador de filtro, caso contrario se deja en false.

2.7 Clase paloSantoJSON.class.php Esta clase sirve para codificar en formato JSON. Nos puede ser de gran ayuda cuando se haga una peticin AJAX al servidor, y enviarle la respuesta al cliente en formato JSON. Codifica un arreglo de tres elementos, cuyos ndices son error, en esta se almacenan los errores en caso de haberlos, statusResponse que almacena un estado de la respuesta, por default se setea en OK y message que almacena la respuesta deseada. Debemos incluir esta clase en nuestro mdulo en caso de desear usarla. El constructor es el siguiente: function PaloSantoJSON()

Cuenta con las siguientes funciones: function createJSON() Codifica la respuesta en JSON con el formato mencionado anteriormente.

function set_error($error) Setea el valor del ndice error por lo que tenga el parmetro $error.

function set_status($status) Setea el valor del ndice statusResponse por lo que tenga el parmetro $status. function set_message($message) Setea el valor del ndice message por lo que tenga el parmetro $message.

3. AJAX en Elastix
El framework Elastix tambin cuenta con una funcin javascript para realizar peticiones AJAX!!. Esta funcin es la siguiente: function request(url,arrParams, recursive, callback)

El parmetro url es la direccin a la cual se hace la peticin (usualmente ser index.php). El parmetro arrParams es un arreglo que contiene los parmetros que recibir el servidor. El parmetro recursive es un booleano, este ser TRUE si deseamos que la misma peticin AJAX se vuelva a realizar una vez el servidor responda, y si deseamos detenerlo en algn momento, la funcin callback debe retornar TRUE. Finalmente el parmetro callback es una funcin que ser invocada una vez que el servidor responda. Ejemplo: Se desea crear una funcin javascript que realice una peticin AJAX al mdulo testModule. Esta funcin recibe como parmetro un texto el cual se debe pasar al servidor. El servidor debe responder el texto traducido en el lenguaje que este seleccionado en el servidor Elastix en caso de contar con esa traduccin, caso contrario devolver el mismo texto. En el cliente se debe mostrar un alert con el texto devuelto por el servidor. Archivo testModule/themes/default/js/javascript.js


function getTextTranslate(text) { var arrAction = new Array(); arrAction["menu"] = "testModule"; arrAction["action"] = "translate"; arrAction["text"] = text; arrAction["rawmode"] = "yes"; //Remember, this is necessary because in this way the server will only response the content of the module that will be a JSON. request("index.php",arrAction,false, function(arrData,statusResponse,error) { //The variable statusResponse contains the value assigned to statusResponse in the JSON response. //The variable error contains tha value assigned to error in the JSON response. //The variable arrData contains the value assigned to message in the JSON response. alert(arrData); } ); } Archivo testModule/index.php <?php include_once "libs/paloSantoForm.class.php"; include_once "libs/paloSantoJSON.class.php"; function _moduleContent(&$smarty, $module_name) { /* Typical headers of the module like the last example. ..... ..... ..... */ $action = getAction(); $content = ""; switch($action){ case "save": $content = saveTestModule($smarty, $module_name, $local_templates_dir); break;


case "translate": $content = translateText(); break; default: // view_form $content = viewFormTestModule($smarty, $module_name, $local_templates_dir); break; } return $content; } /* Here goes the functions last example .... .... .... */ saveTestModule and viewFormTestModule like the

function translateText() { $jsonObject = new PaloSantoJSON(); $text = getParameter("text"); $translated = _tr($text); $jsonObject->set_message($translated); return $jsonObject->createJSON(); } function getAction() { if(getParameter("save")) return "save"; elseif(getParameter("action") == "translate") return "translate"; else return "report"; }

4. Convertir un mdulo en un Addon


Es comn confundirse y pensar que un mdulo y un addon son la misma cosa, al final de cuentas los dos por lo general terminan siendo un nuevo men de Elastix. Sin embargo un addon es algo mucho ms complejo que un mdulo. Un addon es un paquete de software certificado por PaloSanto Solutions y que se encuentra disponible en formato RPM a travs de un repositorio oficial. Un addon puede contener un mdulo, pero adems tambin puede contener otros

componentes de software, escritos en cualquier lenguaje soportado por Elastix. La instalacin de un addon se realiza de manera sencilla e intuitiva a travs del men Addons desde la interfaz Web de Elastix. Dicho lo anterior es importante aclarar que un mdulo de Elastix s se puede convertir en un addon. Para hacer esto es necesario empaquetar el mdulo en formato RPM e iniciar un proceso de certificacin de software interoperable con Elastix. 4.1 Esqueleto del fuente para el empaquetado Usualmente el fuente contendr un archivo XML y dos carpetas principales. El archivo y carpetas respectivamente son: menu.xml, modules y setup. El archivo menu.xml es un XML que contiene los mdulos que sern integrados a Elastix, indicando la ubicacin, nombre, tipo, permisos,etc.

Ejemplo: Se desea crear un archivo menu.xml, para un mdulo padre llamado Parent Module con id parent_module ubicado debajo del mdulo PBX en la posicin 6. Adems habrn dos mdulos ms el primero ser Test Module con id test_module ubicado dentro de parent_module en la primera posicin. Y el mdulo Link Module con id link_module el cual es un mdulo tipo link para acceder al servidor en el puerto 8080. A estos mdulos slo pueden ingresar por default los usuarios del grupo administrador.
<?xml version="1.0" encoding="UTF-8"?> <module> <menulist> <menuitem menuid="parent_module" desc="Parent Module" parent="pbxconfig" module="no" link="" order="6"> <permissions> <group id="1" name="administrator" desc="total access"></group> </permissions> </menuitem> <menuitem menuid="test_module" desc="Test Module" parent="parent_module" module="yes" link="" order="61"> <permissions> <group id="1" name="administrator" desc="total access"></group> </permissions> </menuitem> <menuitem menuid="link_module" desc="Link Module"


parent="parent_module" module="no" link="http://{NAME_SERVER}:8080" order="62"> <permissions> <group id="1" name="administrator" desc="total access"></group> </permissions> </menuitem> </menulist> </module>

Como se puede observar, dentro de la etiqueta menulist van todos los mdulos y cada mdulo se describe mediante la etiqueta menuitem donde el atributo menuid es el id del mdulo, el atributo desc es la etiqueta que se mostrar en la interfaz web, el atributo parent es el id del mdulo que lo contendr, el atributo module puede ser yes si es un mdulo propiamente dicho o no si es un mdulo padre o si es un mdulo tipo link, el atributo link es el link al cual apuntar el mdulo y el mdulo order es el orden que ocupar el mdulo. En la etiqueta permissions se detallan los grupos de usuarios que tendrn acceso por default al mdulo. Ahora lo nico que hay que hacer es usar el script elastix-menumerge pasndole el archivo XML para que quede realizada la integracin con Elastix. As mismo si deseamos remover algn men, se ejecuta el script elastix-menuremove pasndole el id del mismo. Esto se lo debe realizar en el archivo spec. La carpeta modules contiene todos los mdulos incluidos en el addon. La carpeta setup contiene archivos de configuracin o scripts necesarios para el correcto funcionamiento de algn mdulo. Adems, en caso de usar alguna base de datos local contar con una carpeta llamada db, dentro de esta carpeta encontraremos un archivo llamado db.info y tres carpetas: install, update y delete.

El archivo db.info contiene informacin necesaria acerca de la base de datos. Tiene una cabecera indicando el nombre de la base, luego la palabra clave ignore_backup que ser igual a yes en caso de que no se desee hacer un backup de una base existente con el mismo nombre, caso contrario ser no. Tambin tiene la palabra clave engine que indica el motor que usar la base (en Elastix se usa sqlite3 o mysql), luego la palabra clave path que indica la ruta en donde se encuentra la base (para sqlite3 es /var/www/db y para mysql es /var/lib/mysql) y finalmente la palabra clave deletable que ser yes si se desea poder eliminar la base cuando se desinstala el paquete, caso contrario ser no (el hecho de tener

este campo en yes no significa que la base se eliminar automticamente al desinstalar el paquete, simplemente abre esa posibilidad y lo que se deber hacer es colocar un script de eliminacin de la base en la carpeta delete). Ejemplo: Construir un archivo db.info para un addon que tendr que una base de datos sqlite3 llamada myDBSqlite la cual se debe hacer un backup en caso de existir y no debe poder ser eliminable, y una base de datos mysql llamada myDBMysql con las mismas caracersticas.
[myDBSqlite] ignore_backup = no engine = sqlite3 path = /var/www/db deletable = no [myDBMysql] ignore_backup = no engine = mysql path = /var/lib/mysql deletable = no

Dentro de la carpeta install habr una carpeta para cada base de datos con el mismo nombre de la base. Dentro de esta carpeta habr scripts sql que slo se ejecutarn en la instalacin del paquete (y se aplicarn sobre la base de datos correspondiente al nombre de la carpeta). Estos scripts tendrn los nombres 1_schema.sql, 2_schema.sql, 3_schema.sql, etc (usualmente slo se necesitar de uno), el nmero de prefijo es importante porque indica el orden de ejecucin. Para bases de datos sqlite3 simplemente se crean tablas y se aaden registros por default (de ser necesarios) pero para bases mysql tambin es necesario la creacin de la base (CREATE DATABASE dbname;) seguido de un USE dbname; para de ah si proseguir con la creacin de las tablas y dems. En la carpeta update as mismo habr una carpeta para cada base de datos con el mismo nombre de la base. Dentro de cada una de estas carpetas habr otra carpeta llamada version_sql que contendrn los scripts sql de actualizacin. El nombre de estos scripts es sumamente importante, deben tener la siguiente estructura: #number_#lastVersion_#newVersion.sql Donde:

#number es el orden de ejecucin del script. #lastVersion es la ltima versin existente. #newVersion es la nueva versin a lanzar, este script slo se ejecutar para versiones menores a #newVersion. Ejemplo: Cul ser el nombre de scripts sql de actualizacin para: 1. Un script de actualizacin que debe ser el primero y en cuyo momento la ltima versin lanzada fue 2.2.0-2 y slo se debe ejecutar para versiones menores a 2.2.0-3. Otro script de actualizacin que es el segundo en ejecutarse y en cuyo momento la ltima versin lanzada fue la 2.2.0-6 y slo se debe ejecutar para versiones menores a 2.2.0-7

2.

Para el primer script sera: 1_2.2.0-2_2.2.0-3.sql Para el segundo script sera: 2_2.2.0-6_2.2.0-7.sql Ntese que siempre ser #lastVersion < #newVersion, adems el orden de ejecucin de los scripts va de la mano con las versiones, es decir a mayor orden mayores versiones. En una instalacin adems de ejecutarse los scripts de la carpeta install, se ejecutarn todos los scripts de la carpeta update. La carpeta delete tambin contendr carpetas con el mismo nombre de la base de datos, las cuales contendrn scripts sql para la desinstalacin de la base con el nombre 1_dbname.sql, 2_dbname.sql, 3_dbname.sql, etc.

Es recomendable no eliminar las bases en la desinstalacin del paquete

El script que se encarga de leer y ejecutar estos archivos es el elastix-dbprocess que debe ser invocado en el archivo spec.

4.2 Archivo spec Una vez armado el fuente ahora es cuestin de crear el archivo spec, para terminar con el proceso de construccin del RPM o empaquetado. A continuacin se mostrar un pequeo ejemplo de un archivo spec sin entrar en mayores detalles, ya que se asume que el desarrollador tiene claros conocimientos en cuanto a la construccin de paquetes RPM.
%define modname example Summary: Elastix Module Example Name: elastix-%{modname} Version: 2.2.0 Release: 1 License: GPL Group: Applications/System Source0: %{modname}_%{version}-%{release}.tgz BuildRoot: %{_tmppath}/%{name}-%{version}-root BuildArch: noarch Prereq: elastix-framework >= 2.2.0-25 %description Elastix Module Example %prep %setup -n %{modname} %install rm -rf $RPM_BUILD_ROOT # Files provided by all Elastix modules mkdir -p $RPM_BUILD_ROOT/var/www/html/ mv modules/ $RPM_BUILD_ROOT/var/www/html/ # The following folder should contain all the data that is required by the installer, # that cannot be handled by RPM. mkdir -p $RPM_BUILD_ROOT/usr/share/elastix/module_installer/%{name}%{version}-%{release}/ mv setup/ $RPM_BUILD_ROOT/usr/share/elastix/module_installer/%{name}%{version}-%{release}/ mv menu.xml $RPM_BUILD_ROOT/usr/share/elastix/module_installer/%{name}%{version}-%{release}/

%pre mkdir -p /usr/share/elastix/module_installer/%{name}-%{version}-%{release}/


touch /usr/share/elastix/module_installer/%{name}-%{version}%{release}/preversion_%{modname}.info if [ $1 -eq 2 ]; then rpm -q --queryformat='%{VERSION}-%{RELEASE}' %{name} > /usr/share/elastix/module_installer/%{name}-%{version}%{release}/preversion_%{modname}.info fi %post pathModule="/usr/share/elastix/module_installer/%{name}-%{version}%{release}" # Run installer script to fix up ACLs and add module to Elastix menus. elastix-menumerge $pathModule/menu.xml pathSQLiteDB="/var/www/db" mkdir -p $pathSQLiteDB preversion=`cat $pathModule/preversion_%{modname}.info` if [ $1 -eq 1 ]; then #install # The installer database elastix-dbprocess "install" "$pathModule/setup/db" elif [ $1 -eq 2 ]; then #update elastix-dbprocess "update" "$pathModule/setup/db" "$preversion" fi %clean rm -rf $RPM_BUILD_ROOT %preun if [ $1 -eq 0 ] ; then # Validation for desinstall this rpm echo "Delete example menus" elastix-menuremove "%{modname}" # Here you should call to elastix-dbprocess for deleting, the same way that it was for install, just that instead of word install goes word delete. But this is not often used due to the databases usually are not deleted fi %files %defattr(-, asterisk, asterisk) %{_localstatedir}/www/html/* /usr/share/elastix/module_installer/* %changelog * Mon Jan 30 2012 Alberto Santos <asantos@palosanto.com> 2.2.0-1 Initial version.

4.3 Finalizacin del proceso de certificacin. Una vez elaborado el RPM, se procede a firmar el contrato y enviar el empaquetado a PaloSanto Solutions a la direccin de correo certification@palosanto.com con copia a asantos@palosanto.com, junto con un manual de usuario, para proceder con la revisin del mismo. Una vez este sea aprobado pasar a formar parte de los repositorios de Elastix y se convertir en un Addon de Elastix.

Si tienes alguna duda respecto al proceso de certificacin o cualquier aspecto puntual del framework Elastix puedes enviar un correo a cualquiera de las direcciones mencionadas o visitar nuestra pgina web http://addons.elastix.org