Después de desarrollar dos proyectos utilizando CodeIgniter decidí para los nuevos proyectos utilizar Kohana el cual hasta ahora ha sido un cambio agradable desde el punto de vista de una mejor orientación a objetos y el soporte de una comunidad mas dinámica.
Debido a que CI y por supuesto Kohana que es un fork de la primera, separan a las entidades del MVC en directorios por separado: /controllers, /models y /views, me he acostumbrado a crear subdirectorios dentro de ellas para separar los objetos de cada uno de los módulos que componen al sistema de información. Ejemplo: /controllers/admin/perfil.php.
Con CI cargaba los modelos utilizando la siguiente sintáxis:
$this -> load -> model("admin/perfil");
Ahora con Kohana esta sintáxis es obsolota y deben instanciarse los objetos, ya sea con un ámbito local:
$perfil = new Perfil_Model();
O con un ámbito global a todo el controlador.
$this -> perfil = new Perfil_Model();
El problema es que ya no hay forma de especificar el subdirectorio del módulo (no confundir con los módulos de Kohana) que para hechos prácticos de la instanciación del modelo es una cadena de texto.
Estuve revisando la documentación y los foros de Kohana y al parecer aún no hay una solución nativa a esta situación, así que decidí implementar la mia propia que permita la carga modelos en subdirectorios desde cualquier controlador y que hasta la fecha me ha funcionado bien.
Para la implementación de la autenticación que me dispongo a realizar próximamente he definido mi propio controlador base definiendo la clase Controller en application/libraries/MY_Controller.php. Con esto defino los comportamientos generales que tendrán todos los controladores del proyecto.
<?phpdefined('SYSPATH') or die('No direct script access.');
class Controller extends Controller_Core
{publicfunction __construct(){
parent::__construct();
}}?>
A este controlador base le agrego los métodos necesarios para localizar el archivo .php que contiene el modelo que se intenta instanciar y realizo las modificaciones necesarias para incluír esta búsqueda durante la etapa de autocarga de clases (autoload). Los nombres del módulo (del SI), controlador, acción y parámetros son obtenidos en tiempo de ejecución gracias a la facilidad de la clase Router.
El primer método a implementarse es buscarArchivo($directorio, $archivo) el cual se encarga de realizar la búsqueda física y recursiva de $archivo dentro del $directorio especificado.
Se implementa al método auto_load($clase) el cual determina si la clase a cargarse es un modelo debido a la terminación _Model de su nombre de clase, por ahora ignora cualquier otro tipo. En caso de ser un modelo realiza la búsqueda utilizando al método definido anteriormente, el cual en caso de encontrarlo lo incluye para hacerlo disponible al ambiente de ejecución.
Como paso final, en el constructor del Controller se le indica que tome al método auto_load como una de las funciones ejecutadas durante la autocarga de clases.
Gracias a estas modificaciones es posible realizar la creación del objeto new Perfil_Model y el controlador se encargará de realizar la búsqueda y encontrarlo dentro del subdirectorio /models/admin. Sobra hacer notar que para esta solución, la colisión de nombres es un problema ya que se resuelve según sea la clase que se encuentra físicamente primero en el directorio de archivos.
El código fuente del ejemplo descrito puede descargarse del siguiente enlace: MY_Controller.php.
Esta semana encontré algo que me pareció interesante. Es la posibilidad de serializar objetos en Java utilizando un codificador XML. Lo mas interesante se que para realizar esta codificación básica no es necesario de ningún OXM (Object XML Mapper), por el contrario, todo lo necesario viene incluído ya en el J2SE.
Para el ejemplo he creado una clase Worker (POJO) que será serializada y sólo incluye atributos y sus respectivos métodos set/get. Por presentación también sobreescribí al método toString para presentar el contenido del objeto.
A continuación se procede a codificar el objeto y a generar el archivo XML con su contenido.
// Creates the stream to the file that will storage the serialized objectFileOutputStream outputFile = newFileOutputStream("workerman.xml");
// Relates the XML encoder with the output file stream
XMLEncoder xe = new XMLEncoder(outputFile);
// Serializes the selected object using an XML encoding
xe.writeObject(workerman);
// Closes the XML encoder
xe.close();
Terminado este proceso, deberá existir el archivo workerman.xml con la representación XML del objeto workerman creado anteriormente. Esta representación de la información podría ser compartida inclusive con otros sistemas/lenguajes/plataformas diferentes a la actual, cosa que podría tener algunos inconvenientes con la serialización convencional de java.io. El contenido XML (texto plano) probablemente ocupe mas espacio y esto lo haga menos eficiente que una representación binaria.
Por supuesto también es posible realizar el proceso contrario: basados en el archivo workerman.xml con el contenido codificado, obtener la información y crear nuevamente la representación del objeto Worker.
// Creates the stream from the file that storages the already serialized object
inputFile = newFileInputStream("workerman.xml");
// Relates the XML decoder with the input file stream
XMLDecoder xd = new XMLDecoder(inputFile);
// Reads the object from the stream and deserializes it using an XML decoding
clone = (Worker)xd.readObject();
// Closes the XML decoder
xd.close();
El objeto clone deberá contener la misma información que su versión original: workerman.
El contenido del archivo workerman.xml es bastante explícito para su procesamiento en otras plataformas.
Dont feel like home. hes a little out.
And all these words elope. its nothing like your poem.
Putting in. inputting in. dont feel like methadone.
A scratching voice all alone its nothing like your baritone.
Its nothing as it seems. the little that he needs. its home.
The little that he sees. is nothing he concedes. its home.
One uninvited chromosome. a blanket like the ozone.
Its nothing as it seems. all that he needs. its home.
The little that he frees is nothing he believes.
Saving up a sunny day. something maybe two tone.
Anything of his own. a chip off the corner stone.
Whos kidding? rainy day. a one way ticket headstone.
Occupations overthrown. a whisper through a megaphone.
Its nothing as it seems. the little that he needs. its home.
The little that he sees is nothing he concedes. its home.
And all that he frees. a little bittersweet. its home.
Its nothing as it seems. the little that you see its home.
Lo más importante es saber identificar que "el futuro ya ocurrió".
La medida de acierto para la predicción no sólo puede ser la cantidad de hechos que ocurrieron frente a los predecidos, hay que tener en cuenta también la cantidad de hechos que sucedieron y nunca fueron predichos.
Lo importante y distintivo son siempre los cambios en los valores, la percepción y las metas, esto es, cosas que uno puede adivinar, pero no pronosticar.
El trabajo mas importante de un ejecutivo es identificar los cambios que ya han sucedido ("el futuro que ya ocurrió").
El desafio mas importante es utilizar esta información identificada y utilizarla en forma de oportunidades.
Identifique tendencias, analice los cambios evidentes e intente predecir los cambios futuros junto con su impacto.
"Once upon a midnight dreary, while I pondered weak and weary,
Over many a quaint and curious volume of forgotten lore,
While I nodded, nearly napping, suddenly there came a tapping,
As of some one gently rapping, rapping at my chamber door.
`'Tis some visitor,' I muttered, `tapping at my chamber door -
Only this, and nothing more.'
Ah, distinctly I remember it was in the bleak December,
And each separate dying ember wrought its ghost upon the floor.
Eagerly I wished the morrow; - vainly I had sought to borrow
From my books surcease of sorrow - sorrow for the lost Lenore -
For the rare and radiant maiden whom the angels named Lenore -
Nameless here for evermore.
And the silken sad uncertain rustling of each purple curtain
Thrilled me - filled me with fantastic terrors never felt before;
So that now, to still the beating of my heart, I stood repeating
`'Tis some visitor entreating entrance at my chamber door -
Some late visitor entreating entrance at my chamber door; -
This it is, and nothing more,'
Presently my soul grew stronger; hesitating then no longer,
`Sir,' said I, `or Madam, truly your forgiveness I implore;
But the fact is I was napping, and so gently you came rapping,
And so faintly you came tapping, tapping at my chamber door,
That I scarce was sure I heard you' - here I opened wide the door; -
Darkness there, and nothing more.
Deep into that darkness peering, long I stood there wondering, fearing,
Doubting, dreaming dreams no mortal ever dared to dream before
But the silence was unbroken, and the darkness gave no token,
And the only word there spoken was the whispered word, `Lenore!'
This I whispered, and an echo murmured back the word, `Lenore!'
Merely this and nothing more.
Back into the chamber turning, all my soul within me burning,
Soon again I heard a tapping somewhat louder than before.
`Surely,' said I, `surely that is something at my window lattice;
Let me see then, what thereat is, and this mystery explore -
Let my heart be still a moment and this mystery explore; -
'Tis the wind and nothing more!'
Open here I flung the shutter, when, with many a flirt and flutter,
In there stepped a stately raven of the saintly days of yore.
Not the least obeisance made he; not a minute stopped or stayed he;
But, with mien of lord or lady, perched above my chamber door -
Perched upon a bust of Pallas just above my chamber door -
Perched, and sat, and nothing more.
Then this ebony bird beguiling my sad fancy into smiling,
By the grave and stern decorum of the countenance it wore,
`Though thy crest be shorn and shaven, thou,' I said, `art sure no craven.
Ghastly grim and ancient raven wandering from the nightly shore -
Tell me what thy lordly name is on the Night's Plutonian shore!'
Quoth the raven, `Nevermore.'
Much I marvelled this ungainly fowl to hear discourse so plainly,
Though its answer little meaning - little relevancy bore;
For we cannot help agreeing that no living human being
Ever yet was blessed with seeing bird above his chamber door -
Bird or beast above the sculptured bust above his chamber door,
With such name as `Nevermore.'
But the raven, sitting lonely on the placid bust, spoke only,
That one word, as if his soul in that one word he did outpour.
Nothing further then he uttered - not a feather then he fluttered -
Till I scarcely more than muttered `Other friends have flown before -
On the morrow he will leave me, as my hopes have flown before.'
Then the bird said, `Nevermore.'
Startled at the stillness broken by reply so aptly spoken,
`Doubtless,' said I, `what it utters is its only stock and store,
Caught from some unhappy master whom unmerciful disaster
Followed fast and followed faster till his songs one burden bore -
Till the dirges of his hope that melancholy burden bore
Of "Never-nevermore."'
But the raven still beguiling all my sad soul into smiling,
Straight I wheeled a cushioned seat in front of bird and bust and door;
Then, upon the velvet sinking, I betook myself to linking
Fancy unto fancy, thinking what this ominous bird of yore -
What this grim, ungainly, ghastly, gaunt, and ominous bird of yore
Meant in croaking `Nevermore.'
This I sat engaged in guessing, but no syllable expressing
To the fowl whose fiery eyes now burned into my bosom's core;
This and more I sat divining, with my head at ease reclining
On the cushion's velvet lining that the lamp-light gloated o'er,
But whose velvet violet lining with the lamp-light gloating o'er, She shall press, ah, nevermore!
Then, methought, the air grew denser, perfumed from an unseen censer
Swung by Seraphim whose foot-falls tinkled on the tufted floor.
`Wretch,' I cried, `thy God hath lent thee - by these angels he has sent thee
Respite - respite and nepenthe from thy memories of Lenore!
Quaff, oh quaff this kind nepenthe, and forget this lost Lenore!'
Quoth the raven, `Nevermore.'
`Prophet!' said I, `thing of evil! - prophet still, if bird or devil! -
Whether tempter sent, or whether tempest tossed thee here ashore,
Desolate yet all undaunted, on this desert land enchanted -
On this home by horror haunted - tell me truly, I implore -
Is there - is there balm in Gilead? - tell me - tell me, I implore!'
Quoth the raven, `Nevermore.'
`Prophet!' said I, `thing of evil! - prophet still, if bird or devil!
By that Heaven that bends above us - by that God we both adore -
Tell this soul with sorrow laden if, within the distant Aidenn,
It shall clasp a sainted maiden whom the angels named Lenore -
Clasp a rare and radiant maiden, whom the angels named Lenore?'
Quoth the raven, `Nevermore.'
`Be that word our sign of parting, bird or fiend!' I shrieked upstarting -
`Get thee back into the tempest and the Night's Plutonian shore!
Leave no black plume as a token of that lie thy soul hath spoken!
Leave my loneliness unbroken! - quit the bust above my door!
Take thy beak from out my heart, and take thy form from off my door!'
Quoth the raven, `Nevermore.'
And the raven, never flitting, still is sitting, still is sitting
On the pallid bust of Pallas just above my chamber door;
And his eyes have all the seeming of a demon's that is dreaming,
And the lamp-light o'er him streaming throws his shadow on the floor;
And my soul from out that shadow that lies floating on the floor
Shall be lifted - nevermore!"
A pesar de que no he variado los pasos requeridos para realizar la actualización desde artículos anteriores, agregué un paso adicional para remover completamente los módulos de core antígüos y evitar con esto cualquier tipo de incompatibilidad por mezcla de versiones.
Con respecto a los siguientes pasos de actualización se debe tener en cuenta que el directorio donde se ubican los archivos del portal basado en Drupal se encuentran en site localizado en el directorio actual. El paquete con la nueva distribución de Drupal ha sido descargado y copiado también en la ubicación actual.
Al final del proceso de actualización el directorio site contendrá la versión actualizada del sitio y el directorio site.old la copia de seguridad de la versión anterior.
Realizar una copia de seguridad de la base de datos.
Renombrar el sitio actual para conservarlo como una copia de seguridad previa a la actualización.
$ mv site site.old
Descomprimir la última versión de la distribución de Drupal.
$ tar zxvf drupal-5.9.tar.gz
Renombrar el directorio recién extraído para ser el nuevo portal web.
$ mv drupal-5.9/ site
Mueve los módulos de la nueva versión a una ubicación temporal para evitar cualquier tipo de sobreescritura con los módulos antígüos.
$ mv site/modules/ site/modules.new
Restaura los archivos del sitio y de los usuarios.
$ cp -rf site.old/files site
Restaura la información de configuración del sitio.
$ cp -rf site.old/sites site
Restaura los archivos del tema del sitio. Reemplazar MITEMA por el nombre del tema (directorio) a restaurar.
$ cp -rf site.old/themes/MITEMA site/themes/
Restaura la totalidad de los módulos instalados en la versión anterior.
$ cp -rf site.old/modules site
De los módulos recién restaurados remueve los del grupo core para utilizar únicamente las últimas versiones.
Restaura los módulos de core de la última versión.
$ cp -rf site/modules.new/* site/modules
Remueve la copia de seguridad de los módulos de core de la última versión.
$ rm -rf site/modules.new
Ejecute el script de actualización de la base de datos si es necesario.
(web) $URL/apps/site/update.php
Utilizando el módulo update-status verifique si existen módulos con versiones nuevas, suceptibles de ser actualizados.
(web) $URL?q=admin/logs/updates
Actualice los módulos reemplazando sus directorios con las nuevas versiones bajo el directorio /site/modules y ejecute nuevamente el script de actualización de la base de datos.
(web) $URL/apps/site/update.php
Para terminar el proceso de actualización, remueva la copia del paquete de distribución de la última versión de Drupal.