Tutorial: Creación de un field en Drupal 7 mediante Field API (Parte II)

Tutorial: Creación de un field en Drupal 7 mediante Field API (Parte II)

Tutorial: Creación de un field en Drupal 7 mediante Field API (Parte II)

  • Autor: fjavimartin

  • Fecha de Creación: 17/11/2014

  • Categorías:

    • Tutorial,
    • Drupal,
    • Field,
    • Field api

Objetivo

En esta segunda parte del tutorial nuestro objetivo será el siguiente:

  • Añadir un nuevo widget que recogerá todos los campos del formulario dentro de un fieldset.

1. Modificar hook_field_widget_info()

El primer paso será modificar el hook_field_widget_info() para comunicar a drupal la inclusión de un nuevo widget.

/**
 * Implementación del hook_field_widget_info()
 */
function field_doble_texto_field_widget_info() {
  return array(
    'field_doble_texto_widget' => array(
      'label' => t('Campo Doble Texto - Widget'),
      'field types' => array('field_doble_texto'),
    ),
    'field_doble_texto_widget_fieldset' => array(
        'label' => t('Campo Doble Texto - Widget con fieldset'),
        'field types' => array('field_doble_texto'),
    ),
  );
}

2. Modificar el hook_element_info()

Vamos a implementar un formulario nuevo que se cargará cuando seleccionemos este nuevo widget por lo que necesitaremos informar del nuevo tipo e implementar la función encargada de procesarlo.

/**
 * Implementación hook_element_info()
 */
function field_doble_texto_element_info() {
  $elements = array();
  
  $elements['field_doble_texto_widget'] = array(
      '#input' => TRUE,
      '#process' => array('field_doble_texto_widget_process'),
  );
  $elements['field_doble_texto_widget_fieldset'] = array(
      '#input' => TRUE,
      '#process' => array('field_doble_texto_widget_fieldset_process'),
  );
  
  return $elements;
}

/**
 * Implementación de la función que procesa el formulario para el widget field_doble_texto_widget_fieldset
 */
function field_doble_texto_widget_fieldset_process($element, $form_state, $complete_form) {

  $element['fieldset'] = array(
    '#type' => 'fieldset',
    '#title' => t('Field_doble_texto - Fieldset'),
  );
  
  $element['fieldset']['texto1'] = array(
    '#type' => 'textfield',
    '#title' => t('Campo de Texto 1 - Field_doble_Texto'),
    '#prefix' => '<div class="field-doble-texto-texto1">',
    '#default_value' => isset($element['#value']['texto1']) ? $element['#value']['texto1'] : '',
    '#suffix' => '</div>',
    '#maxlength' => 25,
    '#size' => 25,
  );
  
  $element['fieldset']['texto2'] = array(
    '#type' => 'textfield',
    '#title' => t('Campo de Texto 2 - Field_doble_Texto'),
    '#prefix' => '<div class="field-doble-texto-texto2">',
    '#default_value' => isset($element['#value']['texto2']) ? $element['#value']['texto2'] : '',
    '#suffix' => '</div>',
    '#maxlength' => 25,
    '#size' => 25,
  );

  $element['#required'] = FALSE;

  return $element;
}

En la nueva función de proceso incluiremos un fieldset y dentro de él meteremos los campos de texto con los que capturaremos los valores. Como podemos ver en la imagen, el diseño resultante será mucho más limpio y nuestros campos no quedarán “sueltos”.

Imagen 1 – Widget para field_doble_texto con fieldset

Imagen 1 – Widget para field_doble_texto con fieldset

3. Implementación del hook_field_presave()

Hasta ahora toda la parte en la que guardamos datos en la base de datos ha sido transparente, prácticamente como por arte de magia el contenido de los campos de texto que teníamos en nuestro widget se ha guardado y no hemos tenido que hacer casi nada, pero ahora la cosa cambia.

Field API no entiende de arrays anidados, es decir, no entiende de textfield dentro fieldset por lo que tenemos que pasarle los datos “planos” para que pueda guardarlos en la base de datos.

Aquí es donde entra en escena el hook_field_presave(). Se ejecuta justo antes de guardar el valor de $items en la base de datos y será cuando cambiemos la forma de esta variable que recibimos por referencia.

/**
 * Implementación del hook_field_presave()
 */
function field_doble_texto_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
  switch($instance['widget']['type']) {
    case 'field_doble_texto_widget_fieldset':
      foreach ($items as $delta => &$item) {
        $new_item = array();
        $new_item['texto1'] = $item['fieldset']['texto1'];
        $new_item['texto2'] = $item['fieldset']['texto2'];
        $item = $new_item;
      }
      break;
  }
}

El array $items en la primera parte del tutorial se parecía a esto:

$items = Array (
	'0' => Array(
		'texto1' => 'valor1',
		'texto2' => 'valor2',
		),
	),
);

Ahora se parecerá más a esto:

$items = Array (
	'0' => Array(
		'fieldset' => Array (
			'texto1' => 'valor1',
			'texto2' => 'valor2',
			),
		),
	),
);

En este hook lo que hacemos es reconstruir el array $items poniendo los valores contenidos dentro del array fieldset en el primer nivel.

Para el caso en el que quisiéramos incluir un nuevo fieldset dentro del fieldset que ya tenemos declarado tendríamos que tenerlo en cuenta para hacer los valores de nuestro widget “planos”.

A tener en cuenta que si para depurar el código estáis utilizando entradas del tipo:

print '<pre>';
print_r ($items, TRUE);
print '</pre>; 

drupal no mostrará ningún mensaje, no me preguntéis el motivo. La única manera de depurar, al menos este hook, será mediante la utilización de drupal_set_message(print_r($items, TRUE));.

Conclusiones

Después de las dos partes de este tutorial deberíais ser capaces de implementar cualquier tipo de field mediante la field API de drupal.

Poder implementar varios widget/formatter para cada field nos permitirá una gran versatilidad y control sobre los contenidos que grabamos en drupal.

Espero que hayáis disfrutado del tutorial. Compartirlo si os ha resultado interesante y dejar cualquier comentario sobre lo que no os haya gustado u os haya costado entender.

Podréis acceder a la primera parte de este tutorial pinchando aquí.

Las fuentes utilizadas para elaborar este tutorial:

Todos los Derechos Reservados © 2016

Funciona con Drupal