You are here

function views_bulk_operations_modify_action_form in Views Bulk Operations (VBO) 7.3

Action form function.

Displays form elements for properties acquired through Entity Metadata (hook_entity_property_info()), as well as field widgets for each entity bundle, as provided by field_attach_form().

File

actions/modify.action.inc, line 129
VBO action to modify entity values (properties and fields).

Code

function views_bulk_operations_modify_action_form($context, &$form_state) {

  // This action form uses admin-provided settings. If they were not set, pull
  // the defaults now.
  if (!isset($context['settings'])) {
    $context['settings'] = views_bulk_operations_modify_action_views_bulk_operations_form_options();
  }
  $form_state['entity_type'] = $entity_type = $context['entity_type'];

  // For Field API integration to work, a pseudo-entity is constructed for each
  // bundle that has fields available for editing.
  // The entities then get passed to Field API functions
  // (field_attach_form(), field_attach_form_validate(), field_attach_submit()),
  // and filled with form data.
  // After submit, the pseudo-entities get passed to the actual action
  // (views_bulk_operations_modify_action()) which copies the data from the
  // relevant pseudo-entity constructed here to the actual entity being
  // modified.
  $form_state['entities'] = array();
  $info = entity_get_info($entity_type);
  $properties = _views_bulk_operations_modify_action_get_properties($entity_type, $context['settings']['display_values']);
  $bundles = _views_bulk_operations_modify_action_get_bundles($entity_type, $context);
  $form['#attached']['css'][] = drupal_get_path('module', 'views_bulk_operations') . '/css/modify.action.css';
  $form['#tree'] = TRUE;
  if (!empty($properties)) {
    $form['properties'] = array(
      '#type' => 'fieldset',
      '#title' => t('Properties'),
    );
    $form['properties']['show_value'] = array(
      '#suffix' => '<div class="clearfix"></div>',
    );
    foreach ($properties as $key => $property) {
      $form['properties']['show_value'][$key] = array(
        '#type' => 'checkbox',
        '#title' => $property['label'],
      );

      // According to _views_bulk_operations_modify_action_get_properties
      // we have fixed list of supported types. Most of these types are string
      // and only some of them has options list.
      if (isset($property['options list'])) {
        $determined_type = $property['type'] == 'list' ? 'checkboxes' : 'select';
      }
      else {
        $determined_type = $property['type'] == 'boolean' ? 'checkbox' : 'textfield';
      }
      $form['properties'][$key] = array(
        '#type' => $determined_type,
        '#title' => $property['label'],
        '#description' => $property['description'],
        '#states' => array(
          'visible' => array(
            '#edit-properties-show-value-' . str_replace('_', '-', $key) => array(
              'checked' => TRUE,
            ),
          ),
        ),
      );

      // The default #maxlength for textfields is 128, while most varchar
      // columns hold 255 characters, which makes it a saner default here.
      if ($determined_type == 'textfield') {
        $form['properties'][$key]['#maxlength'] = 255;
      }
      if (!empty($property['options list']) && is_callable($property['options list'])) {
        $form['properties'][$key]['#type'] = 'select';
        $form['properties'][$key]['#options'] = call_user_func_array($property['options list'], array(
          $key,
          array(),
        ));
        if ($property['type'] == 'list') {
          $form['properties'][$key]['#type'] = 'checkboxes';
          $form['properties']['_append::' . $key] = array(
            '#type' => 'checkbox',
            '#title' => t('Add new value(s) to %label, instead of overwriting the existing values.', array(
              '%label' => $property['label'],
            )),
            '#states' => array(
              'visible' => array(
                '#edit-properties-show-value-' . $key => array(
                  'checked' => TRUE,
                ),
              ),
            ),
          );
        }
      }
    }
  }

  // Going to need this for multilingual nodes.
  global $language;
  foreach ($bundles as $bundle_name => $bundle) {
    $bundle_key = $info['entity keys']['bundle'];
    $default_values = array();

    // If the bundle key exists, it must always be set on an entity.
    if (!empty($bundle_key)) {
      $default_values[$bundle_key] = $bundle_name;
    }
    $default_values['language'] = $language->language;
    $entity = entity_create($context['entity_type'], $default_values);
    $form_state['entities'][$bundle_name] = $entity;

    // Show the more detailed label only if the entity type has multiple
    // bundles. Otherwise, it would just be confusing.
    if (count($info['bundles']) > 1) {
      $label = t('Fields for @bundle_key @label', array(
        '@bundle_key' => $bundle_key,
        '@label' => $bundle['label'],
      ));
    }
    else {
      $label = t('Fields');
    }
    $form_key = 'bundle_' . $bundle_name;
    $form[$form_key] = array(
      '#type' => 'fieldset',
      '#title' => $label,
      '#parents' => array(
        $form_key,
      ),
    );
    field_attach_form($context['entity_type'], $entity, $form[$form_key], $form_state, entity_language($context['entity_type'], $entity));

    // Now that all the widgets have been added, sort them by #weight.
    // This ensures that they will stay in the correct order when they get
    // assigned new weights.
    uasort($form[$form_key], 'element_sort');
    $display_values = $context['settings']['display_values'];
    $instances = field_info_instances($entity_type, $bundle_name);
    $weight = 0;
    foreach (element_get_visible_children($form[$form_key]) as $field_name) {

      // For our use case it makes no sense for any field widget to be required.
      if (isset($form[$form_key][$field_name]['#language'])) {
        $field_language = $form[$form_key][$field_name]['#language'];
        _views_bulk_operations_modify_action_unset_required($form[$form_key][$field_name][$field_language]);
      }

      // The admin has specified which fields to display, but this field didn't
      // make the cut. Hide it with #access => FALSE and move on.
      if (empty($display_values[VBO_MODIFY_ACTION_ALL]) && empty($display_values[$bundle_name . '::' . $field_name])) {
        $form[$form_key][$field_name]['#access'] = FALSE;
        continue;
      }
      if (isset($instances[$field_name])) {
        $field = $instances[$field_name];
        $form[$form_key]['show_value'][$field_name] = array(
          '#type' => 'checkbox',
          '#title' => $field['label'],
        );
        $form[$form_key][$field_name]['#states'] = array(
          'visible' => array(
            '#edit-bundle-' . str_replace('_', '-', $bundle_name) . '-show-value-' . str_replace('_', '-', $field_name) => array(
              'checked' => TRUE,
            ),
          ),
        );

        // All field widgets get reassigned weights so that additional elements
        // added between them (such as "_append") can be properly ordered.
        $form[$form_key][$field_name]['#weight'] = $weight++;
        $field_info = field_info_field($field_name);
        if ($field_info['cardinality'] != 1) {
          $form[$form_key]['_append::' . $field_name] = array(
            '#type' => 'checkbox',
            '#title' => t('Add new value(s) to %label, instead of overwriting the existing values.', array(
              '%label' => $field['label'],
            )),
            '#states' => array(
              'visible' => array(
                '#edit-bundle-' . str_replace('_', '-', $bundle_name) . '-show-value-' . str_replace('_', '-', $field_name) => array(
                  'checked' => TRUE,
                ),
              ),
            ),
            '#weight' => $weight++,
          );
        }
      }
    }

    // Add a clearfix below the checkboxes so that the widgets are not floated.
    $form[$form_key]['show_value']['#suffix'] = '<div class="clearfix"></div>';
    $form[$form_key]['show_value']['#weight'] = -1;
  }

  // If the form has only one group (for example, "Properties"), remove the
  // title and the fieldset, since there's no need to visually group values.
  $form_elements = element_get_visible_children($form);
  if (count($form_elements) == 1) {
    $element_key = reset($form_elements);
    unset($form[$element_key]['#type']);
    unset($form[$element_key]['#title']);

    // Get a list of all elements in the group, and filter out the non-values.
    $values = element_get_visible_children($form[$element_key]);
    foreach ($values as $index => $key) {
      if ($key == 'show_value' || substr($key, 0, 1) == '_') {
        unset($values[$index]);
      }
    }

    // If the group has only one value, no need to hide it through #states.
    if (count($values) == 1) {
      $value_key = reset($values);
      $form[$element_key]['show_value'][$value_key]['#type'] = 'value';
      $form[$element_key]['show_value'][$value_key]['#value'] = TRUE;
    }
  }
  if (module_exists('token') && $context['settings']['show_all_tokens']) {
    $token_type = str_replace('_', '-', $entity_type);
    $form['tokens'] = array(
      '#type' => 'fieldset',
      '#title' => t('Available tokens'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#weight' => 998,
    );
    $form['tokens']['tree'] = array(
      '#theme' => 'token_tree',
      '#token_types' => array(
        $token_type,
        'site',
      ),
      '#global_types' => array(),
      '#dialog' => TRUE,
    );
  }
  return $form;
}