1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-09 08:17:12 +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; protected $pages;
/**
* Deleted page ID tracking
*
* @var array of [ id => id ]
*
*/
protected $deleted = array();
/**
* Delete recursion level
*
* @var int
*
*/
protected $deleteLevel = 0;
/** /**
* Construct * 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. * Unlike trash(), pages deleted here are not restorable.
* *
@@ -1121,19 +1137,35 @@ class PagesEditor extends Wire {
'uncacheAll' => false, 'uncacheAll' => false,
'recursive' => is_bool($recursive) ? $recursive : false, 'recursive' => is_bool($recursive) ? $recursive : false,
// internal use properties: // internal use properties:
// internal recursion level: incremented only by delete operations initiated by this method
'_level' => 0, '_level' => 0,
// internal delete branch: Page object when deleting a branch
'_deleteBranch' => false, '_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; if(is_array($recursive)) $options = $recursive;
$options = array_merge($defaults, $options); $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 $this->isDeleteable($page, true); // throws WireException
$numDeleted = 0; $numDeleted = 0;
$numChildren = $page->numChildren; $numChildren = $page->numChildren;
$deleteBranch = false; $deleteBranch = false;
$level++;
if($numChildren) { if($numChildren) try {
if(!$options['recursive']) { if(!$options['recursive']) {
throw new WireException("Can't delete Page $page because it has one or more children."); 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) { foreach($page->children('include=all') as $child) {
/** @var Page $child */ /** @var Page $child */
if(isset($deleted[$child->id])) continue;
$options['_level']++; $options['_level']++;
$result = $this->pages->delete($child, true, $options); $result = $this->pages->delete($child, true, $options);
$options['_level']--; $options['_level']--;
if(!$result) throw new WireException("Error doing recursive page delete, stopped by page $child"); if(!$result) throw new WireException("Error doing recursive page delete, stopped by page $child");
$numDeleted += $result; $numDeleted += $result;
} }
} catch(\Exception $e) {
$level = 0;
$deleted = array();
throw $e;
} }
// trigger a hook to indicate delete is ready and WILL occur // trigger a hook to indicate delete is ready and WILL occur
$this->pages->deleteReady($page, $options); $this->pages->deleteReady($page, $options);
$this->clear($page); $this->clear($page);
$database = $this->wire()->database; $database = $this->wire()->database;
@@ -1165,10 +1201,20 @@ class PagesEditor extends Wire {
$this->pages->sortfields()->delete($page); $this->pages->sortfields()->delete($page);
$page->setTrackChanges(false); $page->setTrackChanges(false);
$page->status = Page::statusDeleted; // no need for bitwise addition here, as this page is no longer relevant $page->status = Page::statusDeleted; // no need for bitwise addition here, as this page is no longer relevant
$this->pages->deleted($page, $options);
$numDeleted++; $numDeleted++;
$deleted[$page->id] = $numDeleted;
$this->pages->deleted($page, $options);
if($deleteBranch) $this->pages->deletedBranch($page, $options, $numDeleted); if($deleteBranch) $this->pages->deletedBranch($page, $options, $numDeleted);
if($options['uncacheAll']) $this->pages->uncacheAll($page); 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); $this->pages->debugLog('delete', $page, true);
return $options['recursive'] ? $numDeleted : true; return $options['recursive'] ? $numDeleted : true;