Anonymous avatar Anonymous committed d5ea9fd Merge

Merged in robregonm/cruge (pull request #4)

Agregado soporte para múltiples idiomas y PSR-0

Comments (0)

Files changed (43)

components/CrugeAccessControlFilter.php

-<?php 
-	/*	CrugeAccessControlFilter
-	
-		Concede acceso en base a verificar si el nombre del controller y el action a ser usado
-		estan definidos en las operaciones creadas por el administrador de RBAC.
-		
-		como funciona:
-		
-			si este filtro es usado y un usuario quiere acceder al action: "site/contact"
-			entonces:
-			
-				1. sistema arma un nombre de OPERACION asi: "action_site_contact"
-				
-				2. concede paso tras verificar si el usuario que autenticado tiene acceso con:
-					Yii::app()->user->checkAccess("action_site_contact")
-			
-		como se usa:
-		
-			se declara el uso de esta clase en el metodo filters() de la clase del usuario,
-			asi:
-				array('CrugeAccessControlFilter'),
-		
-			en la clase del usuario asi:
-		
-				public function filters()
-				{
-					return array(
-						//'accessControl', // perform access control for CRUD operations
-						array('CrugeAccessControlFilter'),
-					);
-				}
-				
-				
-		la excepcion reportara error 401 indicando 'Access Denied'. Estandar http.
-		
- 	@author: Christian Salazar H. <christiansalazarh@gmail.com> @bluyell
-	@license protected/modules/cruge/LICENCE
+<?php
+/*	CrugeAccessControlFilter
+
+    Concede acceso en base a verificar si el nombre del controller y el action a ser usado
+    estan definidos en las operaciones creadas por el administrador de RBAC.
+
+    como funciona:
+
+        si este filtro es usado y un usuario quiere acceder al action: "site/contact"
+        entonces:
+
+            1. sistema arma un nombre de OPERACION asi: "action_site_contact"
+
+            2. concede paso tras verificar si el usuario que autenticado tiene acceso con:
+                Yii::app()->user->checkAccess("action_site_contact")
+
+    como se usa:
+
+        se declara el uso de esta clase en el metodo filters() de la clase del usuario,
+        asi:
+            array('CrugeAccessControlFilter'),
+
+        en la clase del usuario asi:
+
+            public function filters()
+            {
+                return array(
+                    //'accessControl', // perform access control for CRUD operations
+                    array('CrugeAccessControlFilter'),
+                );
+            }
+
+
+    la excepcion reportara error 401 indicando 'Access Denied'. Estandar http.
+
+ @author: Christian Salazar H. <christiansalazarh@gmail.com> @bluyell
+@license protected/modules/cruge/LICENCE
 */
-class CrugeAccessControlFilter extends CFilter {
-
-		public function init(){
-			parent::init();
-		}
-	
-		protected function preFilter($filterChain)
-		{
-			
-			
-			$controllerItemName = "controller_".Yii::app()->getController()->id;
-			
-			$currentActionName = Yii::app()->getController()->action->id;
-			$actionItemName = "action_".Yii::app()->getController()->id."_".$currentActionName;
-			
-			// se dara acceso siempre a site/error ya que por defecto
-			// es el punto de muestra de errores de Yii. esto es para facilitar el uso de cruge
-			if((Yii::app()->getController()->id=='site') && (Yii::app()->getController()->action->id=='error'))
-				return true;
-				
-			
-			// tiene permiso para la controladora indicada ?
-			//
-			// tiene permiso para la accion indicada ?
-			//
-			//if(Yii::app()->user->checkAccess($controllerItemName))
-			//{
-				// si tiene permiso.
-				
-				// tiene permiso para la accion indicada ?
-				//
-				if(Yii::app()->user->checkAccess($actionItemName))
-				{
-					// si tiene autorizacion para la accion indicada
-					
-				}
-				else{
-					// no esta autorizado
-					//
-					$this->reportError($actionItemName);
-				}
-			/*
-			}
-			else{
-				// no esta autorizado a la controladora en general.
-				//
-				$this->reportError($controllerItemName);
-			}
-			*/
-			
-			$filterChain->run();
-		}
-		
-		private function reportError($itemName){
-			if(CrugeUtil::config()->allowUserAlways == false)
-				throw new CrugeException($itemName,401);
-		}
-
-		protected function postFilter($filterChain)
-		{
-		}
-	}
+class CrugeAccessControlFilter extends CFilter
+{
+
+    public function init()
+    {
+        parent::init();
+    }
+
+    protected function preFilter($filterChain)
+    {
+
+
+        $controllerItemName = "controller_" . Yii::app()->getController()->id;
+
+        $currentActionName = Yii::app()->getController()->action->id;
+        $actionItemName = "action_" . Yii::app()->getController()->id . "_" . $currentActionName;
+
+        // se dara acceso siempre a site/error ya que por defecto
+        // es el punto de muestra de errores de Yii. esto es para facilitar el uso de cruge
+        if ((Yii::app()->getController()->id == 'site') && (Yii::app()->getController()->action->id == 'error')) {
+            return true;
+        }
+
+
+        // tiene permiso para la controladora indicada ?
+        //
+        // tiene permiso para la accion indicada ?
+        //
+        //if(Yii::app()->user->checkAccess($controllerItemName))
+        //{
+        // si tiene permiso.
+
+        // tiene permiso para la accion indicada ?
+        //
+        if (Yii::app()->user->checkAccess($actionItemName)) {
+            // si tiene autorizacion para la accion indicada
+
+        } else {
+            // no esta autorizado
+            //
+            $this->reportError($actionItemName);
+        }
+        /*
+        }
+        else{
+            // no esta autorizado a la controladora en general.
+            //
+            $this->reportError($controllerItemName);
+        }
+        */
+
+        $filterChain->run();
+    }
+
+    private function reportError($itemName)
+    {
+        if (CrugeUtil::config()->allowUserAlways == false) {
+            throw new CrugeException($itemName, 401);
+        }
+    }
+
+    protected function postFilter($filterChain)
+    {
+    }
+}
+
 ?>

components/CrugeAuthManager.php

 <?php
 /**
-	CrugeAuthManager
+CrugeAuthManager
 
-	este modulo requiere instalacion en config/main.php :
-		'components'=>array(
-			'authManager' => array(
-				'class' => 'application.modules.cruge.components.CrugeAuthManager',
-			),
-		),
-	
-	para acceder a el:
-		Yii::app()->authManager
-	o
-		Yii::app()->user->rbac
+este modulo requiere instalacion en config/main.php :
+'components'=>array(
+'authManager' => array(
+'class' => 'application.modules.cruge.components.CrugeAuthManager',
+),
+),
 
-	para consultar si el usuario actual tiene permiso para alguna operacion:
-		if(Yii::app()->user->checkAccess('createPost')){...}
+para acceder a el:
+Yii::app()->authManager
+o
+Yii::app()->user->rbac
 
+para consultar si el usuario actual tiene permiso para alguna operacion:
+if(Yii::app()->user->checkAccess('createPost')){...}
 
-	FUNCIONES EXTENDIDAS
-	====================
-	
-		permiten listar items. no estan declaradas como parte de la interfaz original de Yii
-	
-		Yii::app()->user->rbac->roles;
-		Yii::app()->user->rbac->tasks;
-		Yii::app()->user->rbac->operations;
 
-	SINTAXIS PARA LA DESCRIPCION DEL AUTHITEM / MENU ITEMS 
-	======================================================
+FUNCIONES EXTENDIDAS
+====================
 
-		Para obtener menu items en base a RBAC se usa el metodo:
+permiten listar items. no estan declaradas como parte de la interfaz original de Yii
 
-		Yii::app()->user->rbac->getMenu([$args]);
+Yii::app()->user->rbac->roles;
+Yii::app()->user->rbac->tasks;
+Yii::app()->user->rbac->operations;
 
-		Para que los menu items funcionen deben contener una SINTAXIS en
-		la DESCRIPCION como describo a continuacion.
-		
-		[$args] son argumentos en forma de array para adosarle a las URL
-		de los menu items aqui obtenidos, leer mas abajo en este mismo apartado.
+SINTAXIS PARA LA DESCRIPCION DEL AUTHITEM / MENU ITEMS
+======================================================
 
-		SINTAXIS
-		
-		La descripcion del CAuthItem puede venir en dos formas:
-		
-		A) Estandar.   	"Mi Descripcion"
+Para obtener menu items en base a RBAC se usa el metodo:
 
-		B) Extendia.	":2 Menu Usuario {menu_principal} {action_site_index}"
+Yii::app()->user->rbac->getMenu([$args]);
 
-		El caso (A) no tiene mayor explicación, la descripcion se usa como
-		un texto informativo y nada mas.
+Para que los menu items funcionen deben contener una SINTAXIS en
+la DESCRIPCION como describo a continuacion.
 
-		El caso (B) representa la "Sintaxis de la Descripcion"
+[$args] son argumentos en forma de array para adosarle a las URL
+de los menu items aqui obtenidos, leer mas abajo en este mismo apartado.
 
-		SU FORMA ES:
+SINTAXIS
 
-		[:]+[nn]+[Texto]+[{auth_item_padre}{acion_auth_item_name}]
+La descripcion del CAuthItem puede venir en dos formas:
 
-		en donde:
+A) Estandar.   	"Mi Descripcion"
 
-		":" 		indica que el CAuthItem es un MENU o un SUB MENU
+B) Extendia.	":2 Menu Usuario {menu_principal} {action_site_index}"
 
-		"nn"		indica la posicion ordinal, si es un MENU o u SUB MENU
+El caso (A) no tiene mayor explicación, la descripcion se usa como
+un texto informativo y nada mas.
 
-		"Texto"		indica el texto del menu o submenu
+El caso (B) representa la "Sintaxis de la Descripcion"
 
-		{parent}	el nombre del CAuthItem superior (al existir este argumento
-					se considera al CAuthItem como un SUBMENU de "parent"
+SU FORMA ES:
 
-		{action}	el nombre del CAuthItem que servirá como ACTION para la
-					url del sub menu item.
+[:]+[nn]+[Texto]+[{auth_item_padre}{acion_auth_item_name}]
 
-		FORMAS POSIBLES:
+en donde:
 
-		":texto"	
-		menu de primer nivel con etiqueta "Texto"
+":" 		indica que el CAuthItem es un MENU o un SUB MENU
 
-		":N texto"	
-		menu de primer nivel con etiqueta "Texto" en posicion N
-		
-		":texto {parent} {action}"
-		menu de segundo nivel con etiqueta "Texto" relativo a "parent" quien
-		debe ser otro CAuthItem con sintaxis de descripcion, pero de tipo Menu.
-		siendo action el nombre del CAuthItem que va a lanzar la URL
-		
-		":texto {parent}" este caso no tiene sentido. (Un submenu sin URL ?!)
+"nn"		indica la posicion ordinal, si es un MENU o u SUB MENU
 
+"Texto"		indica el texto del menu o submenu
 
-		MANEJO DE LA URL / MAPPINGS
+{parent}	el nombre del CAuthItem superior (al existir este argumento
+se considera al CAuthItem como un SUBMENU de "parent"
 
-		La url se toma del nombre de un CAuthItem que ha sido indicada
-		como la seleccionada para el submenu item usando la sintaxis aqui
-		indicada.
+{action}	el nombre del CAuthItem que servirá como ACTION para la
+url del sub menu item.
 
-		ejemplo:
+FORMAS POSIBLES:
 
-			action item:			usada como:
+":texto"
+menu de primer nivel con etiqueta "Texto"
 
-			action_site_index		array('site/index')
+":N texto"
+menu de primer nivel con etiqueta "Texto" en posicion N
 
-			action_ui_editprofile	array('/cruge/ui/editprofile')
+":texto {parent} {action}"
+menu de segundo nivel con etiqueta "Texto" relativo a "parent" quien
+debe ser otro CAuthItem con sintaxis de descripcion, pero de tipo Menu.
+siendo action el nombre del CAuthItem que va a lanzar la URL
 
-		nota acerca de donde salio: "/cruge/ui/":
+":texto {parent}" este caso no tiene sentido. (Un submenu sin URL ?!)
 
-		esta clase tiene un atributo llamado "mappings" el cual
-		va a convertir patrones de URL, 
 
-		por ejemplo:
+MANEJO DE LA URL / MAPPINGS
 
-			"action_ui_XXX" sera convertida a "action_cruge_ui_XXX"
+La url se toma del nombre de un CAuthItem que ha sido indicada
+como la seleccionada para el submenu item usando la sintaxis aqui
+indicada.
 
+ejemplo:
 
-			URL: CASO MODULOS
+action item:			usada como:
 
-			El uso de mapping tambien ayuda para cuando los actions
-			declarados como "actions de menu item" apuntan a aquellos 
-			que estan definidos en un modulo de usuario,
+action_site_index		array('site/index')
 
-			por ejemplo, tienes un action que realmente esta definido
-			dentro de un modulo llamado "tumodulox"
+action_ui_editprofile	array('/cruge/ui/editprofile')
 
-				action_default_index
+nota acerca de donde salio: "/cruge/ui/":
 
-			si no usas un mapping, este action se generara relativo a
-			la aplicacion sin modulo, es decir:
+esta clase tiene un atributo llamado "mappings" el cual
+va a convertir patrones de URL,
 
-				array('default/index')  Y DARA UN ERROR, porque
-				asume que lo que "para tu modulo" era el controller default
-				se le pedira a la aplicacion base y fallará porque no existe.
+por ejemplo:
 
-			por tanto, se resolveria en config main pasandole a esta clase
-			un nuevo mapping:
+"action_ui_XXX" sera convertida a "action_cruge_ui_XXX"
 
-				'mapping' => array(
-						'action_ui_'=>'action_cruge_ui_',
-						'action_default_' => 'action_tumodulox_default_',
-					),
 
-			ahora, al invocar el menu se producira correctamente la URL
-			apuntando a tu modulo:
+URL: CASO MODULOS
 
-				array('/tumodulox/default/index'),
-
-		
-		ARGUMENTOS DE LA URL ($args)
-
-		La url recibe argumentos cuando se invoca a Yii::app()->rbac->getMenu
-
-		Por ejemplo, queremos que todos los menu items tengas adosado un
-		parametro (o mas):
-
-		Yii::app()->user->rbac->getMenu(array('idempresa'=>123));
-
-		esto generara un array de menu items (para CMenu o MbMenu o EMenu etc)
-		cuya url será finalmente asi:
-
-		array('label'=>'cosa', 'url'=>'', 'items'=>
-				array('cosa menor','url'=>array('site/index','idempresa'=>123))
-				..
-				..
-		)
-
-
-	EJEMPLO USO DE ESTA CLASE
-	=========================
-	
-		$auth=Yii::app()->authManager;
-		 
-		$auth->createOperation('createPost','create a post');
-		$auth->createOperation('readPost','read a post');
-		$auth->createOperation('updatePost','update a post');
-		$auth->createOperation('deletePost','delete a post');
-		 
-		$bizRule='return Yii::app()->user->id==$params["post"]->authID;';
-		$task=$auth->createTask('updateOwnPost','update a post by author himself',$bizRule);
-		$task->addChild('updatePost');
-		 
-		$role=$auth->createRole('reader');
-		$role->addChild('readPost');
-		 
-		$role=$auth->createRole('author');
-		$role->addChild('reader');
-		$role->addChild('createPost');
-		$role->addChild('updateOwnPost');
-		 
-		$role=$auth->createRole('editor');
-		$role->addChild('reader');
-		$role->addChild('updatePost');
-		 
-		$role=$auth->createRole('admin');
-		$role->addChild('editor');
-		$role->addChild('author');
-		$role->addChild('deletePost');
-
-		// se asignan los roles a los usuarios, aqui el iduser es el nombre, pero puede (y debe)
-		// ser el Yii::app()->user->id (id=que invoca a user->getId())
-		
-		$auth->assign('reader','readerA');
-		$auth->assign('author','authorB');
-		$auth->assign('editor','editorC');
-		$auth->assign('admin','adminD');	
-	
- 	@author: original de Maurizio Domba <mdomba@gmail.com>
-	@author: Christian Salazar H. <christiansalazarh@gmail.com> @bluyell
-	@license protected/modules/cruge/LICENCE
-*/
-class CrugeAuthManager extends CAuthManager implements IAuthManager {
-
-	// este mapping es usado para el caso de obtener una URL en base a
-	// un CAuthItem.getDescription() usando el mecanismo de  sintaxis
-	// descrito mas abajo.
-	//
-	//	resuelve el problema de 'action_ui_editprofile' el cual
-	//	realmente representa al action action_cruge_ui_editprofile
-	//  al usar getTaskUrl se obtendrá: array('/cruge/ui/editprofile')
-	//  en vez de: array('/ui/editprofile')
-	//
-	//	Importante:
-	//	  este es un mapping de patrones, no de indices directos.
-	//
-	public $mapping = array(
-				'action_ui_' => 'action_cruge_ui_',
-			);
-	private $_enumcontrollers;
-	private $_enumactions;
-
-	/**
-	 * @var string the ID of the {@link CDbConnection} application component. Defaults to 'db'.
-	 * The database must have the tables as declared in "framework/web/auth/*.sql".
-	 */
-	public $connectionID='db';
-	/**
-	 * @var CDbConnection the database connection. By default, this is initialized
-	 * automatically as the application component whose ID is indicated as {@link connectionID}.
-	 */
-	public $db;
-
-
-	
-	
-	public function init()
-	{
-		parent::init();
-		$this->getDbConnection();// para inicializar db
-	}
-	
-	/** retorna el nombre de una tabla configurandola para los prefijos definidos en el modulo
-		$table: uno de {'authitem', 'authitemchild', 'authassignment'}
-	*/
-	protected function getTableName($table){
-		return CrugeUtil::getTableName($table);
-	}
-	
-	public function usingSqlite(){
-		return false;
-	}
-	
-	
-	/**
-	 * Performs access check for the specified user.
-	 * @param string $itemName the name of the operation that need access check
-	 * @param mixed $userId the user ID. This should can be either an integer and a string representing
-	 * the unique identifier of a user. See {@link IWebUser::getId}.
-	 * @param array $params name-value pairs that would be passed to biz rules associated
-	 * with the tasks and roles assigned to the user.
-	 * @return boolean whether the operations can be performed by the user.
-	 */
-	public function checkAccess($itemName,$userId,$params=array())
-	{
-		$assignments=$this->getAuthAssignments($userId);
-		return $this->checkAccessRecursive($itemName,$userId,$params,$assignments);
-	}	
-
-	/**
-	 * Performs access check for the specified user.
-	 * This method is internally called by {@link checkAccess}.
-	 * @param string $itemName the name of the operation that need access check
-	 * @param mixed $userId the user ID. This should can be either an integer and a string representing
-	 * the unique identifier of a user. See {@link IWebUser::getId}.
-	 * @param array $params name-value pairs that would be passed to biz rules associated
-	 * with the tasks and roles assigned to the user.
-	 * @param array $assignments the assignments to the specified user
-	 * @return boolean whether the operations can be performed by the user.
-	 * @since 1.1.3
-	 */
-	protected function checkAccessRecursive($itemName,$userId,$params,$assignments)
-	{
-		if(($item=$this->getAuthItem($itemName))===null)
-			return false;
-		Yii::trace('Checking permission "'.$item->getName().'"','system.web.auth.CDbAuthManager');
-		if($this->executeBizRule($item->getBizRule(),$params,$item->getData()))
-		{
-			if(in_array($itemName,$this->defaultRoles))
-				return true;
-			if(isset($assignments[$itemName]))
-			{
-				$assignment=$assignments[$itemName];
-				if($this->executeBizRule($assignment->getBizRule(),$params,$assignment->getData()))
-					return true;
-			}
-			$parents=$this->db->createCommand()
-				->select('parent')
-				->from($this->getTableName('authitemchild'))
-				->where('child=:name', array(':name'=>$itemName))
-				->queryColumn();
-			foreach($parents as $parent)
-			{
-				if($this->checkAccessRecursive($parent,$userId,$params,$assignments))
-					return true;
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * Adds an item as a child of another item.
-	 * @param string $itemName the parent item name
-	 * @param string $childName the child item name
-	 * @throws CException if either parent or child doesn't exist or if a loop has been detected.
-	 */
-	public function addItemChild($itemName,$childName)
-	{
-		if($itemName===$childName)
-			throw new CException(Yii::t('yii','Cannot add "{name}" as a child of itself.',
-					array('{name}'=>$itemName)));
-
-		$rows=$this->db->createCommand()
-			->select()
-			->from($this->getTableName('authitem'))
-			->where('name=:name1 OR name=:name2', array(
-				':name1'=>$itemName,
-				':name2'=>$childName
-			))
-			->queryAll();
-
-		if(count($rows)==2)
-		{
-			if($rows[0]['name']===$itemName)
-			{
-				$parentType=$rows[0]['type'];
-				$childType=$rows[1]['type'];
-			}
-			else
-			{
-				$childType=$rows[0]['type'];
-				$parentType=$rows[1]['type'];
-			}
-			$this->checkItemChildType($parentType,$childType);
-			if($this->detectLoop($itemName,$childName))
-				throw new CrugeException(Yii::t('yii','Cannot add "{child}" as a child of "{name}". A loop has been detected.',
-					array('{child}'=>$childName,'{name}'=>$itemName)));
-
-			$this->db->createCommand()
-				->insert($this->getTableName('authitemchild'), array(
-					'parent'=>$itemName,
-					'child'=>$childName,
-				));
-		}
-		else
-			throw new CrugeException(Yii::t('yii','Either "{parent}" or "{child}" does not exist.',array('{child}'=>$childName,'{parent}'=>$itemName)));
-	}
-
-	/**
-	 * Removes a child from its parent.
-	 * Note, the child item is not deleted. Only the parent-child relationship is removed.
-	 * @param string $itemName the parent item name
-	 * @param string $childName the child item name
-	 * @return boolean whether the removal is successful
-	 */
-	public function removeItemChild($itemName,$childName)
-	{
-		return $this->db->createCommand()
-			->delete($this->getTableName('authitemchild'), 'parent=:parent AND child=:child', array(
-				':parent'=>$itemName,
-				':child'=>$childName
-			)) > 0;
-	}
-
-	/**
-	 * Returns a value indicating whether a child exists within a parent.
-	 * @param string $itemName the parent item name
-	 * @param string $childName the child item name
-	 * @return boolean whether the child exists
-	 */
-	public function hasItemChild($itemName,$childName)
-	{
-		return $this->db->createCommand()
-			->select('parent')
-			->from($this->getTableName('authitemchild'))
-			->where('parent=:parent AND child=:child', array(
-				':parent'=>$itemName,
-				':child'=>$childName))
-			->queryScalar() !== false;
-	}
-
-	/**
-	 * Returns the children of the specified item.
-	 * @param mixed $names the parent item name. This can be either a string or an array.
-	 * The latter represents a list of item names (available since version 1.0.5).
-	 * @return array all child items of the parent
-	 */
-	public function getItemChildren($names)
-	{
-		if(is_string($names))
-			$condition='parent='.$this->db->quoteValue($names);
-		else if(is_array($names) && $names!==array())
-		{
-			foreach($names as &$name)
-				$name=$this->db->quoteValue($name);
-			$condition='parent IN ('.implode(', ',$names).')';
-		}
-
-		$rows=$this->db->createCommand()
-			->select('name, type, description, bizrule, data')
-			->from(array(
-				$this->getTableName('authitem'),
-				$this->getTableName('authitemchild')
-			))
-			->where($condition.' AND name=child')
-			->queryAll();
-
-		$children=array();
-		foreach($rows as $row)
-		{
-			if(($data=@unserialize($row['data']))===false)
-				$data=null;
-			$children[$row['name']]=new CAuthItem($this,$row['name'],$row['type'],$row['description'],$row['bizrule'],$data);
-		}
-		return $children;
-	}
-
-	/**
-	 * Assigns an authorization item to a user.
-	 * @param string $itemName the item name
-	 * @param mixed $userId the user ID (see {@link IWebUser::getId})
-	 * @param string $bizRule the business rule to be executed when {@link checkAccess} is called
-	 * for this particular authorization item.
-	 * @param mixed $data additional data associated with this assignment
-	 * @return CAuthAssignment the authorization assignment information.
-	 * @throws CrugeException if the item does not exist or if the item has already been assigned to the user
-	 */
-	public function assign($itemName,$userId,$bizRule=null,$data=null)
-	{
-		/*
-		if($this->usingSqlite() && $this->getAuthItem($itemName)===null)
-			throw new CrugeException(Yii::t('yii','The item "{name}" does not exist.',array('{name}'=>$itemName)));
-		*/
-		
-		// por christian salazar
-		if($userId == '' || $userId==null)
-			return null;
-
-		$this->db->createCommand()
-			->insert($this->getTableName('authassignment'), array(
-				'itemname'=>$itemName,
-				'userid'=>$userId,
-				'bizrule'=>$bizRule,
-				'data'=>serialize($data)
-			));
-		return new CAuthAssignment($this,$itemName,$userId,$bizRule,$data);
-	}
-
-	/**
-	 * Revokes an authorization assignment from a user.
-	 * @param string $itemName the item name
-	 * @param mixed $userId the user ID (see {@link IWebUser::getId})
-	 * @return boolean whether removal is successful
-	 */
-	public function revoke($itemName,$userId)
-	{
-		return $this->db->createCommand()
-			->delete($this->getTableName('authassignment'), 'itemname=:itemname AND userid=:userid', array(
-				':itemname'=>$itemName,
-				':userid'=>$userId
-			)) > 0;
-	}
-
-	/**
-	 * Returns a value indicating whether the item has been assigned to the user.
-	 * @param string $itemName the item name
-	 * @param mixed $userId the user ID (see {@link IWebUser::getId})
-	 * @return boolean whether the item has been assigned to the user.
-	 */
-	public function isAssigned($itemName,$userId)
-	{
-		return $this->db->createCommand()
-			->select('itemname')
-			->from($this->getTableName('authassignment'))
-			->where('itemname=:itemname AND userid=:userid', array(
-				':itemname'=>$itemName,
-				':userid'=>$userId))
-			->queryScalar() !== false;
-	}
-
-	/**
-	 * Returns the item assignment information.
-	 * @param string $itemName the item name
-	 * @param mixed $userId the user ID (see {@link IWebUser::getId})
-	 * @return CAuthAssignment the item assignment information. Null is returned if
-	 * the item is not assigned to the user.
-	 */
-	public function getAuthAssignment($itemName,$userId)
-	{
-		$row=$this->db->createCommand()
-			->select()
-			->from($this->getTableName('authassignment'))
-			->where('itemname=:itemname AND userid=:userid', array(
-				':itemname'=>$itemName,
-				':userid'=>$userId))
-			->queryRow();
-		if($row!==false)
-		{
-			if(($data=@unserialize($row['data']))===false)
-				$data=null;
-			return new CAuthAssignment($this,$row['itemname'],$row['userid'],$row['bizrule'],$data);
-		}
-		else
-			return null;
-	}
-
-	
-	/** 
-	 * Retorna un array con los userid que tienen el item asignado
-	 * @param string $itemName el item a buscar
-	 * @return array con los $userid
-	 */
-	public function getUsersAssigned($itemName)
-	{
-		$rows=$this->db->createCommand()
-			->select()
-			->from($this->getTableName('authassignment'))
-			->where('itemname=:itemname ', array(
-				':itemname'=>$itemName,
-				))
-			//->group('userid')
-			->queryAll();
-		$users=array();
-		if($rows != null)
-		foreach($rows as $row)
-			if(!in_array($row['userid'],$users))
-				$users[]=$row['userid'];
-		return $users;
-	}
-
-
-	/** 
-	 * Retorna un array con todos los "parents" de un item hallados en authitemchild
-	 *
-	 * este metodo permite ir hacia atras, lo opuesto a getChildrens, permitiendo conocer
-	 * quienes hacen referencia a un authItem
-	 *  
-	 * @param string $itemName el item a buscar
-	 * @return array con los CAuthItems que hacen la referencia al item.
-	 */
-	public function getParents($itemName)
-	{
-		$rows=$this->db->createCommand()
-			->select()
-			->from($this->getTableName('authitemchild'))
-			->where('child=:itemname ', array(
-					':itemname'=>$itemName,
-				))
-			->queryAll();
-		$parents=array();
-		if($rows != null)
-			foreach($rows as $row)
-				$parents[] = $this->getAuthItem($row['parent']);
-		return $parents;
-	}
-
-	
-	/** 
-	 * Retorna el numero de userid's que tienen el item asignado
-	 * @param string $itemName el item a buscar
-	 * @return cantidad de usuarios asignados
-	 */
-	public function getCountUsersAssigned($itemName)
-	{
-		// TODO: optimizar esto con una consulta de agrupacion y cuenta
-		//
-		$ar = $this->getUsersAssigned($itemName);
-		return count($ar);
-	}
-	
-	/**
-	 * Returns the item assignments for the specified user.
-	 * @param mixed $userId the user ID (see {@link IWebUser::getId})
-	 * @return array the item assignment information for the user. An empty array will be
-	 * returned if there is no item assigned to the user.
-	 */
-	public function getAuthAssignments($userId)
-	{
-		$rows=$this->db->createCommand()
-			->select()
-			->from($this->getTableName('authassignment'))
-			->where('userid=:userid', array(':userid'=>$userId))
-			->queryAll();
-		$assignments=array();
-		foreach($rows as $row)
-		{
-			if(($data=@unserialize($row['data']))===false)
-				$data=null;
-			$assignments[$row['itemname']]=new CAuthAssignment($this,$row['itemname'],$row['userid'],$row['bizrule'],$data);
-			
-		}
-		return $assignments;
-	}
-
-	/**
-	 * Saves the changes to an authorization assignment.
-	 * @param CAuthAssignment $assignment the assignment that has been changed.
-	 */
-	public function saveAuthAssignment($assignment)
-	{
-		$this->db->createCommand()
-			->update($this->getTableName('authassignment'), array(
-				'bizrule'=>$assignment->getBizRule(),
-				'data'=>serialize($assignment->getData()),
-			), 'itemname=:itemname AND userid=:userid', array(
-				'itemname'=>$assignment->getItemName(),
-				'userid'=>$assignment->getUserId()
-			));
-	}
-
-	/**
-	 * Returns the authorization items of the specific type and user.
-	 * @param integer $type the item type (0: operation, 1: task, 2: role). Defaults to null,
-	 * meaning returning all items regardless of their type.
-	 * @param mixed $userId the user ID. Defaults to null, meaning returning all items even if
-	 * they are not assigned to a user.
-	 * @return array the authorization items of the specific type.
-	 */
-	public function getAuthItems($type=null,$userId=null)
-	{
-		if($type===null && $userId===null)
-		{
-			$command=$this->db->createCommand()
-				->select()
-				->from($this->getTableName('authitem'));
-		}
-		else if($userId===null)
-		{
-			$command=$this->db->createCommand()
-				->select()
-				->from($this->getTableName('authitem'))
-				->where('type=:type', array(':type'=>$type));
-		}
-		else if($type===null)
-		{
-			$command=$this->db->createCommand()
-				->select('name,type,description,t1.bizrule,t1.data')
-				->from(array(
-					$this->getTableName('authitem').' t1',
-					$this->getTableName('authassignment').' t2'
-				))
-				->where('name=itemname AND userid=:userid', array(':userid'=>$userId));
-		}
-		else
-		{
-			$command=$this->db->createCommand()
-				->select('name,type,description,t1.bizrule,t1.data')
-				->from(array(
-					$this->getTableName('authitem').' t1',
-					$this->getTableName('authassignment').' t2'
-				))
-				->where('name=itemname AND type=:type AND userid=:userid', array(
-					':type'=>$type,
-					':userid'=>$userId
-				));
-		}
-		$items=array();
-		foreach($command->queryAll() as $row)
-		{
-			if(($data=@unserialize($row['data']))===false)
-				$data=null;
-			$items[$row['name']]=new CAuthItem($this,$row['name'],$row['type'],$row['description'],$row['bizrule'],$data);
-		}
-		return $items;
-	}
-
-	/**
-	 * Creates an authorization item.
-	 * An authorization item represents an action permission (e.g. creating a post).
-	 * It has three types: operation, task and role.
-	 * Authorization items form a hierarchy. Higher level items inheirt permissions representing
-	 * by lower level items.
-	 * @param string $name the item name. This must be a unique identifier.
-	 * @param integer $type the item type (0: operation, 1: task, 2: role).
-	 * @param string $description description of the item
-	 * @param string $bizRule business rule associated with the item. This is a piece of
-	 * PHP code that will be executed when {@link checkAccess} is called for the item.
-	 * @param mixed $data additional data associated with the item.
-	 * @return CAuthItem the authorization item
-	 * @throws CrugeException if an item with the same name already exists
-	 */
-	public function createAuthItem($name,$type,$description='',$bizRule=null,$data=null)
-	{
-		$this->db->createCommand()
-			->insert($this->getTableName('authitem'), array(
-				'name'=>$name,
-				'type'=>$type,
-				'description'=>$description,
-				'bizrule'=>$bizRule,
-				'data'=>serialize($data)
-			));
-		return new CAuthItem($this,$name,$type,$description,$bizRule,$data);
-	}
-
-	/**
-	 * Removes the specified authorization item.
-	 * @param string $name the name of the item to be removed
-	 * @return boolean whether the item exists in the storage and has been removed
-	 */
-	public function removeAuthItem($name)
-	{
-		if($this->usingSqlite())
-		{
-			$this->db->createCommand()
-				->delete($this->getTableName('authitemchild'), 'parent=:name1 OR child=:name2', array(
-					':name1'=>$name,
-					':name2'=>$name
-			));
-			$this->db->createCommand()
-				->delete($this->getTableName('authassignment'), 'itemname=:name', array(
-					':name'=>$name,
-			));
-		}
-
-		return $this->db->createCommand()
-			->delete($this->getTableName('authitem'), 'name=:name', array(
-				':name'=>$name
-			)) > 0;
-	}
-
-	/**
-	 * Returns the authorization item with the specified name.
-	 * @param string $name the name of the item
-	 * @return CAuthItem the authorization item. Null if the item cannot be found.
-	 */
-	public function getAuthItem($name)
-	{
-		$row=$this->db->createCommand()
-			->select()
-			->from($this->getTableName('authitem'))
-			->where('name=:name', array(':name'=>$name))
-			->queryRow();
-
-		if($row!==false)
-		{
-			if(($data=@unserialize($row['data']))===false)
-				$data=null;
-			return new CAuthItem($this,$row['name'],$row['type'],$row['description'],$row['bizrule'],$data);
-		}
-		else
-			return null;
-	}
-
-	/**
-	 * Saves an authorization item to persistent storage.
-	 * @param CAuthItem $item the item to be saved.
-	 * @param string $oldName the old item name. If null, it means the item name is not changed.
-	 */
-	public function saveAuthItem($item,$oldName=null)
-	{
-		if($this->usingSqlite() && $oldName!==null && $item->getName()!==$oldName)
-		{
-			$this->db->createCommand()
-				->update($this->getTableName('authitemchild'), array(
-					'parent'=>$item->getName(),
-				), 'parent=:whereName', array(
-					':whereName'=>$oldName,
-				));
-			$this->db->createCommand()
-				->update($this->getTableName('authitemchild'), array(
-					'child'=>$item->getName(),
-				), 'child=:whereName', array(
-					':whereName'=>$oldName,
-				));
-			$this->db->createCommand()
-				->update($this->getTableName('authassignment'), array(
-					'itemname'=>$item->getName(),
-				), 'itemname=:whereName', array(
-					':whereName'=>$oldName,
-				));
-		}
-
-		$this->db->createCommand()
-			->update($this->getTableName('authitem'), array(
-				'name'=>$item->getName(),
-				'type'=>$item->getType(),
-				'description'=>$item->getDescription(),
-				'bizrule'=>$item->getBizRule(),
-				'data'=>serialize($item->getData()),
-			), 'name=:whereName', array(
-				':whereName'=>$oldName===null?$item->getName():$oldName,
-			));
-
-		// extra: manejo de sintaxis.	
-		//
-		//	cuando un CAuthItem se guarda, se asegura que en caso de ser
-		//  un item tipo TASK que usa sintaxis de descripcion entonces
-		//	vigile el menuitem superior, asignando o desasignando automatica-
-		//	-mente a este TASK con las tareas superior.
-
-
-		if($item->getType() == CAuthItem::TYPE_TASK)
-			if($this->isTaskSubMenuItem($item)){
-				// es un submenu de otra tarea $parent
-				$parent = $this->getParentMenuAuthItem($item);
-				if($parent != null){
-					// no es huerfana
-					// a inserta a $item como hija de $parent
-					if(!$this->hasItemChild($parent->name, $item->name))
-						$this->addItemChild($parent->name, $item->name);
-				}
-			}
-
-	}
-
-	/**
-	 * Saves the authorization data to persistent storage.
-	 */
-	public function save()
-	{
-	}
-
-	/**
-	 * Removes all authorization data.
-	 */
-	public function clearAll()
-	{
-		$this->clearAuthAssignments();
-		$this->db->createCommand()->delete($this->getTableName('authitemchild'));
-		$this->db->createCommand()->delete($this->getTableName('authitem'));
-	}
-
-	/**
-	 * Removes all authorization assignments.
-	 */
-	public function clearAuthAssignments()
-	{
-		$this->db->createCommand()->delete($this->getTableName('authassignment'));
-	}
-
-	/**
-	 * Checks whether there is a loop in the authorization item hierarchy.
-	 * @param string $itemName parent item name
-	 * @param string $childName the name of the child item that is to be added to the hierarchy
-	 * @return boolean whether a loop exists
-	 */
-	public function detectLoop($itemName,$childName)
-	{
-		if($childName===$itemName)
-			return true;
-		foreach($this->getItemChildren($childName) as $child)
-		{
-			if($this->detectLoop($itemName,$child->getName()))
-				return true;
-		}
-		return false;
-	}
-
-	/**
-	 * @return CDbConnection the DB connection instance
-	 * @throws CrugeException if {@link connectionID} does not point to a valid application component.
-	 */
-	protected function getDbConnection()
-	{
-		if($this->db!==null)
-			return $this->db;
-		else if(($this->db=Yii::app()->getComponent($this->connectionID)) instanceof CDbConnection)
-			return $this->db;
-		else
-			throw new CrugeException(Yii::t('yii','CDbAuthManager.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.',
-				array('{id}'=>$this->connectionID)));
-	}
-
-	
-	/* extension:  no pertenece a la interfaz
-	
-	*/
-	public function getAuthItemTypeName($type,$booleanPlural=false){
-		if($type == CAuthItem::TYPE_ROLE)
-			return $booleanPlural==false ? "rol" : "roles";
-		if($type == CAuthItem::TYPE_TASK)
-			return $booleanPlural==false ? "tarea" : "tareas";
-		if($type == CAuthItem::TYPE_OPERATION)
-			return $booleanPlural==false ? "operacion" : "operaciones";
-		return $type;
-	}
-	
-	public function nextType(CAuthItem $item){
-		if($item->type == CAuthItem::TYPE_ROLE)
-			return CAuthItem::TYPE_TASK;
-		if($item->type == CAuthItem::TYPE_TASK)
-			return CAuthItem::TYPE_OPERATION;
-		return null;
-	}
-	
-	public function getRoles($userId = NULL){
-		return $this->getAuthItems(CAuthItem::TYPE_ROLE);
-	}
-	public function getTasks($userId = NULL){
-		return $this->getAuthItems(CAuthItem::TYPE_TASK);
-	}
-	public function getOperations($userId = NULL){
-		return $this->getAuthItems(CAuthItem::TYPE_OPERATION);
-	}
-
-		private function _filtroCruge($ops){
-			$crugeKey = "action_cruge_ui_";
-			$ar = array();
-			foreach($ops as $op)
-			{
-				$actionFull = $this->_mapAction($op->name, $this->mapping);
-				// ejemplo: convirtio action_ui_editprofile
-				//			a : 	  action_cruge_ui_editprofile
-				if(substr($actionFull,0,strlen($crugeKey))==$crugeKey)
-						$ar[] = $op;
-			}
-			return $ar;
-		}
-		private function _filtroNoCruge($ops){
-			$crugeKey = "action_cruge_ui_";
-			$ar = array();
-			foreach($ops as $op)
-			{
-				$actionFull = $this->_mapAction($op->name, $this->mapping);
-				// ejemplo: convirtio action_ui_editprofile
-				//			a : 	  action_cruge_ui_editprofile
-				if(substr($actionFull,0,strlen($crugeKey))!=$crugeKey)
-						$ar[] = $op;
-			}
-			return $ar;
-		}
-
-		private function _filtroNoController($ops){
-			$ar = array();
-			$arcontrollers = array();
-			foreach($this->enumControllers() as $controllerName)
-				$arcontrollers[]  = strtolower("action_".$controllerName."_");
-
-			foreach($ops as $op){
-				$found=false;
-				// busca a ver si esta operacion esta en la lista
-				// de controllers definidos.
-				foreach($arcontrollers as $cn)
-					if(substr($op->name,0, strlen($cn)) == $cn){
-						$found=true;
-						break;
-					}
-				// es una operacion no asociada a un controller
-				// por tanto le damos paso en este filtro
-				if(!$found)
-					$ar[] = $op;
-			}
-			return $ar;
-		}
-
-		// solo aquellas operaciones: "controller_site"
-		// (acceso maestro a controllers)
-		private function _filtroControllerMaestro($ops){
-			$ar = array();
-			$arcontrollers = array();
-			foreach($this->enumControllers() as $controllerName)
-				$arcontrollers[]  = strtolower("controller_".$controllerName);
-			$arcontrollers[] = "controller_ui"; // cruge
-
-			foreach($ops as $op){
-				$found=false;
-				// busca a ver si esta operacion esta en la lista
-				// de controllers definidos.
-				foreach($arcontrollers as $cn)
-					if(substr($op->name,0, strlen($cn)) == $cn)
-						$found=true;
-				// es una operacion no asociada a un controller
-				// por tanto le damos paso en este filtro
-				if($found == true)
-					$ar[] = $op;
-			}
-			return $ar;
-		}
-		private function _filtroNotControllerMaestro($ops){
-			$ar = array();
-			$arcontrollers = array();
-			foreach($this->enumControllers() as $controllerName)
-				$arcontrollers[]  = strtolower("controller_".$controllerName);
-			$arcontrollers[] = "controller_ui"; // cruge
-			foreach($ops as $op){
-				$found=false;
-				// busca a ver si esta operacion esta en la lista
-				// de controllers definidos.
-				foreach($arcontrollers as $cn)
-					if(substr($op->name,0, strlen($cn)) == $cn)
-						$found=true;
-				// es una operacion no asociada a un controller
-				// por tanto le damos paso en este filtro
-				if($found == false)
-					$ar[] = $op;
-			}
-			return $ar;
-		}
-
-		private function _filtroControllerName($ops, $controllerName){
-			$key = '_'.strtolower($controllerName).'_';
-			$ar = array();
-			foreach($ops as $item)
-				if(strstr($item->name, $key))
-					$ar[] = $item;
-			return $ar;
-		}
-
-	
-	/**
-	 * getOperationsFiltered 
-	 *	entrega un array de CAuthItem de tipo "operacion" pero en base a
-	 *	un filtro:
-	 *
-	 *		0 => todas
-	 *		1 => aquellas definidas en codigo
-	 *		2 => las de cruge
-	 *		3 => solo contollers maestro
-	 *		X => solo las del controller name = X
-	 *
-	 * @param string $filter 
-	 * @access public
-	 * @return array de CAuthItem
-	 */
-	public function getOperationsFiltered($filter, $oprList = null){
-		$ar = array();
-		if($oprList == null)
-			$oprList = $this->getOperations();
-		if(($filter == '') || ($filter=='0')){
-			// entrega el array completo de operaciones
-			$ar = $oprList;
-		}elseif($filter=='1'){
-			// OTRAS
-			// aquellas que no pertenecen a ningun controller especifico
-			// 	(porque no indican ningun "action_controller_" conocido)
-			// y que tampoco son de Cruge..
-			$ar = $this->_filtroNotControllerMaestro($this->_filtroNoCruge(
-				$this->_filtroNoController($oprList)));
-		}elseif($filter == '2'){
-			// CRUGE
-			// aqui se usa el $this->mapping tambien para reconocer
-			// los actions de Cruge
-			$ar = $this->_filtroCruge($oprList);
-		}elseif($filter == '3'){
-			// CONTROLLERS
-			// solo aquellos controllers maestros
-			$ar = $this->_filtroControllerMaestro(
-				$this->_filtroNoController($oprList)
-			);
-		}
-		else{
-			// CONTROLLER X
-			// aquellas que coinciden con un nombre de controller seleccion.
-			$ar = $this->_filtroControllerName($oprList, $filter);
-		}
-		return $ar;
-	}
-
-
-	public function getDataProviderRoles($pageSize=20){
-		return new CArrayDataProvider($this->getRoles(), array(
-			'keyField'=>'name',
-			'sort'=>array(
-				'defaultOrder'=>array('name'),
-			),
-			'pagination'=>array(
-				'pageSize'=>$pageSize,
-			),
-		));		
-	}
-	public function getDataProviderTasks($pageSize=50){
-		return new CArrayDataProvider(
-				$this->reorderItemArray($this->getTasks())
-				, array(
-			'keyField'=>'name',
-			'sort'=>array(
-				'defaultOrder'=>array('name'),
-			),
-			'pagination'=>array(
-				'pageSize'=>$pageSize,
-			),
-		));				
-	}
-	/**
-	 * getDataProviderOperations 
-	 *	entrega un dataprovider segun el filtro seleccionado.
-	 *
-	 *	@see getOperationsFiltered
-	 *
-	 * @param string $filter 
-	 * @param int $pageSize 
-	 * @access public
-	 * @return CArrayDataProvider de elementos CAuthItem
-	 */
-	public function getDataProviderOperations($filter='',$pageSize=50){
-		return new CArrayDataProvider($this->getOperationsFiltered($filter)
-		,array(
-			'keyField'=>'name',
-			'sort'=>array(
-				'defaultOrder'=>array('name'),
-			),
-			'pagination'=>array(
-				'pageSize'=>$pageSize,
-			),
-		));				
-	}	
-	public function getRolesAsOptions($emptyLabel=null){
-		$ar = array();
-		if($emptyLabel != null)
-			$ar['']=$emptyLabel;
-		
-		foreach($this->roles as $rol){
-			$ar[$rol->name] = $rol->name;
-		}
-		return $ar;
-	}
-
-
-	// FUNCIONES PARA EL MANEJO DE SINTAXIS APLICADA A LA DESCRIPCION
-	// DEL AUTH ITEM:
-	//
-	//	
-	//
-
-	/**
-	 * isItem 
-	 *	 detecta si la descripcion del item indica que es un menu (o submenu).
-	 *	 lo hace buscando el simbolo ":" al inicio de la descripcion
-	 * @param mixed $obj 
-	 * @access private
-	 * @return boolean true es un menu o un submenuitem.
-	 */
-	private function isItem($obj){
-		$d = trim($obj->getDescription());
-		if(strlen($d) > 0){
-			return ($d[0]==':') ? true : false;
-		}
-		return false;
-	}
-
-
-	/**
-	 * isSubItem 
-	 *	detecta si el item es un submenu, primero preguntando si isItem()
-	 *	y finalmente preguntando si contiene caracteres { }
-	 * 
-	 * @param mixed $obj 
-	 * @access private
-	 * @return bool true si es un subitem.
-	 */
-	public function isSubItem($obj){
-		$d = trim($obj->getDescription());
-		if(!$this->isItem($obj))
-			return false;
-		// sin mucho analisis lexico-sintaxis...
-		// asi facilito..
-		return strstr($d,"{") && strstr($d, "}");
-	}
-
-	
-	/**
-	 * getTaskText 
-	 *	devuelve la descripcion pura de un CAuthItem considerando la
-	 *	sintaxis:
-	 *
-	 *		":Descripcion Pura{menu_padre}{action_xxx}"
-	 *
-	 *		entregando de aqui solo a: "Descripcion Pura"
-	 *
-	 * @param mixed $obj 
-	 * @access private
-	 * @return void
-	 */
-	public function getTaskText($obj){
-		return $this->_getTextFromDescription($obj->getDescription());
-	}
-
-	/**
-	 * getItemPosition 
-	 *	obtiene de la descripcion el argumento numerico de posicion tras
-	 *	el simbolo inicial ":".
-	 *	  ejemplo ":123 mi item" devolvera: 123, sino 0
-	 *
-	 * @param mixed $obj 
-	 * @access private
-	 * @return integer
-	 */
-	public function getItemPosition($obj){
-		$d =  trim(ltrim($obj->getDescription(),':'));
-		$dig='';
-		for($i=0;$i<strlen($d);$i++)
-			if(ctype_digit($d[$i])){
-			$dig .= $d[$i];
-			}
-			else
-			return ($dig)*1;
-		return null;
-	}
-
-
-	/**
-	 * _getParentMenuName 
-	 *	de un texto ":hola {menu_item}" devolvera: "menu_item" 
-	 * @param mixed $m 
-	 * @access private
-	 * @return void
-	 */
-	private function _getParentMenuName($m){
-		if($m == null)
-			return "";
-		if(strlen($m)==0)
-			return "";
-		$r="";
-		$s=0;
-		for($i=0;$i<strlen($m);$i++){
-			if($s==0){
-				if($m[$i]=='{')
-					$s=1;
-			}
-			elseif($s==1){
-				if($m[$i]=='}'){
-					return trim($r);
-				}
-				elseif($m[$i]=='{'){
-					$r="";
-				}
-				else
-					$r .= $m[$i];
-			}
-		}
-		return trim($r);
-	}
-
-	/**
-	 * _getActionItemName 
-	 *	obtiene el contenido de la segunda llave en la sintaxis de la descr
-	 *		ejemplo:
-	 *			$m = "blabla {perrito} y {gatico}";
-	 *		retorna:
-	 *			"gatico" (la segunda llave)
-	 * @param string $m  contenido de la descripcion
-	 * @access protected
-	 * @return string
-	 */
-	private function _getActionItemName($m){
-		if($m == null)
-			return "";
-		if(strlen($m)==0)
-			return "";
-		$r="";
-		$s=0;
-		for($i=0;$i<strlen($m);$i++){
-			if($s==0){
-				if($m[$i]=='{')
-					$s=1;
-			}
-			elseif($s==1){
-				if($m[$i]=='}'){
-					$s=2;
-				}
-			}elseif($s==2){
-				if($m[$i]=='{'){
-					$s=3;
-					$r='';
-				}
-			}elseif($s==3){
-				if($m[$i]=='}'){
-					return trim($r);
-				}elseif($m[$i]=='{'){
-					$r='';
-				}
-				else $r .= $m[$i];
-			}
-		}
-		return trim($r);
-	}
-	private function _getTextFromDescription($description){
-		// limpia cualquier ":" delante
-		$d = trim(ltrim($description,':'));
-		// pasa el numero que pudiese venir a continuacion 
-		$p=0;
-		for($i=0;$i<strlen($d);$i++){
-			if(ctype_digit($d[$i])){
-			  continue;
-			}
-			else{
-				$p=$i;
-				break;
-			}
-		}
-
-		if($p == 0){
-			// no hay numero
-		}
-		else{ 
-			// si hay numero, descripcion continua en posicion $p
-			$d = substr($d,$p);
-		}
-
-		// busca hasta algun posible "{"
-		$tmp = "";
-		for($i=0;$i<strlen($d);$i++)
-			if($d[$i] != '{'){
-				$tmp .= $d[$i];
-			}else
-				break;
-
-		return trim($tmp);
-	}
-	private function _mapAction($action, $mappings){
-		if(trim($action)=="")
-			return "";
-		foreach($mappings as $map=>$xy)
-			if(substr($action,0,strlen($map))==$map)
-				return $xy.substr($action,strlen($map));
-		return $action;
-	}
-
-
-	public function isTaskMenuItem($obj){
-		return $this->isItem($obj);
-	}
-	public function isTaskSubMenuItem($obj){
-		return $this->isSubItem($obj);
-	}
-	public function isTaskTopMenuItem($obj){
-		$n = trim($obj->getName());
-		if($this->isItem($obj)){
-			if(strstr($n,"menu_"))
-			 return true;
-			return false;
-		}
-		else return false;
-	}
-	/**
-	 * getTaskParentMenuName 
-	 *	de una tarea con descripcion: ":Menu1 {menu_principal}" devolvera:
-	 *		el string "menu_principal"
-	 * @param mixed $obj 
-	 * @access public
-	 * @return string  o ""
-	 */
-	public function getTaskParentMenuName($obj){
-		if($this->isTaskSubMenuItem($obj)){
-			return $this->_getParentMenuName($obj->getDescription());
-		}
-		else
-			return "";
-	}
-	/**
-	 * getParentMenuAuthItem
-	 *	pregunta si el CAuthItem $obj tiene un itename padre en su sintaxis
-	 *	de descripcion y si este item name existe como un CAuthItem.
-
-	 * @param CAuthItem $obj el authitem a consultar.
-	 * @access public
-	 * @return CAuthItem del padre dado por la sintaxis de la descripcion.
-	 */
-	public function getParentMenuAuthItem($obj)
-	{
-		$itemname_padre = $this->getTaskParentMenuName($obj);
-		return $this->getAuthItem($itemname_padre);
-	}
-	/**
-	 * getTaskActionItemName
-	 *	de una tarea con descripcion: ":Menu1 {menu_principal} {action_site_index}" 	
-	 * 		devolvera:
-	 *			"action_site_index" (el itemname de aquella operacion "child"
-	 								que sera usada como disparador del menu)
-	 *
-	 * @param mixed $obj 
-	 * @access public
-	 * @return string o ""
-	 */
-	public function getTaskActionItemName($obj){
-		if($this->isTaskSubMenuItem($obj)){
-			return $this->_getActionItemName($obj->getDescription());
-		}
-		else
-			return "";
-	}
-
-	/**
-	 * getTaskUrl 
-	 *	de aquella tarea que usa sintaxis en su descripcion para manejar menues
-	 *	retorna la parte que hace referencia al auth item name del action
-	 *	seleccionado por el usuario para responder para este menu.
-	 *
-	 * @param CAuthItem $obj la tarea
-	 * @param array $args Argumentos en forma de array para adosar
-	 * @access public
-	 * @return array url en forma de array
-	 */
-	public function getTaskUrl($obj, $args=null){
-
-		$itemname = $this->getTaskActionItemName($obj);
-		if($itemname == '')
-			return '';
-
-		// ver si hay un mapping para el action
-		//	este no es un mapping tradicional, sino de patrones:
-		//		ejemplo:
-		//		mapping: "action_ui_" cambiara por "action_cruge_ui_"
-		//
-		$itemname = $this->_mapAction($itemname, $this->mapping);
-
-		// ejemplo, recibe: action_site_index
-		// lo descompone en array('site/index', ..$args..)
-		$e = explode('_', $itemname);
-		if(sizeof($e)==3){
-			$controllerName = $e[1];
-			$actionName = $e[2];
-			$a = array();
-			$a[] = $controllerName."/".$actionName;
-			foreach($args as $k=>$v)
-				$a[$k] = $v;
-			return $a;
-		}
-		elseif(sizeof($e)==4){
-			$moduleName = $e[1];
-			$controllerName = $e[2];
-			$actionName = $e[3];
-			$a = array();
-			$a[] = $moduleName.'/'.$controllerName."/".$actionName;
-			foreach($args as $k=>$v)
-				$a[$k] = $v;
-			return $a;
-		}
-		else
-		return array();
-	}
-
-	/**
-	 * explodeTask 
-	 *	descompone la descripcion de un TASK en sus partes segun sintaxis:
-	 *		":POS descripcion{menu}{action}"
-	 *
-	 * @param CAuthItem $obj 
-	 * @access public
-	 * @return array indexado array('description','position','menu','action')
-	 */
-	public function explodeTask($obj) {
-		return array(
-			'description'=>$this->getTaskText($obj),
-			'position'=>$this->getItemPosition($obj),
-			'menu'=>$this->getTaskParentMenuName($obj),
-			'action'=>$this->getTaskActionItemName($obj),
-		);
-	}
-
-	/**
-	 * setTaskAction 
-	 *	Actualiza un CAuthItem ($obj), le pondrá en su descripcion (usando la
-	 *	sintaxis para menues) al nuevo action, considerando cualquier action
-	 *	existente. 
-	 *
-	 *	ejemplo:
-	 *		descripcion original: ":Subitem X {menu_prinicipal}"
-	 *		el $action_item_name es: "action_site_prueba"
-	 *		el resultado de la descripcion final sera:
-	 *			":Subitem X {menu_prinicipal} {action_site_prueba}"
-	 *
-	 *			***** EL CAuthItem sera Actualizado *****
-	 *
-	 * @param mixed $obj el objeto CAuthItem a quien se le modificara la descr.
-	 * @param mixed $action_item_name El action a usar (itemname del CAuthItem)
-	 * @access public
-	 * @return void 
-	 */
-	public function setTaskAction($obj, $action_item_name){
-		$ar = $this->explodeTask($obj);
-		$newDescr = ":".$ar['position']." ".$ar['description']
-			."{".$ar['menu']."}{".$action_item_name."}";
-		$obj->setDescription($newDescr);
-		$this->saveAuthItem($obj);
-	}
-
-	/**
-	 * isTaskMenuItemChild 
-	 *	detecta si un CAuthItem ($item) es un hijo de otro ($posibleSuperior)
-	 *  utiliza la sintaxis del atributo Description para detectarlo.
-	 * 
-	 * @param CAuthItem $item 
-	 * @param CAuthItem $posibleSuperior 
-	 * @access public
-	 * @return void
-	 */
-	public function isTaskMenuItemChild($item, $posibleSuperior){
-		return ($this->getTaskParentMenuName($item) 
-			== $posibleSuperior->getName());
-	}
-
-
-	/**
-	 * explodeTaskArray 
-	 *	separa un array original de CAuthItem TASK en partes organizadas por
-	 *	tipo: Menu, MenuItems y Tareas Regulares.
-	 *	
-	 *	ejemplo:
-	 *
-	 *		1. se le da una lista entera de todas las tareas del sistema
-	 *		usando $this->getTasks():
-	 *
-	 *		2. se invoca a este metodo
-	 *
-	 *		3. el metodo retorna un array con esta forma:
-	 *
-	 *			array(
-	 *				'topmenu'=>array(...),
-	 *				'childmenu'=>array('authitemname'=>array(), ... ),
-	 *				'regular'=>array(...)
-	 *			);
-	 *
-	 *		se ven 3 categorias (indices) de array aqui:
-	 *			topmenu
-	 *			childmenu
-	 *			regular
-	 *
-	 *		topmenu: 	array de CAuthItem tipo TASK de todos aquellos
-	 *				 	considerados Menu de 1er nivel al usar sintaxis.
-	 *
-	 *		childmenu:	array de arrays de CAuthItem indexado por el nombre del
-	 *					CAuthItem padre del item usando la sintaxis de menu
-
-	 *		orphan:		array de CAuthItem de aquellos marcados con sintaxis
-	 *					de sub menu item pero cuyo padre no existe.
-	 *
-	 *		regular:	array de CAuthItem de todas las tareas que no son menues.
-	 *
-	 *
-	 * @param array $originTaskList CAuthItem tipo TASK
-	 * @access public
-	 * @return array
-	 */
-	public function explodeTaskArray($originTaskList){
-
-		$top = array();		// top menu
-		$child = array();	// menuitems de alguien (index)
-		$error = array();	// huerfanos
-		$regular = array();	// tareas normales
-
-		// detecta TOP menu tasks
-		foreach($originTaskList as $task)
-			if($this->istaskTopMenuItem($task))
-				$top[] = $task;
-		
-		// busca las tareas que son hijas de las primeras 
-		// halladas. (son hijas dada la sintaxis de descripcion del CAuthItem)
-		//
-		foreach($top as $topmenuitem){
-			foreach($originTaskList as $task)
-				if($this->isTaskMenuItemChild($task, $topmenuitem))
-					$child[$topmenuitem->name][] = $task;
-		}
-		
-
-		// agrega los huerfanos.
-		// aquellas tareas marcadas como menuitems cuyo padre no existe
-		//
-		foreach($originTaskList as $task)
-			if($this->isTaskSubMenuItem($task))
-				if(!$this->getParentMenuAuthItem($task))
-					$error[] = $task;
-
-		// agrega todas aquellas tareas que no son menuitems
-		//
-		foreach($originTaskList as $task)
-			if(!$this->isTaskMenuItem($task))
-				$regular[] = $task;
-
-		return array(
-				'topmenu' => $top,
-				'childmenu' => $child,
-				'orphan' => $error,
-				'regular' => $regular
-			);
-	}
-
-	/**
-	 * reorderItemArray 
-	 *	ordernara un array de CAuthItem  de tipo TASK de modo que
-	 *	el array resultante este organizado asi:
-	 *
-	 *		MENU_ITEM_1
-	 *			SUB_MENU_ITEM {parent: MENU_ITEM_1}
-	 *			SUB_MENU_ITEM    "
-	 *			SUB_MENU_ITEM    "
-	 *		MENU_ITEM_2
-	 *			SUB_MENU_ITEM {parent: MENU_ITEM_2}
-	 *			SUB_MENU_ITEM    "
-	 *			SUB_MENU_ITEM    "
-	 *		NO_MENU_ITEM_1
-	 *		NO_MENU_ITEM_2
-	 *		NO_MENU_ITEM_3
-	 *		NO_MENU_ITEM_N
-	 *
-	 * @param mixed $itemArray array de CAuthItem
-	 * @access public
-	 * @return array de CAuthItem 
-	 */
-	public function reorderItemArray($itemArray){
-
-		$r = array();
-
-		// busca aquellas operaciones que son tareas
-		// y que son menu items, pero que no son sub menu items
-		$r1 = array();
-		foreach($itemArray as $item)
-			if($this->isTaskMenuItem($item) 
-				&& !$this->isTaskSubMenuItem($item))
-					$r1[] = $item;
-
-		// busca las tareas que son hijas de las primeras 
-		// halladas. (son hijas dada la sintaxis de descripcion del CAuthItem)
-		//
-		foreach($r1 as $menuitem){
-			$r[] = $menuitem;
-			foreach($itemArray as $item)
-				if($this->isTaskMenuItemChild($item, $menuitem))
-					$r[] = $item;
-		}
-
-		// agrega los huerfanos
-		// aquellas tareas marcadas como menuitems cuyo padre no existe
-		//
-		foreach($itemArray as $item)
-			if($this->isTaskSubMenuItem($item))
-				if(!$this->getParentMenuAuthItem($item))
-					$r[] = $item;
-
-		// agrega todas aquellas tareas que no son menuitems
-		//
-		foreach($itemArray as $item)
-			if(!$this->isTaskMenuItem($item))
-				$r[] = $item;
-
-		return $r;
-	}
-
-
-	/**
-	 * getMenu 
-	 *  devuelve un array indexado listo para usar en CMenu
-	 *	  incluso con una entrada extra para subitems: 'items'
-	 *	  para menues extendidos.
-	 *
-	 *	el array es obtenido usando la sintaxis de la descripcion.
-	 *
-	 * @access public
-	 * @param $arguments adjunta argumentos a la url, ej: array('abc'=>'123')
-	 * @return array indexado ('label','url' [,'items'=>array(...)])
-	 */
-	public function getMenu($userid=-1, $arguments = array()){
-
-		if($userid==-1)
-			$userid = Yii::app()->user->id;
-
-		$r = array();
-		
-		// todas las TAREAS a las que puede acceder este usuario
-
-		// este metodo no sirve porque solo lista elementos directamente
-		// relacionados al userid y no lista aquellos derivados,
-		//$itemArray = $this->getAuthItems(CAuthItem::TYPE_TASK,$userid);
-		
-		$tasklist = $this->tasks;
-
-		// por tanto a lo anterior: listo todas las tareas de tipo menuitem
-		// y pregunto si el usuario tiene acceso a ellas:
-		$itemArray = array();
-		foreach($tasklist as $task){
-			if($this->isTaskMenuItem($task) && !$this->isTaskSubMenuItem($task)){
-				if($this->checkAccess($task->getName(), $userid)){
-					$itemArray[] = $task;
-				}
-			}
-		}
-
-		// todas las tareas consideradas subitems, no importa
-		// si estan asignadas al usuario
-		//
-		$allsubitems = array();
-		foreach($tasklist as $task)
-			if($this->isTaskSubMenuItem($task))
-				$allsubitems[] = $task;
-
-		// Menues de Primer Nivel
-		//
-		// busca aquellas operaciones que son tareas
-		// y que son menu items, pero que no son sub menu items
-		$r1 = array();
-		foreach($itemArray as $item)
-			if($this->isTaskMenuItem($item) 
-				&& !$this->isTaskSubMenuItem($item))
-					$r1[] = $item;
-
-		// busca las tareas que son hijas de las primeras 
-		// halladas. (son hijas dada la sintaxis de descripcion del CAuthItem)
-		//
-		foreach($r1 as $menuitem){
-			// child menu items
-			$items = array();
-			// agrega al menuitem de 1er nivel todas los subitems (tasks)
-			// sin importar si fueron otorgadas al usuario con checkAccess
-			//
-			foreach($allsubitems as $task)
-				if($this->isTaskMenuItemChild($task, $menuitem))
-					$items[] = array(
-						'label'=>$this->getTaskText($task),
-						'url'=>$this->getTaskUrl($task, $arguments),
-					);
-			// top level menu
-			if(!sizeof($items))
-				$items = null;
-			$r[] =  array(
-				'label'=>$this->getTaskText($menuitem),
-				'url' => '',
-				'items' => $items,
-			);
-		}
-		return $r;
-	}
-
-
-	/**
-	 * enumControllers 
-	 *	lista los nombres de los controllers declarados. 
-	 * @access public
-	 * @return array con nombre del controller
-	 */
-	public function enumControllers(){
-		if($this->_enumcontrollers == null){
-			$this->_enumcontrollers = array();
-			$p = Yii::app()->getControllerPath();
-			foreach(scandir($p) as $f){
-				if($f == '.' || $f == '..')	
-					continue;
-				if(strlen($f))
-					if($f[0]=='.')
-						continue;
-				if($pos = strpos(strtolower($f),"controller.php")){
-					$this->_enumcontrollers[] = substr($f,0, $pos);
-				}
-			}
-			return $this->_enumcontrollers;
-		}
-		else
-		return $this->_enumcontrollers;
-	}
-
-	/**
-	 * enumActions 
-	 *	devuelve un array con los nombres de los actions del controller 
-	 * @param mixed $controllerName nombre del controller
-	 * @access public
-	 * @return array lista de actions.
-	 */
-	public function enumActions($controllerName){
-		$this->_enumactions = array();
-		$className = $controllerName.'Controller';
-		Yii::import('application.controllers.'.$className,true);
-		$refx = new ReflectionClass($className); 
-		foreach($refx->getMethods() as $method){
-			if($method->name != 'actions')
-			if(substr($method->name,0,6)=="action")
-				$this->_enumactions[] = substr($method->name,6);
-		}
-		return $this->_enumactions;
-	}
-
-	/**
-	 * autoDetect 
-	 *	lee todos los controllers y actions y los almacena si previamente
-	 *	no estaban registrados.
-	 * @access public
-	 * @return void
-	 */
-	public function autoDetect(){
-
-		// agrega cada actiond e cada controller detectado en codigo fuente
-		//
-		foreach($this->enumControllers() as $c){
-			// cada controller
-			$itemName = "controller_".strtolower($c);
-			if(!$this->getAuthItem($itemName))
-				$this->createAuthItem($itemName,
-						CAuthItem::TYPE_OPERATION,"");
-			// cada action
-			foreach($this->enumActions($c) as $action){
-				$itemName = "action_".strtolower($c)."_".strtolower($action);
-				if(!$this->getAuthItem($itemName))
-					$this->createAuthItem($itemName,
-						CAuthItem::TYPE_OPERATION,"");
-
-			}
-		}
-
-		$this->ensureMenuItemIntegrity();
-	}
-
-
-	/**
-	 * ensureMenuItemIntegrity 
-	 *	se asegura que todas aquellas tareas que usan sintaxis de descripcion
-	 *	y que sean subitems de uno superior (debido a la sintaxis) 
-	 *	se asegura que cada subitem este asignado como un child auth item a
-	 *  la tarea superior.	
-	 *
-	 * @access public
-	 * @return void
-	 */
-	public function ensureMenuItemIntegrity(){
-		$data = $this->explodeTaskArray($this->getTasks());
-		$submenues = $data['childmenu'];
-		foreach($submenues as $parentItemName=>$tasks){
-			// determina si esta tarea esta asignada a su padre
-			foreach($tasks as $task)
-				if(!$this->hasItemChild($parentItemName, $task->name))
-					$this->addItemChild($parentItemName, $task->name);
-		}
-	}
+El uso de mapping tambien ayuda para cuando los actions
+declarados como "actions de menu item" apuntan a aquellos
+que estan definidos en un modulo de usuario,
+
+por ejemplo, tienes un action que realmente esta definido
+dentro de un modulo llamado "tumodulox"
+
+action_default_index
+
+si no usas un mapping, este action se generara relativo a
+la aplicacion sin modulo, es decir:
+
+array('default/index')  Y DARA UN ERROR, porque
+asume que lo que "para tu modulo" era el controller default
+se le pedira a la aplicacion base y fallará porque no existe.
+
+por tanto, se resolveria en config main pasandole a esta clase
+un nuevo mapping:
+
+'mapping' => array(
+'action_ui_'=>'action_cruge_ui_',
+'action_default_' => 'action_tumodulox_default_',
+),
+
+ahora, al invocar el menu se producira correctamente la URL
+apuntando a tu modulo:
+
+array('/tumodulox/default/index'),
+
+
+ARGUMENTOS DE LA URL ($args)
+
+La url recibe argumentos cuando se invoca a Yii::app()->rbac->getMenu
+
+Por ejemplo, queremos que todos los menu items tengas adosado un
+parametro (o mas):
+
+Yii::app()->user->rbac->getMenu(array('idempresa'=>123));
+
+esto generara un array de menu items (para CMenu o MbMenu o EMenu etc)
+cuya url será finalmente asi: