Overview

EJO

Editor de Jerarquías y Orden


Presentación

En ciertas aplicaciones que manejan registros que deben ser clasificados y luego presentados en subconjuntos, es usual que esa categorización deba luego ser utilizada como un menú.
Supongamos el caso de una tienda, que vende productos de diferente clase: carteras, cinturones, collares, aros, etc.
El "catálogo" a mostrar estaría organizado de este modo, por ejemplo:

Catálogo
+--> Carteras
   +--> De fiesta
   +--> Informales
   +--> Sobres
+--> Cinturones
   +--> Femeninos
   +--> Masculinos
+--> Aros
   +--> Clip
      +--> Piedras preciosas
      +--> Piedras semipreciosas
      +--> Solo metal
   +--> Pasantes
      +--> Piedras preciosas
      +--> Piedras semipreciosas
      +--> Solo metal
+--> Collares

Luego, utilizando una acción del controlador que "filtre" por ruta, se podrán listar los artículos que estén dentro de ese grupo identificado por rutas conformadas por los códigos de los ítems que conforman ese árbol, por ejemplo:

ruta de ID  ruta
'/26'       /Collares
'/1/8/15',  /Aros/Clip/Piedras preciosas
'/1/8/48',  /Aros/Clip/Piedras semipreciosas
'/1/8/22',  /Aros/Clip/Solo metal
'/1/9/15',  /Aros/Pasante/Piedras preciosas
'/1/9/48',  /Aros/Pasante/Piedras semipreciosas
'/1/9/22',  /Aros/Pasante/Solo metal

Obsérvese que HAY duplicidad, y se espera que la haya en estos escenarios, pero no hay duplicidad en los registros que forman este árbol.
Sería complicado mantener esa estructura desde el punto de vista del desarrollo, y dado que la información la maneja el "cliente" y debería poder modificarla libremente, es que decidí de hacer aquella solución un módulo.
Este caso "Catálogo" puede aplicarse, por ejemplo, a un "diario" cuyas "notas" se clasifican en "secciones"; un sitio de biología y clasificar los animales, plantas, etc. según su familia taxonómica...
En fin, las aplicaciones son muchas.

Instalación

  • Descargar desde aquí
  • Descomprimir el contenido (o clonar) en protected/modules/ejo
  • Editar main.php:

Caso una sola instancia:

'modules'=>array(  
  'ejo',  
...

Caso una sola instancia personalizada:

'modules'=>array(
  'Nombre' => array(
  'class' => 'application.modules.ejo.EjoModule', // Obligatorio
  //En este caso las tablas y vistas se nombrarán con
  //'Nombre' como base (nombre, nombreRelation, etc...)
)
...

Caso mas de una instancia personalizada:

'modules'=>array(
  'Nombre' => array(
    'class' => 'application.modules.ejo.EjoModule', // Obligatorio
    //En este caso las tablas y vistas se nombrarán con
    //'Nombre' como base (nombre, nombreRelation, etc...)
   )
  'OtroNombre' => array(
    'class' => 'application.modules.ejo.EjoModule', // Obligatorio
    //Si los siguientes parámetros no se indican
    //se usará el ID como base (ID, en este caso "OtroNombre")
    //'Nombre' como base (nombre, nombreRelation, etc...)
    'mainTable = 'MiTabla'; //Por ahora es necesario indicar el prefijo si existiera. Por Defecto: ID
    'relationsTable = 'MiTablaDeRelaciones'; //Por ahora es necesario indicar el prefijo si Existiera. 
                                             //Por Defecto: IDRelations
    'mainView = 'MiTablaVista'; //Nombre la para la vista SQL. Por Defecto: IDView
    'relationsView = 'MiTablaRelacionesVista'; //Nombre la para la vista de relaciones SQL. Por Defecto: IDRelationsView
    'prefixTable = 'tbl_'; //Si no se indica, se usa la de Yii
    'prefixView = 'viw_'; //Yii no prevee prefijos para las vistas. Se sugiere esta: vew_
    'gemiInstalled' = false; //Puede evitarse el uso de GeMI si estuviera instalado.
  )
 ...

Notas

  • Quizá los nombres de las tablas y vistas sean un poco raros y/o largos.
  • Este módulo está diseñado para ofrecer todos los datos sin tener que lidiar con las tablas.
  • También, pienso que si utilizas este módulo, desees que haga el trabajo sucio con las tablas por ti.
  • Si recuperas la cordura luego de ver el "editor del árbol", puedo decir en mi favor que usé código que hace un tiempo escribí y estoy seguro que funciona. Y embarcarme en el uso de JStree o similares retrasará mi implementación. Por lo tanto, eres libre de "colaborar" mejorando esa parte y compartiéndola... Ya el mayor trabajo está hecho. ¡Gracias!
  • Hay algunas partes en el código que pueden ser un poco "desprolijas". Lo reconozco. Por eso lo pongo a disposición de quien desee mejorar esas partes. Todos aprenderemos de ello.

Uso

Instanciar el módulo:

$NuevoEJO = Yii::getModule('Nombre') // El que se indicó en main.php
$NuevoEJO->Propiedad = valor;
$NuevoEJO->Función;

O llamada directa:

Yii::getModule('Nombre')->Propiedad_o_Función // Nombre=El que se indicó en main.php

Administrador

En el arreglo de menú:

array('label' => 'Título', 'url' => array('/nombreEjo/item/index'), 'visible' => !Yii::app()->user->isGuest),

Parámetros

Los que permiten escritura, pueden (y deberían) usarse en main.php para indicar los valores.

afterCreate

Texto que será evaluado al final del proceso de creación del ítem y entrega a la función o método el código del ítem creado. Esto ocurre ANTES de redirigir a la vista luego de crear el registro.

Tipo: Lectura Valor: Texto

'afterCreate' => 'Clase::metodo',//se avaluará como Clase::metodo($itmCodigo)

afterDelete

Texto que será evaluado al final del proceso de borrado del ítem y entrega a la función o método el código del ítem eliminado. Esto ocurre ANTES de redirigir a la vista luego de eliminar el registro.

Tipo: Lectura Valor: Texto

'afterDelete' => 'Clase::metodo',//se avaluará como Clase::metodo($itmCodigo)

afterUpdate

Texto que será evaluado al final del proceso de modificación del ítem y entrega a la función o método el código del ítem modificado. Esto ocurre ANTES de redirigir a la vista luego de MODIFICAR el registro.

Tipo: Lectura Valor: Texto

'afterUpdate' => 'Clase::metodo', //se avaluará como Clase::metodo($itmCodigo)

afterConnect

Texto que será evaluado al final del proceso de modificación de relaciones de los ítems y llama a la función o método indicado. Esto ocurre ANTES de redirigir a la vista luego de MODIFICAR las relaciones.

Tipo: Lectura Valor: Texto

'afterUpdate' => 'Clase::metodo',//se avaluará como Clase::metodo()

codeMsg

Indica el código de los mensajes a utilizar en GeMI (si está instalado)

Tipo: Lectura/Escritura
Valor: Texto

gemiInstalled

Indica si el módulo GeMI está instalado o no.
Si está instalado y se asigna un valor false se impide que EJO haga uso de GeMI (No recomendable)

Tipo: Lectura/Escritura
Valor: Lógico

mainTable

Indica el nombre de la tabla para el módulo.
Si no se indica se utiliza el nombre como base, usando el prefijo de tabla indicado o por defecto de Yii.

Tipo: Lectura/Escritura
Valor: Texto

mainView

Indica el nombre de la vista para el módulo.
Si no se indica se utiliza el nombre como base, usando el prefijo de vista indicado o por defecto 'vew_'.
Yii no considera, o al menos no hay documentación, el uso de vistas

Tipo: Lectura/Escritura
Valor: Texto

name

Indica el nombre de la instancia.
Si es necesario utilizar varias instancias, sólo basta con configurar varios nombres (ID) en main.php

Tipo: Sólo Lectura
Valor: Texto

prefixTable

Indica el prefijo utilizar al crear las tablas.
Si no se indica se utiliza el configurado en Yii.

Tipo: Lectura/Escritura
Valor: Texto

prefixView

Indica el prefijo utilizar al crear las vistas.
Si no se indica se utiliza 'vew_'.
Yii no considera, o al menos no hay documentación, el uso de vistas

Tipo: Lectura/Escritura
Valor: Texto

relationsTable

Indica el nombre de la tabla de relaciones para el módulo.
Si no se indica se utiliza el nombre como base, usando el prefijo de tabla indicado o por defecto de Yii.

Tipo: Lectura/Escritura
Valor: Texto

relationsView

Indica el nombre de la vista de idiomas e ítems definidos.
Ayuda a GeMI (si está instalado) para sitios i18n.
Si no se indica se utiliza el nombre como base, usando el prefijo de vista indicado o por defecto 'vew_'.
Adicionalmente se le agrega el sufijo "_GeMI" para saber si es la estructura para GeMI o no.
Yii no considera, o al menos no hay documentación, el uso de vistas

Tipo: Lectura/Escritura
Valor: Texto

route

Indica la ruta a utilizar cuando se devuelve el arreglo para CMenu o EMenu (preferentemente).
Por defecto su valor es "#".
Supongamos que usaremos EJO para categorizar "recetas". Por lo tanto,tendremos un controlador llamado "receta" y una acción llamada "leer", y en el modelo tenemos una propiedad que se llama "seccion" que "categoriza" las recetas según la "ruta" en la cual se clasificó:

'route' => 'receta/leer?seccion=';

Tipo: Lectura/Escritura
Valor: Texto

showAll

Indica si deben mostrarse sólo los ítems activos o todos. El valor será interpretado por lo tanto puede usarse:

'showAll' => '!Yii::app()->user->isGuest';

Tipo: Lectura/Escritura
Valor: Lógico/Texto

slDescripcion

Descripcion para la columna que contiene los valores para los ítems en idioma origen. Si GeMI estuviera instalado, tomará el nombre del idioma en su notación nativa. Si estuviera indicado en la configuración del módulo, se usará ese texto:

'slDescricpion' => 'Texto Original';

Tipo: Lectura
Valor: Texto

titlePlural

Texto a utilizar en las vistas de CRUD.

Tipo: Lectura/Escritura
Valor: Texto

titleCreate

Texto a utilizar en las vistas Create.
Este texto será "interpretado" por lo tanto puede utilizar esta cadena:

'titleCreate' => '$this->titleSingular . " Create"';

Tipo: Lectura/Escritura
Valor: Texto

titleDelete

Texto a utilizar en las vistas Delete.
Este texto será "interpretado" por lo tanto puede utilizar esta cadena:

'titleDelete' => '$this->titleSingular . " Delete"';

Tipo: Lectura/Escritura
Valor: Texto

titleHierEdit

Texto a utilizar en la vista de edición de jerarquías y orden.
Este texto será "interpretado" por lo tanto puede utilizar esta cadena:

'titleHierEdit' => '$this->titlePlural . " Hierarchy and Order Editor"';

Tipo: Lectura/Escritura
Valor: Texto

titleIndex

Texto a utilizar en las vistas Index.
Este texto será "interpretado" por lo tanto puede utilizar esta cadena:

'titleIndex' => '$this->titlePlural . " Index"';

Tipo: Lectura/Escritura
Valor: Texto

titleUpdate

Texto a utilizar en las vistas Update.
Este texto será "interpretado" por lo tanto puede utilizar esta cadena:

'titleUpdate' => '$this->titleSingular . " Update"';

Tipo: Lectura/Escritura
Valor: Texto

titleSingular

Texto a utilizar en las vistas de CRUD.

Tipo: Lectura/Escritura
Valor: Texto


Métodos

Nota:
Una Ruta es la relación de los ítems creados según su jerarquía.
Siempre comienza con '/' y el separador es '/'.

ListItems($lng = '')

Parámetros:

  • lng: Texto

Devuelve la lista de ítems creados.
Si el módulo GeMI está instalado, indicando lng devolverá la lista en ese idioma o si se omite, o no está activo, en el idioma de la aplicación.

ListPaths($lng = '')

Lista todas las rutas definidas, en el idioma indicado. Si no se indica, se usará el sourceLanguage.

ListPathsItemsID()

Lista todas las rutas definidas, pero indicando los códigos de los ítems

ListPathsWithItem($item = '', $lng = '')

Parámetros:

  • item: Texto
  • lng: Texto

Lista las rutas que contienen al ítem indicado.
Ruta: relación de los ítems creados según su jerarquía.
Siempre comienza con '/' y el separador es '/'.

Ejemplo:

$RutasConPostre = $InstanciaEJO->ListPathsWithItem('postre', 'es');
array(
  '/Receta/postre/helado',
  '/Receta/postre/caliente',
  '/Receta/postre/frutado',
  '/Receta/menu/postre/helado,
  '/Receta/menu/postre/caliente',
  '/Receta/menu/postre/frutado'
)

Si no se indica el resultado es el mismo que ListPaths

ListPathsIDWithItem($item = '')

Parámetros:

  • item: Texto

Lista las rutas que contienen al ítem indicado.
Ruta: relación de los ítems creados según su jerarquía.
Siempre comienza con '/' y el separador es '/'.

Ejemplo: /Receta/postre/helado

Si no se indica el resultado es el mismo que ListPathsItemsId

En este caso las rutas devueltas utilizarán los ID de los ítems y no su texto descriptivo.

Ejemplo (según resultado ejemplo anterior)

$RutasConPostre = $InstanciaEJO->ListPathsWithIDItem('postre');
array(
  '/1/8/15',
  '/1/8/48',
  '/1/8/22',
  '/1/36/8/15,
  '/1/36/8/48',
  '/1/36/8/22'
)

menuArray

Magic Getter
Devuelve un arreglo para utilizar con CMenu o (preferentemente) EMenu.