View source
<?php
namespace Drupal\views_bulk_operations\Service;
use Drupal\views\Views;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Entity\EntityInterface;
use Drupal\views_bulk_operations\ViewsBulkOperationsBatch;
class ViewsBulkOperationsActionProcessor implements ViewsBulkOperationsActionProcessorInterface {
use StringTranslationTrait;
protected $viewDataService;
protected $actionManager;
protected $currentUser;
protected $moduleHandler;
protected $initialized = FALSE;
protected $action;
protected $view;
protected $bulkFormData;
protected $queue = [];
public function __construct(ViewsbulkOperationsViewDataInterface $viewDataService, ViewsBulkOperationsActionManager $actionManager, AccountProxyInterface $currentUser, ModuleHandlerInterface $moduleHandler) {
$this->viewDataService = $viewDataService;
$this->actionManager = $actionManager;
$this->currentUser = $currentUser;
$this->moduleHandler = $moduleHandler;
}
public function initialize(array $view_data, $view = NULL) {
if ($this->initialized) {
$this->queue = [];
}
if (!isset($view_data['configuration'])) {
$view_data['configuration'] = [];
}
if (!empty($view_data['preconfiguration'])) {
$view_data['configuration'] += $view_data['preconfiguration'];
}
$this->action = $this->actionManager
->createInstance($view_data['action_id'], $view_data['configuration']);
$this
->setActionContext($view_data);
$this->bulkFormData = $view_data;
$this
->setView($view);
$this->initialized = TRUE;
}
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']);
}
$this->view->get_total_rows = TRUE;
$this->view->views_bulk_operations_processor_built = TRUE;
if (!empty($this->bulkFormData['arguments'])) {
$this->view
->setArguments($this->bulkFormData['arguments']);
}
}
public function getPageList($page) {
$list = [];
$this->viewDataService
->init($this->view, $this->view
->getDisplay(), $this->bulkFormData['relationship_id']);
if (!empty($this->bulkFormData['exposed_input'])) {
$this->view
->setExposedInput($this->bulkFormData['exposed_input']);
}
$this->view
->setItemsPerPage($this->bulkFormData['batch_size']);
$this->view
->setCurrentPage($page);
$this->view
->build();
$offset = $this->bulkFormData['batch_size'] * $page;
if ($pager_offset = $this->view->pager
->getOffset()) {
$offset += $pager_offset;
}
$this->view->query
->setLimit($this->bulkFormData['batch_size']);
$this->view->query
->setOffset($offset);
$this->moduleHandler
->invokeAll('views_pre_execute', [
$this->view,
]);
$this->view->query
->execute($this->view);
$base_field = $this->view->storage
->get('base_field');
foreach ($this->view->result as $row) {
$entity = $this->viewDataService
->getEntity($row);
$list[] = [
$row->{$base_field},
$entity
->language()
->getId(),
$entity
->getEntityTypeId(),
$entity
->id(),
];
}
return $list;
}
public function populateQueue(array $list, array &$context = []) {
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;
}
if ($batch_size) {
$batch_list = array_slice($list, $offset, $batch_size);
}
else {
$batch_list = $list;
}
$base_field_values = [];
foreach ($batch_list as $item) {
$base_field_values[] = $item[0];
}
if (empty($base_field_values)) {
return 0;
}
$this->view
->setItemsPerPage(0);
$this->view
->setCurrentPage(0);
$this->view
->setOffset(0);
$this->view
->initHandlers();
if (!empty($this->view->filter)) {
foreach ($this->view->filter as $id => $filter) {
if (!empty($filter->options['exposed'])) {
unset($this->view->filter[$id]);
}
}
}
$this->view
->build();
$base_field = $this->view->storage
->get('base_field');
if (isset($this->view->query->fields[$base_field])) {
$base_field_alias = $this->view->query->fields[$base_field]['table'] . '.' . $this->view->query->fields[$base_field]['alias'];
}
else {
$base_field_alias = $base_field;
}
$this->view->query
->addWhere(0, $base_field_alias, $base_field_values, 'IN');
$this->view->query
->build($this->view);
$this->moduleHandler
->invokeAll('views_pre_execute', [
$this->view,
]);
$this->view->query
->execute($this->view);
$this->viewDataService
->init($this->view, $this->view
->getDisplay(), $this->bulkFormData['relationship_id']);
foreach ($this->view->result as $row_index => $row) {
$found = FALSE;
$entity = $this->viewDataService
->getEntity($row);
foreach ($batch_list as $delta => $item) {
if ($row->{$base_field} === $item[0] && $entity
->language()
->getId() === $item[1]) {
$this->queue[] = $entity;
$found = TRUE;
unset($batch_list[$delta]);
break;
}
}
if (!$found) {
unset($this->view->result[$row_index]);
}
}
if (!empty($context)) {
if (!isset($context['sandbox']['total'])) {
if (empty($list)) {
$context['sandbox']['total'] = $this->viewDataService
->getTotalResults();
}
else {
$context['sandbox']['total'] = count($list);
}
}
$context['sandbox']['batch_size'] = $batch_size;
$this
->setActionContext($context);
}
if ($batch_size) {
$current_batch++;
}
$this
->setActionView();
return count($this->queue);
}
protected function setActionContext(array $context) {
if (isset($this->action) && method_exists($this->action, 'setContext')) {
$this->action
->setContext($context);
}
}
protected function setActionView() {
if (isset($this->action) && method_exists($this->action, 'setView')) {
$this->action
->setView($this->view);
}
}
public function process() {
$output = [];
foreach ($this->queue as $delta => $entity) {
if (!$entity instanceof EntityInterface) {
$output[] = $this
->t('Skipped');
unset($this->queue[$delta]);
}
}
$action_definition = $this->actionManager
->getDefinition($this->bulkFormData['action_id']);
if (!empty($action_definition['type'])) {
foreach ($this->queue as $delta => $entity) {
if ($entity
->getEntityTypeId() !== $action_definition['type']) {
$output[] = $this
->t('Entity type not supported');
unset($this->queue[$delta]);
}
}
}
foreach ($this->queue as $delta => $entity) {
if (!$this->action
->access($entity, $this->currentUser)) {
$output[] = $this
->t('Access denied');
unset($this->queue[$delta]);
}
}
$results = $this->action
->executeMultiple($this->queue);
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;
}
public function executeProcessing(array &$data, $view = NULL) {
if ($data['batch']) {
$batch = ViewsBulkOperationsBatch::getBatch($data);
batch_set($batch);
}
else {
$list = $data['list'];
if (!$this->initialized) {
$this
->initialize($data, $view);
}
if (empty($list)) {
$list = $this
->getPageList(0);
}
if ($this
->populateQueue($list)) {
$batch_results = $this
->process();
}
$results = [
'operations' => [],
];
foreach ($batch_results as $result) {
$results['operations'][] = (string) $result;
}
ViewsBulkOperationsBatch::finished(TRUE, $results, []);
}
}
}