1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-12 17:54:44 +02:00

Update ProcessPageEdit to enable removal of system status when superuser in advanced mode (though I don't recommend using it unless you are trying to fix something that's broken), plus make a couple more status options available to superuser in advanced mode. Also some other unrelated and minor optimizations in this module.

This commit is contained in:
Ryan Cramer
2021-06-30 09:38:10 -04:00
parent 9ea37575ad
commit ecd491c5d8

View File

@@ -8,7 +8,7 @@
* For more details about how Process modules work, please see: * For more details about how Process modules work, please see:
* /wire/core/Process.php * /wire/core/Process.php
* *
* ProcessWire 3.x, Copyright 2018 by Ryan Cramer * ProcessWire 3.x, Copyright 2021 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* @property string $noticeUnknown * @property string $noticeUnknown
@@ -54,7 +54,7 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
return array( return array(
'title' => 'Page Edit', 'title' => 'Page Edit',
'summary' => 'Edit a Page', 'summary' => 'Edit a Page',
'version' => 109, 'version' => 110,
'permanent' => true, 'permanent' => true,
'permission' => 'page-edit', 'permission' => 'page-edit',
'icon' => 'edit', 'icon' => 'edit',
@@ -345,8 +345,13 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
$this->set('viewAction', 'this'); $this->set('viewAction', 'this');
return parent::__construct(); return parent::__construct();
} }
/**
* Wired to API
*
*/
public function wired() { public function wired() {
parent::wired();
if($this->wire('process') instanceof WirePageEditor) { if($this->wire('process') instanceof WirePageEditor) {
// keep existing process, which may be building on top of this one // keep existing process, which may be building on top of this one
} else { } else {
@@ -437,7 +442,7 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
if($context) $this->requestContext = $this->sanitizer->name($context); if($context) $this->requestContext = $this->sanitizer->name($context);
// optional language GET var // optional language GET var
$languages = $this->wire('languages'); $languages = $this->wire()->languages;
if($languages) { if($languages) {
$this->hasLanguagePageNames = $this->modules->isInstalled('LanguageSupportPageNames'); $this->hasLanguagePageNames = $this->modules->isInstalled('LanguageSupportPageNames');
if($this->hasLanguagePageNames) { if($this->hasLanguagePageNames) {
@@ -476,40 +481,35 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
protected function ___loadPage($id) { protected function ___loadPage($id) {
/** @var Page|NullPage $page */ /** @var Page|NullPage $page */
$page = $this->wire('pages')->get((int) $id); $page = $this->wire()->pages->get((int) $id);
if($page instanceof NullPage) { if($page instanceof NullPage) {
throw new WireException($this->noticeUnknown); // page doesn't exist throw new WireException($this->noticeUnknown); // page doesn't exist
} }
$editable = $page->editable(); $editable = $page->editable();
/** @var User $user */
$user = $this->user;
/** @var Config $config */
$config = $this->config;
/** @var Config $config */
$input = $this->input;
if($page instanceof User) { if($page instanceof User) {
// special case when page is a User // special case when page is a User
$userAdmin = $this->user->hasPermission('user-admin');
$userAdmin = $user->hasPermission('user-admin'); if($userAdmin && $this->wire()->process != 'ProcessUser') {
$field = $input->get('field') ? $this->wire('fields')->get($input->get->fieldName('field')) : null;
if($userAdmin && $this->wire('process') != 'ProcessUser') {
// only allow user pages to be edited from the access section (at least for non-superusers) // only allow user pages to be edited from the access section (at least for non-superusers)
$this->session->redirect($config->urls->admin . 'access/users/edit/?id=' . $page->id); $this->session->redirect($this->config->urls->admin . 'access/users/edit/?id=' . $page->id);
}
} else if(!$userAdmin && $page->id === $user->id && $field && $config->ajax) { if(!$userAdmin && $page->id === $this->user->id && $this->config->ajax) {
// user is editing themself and we're responding to an ajax request for a field // user that lacks user-admin permission editing themself during ajax request
/** @var PagePermissions $pagePermissions */ $fieldName = $this->input->get->fieldName('field');
$pagePermissions = $this->modules->get('PagePermissions'); $field = $fieldName ? $this->wire()->fields->get($fieldName) : null;
$editable = $pagePermissions->userFieldEditable($field); if($field instanceof Field) {
// prevent a later potential redirect to user editor // respond to ajax request for field that is editable
if($editable) $this->setEditor = false; /** @var PagePermissions $pagePermissions */
$pagePermissions = $this->modules->get('PagePermissions');
$editable = $pagePermissions->userFieldEditable($field);
// prevent a later potential redirect to user editor
if($editable) $this->setEditor = false;
}
} }
} }
@@ -633,7 +633,8 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
$out .= "</ul>"; $out .= "</ul>";
} }
$out .= "<scr" . "ipt>initPageEditForm();</script>"; // ends up being slightly faster than ready() (or at least appears that way) $func = 'initPageEditForm();'; // to prevent IDE from flagging as unknown function
$out .= "<scr" . "ipt>$func</script>"; // ends up being slightly faster than ready() (or at least appears that way)
return $out; return $out;
} }
@@ -665,6 +666,7 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
if($this->requestModal) return array(); if($this->requestModal) return array();
$viewable = $this->page->viewable(); $viewable = $this->page->viewable();
$process = $this->wire()->process;
$actions = array(); $actions = array();
$actions['exit'] = array( $actions['exit'] = array(
@@ -680,9 +682,8 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
'label' => $this->_('%s + View'), 'label' => $this->_('%s + View'),
'class' => '', 'class' => '',
); );
if($this->wire('process') == $this && $this->page->id > 1) { if("$process" === "$this" && $this->page->id > 1) {
$parent = $this->page->parent(); $parent = $this->page->parent();
if($parent->addable()) $actions['add'] = array( if($parent->addable()) $actions['add'] = array(
'value' => 'add', 'value' => 'add',
@@ -1459,14 +1460,10 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
*/ */
protected function buildFormPrevPaths() { protected function buildFormPrevPaths() {
/** @var WireInput $input */ $input = $this->input;
$input = $this->wire('input'); $modules = $this->modules;
/** @var Modules $modules */ $sanitizer = $this->sanitizer;
$modules = $this->wire('modules'); $languages = $this->wire()->languages;
/** @var Sanitizer $sanitizer */
$sanitizer = $this->wire('sanitizer');
/** @var Languages|null $languages */
$languages = $this->wire('languages');
if($this->isPost && $input->post('_prevpath_add') === null) return null; if($this->isPost && $input->post('_prevpath_add') === null) return null;
if(!$modules->isInstalled('PagePathHistory')) return null; if(!$modules->isInstalled('PagePathHistory')) return null;
@@ -1697,34 +1694,14 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
protected function buildFormStatus() { protected function buildFormStatus() {
$status = (int) $this->page->status; $status = (int) $this->page->status;
$statuses = array();
$debug = $this->config->debug; $debug = $this->config->debug;
$advanced = $this->config->advanced; $statuses = $this->getAllowedStatuses();
/** @var InputfieldCheckboxes $field */ /** @var InputfieldCheckboxes $field */
$field = $this->modules->get('InputfieldCheckboxes'); $field = $this->modules->get('InputfieldCheckboxes');
$field->attr('name', 'status'); $field->attr('name', 'status');
$field->icon = 'sliders'; $field->icon = 'sliders';
if(!$this->page->template->noUnpublish && $this->page->publishable()) {
$statuses[Page::statusUnpublished] = $this->_('Unpublished: Not visible on site'); // Settings: Unpublished status checkbox label
}
if($this->user->hasPermission('page-hide', $this->page)) {
$statuses[Page::statusHidden] = $this->_('Hidden: Excluded from lists and searches'); // Settings: Hidden status checkbox label
}
if($this->user->hasPermission('page-lock', $this->page)) {
$statuses[Page::statusLocked] = $this->_('Locked: Not editable'); // Settings: Locked status checkbox label
}
if($this->user->isSuperuser()) {
$statuses[Page::statusUnique] = sprintf($this->_('Unique: Require page name “%s” to be globally unique'), $this->page->name) .
($this->wire('languages') ? ' ' . $this->_('(in default language only)') : '');
if($advanced) {
$statuses[Page::statusSystemID] = "System: Non-deleteable and locked ID (status not removeable via API)";
$statuses[Page::statusSystem] = "System: Non-deleteable and locked ID, name, template, parent (status not removeable via API)";
}
}
$value = array(); $value = array();
foreach($statuses as $s => $label) { foreach($statuses as $s => $label) {
@@ -1803,7 +1780,7 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
if(!$this->page->isTrash()) return false; if(!$this->page->isTrash()) return false;
if(!$this->page->restorable()) return false; if(!$this->page->restorable()) return false;
$info = $this->wire('pages')->trasher()->getRestoreInfo($this->page); $info = $this->wire()->pages->trasher()->getRestoreInfo($this->page);
if(!$info['restorable']) return false; if(!$info['restorable']) return false;
/** @var InputfieldWrapper $wrapper */ /** @var InputfieldWrapper $wrapper */
@@ -2195,7 +2172,7 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
$this->page->setQuietly('_forceAddStatus', 0); $this->page->setQuietly('_forceAddStatus', 0);
} }
$languages = $this->wire('languages'); $languages = $this->wire()->languages;
$errorAction = (int) $this->page->template->errorAction; $errorAction = (int) $this->page->template->errorAction;
foreach($form as $inputfield) { foreach($form as $inputfield) {
@@ -2383,34 +2360,30 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
*/ */
protected function processInputStatus(Inputfield $inputfield) { protected function processInputStatus(Inputfield $inputfield) {
$status = $inputfield->value; $inputStatusFlags = $inputfield->val();
if(!is_array($inputStatusFlags)) $inputStatusFlags = array();
foreach($inputStatusFlags as $k => $v) $inputStatusFlags[$k] = (int) $v;
$allowedStatusFlags = array_keys($this->getAllowedStatuses());
$statusLabels = array_flip(Page::getStatuses());
$value = $this->page->status; $value = $this->page->status;
if(!is_array($status)) $status = array(); foreach($allowedStatusFlags as $flag) {
if(in_array($flag, $inputStatusFlags, true)) {
$statusFlags = array(); if($value & $flag) {
if($this->user->hasPermission('page-hide', $this->page)) $statusFlags[] = Page::statusHidden; // already has flag
if($this->page->publishable()) $statusFlags[] = Page::statusUnpublished; } else {
if($this->user->hasPermission('page-lock', $this->page)) $statusFlags[] = Page::statusLocked; $value = $value | $flag; // add status
$this->message(sprintf($this->_('Added status: %s'), $statusLabels[$flag]), Notice::debug);
if($this->user->isSuperuser()) { }
$statusFlags[] = Page::statusUnique;
if($this->config->advanced) {
$statusFlags[] = Page::statusSystemID;
$statusFlags[] = Page::statusSystem;
}
}
foreach($statusFlags as $flag) {
if(in_array($flag, $status)) {
if(!($value & $flag)) $value = $value | $flag;
} else if($value & $flag) { } else if($value & $flag) {
$value = $value & ~$flag; $value = $value & ~$flag; // remove flag
$this->message(sprintf($this->_('Removed status: %s'), $statusLabels[$flag]), Notice::debug);
} }
} }
$this->page->status = $value; $this->page->status = $value;
return true; return true;
} }
@@ -2500,6 +2473,7 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
if(!$this->ajaxEditable($page)) throw new WirePermissionException($this->noticeNoAccess); if(!$this->ajaxEditable($page)) throw new WirePermissionException($this->noticeNoAccess);
$this->session->CSRF->validate(); // throws exception when invalid $this->session->CSRF->validate(); // throws exception when invalid
/** @var InputfieldWrapper $form */
$form = $this->wire(new InputfieldWrapper()); $form = $this->wire(new InputfieldWrapper());
$form->useDependencies = false; $form->useDependencies = false;
$keys = array(); $keys = array();
@@ -2963,6 +2937,61 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
return $this->tabs; return $this->tabs;
} }
/**
* Get allowed page statuses
*
* @return array Array of [ statusFlagInteger => 'Status flag label' ]
* @since 3.0.181
*
*/
public function getAllowedStatuses() {
$page = $this->page;
$config = $this->wire()->config;
$statuses = array();
$superuser = $this->user->isSuperuser();
if(!$this->page->template->noUnpublish && $this->page->publishable()) {
$statuses[Page::statusUnpublished] = $this->_('Unpublished: Not visible on site'); // Settings: Unpublished status checkbox label
}
if($this->user->hasPermission('page-hide', $this->page)) {
$statuses[Page::statusHidden] = $this->_('Hidden: Excluded from lists and searches'); // Settings: Hidden status checkbox label
}
if($this->user->hasPermission('page-lock', $this->page)) {
$statuses[Page::statusLocked] = $this->_('Locked: Not editable'); // Settings: Locked status checkbox label
}
if($superuser) {
$uniqueNote = ($this->wire('languages') ? ' ' . $this->_('(in default language only)') : '');
$statuses[Page::statusUnique] = sprintf($this->_('Unique: Require page name “%s” to be globally unique'), $this->page->name) . $uniqueNote;
}
if($superuser && $config->advanced) {
// additional statuses available to superuser in advanced mode
$hasSystem = $page->hasStatus(Page::statusSystem) || $page->hasStatus(Page::statusSystemID) || $page->hasStatus(Page::statusSystemOverride);
$statuses[Page::statusSystem] = "System: Non-deleteable and locked ID, name, template, parent (status not removeable without override)";
$statuses[Page::statusSystemID] = "System ID: Non-deleteable and locked ID (status not removeable without override)";
if($hasSystem) $statuses[Page::statusSystemOverride] = "System Override: Override (must be added temporarily in its own save before system status can be removed)";
$statuses[Page::statusDraft] = "Draft: Page has a separate draft version";
$statuses[Page::statusOn] = "On: Internal toggle when combined with other statuses (only for specific cases, otherwise ignored)";
/*
* Additional statuses that are possible but shouldn't be editable (uncomment temporarily if needed)
*
* $statuses[Page::statusTemp] = "Temp: Unpublished page more than 1 day old may be automatically deleted";
* $statuses[Page::statusFlagged] = "Flagged: Page is flagged as incomplete, needing review, or having some issue";
* $statuses[Page::statusTrash] = "Internal trash: Indicates that page is in the trash";
* $statuses[Page::statusReserved] = "Internal-reserved: Status reserved for future use";
* $statuses[Page::statusInternal] = "Internal-internal: Status for internal or future use";
*
*/
}
return $statuses;
}
/** /**
* Get PageBookmarks array * Get PageBookmarks array
* *
@@ -3147,11 +3176,16 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
* *
*/ */
public function getModuleConfigInputfields(array $data) { public function getModuleConfigInputfields(array $data) {
$config = $this->wire()->config;
$pages = $this->wire()->pages;
$modules = $this->wire()->modules;
$inputfields = new InputfieldWrapper(); $inputfields = new InputfieldWrapper();
$this->wire($inputfields);
$f = $this->wire('modules')->get('InputfieldRadios'); $this->wire($inputfields);
/** @var InputfieldRadios $f */
$f = $modules->get('InputfieldRadios');
$f->name = 'viewAction'; $f->name = 'viewAction';
$f->label = $this->_('Default "view" location/action'); $f->label = $this->_('Default "view" location/action');
$f->description = $this->_('The default type of action used when the "view" tab is clicked on in the page editor.'); $f->description = $this->_('The default type of action used when the "view" tab is clicked on in the page editor.');
@@ -3161,7 +3195,8 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
$f->addOption($name, $label); $f->addOption($name, $label);
} }
$configData = $this->wire('config')->pageEdit; /** @var array $configData */
$configData = $config->pageEdit;
if(isset($data['viewAction'])) { if(isset($data['viewAction'])) {
$f->attr('value', $data['viewAction']); $f->attr('value', $data['viewAction']);
} else if(is_array($configData) && !empty($configData['viewNew'])) { } else if(is_array($configData) && !empty($configData['viewNew'])) {
@@ -3174,8 +3209,8 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
$bookmarks = $this->getPageBookmarks(); $bookmarks = $this->getPageBookmarks();
$bookmarks->addConfigInputfields($inputfields); $bookmarks->addConfigInputfields($inputfields);
$admin = $this->wire('pages')->get($this->wire('config')->adminRootPageID); $admin = $pages->get($config->adminRootPageID);
$page = $this->wire('pages')->get($admin->path . 'page/edit/'); $page = $pages->get($admin->path . 'page/edit/');
$bookmarks->checkProcessPage($page); $bookmarks->checkProcessPage($page);
return $inputfields; return $inputfields;