You are here

function paragraphs_field_multiple_value_form in Paragraphs 7

Special handling to create form elements for multiple values.

Handles generic features for multiple fields:

  • number of widgets
  • AHAH-'add more' button
  • drag-n-drop value reordering.
1 call to paragraphs_field_multiple_value_form()
paragraphs_field_widget_form in ./paragraphs.field_widget.inc
Implements hook_field_widget_form().

File

./paragraphs.field_widget.inc, line 54
Holds functions for the paragraphs widgets.

Code

function paragraphs_field_multiple_value_form($field, $instance, $langcode, $items, &$form, &$form_state, $delta, $original_element) {
  $field_name = $field['field_name'];
  $parents = $form['#parents'];
  $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
  $max = $field_state['items_count'] - 1;
  $title = check_plain($instance['label']);
  $description = field_filter_xss($instance['description']);
  $id_prefix = implode('-', array_merge($parents, array(
    $field_name,
  )));
  $wrapper_id = drupal_html_id($id_prefix . '-add-more-wrapper');
  $field_elements = array();
  $function = $instance['widget']['module'] . '_field_widget_form_build';
  $had_first = FALSE;
  $actual_item_count = 0;
  if (function_exists($function)) {
    for ($delta = 0; $delta <= $max; $delta++) {
      $multiple = TRUE;
      $element = array(
        '#entity_type' => $original_element['#entity_type'],
        '#entity' => $original_element['#entity'],
        '#bundle' => $original_element['#bundle'],
        '#field_name' => $field_name,
        '#language' => $langcode,
        '#field_parents' => $parents,
        '#columns' => array_keys($field['columns']),
        // For multiple fields, title and description are handled by the
        // wrapping table.
        '#title' => $multiple ? '' : $title,
        '#description' => $multiple ? '' : $description,
        '#delta' => $delta,
        '#weight' => $delta,
        '#wrapper_id' => $wrapper_id,
      );
      if ($element = $function($form, $form_state, $field, $instance, $langcode, $items, $delta, $element)) {

        // Input field for the delta (drag-n-drop reordering).
        if ($multiple) {

          // We name the element '_weight' to avoid clashing with elements
          // defined by widget.
          $element['_weight'] = array(
            '#type' => 'weight',
            '#title' => t('Weight for row @number', array(
              '@number' => $delta + 1,
            )),
            '#title_display' => 'invisible',
            // Note: this 'delta' is the FAPI 'weight' element's property.
            '#delta' => $max,
            '#default_value' => isset($items[$delta]['_weight']) ? $items[$delta]['_weight'] : $delta,
            '#weight' => 100,
          );
        }

        // Because our deleted elements are still in the form, only the first
        // shown element is required.
        if (!$had_first && (!isset($element['#access']) || $element['#access'])) {
          $had_first = TRUE;
          $element['#required'] = $instance['required'];
        }
        if (!isset($element['#access']) || $element['#access']) {
          $actual_item_count++;
        }

        // Allow modules to alter the field widget form element.
        $context = array(
          'form' => $form,
          'field' => $field,
          'instance' => $instance,
          'langcode' => $langcode,
          'items' => $items,
          'delta' => $delta,
        );
        drupal_alter(array(
          'paragraphs_field_widget_form',
          'paragraphs_field_widget_' . $instance['widget']['type'] . '_form',
        ), $element, $form_state, $context);
        $field_elements[$delta] = $element;
      }
    }
    $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
    $field_state['real_items_count'] = $actual_item_count;
    field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
    $field_elements += array(
      '#theme' => 'paragraphs_field_multiple_value_form',
      '#field_name' => $field['field_name'],
      '#cardinality' => $field['cardinality'],
      '#title' => $title,
      '#required' => $instance['required'],
      '#description' => $description,
      '#prefix' => '<div id="' . $wrapper_id . '">',
      '#suffix' => '</div>',
      '#max_delta' => $max,
      '#instance' => $instance,
      '#element_validate' => array(
        '_paragraphs_multiple_field_validate',
      ),
    );

    // Add 'add more' button, if not working with a programmed form.
    if (empty($form_state['programmed'])) {
      $available_bundles = paragraphs_bundle_load();
      $select_bundles = array();
      $select_bundles_weighted = array();

      // By default, consider that no bundle has been explicitly picked.
      $explicitly_enabled = FALSE;
      foreach ($instance['settings']['allowed_bundles'] as $allowed_bundle_key => $allowed_bundle_value) {
        if ($allowed_bundle_key === $allowed_bundle_value && isset($available_bundles[$allowed_bundle_key])) {
          $select_bundles[$available_bundles[$allowed_bundle_key]->bundle] = $available_bundles[$allowed_bundle_key]->label;

          // If an item has been explicitly selected, raise our flag.
          $explicitly_enabled = TRUE;
        }
        elseif (isset($available_bundles[$allowed_bundle_key]->bundle)) {
          $select_bundles_weighted[$available_bundles[$allowed_bundle_key]->bundle] = $available_bundles[$allowed_bundle_key]->label;
        }
      }

      // If no bundle has been explicitly selected, give access to all of them.
      if (!$explicitly_enabled) {
        $select_bundles = $select_bundles_weighted;
        foreach ($available_bundles as $bundle) {
          if (!isset($select_bundles[$bundle->bundle])) {
            $select_bundles[$bundle->bundle] = $bundle->label;
          }
        }
      }
      $removed_a_bundle = FALSE;
      $weight = 0;
      foreach ($select_bundles as $machine_name => $bundle) {
        $select_bundles[$machine_name] = array(
          'name' => $bundle,
          'weight' => $weight,
        );

        /* @var $entity_shell ParagraphsItemEntity */
        $entity_shell = entity_create('paragraphs_item', array(
          'bundle' => $machine_name,
          'field_name' => $field_name,
        ));
        $entity_shell
          ->setHostEntity($original_element['#entity_type'], $original_element['#entity'], $langcode, FALSE);
        if (!entity_access('create', 'paragraphs_item', $entity_shell)) {
          unset($select_bundles[$machine_name]);
          $removed_a_bundle = TRUE;
        }
        elseif (isset($instance['settings']['bundle_weights'][$machine_name])) {
          $select_bundles[$machine_name]['weight'] = $instance['settings']['bundle_weights'][$machine_name];
        }
        $weight++;
      }
      $field_elements['#select_bundles'] = $select_bundles;
      if ($removed_a_bundle && count($select_bundles) === 0) {
        $field_elements['add_more'] = array(
          '#type' => 'container',
          '#tree' => TRUE,
        );
        $field_elements['add_more']['add_more'] = array(
          '#type' => 'markup',
          '#markup' => '<em>' . t('You are not allowed to add any of the bundles.') . '</em>',
        );
      }
      elseif (count($select_bundles)) {
        uasort($select_bundles, 'drupal_sort_weight');
        $field = $field_state['field'];
        if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $field_state['real_items_count'] < $field['cardinality']) {
          if (!isset($instance['settings']['title'])) {
            $instance['settings']['title'] = PARAGRAPHS_DEFAULT_TITLE;
          }
          $instance_title = t($instance['settings']['title']);
          $field_elements['add_more'] = array(
            '#type' => 'container',
            '#tree' => TRUE,
          );
          $add_mode = isset($instance['settings']['add_mode']) ? $instance['settings']['add_mode'] : PARAGRAPHS_DEFAULT_ADD_MODE;
          if ($add_mode == 'button') {
            foreach ($select_bundles as $machine_name => $bundle) {

              /* @var $entity_shell ParagraphsItemEntity */
              $entity_shell = entity_create('paragraphs_item', array(
                'bundle' => $machine_name,
                'field_name' => $field_name,
              ));
              $entity_shell
                ->setHostEntity($original_element['#entity_type'], $original_element['#entity'], $langcode, FALSE);
              $field_elements['add_more']['add_more_bundle_' . $machine_name] = array(
                '#type' => 'submit',
                '#name' => strtr($id_prefix, '-', '_') . '_add_more_add_more_bundle_' . $machine_name,
                '#value' => t('Add !title', array(
                  '!title' => $bundle['name'],
                )),
                '#access' => entity_access('create', 'paragraphs_item', $entity_shell),
                '#attributes' => array(
                  'class' => array(
                    'field-add-more-submit',
                    'paragraphs-add-more-submit',
                  ),
                ),
                '#limit_validation_errors' => array(),
                '#submit' => array(
                  'paragraphs_add_more_submit',
                ),
                '#ajax' => array(
                  'callback' => 'paragraphs_add_more_js',
                  'wrapper' => $wrapper_id,
                  'effect' => 'fade',
                ),
              );
            }
          }
          else {
            uasort($select_bundles, 'drupal_sort_weight');
            $select_list = array();
            foreach ($select_bundles as $machine_name => $bundle) {
              $select_list[$machine_name] = $bundle['name'];
            }
            $field_elements['add_more']['type'] = array(
              '#type' => 'select',
              '#name' => strtr($id_prefix, '-', '_') . '_add_more_type',
              '#title' => t('!title type', array(
                '!title' => $instance_title,
              )),
              '#options' => $select_list,
              '#attributes' => array(
                'class' => array(
                  'field-add-more-type',
                ),
              ),
              '#limit_validation_errors' => array(
                array_merge($parents, array(
                  $field_name,
                  $langcode,
                )),
              ),
            );

            // Hide the bundle selection if only one bundle is allowed.
            if (count($select_list) == 1) {
              $field_elements['add_more']['type']['#type'] = 'hidden';
              $keys = array_keys($select_list);
              $field_elements['add_more']['type']['#value'] = $keys[0];
            }
            if (isset($form_state['input'][strtr($id_prefix, '-', '_') . '_add_more_type'])) {
              $field_elements['add_more']['type']['#default_value'] = $form_state['input'][strtr($id_prefix, '-', '_') . '_add_more_type'];
            }
            $text = t('Add new !title', array(
              '!title' => $instance_title,
            ));
            if ($max >= 0) {
              $text = t('Add another !title', array(
                '!title' => $instance_title,
              ));
            }
            $field_elements['add_more']['add_more'] = array(
              '#type' => 'submit',
              '#name' => strtr($id_prefix, '-', '_') . '_add_more_add_more',
              '#value' => $text,
              '#attributes' => array(
                'class' => array(
                  'field-add-more-submit',
                  'paragraphs-add-more-submit',
                ),
              ),
              '#limit_validation_errors' => array(),
              '#submit' => array(
                'paragraphs_add_more_submit',
              ),
              '#ajax' => array(
                'callback' => 'paragraphs_add_more_js',
                'wrapper' => $wrapper_id,
                'effect' => 'fade',
              ),
            );
          }
        }
      }
      else {
        $field_elements['add_more']['add_more'] = array(
          '#type' => 'markup',
          '#markup' => '<em>' . t('No bundles available, edit field settings') . '</em>',
        );
      }
    }
  }
  if (module_exists('file')) {

    // file.js triggers uploads when the main Submit button is clicked.
    $field_elements['#attached']['js'] = array(
      drupal_get_path('module', 'file') . '/file.js',
      array(
        'data' => drupal_get_path('module', 'paragraphs') . '/paragraphs.js',
        'type' => 'file',
        'weight' => 9999,
      ),
    );
    $form_state['has_file_element'] = TRUE;
  }
  return $field_elements;
}