1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-10 00:37:02 +02:00

Update PagesEditor::delete() method to track already-deleted pages to prevent duplicate calls from nested repeaters and such.

This commit is contained in:
Ryan Cramer
2024-07-30 11:20:16 -04:00
parent bda807a574
commit 19fb83201d

View File

@@ -28,6 +28,22 @@ class PagesEditor extends Wire {
*/
protected $pages;
/**
* Deleted page ID tracking
*
* @var array of [ id => id ]
*
*/
protected $deleted = array();
/**
* Delete recursion level
*
* @var int
*
*/
protected $deleteLevel = 0;
/**
* Construct
*
@@ -1098,7 +1114,7 @@ class PagesEditor extends Wire {
}
/**
* Permanently delete a page and it's fields.
* Permanently delete a page and its fields.
*
* Unlike trash(), pages deleted here are not restorable.
*
@@ -1121,19 +1137,35 @@ class PagesEditor extends Wire {
'uncacheAll' => false,
'recursive' => is_bool($recursive) ? $recursive : false,
// internal use properties:
// internal recursion level: incremented only by delete operations initiated by this method
'_level' => 0,
// internal delete branch: Page object when deleting a branch
'_deleteBranch' => false,
);
// page IDs for all delete operations, cleared out once no longer recursive
static $deleted = array();
// external recursion level: all recursive delete operations including those initiated from hooks
static $level = 0;
if(is_array($recursive)) $options = $recursive;
$options = array_merge($defaults, $options);
// check if page already deleted in a recursive call
if(isset($deleted[$page->id])) {
// page already deleted, return result from that call
return $options['recursive'] ? $deleted[$page->id] : true;
}
$this->isDeleteable($page, true); // throws WireException
$numDeleted = 0;
$numChildren = $page->numChildren;
$deleteBranch = false;
$level++;
if($numChildren) {
if($numChildren) try {
if(!$options['recursive']) {
throw new WireException("Can't delete Page $page because it has one or more children.");
}
@@ -1144,17 +1176,21 @@ class PagesEditor extends Wire {
}
foreach($page->children('include=all') as $child) {
/** @var Page $child */
if(isset($deleted[$child->id])) continue;
$options['_level']++;
$result = $this->pages->delete($child, true, $options);
$options['_level']--;
if(!$result) throw new WireException("Error doing recursive page delete, stopped by page $child");
$numDeleted += $result;
}
} catch(\Exception $e) {
$level = 0;
$deleted = array();
throw $e;
}
// trigger a hook to indicate delete is ready and WILL occur
$this->pages->deleteReady($page, $options);
$this->clear($page);
$database = $this->wire()->database;
@@ -1165,10 +1201,20 @@ class PagesEditor extends Wire {
$this->pages->sortfields()->delete($page);
$page->setTrackChanges(false);
$page->status = Page::statusDeleted; // no need for bitwise addition here, as this page is no longer relevant
$this->pages->deleted($page, $options);
$numDeleted++;
$deleted[$page->id] = $numDeleted;
$this->pages->deleted($page, $options);
if($deleteBranch) $this->pages->deletedBranch($page, $options, $numDeleted);
if($options['uncacheAll']) $this->pages->uncacheAll($page);
if($level > 0) $level--;
if($level < 1) {
// back at root call, reset all tracking
$deleted = array();
$level = 0;
}
$this->pages->debugLog('delete', $page, true);
return $options['recursive'] ? $numDeleted : true;