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

Add support for using repeaters in user profile editor per issue processwire/processwire-issues#407

This commit is contained in:
Ryan Cramer
2017-10-20 09:43:08 -04:00
parent b4f977c36a
commit 56e35b55ea
4 changed files with 100 additions and 14 deletions

View File

@@ -119,8 +119,10 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
$template->set('pageClass', $class);
$template->save();
}
$process = $this->wire('page')->process;
if($this->wire('page')->process == 'ProcessPageEdit') {
if($process == 'ProcessPageEdit' || $process == 'ProcessProfile') {
$this->addHookBefore('ProcessPageEdit::ajaxSave', $this, 'hookProcessPageEditAjaxSave');
@@ -200,15 +202,48 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
*
*/
public function hookPagePermissionsPageEditableAjax(HookEvent $event) {
if($event->return) return;
$page = $event->arguments(0);
if(!$page instanceof RepeaterPage) return;
$forField = $page->getForField();
$n = 0;
while($page instanceof RepeaterPage) {
$forField = $page->getForField();
$page = $page->getForPage();
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;
}
}
/**

View File

@@ -588,6 +588,9 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
*
*/
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('JqueryUI')->use('vex');
@@ -620,6 +623,12 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
$this->wrapAttr('data-depth', (int) $this->repeaterDepth);
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) {}
$this->wire('config')->js('InputfieldRepeater', array(

View File

@@ -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
*
* 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
* already determined that the page is editable.
* When using field, specify boolean false for second argument to bypass PageEditable check, as an
* optimization, if you have already determined that the page is editable.
*
* @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?
*
* @param string $name Field name
* @param Field|string $name Field or Field name
* @param User|null User to check (default=current user)
* @return bool
*
*/
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(!$user->isLoggedin()) return false;
if(!$user->hasPermission('profile-edit')) return false;

View File

@@ -216,6 +216,12 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
*/
protected $editor = null;
/**
* Tell the Page what Process is being used to edit it?
*
*/
protected $setEditor = true;
/**
* Names of changed fields
*
@@ -356,17 +362,47 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
*
*/
protected function ___loadPage($id) {
/** @var Page|NullPage $page */
$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
}
$editable = $page->editable();
if(!$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)
$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;
@@ -383,8 +419,11 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
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))) {
$this->ajaxSave($this->page);
return '';