Improve extensibility of `ObjectTypePackageInstallationPlugin` for plugins
authorMatthias Schmidt <gravatronics@live.com>
Sat, 2 Jun 2018 07:25:18 +0000 (09:25 +0200)
committerMatthias Schmidt <gravatronics@live.com>
Sat, 2 Jun 2018 07:25:18 +0000 (09:25 +0200)
See #2545

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

index 6ee686a44147f0570b755a4bdb6c37d04111edd5..4eadc02d0f611207974b7b3dd5a5863283bcd281 100644 (file)
@@ -333,43 +333,11 @@ class ObjectTypePackageInstallationPlugin extends AbstractXMLPackageInstallation
                        );
                
                // com.woltlab.wcf.bulkProcessing.user.action
-               $this->getObjectTypeDefinitionDataContainer($form, 'com.woltlab.wcf.bulkProcessing.user.action')
-                       ->appendChildren([
-                               TextFormField::create('bulkProcessingUserAction')
-                                       ->objectProperty('action')
-                                       ->label('wcf.acp.pip.objectType.com.woltlab.wcf.bulkProcessing.user.action.action')
-                                       ->description('wcf.acp.pip.objectType.com.woltlab.wcf.bulkProcessing.user.action.action.description')
-                                       ->addValidator(new FormFieldValidator('format', function(TextFormField $formField) {
-                                               if (!preg_match('~^[a-z][A-z]+$~', $formField->getValue())) {
-                                                       $formField->addValidationError(
-                                                               new FormFieldValidationError(
-                                                                       'format',
-                                                                       'wcf.acp.pip.objectType.com.woltlab.wcf.bulkProcessing.user.action.action.error.format'
-                                                               )
-                                                       );
-                                               }
-                                       })),
-                               
-                               OptionFormField::create('bulkProcessingUserOptions')
-                                       ->objectProperty('options')
-                                       ->description('wcf.acp.pip.objectType.com.woltlab.wcf.bulkProcessing.user.action.options.description')
-                                       ->packageIDs(array_merge(
-                                               [$this->installation->getPackage()->packageID],
-                                               array_keys($this->installation->getPackage()->getAllRequiredPackages())
-                                       )),
-                               
-                               UserGroupOptionFormField::create('bulkProcessingUserPermissions')
-                                       ->objectProperty('permissions')
-                                       ->description('wcf.acp.pip.objectType.com.woltlab.wcf.bulkProcessing.user.action.permissions.description')
-                                       ->packageIDs(array_merge(
-                                               [$this->installation->getPackage()->packageID],
-                                               array_keys($this->installation->getPackage()->getAllRequiredPackages())
-                                       ))
-                       ]);
+               $this->addBulkProcessingActionFields($form, 'com.woltlab.wcf.bulkProcessing.user.action');
                
                // com.woltlab.wcf.bulkProcessing.user.condition
                $bulkProcessingUserConditionContainer = $this->getObjectTypeDefinitionDataContainer($form, 'com.woltlab.wcf.bulkProcessing.user.condition');
-               $this->addConditionFields($bulkProcessingUserConditionContainer, true, true);
+               $this->addConditionFields($bulkProcessingUserConditionContainer);
                
                // com.woltlab.wcf.category
                $this->getObjectTypeDefinitionDataContainer($form, 'com.woltlab.wcf.category')
@@ -676,7 +644,7 @@ XML;
         * @return      FormContainer
         * @since       3.2
         */
