From efbc545e4a64a47a7932344283ec8422c4c27e8c Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Fri, 13 Jul 2018 10:34:20 +0200 Subject: [PATCH] Add GUI for eventListener package installation plugin See #2545 --- ...istenerPackageInstallationPlugin.class.php | 207 +++++++++++++++++- wcfsetup/install/lang/en.xml | 17 ++ 2 files changed, 221 insertions(+), 3 deletions(-) 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 505fdaf5d5..e6e24ef32e 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/EventListenerPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/EventListenerPackageInstallationPlugin.class.php @@ -3,20 +3,37 @@ declare(strict_types=1); namespace wcf\system\package\plugin; use wcf\data\event\listener\EventListener; use wcf\data\event\listener\EventListenerEditor; +use wcf\data\event\listener\EventListenerList; use wcf\system\cache\builder\EventListenerCacheBuilder; -use wcf\system\devtools\pip\IIdempotentPackageInstallationPlugin; +use wcf\system\devtools\pip\IDevtoolsPipEntryList; +use wcf\system\devtools\pip\IGuiPackageInstallationPlugin; +use wcf\system\devtools\pip\TXmlGuiPackageInstallationPlugin; +use wcf\system\event\listener\IParameterizedEventListener; +use wcf\system\form\builder\container\FormContainer; +use wcf\system\form\builder\field\BooleanFormField; +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; /** * Installs, updates and deletes event listeners. * - * @author Marcel Werk + * @author Matthias Schmidt, Marcel Werk * @copyright 2001-2018 WoltLab GmbH * @license GNU Lesser General Public License * @package WoltLabSuite\Core\System\Package\Plugin */ -class EventListenerPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin implements IIdempotentPackageInstallationPlugin { +class EventListenerPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin implements IGuiPackageInstallationPlugin { + use TXmlGuiPackageInstallationPlugin; + /** * @inheritDoc */ @@ -161,9 +178,193 @@ class EventListenerPackageInstallationPlugin extends AbstractXMLPackageInstallat /** * @inheritDoc + * @since 3.1 */ public static function getSyncDependencies() { return []; } + /** + * @inheritDoc + * @since 3.2 + */ + public function addFormFields(IFormDocument $form) { + /** @var FormContainer $dataContainer */ + $dataContainer = $form->getNodeById('data'); + + $dataContainer->appendChildren([ + TextFormField::create('listenerName') + ->label('wcf.acp.pip.eventListener.listenerName') + ->description('wcf.acp.pip.eventListener.listenerName.description') + ->required() + ->addValidator(new FormFieldValidator('format', function(TextFormField $formField) { + if (preg_match('~^[a-z][A-z0-9]*$~', $formField->getSaveValue()) !== 1) { + $formField->addValidationError( + new FormFieldValidationError( + 'format', + 'wcf.acp.pip.eventListener.listenerName.error.format' + ) + ); + } + })) + ->addValidator(new FormFieldValidator('uniqueness', function(TextFormField $formField) { + if ( + $formField->getDocument()->getFormMode() === IFormDocument::FORM_MODE_CREATE || + $this->editedEntry->getAttribute('name') !== $formField->getValue() + ) { + $eventListenerList = new EventListenerList(); + $eventListenerList->getConditionBuilder()->add('listenerName = ?', [$formField->getValue()]); + + if ($eventListenerList->countObjects() > 0) { + $formField->addValidationError( + new FormFieldValidationError( + 'notUnique', + 'wcf.acp.pip.eventListener.listenerName.error.notUnique' + ) + ); + } + } + })), + + ClassNameFormField::create('eventClassName') + ->objectProperty('eventclassname') + ->label('wcf.acp.pip.eventListener.eventClassName') + ->description('wcf.acp.pip.eventListener.eventClassName.description') + ->required() + ->instantiable(false), + + TextFormField::create('eventName') + ->objectProperty('eventname') + ->label('wcf.acp.pip.eventListener.eventName') + ->description('wcf.acp.pip.eventListener.eventName.description') + ->required(), + + ClassNameFormField::create('listenerClassName') + ->objectProperty('listenerclassname') + ->label('wcf.acp.pip.eventListener.listenerClassName') + ->required() + ->implementedInterface(IParameterizedEventListener::class), + + SingleSelectionFormField::create('environment') + ->label('wcf.acp.pip.eventListener.environment') + ->description('wcf.acp.pip.eventListener.environment.description') + ->options([ + 'admin' => 'admin', + 'user' => 'user' + ]) + ->value('user'), + + BooleanFormField::create('inherit') + ->label('wcf.acp.pip.eventListener.inherit') + ->description('wcf.acp.pip.eventListener.inherit.description'), + + IntegerFormField::create('niceValue') + ->objectProperty('nice') + ->label('wcf.acp.pip.eventListener.niceValue') + ->description('wcf.acp.pip.eventListener.niceValue.description') + ->nullable() + ->minimum(-128) + ->maximum(127), + + OptionFormField::create() + ->description('wcf.acp.pip.eventListener.options.description') + ->packageIDs(array_merge( + [$this->installation->getPackage()->packageID], + array_keys($this->installation->getPackage()->getAllRequiredPackages()) + )), + + UserGroupOptionFormField::create() + ->description('wcf.acp.pip.eventListener.permissions.description') + ->packageIDs(array_merge( + [$this->installation->getPackage()->packageID], + array_keys($this->installation->getPackage()->getAllRequiredPackages()) + )) + ]); + } + + /** + * @inheritDoc + * @since 3.2 + */ + protected function getElementData(\DOMElement $element, bool $saveData = false): array { + $data = [ + 'eventClassName' => $element->getElementsByTagName('eventclassname')->item(0)->nodeValue, + 'eventName' => StringUtil::normalizeCsv($element->getElementsByTagName('eventname')->item(0)->nodeValue), + 'listenerClassName' => $element->getElementsByTagName('listenerclassname')->item(0)->nodeValue, + 'listenerName' => $element->getAttribute('name'), + 'packageID' => $this->installation->getPackage()->packageID + ]; + + foreach (['environment', 'inherit', 'nice', 'options', 'permissions'] as $optionalElementProperty) { + $optionalElement = $element->getElementsByTagName($optionalElementProperty)->item(0); + if ($optionalElement !== null) { + $data[$optionalElementProperty] = $optionalElement->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([ + 'listenerName' => 'wcf.acp.pip.eventListener.listenerName', + 'eventClassName' => 'wcf.acp.pip.eventListener.eventClassName', + 'eventName' => 'wcf.acp.pip.eventListener.eventName' + ]); + } + + /** + * @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 { + $data = $form->getData()['data']; + + $eventListener = $document->createElement($this->tagName); + $eventListener->setAttribute('name', $data['listenerName']); + + foreach (['eventclassname', 'eventname', 'listenerclassname'] as $property) { + $eventListener->appendChild($document->createElement($property, $data[$property])); + } + + foreach (['environment', 'inherit', 'nice', 'options', 'permissions'] as $optionalProperty) { + if (!empty($data[$optionalProperty])) { + $eventListener->appendChild($document->createElement($optionalProperty, (string)$data[$optionalProperty])); + } + } + + $document->getElementsByTagName('import')->item(0)->appendChild($eventListener); + + return $eventListener; + } } diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index 0b7146d899..fd4e723755 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -2032,6 +2032,23 @@ If you have already bought the licenses for the listed apps, th + + + + + + + + + + + user) or the ACP (admin).]]> + + + + + + -- 2.20.1