Pedro Peláez | 24 marzo 2014 | Comentarios (0)
Drupal 8 instalador

Instalación

El proceso de instalación de Drupal ha llegado a un punto en el que es trivial, cualquiera que preste atención a los mensajes en el navegador puede hacer una instalación satisfactoria.

El objetivo de este artículo no es instalar Drupal 8, si no saber qué hace la instalación “por dentro”, diseccionaremos el código de la versión Alpha 10 de Drupal 8. Esto, que en principio parece poco necesario, nos dará una primera toma de contacto con el nuevo modelo y nos permitirá responder al porqué de la forma de hacer las cosas cuando nuestra web esté funcionando. Ni decir tiene que una versión Alpha de una aplicación no debe ponerse en producción, al público, ya que al salir una nueva versión alpha o pasar a beta pueden descartarse mecanismos internos o añadirse nuevos que hagan de la versión que estamos usando una ruta sin salida.

El asistente de instalación

Antes de empezar debemos conocer el asistente de instalación, los pasos que sigue, para luego buscar esos pasos en el código y tener un objetivo inicial de estudio.

Como para pruebas se suelen usar máquinas virtuales con escasos recursos o equipos viejos, al menos esa es mi costumbre, a la hora de configurar las traducciones el nuevo instalador de Drupal 8 falla por un consumo excesivo de tiempo de ejecución, tarda más de 30s en cargar las traducciones. Para solucionarlo tenemos dos opciones: Usar una maquina más potente o bien hacer un pequeño cambio en el instalador. En el archivo \core\install.php podemos añadir un límite infinito de tiempo de ejecución, en principio en cualquier parte del archivo, aunque yo lo puse en la línea 30. (El limite se configura con “set_time_limit(0);”)

Os dejo una serie de capturas de pantalla del instalador (ya parcheado):

1.- Choose language   Drupal

2.- Seleccionar un perfil de instalación   Drupal

3.- Configuración de la base de datos   Drupal

4.- Installing Drupal   Drupal

Aquí es en donde suele fallar si nuestro servidor está muy saturado o tenemos pocos recursos

5.- Traducciones actualizadas.   Drupal

6.- Configurar sitio   Drupal

7.- Actualizando configuración de traducciones   Drupal

8.- Instalación de Drupal completa   Drupal

Para más información sobre cómo preparar el sistema para hacer la instalación, cosas como crear la base de datos, instalar apache/nginx, etc preguntando a Google o Bing encontraremos mil y un tutoriales.

La instalación por dentro

Prerrequisitos:

  • Conocer algo de PHP y poder cambiar de contexto “mental” rápidamente
  • Un nivel aceptable en comprensión de inglés escrito.
  • Tener el código fuente de Drupal 8 Alpha 10
  • Tener un buen entorno de desarrollo para PHP, personalmente uso Netbeans.

Cabe señalar que para seguir este ejercicio lo mejor será tener el entorno de desarrollo abierto e ir saltando según se indica de unos archivos a otros, trataré de no dejar mucho en el aire.

Vamos al grano, hemos copiado los archivos a su lugar correcto en el servidor y hemos apuntado el navegador al nuevo sitio. Y… magia nos aparece el instalador. ¿Por qué? ¿Cómo sabe que no está instalado?

Bueno, la configuración por defecto de nuestro servidor web, sea apache o cualquier otro, debe apuntar a una página inicial. Normalmente es index.html o index.php así que podemos suponer que pase lo que pase ocurrirá en dichos archivos.

Al abrir el archivo \index.php de Drupal lo primero que vemos son dos importaciones de código seguidas de una llamada a un manejador de peticiones encapsulado dentro de un capturador de errores, try/catch.

Haciendo un seguimiento de llamadas de ambas librerías en el orden en el que son cargadas podemos llegar al punto donde se lanza el instalador. Claro que también podemos probar suerte usando el buscador de nuestro IDE. Probaremos buscando “install.php” ya que es el script al que llegamos al entrar en la web por primera vez, y hay suerte, ya que nos encontramos con esa redirección en el archivo bootstrap.inc, importado en el segundo comando de index.php.

Nota: Considero que estoy en un script cuando en la dirección del navegador, la URL, aparece dicho script. Hay excepciones, si tenemos activo un módulo de reescritura de URLs como mod_rewrite no será tan directo y tendremos un problema jeje pero en el instalador no se hace uso de esto, así que el problema será de otro.

