Hero

Como alterar los tipos de elementos de FAPI en Drupal 7

Mayo 30, 2013

enzo
PHP
Programación
Drupal
Desarrollo de Modulos

Amig@s Drupaler@s

Hoy vengo a compartirles unas de esas problemas o requerimientos que te hacen pensar “Por todas las deidades” tengo que “Hackear el Core de Drupal”. El problema en cuestion es cambiar la propiedad ID de los Radio Buttons usados en los formularios de edición de los Tipos de Contenido o en los creados por módulos como en EntityForm y Webform.

Los atributos que se generan para un típico elementos de selección como en que se muestra en la siguiente imagen es controlado por la función form_process_radios y la cual se define dentro del módulo de system en la implementación del hook hook_element_info() en la función system_element_info.

hack the drupal core 0

El HTML generado se muestra a continuación.

<div class="field-type-list-text field-name-temporal field-widget-options-buttons form-wrapper" id="edit-temporal"><div class="form-item form-type-radios form-item-temporal-und">
  <label for="edit-temporal-und">Hack the Drupal Core? <span class="form-required" title="This field is required.">*</span></label>
 <div id="" vm_functions_render_root_terms="" class="form-radios"><div class="form-item form-type-radio form-item-temporal-und">
 <input type="radio" id="edit-temporal-und-never" name="temporal[und]" value="Never" class="form-radio">  <label class="option" for="edit-temporal-und-never">Never </label>

</div>
<div class="form-item form-type-radio form-item-temporal-und">
 <input type="radio" id="edit-temporal-und-sometimes" name="temporal[und]" value="Sometimes" class="form-radio">  <label class="option" for="edit-temporal-und-sometimes">Sometimes </label>

</div>
<div class="form-item form-type-radio form-item-temporal-und">
 <input type="radio" id="edit-temporal-und-are-you-crazy" name="temporal[und]" value="Are you crazy?" class="form-radio">  <label class="option" for="edit-temporal-und-are-you-crazy">Are you crazy? </label>

</div>
</div>
</div>
</div>

Como se puede observar los ids de los radios son de la forma edit-temporal-und-are-you-crazy y en nuestro requerimiento se necesita que sea [field_name]-[radio]-[language]-[option] para poder hacer este trabajo debemos hacer uso del hook hook_element_info_alter() el cual nos permitirá cambiar la definición de la función process para los radios como se muestra en el siguiente código:

function MIMODULO_element_info_alter(&$type) {
 if(isset($type['radios'])) {
  $type['radios']['#process'][0] = '_MIMODULO_form_process_radios';
}

Después de esta modificación para todos los formularios de nuestro Drupal se ejecutara la función _MIMODULO_form_process_radios en la cual podremos hacer todos los cambios que consideremos necesarios, a continuación la implementación de esta función.

function _MIMODULO_form_process_radios($element) {
  if (count($element['#options']) > 0) {
    $weight = 0;
    foreach ($element['#options'] as $key => $choice) {
      // Maintain order of options as defined in #options, in case the element
      // defines custom option sub-elements, but does not define all option
      // sub-elements.
      $weight += 0.001;

      $element += array($key => array());
      // Generate the parents as the autogenerator does, so we will have a
      // unique id for each radio button.
      $parents_for_id = array_merge($element['#parents'], array('radio'), array($key));
      $element[$key] += array(
        '#type' => 'radio',
        '#title' => $choice,
        
        // The key is sanitized in drupal_attributes() during output from the
        // theme function.
        '#return_value' => $key,
        
        // Use default or FALSE. A value of FALSE means that the radio button is
        // not 'checked'.
        '#default_value' => isset($element['#default_value']) ? $element['#default_value'] : FALSE,
        '#attributes' => $element['#attributes'],
        '#parents' => $element['#parents'],
        '#id' => drupal_html_id(implode('-', $parents_for_id)),
        '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
        '#weight' => $weight,
      );
    }
  }
  return $element;
}

El cambio anterior generaría un nuevo HTML como se muestra a continuación.

<div class="form-item form-type-radios form-item-temporal-und">
  <label for="edit-temporal-und">Hack the Drupal Core? <span class="form-required" title="This field is required.">*</span></label>
 <div id="" vm_functions_render_root_terms="" class="form-radios"><div class="form-item form-type-radio form-item-temporal-und">
 <input type="radio" id="temporal-und-radio-never" name="temporal[und]" value="Never" class="form-radio">  <label class="option" for="temporal-und-radio-never">Never </label>

</div>
<div class="form-item form-type-radio form-item-temporal-und">
 <input type="radio" id="temporal-und-radio-sometimes" name="temporal[und]" value="Sometimes" class="form-radio">  <label class="option" for="temporal-und-radio-sometimes">Sometimes </label>

</div>
<div class="form-item form-type-radio form-item-temporal-und">
 <input type="radio" id="temporal-und-radio-are-you-crazy" name="temporal[und]" value="Are you crazy?" class="form-radio">  <label class="option" for="temporal-und-radio-are-you-crazy">Are you crazy? </label>

</div>
</div>
</div>

Es importante resaltar que und es la definición de la constante de Drupal LANGUAGE_NONE que indica que en nuestro sitio no existe algún idioma definido y temporal es el nombre de campo que se ha usado para el ejemplo.

Se deje a la imaginación del lector implementaciones adicionales a esta función o la sobre escrituras de otros elementos de FAPI.

Espero que haya sido de su agrado.

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