Al dia con Drupal 8: Actualizando el módulo humanstxt

La fecha de lanzamiento de Drupal 8 se acerca cada día (o quizás no), y tras el API freeze de Julio, las herramientas del núcleo empiezan a estar relativamente estables, aunque sujetas a bastantes cambios, sobre todo la parte de campos y entidades.

Es el momento de empezar a pensar en actualizar módulos que no requieran un excesivo uso de las nuevas API de entidades y campos. Es el caso del módulo Humans.txt que proporciona un fichero para atribuir y reconocer contribuciones en un determinado proyecto web. Más información y página oficial.

Nuevo fichero info en YAML

Los ficheros .info se han eliminado en favor de un nuevo fichero YAML basado en un componente Symfony, por lo que los nuevos ficheros serán .info.yaml. Para el caso del módulo Humans.txt, el nuevo fichero humanstxt.info.yaml queda como sigue:

name: Humans.txt
type: module
description: 'Generates a humans.txt file dynamically and allows you to edit it.'
package: Other
core: 8.x
configure: admin/config/search/humanstxt

La clave type: module es ahora obligatoria para diferenciar entre módulos, plantillas y perfiles de instalación. Change notice.

Variables como configuración (CMI)

La iniciativa CMI (Configuration Management Initiative) va a cambiar de forma drástica la forma de tratar la configuración en nuestros projectos Drupal. Se han identificado de forma diferenciada las partes de un sitio que son configuración (variables, campos, vistas, etc) y estos elementos ya no son tratados en base de datos sino en ficheros, de nuevo usando el formato YAML. Esto tiene grandes ventajas de cara a mover nuestra configuración de entorno a entorno y desde un punto de vista de código, tiene esta pinta:

En Drupal 7

variable_get('humanstxt_display_link', FALSE);

En Drupal 8

Drupal::config('humanstxt.settings')->get('display_link');

Tanto variable_get() como variable_set() dejan de existir para ser reemplazadas por Drupal::config() tampoco es necesario borrar las variables al desinstalar y variable_del() tampoco existe en Drupal 8. Para actualizar las variables de nuestros módulos, se debe utilizar update_variables_to_config() en un hook_update_N(). Por ejemplo:

function humanstxt_update_8001() {
  update_variables_to_config('humanstxt.settings',array(
    'humanstxt' => 'content',
    'humanstxt_display_link' => 'display_link',
  ));
}

Nota: El nombre de las variables en el nuevo sistema no tiene porque incluir el nombre del módulo ya que está dentro del contexto de la configuración, que sí se debe marcar con el nombre del módulo, en este caso: humanstxt.settings.

Y finalmente, el fichero de configuración, humans.settings.yml, que debe estar en el directorio config del módulo:

content: ''
display_link: FALSE

Nuevo sistema de rutas

Todavía no podemos despedirnos de hook_menu, pero para algunas cosas, como páginas con formularios o algunos listados, se puede utilizar un nuevo sistema de rutas basado en Symfony y ficheros YAML de nuevo. El formulario de configuración del módulo pasa de estar en un fichero admin.inc a ser un plugin declarado a través de un fichero de rutas. El primer paso es definir o modificar una entrada de hook_menu utilizando la entrada route_name.

function humanstxt_menu() {
  $items['admin/config/search/humanstxt'] = array(
    'title' => 'Humanstxt',
    'description' => 'Manage your humans.txt file.',
    'route_name' => 'humanstxt_admin_settings',
  );
  return $items;
}

La entrada en route_name se debe declarar en un fichero routing.yml en la raiz del módulo, por ejemplo humanstxt.routing.yml

humanstxt_admin_settings:
  pattern: '/admin/config/search/humanstxt'
  defaults:
    _form: 'Drupal\humanstxt\Form\HumanstxtAdminSettingsForm'
  requirements:
    _permission: 'administer humans.txt'

