View source
<?php
namespace Drupal\views_bulk_operations\Plugin\views\field;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RedirectDestinationTrait;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\Plugin\views\field\FieldPluginBase;
use Drupal\views\Plugin\views\field\UncacheableFieldHandlerTrait;
use Drupal\views\Plugin\views\style\Table;
use Drupal\views\ResultRow;
use Drupal\views\ViewExecutable;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\views_bulk_operations\Service\ViewsbulkOperationsViewDataInterface;
use Drupal\views_bulk_operations\Service\ViewsBulkOperationsActionManager;
use Drupal\views_bulk_operations\Service\ViewsBulkOperationsActionProcessorInterface;
use Drupal\views_bulk_operations\Form\ViewsBulkOperationsFormTrait;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\Url;
class ViewsBulkOperationsBulkForm extends FieldPluginBase implements CacheableDependencyInterface, ContainerFactoryPluginInterface {
use RedirectDestinationTrait;
use UncacheableFieldHandlerTrait;
use ViewsBulkOperationsFormTrait;
protected $viewData;
protected $actionManager;
protected $actionProcessor;
protected $tempStoreFactory;
protected $currentUser;
protected $requestStack;
protected $actions = [];
protected $bulkOptions;
protected $tempStoreData = [];
public function __construct(array $configuration, $plugin_id, $plugin_definition, ViewsbulkOperationsViewDataInterface $viewData, ViewsBulkOperationsActionManager $actionManager, ViewsBulkOperationsActionProcessorInterface $actionProcessor, PrivateTempStoreFactory $tempStoreFactory, AccountInterface $currentUser, RequestStack $requestStack) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->viewData = $viewData;
$this->actionManager = $actionManager;
$this->actionProcessor = $actionProcessor;
$this->tempStoreFactory = $tempStoreFactory;
$this->currentUser = $currentUser;
$this->requestStack = $requestStack;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('views_bulk_operations.data'), $container
->get('plugin.manager.views_bulk_operations_action'), $container
->get('views_bulk_operations.processor'), $container
->get('tempstore.private'), $container
->get('current_user'), $container
->get('request_stack'));
}
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
parent::init($view, $display, $options);
if (!empty($this->view->views_bulk_operations_processor_built)) {
return;
}
$this->view->get_total_rows = TRUE;
$this->viewData
->init($view, $display, $this->options['relationship']);
$this->actions = [];
$entity_types = $this->viewData
->getEntityTypeIds();
if (!empty($entity_types)) {
foreach ($this->actionManager
->getDefinitions() as $id => $definition) {
if (empty($definition['type']) || in_array($definition['type'], $entity_types, TRUE)) {
$this->actions[$id] = $definition;
}
}
}
$this->options['form_step'] = TRUE;
}
protected function updateTempstoreData(array $bulk_form_keys = NULL) {
$this->tempStoreData = $this
->getTempstoreData($this->view
->id(), $this->view->current_display);
$variable = [
'batch' => $this->options['batch'],
'batch_size' => $this->options['batch'] ? $this->options['batch_size'] : 0,
'total_results' => $this->viewData
->getTotalResults($this->options['clear_on_exposed']),
'relationship_id' => $this->options['relationship'],
'arguments' => $this->view->args,
'exposed_input' => $this
->getExposedInput(),
];
if (isset($bulk_form_keys)) {
$variable['bulk_form_keys'] = $bulk_form_keys;
}
$request = $this->requestStack
->getCurrentRequest();
$destination = $request->query
->get('destination');
if ($destination) {
$request->query
->remove('destination');
unset($variable['exposed_input']['destination']);
if (strpos($destination, '/') !== 0) {
$destination = '/' . $destination;
}
$variable['redirect_url'] = Url::fromUserInput($destination, []);
}
else {
$variable['redirect_url'] = Url::createFromRequest(clone $this->requestStack
->getCurrentRequest());
}
$query = $variable['redirect_url']
->getOption('query');
if (!$query) {
$query = [];
}
$query += $variable['exposed_input'];
$variable['redirect_url']
->setOption('query', $query);
if (!is_array($this->tempStoreData)) {
$this->tempStoreData = [];
$this->tempStoreData += [
'view_id' => $this->view
->id(),
'display_id' => $this->view->current_display,
'list' => [],
'exclude_mode' => FALSE,
];
$this->tempStoreData += $variable;
$this
->setTempstoreData($this->tempStoreData);
}
else {
$update = FALSE;
$clear_triggers = [
'arguments',
];
if ($this->options['clear_on_exposed']) {
$clear_triggers[] = 'exposed_input';
}
foreach ($clear_triggers as $trigger) {
if ($variable[$trigger] !== $this->tempStoreData[$trigger]) {
$this->tempStoreData[$trigger] = $variable[$trigger];
$this->tempStoreData['list'] = [];
$this->tempStoreData['exclude_mode'] = FALSE;
}
unset($variable[$trigger]);
$update = TRUE;
}
foreach ($variable as $param => $value) {
if (!isset($this->tempStoreData[$param]) || $this->tempStoreData[$param] != $value) {
$update = TRUE;
$this->tempStoreData[$param] = $value;
}
}
if ($update) {
$this
->setTempstoreData($this->tempStoreData);
}
}
}
protected function getExposedInput(array $exposed_input = []) {
if (empty($exposed_input)) {
$exposed_input = array_merge($this->view
->getExposedInput(), $this->view->exposed_raw_input);
}
ksort($exposed_input);
foreach ($exposed_input as $name => $value) {
if (is_array($value) && !empty($value)) {
$exposed_input[$name] = $this
->getExposedInput($value);
}
}
return $exposed_input;
}
protected function currentUser() {
return $this->currentUser;
}
public function getCacheMaxAge() {
return 0;
}
public function getCacheContexts() {
return [];
}
public function getCacheTags() {
return [];
}
public function getEntity(ResultRow $row) {
return $this->viewData
->getEntity($row);
}
public function query() {
}
protected function defineOptions() {
$options = parent::defineOptions();
$options['batch'] = [
'default' => TRUE,
];
$options['batch_size'] = [
'default' => 10,
];
$options['form_step'] = [
'default' => TRUE,
];
$options['buttons'] = [
'default' => FALSE,
];
$options['clear_on_exposed'] = [
'default' => TRUE,
];
$options['action_title'] = [
'default' => $this
->t('Action'),
];
$options['selected_actions'] = [
'default' => [],
];
$options['force_selection_info'] = [
'default' => FALSE,
];
return $options;
}
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
if (empty($this->actions)) {
$form = [
'#type' => 'item',
'#title' => $this
->t('NOTE'),
'#markup' => $this
->t('Views Bulk Operations will work only with normal entity views and contrib module views that are integrated. See \\Drupal\\views_bulk_operations\\EventSubscriber\\ViewsBulkOperationsEventSubscriber class for integration best practice.'),
'#prefix' => '<div class="scroll">',
'#suffix' => '</div>',
];
return;
}
$form['#attributes']['class'][] = 'views-bulk-operations-ui';
$form['#attached']['library'][] = 'views_bulk_operations/adminUi';
$form['batch'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Process in a batch operation'),
'#default_value' => $this->options['batch'],
];
$form['batch_size'] = [
'#title' => $this
->t('Batch size'),
'#type' => 'number',
'#min' => 1,
'#step' => 1,
'#description' => $this
->t('Only applicable if results are processed in a batch operation.'),
'#default_value' => $this->options['batch_size'],
];
$form['form_step'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Configuration form on new page (configurable actions)'),
'#default_value' => $this->options['form_step'],
'#access' => FALSE,
];
$form['buttons'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Display selectable actions as buttons.'),
'#default_value' => $this->options['buttons'],
];
$form['clear_on_exposed'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Clear selection when exposed filters change.'),
'#description' => $this
->t('With this enabled, selection will be cleared every time exposed filters are changed, select all will select all rows with exposed filters applied and view total count will take exposed filters into account. When disabled, select all selects all results in the view with empty exposed filters and one can change exposed filters while selecting rows without the selection being lost.'),
'#default_value' => $this->options['clear_on_exposed'],
];
$form['force_selection_info'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Always show selection info'),
'#default_value' => $this->options['force_selection_info'],
'#description' => $this
->t('Should the selection info fieldset be shown above the view even if there is only one page of results and full selection can be seen in the view itself?'),
];
$form['action_title'] = [
'#type' => 'textfield',
'#title' => $this
->t('Action title'),
'#default_value' => $this->options['action_title'],
'#description' => $this
->t('The title shown above the actions dropdown.'),
];
$form['selected_actions'] = [
'#tree' => TRUE,
'#type' => 'details',
'#open' => TRUE,
'#title' => $this
->t('Selected actions'),
'#attributes' => [
'class' => [
'vbo-actions-widget',
],
],
];
$form_values = $form_state
->getValue([
'options',
'selected_actions',
]);
if (is_null($form_values)) {
$config_data = $this->options['selected_actions'];
$selected_actions_data = [];
foreach ($config_data as $key => $item) {
$selected_actions_data[$item['action_id']] = $item;
}
}
else {
$selected_actions_data = $form_values;
}
$delta = 0;
foreach ($this->actions as $id => $action) {
$form['selected_actions'][$delta]['action_id'] = [
'#type' => 'value',
'#value' => $id,
];
$form['selected_actions'][$delta]['state'] = [
'#type' => 'checkbox',
'#title' => $action['label'],
'#default_value' => empty($selected_actions_data[$id]) ? 0 : 1,
'#attributes' => [
'class' => [
'vbo-action-state',
],
],
];
$form['selected_actions'][$delta]['preconfiguration'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Preconfiguration for "@action"', [
'@action' => $action['label'],
]),
'#states' => [
'visible' => [
sprintf('[name="options[selected_actions][%d][state]"]', $delta) => [
'checked' => TRUE,
],
],
],
];
$form['selected_actions'][$delta]['preconfiguration']['label_override'] = [
'#type' => 'textfield',
'#title' => $this
->t('Override label'),
'#description' => $this
->t('Leave empty for the default label.'),
'#default_value' => isset($selected_actions_data[$id]['preconfiguration']['label_override']) ? $selected_actions_data[$id]['preconfiguration']['label_override'] : '',
];
if (empty($action['confirm_form_route_name'])) {
$form['selected_actions'][$delta]['preconfiguration']['add_confirmation'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Add confirmation step'),
'#default_value' => isset($selected_actions_data[$id]['preconfiguration']['add_confirmation']) ? $selected_actions_data[$id]['preconfiguration']['add_confirmation'] : FALSE,
];
}
if (method_exists($action['class'], 'buildPreConfigurationForm')) {
if (!isset($selected_actions_data[$id]['preconfiguration'])) {
$selected_actions_data[$id]['preconfiguration'] = [];
}
$actionObject = $this->actionManager
->createInstance($id);
if ($this->view instanceof ViewExecutable) {
if ($this->view->inited !== TRUE) {
$this->view
->initHandlers();
}
$actionObject
->setView($this->view);
}
$form['selected_actions'][$delta]['preconfiguration'] = $actionObject
->buildPreConfigurationForm($form['selected_actions'][$delta]['preconfiguration'], $selected_actions_data[$id]['preconfiguration'], $form_state);
}
$delta++;
}
parent::buildOptionsForm($form, $form_state);
}
public function submitOptionsForm(&$form, FormStateInterface $form_state) {
$selected_actions =& $form_state
->getValue([
'options',
'selected_actions',
]);
$selected_actions = array_filter($selected_actions, function ($action_data) {
return !empty($action_data['state']);
});
foreach ($selected_actions as $delta => &$item) {
unset($item['state']);
if (empty($item['preconfiguration']['label_override'])) {
unset($item['preconfiguration']['label_override']);
}
if (empty($item['preconfiguration'])) {
unset($item['preconfiguration']);
}
}
parent::submitOptionsForm($form, $form_state);
}
public function preRender(&$values) {
parent::preRender($values);
if (empty($this
->getBulkOptions())) {
$this->options['element_label_class'] .= 'empty';
$this->options['element_class'] .= 'empty';
$this->options['element_wrapper_class'] .= 'empty';
$this->options['label'] = '';
}
elseif (!empty($this->view->style_plugin) && $this->view->style_plugin instanceof Table) {
$this->options['element_label_class'] .= 'select-all';
$this->options['label'] = '';
}
}
public function getValue(ResultRow $row, $field = NULL) {
return '<!--form-item-' . $this->options['id'] . '--' . $row->index . '-->';
}
public function viewsForm(array &$form, FormStateInterface $form_state) {
$form['#cache']['max-age'] = 0;
$form['#attributes']['class'][] = 'vbo-view-form';
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';
$action_options = $this
->getBulkOptions();
if (!empty($this->view->result) && !empty($action_options)) {
$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();
}
}
if (empty($form_state
->getUserInput()['op'])) {
$this
->updateTempstoreData($bulk_form_keys);
}
else {
$this
->updateTempstoreData();
}
$form[$this->options['id']]['#tree'] = TRUE;
if (!empty($this->view->pager) && method_exists($this->view->pager, 'hasMoreRecords')) {
$pagerData = [
'current' => $this->view->pager
->getCurrentPage(),
'more' => $this->view->pager
->hasMoreRecords(),
];
}
$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,
];
if (isset($element['#value']) && $element['#value'] != $checked) {
$element['#value'] = $checked;
}
}
$form['header'] = [
'#type' => 'container',
'#weight' => -100,
];
$form['header'][$this->options['id']] = [
'#type' => 'container',
'#attributes' => [
'id' => 'vbo-action-form-wrapper',
],
];
if ($this->options['buttons']) {
unset($form['actions']['submit']);
foreach ($action_options as $id => $label) {
$form['actions'][$id] = [
'#type' => 'submit',
'#value' => $label,
];
}
}
else {
$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,
];
}
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;
}
}
}
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' => [
'data-view-id' => $this->tempStoreData['view_id'],
'data-display-id' => $this->tempStoreData['display_id'],
'class' => [
'vbo-multipage-selector',
],
],
];
$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' => [],
];
}
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']),
];
}
$form['header'][$this->options['id']]['actions'] = $form['actions'];
}
else {
unset($form['actions']);
}
}
public static function viewsFormAjax(array $form, FormStateInterface $form_state) {
$trigger = $form_state
->getTriggeringElement();
$plugin_id = $trigger['#array_parents'][1];
return $form['header'][$plugin_id]['configuration'];
}
protected function getBulkOptions() {
if (!isset($this->bulkOptions)) {
$this->bulkOptions = [];
foreach ($this->options['selected_actions'] as $key => $selected_action_data) {
if (!isset($this->actions[$selected_action_data['action_id']])) {
continue;
}
$definition = $this->actions[$selected_action_data['action_id']];
if (!empty($definition['requirements']['_permission']) && !$this->currentUser
->hasPermission($definition['requirements']['_permission'])) {
continue;
}
if (!empty($definition['requirements']['_custom_access']) && !$definition['class']::customAccess($this->currentUser, $this->view)) {
continue;
}
if (!empty($selected_action_data['preconfiguration']['label_override'])) {
$this->bulkOptions[$key] = $selected_action_data['preconfiguration']['label_override'];
}
else {
$this->bulkOptions[$key] = $definition['label'];
}
}
}
return $this->bulkOptions;
}
public function viewsFormSubmit(array &$form, FormStateInterface $form_state) {
if ($form_state
->get('step') == 'views_form_views_form') {
$action_config = $this->options['selected_actions'][$form_state
->getValue('action')];
$action = $this->actions[$action_config['action_id']];
$this->tempStoreData['action_id'] = $action_config['action_id'];
$this->tempStoreData['action_label'] = empty($action_config['preconfiguration']['label_override']) ? (string) $action['label'] : $action_config['preconfiguration']['label_override'];
$this->tempStoreData['relationship_id'] = $this->options['relationship'];
$this->tempStoreData['preconfiguration'] = isset($action_config['preconfiguration']) ? $action_config['preconfiguration'] : [];
$this->tempStoreData['clear_on_exposed'] = $this->options['clear_on_exposed'];
$this->tempStoreData['confirm_route'] = $action['confirm_form_route_name'];
if (empty($this->tempStoreData['confirm_route']) && !empty($action_config['preconfiguration']['add_confirmation'])) {
$this->tempStoreData['confirm_route'] = 'views_bulk_operations.confirm';
}
$configurable = $this
->isActionConfigurable($action);
if ($configurable && empty($this->options['form_step'])) {
$actionObject = $this->actionManager
->createInstance($action_id);
if (method_exists($actionObject, 'submitConfigurationForm')) {
$actionObject
->submitConfigurationForm($form, $form_state);
$this->tempStoreData['configuration'] = $actionObject
->getConfiguration();
}
else {
$form_state
->cleanValues();
$this->tempStoreData['configuration'] = $form_state
->getValues();
}
}
$selected_keys = [];
$input = $form_state
->getUserInput();
foreach ($input[$this->options['id']] as $row_index => $bulk_form_key) {
$selected_keys[$bulk_form_key] = $bulk_form_key;
}
$select_all = $form_state
->getValue('select_all');
foreach ($this->tempStoreData['bulk_form_keys'] as $bulk_form_key) {
if (isset($selected_keys[$bulk_form_key]) && !$select_all || !isset($selected_keys[$bulk_form_key]) && $select_all) {
$this->tempStoreData['list'][$bulk_form_key] = $this
->getListItem($bulk_form_key);
}
else {
unset($this->tempStoreData['list'][$bulk_form_key]);
}
}
$this->tempStoreData['exclude_mode'] = !empty($select_all);
$redirect_route = 'views_bulk_operations.execute_batch';
if ($this->options['form_step'] && $configurable) {
$redirect_route = 'views_bulk_operations.execute_configurable';
}
elseif (!empty($this->tempStoreData['confirm_route'])) {
$redirect_route = $this->tempStoreData['confirm_route'];
}
if (!empty($redirect_route)) {
$this
->setTempstoreData($this->tempStoreData);
$form_state
->setRedirect($redirect_route, [
'view_id' => $this->view
->id(),
'display_id' => $this->view->current_display,
]);
}
else {
$this
->deleteTempstoreData();
$this->actionProcessor
->executeProcessing($this->tempStoreData, $this->view);
$form_state
->setRedirectUrl($this->tempStoreData['redirect_url']);
}
}
}
public function clearSelection(array &$form, FormStateInterface $form_state) {
$this
->deleteTempstoreData();
}
public function viewsFormValidate(&$form, FormStateInterface $form_state) {
if ($this->options['buttons']) {
$trigger = $form_state
->getTriggeringElement();
$action_delta = end($trigger['#parents']);
$form_state
->setValue('action', $action_delta);
}
else {
$action_delta = $form_state
->getValue('action');
}
if ($action_delta === '') {
$form_state
->setErrorByName('action', $this
->t('Please select an action to perform.'));
}
else {
if (!isset($this->options['selected_actions'][$action_delta])) {
$form_state
->setErrorByName('action', $this
->t('Form error occurred, please try again.'));
}
elseif (!isset($this->actions[$this->options['selected_actions'][$action_delta]['action_id']])) {
$form_state
->setErrorByName('action', $this
->t('Form error occurred, Unavailable action selected.'));
}
}
if (!$form_state
->getValue('select_all')) {
$this->tempStoreData = $this
->getTempstoreData();
$selected = array_filter($form_state
->getValue($this->options['id']));
if (empty($this->tempStoreData['list']) && empty($selected)) {
$form_state
->setErrorByName('', $this
->t('No items selected.'));
}
}
if (empty($this->options['form_step']) && !empty($form['header'][$this->options['id']]['configuration']['#config_included'])) {
$action_id = $form_state
->getValue('action');
$action = $this->actions[$action_id];
if (method_exists($action['class'], 'validateConfigurationForm')) {
$actionObject = $this->actionManager
->createInstance($action_id);
$actionObject
->validateConfigurationForm($form['header'][$this->options['id']]['configuration'], $form_state);
}
}
if ($form_state
->getErrors()) {
$bulk_form_keys = [];
foreach ($form[$this->options['id']] as $row_index => $element) {
if (is_numeric($row_index) && isset($element['#return_value'])) {
$bulk_form_keys[$row_index] = $element['#return_value'];
}
}
$this
->updateTempstoreData($bulk_form_keys);
}
}
public function clickSortable() {
return FALSE;
}
protected function isActionConfigurable($action) {
return in_array('Drupal\\Core\\Plugin\\PluginFormInterface', class_implements($action['class']), TRUE) || method_exists($action['class'], 'buildConfigurationForm');
}
}