Hero

Cómo definir un valor por defecto a un entity reference en Drupal 7

Julio 25, 2013

enzo
Drupal
Desarrollo de Modulos

Las personas que saben algo de diseño de base de datos y del modelo Entidad Relación al llegar a Drupal lo primero que desean hacer es poder relacionar entidades. Afortunadamente la relación de entidades se pude llevar usando el módulo Entity Reference.

Imaginemos que tenemos un sistema que tiene el tipo de contenido producto y que los productos podrían estar relacionados con el tipo de contenido references.

Para hacer este proceso mas integrado es posible usar del módulo Inline Entity Form que nos permitiría en la edición de los nodos producto, enlazar nuestros producto con refereces existentes o crear nuevas references en el mismo formulario como se puede observar en la siguiente imagen.

inline edit form

Todo lo anterior suena muy bien, pero requeriría que todo el trabajo sea hecho por una persona y en el momento de edición del producto.

Si deseáramos que la creación de los nodos de tipo reference sea de carácter contributivo por los usuarios de la aplicación y que cada usuario seleccione a que producto pertenece la referencia, solo debemos hacer uso del modulo Entity Reference y podríamos usar el modo auto completar para hacer el proceso de creación un poco mas fácil.

Pero imaginemos este escenario: Estamos navegando en una página de una entidad producto y creamos un bloque con un enlace que permite a los usuarios agregar nuevas referencias, al ingresar a este enlace tendríamos un formulario funcional tal y como se definió, pero no estamos sacando provecho a la navegación anterior para agilizar la referencia.

A continuación puede observar un código para ejecutar esta acción.

/**
 * Implements hook_form_alter().
 */
function MIMOUDLO_form_alter(&$form, &$form_state, $form_id) {

  if (isset($form['type']) &&  $form['type']['#value'] . '_node_form' == $form_id && $form['type']['#value'] == 'reference') {
    global $language, $base_url;

    //Check if referer exist and if is a local referer
    if(isset($_SERVER['HTTP_REFERER']) && parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) == parse_url($base_url, PHP_URL_HOST) &&
       empty($form['field_related_to'][LANGUAGE_NONE][0]['target_id']['#default_value'])) {

      $path = ltrim(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_PATH),$language->language . '/');
 
      $position = 1;
      if(strstr($path, 'node/')) {
        $item = menu_get_item($path);
      } else if($path != $real_path = drupal_get_normal_path($path)) {
        $item = menu_get_item($real_path);
      }
 
      if($item) {
        $node = $item['map'][$position];
        if(in_array($node->type,array('product'))) {
          $form['field_related_to'][LANGUAGE_NONE][0]['target_id']['#entity_type'] = 'node';
          $form['field_related_to'][LANGUAGE_NONE][0]['target_id']['#entity'] = $node;
          $form['field_related_to'][LANGUAGE_NONE][0]['target_id']['#default_value'] = $node->title . " (" . $node->nid . ')';
        }
      }
    }
  }
}

En el código anterior implementamos el hook_form_alter y en la línea 6 definimos que se ejecute únicamente para el formulario de edición del tipo de contenido preferences.

if (isset($form['type']) &&  $form['type']['#value'] . '_node_form' == $form_id && $form['type']['#value'] == 'reference')

En la línea 10 hacemos una validación para verificar que existe una pagina de referral y que sea una página local de Drupal y si estamos en modo creación para un nodo tipo reference.

if(isset($_SERVER['HTTP_REFERER']) && parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) == parse_url($base_url, PHP_URL_HOST) &&
       empty($form['field_related_to'][LANGUAGE_NONE][0]['target_id']['#default_value']))

En la línea 13 obtenemos la rula relativa de la página anterior, eliminado el dominio y el prefijo de idioma si existe.

$path = ltrim(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_PATH),$language->language . '/');

Posteriormente entre las lineas 16 a 20 se trata de traducir la url en un objeto tipo nodo usando la función menu_get_item.

      if(strstr($path, 'node/')) {
        $item = menu_get_item($path);
      } else if($path != $real_path = drupal_get_normal_path($path)) {
        $item = menu_get_item($real_path);
      }

Para finalizar entre las lineas 22 a 29 determinamos si el nodo anterior es del tipo product, se modifica el formulario para preseleccionar el auto complete con la información de la página recientemente visitada.

if($item) {
        $node = $item['map'][$position];
        if(in_array($node->type,array('candidate','party'))) {
          $form['field_related_to'][LANGUAGE_NONE][0]['target_id']['#entity_type'] = 'node';
          $form['field_related_to'][LANGUAGE_NONE][0]['target_id']['#entity'] = $node;
          $form['field_related_to'][LANGUAGE_NONE][0]['target_id']['#default_value'] = $node->title . " (" . $node->nid . ')';
        }
      }

Espero que haya sido de su agrado.

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