Add GUI support for abstract menu package installation plugin
authorMatthias Schmidt <gravatronics@live.com>
Sun, 10 Jun 2018 08:44:22 +0000 (10:44 +0200)
committerMatthias Schmidt <gravatronics@live.com>
Sun, 10 Jun 2018 08:44:22 +0000 (10:44 +0200)
See #2545

wcfsetup/install/files/lib/system/package/plugin/AbstractMenuPackageInstallationPlugin.class.php
wcfsetup/install/lang/en.xml

index a6d3b2542893793a14798eaf873d9f46dad9fcf7..6514eda01a1b20bb9b3956504571e9ffa5e81641 100644 (file)
@@ -1,10 +1,24 @@
 <?php
 declare(strict_types=1);
 namespace wcf\system\package\plugin;
+use wcf\page\IPage;
+use wcf\system\devtools\pip\IDevtoolsPipEntryList;
 use wcf\system\devtools\pip\IIdempotentPackageInstallationPlugin;
+use wcf\system\devtools\pip\TXmlGuiPackageInstallationPlugin;
 use wcf\system\exception\SystemException;
+use wcf\system\form\builder\container\IFormContainer;
+use wcf\system\form\builder\field\ClassNameFormField;
+use wcf\system\form\builder\field\IntegerFormField;
+use wcf\system\form\builder\field\OptionFormField;
+use wcf\system\form\builder\field\SingleSelectionFormField;
+use wcf\system\form\builder\field\TextFormField;
+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\IFormDocument;
 use wcf\system\WCF;
 use wcf\util\StringUtil;