Este fichero tiene varias claves posibles, la ruta o pattern, un formulario con la clave _form y con un check de permisos _permission que se declara como habitualmente, con hook_permission.

El formulario definido con la clave _form lo he definido como Drupal\humanstxt\Form\HumanstxtAdminSettingsForm, que según la referencia PSR-0 introducida en Drupal 8, se cargará automáticamente situando el fichero de la clase del formulario en el directorio /lib/Drupal/humanstxt/Form/HumanstxtAdminSettingsForm.php.

namespace Drupal\humanstxt\Form;
use Drupal\system\SystemConfigFormBase;

class HumanstxtAdminSettingsForm extends SystemConfigFormBase {

  public function getFormID() {
    return 'humanstxt_admin_settings';
  }

  public function buildForm(array $form, array &$form_state) {
    $config = $this->configFactory->get('humanstxt.settings');

    $default_value = _humanstxt_get_content();
    if (empty($default_value)) {
      $default_value = <<<VALUE
/* TEAM */
/* SITE */
Tools:Drupal
VALUE;
    }

    $form['humanstxt_content'] = array(
      '#type' => 'textarea',
      '#title' => t('Contents of humans.txt'),
      '#default_value' => $default_value,
      '#cols' => 60,
      '#rows' => 20,
      '#wysiwyg' => FALSE,
    );
    $form['humanstxt_display_link'] = array(
      '#type' => 'checkbox',
      '#title' => t('Display humans.txt in head section as a link.'),
      '#default_value' => $config->get('display_link'),
    );
    return parent::buildForm($form, $form_state);
  }

  public function submitForm(array &$form, array &$form_state) {
    $this->configFactory->get('humanstxt.settings')
      ->set('content', $form_state['values']['humanstxt_content'])
      ->set('display_link', $form_state['values']['humanstxt_display_link'])
      ->save();
    parent::submitForm($form, $form_state);
  }
}

Este nuevo fichero es básicamente el antiguo formulario de configuración convertido a objetos con al menos tres componentes:

  • getFormID: Define el identificador del formulario, tiene que coincidir con el route_name y la clave del fichero de rutas (routing.yml).
  • buildForm: Se construye un formulario "de los de toda la vida" con Form API y se devuelve el array.
  • submitForm: Acciones a realizar cuando se guarda el formulario, en este caso, simplemente guardar las variables de configuración.

Otros cambios menores

Finalmente, he tenido que afrontar algunos otros cambios menores en el API, que en casi todos los casos suponen pequeños cambios de código o estrategia:

  • La opción para las "url limpias" se solía guardar en la configuración en una variable llamada clean_url que ha sido eliminada. Ahora se puede comprobar si las urls limpias se han configurado correctamente a través del objeto request.
    $request = \Drupal::request();
    $request->attributes->get('clean_urls');
  • La función drupal_exit() se ha eliminado. En el caso de este módulo, usar exit de php es suficiente, pero en caso de no serlo, se puede utilizar ServiceUnavailableHttpException para devolver la respuesta deseada.
  • Esta es facil: get_t() desaparece y ahora solo se usa t(). No tiene pérdida.
  • La función system_settings_form es reemplazada por el sistema de formularios mencionado arriba. Más detalles.

Recursos

Comentarios

Buen post. Tendremos que ir poniéndonos al día :)

Muchas gracias por la informacion.
Lo que mas odio de Symfony son sus yml y sus ficheros de configuracion, y ahora tambien en mi amado Drupal no lo puedo creer, algien me puede explicar que ventaja puede traer.

Gran post !!

Un detalle que me he encontrado, con los últimos cambios parece ser que la clase \Drupal\system\SystemConfigFormBase a pasado a ser \Drupal\Core\Form\ConfigFormBase

https://drupal.org/node/2089627

Desde luego que se agradecen aportes como este en la red. Siempre son de muchisima ayuda. Gracias.

Añadir nuevo comentario