-       protected function getObjectTypeDefinitionDataContainer(IFormDocument $form, string $definitionName): FormContainer {
+       public function getObjectTypeDefinitionDataContainer(IFormDocument $form, string $definitionName): FormContainer {
                /** @var SingleSelectionFormField $definitionNameField */
                $definitionNameField = $form->getNodeById('definitionName');
                
@@ -770,6 +738,52 @@ XML;
                return $type;
        }
        
+       /**
+        * Adds bulk processing action-related fields to the given form for the given bulk
+        * processing action object type definition. 
+        * 
+        * @param       IFormDocument   $form
+        * @param       string          $objectTypeDefinition
+        */
+       public function addBulkProcessingActionFields(IFormDocument $form, string $objectTypeDefinition) {
+               $definitionPieces = explode('.', $objectTypeDefinition);
+               $definitionIdString = implode('', array_map('ucfirst', $definitionPieces));
+               
+               $this->getObjectTypeDefinitionDataContainer($form, $objectTypeDefinition)
+                       ->appendChildren([
+                               TextFormField::create('bulkProcessing' . $definitionIdString . 'Action')
+                                       ->objectProperty('action')
+                                       ->label('wcf.acp.pip.objectType.bulkProcessing.action')
+                                       ->description('wcf.acp.pip.objectType.bulkProcessing.action.description')
+                                       ->addValidator(new FormFieldValidator('format', function(TextFormField $formField) {
+                                               if (!preg_match('~^[a-z][A-z]+$~', $formField->getValue())) {
+                                                       $formField->addValidationError(
+                                                               new FormFieldValidationError(
+                                                                       'format',
+                                                                       'wcf.acp.pip.objectType.bulkProcessing.action.error.format'
+                                                               )
+                                                       );
+                                               }
+                                       })),
+                               
+                               OptionFormField::create('bulkProcessing' . $definitionIdString . 'Options')
+                                       ->objectProperty('options')
+                                       ->description('wcf.acp.pip.objectType.bulkProcessing.action.options.description')
+                                       ->packageIDs(array_merge(
+                                               [$this->installation->getPackage()->packageID],
+                                               array_keys($this->installation->getPackage()->getAllRequiredPackages())
+                                       )),
+                               
+                               UserGroupOptionFormField::create('bulkProcessing' . $definitionIdString . 'Permissions')
+                                       ->objectProperty('permissions')
+                                       ->description('wcf.acp.pip.objectType.bulkProcessing.action.permissions.description')
+                                       ->packageIDs(array_merge(
+                                               [$this->installation->getPackage()->packageID],
+                                               array_keys($this->installation->getPackage()->getAllRequiredPackages())
+                                       ))
+                       ]);
+       }
+       
        /**
         * Adds all condition specific fields to the given form container.
         * 
@@ -778,7 +792,7 @@ XML;
         * @param       bool                    $addConditionGroup
         * @since       3.2
         */
-       protected function addConditionFields(IFormContainer $dataContainer, bool $addConditionObject = true, bool $addConditionGroup = true) {
+       public function addConditionFields(IFormContainer $dataContainer, bool $addConditionObject = true, bool $addConditionGroup = true) {
                $prefix = preg_replace('~Fields$~', '', $dataContainer->getId());
                
                if ($addConditionObject) {
@@ -843,27 +857,6 @@ XML;
                /** @var TextFormField $className */
                $className = $dataContainer->getDocument()->getNodeById('className');
                
-               $dataContainer->appendChildren([
-                       IntegerFormField::create($prefix . 'IntegerMinValue')
-                               ->objectProperty('minvalue')
-                               ->label('wcf.acp.pip.objectType.condition.integer.minValue')
-                               ->description('wcf.acp.pip.objectType.condition.integer.minValue.description')
-                               ->addDependency(
-                                       ValueFormFieldDependency::create('className')
-                                               ->field($className)
-                                               ->values($integerConditions)
-                               ),
-                       IntegerFormField::create($prefix . 'IntegerMaxValue')
-                               ->objectProperty('maxvalue')
-                               ->label('wcf.acp.pip.objectType.condition.integer.maxValue')
-                               ->description('wcf.acp.pip.objectType.condition.integer.maxValue.description')
-                               ->addDependency(
-                                       ValueFormFieldDependency::create('className')
-                                               ->field($className)
-                                               ->values($integerConditions)
-                               )
-               ]);
-               
                // `UserGroupCondition`
                $dataContainer->appendChild(
                        BooleanFormField::create($prefix . 'UserGroupIncludeGuests')
@@ -879,58 +872,93 @@ XML;
                
                // `UserIntegerPropertyCondition`
                $dataContainer->appendChild(
-                       TextFormField::create($prefix . 'UserIntegerPropertyName')
-                               ->objectProperty('propertyname')
-                               ->label('wcf.acp.pip.objectType.condition.userIntegerProperty.propertyName')
-                               ->description('wcf.acp.pip.objectType.condition.userIntegerProperty.propertyName.description')
-                               ->addDependency(
-                                       ValueFormFieldDependency::create('className')
-                                               ->field($className)
-                                               ->values([UserIntegerPropertyCondition::class])
-                               )
-                               ->addValidator(new FormFieldValidator('userTableIntegerColumn', function(TextFormField $formField) {
-                                       $columns = WCF::getDB()->getEditor()->getColumns('wcf' . WCF_N . '_user');
-                                       
-                                       foreach ($columns as $column) {
-                                               if ($column['name'] === $formField->getValue()) {
-                                                       if ($column['data']['type'] !== 'int') {
-                                                               $formField->addValidationError(new FormFieldValidationError(
-                                                                       'noIntegerColumn',
-                                                                       'wcf.acp.pip.objectType.condition.userIntegerProperty.propertyName.error.noIntegerColumn'
-                                                               ));
-                                                       }
-                                                       
-                                                       return;
-                                               }
-                                       }
-                                       
-                                       $formField->addValidationError(new FormFieldValidationError(
-                                               'nonExistent',
-                                               'wcf.acp.pip.objectType.condition.userIntegerProperty.propertyName.error.nonExistent'
-                                       ));
-                               }))
+                       $this->getIntegerConditionPropertyNameField(
+                               $className,
+                               UserIntegerPropertyCondition::class,
+                               $prefix . 'UserIntegerPropertyName',
+                               'wcf.acp.pip.objectType.condition.userIntegerProperty',
+                               'wcf' . WCF_N . '_user'
+                       )->required()
                );
                
                // `UserTimestampPropertyCondition`
                $dataContainer->appendChild(
-                       TextFormField::create($prefix . 'UserTimestampPropertyName')
-                               ->objectProperty('propertyname')
-                               ->label('wcf.acp.pip.objectType.condition.userTimestampProperty.propertyName')
-                               ->description('wcf.acp.pip.objectType.condition.userTimestampProperty.propertyName.description')
+                       $this->getIntegerConditionPropertyNameField(
+                               $className,
+                               UserTimestampPropertyCondition::class,
+                               $prefix . 'UserTimestampPropertyName',
+                               'wcf.acp.pip.objectType.condition.userIntegerProperty',
+                               'wcf' . WCF_N . '_user'
+                       )->required()
+               );
+               
+               $parameters = [
+                       'dataContainer' => $dataContainer,
+                       'prefix' => $prefix
+               ];
+               EventHandler::getInstance()->fireAction($this, 'addConditionFields', $parameters);
+               
+               // integer property fields should be shown last
+               $dataContainer->appendChildren([
+                       IntegerFormField::create($prefix . 'IntegerMinValue')
+                               ->objectProperty('minvalue')
+                               ->label('wcf.acp.pip.objectType.condition.integer.minValue')
+                               ->description('wcf.acp.pip.objectType.condition.integer.minValue.description')
+                               ->addDependency(
+                                       ValueFormFieldDependency::create('className')
+                                               ->field($className)
+                                               ->values($integerConditions)
+                               ),
+                       IntegerFormField::create($prefix . 'IntegerMaxValue')
+                               ->objectProperty('maxvalue')
+                               ->label('wcf.acp.pip.objectType.condition.integer.maxValue')
+                               ->description('wcf.acp.pip.objectType.condition.integer.maxValue.description')
                                ->addDependency(
                                        ValueFormFieldDependency::create('className')
                                                ->field($className)
-                                               ->values([UserTimestampPropertyCondition::class])
+                                               ->values($integerConditions)
                                )
-                               ->addValidator(new FormFieldValidator('userTableIntegerColumn', function(TextFormField $formField) {
-                                       $columns = WCF::getDB()->getEditor()->getColumns('wcf' . WCF_N . '_user');
+               ]);
+       }
+       
+       /**
+        * Returns a form field to enter the name of an integer property for an
+        * integer condition.
+        * 
+        * TODO: Can be use generic language items instead?
+        * The following language items must exist:
+        *      - `{$languageItemPrefix}.propertyName`,
+        *      - `{$languageItemPrefix}.propertyName.description`,
+        *      - `{$languageItemPrefix}.propertyName.error.noIntegerColumn`,
+        *      - `{$languageItemPrefix}.propertyName.error.nonExistent`.
+        * 
+        * @param       TextFormField   $classNameField         class name field on which the visibility of the created field depends
+        * @param       string          $conditionClass         name of the PHP class the field is created for
+        * @param       string          $id                     id of the created field
+        * @param       string          $languageItemPrefix     language item prefix used for label, description, and error language items
+        * @param       string          $databaseTableName      name of the database table that stores the conditioned objects
+        * @return      TextFormField
+        */
+       public function getIntegerConditionPropertyNameField(TextFormField $classNameField, string $conditionClass, string $id, string $languageItemPrefix, string $databaseTableName): TextFormField {
+               return TextFormField::create($id)
+                       ->objectProperty('propertyname')
+                       ->label($languageItemPrefix . '.propertyName')
+                       ->description($languageItemPrefix . '.propertyName.description')
+                       ->addDependency(
+                               ValueFormFieldDependency::create('className')
+                                       ->field($classNameField)
+                                       ->values([$conditionClass])
+                       )
+                       ->addValidator(new FormFieldValidator('userTableIntegerColumn', function(TextFormField $formField) use ($databaseTableName, $languageItemPrefix) {
+                               if ($formField->getSaveValue()) {
+                                       $columns = WCF::getDB()->getEditor()->getColumns($databaseTableName);
                                        
                                        foreach ($columns as $column) {
                                                if ($column['name'] === $formField->getValue()) {
                                                        if ($column['data']['type'] !== 'int') {
                                                                $formField->addValidationError(new FormFieldValidationError(
                                                                        'noIntegerColumn',
-                                                                       'wcf.acp.pip.objectType.condition.userTimestampProperty.propertyName.error.noIntegerColumn'
+                                                                       $languageItemPrefix . '.propertyName.error.noIntegerColumn'
                                                                ));
                                                        }
                                                        
@@ -940,13 +968,10 @@ XML;
                                        
                                        $formField->addValidationError(new FormFieldValidationError(
                                                'nonExistent',
-                                               'wcf.acp.pip.objectType.condition.userTimestampProperty.propertyName.error.nonExistent'
+                                               $languageItemPrefix . '.propertyName.error.nonExistent'
                                        ));
-                               }))
-               );
-               
-               $parameters = ['dataContainer' => $dataContainer];
-               EventHandler::getInstance()->fireAction($this, 'addConditionFields', $parameters);
+                               }
+                       }));
        }
        
        /**
index 1d9569d2e44ca4434dd8edfe83240cf6f049b0b6..8948fdb78515a53a8713f20571b438e0dd3c960c 100644 (file)
@@ -1698,11 +1698,11 @@ When prompted for the notification URL for the instant payment notifications, pl
                <item name="wcf.acp.pip.objectType.com.woltlab.wcf.attachment.objectType.private"><![CDATA[Attachments are Private]]></item>
                <item name="wcf.acp.pip.objectType.com.woltlab.wcf.attachment.objectType.private.description"><![CDATA[Private attachments are ignored by the attachment management in the ACP.]]></item>
                <item name="wcf.acp.pip.objectType.com.woltlab.wcf.bulkProcessing.user.action.data.title"><![CDATA[User Bulk Processing Action Data]]></item>
-               <item name="wcf.acp.pip.objectType.com.woltlab.wcf.bulkProcessing.user.action.action"><![CDATA[Action]]></item>
-               <item name="wcf.acp.pip.objectType.com.woltlab.wcf.bulkProcessing.user.action.action.description"><![CDATA[Unique textual identifier of the user bulk processing action that may only contain letters and must start with a lowercase letter.]]></item>
-               <item name="wcf.acp.pip.objectType.com.woltlab.wcf.bulkProcessing.user.action.action.error.format"><![CDATA[The entered action is invalid.]]></item>
-               <item name="wcf.acp.pip.objectType.com.woltlab.wcf.bulkProcessing.user.action.options.description"><![CDATA[At least one of the entered options has to be enabled for the user bulk processing action to be available. Options of non-required packages will be reported as non-existing.]]></item>
-               <item name="wcf.acp.pip.objectType.com.woltlab.wcf.bulkProcessing.user.action.permissions.description"><![CDATA[The active user must be granted at least one of the entered permissions in order to execute the action. Permissions of non-required packages will be reported as non-existing.]]></item>
+               <item name="wcf.acp.pip.objectType.bulkProcessing.action"><![CDATA[Action]]></item>
+               <item name="wcf.acp.pip.objectType.bulkProcessing.action.description"><![CDATA[Unique textual identifier of the bulk processing action that may only contain letters and must start with a lowercase letter.]]></item>
+               <item name="wcf.acp.pip.objectType.bulkProcessing.action.error.format"><![CDATA[The entered action is invalid.]]></item>
+               <item name="wcf.acp.pip.objectType.bulkProcessing.action.options.description"><![CDATA[At least one of the entered options has to be enabled for the bulk processing action to be available. Options of non-required packages will be reported as non-existing.]]></item>
+               <item name="wcf.acp.pip.objectType.bulkProcessing.action.permissions.description"><![CDATA[The active user must be granted at least one of the entered permissions in order to execute the action. Permissions of non-required packages will be reported as non-existing.]]></item>
                <item name="wcf.acp.pip.objectType.com.woltlab.wcf.bulkProcessing.user.condition.data.title"><![CDATA[User Bulk Processing Condition Data]]></item>
                <item name="wcf.acp.pip.objectType.com.woltlab.wcf.category.data.title"><![CDATA[Category Type Data]]></item>
                <item name="wcf.acp.pip.objectType.com.woltlab.wcf.category.defaultPermission"><![CDATA[Category Default Permission]]></item>
@@ -1771,10 +1771,6 @@ When prompted for the notification URL for the instant payment notifications, pl
                <item name="wcf.acp.pip.objectType.condition.userIntegerProperty.propertyName.description"><![CDATA[Name of the user property/user database table column used for the condition.]]></item>
                <item name="wcf.acp.pip.objectType.condition.userIntegerProperty.propertyName.error.noIntegerColumn"><![CDATA[The entered column name of the <code>wcf{WCF_N}_user</code> database table is no <code>INT</code> column.]]></item>
                <item name="wcf.acp.pip.objectType.condition.userIntegerProperty.propertyName.error.nonExistent"><![CDATA[The entered column does not exist in the <code>wcf{WCF_N}_user</code> database table.]]></item>
-               <item name="wcf.acp.pip.objectType.condition.userTimestampProperty.propertyName"><![CDATA[User Property Name]]></item>
-               <item name="wcf.acp.pip.objectType.condition.userTimestampProperty.propertyName.description"><![CDATA[Name of the user property/user database table column used for the condition.]]></item>
-               <item name="wcf.acp.pip.objectType.condition.userTimestampProperty.propertyName.error.noIntegerColumn"><![CDATA[The entered column name of the <code>wcf{WCF_N}_user</code> database table is no <code>INT</code> column.]]></item>
-               <item name="wcf.acp.pip.objectType.condition.userTimestampProperty.propertyName.error.nonExistent"><![CDATA[The entered column does not exist in the <code>wcf{WCF_N}_user</code> database table.]]></item>
                <item name="wcf.acp.pip.objectType.definitionName"><![CDATA[Object Type Definition]]></item>
                <item name="wcf.acp.pip.objectType.definitionName.com.woltlab.wcf.acl.description"><![CDATA[This object type definition is used to register types of objects for which ACL is available. ACL (Access control list) is used to set up (multiple) user and user group permissions for a specific object.]]></item>
                <item name="wcf.acp.pip.objectType.definitionName.com.woltlab.wcf.acl.simple.description"><![CDATA[This object type definition is used to register types of objects for which simple ACL is available. Simple ACL (Access control list) is used to set up <strong>one</strong> yes/no permission user and user group permissions for a specific object.]]></item>