class ViewsBulkOperationsActionProcessor in Views Bulk Operations (VBO) 8
Same name and namespace in other branches
- 8.3 src/Service/ViewsBulkOperationsActionProcessor.php \Drupal\views_bulk_operations\Service\ViewsBulkOperationsActionProcessor
- 8.2 src/Service/ViewsBulkOperationsActionProcessor.php \Drupal\views_bulk_operations\Service\ViewsBulkOperationsActionProcessor
- 4.0.x src/Service/ViewsBulkOperationsActionProcessor.php \Drupal\views_bulk_operations\Service\ViewsBulkOperationsActionProcessor
Defines VBO action processor.
Hierarchy
- class \Drupal\views_bulk_operations\Service\ViewsBulkOperationsActionProcessor implements ViewsBulkOperationsActionProcessorInterface uses StringTranslationTrait
Expanded class hierarchy of ViewsBulkOperationsActionProcessor
1 string reference to 'ViewsBulkOperationsActionProcessor'
1 service uses ViewsBulkOperationsActionProcessor
File
- src/
Service/ ViewsBulkOperationsActionProcessor.php, line 17
Namespace
Drupal\views_bulk_operations\ServiceView source
class ViewsBulkOperationsActionProcessor implements ViewsBulkOperationsActionProcessorInterface {
use StringTranslationTrait;
/**
* View data provider service.
*
* @var \Drupal\views_bulk_operations\Service\ViewsbulkOperationsViewDataInterface
*/
protected $viewDataService;
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* VBO action manager.
*
* @var \Drupal\views_bulk_operations\Service\ViewsBulkOperationsActionManager
*/
protected $actionManager;
/**
* Current user object.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $user;
/**
* Module handler service.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Is the object initialized?
*
* @var bool
*/
protected $initialized = FALSE;
/**
* Definition of the processed action.
*
* @var array
*/
protected $actionDefinition;
/**
* The processed action object.
*
* @var array
*/
protected $action;
/**
* The current view object.
*
* @var \Drupal\views\ViewExecutable
*/
protected $view;
/**
* View data from the bulk form.
*
* @var array
*/
protected $bulkFormData;
/**
* Array of entities that will be processed in the current batch.
*
* @var array
*/
protected $queue = [];
/**
* Constructor.
*
* @param \Drupal\views_bulk_operations\Service\ViewsbulkOperationsViewDataInterface $viewDataService
* View data provider service.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* Entity type manager.
* @param \Drupal\views_bulk_operations\Service\ViewsBulkOperationsActionManager $actionManager
* VBO action manager.
* @param \Drupal\Core\Session\AccountProxyInterface $user
* Current user object.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
* Module handler service.
*/
public function __construct(ViewsbulkOperationsViewDataInterface $viewDataService, EntityTypeManagerInterface $entityTypeManager, ViewsBulkOperationsActionManager $actionManager, AccountProxyInterface $user, ModuleHandlerInterface $moduleHandler) {
$this->viewDataService = $viewDataService;
$this->entityTypeManager = $entityTypeManager;
$this->actionManager = $actionManager;
$this->user = $user;
$this->moduleHandler = $moduleHandler;
}
/**
* {@inheritdoc}
*/
public function initialize(array $view_data, $view = NULL) {
// It may happen that the service was already initialized
// in this request (e.g. multiple Batch API operation calls).
// Clear the processing queue in such a case.
if ($this->initialized) {
$this->queue = [];
}
if (!isset($view_data['configuration'])) {
$view_data['configuration'] = [];
}
if (!empty($view_data['preconfiguration'])) {
$view_data['configuration'] += $view_data['preconfiguration'];
}
// Initialize action object.
$this->actionDefinition = $this->actionManager
->getDefinition($view_data['action_id']);
$this->action = $this->actionManager
->createInstance($view_data['action_id'], $view_data['configuration']);
// Set action context.
$this
->setActionContext($view_data);
// Set entire view data as object parameter for future reference.
$this->bulkFormData = $view_data;
// Set the current view.
$this
->setView($view);
$this->initialized = TRUE;
}
/**
* Set the current view object.
*
* @param mixed $view
* The current view object or NULL.
*/
protected function setView($view = NULL) {
if (!is_null($view)) {
$this->view = $view;
}
else {
$this->view = Views::getView($this->bulkFormData['view_id']);
$this->view
->setDisplay($this->bulkFormData['display_id']);
if (!empty($this->bulkFormData['arguments'])) {
$this->view
->setArguments($this->bulkFormData['arguments']);
}
if (!empty($this->bulkFormData['exposed_input'])) {
$this->view
->setExposedInput($this->bulkFormData['exposed_input']);
}
}
}
/**
* {@inheritdoc}
*/
public function populateQueue(array $list, array &$context = []) {
// Determine batch size and offset.
if (!empty($context)) {
$batch_size = $this->bulkFormData['batch_size'];
if (!isset($context['sandbox']['current_batch'])) {
$context['sandbox']['current_batch'] = 0;
}
$current_batch =& $context['sandbox']['current_batch'];
$offset = $current_batch * $batch_size;
}
else {
$batch_size = 0;
$current_batch = 0;
$offset = 0;
}
// Get view results if required.
if (empty($list)) {
$this->view
->setItemsPerPage($batch_size);
$this->view
->setCurrentPage($current_batch);
$this->view
->build();
// If the view doesn't start from the first result,
// move the offset.
if ($view_offset = $this->view->pager
->getOffset()) {
$offset += $view_offset;
}
$this->view->query
->setLimit($batch_size);
$this->view->query
->setOffset($offset);
// Let modules modify the view just prior to executing it.
$this->moduleHandler
->invokeAll('views_pre_execute', [
$this->view,
]);
$this->view->query
->execute($this->view);
// Prepare result getter.
$this->viewDataService
->init($this->view, $this->view
->getDisplay(), $this->bulkFormData['relationship_id']);
foreach ($this->view->result as $row) {
$this->queue[] = $this->viewDataService
->getEntity($row);
}
}
else {
if ($batch_size) {
$batch_list = array_slice($list, $offset, $batch_size);
}
else {
$batch_list = $list;
}
foreach ($batch_list as $item) {
$this->queue[] = $this
->getEntity($item);
}
if ($this->actionDefinition['pass_view']) {
$this
->populateViewResult($batch_list, $context, $current_batch);
}
}
// Extra processing when executed in a Batch API operation.
if (!empty($context)) {
if (!isset($context['sandbox']['total'])) {
if (empty($list)) {
$context['sandbox']['total'] = $this->viewDataService
->getTotalResults();
}
else {
$context['sandbox']['total'] = count($list);
}
}
if ($this->actionDefinition['pass_context']) {
// Add batch size to context array for potential use in actions.
$context['sandbox']['batch_size'] = $batch_size;
$this->action
->setContext($context);
}
}
if ($batch_size) {
$current_batch++;
}
if ($this->actionDefinition['pass_view']) {
$this->action
->setView($this->view);
}
return count($this->queue);
}
/**
* {@inheritdoc}
*/
public function setActionContext(array $context) {
if (isset($this->action) && method_exists($this->action, 'setContext')) {
$this->action
->setContext($context);
}
}
/**
* {@inheritdoc}
*/
public function process() {
$output = [];
// Check if all queue items are actually Drupal entities.
foreach ($this->queue as $delta => $entity) {
if (!$entity instanceof EntityInterface) {
$output[] = $this
->t('Skipped');
unset($this->queue[$delta]);
}
}
// Check entity type for multi-type views like search_api index.
if (!empty($this->actionDefinition['type'])) {
foreach ($this->queue as $delta => $entity) {
if ($entity
->getEntityTypeId() !== $this->actionDefinition['type']) {
$output[] = $this
->t('Entity type not supported');
unset($this->queue[$delta]);
}
}
}
// Check access.
foreach ($this->queue as $delta => $entity) {
if (!$this->action
->access($entity, $this->user)) {
$output[] = $this
->t('Access denied');
unset($this->queue[$delta]);
}
}
// Process queue.
$results = $this->action
->executeMultiple($this->queue);
// Populate output.
if (empty($results)) {
$count = count($this->queue);
for ($i = 0; $i < $count; $i++) {
$output[] = $this->bulkFormData['action_label'];
}
}
else {
foreach ($results as $result) {
$output[] = $result;
}
}
return $output;
}
/**
* {@inheritdoc}
*/
public function executeProcessing(array &$data, $view = NULL) {
if ($data['batch']) {
$batch = ViewsBulkOperationsBatch::getBatch($data);
batch_set($batch);
}
else {
$list = $data['list'];
// Populate and process queue.
if (!$this->initialized) {
$this
->initialize($data, $view);
}
if ($this
->populateQueue($list)) {
$batch_results = $this
->process();
}
$results = [
'operations' => [],
];
foreach ($batch_results as $result) {
$results['operations'][] = (string) $result;
}
ViewsBulkOperationsBatch::finished(TRUE, $results, []);
}
}
/**
* {@inheritdoc}
*/
public function getEntity(array $entity_data) {
if (!isset($entity_data[4])) {
$entity_data[4] = FALSE;
}
list(, $langcode, $entity_type_id, $id, $revision_id) = $entity_data;
// Load the entity or a specific revision depending on the given key.
$entityStorage = $this->entityTypeManager
->getStorage($entity_type_id);
$entity = $revision_id ? $entityStorage
->loadRevision($revision_id) : $entityStorage
->load($id);
if ($entity instanceof TranslatableInterface) {
$entity = $entity
->getTranslation($langcode);
}
return $entity;
}
/**
* Populate view result with selected rows.
*
* @param array $list
* User selection data.
* @param array $context
* Batch API context.
* @param int $current_batch
* The current batch index.
*/
protected function populateViewResult(array $list, array $context, $current_batch) {
if (!empty($this->bulkFormData['prepopulated'])) {
$this->view
->setItemsPerPage($this->bulkFormData['batch_size']);
$this->view
->setCurrentPage($current_batch);
$this->view
->build();
$this->moduleHandler
->invokeAll('views_pre_execute', [
$this->view,
]);
$this->view->query
->execute($this->view);
}
else {
if ($this->bulkFormData['current_page']) {
$this->view
->setCurrentPage($this->bulkFormData['current_page']);
}
$this->view
->build();
$this->moduleHandler
->invokeAll('views_pre_execute', [
$this->view,
]);
$this->view->query
->execute($this->view);
// Filter result using the $list array.
foreach ($this->view->result as $delta => $row) {
$entity = $this->viewDataService
->getEntity($row);
$unset = TRUE;
foreach ($list as $item) {
if ($item[1] === $entity
->language()
->getId() && $item[2] === $entity
->getEntityTypeId() && $item[3] === $entity
->id()) {
$unset = FALSE;
break;
}
}
if ($unset) {
unset($this->view->result[$delta]);
}
}
}
}
/**
* {@inheritdoc}
*/
public function getQueue() {
return $this->queue;
}
}