monster_menus-9.0.x-dev/src/GetTreeIterator/ContentDeleteIter.php
src/GetTreeIterator/ContentDeleteIter.php
<?php
namespace Drupal\monster_menus\GetTreeIterator;
use Drupal\Core\Database\Database;
use Drupal\monster_menus\Constants;
use Drupal\monster_menus\Entity\MMTree;
use Drupal\monster_menus\GetTreeIterator;
use Drupal\Core\Database\Connection;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
class ContentDeleteIter extends GetTreeIterator {
/**
* Database Service Object.
*
* @var Connection
*/
protected $database;
public $delete_nodes, $allow_non_empty_bin, $count = 0, $err = '', $start_time, $limit_time;
private $first, $mmtids = [], $bins = [], $is_bin = FALSE, $is_cli;
/**
* Constructs a ContentDeleteIter object.
*
* @param $delete_nodes
* If TRUE, also delete any nodes using these IDs (TRUE)
* @param $allow_non_empty_bin
* If TRUE, allow a non-empty recycle bin at the top level to be deleted
* (FALSE)
*/
public function __construct($delete_nodes, $allow_non_empty_bin, $start_time, $limit_time) {
$this->delete_nodes = $delete_nodes;
$this->allow_non_empty_bin = $allow_non_empty_bin;
$this->is_cli = !isset($_SERVER['SERVER_SOFTWARE']) && PHP_SAPI === 'cli';
$this->database = Database::getConnection();
$this->start_time = $start_time;
$this->limit_time = $limit_time;
}
/**
* {@inheritdoc}
*/
public function iterate($item) {
$this->count++;
if ($this->is_cli && ($this->count % 10) == 0) {
print $this->count . "\r";
}
if (!$item->level) {
$this->first = $item;
if ($item->name == Constants::MM_ENTRY_NAME_RECYCLE) {
$this->is_bin = TRUE;
}
}
else if ($this->is_bin && $item->level == 1 && !$this->allow_non_empty_bin) {
$this->err = t('This is a recycle bin that is not empty.');
return 0;
}
if (!$item->perms[Constants::MM_PERMS_WRITE] && $item->name != Constants::MM_ENTRY_NAME_RECYCLE) {
$msg = $item->mmtid == $this->first->mmtid ?
'You do not have permission to delete the page %name' :
'You cannot delete this page because you do not have permission to delete the sub-page %name';
$this->err = t($msg, ['%name' => $item->name]);
return 0;
}
$this->mmtids[] = $item->mmtid;
if ($item->name == Constants::MM_ENTRY_NAME_RECYCLE) {
$this->bins[] = $item->mmtid;
}
return 1;
}
/**
* Perform the deletion.
*/
public function delete() {
if ($this->err) {
return;
}
$all_nids = [];
// Move the parent page to the end of the list so it gets deleted last.
array_push($this->mmtids, array_shift($this->mmtids));
// Start a transaction.
$txn = $this->database->startTransaction();
$remain = count($this->mmtids);
foreach (array_chunk($this->mmtids, 50) as $mmtids) {
if ($this->is_cli) {
print $remain . " \r";
$remain -= count($mmtids);
}
$chunk_nids = [];
if ($this->delete_nodes) {
$storage_handler = \Drupal::entityTypeManager()->getStorage('node');
/** @var NodeInterface $node */
foreach (array_chunk(Node::loadMultiple(mm_content_get_nids_by_mmtid($mmtids, 0, TRUE)), 50, TRUE) as $nodes_chunk) {
foreach ($nodes_chunk as $nid => $node) {
if (!$node->access('delete')) {
unset($nodes_chunk[$nid]);
}
}
$chunk_nids = array_merge($chunk_nids, array_keys($nodes_chunk));
$storage_handler->delete($nodes_chunk);
if ($this->limit_time && time() - $this->start_time > $this->limit_time) {
$all_nids = array_merge($all_nids, $chunk_nids);
\Drupal::moduleHandler()->invokeAll('mm_delete', [[], $all_nids]);
// End transaction.
unset($txn);
mm_content_notify_change('delete_node', NULL, $all_nids);
$timeout_msg = t('mm_content_delete() time limit reached. Deletion will continue the next time this function is called.');
if ($this->is_cli) {
print $timeout_msg . "\n";
}
\Drupal::logger('mm')->notice($timeout_msg);
$this->err = t('Timeout.');
return;
}
}
}
MMTree::deleteMultiple($mmtids);
// Invoke mm_delete hooks.
\Drupal::moduleHandler()->invokeAll('mm_delete', [$mmtids, $chunk_nids]);
$all_nids = array_merge($all_nids, $chunk_nids);
}
// End transaction.
unset($txn);
if ($this->mmtids) {
mm_content_notify_change('delete_page', $this->mmtids);
}
if ($all_nids) {
mm_content_notify_change('delete_node', NULL, $all_nids);
}
// Clear caches for this entry and its children.
mm_content_clear_caches($this->mmtids);
mm_content_clear_routing_cache_tagged($this->mmtids);
if ($this->bins) {
$this->database->delete('mm_tree_revision')
->condition('mmtid', $this->bins, 'IN')
->execute();
}
mm_content_clear_caches($this->first->parent); // clear caches for parent
\Drupal::logger('mm')->notice('Deleted %name (%alias) mmtids = %mmtids', [
'%name' => $this->first->name,
'%alias' => $this->first->alias,
'%mmtids' => join(',', array_slice($this->mmtids, 0, 10)) . (count($this->mmtids) > 10 ? '...' : ''),
]);
}
}