¿Nos sirve este truquillo? Echemos un vistazo a lo que hay delante de la llamada. Ahora vemos la importancia de un código bien comentado, Drupal está muy documentado directamente en el código, lo que

nos facilita hacer modificaciones y buscar soluciones con mucho menos esfuerzo.

Lo primero que encontramos en el método que termina llamando al instalador es una inicialización del entorno, y si echamos un vistacillo en este método veremos que lo que hace es configurar el servidor web de manera uniforme. Este sería un buen sitio para situar el parche al instalador que hicimos antes, pero como dejar sin límite de ejecución a PHP podría bloquear nuestro servidor mejor lo dejamos solo en el instalador.

Siguiendo con lo que estábamos, lo siguiente es comprobar si se trata de un sitio de pruebas, los famosos test cases, y como no es nuestro caso suponemos que esa comprobación pasa como falsa y se ejecuta la línea 1587 de bootstrap.php (no te pierdas, no nos hemos movido del sitio)

La siguiente línea a ejecutar parece ser la inicialización de la configuración, línea 1591. Cotilleemos un poco, se crean las variables globales y se inicializan los arrays, arreglos o matrices, de configuración. Luego comprueba si el archivo de configuración, “settings.php”, es legible para cargarlo en caso afirmativo y luego crea el objeto de configuraciones, por la forma en la que es creado apostaría por un patrón singleton. <[\core\includes\bootstrap.inc:422] new Settings($settings);>

Si vamos al directorio de configuración por defecto de Drupal, \sites\default\, veremos que el archivo que intenta cargar no existe por lo que la configuración que tendremos en nuestro Drupal hasta este punto será un array vacío.

Volviendo al método que llamaba a la instalación, línea 1592, vemos una inicialización de la petición, al ir a ver qué hace lo primero que encontramos es una nota @todo en la cabecera del método indicando que esto debe cambiarse en la versión final de Drupal. Por lo demás no es otra cosa que inicializaciones de rutas y protocolos, seguimos a lo nuestro, vamos a la siguiente línea, 1595, el cargador de clases.

Este cargador de clases prepara el entorno de ejecución para la carga de las clases cuando sean necesarias. Si leemos con atención los comentarios hay algo que llama la atención: hace referencia al caché APC, mmm interesante… Vamos a mirar el archivo de configuración settings.php. Premio, en la línea 403 encontramos una referencia a APC y al cargador de clases, resulta que Drupal 8 puede usar APC para acelerar considerablemente la carga de código por demanda pero por defecto lo trae desactivado, supongo que por compatibilidad y por qué es una versión alpha, en desarrollo. (¿Lo habrán tenido en cuenta las comparativas que dicen que esta versión será más lenta?).

Nota: Solo por esto nos ha merecido la pena el ejercicio, pero sigamos…

Linea 1598, ¿Un timer!!? Indaguemos, esto es raro de ver en PHP… “Bicheando” el archivo \core\lib\Drupal\Component\Utility\Timer.php podemos ver que está guardando información sobre el momento en el que empieza la ejecución, supongo que para luego restarlo al tiempo en el que termina y poder mostrar el tiempo total consumido en ejecutar. Aunque los recursos consumidos son mínimos creo que sería más eficiente no hacerlo a no ser que estuviéramos en una configuración con depuración activa (con millones de usuarios haciendo peticiones se desperdicia mucho tiempo y recursos con esto).

Puntos negativos aparte ;) seguimos. Lo siguiente es verificar el juego de caracteres en uso, al echar un ojo vemos que es poca cosa.

Las siguientes dos líneas, 1604 y 1605, hacen que Drupal tome el control sobre la respuesta a errores de código, lo que le da la capacidad de guardar en el log los errores de ejecución PHP para ayudar a crear módulos y cosas semejantes.

Y llegamos a lo que estábamos buscando, la llamada al instalador. Se comprueba si existe la variable global $databases y si está vacía, ya que existir existe, y no estamos instalando se lanza la instalación.

Para conocer como detecta que no está en un proceso de instalación habrá que mirar dentro de los métodos drupal_installation_attempted() y drupal_is_cli() a los que hace referencia.

