Hero

Como alterar un field widget para taxonomías en Drupal 7

Mayo 07, 2013

kenneth
APIs
Drupal
Desarrollo de Modulos
Field API

Cuando trabajamos con taxonomías en Drupa estas se pueden agregar a cualquier Tipo de Contenido usando el campo ”term references” para de esta manera lograr categorizar el contenido.

Los campos del tipo ”term reference” deben utilizar un widget para mostrar los datos de la taxonomía, algunos de los widget existentes en Drupal se muestran en la siguiente imagen:

widgets term reference

Estos widgets nos dan la flexibilidad de mostrar la información con cierto formato predefinido.

Sin embargo cuando se trata de poder definir las opciones permitidas que puede contener este widget en algunos casos las opciones existentes no son suficientes, por ejemplo si tenemos el siguiente caso de uso:

“Es requerido indicar en los campos del tipo ‘term reference’ para el widget de ‘Check boxes/radio buttons’ la opción de poder mostrar únicamente los términos que pertenecen al nivel superior (términos padres) en una taxonomía de multi-nivel”.

Para llevar a cabo esta tarea debemos pensar en agregar un funcionamiento extra al widget para que el usuario final decida cuando mostrar únicamente los términos padres.

A continuación presentare una solución a este problema.

  1. Implementar hook_FORM_ID_alter.

Primero debemos implementar en nuestro modulo_personalizado el hook_FORM_ID_alter sobre el formulario: field_ui_field_edit_form para poder agregar la opción nueva y ofrecer la posibilidad de mostrar únicamente los términos padres, a continuación se muestra el código:

function modulo_personalizado_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
  $field = $form['#field'];
  $instance = $form['#instance'];

  if ($field['type'] == 'taxonomy_term_reference' && $instance['widget']['type'] == 'options_buttons') {

    $form['instance']['widget']['settings']['render_root_terms'] = array(
      '#type' => 'checkbox',
      '#title' => t('Only render parent terms'),
      '#default_value' => isset($instance['widget']['settings']['render_root_terms']) ? $instance['widget']['settings']['render_root_terms'] : FALSE,
      '#description' => t('This option overwrites the behavior and will print only the terms that are defined as parent root.'),
    );
  }
}

Con esta definición podemos observar en nuestro formulario de edición del campo la nueva opción para poder renderizar los términos padres y donde ya se han incluido las traducciones a los textos.

render only parents

  1. Implementar hook_field_widget_info_alter.

Ahora debemos agregar una opción mas a la configuración de los widgets que son del tipo “Check boxes/radio buttons’ en su definición, para esto utilizaremos el hook_field_widget_info_alter, el código implementado seria el siguiente:

function modulo_personalizado_field_widget_info_alter(&$info) {
  if (isset($info['options_buttons']['settings'])) {
    $info['options_buttons']['settings'] += array(
      'render_root_terms' => FALSE,
    );
  }
}

Una vez hecho esto, nuestras instancias de campos que utilicen este tipo de widget en particular podrán almacenar el valor que se le configure en la opción de “Renderizar términos padres”.

  1. Implementar hook_field_widget_form_alter

Para finalizar, solamente resta sobrescribir el comportamiento del widget mediante el hook_field_widget_form_alter, en esta implementación utilizaremos una función llamada “modulo_personalizado_retrieve_root_terms” la cual nos retornara únicamente los términos padres, para poder agregarlos como las opciones permitidas al widget, la implementación se vera de la siguiente manera:

function modulo_personalizado_field_widget_form_alter(&$element, &$form_state, $context) {
  $field = $context['field'];
  $instance = $context['instance'];

  if (!empty($instance['widget']['settings']['render_root_terms'])) {
    $options = modulo_personalizado_retrieve_root_terms($field);
    if (isset($element['#options']['_none'])) {
      $options = array('_none' => $element['#options']['_none']) + $options;
    }
    $element['#options'] = $options;
  }
}

function modulo_personalizado_retrieve_root_terms($field) {
  $options = array();
  foreach ($field['settings']['allowed_values'] as $tree) {
    if ($vocabulary = taxonomy_vocabulary_machine_name_load($tree['vocabulary'])) {
      if ($terms = taxonomy_get_tree($vocabulary->vid, 0, 1)) {
        foreach ($terms as $term) {
          if ($term->depth == 0) {
            $options[$term->tid] = $term->name;
          }
        }
      }
    }
  }
  return $options;
}

Espero que les sea de mucha ayuda, y eventualmente logren extender las configuración de algún widget en particular,

Saludos,

Recibe consejos y oportunidades de trabajo 100% remotas y en dólares de weKnow Inc.