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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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(
|
||||
|
@@ -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;
|
||||
|
@@ -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 '';
|
||||
|
Reference in New Issue
Block a user