En el primer método tan solo comprueba que exista la variable global $install_state y de existir que el array de control de estado este vacío, Línea 1894 de bootstrap.inc.

El segundo método solo comprueba que se esté llamando a Drupal desde una línea de comandos, no tendría sentido mostrar el instalador en HTML en ese caso, línea 2295.

Así que sabe que no está instalado por que no hay definida ninguna base de datos, es igual si de haberla es correcta o no, tan solo se consulta que no haya ninguna, que el array este vacío.

El ciclo de instalación

Ya estamos en el instalador de Drupal 8, ¿y “eso” cómo funciona? Para responder vamos a mirar dentro del archivo \core\install.php que es donde nos ha mandado.

Lo primero de todo es cambiar el directorio de trabajo de PHP a la raíz de Drupal, así se evita tener que hacer complejas búsquedas de archivos, tan solo debe considerarse en todo Drupal que estamos en el raíz y dar la ruta relativa a lo que queremos abrir. A continuación cambiamos el modo de mantenimiento a “install”, dejando constancia de esta manera que estamos en el instalador.

Se verifica que se usa PHP 5.4.2, como mínimo, y si es así cargamos el núcleo del instalador y lo lanzamos, línea 33.

Abrimos \core\includes\install.core.inc y vemos que lo que se hace nada más cargar es pedir multitud de clases y librerías y definir algunas constantes.

En la línea 85 encontramos el método llamado para lanzar el instalador, el cual espera un array de configuraciones, para otro tipo de instalaciones que no vienen al caso, e inicializa variables de estado y configuración.

A continuación inicia el procesado de la petición actual, la cual dependerá del estado en el que se encuentre el instalador y lo ejecuta en la siguiente línea, install_run_tasks(..).

Si seguimos las llamadas de este método llegaremos al array donde se definen todas las tareas de instalación, método install_tasks(…).

En la línea 645 vemos la estructura de este array, en ella se define como clave el nombre del método al que llamar para la tarea. No lo dice por ningún sitio, pero si nuestro IDE nos muestra la estructura del código no tardaremos mucho en darnos cuenta que esas claves coinciden con métodos definidos en el mismo archivo que estamos analizando, curioso cómo se han centrado en informar que las tareas pueden añadirse dinámicamente y han olvidado el detallito de los métodos como claves. Luego aprovecharemos este detalle para “trastear” cada paso sin complicarnos con una traza muy profunda, iremos a tiro hecho.

Ya tenemos lo que se hace en cada caso, pero en el mismo método vemos que hay más. Justo después del array de tareas aparece la llamada al hook de los profiles, exactamente la llamada al hook se hace en la línea 706 y el resultado se añade al array de tareas a continuación.

Luego, línea 714, se añaden las tareas finales del instalador que son las de traducción y la finalización del proceso de instalación.

Una vez el array de tareas parece completo se llama al hook _install_tasks_alter para que el profile pueda modificar todo el proceso a su antojo, línea 738.

Para terminar se repasa el array de tareas añadiendo los valores por defecto que no se hayan definido y se devuelve el resultado al flujo de ejecución.

Ahora sigamos en install_drupal(), línea 117 de install_core.inc. En esta línea se comprueba si se ha terminado de instalar y en caso afirmativo se borra la variable global que lo indica permitiendo de este modo que la web se ejecute normalmente.

Cuando estábamos buscando el array de tareas pasamos por el metodo “install_run_tasks()”, línea 463 de install.core.inc, y saltamos al siguiente método en su primera línea. Si seguimos mirando línea a línea veremos que hace algunas transformaciones y luego llamada a install_run_task(), en la línea 477, pasándole como parámetro una tarea del array de tareas.

Si la seguimos vemos que en caso de que el tipo de tarea sea un formulario se hace pasar por alguna suerte de controlador, línea 515, y en caso de ser una tarea apilada se ejecuta en 522. No seguiremos esta ruta de ejecución y vamos a pasar a ver cada una de las tareas por defecto, a ver que hacen. (Lo dejo en la curiosidad de cada uno que siga profundizando)

Elegir un idioma [Línea 1408 de install.core.inc]

Tal como indican en los comentarios de este método se seleccionará el lenguaje usado para la instalación.

Para ello lo primero que se hace es localizar todos los archivos de traducción disponibles y añadirlos a los ya conocidos, el proceso inicial de instalación ya carga algunos al empezar.

