1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-08 15:57:01 +02:00

Add new hooks: Pages::trashReady(), Pages::deleteBranchReady(), Pages::deletedBranch(). The deleteBranch hooks cover the case of recursive deletions where an entire branch of pages is deleted. For those cases, these hooks can be more useful than the regular deleteReady() and deleted() hooks because those two are called for every single page, rather than just for the initiating page.

This commit is contained in:
Ryan Cramer
2020-07-17 14:43:33 -04:00
parent 63a59e2317
commit 6a1b6a21ae
3 changed files with 90 additions and 22 deletions

View File

@@ -8,7 +8,7 @@
*
* This is the most used object in the ProcessWire API.
*
* ProcessWire 3.x, Copyright 2019 by Ryan Cramer
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer
* https://processwire.com
*
* @link http://processwire.com/api/variables/pages/ Offical $pages Documentation
@@ -49,10 +49,13 @@
* @method added(Page $page) Hook called when a new page has been added.
* @method moved(Page $page) Hook called when a page has been moved from one parent to another.
* @method templateChanged(Page $page) Hook called when a page template has been changed.
* @method trashReady(Page $page) Hook called when a page is about to be moved to the trash.
* @method trashed(Page $page) Hook called when a page has been moved to the trash.
* @method restored(Page $page) Hook called when a page has been moved OUT of the trash.
* @method deleteReady(Page $page) Hook called just before a page is deleted.
* @method deleted(Page $page) Hook called after a page has been deleted.
* @method deleteReady(Page $page, array $options) Hook called just before a page is deleted.
* @method deleted(Page $page, array $options) Hook called after a page has been deleted.
* @method deleteBranchReady(Page $page, array $options) Hook called before a branch of pages deleted, on initiating page only.
* @method deletedBranch(Page $page, array $options, $numDeleted) Hook called after branch of pages deleted, on initiating page only.
* @method cloneReady(Page $page, Page $copy) Hook called just before a page is cloned.
* @method cloned(Page $page, Page $copy) Hook called after a page has been successfully cloned.
* @method renamed(Page $page) Hook called after a page has been successfully renamed.
@@ -1677,6 +1680,18 @@ class Pages extends Wire {
}
}
/**
* Hook called when a Page is about to be trashed
*
* @param Page $page
* @since 3.0.163
*
*/
public function ___trashReady(Page $page) {
if($page) {} // ignore
}
/**
* Hook called when a page has been moved to the trash
*
@@ -1733,9 +1748,11 @@ class Pages extends Wire {
* #pw-hooker
*
* @param Page $page Page that is about to be deleted.
* @param array $options Options passed to delete method (since 3.0.163)
*
*/
public function ___deleteReady(Page $page) {
public function ___deleteReady(Page $page, array $options = array()) {
if($options) {} // ignore
foreach($this->types as $manager) {
if($manager->hasValidTemplate($page)) $manager->deleteReady($page);
}
@@ -1747,10 +1764,12 @@ class Pages extends Wire {
* #pw-hooker
*
* @param Page $page Page that was deleted
* @param array $options Options passed to delete method (since 3.0.163)
*
*/
public function ___deleted(Page $page) {
$this->log("Deleted page", $page);
public function ___deleted(Page $page, array $options = array()) {
if($options) {}
if(empty($options['_deleteBranch'])) $this->log("Deleted page", $page);
/** @var WireCache $cache */
$cache = $this->wire('cache');
$cache->maintenance($page);
@@ -1758,6 +1777,40 @@ class Pages extends Wire {
if($manager->hasValidTemplate($page)) $manager->deleted($page);
}
}
/**
* Hook called before a branch of pages is about to be deleted, called on root page of branch only
*
* Note: this is called only on deletions that had 'recursive' option true and 1+ children.
*
* #pw-hooker
*
* @param Page $page Page that was deleted
* @param array $options Options passed to delete method
* @since 3.0.163
*
*/
public function ___deleteBranchReady(Page $page, array $options) {
if($page && $options) {}
}
/**
* Hook called after a a branch of pages has been deleted, called on root page of branch only
*
* Note: this is called only on deletions that had 'recursive' option true and 1+ children.
*
* #pw-hooker
*
* @param Page $page Page that was the root of the branch
* @param array $options Options passed to delete method
* @param int $numDeleted Number of pages deleted
* @since 3.0.163
*
*/
public function ___deletedBranch(Page $page, array $options, $numDeleted) {
if($page && $options) {}
$this->log("Deleted branch with $numDeleted page(s)", $page);
}
/**
* Hook called when a page is about to be cloned, but before data has been touched

View File

@@ -5,7 +5,7 @@
*
* Implements page manipulation methods of the $pages API variable
*
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer
* https://processwire.com
*
*/
@@ -1044,8 +1044,8 @@ class PagesEditor extends Wire {
* @param bool|array $recursive If set to true, then this will attempt to delete all children too.
* If you don't need this argument, optionally provide $options array instead.
* @param array $options Optional settings to change behavior:
* - uncacheAll (bool): Whether to clear memory cache after delete (default=false)
* - recursive (bool): Same as $recursive argument, may be specified in $options array if preferred.
* - `uncacheAll` (bool): Whether to clear memory cache after delete (default=false)
* - `recursive` (bool): Same as $recursive argument, may be specified in $options array if preferred.
* @return bool|int Returns true (success), or integer of quantity deleted if recursive mode requested.
* @throws WireException on fatal error
*
@@ -1055,29 +1055,40 @@ class PagesEditor extends Wire {
$defaults = array(
'uncacheAll' => false,
'recursive' => is_bool($recursive) ? $recursive : false,
// internal use properties:
'_level' => 0,
'_deleteBranch' => false,
);
if(is_array($recursive)) $options = $recursive;
$options = array_merge($defaults, $options);
$this->isDeleteable($page, true); // throws WireException
$numDeleted = 0;
$numChildren = $page->numChildren;
$deleteBranch = false;
if($page->numChildren) {
if($numChildren) {
if(!$options['recursive']) {
throw new WireException("Can't delete Page $page because it has one or more children.");
} else foreach($page->children("include=all") as $child) {
}
if($options['_level'] === 0) {
$deleteBranch = true;
$options['_deleteBranch'] = $page;
$this->pages->deleteBranchReady($page, $options);
}
foreach($page->children('include=all') as $child) {
/** @var Page $child */
if($this->pages->delete($child, true, $options)) {
$numDeleted++;
} else {
throw new WireException("Error doing recursive page delete, stopped by page $child");
}
$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;
}
}
// trigger a hook to indicate delete is ready and WILL occur
$this->pages->deleteReady($page);
$this->pages->deleteReady($page, $options);
foreach($page->fieldgroup as $field) {
if(!$field->type->deletePageField($page, $field)) {
@@ -1099,7 +1110,7 @@ class PagesEditor extends Wire {
// delete entirely from pages_parents table
$this->pages->parents()->delete($page);
$database = $this->wire('database');
$database = $this->wire()->database;
$query = $database->prepare("DELETE FROM pages WHERE id=:page_id LIMIT 1"); // QA
$query->bindValue(":page_id", $page->id, \PDO::PARAM_INT);
$query->execute();
@@ -1107,8 +1118,9 @@ 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);
$this->pages->deleted($page, $options);
$numDeleted++;
if($deleteBranch) $this->pages->deletedBranch($page, $options, $numDeleted);
if($options['uncacheAll']) $this->pages->uncacheAll($page);
$this->pages->debugLog('delete', $page, true);

View File

@@ -5,7 +5,7 @@
*
* Implements page trash/restore/empty methods of the $pages API variable
*
* ProcessWire 3.x, Copyright 2018 by Ryan Cramer
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer
* https://processwire.com
*
*/
@@ -45,10 +45,13 @@ class PagesTrash extends Wire {
throw new WireException("This page (id=$page->id) may not be placed in the trash");
}
if(!$trash = $this->pages->get($this->config->trashPageID)) {
$trash = $this->pages->get($this->config->trashPageID);
if(!$trash->id) {
throw new WireException("Unable to load trash page defined by config::trashPageID");
}
$this->pages->trashReady($page);
$page->addStatus(Page::statusTrash);
if(!$page->parent->isTrash()) {