1
0
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:
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

@@ -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;
}
} }
/** /**

View File

@@ -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(

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 * 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;

View File

@@ -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);