Si no hay ningún idioma seleccionado se selecciona uno por defecto según los lenguajes disponibles para a continuación verificar si hay un código de idioma entre los parámetros. De no ser así se muestra el formulario de selección de idioma.

Solo estoy comentando sobre la instalación interactiva, con el asistente, y en este modo solo tenemos dos pasos: Mostrar el formulario y aplicar la selección del usuario. En el modo interactivo si solo dejamos un idioma será el que se use para instalar.

Elegir perfil [Línea 1227 de install.core.inc]

Lo primero de todo es comprobar que haya un profile ya definido en la configuración de instalación y lo segundo, en caso de que no haya uno seleccionado, es comprobar si hay alguno que poder elegir, en caso contrario error al canto, pero supongamos que si lo hay.

A continuación intentamos seleccionar un profile por defecto llamando, y asignando

en la misma condicional cosa muy fea y de poco estilo, a _install_select_profile(..). En este método si tan solo se detecta un profile lo selecciona, si no si ya había uno seleccionado lo devuelve como el selecto.

Si nada de esto es cierto, o posible, se recorren todos los profiles conocidos en busca de uno del tipo “distribución” y de encontrarse se seleccionará, línea 1281. Notar que si existen dos o más profiles de distribución solo se podrá ejecutar el primero que se encuentre.

Volviendo a la línea 1234, la que tenía poco estilo, decir que esta línea aprovecha la conversión a boolean que hace PHP para saltarse la selección por defecto si la respuesta del método _install_select_profile(..) es una cadena vacía. Dado ese caso, lo más común, la instalación falla en modo desatendido y en nuestro caso se muestra el formulario de selección de profile, perfiles de instalación.

Por cierto, el directorio de profiles por defecto de Drupal 8 es \core\profiles\

Configurar base de datos [Línea 1032 de install.core.inc]

Este método es de los pasos más importantes en Drupal, ya que la base de datos es vital para esta aplicación. Además en este paso se crea el archivo de configuración de nuestra web.

En primer lugar lo que hace es crear la ruta al mencionado archivo de configuración y guardarla en $settings_file, línea 1036. Luego lo pasará como campo oculto en el formulario al manejador del formulario, método install_settings_form_submit indicado en la línea 1102 del array del formulario.

Curiosamente se obliga a que MySQL sea la primera opción de la lista, si está disponible, en el método llamado en la línea 1040, para determinar las bases de datos que se pueden escoger.

El método para la tarea de configuración de la base de datos no deja de ser un formulario de la Form API de Drupal, no hay mucho más que ver aquí pero vamos a ver un poco que pasa al procesar el formulario, a ver que encontramos…

El método install_settings_form_submit(..) se define en la línea 1179 de install.core.inc y en él se definen valores por defecto, la clave hash que viene a ser como sal en una herida abierta para los mal intencionados, se escribe, por fin, el archivo de configuración y se verifica que la tarea quedó como “dios manda”, ósea con Drupal preparado para instalarse y sin pisar una instalación ya existente, para eso está el actualizador. Parece que no se haga nada fuera de lo normal, seguimos…

Instalar sitio [Línea 1793 de install.core.inc]

Llegados a este punto se instalarán todos los módulos necesarios para el profile indicado, recordemos que siempre hay uno seleccionado. Este proceso se hace mediante una pila de tareas y hay poco que ver, aunque si hay algo donde indagar. En la línea 1832 se indica un método de respuesta al terminar, vamos a echarle un ojo.

Nos lo encontramos en la línea 2080 y al parecer tan solo borra la caché, poca chicha :D Tarea para el lector: ver cómo funcionan esto de borrar la caché para tener acceso completo a los módulos (adelanto, como las configuraciones de los módulos esta en caché si no se borra es como si los módulos no estuviesen instalados, una mala pasada de la caché, lo sé pero…, es un mal necesario o Drupal necesitaría superservidores para funcionar)

Configurar traducciones [Línea 1846 de install.core.inc]

Este punto, a mi entender, se ha vuelto conflictivo en Drupal 8. Al hacerse un tratamiento exhaustivo de las traducciones se ha alargado mucho el tiempo necesario para ejecutarlo y en servidores modestos esto impide una instalación “limpia”, si bien es verdad que aunque pueda producirse un error en este punto esto no afecta a la instalación, recargando la página el proceso continua como si se hubiera completado con éxito, aunque seguro que algo no quedo bien del todo.

