From 6cce1152a855f636ac22689cbf531f3928f97506 Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Thu, 20 Feb 2020 18:10:39 +0100 Subject: [PATCH] Fix ACL form field value handling via AJAX --- com.woltlab.wcf/templates/__aclFormField.tpl | 2 +- .../templates/aclPermissionJavaScript.tpl | 12 ++++- .../files/acp/templates/__aclFormField.tpl | 2 +- .../acp/templates/aclPermissionJavaScript.tpl | 12 ++++- wcfsetup/install/files/js/WCF.ACL.js | 14 ++++- .../Core/Form/Builder/Field/Acl.js | 51 +++++++++++++++++++ .../WoltLabSuite/Core/Form/Builder/Manager.js | 17 ++++++- .../files/lib/system/acl/ACLHandler.class.php | 24 ++++++--- .../builder/field/acl/AclFormField.class.php | 21 +++++++- 9 files changed, 140 insertions(+), 15 deletions(-) create mode 100644 wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Acl.js diff --git a/com.woltlab.wcf/templates/__aclFormField.tpl b/com.woltlab.wcf/templates/__aclFormField.tpl index 033074374b..1b16c1c51d 100644 --- a/com.woltlab.wcf/templates/__aclFormField.tpl +++ b/com.woltlab.wcf/templates/__aclFormField.tpl @@ -2,4 +2,4 @@ {include file='aclPermissions'} {/if} -{include file='aclPermissionJavaScript' containerID=$field->getPrefixedId()|concat:'Container' categoryName=$field->getCategoryName() objectID=$field->getObjectID() objectTypeID=$field->getObjectType()->objectTypeID} +{include file='aclPermissionJavaScript' containerID=$field->getPrefixedId()|concat:'Container' categoryName=$field->getCategoryName() objectID=$field->getObjectID() objectTypeID=$field->getObjectType()->objectTypeID aclFormBuilderMode=true} diff --git a/com.woltlab.wcf/templates/aclPermissionJavaScript.tpl b/com.woltlab.wcf/templates/aclPermissionJavaScript.tpl index 850195c299..830c865762 100644 --- a/com.woltlab.wcf/templates/aclPermissionJavaScript.tpl +++ b/com.woltlab.wcf/templates/aclPermissionJavaScript.tpl @@ -87,6 +87,16 @@ {/foreach} {/if} {/if} - new {if $aclListClassName|isset}{@$aclListClassName}{else}WCF.ACL.List{/if}($('#{@$containerID}'), {@$objectTypeID}, {if $categoryName|isset}'{@$categoryName}'{else}null{/if}, {if $objectID|isset}{@$objectID}{else}0{/if}, {if !$includeUserGroups|isset || $includeUserGroups}true{else}false{/if}{if $aclValues[$objectTypeID]|isset}, initialPermissions{/if}); + + var aclList = new {if $aclListClassName|isset}{@$aclListClassName}{else}WCF.ACL.List{/if}($('#{@$containerID}'), {@$objectTypeID}, {if $categoryName|isset}'{@$categoryName}'{else}null{/if}, {if $objectID|isset}{@$objectID}{else}0{/if}, {if !$includeUserGroups|isset || $includeUserGroups}true{else}false{/if}{if $aclValues[$objectTypeID]|isset}, initialPermissions{/if}); + + {if !$aclFormBuilderMode|empty} + require(['WoltLabSuite/Core/Form/Builder/Manager'], function(FormBuilderManager) { + FormBuilderManager.getField( + '{@$field->getDocument()->getId()}', + '{@$field->getPrefixedId()}' + ).setAclList(aclList); + }); + {/if} }); diff --git a/wcfsetup/install/files/acp/templates/__aclFormField.tpl b/wcfsetup/install/files/acp/templates/__aclFormField.tpl index 033074374b..1b16c1c51d 100644 --- a/wcfsetup/install/files/acp/templates/__aclFormField.tpl +++ b/wcfsetup/install/files/acp/templates/__aclFormField.tpl @@ -2,4 +2,4 @@ {include file='aclPermissions'} {/if} -{include file='aclPermissionJavaScript' containerID=$field->getPrefixedId()|concat:'Container' categoryName=$field->getCategoryName() objectID=$field->getObjectID() objectTypeID=$field->getObjectType()->objectTypeID} +{include file='aclPermissionJavaScript' containerID=$field->getPrefixedId()|concat:'Container' categoryName=$field->getCategoryName() objectID=$field->getObjectID() objectTypeID=$field->getObjectType()->objectTypeID aclFormBuilderMode=true} diff --git a/wcfsetup/install/files/acp/templates/aclPermissionJavaScript.tpl b/wcfsetup/install/files/acp/templates/aclPermissionJavaScript.tpl index 850195c299..830c865762 100644 --- a/wcfsetup/install/files/acp/templates/aclPermissionJavaScript.tpl +++ b/wcfsetup/install/files/acp/templates/aclPermissionJavaScript.tpl @@ -87,6 +87,16 @@ {/foreach} {/if} {/if} - new {if $aclListClassName|isset}{@$aclListClassName}{else}WCF.ACL.List{/if}($('#{@$containerID}'), {@$objectTypeID}, {if $categoryName|isset}'{@$categoryName}'{else}null{/if}, {if $objectID|isset}{@$objectID}{else}0{/if}, {if !$includeUserGroups|isset || $includeUserGroups}true{else}false{/if}{if $aclValues[$objectTypeID]|isset}, initialPermissions{/if}); + + var aclList = new {if $aclListClassName|isset}{@$aclListClassName}{else}WCF.ACL.List{/if}($('#{@$containerID}'), {@$objectTypeID}, {if $categoryName|isset}'{@$categoryName}'{else}null{/if}, {if $objectID|isset}{@$objectID}{else}0{/if}, {if !$includeUserGroups|isset || $includeUserGroups}true{else}false{/if}{if $aclValues[$objectTypeID]|isset}, initialPermissions{/if}); + + {if !$aclFormBuilderMode|empty} + require(['WoltLabSuite/Core/Form/Builder/Manager'], function(FormBuilderManager) { + FormBuilderManager.getField( + '{@$field->getDocument()->getId()}', + '{@$field->getPrefixedId()}' + ).setAclList(aclList); + }); + {/if} }); diff --git a/wcfsetup/install/files/js/WCF.ACL.js b/wcfsetup/install/files/js/WCF.ACL.js index cb3567db1b..fd4c2e9f96 100644 --- a/wcfsetup/install/files/js/WCF.ACL.js +++ b/wcfsetup/install/files/js/WCF.ACL.js @@ -10,7 +10,7 @@ if (COMPILER_TARGET_DEFAULT) { * ACL support for WCF * * @author Alexander Ebert - * @copyright 2001-2019 WoltLab GmbH + * @copyright 2001-2020 WoltLab GmbH * @license GNU Lesser General Public License */ WCF.ACL.List = Class.extend({ @@ -599,6 +599,18 @@ if (COMPILER_TARGET_DEFAULT) { } } } + }, + + /** + * Returns the ACL data stored for this list. + * + * @return object + * @since 5.2.3 + */ + getData: function() { + this._savePermissions(); + + return this._values; } }); } diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Acl.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Acl.js new file mode 100644 index 0000000000..c984d4cadf --- /dev/null +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Acl.js @@ -0,0 +1,51 @@ +/** + * Data handler for a acl form builder field in an Ajax form. + * + * @author Matthias Schmidt + * @copyright 2001-2020 WoltLab GmbH + * @license GNU Lesser General Public License + * @module WoltLabSuite/Core/Form/Builder/Field/Acl + * @since 5.2.3 + */ +define(['Core', './Field'], function(Core, FormBuilderField) { + "use strict"; + + /** + * @constructor + */ + function FormBuilderFieldAcl(fieldId) { + this.init(fieldId); + + this._aclList = null; + }; + Core.inherit(FormBuilderFieldAcl, FormBuilderField, { + /** + * @see WoltLabSuite/Core/Form/Builder/Field/Field#_getData + */ + _getData: function() { + var data = {}; + + data[this._fieldId] = this._aclList.getData(); + + return data; + }, + + /** + * @see WoltLabSuite/Core/Form/Builder/Field/Field#_readField + */ + _readField: function() { + // does nothing + }, + + /** + * Sets the ACL list object used to extract the ACL values. + * + * @param {WCF.ACL.List} aclList + */ + setAclList: function(aclList) { + this._aclList = aclList; + } + }); + + return FormBuilderFieldAcl; +}); diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Manager.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Manager.js index 2bd57c2eba..ce30984106 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Manager.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Manager.js @@ -3,7 +3,7 @@ * of the registered forms. * * @author Matthias Schmidt - * @copyright 2001-2019 WoltLab GmbH + * @copyright 2001-2020 WoltLab GmbH * @license GNU Lesser General Public License * @module WoltLabSuite/Core/Form/Builder/Manager * @since 5.2 @@ -61,6 +61,21 @@ define([ }); }, + /** + * Returns the registered form field with given id. + * + * @param {string} formId + * @return {WoltLabSuite/Core/Form/Builder/Field/Field} + * @since 5.2.3 + */ + getField: function(formId, fieldId) { + if (!this.hasField(formId, fieldId)) { + throw new Error("Unknown field with id '" + formId + "' for form with id '" + fieldId + "'."); + } + + return _fields.get(formId).get(fieldId); + }, + /** * Returns the registered form with given id. * diff --git a/wcfsetup/install/files/lib/system/acl/ACLHandler.class.php b/wcfsetup/install/files/lib/system/acl/ACLHandler.class.php index 9503ebee32..3017d754fc 100644 --- a/wcfsetup/install/files/lib/system/acl/ACLHandler.class.php +++ b/wcfsetup/install/files/lib/system/acl/ACLHandler.class.php @@ -133,19 +133,24 @@ class ACLHandler extends SingletonFactory { * using form builder, you do not need this method. * * @param integer $objectTypeID + * @param array|null $valuesSource array used to read the values from (if `null`, `$_POST['aclValues']` is used) * @since 5.2 */ - public function readValues($objectTypeID) { + public function readValues($objectTypeID, array $valuesSource = null) { $this->__readValues[$objectTypeID] = []; - if (isset($_POST['aclValues'])) { + if ($valuesSource === null && isset($_POST['aclValues'])) { + $valuesSource = $_POST['aclValues']; + } + + if (isset($valuesSource)) { $options = ACLOption::getOptions($objectTypeID)->getObjects(); foreach (['group', 'user'] as $type) { - if (isset($_POST['aclValues'][$type])) { + if (isset($valuesSource[$type])) { $this->__readValues[$objectTypeID][$type] = []; - foreach ($_POST['aclValues'][$type] as $typeID => $optionData) { + foreach ($valuesSource[$type] as $typeID => $optionData) { $this->__readValues[$objectTypeID][$type][$typeID] = []; foreach ($optionData as $optionID => $optionValue) { @@ -245,16 +250,21 @@ class ACLHandler extends SingletonFactory { $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); + $objectTypeID = reset($options)->objectTypeID; + // add new values if given - if (!isset($_POST['aclValues']) || !isset($_POST['aclValues'][$type])) { - return; + $values = []; + if (isset($this->__readValues[$objectTypeID]) && isset($this->__readValues[$objectTypeID][$type])) { + $values = $this->__readValues[$objectTypeID][$type]; + } + else if (isset($_POST['aclValues']) && isset($_POST['aclValues'][$type])) { + $values = $_POST['aclValues'][$type]; } $sql = "INSERT INTO wcf".WCF_N."_acl_option_to_".$type." (optionID, objectID, ".$type."ID, optionValue) VALUES (?, ?, ?, ?)"; $statement = WCF::getDB()->prepareStatement($sql); - $values =& $_POST['aclValues'][$type]; WCF::getDB()->beginTransaction(); foreach ($values as $typeID => $optionData) { diff --git a/wcfsetup/install/files/lib/system/form/builder/field/acl/AclFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/acl/AclFormField.class.php index d642904a0a..3bdae00ca8 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/acl/AclFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/acl/AclFormField.class.php @@ -12,7 +12,7 @@ use wcf\system\form\builder\TObjectTypeFormNode; * Implementation of a form field for setting acl option values. * * @author Matthias Schmidt - * @copyright 2001-2019 WoltLab GmbH + * @copyright 2001-2020 WoltLab GmbH * @license GNU Lesser General Public License * @package WoltLabSuite\Core\System\Form\Builder\Field\Acl * @since 5.2 @@ -26,6 +26,12 @@ class AclFormField extends AbstractFormField implements IObjectTypeFormNode { */ protected $categoryName; + /** + * @inheritDoc + * @since 5.2.3 + */ + protected $javaScriptDataHandlerModule = 'WoltLabSuite/Core/Form/Builder/Field/Acl'; + /** * id of the edited object or `null` if no object is edited * @var null|int @@ -144,7 +150,18 @@ class AclFormField extends AbstractFormField implements IObjectTypeFormNode { * @inheritDoc */ public function readValue() { - ACLHandler::getInstance()->readValues($this->getObjectType()->objectTypeID); + $valueSource = $_POST; + if ($this->getDocument()->isAjax()) { + $valueSource = []; + if ( + $this->getDocument()->hasRequestData($this->getPrefixedId()) + && is_array($this->getDocument()->getRequestData($this->getPrefixedId())) + ) { + $valueSource = $this->getDocument()->getRequestData($this->getPrefixedId()); + } + } + + ACLHandler::getInstance()->readValues($this->getObjectType()->objectTypeID, $valueSource); return $this; } -- 2.20.1