mirror of
https://github.com/processwire/processwire.git
synced 2025-08-13 18:24:57 +02:00
Add support for using repeaters in user profile editor per issue processwire/processwire-issues#407
This commit is contained in:
@@ -120,7 +120,9 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
|
|||||||
$template->save();
|
$template->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->wire('page')->process == 'ProcessPageEdit') {
|
$process = $this->wire('page')->process;
|
||||||
|
|
||||||
|
if($process == 'ProcessPageEdit' || $process == 'ProcessProfile') {
|
||||||
|
|
||||||
$this->addHookBefore('ProcessPageEdit::ajaxSave', $this, 'hookProcessPageEditAjaxSave');
|
$this->addHookBefore('ProcessPageEdit::ajaxSave', $this, 'hookProcessPageEditAjaxSave');
|
||||||
|
|
||||||
@@ -200,15 +202,48 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function hookPagePermissionsPageEditableAjax(HookEvent $event) {
|
public function hookPagePermissionsPageEditableAjax(HookEvent $event) {
|
||||||
|
|
||||||
if($event->return) return;
|
if($event->return) return;
|
||||||
|
|
||||||
$page = $event->arguments(0);
|
$page = $event->arguments(0);
|
||||||
if(!$page instanceof RepeaterPage) return;
|
if(!$page instanceof RepeaterPage) return;
|
||||||
|
|
||||||
|
$forField = $page->getForField();
|
||||||
$n = 0;
|
$n = 0;
|
||||||
|
|
||||||
while($page instanceof RepeaterPage) {
|
while($page instanceof RepeaterPage) {
|
||||||
|
$forField = $page->getForField();
|
||||||
$page = $page->getForPage();
|
$page = $page->getForPage();
|
||||||
if(++$n > 20) break;
|
if(++$n > 20) break;
|
||||||
}
|
}
|
||||||
if(!$page instanceof RepeaterPage) $event->return = $page->editable();
|
|
||||||
|
if(!$page instanceof RepeaterPage) {
|
||||||
|
// found the original owning page (forPage)
|
||||||
|
|
||||||
|
$editable = null;
|
||||||
|
/** @var User $user */
|
||||||
|
$user = $this->wire('user');
|
||||||
|
/** @var WireInput $input */
|
||||||
|
$input = $this->wire('input');
|
||||||
|
/** @var Field|null $field */
|
||||||
|
$field = $input->get('field') ? $this->wire('fields')->get($input->get->fieldName('field')) : $forField;
|
||||||
|
|
||||||
|
if($page instanceof User && $field && $field->type instanceof FieldtypeRepeater) {
|
||||||
|
// editing a repeater field in a User
|
||||||
|
if($user->hasPermission('user-admin')) {
|
||||||
|
$editable = true;
|
||||||
|
} else if($page->id === $user->id) {
|
||||||
|
// user editing themself, repeater field
|
||||||
|
/** @var PagePermissions $pagePermissions */
|
||||||
|
$pagePermissions = $this->wire('modules')->get('PagePermissions');
|
||||||
|
$editable = $pagePermissions->userFieldEditable($field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($editable === null) $editable = $page->editable();
|
||||||
|
|
||||||
|
$event->return = $editable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -589,6 +589,9 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
|||||||
*/
|
*/
|
||||||
public function renderReady(Inputfield $parent = null, $renderValueMode = false) {
|
public function renderReady(Inputfield $parent = null, $renderValueMode = false) {
|
||||||
|
|
||||||
|
/** @var User $user */
|
||||||
|
$user = $this->wire('user');
|
||||||
|
|
||||||
$this->wire('modules')->get('JqueryCore')->use('cookie');
|
$this->wire('modules')->get('JqueryCore')->use('cookie');
|
||||||
$this->wire('modules')->get('JqueryUI')->use('vex');
|
$this->wire('modules')->get('JqueryUI')->use('vex');
|
||||||
$this->preloadInputfieldAssets();
|
$this->preloadInputfieldAssets();
|
||||||
@@ -620,6 +623,12 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
|||||||
$this->wrapAttr('data-depth', (int) $this->repeaterDepth);
|
$this->wrapAttr('data-depth', (int) $this->repeaterDepth);
|
||||||
|
|
||||||
list($editorUrl, $queryString) = explode('?', $this->page->editUrl());
|
list($editorUrl, $queryString) = explode('?', $this->page->editUrl());
|
||||||
|
|
||||||
|
if(strpos($editorUrl, '/users/edit/') && !$user->isSuperuser() && !$user->hasPermission('user-admin')) {
|
||||||
|
// to accommodate repeater in user profile, use main page editor
|
||||||
|
$editorUrl = str_replace('/access/users/edit/', '/page/edit/', $editorUrl);
|
||||||
|
}
|
||||||
|
|
||||||
if($queryString) {}
|
if($queryString) {}
|
||||||
|
|
||||||
$this->wire('config')->js('InputfieldRepeater', array(
|
$this->wire('config')->js('InputfieldRepeater', array(
|
||||||
|
@@ -116,10 +116,11 @@ class PagePermissions extends WireData implements Module {
|
|||||||
/**
|
/**
|
||||||
* Hook that adds a Page::editable([$field]) method to determine if $page is editable by current user
|
* Hook that adds a Page::editable([$field]) method to determine if $page is editable by current user
|
||||||
*
|
*
|
||||||
* A field name may optionally be specified as the first argument, in which case the field on that page will also be checked for access.
|
* A field name may optionally be specified as the first argument, in which case the field on that
|
||||||
|
* page will also be checked for access.
|
||||||
*
|
*
|
||||||
* When using field, specify boolean false for second argument to bypass PageEditable check, as an optimization, if you have
|
* When using field, specify boolean false for second argument to bypass PageEditable check, as an
|
||||||
* already determined that the page is editable.
|
* optimization, if you have already determined that the page is editable.
|
||||||
*
|
*
|
||||||
* @param HookEvent $event
|
* @param HookEvent $event
|
||||||
*
|
*
|
||||||
@@ -448,12 +449,14 @@ class PagePermissions extends WireData implements Module {
|
|||||||
/**
|
/**
|
||||||
* Is the given field editable by the current user in their user profile?
|
* Is the given field editable by the current user in their user profile?
|
||||||
*
|
*
|
||||||
* @param string $name Field name
|
* @param Field|string $name Field or Field name
|
||||||
* @param User|null User to check (default=current user)
|
* @param User|null User to check (default=current user)
|
||||||
* @return bool
|
* @return bool
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function userFieldEditable($name, User $user = null) {
|
public function userFieldEditable($name, User $user = null) {
|
||||||
|
if(is_object($name) && $name instanceof Field) $name = $name->name;
|
||||||
|
if(empty($name) || !is_string($name)) return false;
|
||||||
if(is_null($user)) $user = $this->wire('user');
|
if(is_null($user)) $user = $this->wire('user');
|
||||||
if(!$user->isLoggedin()) return false;
|
if(!$user->isLoggedin()) return false;
|
||||||
if(!$user->hasPermission('profile-edit')) return false;
|
if(!$user->hasPermission('profile-edit')) return false;
|
||||||
|
@@ -216,6 +216,12 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
|
|||||||
*/
|
*/
|
||||||
protected $editor = null;
|
protected $editor = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the Page what Process is being used to edit it?
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected $setEditor = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Names of changed fields
|
* Names of changed fields
|
||||||
*
|
*
|
||||||
@@ -357,16 +363,46 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
|
|||||||
*/
|
*/
|
||||||
protected function ___loadPage($id) {
|
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); // Init error: page doesn't exist
|
if($page instanceof NullPage) {
|
||||||
|
throw new WireException($this->noticeUnknown); // page doesn't exist
|
||||||
|
}
|
||||||
|
|
||||||
if(!$page->editable()) {
|
$editable = $page->editable();
|
||||||
if($page instanceof User && $this->wire('user')->hasPermission('user-admin') && $this->wire('process') != 'ProcessUser') {
|
|
||||||
|
/** @var User $user */
|
||||||
|
$user = $this->wire('user');
|
||||||
|
|
||||||
|
/** @var Config $config */
|
||||||
|
$config = $this->wire('config');
|
||||||
|
|
||||||
|
/** @var Config $config */
|
||||||
|
$input = $this->wire('input');
|
||||||
|
|
||||||
|
if($page instanceof User) {
|
||||||
|
// special case when page is a User
|
||||||
|
|
||||||
|
$userAdmin = $user->hasPermission('user-admin');
|
||||||
|
$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->wire('session')->redirect($this->wire('config')->urls->admin . 'access/users/edit/?id=' . $page->id);
|
$this->wire('session')->redirect($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->wire('modules')->get('PagePermissions');
|
||||||
|
$editable = $pagePermissions->userFieldEditable($field);
|
||||||
|
// prevent a later potential redirect to user editor
|
||||||
|
if($editable) $this->setEditor = false;
|
||||||
}
|
}
|
||||||
throw new WirePermissionException($this->noticeNoAccess); // Init: user doesn't have access
|
}
|
||||||
|
|
||||||
|
if(!$editable) {
|
||||||
|
throw new WirePermissionException($this->noticeNoAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $page;
|
return $page;
|
||||||
@@ -383,7 +419,10 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
|
|||||||
|
|
||||||
if(!$this->page) throw new WireException("No page found");
|
if(!$this->page) throw new WireException("No page found");
|
||||||
|
|
||||||
$this->page->setEditor($this->editor ? $this->editor : $this);
|
if($this->setEditor) {
|
||||||
|
// note that setting the editor can force a redirect to a ProcessPageType editor
|
||||||
|
$this->page->setEditor($this->editor ? $this->editor : $this);
|
||||||
|
}
|
||||||
|
|
||||||
if($this->config->ajax && (isset($_SERVER['HTTP_X_FIELDNAME']) || count($_POST))) {
|
if($this->config->ajax && (isset($_SERVER['HTTP_X_FIELDNAME']) || count($_POST))) {
|
||||||
$this->ajaxSave($this->page);
|
$this->ajaxSave($this->page);
|
||||||
|
Reference in New Issue
Block a user