+use wcf\util\Url;
 
 /**
  * Abstract implementation of a package installation plugin for menu items.
@@ -15,6 +29,12 @@ use wcf\util\StringUtil;
  * @package    WoltLabSuite\Core\System\Package\Plugin
  */
 abstract class AbstractMenuPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin implements IIdempotentPackageInstallationPlugin {
+       // we do no implement `IGuiPackageInstallationPlugin` but instead just
+       // provide the default implementation to ensure backwards compatibility
+       // with third-party packages containing classes that extend this abstract
+       // class
+       use TXmlGuiPackageInstallationPlugin;
+       
        /**
         * @inheritDoc
         */
@@ -92,8 +112,201 @@ abstract class AbstractMenuPackageInstallationPlugin extends AbstractXMLPackageI
        
        /**
         * @inheritDoc
+        * @since       3.1
         */
        public static function getSyncDependencies() {
                return [];
        }
+       
+       /**
+        * @inheritDoc
+        * @since       3.2
+        */
+       public function addFormFields(IFormDocument $form) {
+               /** @var IFormContainer $dataContainer */
+               $dataContainer = $form->getNodeById('data');
+               
+               $dataContainer->appendChildren([
+                       TextFormField::create('menuItem')
+                               ->objectProperty('name')
+                               ->label('wcf.acp.pip.abstractMenu.menuItem'),
+                       
+                       SingleSelectionFormField::create('parentMenuItem')
+                               ->objectProperty('parent')
+                               ->label('wcf.acp.pip.abstractForm.parentMenuItem')
+                               ->filterable(),
+                       
+                       ClassNameFormField::create('menuItemController')
+                               ->objectProperty('controller')
+                               ->label('wcf.acp.pip.abstractForm.menuItemController')
+                               ->implementedInterface(IPage::class),
+                       
+                       TextFormField::create('menuItemLink')
+                               ->objectProperty('link')
+                               ->label('wcf.acp.pip.abstractMenu.menuItemLink')
+                               ->description('wcf.acp.pip.abstractMenu.menuItemLink.description')
+                               ->objectProperty('link')
+                               ->addValidator(new FormFieldValidator('linkSpecified', function(TextFormField $formField) {
+                                       /** @var ClassNameFormField $menuItemController */
+                                       $menuItemController = $formField->getDocument()->getNodeById('menuItemController');
+                                       
+                                       // ensure that either a menu item controller is specified or a link
+                                       if ($formField->getSaveValue() === '' && $menuItemController->getSaveValue() === '') {
+                                               $formField->addValidationError(
+                                                       new FormFieldValidationError(
+                                                               'noLinkSpecified',
+                                                               'wcf.acp.pip.abstractMenu.menuItemLink.error.noLinkSpecified'
+                                                       )
+                                               );
+                                       }
+                               }))
+                               ->addValidator(new FormFieldValidator('format', function(TextFormField $formField) {
+                                       if ($formField->getSaveValue() !== '') {
+                                               /** @var ClassNameFormField $menuItemController */
+                                               $menuItemController = $formField->getDocument()->getNodeById('menuItemController');
+                                               
+                                               if (!$menuItemController->getSaveValue() && !Url::is($formField->getSaveValue())) {
+                                                       $formField->addValidationError(
+                                                               new FormFieldValidationError(
+                                                                       'noLink',
+                                                                       'wcf.acp.pip.abstractMenu.menuItemLink.error.noLink'
+                                                               )
+                                                       );
+                                               }
+                                               else if ($menuItemController->getSaveValue() && Url::is($formField->getSaveValue())) {
+                                                       $formField->addValidationError(
+                                                               new FormFieldValidationError(
+                                                                       'isLink',
+                                                                       'wcf.acp.pip.abstractMenu.menuItemLink.error.isLink'
+                                                               )
+                                                       );
+                                               }
+                                       }
+                               })),
+                       
+                       OptionFormField::create()
+                               ->description('wcf.acp.pip.abstractMenu.options.description')
+                               ->saveValueType(OptionFormField::SAVE_VALUE_TYPE_CSV)
+                               ->packageIDs(array_merge(
+                                       [$this->installation->getPackage()->packageID],
+                                       array_keys($this->installation->getPackage()->getAllRequiredPackages())
+                               )),
+                       
+                       UserGroupOptionFormField::create()
+                               ->description('wcf.acp.pip.abstractMenu.options.description')
+                               ->saveValueType(OptionFormField::SAVE_VALUE_TYPE_CSV)
+                               ->packageIDs(array_merge(
+                                       [$this->installation->getPackage()->packageID],
+                                       array_keys($this->installation->getPackage()->getAllRequiredPackages())
+                               )),
+                       
+                       IntegerFormField::create('showOrder')
+                               ->objectProperty('showorder')
+                               ->label('wcf.acp.pip.abstractMenu.showOrder')
+                               ->description('wcf.acp.pip.abstractMenu.showOrder.description')
+                               ->objectProperty('showorder')
+                               ->minimum(1)
+               ]);
+       }
+       
+       /**
+        * @inheritDoc
+        * @since       3.2
+        */
+       protected function getElementData(\DOMElement $element): array {
+               $data = [
+                       'menuItem' => $element->getAttribute('name'),
+                       'packageID' => $this->installation->getPackage()->packageID
+               ];
+               
+               $parentMenuItem = $element->getElementsByTagName('parent')->item(0);
+               if ($parentMenuItem !== null) {
+                       $data['parentMenuItem'] = $parentMenuItem->nodeValue;
+               }
+               
+               $controller = $element->getElementsByTagName('controller')->item(0);
+               if ($controller !== null) {
+                       $data['menuItemController'] = $controller->nodeValue;
+               }
+               
+               $link = $element->getElementsByTagName('link')->item(0);
+               if ($link !== null) {
+                       $data['menuItemLink'] = $link->nodeValue;
+               }
+               
+               $options = $element->getElementsByTagName('options')->item(0);
+               if ($options !== null) {
+                       $data['options'] = $options->nodeValue;
+               }
+               
+               $permissions = $element->getElementsByTagName('permissions')->item(0);
+               if ($permissions !== null) {
+                       $data['permissions'] = $permissions->nodeValue;
+               }
+               
+               $showOrder = $element->getElementsByTagName('showOrder')->item(0);
+               if ($showOrder !== null) {
+                       $data['showOrder'] = $showOrder->nodeValue;
+               }
+               
+               return $data;
+       }
+       
+       /**
+        * @inheritDoc
+        * @since       3.2
+        */
+       public function getElementIdentifier(\DOMElement $element): string {
+               return $element->getAttribute('name');
+       }
+       
+       /**
+        * @inheritDoc
+        * @since       3.2
+        */
+       protected function setEntryListKeys(IDevtoolsPipEntryList $entryList) {
+               $entryList->setKeys([
+                       'menuItem' => 'wcf.acp.pip.abstractMenu.menuItem',
+                       'parentMenuItem' => 'wcf.acp.pip.abstractMenu.parentMenuItem'
+               ]);
+       }
+       
+       /**
+        * @inheritDoc
+        * @since       3.2
+        */
+       protected function sortDocument(\DOMDocument $document) {
+               $this->sortImportDelete($document);
+               
+               $compareFunction = function(\DOMElement $element1, \DOMElement $element2) {
+                       return strcmp(
+                               $element1->getAttribute('name'),
+                               $element2->getAttribute('name')
+                       );
+               };
+               
+               $this->sortChildNodes($document->getElementsByTagName('import'), $compareFunction);
+               $this->sortChildNodes($document->getElementsByTagName('delete'), $compareFunction);
+       }
+       
+       /**
+        * @inheritDoc
+        * @since       3.2
+        */
+       protected function writeEntry(\DOMDocument $document, IFormDocument $form): \DOMElement {
+               $formData = $form->getData()['data'];
+               
+               $menuItem = $document->createElement($this->tagName);
+               $menuItem->setAttribute('name', $formData['name']);
+               
+               foreach (['parent', 'controller', 'link', 'options', 'permissions', 'showorder'] as $field) {
+                       if (isset($formData[$field]) && $formData[$field] !== '') {
+                               $menuItem->appendChild($document->createElement($field, (string) $formData[$field]));
+                       }
+               }
+               
+               $document->getElementsByTagName('import')->item(0)->appendChild($menuItem);
+               
+               return $menuItem;
+       }
 }
