public function ViewsBulkOperationsBulkForm::viewsForm in Views Bulk Operations (VBO) 8.3
Same name and namespace in other branches
- 8 src/Plugin/views/field/ViewsBulkOperationsBulkForm.php \Drupal\views_bulk_operations\Plugin\views\field\ViewsBulkOperationsBulkForm::viewsForm()
- 8.2 src/Plugin/views/field/ViewsBulkOperationsBulkForm.php \Drupal\views_bulk_operations\Plugin\views\field\ViewsBulkOperationsBulkForm::viewsForm()
- 4.0.x src/Plugin/views/field/ViewsBulkOperationsBulkForm.php \Drupal\views_bulk_operations\Plugin\views\field\ViewsBulkOperationsBulkForm::viewsForm()
Form constructor for the bulk form.
Parameters
array $form: An associative array containing the structure of the form.
\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.
File
- src/
Plugin/ views/ field/ ViewsBulkOperationsBulkForm.php, line 613
Class
- ViewsBulkOperationsBulkForm
- Defines the Views Bulk Operations field plugin.
Namespace
Drupal\views_bulk_operations\Plugin\views\fieldCode
public function viewsForm(array &$form, FormStateInterface $form_state) {
// Make sure we do not accidentally cache this form.
// @todo Evaluate this again in https://www.drupal.org/node/2503009.
$form['#cache']['max-age'] = 0;
// Add VBO class to the form.
$form['#attributes']['class'][] = 'vbo-view-form';
// Add VBO front UI and tableselect libraries for table display style.
if ($this->view->style_plugin instanceof Table) {
$form['#attached']['library'][] = 'core/drupal.tableselect';
$this->view->style_plugin->options['views_bulk_operations_enabled'] = TRUE;
}
$form['#attached']['library'][] = 'views_bulk_operations/frontUi';
// Only add the bulk form options and buttons if
// there are results and any actions are available.
$action_options = $this
->getBulkOptions();
if (!empty($this->view->result) && !empty($action_options)) {
// Calculate bulk form keys and get labels for all rows.
$bulk_form_keys = [];
$entity_labels = [];
$base_field = $this->view->storage
->get('base_field');
foreach ($this->view->result as $row_index => $row) {
if ($entity = $this
->getEntity($row)) {
$bulk_form_keys[$row_index] = self::calculateEntityBulkFormKey($entity, $row->{$base_field});
$entity_labels[$row_index] = $entity
->label();
}
}
// Update and fetch tempstore data to be available from this point
// as it's needed for proper functioning of further logic.
// Update tempstore data with bulk form keys only when the form is
// displayed, but not when the form is being built before submission
// (data is subject to change - new entities added or deleted after
// the form display). TODO: consider using $form_state->set() instead.
if (empty($form_state
->getUserInput()['op'])) {
$this
->updateTempstoreData($bulk_form_keys);
}
else {
$this
->updateTempstoreData();
}
$form[$this->options['id']]['#tree'] = TRUE;
// Get pager data if available.
if (!empty($this->view->pager) && method_exists($this->view->pager, 'hasMoreRecords')) {
$pagerData = [
'current' => $this->view->pager
->getCurrentPage(),
'more' => $this->view->pager
->hasMoreRecords(),
];
}
// Render checkboxes for all rows.
$page_selected = [];
foreach ($bulk_form_keys as $row_index => $bulk_form_key) {
$checked = isset($this->tempStoreData['list'][$bulk_form_key]);
if (!empty($this->tempStoreData['exclude_mode'])) {
$checked = !$checked;
}
if ($checked) {
$page_selected[] = $bulk_form_key;
}
$form[$this->options['id']][$row_index] = [
'#type' => 'checkbox',
'#title' => $entity_labels[$row_index],
'#title_display' => 'invisible',
'#default_value' => $checked,
'#return_value' => $bulk_form_key,
];
// We should use #value instead of #default_value to always apply
// the plugin's own saved checkbox state (data being changed after form
// submission results in wrong values applied by the FAPI),
// however - automated tests fail if it's done this way.
// We have to apply values conditionally for tests to pass.
if (isset($element['#value']) && $element['#value'] != $checked) {
$element['#value'] = $checked;
}
}
// Ensure a consistent container for filters/operations
// in the view header.
$form['header'] = [
'#type' => 'container',
'#weight' => -100,
];
// Build the bulk operations action widget for the header.
// Allow themes to apply .container-inline on this separate container.
$form['header'][$this->options['id']] = [
'#type' => 'container',
'#attributes' => [
'id' => 'vbo-action-form-wrapper',
],
];
// Display actions buttons or selector.
if ($this->options['buttons']) {
unset($form['actions']['submit']);
foreach ($action_options as $id => $label) {
$form['actions'][$id] = [
'#type' => 'submit',
'#value' => $label,
];
}
}
else {
// Replace the form submit button label.
$form['actions']['submit']['#value'] = $this
->t('Apply to selected items');
$form['header'][$this->options['id']]['action'] = [
'#type' => 'select',
'#title' => $this->options['action_title'],
'#options' => [
'' => $this
->t('-- Select action --'),
] + $action_options,
];
}
// Add AJAX functionality if actions are configurable through this form.
if (empty($this->options['form_step'])) {
$form['header'][$this->options['id']]['action']['#ajax'] = [
'callback' => [
__CLASS__,
'viewsFormAjax',
],
'wrapper' => 'vbo-action-configuration-wrapper',
];
$form['header'][$this->options['id']]['configuration'] = [
'#type' => 'container',
'#attributes' => [
'id' => 'vbo-action-configuration-wrapper',
],
];
$action_id = $form_state
->getValue('action');
if (!empty($action_id)) {
$action = $this->actions[$action_id];
if ($this
->isActionConfigurable($action)) {
$actionObject = $this->actionManager
->createInstance($action_id);
$form['header'][$this->options['id']]['configuration'] += $actionObject
->buildConfigurationForm($form['header'][$this->options['id']]['configuration'], $form_state);
$form['header'][$this->options['id']]['configuration']['#config_included'] = TRUE;
}
}
}
// Selection info: displayed if exposed filters are set and selection
// is not cleared when they change or "select all" element display
// conditions are met. Also displayed by default if VBO field has such
// configuration set.
if ($this->options['force_selection_info']) {
$display_select_all = TRUE;
}
else {
$display_select_all = !$this->options['clear_on_exposed'] && !empty($this->view
->getExposedInput()) || isset($pagerData) && ($pagerData['more'] || $pagerData['current'] > 0);
}
if ($display_select_all) {
$count = empty($this->tempStoreData['exclude_mode']) ? count($this->tempStoreData['list']) : $this->tempStoreData['total_results'] - count($this->tempStoreData['list']);
$form['header'][$this->options['id']]['multipage'] = [
'#type' => 'details',
'#open' => FALSE,
'#title' => $this
->formatPlural($count, 'Selected 1 item in this view', 'Selected @count items in this view'),
'#attributes' => [
// Add view_id and display_id to be available for
// js multipage selector functionality.
'data-view-id' => $this->tempStoreData['view_id'],
'data-display-id' => $this->tempStoreData['display_id'],
'class' => [
'vbo-multipage-selector',
],
],
];
// Get selection info elements.
$form['header'][$this->options['id']]['multipage']['list'] = $this
->getMultipageList($this->tempStoreData);
$form['header'][$this->options['id']]['multipage']['clear'] = [
'#type' => 'submit',
'#value' => $this
->t('Clear'),
'#submit' => [
[
$this,
'clearSelection',
],
],
'#limit_validation_errors' => [],
];
}
// Select all results checkbox. Always display on non-table displays.
if ($display_select_all || !$this->view->style_plugin instanceof Table) {
$form['header'][$this->options['id']]['select_all'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Select / deselect all results in this view (all pages, @count total)', [
'@count' => $this->tempStoreData['total_results'],
]),
'#attributes' => [
'class' => [
'vbo-select-all',
],
],
'#default_value' => !empty($this->tempStoreData['exclude_mode']),
];
}
// Duplicate the form actions into the action container in the header.
$form['header'][$this->options['id']]['actions'] = $form['actions'];
}
else {
// Remove the default actions build array.
unset($form['actions']);
}
}