From bf62fbb897dabb4458df47d260d894340d6f1571 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Thu, 28 Jun 2018 12:59:59 -0400 Subject: [PATCH] Upgrade ProcessPageList to support showing and use of trash to non-superusers, for pages user is allowed to edit --- .../ProcessPageList/ProcessPageList.module | 4 +- .../ProcessPageListActions.php | 39 +++++----- .../ProcessPageListRenderJSON.php | 72 +++++++++++++++++-- 3 files changed, 88 insertions(+), 27 deletions(-) diff --git a/wire/modules/Process/ProcessPageList/ProcessPageList.module b/wire/modules/Process/ProcessPageList/ProcessPageList.module index 16683816..b979aaf6 100644 --- a/wire/modules/Process/ProcessPageList/ProcessPageList.module +++ b/wire/modules/Process/ProcessPageList/ProcessPageList.module @@ -8,7 +8,7 @@ * For more details about how Process modules work, please see: * /wire/core/Process.php * - * ProcessWire 3.x, Copyright 2017 by Ryan Cramer + * ProcessWire 3.x, Copyright 2018 by Ryan Cramer * https://processwire.com * * @property bool $showRootPage Whether root page (like home) should be shown. @@ -37,7 +37,7 @@ class ProcessPageList extends Process implements ConfigurableModule { return array( 'title' => 'Page List', 'summary' => 'List pages in a hierarchal tree structure', - 'version' => 119, + 'version' => 120, 'permanent' => true, 'permission' => 'page-edit', 'icon' => 'sitemap', diff --git a/wire/modules/Process/ProcessPageList/ProcessPageListActions.php b/wire/modules/Process/ProcessPageList/ProcessPageListActions.php index 1d974a25..57554d95 100644 --- a/wire/modules/Process/ProcessPageList/ProcessPageListActions.php +++ b/wire/modules/Process/ProcessPageList/ProcessPageListActions.php @@ -167,25 +167,26 @@ class ProcessPageListActions extends Wire { } } - if($this->superuser) { - $trashIcon = " "; - if($page->trashable()) { - $extras['trash'] = array( - 'cn' => 'Trash', - 'name' => $trashIcon . $this->actionLabels['trash'], - 'url' => "$adminUrl?action=trash&id=$page->id", - 'ajax' => true - ); - } else if($trash) { - if(preg_match('/^(' . $page->id . ')\.\d+\.\d+_.+$/', $page->name)) { - $extras['restore'] = array( - 'cn' => 'Restore', - 'name' => $trashIcon . $this->actionLabels['restore'], - 'url' => "$adminUrl?action=restore&id=$page->id", - 'ajax' => true - ); - } - } + $trashable = $page->trashable(); + $trashIcon = " "; + if($trashable && !$user->isSuperuser()) { + // do not allow non-superuser ability to trash branches of pages, only individual pages + if($page->numChildren(1) > 0) $trashable = false; + } + if($trashable) { + $extras['trash'] = array( + 'cn' => 'Trash', + 'name' => $trashIcon . $this->actionLabels['trash'], + 'url' => "$adminUrl?action=trash&id=$page->id", + 'ajax' => true + ); + } else if($trash && $page->restorable()) { + $extras['restore'] = array( + 'cn' => 'Restore', + 'name' => $trashIcon . $this->actionLabels['restore'], + 'url' => "$adminUrl?action=restore&id=$page->id", + 'ajax' => true + ); } return $extras; diff --git a/wire/modules/Process/ProcessPageList/ProcessPageListRenderJSON.php b/wire/modules/Process/ProcessPageList/ProcessPageListRenderJSON.php index 0ee77df6..5a5563e9 100644 --- a/wire/modules/Process/ProcessPageList/ProcessPageListRenderJSON.php +++ b/wire/modules/Process/ProcessPageList/ProcessPageListRenderJSON.php @@ -9,6 +9,8 @@ require_once(dirname(__FILE__) . '/ProcessPageListRender.php'); class ProcessPageListRenderJSON extends ProcessPageListRender { protected $systemIDs = array(); + + protected $allowTrash = null; public function __construct(Page $page, PageArray $children) { @@ -22,6 +24,44 @@ class ProcessPageListRenderJSON extends ProcessPageListRender { ); } + /** + * Are we allowed to display the Trash page? + * + * @return bool + * + */ + protected function allowTrash() { + + if($this->allowTrash !== null) return $this->allowTrash; + + /** @var User $user */ + $user = $this->wire('user'); + + $petc = 'page-edit-trash-created'; + if(!$this->wire('permissions')->has($petc)) $petc = false; + + if($user->isSuperuser()) { + // superuser + $this->allowTrash = true; + } else if($user->hasPermission('page-delete')) { + // has page-delete globally + $this->allowTrash = true; + } else if($petc && $user->hasPermission($petc)) { + // has page-edit-trash-created globally + $this->allowTrash = true; + } else if($user->hasPermission('page-delete', true)) { + // has page-delete added specifically at a template + $this->allowTrash = true; + } else if($petc && $user->hasPermission($petc, true)) { + // has page-edit-trash-created added specifically at a template + $this->allowTrash = true; + } else { + $this->allowTrash = false; + } + + return $this->allowTrash; + } + public function renderChild(Page $page) { $outputFormatting = $page->outputFormatting; @@ -59,12 +99,24 @@ class ProcessPageListRenderJSON extends ProcessPageListRender { } if($page->id == $this->config->trashPageID) { - $note = "< " . $this->_("Trash open: drag pages below here to trash them"); // Message that appears next to the Trash page when open + $note = ''; + if($this->superuser) { + $note = "< " . $this->_("Trash open: drag pages below here to trash them"); // Message that appears next to the Trash page when open + } $icons = array('trash-o'); // override any other icons + $numChildren = $page->numChildren(false); + if($numChildren > 0 && !$this->superuser) { + // manually count quantity that are listable in the trash + $numChildren = 0; + foreach($page->children("include=all") as $child) { + if($child->listable()) $numChildren++; + } + } } else { if($page->hasStatus(Page::statusTemp)) $icons[] = 'bolt'; if($page->hasStatus(Page::statusLocked)) $icons[] = 'lock'; if($page->hasStatus(Page::statusDraft)) $icons[] = 'paperclip'; + $numChildren = $page->numChildren(1); } if(!$label) $label = $this->getPageLabel($page); @@ -77,7 +129,7 @@ class ProcessPageListRenderJSON extends ProcessPageListRender { 'id' => $page->id, 'label' => $label, 'status' => $page->status, - 'numChildren' => $page->numChildren(1), + 'numChildren' => $numChildren, 'path' => $page->template->slashUrls || $page->id == 1 ? $page->path() : rtrim($page->path(), '/'), 'template' => $page->template->name, //'rm' => $this->superuser && $page->trashable(), @@ -97,26 +149,34 @@ class ProcessPageListRenderJSON extends ProcessPageListRender { public function render() { $children = array(); - $extraPages = array(); // pages forced to bottom of list - $id404 = $this->wire('config')->http404PageID; + $config = $this->wire('config'); + $idTrash = $config->trashPageID; + $id404 = $config->http404PageID; + $page404 = null; foreach($this->children as $page) { if(!$this->superuser && !$page->listable()) continue; if($page->id == $id404 && !$this->superuser) { // allow showing 404 page, only if it's editable + $page404 = $page; if(!$page->editable()) continue; } else if(in_array($page->id, $this->systemIDs)) { - $extraPages[] = $page; + if($this->superuser) $extraPages[$page->id] = $page; continue; } $child = $this->renderChild($page); $children[] = $child; } + + if(!$this->superuser && $page404 && $page404->parent_id == 1 && !isset($extraPages[$idTrash])) { + $pageTrash = $this->wire('pages')->get($idTrash); + if($pageTrash->id && $pageTrash->listable()) $extraPages[$pageTrash->id] = $pageTrash; + } - if($this->superuser) foreach($extraPages as $page) { + foreach($extraPages as $page) { $children[] = $this->renderChild($page); }