Fix ACL form field value handling via AJAX
authorMatthias Schmidt <gravatronics@live.com>
Thu, 20 Feb 2020 17:10:39 +0000 (18:10 +0100)
committerMatthias Schmidt <gravatronics@live.com>
Thu, 20 Feb 2020 17:10:39 +0000 (18:10 +0100)
com.woltlab.wcf/templates/__aclFormField.tpl
com.woltlab.wcf/templates/aclPermissionJavaScript.tpl
wcfsetup/install/files/acp/templates/__aclFormField.tpl
wcfsetup/install/files/acp/templates/aclPermissionJavaScript.tpl
wcfsetup/install/files/js/WCF.ACL.js
wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Acl.js [new file with mode: 0644]
wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Manager.js
wcfsetup/install/files/lib/system/acl/ACLHandler.class.php
wcfsetup/install/files/lib/system/form/builder/field/acl/AclFormField.class.php

index 033074374bee6b64613b3e6dd7f808fc34fa5bff..1b16c1c51dc75a37e956f37a7a004a297685fe21 100644 (file)
@@ -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}
index 850195c299bd8dbc8893fa49052d931b4042aaf5..830c86576229355c336b9cfa579ec610c8b9b05e 100644 (file)
                                {/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}
        });
 </script>
index 033074374bee6b64613b3e6dd7f808fc34fa5bff..1b16c1c51dc75a37e956f37a7a004a297685fe21 100644 (file)
@@ -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}
index 850195c299bd8dbc8893fa49052d931b4042aaf5..830c86576229355c336b9cfa579ec610c8b9b05e 100644 (file)
                                {/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}
        });
 </script>
index cb3567db1b20b539f03a968c0b012a757be83f1a..fd4c2e9f96fd91c9fb7b689177b38422be72c94b 100644 (file)
@@ -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 <http://opensource.org/licenses/lgpl-license.php>
         */
        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 (file)
index 0000000..c984d4c
--- /dev/null
@@ -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 <http://opensource.org/licenses/lgpl-license.php>
+ * @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;
+});
index 2bd57c2eba15bfb4e529a378e2bc3a4123e5632e..ce3098410637409919d97f6101d3f2f43b9593a3 100644 (file)
@@ -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 <http://opensource.org/licenses/lgpl-license.php>
  * @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.
                 * 
index 9503ebee32459509c26600a2ac5f669e46dff246..3017d754fcd20b62201e5688fe90f3e0437e6abd 100644 (file)
@@ -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) {
index d642904a0a12389021851a407f37d576fde9bcaa..3bdae00ca858786f20620aa42ef35abc33e298d4 100644 (file)
@@ -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 <http://opensource.org/licenses/lgpl-license.php>
  * @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;
        }