You are here

function paragraphs_field_widget_form_build in Paragraphs 7

Widget form implementation for paragraphs.

Parameters

array $form: The form structure where widgets are being attached to. This might be a full form structure, or a sub-element of a larger form.

array $form_state: An associative array containing the current state of the form.

array $field: The field structure.

array $instance: The field instance.

string $langcode: The language associated with $items.

array $items: Array of default values for this field.

int $delta: The order of this item in the array of subelements (0, 1, 2, etc).

array $element: A form element array containing basic properties for the widget.

Return value

array The form elements for a single widget for this field.

File

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

Code

function paragraphs_field_widget_form_build(array &$form, array &$form_state, array $field, array $instance, $langcode, array $items, $delta, array $element) {
  static $recursion = 0;
  if (!isset($instance['settings']['title'])) {
    $instance['settings']['title'] = PARAGRAPHS_DEFAULT_TITLE;
  }
  $instance_title = t($instance['settings']['title']);
  if (!isset($instance['settings']['title_multiple'])) {
    $instance['settings']['title_multiple'] = PARAGRAPHS_DEFAULT_TITLE_MULTIPLE;
  }

  // If the paragraphs item form contains another paragraph,
  // we might ran into a recursive loop. Prevent that.
  if ($recursion++ > PARAGRAPHS_RECURSION_LIMIT) {
    drupal_set_message(t('The paragraphs item form has not been embedded to avoid recursive loops.'), 'error');
    return $element;
  }
  $field_parents = $element['#field_parents'];
  $field_name = $element['#field_name'];
  $language = $element['#language'];

  // Set host entity data since field_attach_form() overrides the $element
  // values with the values for the paragraphs item.
  $element['#host_entity_type'] = $element['#entity_type'];
  $element['#host_entity'] = $element['#entity'];
  $element['#host_bundle'] = $element['#bundle'];
  $bundle = FALSE;
  $id_prefix = implode('-', array_merge($field_parents, array(
    $field_name,
  )));
  if (isset($form_state['input'][strtr($id_prefix, '-', '_') . '_add_more_type'])) {
    $bundle = $form_state['input'][strtr($id_prefix, '-', '_') . '_add_more_type'];
  }
  elseif (isset($form_state['input']['_triggering_element_name'])) {
    if (strpos($form_state['input']['_triggering_element_name'], strtr($id_prefix, '-', '_') . '_add_more_add_more_bundle_') === 0) {
      $bundle = substr($form_state['input']['_triggering_element_name'], drupal_strlen(strtr($id_prefix, '-', '_') . '_add_more_add_more_bundle_'));
    }
  }

  // Nest the paragraphs item entity form in a dedicated parent space,
  // by appending [field_name, langcode, delta] to the current parent space.
  // That way the form values of the paragraphs item are separated.
  $parents = array_merge($field_parents, array(
    $field_name,
    $language,
    $delta,
  ));
  $element += array(
    '#element_validate' => array(
      'paragraphs_field_widget_embed_validate',
    ),
    '#parents' => $parents,
  );
  $field_state = field_form_get_state($field_parents, $field_name, $language, $form_state);
  $deleted_paragraph = FALSE;
  $confirmed_deleted_paragraph = FALSE;
  $is_new_paragraph = FALSE;
  $default_edit_mode = isset($instance['settings']['default_edit_mode']) ? $instance['settings']['default_edit_mode'] : PARAGRAPHS_DEFAULT_EDIT_MODE;
  $default_edit_mode_override = isset($instance['settings']['default_edit_mode_override']) ? $instance['settings']['default_edit_mode_override'] : PARAGRAPHS_DEFAULT_EDIT_MODE_OVERRIDE;
  $force_open = !empty($instance['widget']['paragraphs_edit_mode_open']) || count($items) < $default_edit_mode_override;
  $being_edited_paragraph = $default_edit_mode === 'open';
  if (isset($field_state['entity'][$delta])) {
    if (isset($field_state['entity'][$delta]->removed) && $field_state['entity'][$delta]->removed) {
      $deleted_paragraph = TRUE;
    }
    if (isset($field_state['entity'][$delta]->confirmed_removed) && $field_state['entity'][$delta]->confirmed_removed) {
      $confirmed_deleted_paragraph = TRUE;
    }
    if ($being_edited_paragraph || isset($field_state['entity'][$delta]->being_edited) && $field_state['entity'][$delta]->being_edited) {
      $being_edited_paragraph = TRUE;
    }
    else {
      $being_edited_paragraph = FALSE;
    }

    /* @var $paragraph_item ParagraphsItemEntity */
    $paragraph_item = $field_state['entity'][$delta];
    $paragraph_item
      ->setHostEntity($element['#host_entity_type'], $element['#host_entity'], $langcode, FALSE);
  }
  else {
    if (isset($items[$delta])) {
      $paragraph_item = paragraphs_field_get_entity($items[$delta]);
    }

    // Show an empty collection if we have no existing one or it does not
    // load.
    if (empty($paragraph_item) && $bundle) {

      /* @var $paragraph_item ParagraphsItemEntity */
      $paragraph_item = entity_create('paragraphs_item', array(
        'bundle' => $bundle,
        'field_name' => $field_name,
      ));
      $paragraph_item->being_edited = TRUE;
      $being_edited_paragraph = TRUE;
      $is_new_paragraph = TRUE;
    }
    if (!empty($paragraph_item)) {

      /* @var $paragraph_item ParagraphsItemEntity */
      $paragraph_item
        ->setHostEntity($element['#host_entity_type'], $element['#host_entity'], $langcode, FALSE);
      if ($force_open) {
        $paragraph_item->being_edited = TRUE;
        $being_edited_paragraph = TRUE;
      }

      // Put our entity in the form state, so FAPI callbacks can access it.
      $field_state['entity'][$delta] = $paragraph_item;
    }
  }
  field_form_set_state($field_parents, $field_name, $language, $form_state, $field_state);
  if (!empty($paragraph_item)) {
    $bundle_info = paragraphs_bundle_load($paragraph_item->bundle);
    if ($bundle_info) {
      $element['paragraph_bundle_title'] = array(
        '#type' => 'container',
        '#weight' => -100,
      );
      $element['paragraph_bundle_title']['info'] = array(
        '#markup' => t('@title type: %bundle', array(
          '@title' => $instance_title,
          '%bundle' => $bundle_info->label,
        )),
      );
    }
    if (!$deleted_paragraph) {
      $element['actions'] = array(
        '#type' => 'actions',
        '#weight' => 9999,
      );
      field_attach_form('paragraphs_item', $paragraph_item, $element, $form_state, $language);
      if ($being_edited_paragraph) {
        if (!$is_new_paragraph && !entity_access('update', 'paragraphs_item', $paragraph_item)) {
          foreach (element_children($element) as $key) {
            if ($key != 'paragraph_bundle_title' && $key != 'actions' && $key != 'paragraph_bundle_preview' && $key != 'access_info') {
              $element[$key]['#access'] = FALSE;
            }
          }
          $element['access_info'] = array(
            '#type' => 'container',
            '#weight' => 9998,
          );
          $element['access_info']['info'] = array(
            '#type' => 'markup',
            '#markup' => '<em>' . t('You are not allowed to edit this @title item.', array(
              '@title' => $instance_title,
            )) . '</em>',
          );
        }
        else {
          if (empty($element['#required'])) {
            $element['#after_build'][] = 'paragraphs_field_widget_embed_delay_required_validation';
          }
        }
        if ($default_edit_mode != 'open') {
          $element['actions']['collapse_button'] = array(
            '#delta' => $delta,
            '#name' => implode('_', $parents) . '_collapse_button',
            '#type' => 'submit',
            '#value' => t('Collapse'),
            '#validate' => array(),
            '#submit' => array(
              'paragraphs_collapse_submit',
            ),
            '#limit_validation_errors' => array(
              $parents,
            ),
            '#ajax' => array(
              'callback' => '_paragraphs_ajax_update_callback',
              'effect' => 'fade',
              'wrapper' => $element['#wrapper_id'],
            ),
            '#access' => entity_access('update', 'paragraphs_item', $paragraph_item),
            '#weight' => 999,
          );
        }
      }
      else {
        if ($default_edit_mode === 'preview' && entity_access('view', 'paragraphs_item', $paragraph_item)) {
          $element['paragraph_bundle_preview'] = array(
            '#type' => 'container',
          );
          $preview = $paragraph_item
            ->view('paragraphs_editor_preview', $langcode);
          $element['paragraph_bundle_preview']['preview'] = $preview;
        }
        foreach (element_children($element) as $key) {
          if ($key != 'paragraph_bundle_title' && $key != 'actions' && $key != 'paragraph_bundle_preview' && $key != 'access_info') {
            $element[$key]['#access'] = FALSE;
          }
        }
        $element['actions'] = array(
          '#type' => 'actions',
          '#weight' => 9999,
        );
        if (isset($field_state['entity'][$delta]->must_be_saved) && $field_state['entity'][$delta]->must_be_saved) {
          $element['actions']['must_be_saved'] = array(
            '#markup' => '<p><em>' . t('Warning: this content must be saved to reflect changes on this paragraphs item.') . '</em></p>',
            '#weight' => 998,
          );
        }
        $element['actions']['edit_button'] = array(
          '#delta' => $delta,
          '#name' => implode('_', $parents) . '_edit_button',
          '#type' => 'submit',
          '#value' => t('Edit'),
          '#validate' => array(),
          '#submit' => array(
            'paragraphs_edit_submit',
          ),
          '#limit_validation_errors' => array(),
          '#ajax' => array(
            'callback' => '_paragraphs_ajax_update_callback',
            'effect' => 'fade',
            'wrapper' => $element['#wrapper_id'],
          ),
          '#access' => entity_access('update', 'paragraphs_item', $paragraph_item),
          '#weight' => 999,
        );
      }
      if (isset($paragraph_item)) {
        $element['actions']['remove_button'] = array(
          '#delta' => $delta,
          '#name' => implode('_', $parents) . '_remove_button',
          '#type' => 'submit',
          '#value' => t('Remove'),
          '#validate' => array(),
          '#submit' => array(
            'paragraphs_remove_submit',
          ),
          '#limit_validation_errors' => array(),
          '#ajax' => array(
            'callback' => '_paragraphs_ajax_update_callback',
            'effect' => 'fade',
            'wrapper' => $element['#wrapper_id'],
          ),
          '#access' => entity_access('delete', 'paragraphs_item', $paragraph_item),
          '#weight' => 1000,
        );
      }
      if (isset($element['actions']['edit_button']) && !$element['actions']['edit_button']['#access'] && isset($element['actions']['remove_button']) && !$element['actions']['remove_button']['#access']) {
        $element['access_info'] = array(
          '#type' => 'container',
          '#weight' => 9998,
        );
        $element['access_info']['info'] = array(
          '#type' => 'markup',
          '#markup' => '<em>' . t('You are not allowed to edit or remove this @title item.', array(
            '@title' => $instance_title,
          )) . '</em>',
        );
      }
      elseif (isset($element['actions']['edit_button']) && !$element['actions']['edit_button']['#access']) {
        $element['access_info'] = array(
          '#type' => 'container',
          '#weight' => 9998,
        );
        $element['access_info']['info'] = array(
          '#type' => 'markup',
          '#markup' => '<em>' . t('You are not allowed to edit this @title item.', array(
            '@title' => $instance_title,
          )) . '</em>',
        );
      }
      elseif (isset($element['actions']['remove_button']) && !$element['actions']['remove_button']['#access']) {
        $element['access_info'] = array(
          '#type' => 'container',
          '#weight' => 9998,
        );
        $element['access_info']['info'] = array(
          '#type' => 'markup',
          '#markup' => '<em>' . t('You are not allowed to remove this @title item.', array(
            '@title' => $instance_title,
          )) . '</em>',
        );
      }
    }
    else {
      $element['actions'] = array(
        '#type' => 'actions',
        '#weight' => 9999,
      );
      $element['actions']['remove_button'] = array(
        '#markup' => '<p>' . t('This @title has been removed, press the button below to restore.', array(
          '@title' => $instance_title,
        )) . ' </p><p><em>' . t('Warning: this @title will actually be deleted when you press "!confirm" or "!save"!', array(
          '@title' => $instance_title,
          '!confirm' => t('Confirm Deletion'),
          '!save' => t('Save'),
        )) . '</em></p>',
      );
      $element['actions']['restore_button'] = array(
        '#delta' => $delta,
        '#name' => implode('_', $parents) . '_restore_button',
        '#type' => 'submit',
        '#value' => t('Restore'),
        '#validate' => array(),
        '#submit' => array(
          'paragraphs_restore_submit',
        ),
        '#limit_validation_errors' => array(),
        '#ajax' => array(
          'callback' => '_paragraphs_ajax_update_callback',
          'effect' => 'fade',
          'wrapper' => $element['#wrapper_id'],
        ),
        '#weight' => 1000,
      );
      $element['actions']['confirm_delete_button'] = array(
        '#delta' => $delta,
        '#name' => implode('_', $parents) . '_deleteconfirm_button',
        '#type' => 'submit',
        '#value' => t('Confirm Deletion'),
        '#validate' => array(),
        '#submit' => array(
          'paragraphs_deleteconfirm_submit',
        ),
        '#limit_validation_errors' => array(),
        '#ajax' => array(
          'callback' => '_paragraphs_ajax_update_callback',
          'effect' => 'fade',
          'wrapper' => $element['#wrapper_id'],
        ),
        '#weight' => 1001,
      );
    }
  }

  // Hide full item when we are confirmed delete.
  if ($confirmed_deleted_paragraph) {
    $element['#access'] = FALSE;
  }
  $recursion--;
  return $element;
}