From 4778307c1045cb11ea981f8c486b21a82e1eb486 Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Fri, 16 Nov 2018 19:06:32 +0100 Subject: [PATCH] Fix various issues when saving gui-edited PIP entries See #2545 --- ...tDatabaseObjectListBoxController.class.php | 10 +- ...TXmlGuiPackageInstallationPlugin.class.php | 22 ++- ...LOptionPackageInstallationPlugin.class.php | 185 +++++++++++------- ...ACPMenuPackageInstallationPlugin.class.php | 3 + ...roviderPackageInstallationPlugin.class.php | 3 + ...actMenuPackageInstallationPlugin.class.php | 23 +++ ...tOptionPackageInstallationPlugin.class.php | 163 ++++++++++----- ...ractXMLPackageInstallationPlugin.class.php | 2 +- .../BBCodePackageInstallationPlugin.class.php | 39 +++- .../BoxPackageInstallationPlugin.class.php | 14 ++ ...dActionPackageInstallationPlugin.class.php | 17 +- ...CronjobPackageInstallationPlugin.class.php | 34 +++- ...istenerPackageInstallationPlugin.class.php | 26 ++- ...anguagePackageInstallationPlugin.class.php | 5 +- ...roviderPackageInstallationPlugin.class.php | 12 +- ...enuItemPackageInstallationPlugin.class.php | 36 ++-- ...initionPackageInstallationPlugin.class.php | 3 + .../OptionPackageInstallationPlugin.class.php | 10 +- .../PagePackageInstallationPlugin.class.php | 31 ++- .../SmileyPackageInstallationPlugin.class.php | 18 +- ...istenerPackageInstallationPlugin.class.php | 58 +++++- ...pOptionPackageInstallationPlugin.class.php | 5 + ...serMenuPackageInstallationPlugin.class.php | 8 +- ...onEventPackageInstallationPlugin.class.php | 12 ++ ...rOptionPackageInstallationPlugin.class.php | 10 +- ...ileMenuPackageInstallationPlugin.class.php | 10 + wcfsetup/install/lang/en.xml | 2 +- 27 files changed, 577 insertions(+), 184 deletions(-) diff --git a/wcfsetup/install/files/lib/system/box/AbstractDatabaseObjectListBoxController.class.php b/wcfsetup/install/files/lib/system/box/AbstractDatabaseObjectListBoxController.class.php index 4748d59660..dbc18b0723 100644 --- a/wcfsetup/install/files/lib/system/box/AbstractDatabaseObjectListBoxController.class.php +++ b/wcfsetup/install/files/lib/system/box/AbstractDatabaseObjectListBoxController.class.php @@ -159,7 +159,10 @@ abstract class AbstractDatabaseObjectListBoxController extends AbstractBoxContro ->objectProperty('sortField') ->label('wcf.acp.box.controller.sortField') ->description('wcf.acp.box.controller.sortField.description') - ->options(array_combine($this->validSortFields, $this->validSortFields)) + ->options(array_merge( + ['' => 'wcf.global.noSelection'], + array_combine($this->validSortFields, $this->validSortFields) + )) ->addDependency( ValueFormFieldDependency::create('boxType') ->field($objectTypeField) @@ -168,6 +171,11 @@ abstract class AbstractDatabaseObjectListBoxController extends AbstractBoxContro SortOrderFormField::create($prefix . 'sortOrder') ->objectProperty('sortOrder') + ->options([ + '' => 'wcf.global.noSelection', + 'ASC' => 'wcf.global.sortOrder.ascending', + 'DESC' => 'wcf.global.sortOrder.descending', + ]) ->addDependency( ValueFormFieldDependency::create('boxType') ->field($objectTypeField) diff --git a/wcfsetup/install/files/lib/system/devtools/pip/TXmlGuiPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/devtools/pip/TXmlGuiPackageInstallationPlugin.class.php index ae709f4903..574c5d2360 100644 --- a/wcfsetup/install/files/lib/system/devtools/pip/TXmlGuiPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/devtools/pip/TXmlGuiPackageInstallationPlugin.class.php @@ -7,6 +7,7 @@ use wcf\system\form\builder\field\IFormField; use wcf\system\form\builder\IFormDocument; use wcf\system\form\builder\IFormNode; use wcf\system\package\PackageInstallationDispatcher; +use wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin; use wcf\system\WCF; use wcf\util\DOMUtil; use wcf\util\StringUtil; @@ -24,6 +25,7 @@ use wcf\util\XML; * @since 3.2 * * @property PackageInstallationDispatcher|DevtoolsPackageInstallationDispatcher $installation + * @mixin AbstractXMLPackageInstallationPlugin */ trait TXmlGuiPackageInstallationPlugin { /** @@ -69,7 +71,7 @@ trait TXmlGuiPackageInstallationPlugin { /** * Adds optional child elements to the given elements based on the given * child data and form. - * + * * @param \DOMElement $element element to which the child elements are added * @param array $children * @param IFormDocument $form form containing the children's data @@ -79,22 +81,22 @@ trait TXmlGuiPackageInstallationPlugin { $document = $element->ownerDocument; - foreach ($children as $index => $key) { - if (is_string($index)) { - $childName = $index; - if (!is_array($key)) { + foreach ($children as $key => $value) { + if (is_string($key)) { + $childName = $key; + if (!is_array($value)) { $isOptional = true; $cdata = false; - $defaultValue = $key; + $defaultValue = $value; } else { - $isOptional = array_key_exists('defaultValue', $key); - $cdata = $key['cdata'] ?? false; - $defaultValue = $key['defaultValue'] ?? null; + $isOptional = array_key_exists('defaultValue', $value); + $cdata = $value['cdata'] ?? false; + $defaultValue = $value['defaultValue'] ?? null; } } else { - $childName = $key; + $childName = $value; $isOptional = false; $cdata = false; $defaultValue = null; diff --git a/wcfsetup/install/files/lib/system/package/plugin/ACLOptionPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/ACLOptionPackageInstallationPlugin.class.php index 38bdfd8612..f800730b49 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/ACLOptionPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/ACLOptionPackageInstallationPlugin.class.php @@ -2,6 +2,8 @@ namespace wcf\system\package\plugin; use wcf\data\acl\option\ACLOptionEditor; use wcf\data\acl\option\ACLOptionList; +use wcf\data\acl\option\category\ACLOptionCategory; +use wcf\data\acl\option\category\ACLOptionCategoryEditor; use wcf\data\acl\option\category\ACLOptionCategoryList; use wcf\data\object\type\ObjectTypeCache; use wcf\system\devtools\pip\IDevtoolsPipEntryList; @@ -147,32 +149,65 @@ class ACLOptionPackageInstallationPlugin extends AbstractOptionPackageInstallati * @inheritDoc */ protected function saveCategory($category) { - $objectTypeID = $this->getObjectTypeID($category['objecttype'] ?? $category['objectType']); + if (isset($category['objectTypeID'])) { + $objectTypeID = $category['objectTypeID']; + } + else { + $objectTypeID = $this->getObjectTypeID($category['objecttype']); + } - // search existing category - $sql = "SELECT categoryID - FROM wcf".WCF_N."_".$this->tableName."_category - WHERE categoryName = ? - AND objectTypeID = ? - AND packageID = ?"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute([ - $category['categoryName'], - $objectTypeID, - $this->installation->getPackageID() - ]); - $row = $statement->fetchArray(); - if (!$row) { - // insert new category - $sql = "INSERT INTO wcf".WCF_N."_".$this->tableName."_category - (packageID, objectTypeID, categoryName) - VALUES (?, ?, ?)"; + if ($this->editedEntry === null) { + // search existing category + $sql = "SELECT categoryID + FROM wcf".WCF_N."_".$this->tableName."_category + WHERE categoryName = ? + AND objectTypeID = ? + AND packageID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute([ - $this->installation->getPackageID(), + $category['categoryName'], $objectTypeID, - $category['categoryName'] + $this->installation->getPackageID() ]); + $row = $statement->fetchArray(); + if (!$row) { + // insert new category + $sql = "INSERT INTO wcf".WCF_N."_".$this->tableName."_category + (packageID, objectTypeID, categoryName) + VALUES (?, ?, ?)"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute([ + $this->installation->getPackageID(), + $objectTypeID, + $category['categoryName'] + ]); + } + } + else { + $editedData = $this->getElementData($this->editedEntry, true); + + $sql = "SELECT categoryID + FROM wcf".WCF_N."_".$this->tableName."_category + WHERE categoryName = ? + AND objectTypeID = ? + AND packageID = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute([ + $editedData['categoryName'], + $editedData['objectTypeID'], + $this->installation->getPackageID() + ]); + $categoryID = $statement->fetchSingleColumn(); + + if ($categoryID === false) { + throw new \UnexpectedValueException("Cannot find edited acl option category in database."); + } + else { + (new ACLOptionCategoryEditor(new ACLOptionCategory($categoryID)))->update([ + 'categoryName' => $category['categoryName'], + 'objectTypeID' => $objectTypeID + ]); + } } } @@ -218,41 +253,7 @@ class ACLOptionPackageInstallationPlugin extends AbstractOptionPackageInstallati 'objectTypeID' => $objectTypeID ]; - // check for option existence - $sql = "SELECT optionID - FROM wcf".WCF_N."_".$this->tableName." - WHERE optionName = ? - AND objectTypeID = ? - AND packageID = ?"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute([ - $data['optionName'], - $data['objectTypeID'], - $this->installation->getPackageID() - ]); - $row = $statement->fetchArray(); - if (!$row) { - $sql = "INSERT INTO wcf".WCF_N."_".$this->tableName." - (packageID, objectTypeID, optionName, categoryName) - VALUES (?, ?, ?, ?)"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute([ - $this->installation->getPackageID(), - $data['objectTypeID'], - $data['optionName'], - $data['categoryName'] - ]); - } - else { - $sql = "UPDATE wcf".WCF_N."_".$this->tableName." - SET categoryName = ? - WHERE optionID = ?"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute([ - $data['categoryName'], - $row['optionID'] - ]); - } + $this->saveOption($data, $data['categoryName']); } } @@ -260,7 +261,41 @@ class ACLOptionPackageInstallationPlugin extends AbstractOptionPackageInstallati * @inheritDoc */ protected function saveOption($option, $categoryName, $existingOptionID = 0) { - // does nothing + // check for option existence + $sql = "SELECT optionID + FROM wcf".WCF_N."_".$this->tableName." + WHERE optionName = ? + AND objectTypeID = ? + AND packageID = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute([ + $option['optionName'], + $option['objectTypeID'], + $this->installation->getPackageID() + ]); + $row = $statement->fetchArray(); + if (!$row) { + $sql = "INSERT INTO wcf".WCF_N."_".$this->tableName." + (packageID, objectTypeID, optionName, categoryName) + VALUES (?, ?, ?, ?)"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute([ + $this->installation->getPackageID(), + $option['objectTypeID'], + $option['optionName'], + $categoryName + ]); + } + else { + $sql = "UPDATE wcf".WCF_N."_".$this->tableName." + SET categoryName = ? + WHERE optionID = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute([ + $categoryName, + $row['optionID'] + ]); + } } /** @@ -476,20 +511,38 @@ class ACLOptionPackageInstallationPlugin extends AbstractOptionPackageInstallati */ protected function doGetElementData(\DOMElement $element, $saveData) { $data = [ - 'name' => $element->getAttribute('name'), 'packageID' => $this->installation->getPackage()->packageID, 'objectType' => $element->getElementsByTagName('objecttype')->item(0)->nodeValue ]; - if ($this->entryType === 'options') { - $categoryName = $element->getElementsByTagName('categoryname')->item(0); - if ($categoryName !== null) { - $data['categoryname'] = $categoryName->nodeValue; - } + switch ($this->entryType) { + case 'categories': + $data['categoryName'] = $element->getAttribute('name'); + + break; + + case 'options': + $data['optionName'] = $element->getAttribute('name'); + + $categoryName = $element->getElementsByTagName('categoryname')->item(0); + if ($categoryName !== null) { + $data['categoryname'] = $categoryName->nodeValue; + } + else if ($saveData) { + $data['categoryname'] = ''; + } + + break; } - else if ($saveData) { - $data['categoryName'] = $data['name']; - unset($data['name']); + + if (!$saveData) { + $data['name'] = $element->getAttribute('name'); + } + else { + $objectType = $data['objectType']; + unset($data['objectType']); + + $data['objectTypeID'] = $this->getObjectTypeID($objectType); } return $data; diff --git a/wcfsetup/install/files/lib/system/package/plugin/ACPMenuPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/ACPMenuPackageInstallationPlugin.class.php index 5827a3474a..50fa14f026 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/ACPMenuPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/ACPMenuPackageInstallationPlugin.class.php @@ -135,6 +135,9 @@ class ACPMenuPackageInstallationPlugin extends AbstractMenuPackageInstallationPl if ($icon !== null) { $data['icon'] = $icon->nodeValue; } + else { + $data['icon'] = ''; + } return $data; } diff --git a/wcfsetup/install/files/lib/system/package/plugin/ACPSearchProviderPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/ACPSearchProviderPackageInstallationPlugin.class.php index 61a2d461d0..cb769c02ea 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/ACPSearchProviderPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/ACPSearchProviderPackageInstallationPlugin.class.php @@ -124,6 +124,9 @@ class ACPSearchProviderPackageInstallationPlugin extends AbstractXMLPackageInsta if ($showOrder) { $data['showOrder'] = $showOrder->nodeValue; } + else if ($saveData) { + $data['showOrder'] = $this->getShowOrder(null); + } return $data; } diff --git a/wcfsetup/install/files/lib/system/package/plugin/AbstractMenuPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/AbstractMenuPackageInstallationPlugin.class.php index e5081668a5..620d91143b 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/AbstractMenuPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/AbstractMenuPackageInstallationPlugin.class.php @@ -327,31 +327,54 @@ abstract class AbstractMenuPackageInstallationPlugin extends AbstractXMLPackageI if ($parentMenuItem !== null) { $data['parentMenuItem'] = $parentMenuItem->nodeValue; } + else if ($saveData) { + $data['parentMenuItem'] = ''; + } $controller = $element->getElementsByTagName('controller')->item(0); if ($controller !== null) { $data['menuItemController'] = $controller->nodeValue; } + else if ($saveData) { + $data['menuItemController'] = ''; + } $link = $element->getElementsByTagName('link')->item(0); if ($link !== null) { $data['menuItemLink'] = $link->nodeValue; } + else if ($saveData) { + $data['menuItemLink'] = ''; + } $options = $element->getElementsByTagName('options')->item(0); if ($options !== null) { $data['options'] = $options->nodeValue; } + else if ($saveData) { + $data['options'] = ''; + } $permissions = $element->getElementsByTagName('permissions')->item(0); if ($permissions !== null) { $data['permissions'] = $permissions->nodeValue; } + else if ($saveData) { + $data['permissions'] = ''; + } $showOrder = $element->getElementsByTagName('showorder')->item(0); if ($showOrder !== null) { $data['showOrder'] = $showOrder->nodeValue; } + if ($saveData && $this->editedEntry === null) { + // only set explicit showOrder when adding new menu item + $data['showOrder'] = $this->getShowOrder( + $data['showOrder'] ?? null, + $data['parentMenuItem'], + 'parentMenuItem' + ); + } return $data; } diff --git a/wcfsetup/install/files/lib/system/package/plugin/AbstractOptionPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/AbstractOptionPackageInstallationPlugin.class.php index d2d57af41c..e644947b33 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/AbstractOptionPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/AbstractOptionPackageInstallationPlugin.class.php @@ -696,9 +696,7 @@ abstract class AbstractOptionPackageInstallationPlugin extends AbstractXMLPackag * @since 3.2 */ protected function doGetElementData(\DOMElement $element, $saveData) { - $data = [ - 'packageID' => $this->installation->getPackage()->packageID - ]; + $data = []; switch ($this->entryType) { case 'categories': @@ -708,82 +706,139 @@ abstract class AbstractOptionPackageInstallationPlugin extends AbstractXMLPackag if ($parent !== null) { $data['parentCategoryName'] = $parent->nodeValue; } + else if ($saveData) { + $data['parentCategoryName'] = ''; + } foreach (['options', 'permissions'] as $optionalPropertyName) { $optionalProperty = $element->getElementsByTagName($optionalPropertyName)->item(0); if ($optionalProperty !== null) { $data[$optionalPropertyName] = StringUtil::normalizeCsv($optionalProperty->nodeValue); } + else if ($saveData) { + $data[$optionalPropertyName] = ''; + } } $showOrder = $element->getElementsByTagName('showorder')->item(0); if ($showOrder !== null) { $data['showOrder'] = $showOrder->nodeValue; } + if ($saveData && $this->editedEntry === null) { + // only set explicit showOrder when adding new categories + $data['showOrder'] = $this->getShowOrder( + $data['showOrder'] ?? null, + $data['parentCategoryName'], + 'parentCategoryName', + '_category' + ); + } break; case 'options': - $data['optionName'] = $element->getAttribute('name'); - $data['categoryName'] = $element->getElementsByTagName('categoryname')->item(0)->nodeValue; - $data['optionType'] = $element->getElementsByTagName('optiontype')->item(0)->nodeValue; - - foreach (['defaultValue', 'enableOptions', 'validationPattern', 'showOrder'] as $optionalPropertyName) { - $optionalProperty = $element->getElementsByTagName(strtolower($optionalPropertyName))->item(0); - if ($optionalProperty !== null) { - $data[$optionalPropertyName] = $optionalProperty->nodeValue; + if (!$saveData) { + $data['optionName'] = $element->getAttribute('name'); + $data['categoryName'] = $element->getElementsByTagName('categoryname')->item(0)->nodeValue; + $data['optionType'] = $element->getElementsByTagName('optiontype')->item(0)->nodeValue; + + foreach (['defaultValue', 'enableOptions', 'validationPattern'] as $optionalPropertyName) { + $optionalProperty = $element->getElementsByTagName(strtolower($optionalPropertyName))->item(0); + if ($optionalProperty !== null) { + $data[$optionalPropertyName] = $optionalProperty->nodeValue; + } } - } - - foreach (['options', 'permissions'] as $optionalPropertyName) { - $optionalProperty = $element->getElementsByTagName($optionalPropertyName)->item(0); - if ($optionalProperty !== null) { - $data[$optionalPropertyName] = StringUtil::normalizeCsv($optionalProperty->nodeValue); + + $showOrder = $element->getElementsByTagName('showorder')->item(0); + if ($showOrder !== null) { + $data['showOrder'] = $showOrder->nodeValue; } - } - - // object-type specific elements - $optionals = [ - 'minvalue', - 'maxvalue', - 'suffix', - 'minlength', - 'maxlength', - 'issortable', - 'allowemptyvalue', - 'disableAutocomplete' - ]; - - foreach ($optionals as $optionalPropertyName) { - $optionalProperty = $element->getElementsByTagName($optionalPropertyName)->item(0); - if ($optionalProperty !== null) { - $data[$optionalPropertyName] = $optionalProperty->nodeValue; + + foreach (['options', 'permissions'] as $optionalPropertyName) { + $optionalProperty = $element->getElementsByTagName($optionalPropertyName)->item(0); + if ($optionalProperty !== null) { + $data[$optionalPropertyName] = StringUtil::normalizeCsv($optionalProperty->nodeValue); + } } - } - - if ($saveData) { - $lowercaseData = [ - 'categoryname' => $data['categoryName'], - 'packageID' => $this->installation->getPackage()->packageID, - 'name' => $data['optionName'] - ]; - $lowercaseFields = [ - 'optionName', - 'optionType', - 'defaultValue', - 'enableOptions', - 'validationPattern', - 'showOrder' + // object-type specific elements + $optionals = [ + 'minvalue', + 'maxvalue', + 'suffix', + 'minlength', + 'maxlength', + 'issortable', + 'allowemptyvalue', + 'disableAutocomplete' ]; - foreach ($lowercaseFields as $name) { - if (isset($data[$name])) { - $lowercaseData[strtolower($name)] = $data[$name]; + foreach ($optionals as $optionalPropertyName) { + $optionalProperty = $element->getElementsByTagName($optionalPropertyName)->item(0); + if ($optionalProperty !== null) { + $data[$optionalPropertyName] = $optionalProperty->nodeValue; + } + } + } + else { + $data['name'] = $element->getAttribute('name'); + $data['categoryname'] = $element->getElementsByTagName('categoryname')->item(0)->nodeValue; + $data['optiontype'] = $element->getElementsByTagName('optiontype')->item(0)->nodeValue; + + foreach (['defaultvalue', 'enableoptions', 'validationpattern'] as $optionalPropertyName) { + $optionalProperty = $element->getElementsByTagName($optionalPropertyName)->item(0); + if ($optionalProperty !== null) { + $data[$optionalPropertyName] = $optionalProperty->nodeValue; + } + else if ($optionalPropertyName === 'defaultvalue') { + $data[$optionalPropertyName] = null; + } + else { + $data[$optionalPropertyName] = ''; + } + } + + $showOrder = $element->getElementsByTagName('showorder')->item(0); + if ($showOrder !== null) { + $data['showorder'] = $showOrder->nodeValue; + } + if ($this->editedEntry === null) { + // only set explicit showOrder when adding new categories + $data['showorder'] = $this->getShowOrder( + $data['showorder'] ?? null, + $data['categoryName'], + 'categoryName' + ); + } + + foreach (['options', 'permissions'] as $optionalPropertyName) { + $optionalProperty = $element->getElementsByTagName($optionalPropertyName)->item(0); + if ($optionalProperty !== null) { + $data[$optionalPropertyName] = StringUtil::normalizeCsv($optionalProperty->nodeValue); + } + else { + $daota[$optionalPropertyName] = ''; } } - return $lowercaseData; + // object-type specific elements + $optionals = [ + 'minvalue', + 'maxvalue', + 'suffix', + 'minlength', + 'maxlength', + 'issortable', + 'allowemptyvalue', + 'disableAutocomplete' + ]; + + foreach ($optionals as $optionalPropertyName) { + $optionalProperty = $element->getElementsByTagName($optionalPropertyName)->item(0); + if ($optionalProperty !== null) { + $data[$optionalPropertyName] = $optionalProperty->nodeValue; + } + } } break; diff --git a/wcfsetup/install/files/lib/system/package/plugin/AbstractXMLPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/AbstractXMLPackageInstallationPlugin.class.php index 63672c352f..1c76e61fe2 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/AbstractXMLPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/AbstractXMLPackageInstallationPlugin.class.php @@ -374,7 +374,7 @@ abstract class AbstractXMLPackageInstallationPlugin extends AbstractPackageInsta /** * Returns the show order value. * - * @param integer $showOrder + * @param null|integer $showOrder * @param string $parentName * @param string $columnName * @param string $tableNameExtension diff --git a/wcfsetup/install/files/lib/system/package/plugin/BBCodePackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/BBCodePackageInstallationPlugin.class.php index 50fd25ba13..139d3e61b6 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/BBCodePackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/BBCodePackageInstallationPlugin.class.php @@ -255,30 +255,49 @@ class BBCodePackageInstallationPlugin extends AbstractXMLPackageInstallationPlug if ($child !== null) { $data[$arrayKey] = $child->nodeValue; } + else if ($saveData) { + if (substr($arrayKey, 0, 2) === 'is') { + $data[$arrayKey] = 0; + } + else { + $data[$arrayKey] = ''; + } + } } if (!empty($data['wysiwygicon']) && !empty($data['buttonLabel'])) { $data['showButton'] = 1; } + else if ($saveData) { + $data['showButton'] = 0; + } // attributes $attributes = $element->getElementsByTagName('attributes')->item(0); if ($attributes !== null) { $optionalAttributeElements = [ - 'attributeHtml' => 'html', + $saveData ? 'html' : 'attributeHtml' => 'html', 'required' => 'required', - 'useText' => 'usetext', - 'validationPattern' => 'validationpattern', + 'usetext' => $saveData ? 'usetext' : 'useText', + 'validationpattern' => $saveData ? 'validationpattern' : 'validationPattern' ]; /** @var \DOMElement $attribute */ foreach ($attributes->childNodes as $attribute) { - $attributeData = ['name' => $attribute->nodeValue]; + $attributeData = []; - foreach ($optionalAttributeElements as $arrayKey => $elementName) { + foreach ($optionalAttributeElements as $elementName => $arrayIndex) { $child = $attribute->getElementsByTagName($elementName)->item(0); if ($child !== null) { - $attributeData[$arrayKey] = $child->nodeValue; + $attributeData[$arrayIndex] = $child->nodeValue; + } + else if ($saveData) { + if ($elementName === 'required' || $elementName === 'usetext') { + $attributeData[$arrayIndex] = 0; + } + else { + $attributeData[$arrayIndex] = ''; + } } } @@ -530,13 +549,15 @@ class BBCodePackageInstallationPlugin extends AbstractXMLPackageInstallationPlug $attribute = $document->createElement('attribute'); $attribute->setAttribute('name', (string) $attributeNumber); - if (!empty($attributeData['attributeHtml'])) { + if (!empty($attributeData['html'])) { $html = $document->createElement('html'); - $html->appendChild($document->createCDATASection($attributeData['attributeHtml'])); + $html->appendChild($document->createCDATASection($attributeData['html'])); $attribute->appendChild($html); } if (!empty($attributeData['validationPattern'])) { - $attribute->appendChild($document->createElement('validationpattern', $attributeData['validationPattern'])); + $validationpattern = $document->createElement('validationpattern'); + $validationpattern->appendChild($document->createCDATASection($attributeData['validationPattern'])); + $attribute->appendChild($validationpattern); } if (!empty($attributeData['required'])) { $attribute->appendChild($document->createElement('required', $attributeData['required'])); diff --git a/wcfsetup/install/files/lib/system/package/plugin/BoxPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/BoxPackageInstallationPlugin.class.php index cf0a074343..36ad15c2b9 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/BoxPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/BoxPackageInstallationPlugin.class.php @@ -640,11 +640,17 @@ class BoxPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin if ($contentContent !== null) { $data['content'][$languageID] = $contentContent->nodeValue; } + else if ($saveData) { + $data['content'][$languageID] = ''; + } $title = $content->getElementsByTagName('title')->item(0); if ($title !== null) { $data['title'][$languageID] = $title->nodeValue; } + else if ($saveData) { + $data['title'][$languageID] = ''; + } } } @@ -653,6 +659,14 @@ class BoxPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin if ($optionalElement !== null) { $data[$optionalElementName] = $optionalElement->nodeValue; } + else if ($saveData) { + if ($optionalElementName === 'showHeader' || $optionalElementName === 'visibleEverywhere') { + $data[$optionalElementName] = 0; + } + else { + $data[$optionalElementName] = ''; + } + } } $visibilityExceptions = $element->getElementsByTagName('visibilityExceptions')->item(0); diff --git a/wcfsetup/install/files/lib/system/package/plugin/ClipboardActionPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/ClipboardActionPackageInstallationPlugin.class.php index 044fd843ae..ef28aa975e 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/ClipboardActionPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/ClipboardActionPackageInstallationPlugin.class.php @@ -4,6 +4,7 @@ use wcf\data\clipboard\action\ClipboardAction; use wcf\data\clipboard\action\ClipboardActionEditor; use wcf\data\clipboard\action\ClipboardActionList; use wcf\system\clipboard\action\IClipboardAction; +use wcf\system\database\util\PreparedStatementConditionBuilder; use wcf\system\devtools\pip\IDevtoolsPipEntryList; use wcf\system\devtools\pip\IGuiPackageInstallationPlugin; use wcf\system\devtools\pip\TXmlGuiPackageInstallationPlugin; @@ -138,11 +139,15 @@ class ClipboardActionPackageInstallationPlugin extends AbstractXMLPackageInstall * @inheritDoc */ protected function postImport() { + $conditionBuilder = new PreparedStatementConditionBuilder(); + $conditionBuilder->add('packageID = ?', [$this->installation->getPackageID()]); + $conditionBuilder->add('actionID IN (?)', [array_keys($this->pages)]); + // clear pages $sql = "DELETE FROM wcf".WCF_N."_clipboard_page - WHERE packageID = ?"; + " . $conditionBuilder; $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute([$this->installation->getPackageID()]); + $statement->execute($conditionBuilder->getParameters()); if (!empty($this->pages)) { // insert pages @@ -256,6 +261,14 @@ class ClipboardActionPackageInstallationPlugin extends AbstractXMLPackageInstall if ($showOrder !== null) { $data['showOrder'] = $showOrder->nodeValue; } + if ($saveData && $this->editedEntry === null) { + // only set explicit showOrder when adding new clipboard actions + $data['showOrder'] = $this->getShowOrder( + $data['showOrder'] ?? null, + $data['actionClassName'], + 'actionClassName' + ); + } /** @var \DOMElement $page */ foreach ($element->getElementsByTagName('pages')->item(0)->childNodes as $page) { diff --git a/wcfsetup/install/files/lib/system/package/plugin/CronjobPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/CronjobPackageInstallationPlugin.class.php index c4d0cf8ad2..4425dd778f 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/CronjobPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/CronjobPackageInstallationPlugin.class.php @@ -298,14 +298,46 @@ class CronjobPackageInstallationPlugin extends AbstractXMLPackageInstallationPlu } } + $canBeEdited = $element->getElementsByTagName('canbeedited')->item(0); + if ($canBeEdited !== null) { + $data['canBeEdited'] = $canBeEdited->nodeValue; + } + else if ($saveData) { + $data['canBeEdited'] = 1; + } + $canBeEdited = $element->getElementsByTagName('canbeedited')->item(0); if ($canBeEdited !== null) { $data['canBeDisabled'] = $canBeEdited->nodeValue; } + else if ($saveData) { + $data['canBeDisabled'] = 1; + } $isDisabled = $element->getElementsByTagName('isdisabled')->item(0); if ($isDisabled !== null) { - $data['canBeDisabled'] = $isDisabled->nodeValue; + $data['isDisabled'] = $isDisabled->nodeValue; + } + else if ($saveData) { + $data['isDisabled'] = 0; + } + + $isDisabled = $element->getElementsByTagName('options')->item(0); + if ($isDisabled !== null) { + $data['options'] = $isDisabled->nodeValue; + } + else if ($saveData) { + $data['options'] = ''; + } + + if ($saveData) { + $descriptions = $data['description']; + unset($data['description']); + + $data['description'] = []; + foreach ($descriptions as $languageID => $description) { + $data['description'][LanguageFactory::getInstance()->getLanguage($languageID)->languageCode] = $description; + } } return $data; diff --git a/wcfsetup/install/files/lib/system/package/plugin/EventListenerPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/EventListenerPackageInstallationPlugin.class.php index 7882d8a928..3b78f11339 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/EventListenerPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/EventListenerPackageInstallationPlugin.class.php @@ -294,11 +294,35 @@ class EventListenerPackageInstallationPlugin extends AbstractXMLPackageInstallat 'packageID' => $this->installation->getPackage()->packageID ]; - foreach (['environment', 'inherit', 'nice', 'options', 'permissions'] as $optionalElementProperty) { + foreach (['environment', 'inherit', 'options', 'permissions'] as $optionalElementProperty) { $optionalElement = $element->getElementsByTagName($optionalElementProperty)->item(0); if ($optionalElement !== null) { $data[$optionalElementProperty] = $optionalElement->nodeValue; } + else if ($saveData) { + switch ($optionalElementProperty) { + case 'environment': + $data[$optionalElementProperty] = 'user'; + break; + + case 'inherit': + $data[$optionalElementProperty] = 0; + break; + + case 'options': + case 'permissions': + $data[$optionalElementProperty] = ''; + break; + } + } + } + + $niceValue = $element->getElementsByTagName('nice')->item(0); + if ($niceValue !== null) { + $data['niceValue'] = $niceValue->nodeValue; + } + else if ($saveData) { + $data['niceValue'] = 0; } return $data; diff --git a/wcfsetup/install/files/lib/system/package/plugin/LanguagePackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/LanguagePackageInstallationPlugin.class.php index c7ccfe8562..baecb7e179 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/LanguagePackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/LanguagePackageInstallationPlugin.class.php @@ -291,7 +291,7 @@ class LanguagePackageInstallationPlugin extends AbstractXMLPackageInstallationPl * @inheritDoc */ protected function findExistingItem(array $data) { - wcfDebug($data); + // does nothing } /** @@ -529,12 +529,13 @@ class LanguagePackageInstallationPlugin extends AbstractXMLPackageInstallationPl } } else { - $data['languageCategory'] = $languageCategory; + $data['languageCategoryID'] = LanguageFactory::getInstance()->getCategory($languageCategory)->languageCategoryID; } } if (!$saveData) { $data[$element->ownerDocument->documentElement->getAttribute('languagecode')] = $element->nodeValue; + $data['languageCategoryIDMode'] = 'selection'; } return $data; diff --git a/wcfsetup/install/files/lib/system/package/plugin/MediaProviderPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/MediaProviderPackageInstallationPlugin.class.php index 4aae173f4d..6e42a48e9b 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/MediaProviderPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/MediaProviderPackageInstallationPlugin.class.php @@ -8,6 +8,7 @@ use wcf\system\devtools\pip\IGuiPackageInstallationPlugin; use wcf\system\devtools\pip\TXmlGuiPackageInstallationPlugin; use wcf\system\form\builder\container\FormContainer; use wcf\system\form\builder\field\ClassNameFormField; +use wcf\system\form\builder\field\data\CustomFormFieldDataProcessor; use wcf\system\form\builder\field\MultilineTextFormField; use wcf\system\form\builder\field\TextFormField; use wcf\system\form\builder\field\TitleFormField; @@ -187,6 +188,13 @@ class MediaProviderPackageInstallationPlugin extends AbstractXMLPackageInstallat } })) ]); + + $form->getDataHandler()->add(new CustomFormFieldDataProcessor('unifyNewlines', function(IFormDocument $document, array $parameters) { + $parameters['data']['regex'] = StringUtil::unifyNewlines(StringUtil::escapeCDATA($parameters['data']['regex'])); + $parameters['data']['html'] = StringUtil::unifyNewlines(StringUtil::escapeCDATA($parameters['data']['html'])); + + return $parameters; + })); } /** @@ -206,7 +214,6 @@ class MediaProviderPackageInstallationPlugin extends AbstractXMLPackageInstallat $data['html'] = $html->nodeValue; } else if ($saveData) { - // when saving data, `html` has to be present $data['html'] = ''; } @@ -214,6 +221,9 @@ class MediaProviderPackageInstallationPlugin extends AbstractXMLPackageInstallat if ($className !== null) { $data['className'] = $className->nodeValue; } + else if ($saveData) { + $data['className'] = ''; + } return $data; } diff --git a/wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php index 8b8f3c378e..9ca8878dac 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/MenuItemPackageInstallationPlugin.class.php @@ -14,7 +14,6 @@ use wcf\system\devtools\pip\TXmlGuiPackageInstallationPlugin; use wcf\system\exception\SystemException; use wcf\system\form\builder\container\FormContainer; use wcf\system\form\builder\field\dependency\ValueFormFieldDependency; -use wcf\system\form\builder\field\IntegerFormField; use wcf\system\form\builder\field\RadioButtonFormField; use wcf\system\form\builder\field\SingleSelectionFormField; use wcf\system\form\builder\field\TextFormField; @@ -358,15 +357,7 @@ class MenuItemPackageInstallationPlugin extends AbstractXMLPackageInstallationPl ->label('wcf.acp.pip.menuItem.externalURL') ->description('wcf.acp.pip.menuItem.externalURL.description') ->required() - ->i18n(), - - IntegerFormField::create('showOrder') - ->objectProperty('showorder') - ->label('wcf.acp.pip.menuItem.showOrder') - ->description('wcf.acp.pip.menuItem.showOrder.description') - ->objectProperty('showorder') - ->minimum(1) - ->nullable() + ->i18n() ]); /** @var SingleSelectionFormField $menuField */ @@ -449,14 +440,17 @@ class MenuItemPackageInstallationPlugin extends AbstractXMLPackageInstallationPl $data['title'][LanguageFactory::getInstance()->getLanguageByCode($title->getAttribute('language'))->languageID] = $title->nodeValue; } - foreach (['externalURL', 'menu', 'page', 'parent', 'showOrder'] as $optionalElementName) { + foreach (['externalURL', 'menu', 'page', 'parent'] as $optionalElementName) { $optionalElement = $element->getElementsByTagName($optionalElementName)->item(0); if ($optionalElement !== null) { $data[$optionalElementName] = $optionalElement->nodeValue; } + else if ($saveData) { + $data[$optionalElementName] = ''; + } } - if (isset($data['parent'])) { + if (!empty($data['parent'])) { $menuItemList = new MenuItemList(); $menuItemList->getConditionBuilder()->add('identifier = ?', [$data['parent']]); $menuItemList->getConditionBuilder()->add('packageID IN (?)', [ @@ -470,15 +464,27 @@ class MenuItemPackageInstallationPlugin extends AbstractXMLPackageInstallationPl if (count($menuItemList) === 1) { if ($saveData) { $data['menuID'] = $menuItemList->current()->menuID; + $data['parentItemID'] = $menuItemList->current()->itemID; + + unset($data['parent']); } else { $data['menu'] = (new Menu($menuItemList->current()->menuID))->identifier; } } } - else if (isset($data['menu']) && $saveData) { - $data['menuID'] = $this->getMenuID($data['menu']); - unset($data['menu']); + else if ($saveData) { + if (isset($data['menu'])) { + $data['menuID'] = $this->getMenuID($data['menu']); + unset($data['menu']); + } + + $data['parentItemID'] = null; + } + + if ($saveData && $this->editedEntry === null) { + // only set explicit showOrder when adding new menu item + $data['showOrder'] = $this->getItemOrder($data['menuID'], $data['parentItemID']); } if ($saveData) { diff --git a/wcfsetup/install/files/lib/system/package/plugin/ObjectTypeDefinitionPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/ObjectTypeDefinitionPackageInstallationPlugin.class.php index f9eab98446..3962b6b046 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/ObjectTypeDefinitionPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/ObjectTypeDefinitionPackageInstallationPlugin.class.php @@ -155,6 +155,9 @@ class ObjectTypeDefinitionPackageInstallationPlugin extends AbstractXMLPackageIn if ($interfaceName) { $data['interfaceName'] = $interfaceName->nodeValue; } + else if ($saveData) { + $data['interfaceName'] = ''; + } return $data; } diff --git a/wcfsetup/install/files/lib/system/package/plugin/OptionPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/OptionPackageInstallationPlugin.class.php index a6b05c6a06..878fb9f98b 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/OptionPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/OptionPackageInstallationPlugin.class.php @@ -252,7 +252,15 @@ class OptionPackageInstallationPlugin extends AbstractOptionPackageInstallationP foreach (['selectOptions', 'hidden', 'supportI18n', 'requireI18n'] as $optionalPropertyName) { $optionalProperty = $element->getElementsByTagName(strtolower($optionalPropertyName))->item(0); if ($optionalProperty !== null) { - $data[$optionalPropertyName] = $optionalProperty->nodeValue; + $data[$saveData ? strtolower($optionalPropertyName) : $optionalPropertyName] = $optionalProperty->nodeValue; + } + else if ($saveData) { + if ($optionalPropertyName === 'selectOptions') { + $data['selectoptions'] = ''; + } + else { + $data[strtolower($optionalPropertyName)] = 0; + } } } diff --git a/wcfsetup/install/files/lib/system/package/plugin/PagePackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/PagePackageInstallationPlugin.class.php index f21bd44d38..c423f9cb10 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/PagePackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/PagePackageInstallationPlugin.class.php @@ -525,7 +525,7 @@ class PagePackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin } return $nestedOptions; - }, true) + }, atrue) ->addValidator(new FormFieldValidator('selfParent', function(SingleSelectionFormField $formField) { /** @var TextFormField $identifier */ $identifier = $formField->getDocument()->getNodeById('identifier'); @@ -660,23 +660,42 @@ class PagePackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin 'excludeFromLandingPage', 'availableDuringOfflineMode', 'requireObjectID' ]; + $zeroDefaultOptions = [ + 'hasFixedParent', + 'allowSpidersToIndex', + 'excludeFromLandingPage', + 'availableDuringOfflineMode', + 'requireObjectID' + ]; + foreach ($optionalElements as $optionalElementName) { $optionalElement = $element->getElementsByTagName($optionalElementName)->item(0); if ($optionalElement !== null) { $data[$optionalElementName] = $optionalElement->nodeValue; } + else if ($saveData) { + if (in_array($optionalElementName, $zeroDefaultOptions)) { + $data[$optionalElementName] = 0; + } + else { + $data[$optionalElementName] = ''; + } + } } - $readData = function($languageID, \DOMElement $content) use (&$data) { + $readData = function($languageID, \DOMElement $content) use (&$data, $saveData) { foreach (['title', 'content', 'customURL', 'metaDescription', 'metaKeywords'] as $contentElementName) { $contentElement = $content->getElementsByTagName($contentElementName)->item(0); + if (!isset($data[$contentElementName])) { + $data[$contentElementName] = []; + } + if ($contentElement) { - if (!isset($data[$contentElementName])) { - $data[$contentElementName] = []; - } - $data[$contentElementName][$languageID] = $contentElement->nodeValue; } + else if ($saveData) { + $data[$contentElementName][$languageID] = ''; + } } }; diff --git a/wcfsetup/install/files/lib/system/package/plugin/SmileyPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/SmileyPackageInstallationPlugin.class.php index 1b24a882fa..9685b20248 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/SmileyPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/SmileyPackageInstallationPlugin.class.php @@ -168,9 +168,11 @@ class SmileyPackageInstallationPlugin extends AbstractXMLPackageInstallationPlug return; } + $aliases = $this->editedEntry ? $this->editedEntry->getElementsByTagName('aliases')->item(0) : null; if ( $formField->getDocument()->getFormMode() === IFormDocument::FORM_MODE_CREATE || - $this->editedEntry->getElementsByTagName('aliases')->item(0)->nodeValue !== $formField->getSaveValue() + $aliases === null || + $aliases->nodeValue !== $formField->getSaveValue() ) { $notUniqueCodes = []; foreach ($formField->getValue() as $alias) { @@ -243,10 +245,16 @@ class SmileyPackageInstallationPlugin extends AbstractXMLPackageInstallationPlug if ($child !== null) { $data[$arrayKey] = $child->nodeValue; } - } - - if ($saveData && !isset($data['aliases'])) { - $data['aliases'] = ''; + else { + if ($arrayKey === 'showOrder') { + if ($this->editedEntry === null) { + $data[$arrayKey] = $this->getShowOrder(null); + } + } + else { + $data[$arrayKey] = ''; + } + } } return $data; diff --git a/wcfsetup/install/files/lib/system/package/plugin/TemplateListenerPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/TemplateListenerPackageInstallationPlugin.class.php index 6d6c9d9122..0f883d6a6a 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/TemplateListenerPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/TemplateListenerPackageInstallationPlugin.class.php @@ -13,6 +13,9 @@ use wcf\system\devtools\pip\TXmlGuiPackageInstallationPlugin; use wcf\system\form\builder\container\FormContainer; use wcf\system\form\builder\field\data\CustomFormFieldDataProcessor; use wcf\system\form\builder\field\dependency\ValueFormFieldDependency; +use wcf\system\form\builder\field\IntegerFormField; +use wcf\system\form\builder\field\OptionFormField; +use wcf\system\form\builder\field\UserGroupOptionFormField; use wcf\system\form\builder\field\validation\FormFieldValidationError; use wcf\system\form\builder\field\validation\FormFieldValidator; use wcf\system\form\builder\field\MultilineTextFormField; @@ -274,7 +277,7 @@ class TemplateListenerPackageInstallationPlugin extends AbstractXMLPackageInstal $nameField = $formField->getDocument()->getNodeById('name'); /** @var SingleSelectionFormField $templateNameFormField */ - $templateNameFormField = $formField->getDocument()->getNodeById('templateName'); + $templateNameFormField = $formField->getDocument()->getNodeById('frontendTemplateName'); /** @var SingleSelectionFormField $acpTemplateNameFormField */ $acpTemplateNameFormField = $formField->getDocument()->getNodeById('acpTemplateName'); @@ -334,7 +337,29 @@ class TemplateListenerPackageInstallationPlugin extends AbstractXMLPackageInstal ->objectProperty('templatecode') ->label('wcf.acp.pip.templateListener.templateCode') ->description('wcf.acp.pip.templateListener.templateCode.description') - ->required() + ->required(), + + IntegerFormField::create('niceValue') + ->objectProperty('nice') + ->label('wcf.acp.pip.templateListener.niceValue') + ->description('wcf.acp.pip.templateListener.niceValue.description') + ->nullable() + ->minimum(-128) + ->maximum(127), + + OptionFormField::create() + ->description('wcf.acp.pip.templateListener.options.description') + ->packageIDs(array_merge( + [$this->installation->getPackage()->packageID], + array_keys($this->installation->getPackage()->getAllRequiredPackages()) + )), + + UserGroupOptionFormField::create() + ->description('wcf.acp.pip.templateListener.permissions.description') + ->packageIDs(array_merge( + [$this->installation->getPackage()->packageID], + array_keys($this->installation->getPackage()->getAllRequiredPackages()) + )) ]); /** @var SingleSelectionFormField $environment */ @@ -364,7 +389,7 @@ class TemplateListenerPackageInstallationPlugin extends AbstractXMLPackageInstal * @since 3.2 */ protected function doGetElementData(\DOMElement $element, $saveData) { - return [ + $data = [ 'environment' => $element->getElementsByTagName('environment')->item(0)->nodeValue, 'eventName' => $element->getElementsByTagName('eventname')->item(0)->nodeValue, 'name' => $element->getAttribute('name'), @@ -372,6 +397,26 @@ class TemplateListenerPackageInstallationPlugin extends AbstractXMLPackageInstal 'templateCode' => $element->getElementsByTagName('templatecode')->item(0)->nodeValue, 'templateName' => $element->getElementsByTagName('templatename')->item(0)->nodeValue ]; + + $nice = $element->getElementsByTagName('nice')->item(0); + if ($nice !== null) { + $data['niceValue'] = $nice->nodeValue; + } + else if ($saveData) { + $data['niceValue'] = 0; + } + + foreach (['options', 'permissions'] as $elementName) { + $optionalElement = $element->getElementsByTagName($elementName)->item(0); + if ($optionalElement !== null) { + $data[$elementName] = $optionalElement->nodeValue; + } + else if ($saveData) { + $data[$elementName] = ''; + } + } + + return $data; } /** @@ -406,7 +451,7 @@ class TemplateListenerPackageInstallationPlugin extends AbstractXMLPackageInstal case 'user': /** @var SingleSelectionFormField $templateName */ - $templateName = $document->getNodeById('templateName'); + $templateName = $document->getNodeById('frontendTemplateName'); /** @var SingleSelectionFormField $eventName */ $eventName = $document->getNodeById($data['templateName'] . '_eventName'); @@ -456,7 +501,10 @@ class TemplateListenerPackageInstallationPlugin extends AbstractXMLPackageInstal 'eventname', 'templatecode' => [ 'cdata' => true - ] + ], + 'nice' => 0, + 'options' => '', + 'permissions' => '' ], $form ); diff --git a/wcfsetup/install/files/lib/system/package/plugin/UserGroupOptionPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/UserGroupOptionPackageInstallationPlugin.class.php index be76c88840..630e8a6a8d 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/UserGroupOptionPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/UserGroupOptionPackageInstallationPlugin.class.php @@ -288,6 +288,11 @@ class UserGroupOptionPackageInstallationPlugin extends AbstractOptionPackageInst $data[$optionalPropertyName] = $optionalProperty->nodeValue; } } + else if ($saveData && $optionalPropertyName === 'usersOnly') { + // all of the other fields will be put in `additionalData` + // or not saved thus empty values are not necessary + $data['usersonly'] = 0; + } } break; diff --git a/wcfsetup/install/files/lib/system/package/plugin/UserMenuPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/UserMenuPackageInstallationPlugin.class.php index 2f424afd49..4273cfe9a2 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/UserMenuPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/UserMenuPackageInstallationPlugin.class.php @@ -107,7 +107,7 @@ class UserMenuPackageInstallationPlugin extends AbstractMenuPackageInstallationP // thus the parent menu item must be at least on the second level // for the menu item to support links $menuItemsSupportingLinks = array_keys(array_filter($menuItemLevels, function($menuItemLevel) { - return $menuItemLevel >= 2; + return $menuItemLevel >= 1; })); foreach (['menuItemController', 'menuItemLink'] as $nodeId) { @@ -132,11 +132,17 @@ class UserMenuPackageInstallationPlugin extends AbstractMenuPackageInstallationP if ($className !== null) { $data['className'] = $className->nodeValue; } + else if ($saveData) { + $data['className'] = ''; + } $icon = $element->getElementsByTagName('iconclassname')->item(0); if ($icon !== null) { $data['iconClassName'] = $icon->nodeValue; } + else if ($saveData) { + $data['iconClassName'] = ''; + } return $data; } diff --git a/wcfsetup/install/files/lib/system/package/plugin/UserNotificationEventPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/UserNotificationEventPackageInstallationPlugin.class.php index 78ba3657be..c4ebc7a244 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/UserNotificationEventPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/UserNotificationEventPackageInstallationPlugin.class.php @@ -306,21 +306,33 @@ class UserNotificationEventPackageInstallationPlugin extends AbstractXMLPackageI if ($options) { $data['options'] = StringUtil::normalizeCsv($options->nodeValue); } + else if ($saveData) { + $data['options'] = ''; + } $permissions = $element->getElementsByTagName('permissions')->item(0); if ($permissions) { $data['permissions'] = StringUtil::normalizeCsv($permissions->nodeValue); } + else if ($saveData) { + $data['permissions'] = ''; + } // the presence of a `preset` element is treated as `1 if ($element->getElementsByTagName('preset')->length === 1) { $data['preset'] = 1; } + else if ($saveData) { + $data['preset'] = 0; + } $presetMailNotificationType = $element->getElementsByTagName('presetmailnotificationtype')->item(0); if ($presetMailNotificationType && in_array($presetMailNotificationType->nodeValue, ['instant', 'daily'])) { $data['presetMailNotificationType'] = $presetMailNotificationType->nodeValue; } + else if ($saveData) { + $data['presetMailNotificationType'] = 'none'; + } return $data; } diff --git a/wcfsetup/install/files/lib/system/package/plugin/UserOptionPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/UserOptionPackageInstallationPlugin.class.php index 91fc08cfa1..05544a331b 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/UserOptionPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/UserOptionPackageInstallationPlugin.class.php @@ -238,6 +238,7 @@ class UserOptionPackageInstallationPlugin extends AbstractOptionPackageInstallat ->label('wcf.acp.pip.userOption.options.editable') ->description('wcf.acp.pip.userOption.options.editable.description') ->options([ + 0 => 'wcf.acp.user.option.editable.0', 1 => 'wcf.acp.user.option.editable.1', 2 => 'wcf.acp.user.option.editable.2', 3 => 'wcf.acp.user.option.editable.3', @@ -361,6 +362,11 @@ class UserOptionPackageInstallationPlugin extends AbstractOptionPackageInstallat $data[$optionalPropertyName] = $optionalProperty->nodeValue; } } + else if ($saveData && $optionalPropertyName === 'selectOptions') { + // all of the other fields will be put in `additionalData`, + // thus empty values are not necessary + $data['selectoptions'] = ''; + } } $messageObjectType = $element->getElementsByTagName('messageObjectType')->item(0); @@ -423,9 +429,9 @@ class UserOptionPackageInstallationPlugin extends AbstractOptionPackageInstallat 'outputclass' => '', 'required' => 0, 'askduringregistration' => 0, - 'editable' => '0', - 'visible' => '0', 'searchable' => 0, + 'visible' => '0', + 'editable' => '0', 'isdisabled' => 0, 'messageObjectType' => '', 'contentpattern' => '' diff --git a/wcfsetup/install/files/lib/system/package/plugin/UserProfileMenuPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/UserProfileMenuPackageInstallationPlugin.class.php index 8368ac96ba..d34635a0b8 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/UserProfileMenuPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/UserProfileMenuPackageInstallationPlugin.class.php @@ -188,16 +188,26 @@ class UserProfileMenuPackageInstallationPlugin extends AbstractXMLPackageInstall if ($options) { $data['options'] = StringUtil::normalizeCsv($options->nodeValue); } + else if ($saveData) { + $data['options'] = ''; + } $permissions = $element->getElementsByTagName('permissions')->item(0); if ($permissions) { $data['permissions'] = StringUtil::normalizeCsv($permissions->nodeValue); } + else if ($saveData) { + $data['permissions'] = ''; + } $showOrder = $element->getElementsByTagName('showorder')->item(0); if ($showOrder) { $data['showOrder'] = intval($showOrder->nodeValue); } + if ($saveData && $this->editedEntry === null) { + // only set explicit showOrder when adding new menu item + $data['showOrder'] = $this->getShowOrder($data['showOrder'] ?? null); + } return $data; } diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index 1ecb9d4faa..ef1698fa2b 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -2183,7 +2183,7 @@ If you have already bought the licenses for the listed apps, th {$notUniqueCode}{/implode}.]]> - + {'WCF_DIR'|constant}.]]> -- 2.20.1