index b451cec215fd6e91f1d27b71b9a1d7b134390f72..f020e4aaa6dd640fa6cf9281ae5360276aa63115 100644 (file)
@@ -1900,6 +1900,19 @@ When prompted for the notification URL for the instant payment notifications, pl
                <item name="wcf.acp.pip.aclOption.objectType.categories.error.notUnique"><![CDATA[The entered name is already used by another ACL option category for the same ACL object type.]]></item>
                <item name="wcf.acp.pip.aclOption.objectType.options.description"><![CDATA[The ACL object type determines to which type of objects the option belongs to. Note that only ACL object types of the package itself or its required packages are available.]]></item>
                <item name="wcf.acp.pip.aclOption.objectType.options.error.notUnique"><![CDATA[The entered name is already used by another ACL option for the same ACL object type.]]></item>
+               <item name="wcf.acp.pip.abstractMenu.menuItem"><![CDATA[Menu Item Identifier]]></item>
+               <item name="wcf.acp.pip.abstractMenu.menuItem.error.notUnique"><![CDATA[The entered identifier is already used by another menu item.]]></item>
+               <item name="wcf.acp.pip.abstractForm.parentMenuItem"><![CDATA[Parent Menu Item]]></item>
+               <item name="wcf.acp.pip.abstractForm.menuItemController"><![CDATA[Menu Item Controller]]></item>
+               <item name="wcf.acp.pip.abstractMenu.menuItemLink"><![CDATA[Menu Item Link]]></item>
+               <item name="wcf.acp.pip.abstractMenu.menuItemLink.description"><![CDATA[If no menu item controller is used, the entered link will be used. If, however, a menu item controller is used, the entered link will be appended to the link to the controller.]]></item>
+               <item name="wcf.acp.pip.abstractMenu.menuItemLink.error.isLink"><![CDATA[The entered value is a valid link. If you entered a menu item controller, the menu item link is appended to the link to the controller.]]></item>
+               <item name="wcf.acp.pip.abstractMenu.menuItemLink.error.noLink"><![CDATA[The entered value is no valid link.]]></item>
+               <item name="wcf.acp.pip.abstractMenu.menuItemLink.error.noLinkSpecified"><![CDATA[You either have to enter a menu item controller or a menu item link.]]></item>
+               <item name="wcf.acp.pip.abstractMenu.options.description"><![CDATA[At least one of the entered options has to be enabled for the menu item to be visible. Options of non-required packages will be reported as non-existing.]]></item>
+               <item name="wcf.acp.pip.abstractMenu.permissions.description"><![CDATA[The active user must be granted at least one of the entered permissions in order to see the menu item. Permissions of non-required packages will be reported as non-existing.]]></item>
+               <item name="wcf.acp.pip.abstractMenu.showOrder"><![CDATA[Position]]></item>
+               <item name="wcf.acp.pip.abstractMenu.showOrder.description"><![CDATA[The entered value determines in which order the menu items with the same parent are shown.]]></item>
        </category>
        
        <category name="wcf.acp.rebuildData">