You are here

function entityreference_view_widget_field_widget_form in Entity Reference View Widget 7

Same name and namespace in other branches
  1. 7.2 entityreference_view_widget.module \entityreference_view_widget_field_widget_form()

Implements hook_field_widget_form().

File

./entityreference_view_widget.module, line 179

Code

function entityreference_view_widget_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $field_name = $field['field_name'];
  $field_language = $element['#language'];
  $entity_type = $field['settings']['target_type'];
  $widget = $instance['widget'];

  // The view hasn't been selected yet, abort.
  if (empty($widget['settings']['view'])) {
    return;
  }

  // Only fields with unlimited cardinality are supported at the moment.
  if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED) {
    drupal_set_message(t("The widget for field %field won't be displayed because it only supports fields with unlimited cardinality.", array(
      '%field' => $instance['label'],
    )), 'error');
    return;
  }

  // Load the items for form rebuilds from the field state as they might not be
  // in $form_state['values'] because of validation limitations. Also, they are
  // only passed in as $items when editing existing entities.
  $field_state = field_form_get_state($element['#field_parents'], $field['field_name'], $langcode, $form_state);
  if (isset($field_state['items'])) {
    $items = $field_state['items'];
  }
  $selected_entity_ids = array();
  foreach ($items as $item) {
    $selected_entity_ids[] = $item['target_id'];
  }

  // First build the view used for selecting items.
  $target_view = explode('|', $widget['settings']['view']);
  $view = views_get_view($target_view[0]);
  $view
    ->set_display($target_view[1]);

  // If the widget has been rebuilt via #ajax, change the exposed filter and
  // pager values, if needed.
  $ajax = isset($form_state['values'][$field_name][$field_language]);
  if ($ajax) {
    $values = $form_state['values'][$field_name];

    // Set exposed_raw_input and exposed_data just like views_exposed_form_submit() does.
    if (!empty($values['exposed_filters'])) {
      $exposed_input = $values['exposed_filters'];
      $view->exposed_raw_input = $exposed_input;
      $view->exposed_data = $exposed_input;

      // Also set exposed_input, to prevent get_exposed_input() from using the
      // previous outdated values
      unset($exposed_input['submit']);
      $view->exposed_input = $exposed_input;
    }

    // Only change the page if the rebuild wasn't triggered by an exposed filter,
    // and the page param is properly formatted.
    if (isset($values['page']) && is_numeric($values['page']) && empty($form_state['triggering_element']['#exposed_filter'])) {
      $view
        ->set_current_page($values['page']);
    }
  }

  // Pass the selected entity ids as the first argument, if needed.
  if (!empty($selected_entity_ids) && !empty($widget['settings']['pass_argument'])) {
    $arguments = array();
    $arguments[0] = implode(',', $selected_entity_ids);
    $view
      ->set_arguments($arguments);
  }

  // Display errors here if there is no full page build.
  $output = $ajax ? theme('status_messages') : '';
  $output .= $view
    ->preview($target_view[1]);
  $element += array(
    '#element_validate' => array(
      'entityreference_view_widget_validate',
    ),
    '#theme' => 'widget',
    '#theme_wrappers' => array(
      'fieldset',
    ),
    '#attributes' => array(
      'class' => array(
        'entityreference-view-widget',
      ),
    ),
  );
  $element['#attached']['css'][] = drupal_get_path('module', 'entityreference_view_widget') . '/entityreference_view_widget.css';
  $element['#attached']['js'][] = drupal_get_path('module', 'entityreference_view_widget') . '/entityreference_view_widget.js';

  // Add the rendered view and the exposed filters form.
  $element['view'] = array(
    '#markup' => $output,
  );
  if (!empty($view->exposed_widgets)) {
    $element['filters'] = entityreference_view_widget_prepare_filters($view->exposed_widgets, $field_name);
  }

  // Add a hidden form element to hold the current pager value.
  $element['page'] = array(
    // Set the parents above $field_language, so that the value doesn't get wiped
    // in entityreference_view_widget_validate.
    '#parents' => array(
      $field_name,
      'page',
    ),
    '#type' => 'hidden',
    '#attributes' => array(
      'class' => array(
        'entityreference-view-widget-page',
      ),
    ),
    '#default_value' => 0,
  );

  // In order to have #ajax-ified pagers, we do a horrible thing here: a hidden
  // #ajax button is added, then when a pager link is clicked, a piece of JS code
  // sets the hidden page field (defined above) and simulates a click of the
  // button (defined below).
  $element['pager_submit'] = array(
    '#type' => 'button',
    '#name' => 'pager_submit',
    '#attributes' => array(
      'class' => array(
        'pager-submit',
      ),
    ),
    '#ajax' => array(
      'path' => 'entityreference_view_widget/ajax/' . $field_name,
      'wrapper' => 'edit-' . str_replace('_', '-', $field_name),
      'method' => 'replace',
      'progress' => array(
        'type' => 'throbber',
        'message' => '',
      ),
    ),
    '#limit_validation_errors' => array(
      array(
        $field_name,
      ),
    ),
    '#weight' => 100,
    '#submit' => array(
      'entityreference_view_widget_exposed_filters_pager_submit',
    ),
  );
  if (!$view->display_handler->options['hide_left']) {

    // Add a list of selected items (each item is a full rendered entity).
    if (!empty($selected_entity_ids)) {
      $selected_entities = entity_load($entity_type, $selected_entity_ids);
      $entity_view = entity_view($entity_type, $selected_entities, 'entityreference_view_widget');
      $entity_view = reset($entity_view);
      $i = 0;
      foreach ($selected_entities as $entity_id => $entity) {

        // Remove the checkbox placeholder, it's not needed in this context.
        unset($entity_view[$entity_id]['entityreference_view_widget_action']);
        $entity_view[$entity_id]['_weight'] = array(
          '#parents' => array(
            $field_name,
            $field_language,
            'items',
            $entity_id,
            '_weight',
          ),
          '#type' => 'weight',
          '#title' => t('Weight for @title', array(
            '@title' => entity_label($entity_type, $entity),
          )),
          '#title_display' => 'invisible',
          '#delta' => count($selected_entities),
          '#default_value' => $i,
        );
        $entity_view[$entity_id]['remove'] = array(
          '#parents' => array(
            $field_name,
            $field_language,
            'items',
            $entity_id,
            'remove',
          ),
          '#type' => 'checkbox',
          '#title' => t('Remove'),
          '#weight' => -10,
          '#refresh_items' => TRUE,
          '#ajax' => array(
            'path' => 'entityreference_view_widget/ajax/' . $field_name,
            'wrapper' => 'edit-' . str_replace('_', '-', $field_name),
            'method' => 'replace',
            'progress' => array(
              'type' => 'throbber',
              'message' => '',
            ),
          ),
        );
        $i++;
      }
      $element['selected_items'] = $entity_view;
      $element['selected_items']['#theme'] = 'entityreference_view_widget_selected_items';
    }
    else {

      // Add empty text.
      $element['selected_items'] = array(
        '#markup' => t('No items have been selected.'),
      );
    }
  }

  // Create the checkboxes that will replace the placeholders in entities
  // displayed through the view.
  $substitutions = array();
  $result_entities = $view->query
    ->get_result_entities($view->result);
  foreach ($result_entities[1] as $row_id => $entity) {
    $entity_id = entity_id($entity_type, $entity);
    if (!$view->display_handler->options['hide_left']) {
      $element['add'][$entity_id] = array(
        '#type' => 'checkbox',
        '#refresh_items' => TRUE,
        '#ajax' => array(
          'path' => 'entityreference_view_widget/ajax/' . $field_name,
          'wrapper' => 'edit-' . str_replace('_', '-', $field_name),
          'method' => 'replace',
          'progress' => array(
            'type' => 'throbber',
            'message' => '',
          ),
        ),
      );
    }
    else {
      $element['add'][$entity_id] = array(
        '#type' => 'checkbox',
        '#refresh_items' => TRUE,
      );
    }
    $substitutions[] = array(
      'placeholder' => '<!--entityreference-view-widget-action-' . $entity_id . '-->',
      'entity_id' => $entity_id,
    );
  }
  $element['#substitutions'] = array(
    '#type' => 'value',
    '#value' => $substitutions,
  );
  return $element;
}