1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-12 09:44:38 +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:
* /wire/core/Process.php
*
* ProcessWire 3.x, Copyright 2018 by Ryan Cramer
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
* https://processwire.com
*
* @property string $noticeUnknown
@@ -54,7 +54,7 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
return array(
'title' => 'Page Edit',
'summary' => 'Edit a Page',
'version' => 109,
'version' => 110,
'permanent' => true,
'permission' => 'page-edit',
'icon' => 'edit',
@@ -345,8 +345,13 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
$this->set('viewAction', 'this');
return parent::__construct();
}
/**
* Wired to API
*
*/
public function wired() {
parent::wired();
if($this->wire('process') instanceof WirePageEditor) {
// keep existing process, which may be building on top of this one
} else {
@@ -437,7 +442,7 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
if($context) $this->requestContext = $this->sanitizer->name($context);
// optional language GET var
$languages = $this->wire('languages');
$languages = $this->wire()->languages;
if($languages) {
$this->hasLanguagePageNames = $this->modules->isInstalled('LanguageSupportPageNames');
if($this->hasLanguagePageNames) {
@@ -476,40 +481,35 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
protected function ___loadPage($id) {
/** @var Page|NullPage $page */
$page = $this->wire('pages')->get((int) $id);
$page = $this->wire()->pages->get((int) $id);
if($page instanceof NullPage) {
throw new WireException($this->noticeUnknown); // page doesn't exist
}
$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) {
// special case when page is a User
$userAdmin = $this->user->hasPermission('user-admin');
$userAdmin = $user->hasPermission('user-admin');
$field = $input->get('field') ? $this->wire('fields')->get($input->get->fieldName('field')) : null;
if($userAdmin && $this->wire('process') != 'ProcessUser') {
if($userAdmin && $this->wire()->process != 'ProcessUser') {
// 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) {
// user is editing themself and we're responding to an ajax request for a field
/** @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;
if(!$userAdmin && $page->id === $this->user->id && $this->config->ajax) {
// user that lacks user-admin permission editing themself during ajax request
$fieldName = $this->input->get->fieldName('field');
$field = $fieldName ? $this->wire()->fields->get($fieldName) : null;
if($field instanceof Field) {
// respond to ajax request for field that is editable
/** @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 .= "<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;
}
@@ -665,6 +666,7 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
if($this->requestModal) return array();
$viewable = $this->page->viewable();
$process = $this->wire()->process;
$actions = array();
$actions['exit'] = array(
@@ -680,9 +682,8 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
'label' => $this->_('%s + View'),
'class' => '',
);
if($this->wire('process') == $this && $this->page->id > 1) {
if("$process" === "$this" && $this->page->id > 1) {
$parent = $this->page->parent();
if($parent->addable()) $actions['add'] = array(
'value' => 'add',
@@ -1459,14 +1460,10 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
*/
protected function buildFormPrevPaths() {
/** @var WireInput $input */
$input = $this->wire('input');
/** @var Modules $modules */
$modules = $this->wire('modules');
/** @var Sanitizer $sanitizer */
$sanitizer = $this->wire('sanitizer');
/** @var Languages|null $languages */
$languages = $this->wire('languages');
$input = $this->input;
$modules = $this->modules;
$sanitizer = $this->sanitizer;
$languages = $this->wire()->languages;
if($this->isPost && $input->post('_prevpath_add') === null) return null;
if(!$modules->isInstalled('PagePathHistory')) return null;
@@ -1697,34 +1694,14 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
protected function buildFormStatus() {
$status = (int) $this->page->status;
$statuses = array();
$debug = $this->config->debug;
$advanced = $this->config->advanced;
$statuses = $this->getAllowedStatuses();
/** @var InputfieldCheckboxes $field */
$field = $this->modules->get('InputfieldCheckboxes');
$field->attr('name', 'status');
$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();
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->restorable()) return false;
$info = $this->wire('pages')->trasher()->getRestoreInfo($this->page);
$info = $this->wire()->pages->trasher()->getRestoreInfo($this->page);
if(!$info['restorable']) return false;
/** @var InputfieldWrapper $wrapper */
@@ -2195,7 +2172,7 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
$this->page->setQuietly('_forceAddStatus', 0);
}
$languages = $this->wire('languages');
$languages = $this->wire()->languages;
$errorAction = (int) $this->page->template->errorAction;
foreach($form as $inputfield) {
@@ -2383,34 +2360,30 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
*/
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;
if(!is_array($status)) $status = array();
$statusFlags = array();
if($this->user->hasPermission('page-hide', $this->page)) $statusFlags[] = Page::statusHidden;
if($this->page->publishable()) $statusFlags[] = Page::statusUnpublished;
if($this->user->hasPermission('page-lock', $this->page)) $statusFlags[] = Page::statusLocked;
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;
foreach($allowedStatusFlags as $flag) {
if(in_array($flag, $inputStatusFlags, true)) {
if($value & $flag) {
// already has flag
} else {
$value = $value | $flag; // add status
$this->message(sprintf($this->_('Added status: %s'), $statusLabels[$flag]), Notice::debug);
}
} 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;
return true;
}
@@ -2500,6 +2473,7 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
if(!$this->ajaxEditable($page)) throw new WirePermissionException($this->noticeNoAccess);
$this->session->CSRF->validate(); // throws exception when invalid
/** @var InputfieldWrapper $form */
$form = $this->wire(new InputfieldWrapper());
$form->useDependencies = false;
$keys = array();
@@ -2963,6 +2937,61 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
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
*
@@ -3147,11 +3176,16 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
*
*/
public function getModuleConfigInputfields(array $data) {
$config = $this->wire()->config;
$pages = $this->wire()->pages;
$modules = $this->wire()->modules;
$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->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.');
@@ -3161,7 +3195,8 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
$f->addOption($name, $label);
}
$configData = $this->wire('config')->pageEdit;
/** @var array $configData */
$configData = $config->pageEdit;
if(isset($data['viewAction'])) {
$f->attr('value', $data['viewAction']);
} else if(is_array($configData) && !empty($configData['viewNew'])) {
@@ -3174,8 +3209,8 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
$bookmarks = $this->getPageBookmarks();
$bookmarks->addConfigInputfields($inputfields);
$admin = $this->wire('pages')->get($this->wire('config')->adminRootPageID);
$page = $this->wire('pages')->get($admin->path . 'page/edit/');
$admin = $pages->get($config->adminRootPageID);
$page = $pages->get($admin->path . 'page/edit/');
$bookmarks->checkProcessPage($page);
return $inputfields;