Vamos a ver el código, a ver que nos cuenta.

Lo primero es incluir el código /../modules/locale/locale.bulk.inc y cómo podemos ver en su cabecera lo que hace es importar masivamente archivos .po, los de traducción.

A continuación se verifican ciertas configuraciones por defecto y si el idioma no es Ingles se da orden de procesado en masa de las traducciones. Si profundizamos llegaremos a ver que las cadenas de traducción acaban en la base de datos donde será más fácil su recuperación.

Configurar sitio [Línea 1933 de install.core.inc]

Ahora se comprueba el archivo de configuración, llegados a este punto debe existir sí o sí. Si tiene permisos de escritura se avisa al usuario.

Luego se hace algunas pre configuraciones del formulario y se llama al método _install_configure_form(..), línea 2437, para que termine de preparar el formulario y lo presente al usuario. Una vez este lo rellena y envía se verifica de la manera normal en la Form API. En la cabecera del método se nos avisa que revisemos tres métodos más: install_configure_form(), install_configure_form_validate() y install_configure_form_submit().

El primero es el que estamos analizando de la tarea “configurar sitio”. El segundo tan solo verifica el nombre de usuario, de esa manera tan fea de asignar en la misma condición. Si no hay nombre falla. Y por último el método install_configure_form_submit() cuya tarea es guardar las configuraciones y crear el tan necesario y famoso usuario 1 de Drupal, además lo hace el usuario activo y le inicia sesión (línea 2590), por eso cuando termina el proceso de instalación no tenemos que iniciar sesión.

Terminar traducciones [Línea 1984 de install.core.inc]

En este paso de finalización se verifica que estén cargadas las traducciones de los módulos y demás artefactos que necesiten traducción y no se haya hecho al principio, estos elementos que pueden necesitar traducción son llamados proyectos.

Un dato curioso es que en este proceso el modulo, del core, “Update” debe estar activo para que pase algo y si no es el caso simplemente se informa que no hay nada más que traducir, en lugar de avisar con un error. Me resulta curioso porque en Drupal 7 este módulo, creo recordar, que no se activa en el profile por defecto, si es el mismo caso el paso que nos ocupa no haría nada.

modulo update

Y parece que no se activa, o se nos pasó algo o este paso no hace nada. Se me ocurre que el modulo se active durante la instalación y luego se desactive. En cualquier caso es bueno tenerlo en marcha.

Traducir configuración [Línea 2011 de install.core.inc]

En este paso se actualizan los nombres de las traducciones. ¿?¿? Haciendo saltos como un canguro por el código pasamos por varias llamadas consecutivas, hay pocos comentarios y pocas líneas:

Línea 649 de locale.bulk.inc, donde en 652 llama a locale_config_batch_build situado en 673. Ahí se configura la pila de proceso haciendo referencia al método locale_config_batch_refresh_name como ejecutor de paso. Este método lo encontramos en la línea 717 del mismo archivo. En él se pide una actualización en masa para luego ir asignándolo uno a uno. Esa actualización se hace en locale_config_update_multiple, encontrado en la línea 764 del mismo archivo, y allí se toma la lista de idiomas y se guardan las traducciones para cada uno si hay una traducción, en caso contrario se borra.

Resumiendo se quitan las cadenas que no están traducidas de la lista para reducir su tamaño. (No me gusta mucho esta conclusión, si alguien se anima a puntualizar…)

Terminado [Línea 2025 de install.core.inc]

Hemos llegado al final del camino sin muchos contratiempos y Drupal nos informa que todo fue bien y la web esta lista, pero… ¿habrá algo más detrás de tan pacifico mensaje?

Antes de salir este mensaje se cambia el peso del módulo profile, pasa a ser el último a cargar, se borra la cache en la línea 2034 y se prepara el mensaje a mostrar.

Además se ejecuta Cron, el proceso de fondo, y se guarda una copia de las configuraciones, intuyo que se trata de las configuraciones de los módulos. Y para acabar del todo se devuelve un pequeño array informativo.

Y eso es todo el proceso de instalación, espero no haber sido demasiado espeso en la exposición.

Comments are closed.

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR