Added AbstractAcpForm with integrated i18n support
authorAlexander Ebert <ebert@woltlab.com>
Fri, 16 Jun 2017 11:54:55 +0000 (13:54 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Fri, 16 Jun 2017 12:25:44 +0000 (14:25 +0200)
wcfsetup/install/files/lib/acp/form/AbstractAcpForm.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/form/AbstractForm.class.php
wcfsetup/install/files/lib/system/language/I18nValue.class.php [new file with mode: 0644]

diff --git a/wcfsetup/install/files/lib/acp/form/AbstractAcpForm.class.php b/wcfsetup/install/files/lib/acp/form/AbstractAcpForm.class.php
new file mode 100644 (file)
index 0000000..0d2387b
--- /dev/null
@@ -0,0 +1,205 @@
+<?php
+namespace wcf\acp\form;
+use wcf\data\DatabaseObject;
+use wcf\data\DatabaseObjectEditor;
+use wcf\form\AbstractForm;
+use wcf\system\exception\UserInputException;
+use wcf\system\language\I18nHandler;
+use wcf\system\language\I18nValue;
+use wcf\system\WCF;
+
+/**
+ * Default implementation for ACP forms with i18n support.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2017 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    WoltLabSuite\Core\Acp\Form
+ * @since       3.1
+ */
+abstract class AbstractAcpForm extends AbstractForm {
+       /**
+        * action type
+        * @var string
+        */
+       public $action = 'add';
+       
+       /**
+        * @var I18nValue[]
+        */
+       public $i18nValues = [];
+       
+       /**
+        * Registers a new i18n value.
+        * 
+        * @param       I18nValue       $value
+        */
+       public function registerI18nValue(I18nValue $value) {
+               $fieldName = $value->getFieldName();
+               
+               if (isset($this->i18nValues[$fieldName])) {
+                       throw new \InvalidArgumentException("Duplicate value definition for '{$fieldName}'.");
+               }
+               else if (!property_exists($this, $fieldName)) {
+                       throw new \UnexpectedValueException("Implementing class does not expose the property '{$fieldName}'.");
+               }
+               
+               $this->i18nValues[$fieldName] = $value;
+               
+               I18nHandler::getInstance()->register($fieldName);
+       }
+       
+       /**
+        * Retrieves an i18n value object.
+        * 
+        * @param       string          $fieldName
+        * @return      I18nValue|null
+        */
+       public function getI18nValue($fieldName) {
+               if (isset($this->i18nValues[$fieldName])) {
+                       return $this->i18nValues[$fieldName];
+               }
+               
+               return null;
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function readFormParameters() {
+               parent::readFormParameters();
+               
+               if (!empty($this->i18nValues)) {
+                       I18nHandler::getInstance()->readValues();
+                       
+                       foreach ($this->i18nValues as $fieldName => $value) {
+                               if (I18nHandler::getInstance()->isPlainValue($fieldName)) {
+                                       $this->{$fieldName} = I18nHandler::getInstance()->getValue($fieldName);
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function validate() {
+               parent::validate();
+               
+               foreach ($this->i18nValues as $fieldName => $value) {
+                       if (!I18nHandler::getInstance()->validateValue($fieldName, $value->getFlag(I18nValue::REQUIRE_I18N), $value->getFlag(I18nValue::ALLOW_EMPTY))) {
+                               throw new UserInputException(
+                                       $fieldName,
+                                       (I18nHandler::getInstance()->isPlainValue($fieldName)) ? 'empty' : 'multilingual'
+                               );
+                       }
+               }
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function readDataI18n(DatabaseObject $databaseObject) {
+               if (empty($_POST) && !empty($this->i18nValues)) {
+                       I18nHandler::getInstance()->readValues();
+                       
+                       foreach ($this->i18nValues as $fieldName => $value) {
+                               I18nHandler::getInstance()->setOptions(
+                                       $fieldName,
+                                       $value->getPackageID(),
+                                       $databaseObject->{$fieldName},
+                                       "{$value->getLanguageItem()}\d+"
+                               );
+                       }
+               }
+       }
+       
+       public function beforeSaveI18n(DatabaseObject $databaseObject) {
+               $values = [];
+               
+               foreach ($this->i18nValues as $fieldName => $value) {
+                       $this->{$fieldName} = $value->getLanguageItem() . $databaseObject->getObjectID();
+                       if (I18nHandler::getInstance()->isPlainValue($fieldName)) {
+                               I18nHandler::getInstance()->remove($fieldName);
+                               
+                               $values[$fieldName] = I18nHandler::getInstance()->getValue($fieldName);
+                               $this->{$fieldName} = $values[$fieldName];
+                       }
+                       else {
+                               I18nHandler::getInstance()->save(
+                                       $fieldName,
+                                       $this->{$fieldName},
+                                       $value->getLanguageCategory(),
+                                       $value->getPackageID()
+                               );
+                               
+                               $value[$fieldName] = I18nHandler::getInstance()->getValues($fieldName)[WCF::getLanguage()->languageID];
+                       }
+               }
+               
+               return $values;
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function saveI18n(DatabaseObject $databaseObject, $editorClass) {
+               $data = [];
+               
+               $objectID = $databaseObject->getObjectID();
+               foreach ($this->i18nValues as $fieldName => $value) {
+                       if (!I18nHandler::getInstance()->isPlainValue($fieldName)) {
+                               $languageItem = $value->getLanguageItem() . $objectID;
+                               I18nHandler::getInstance()->save(
+                                       $fieldName,
+                                       $languageItem,
+                                       $value->getLanguageCategory(),
+                                       $value->getPackageID()
+                               );
+                               
+                               $data[$fieldName] = $languageItem;
+                       }
+               }
+               
+               if (!empty($data)) {
+                       /** @var DatabaseObjectEditor $editor */
+                       $editor = new $editorClass($databaseObject);
+                       $editor->update($data);
+               }
+       }
+       
+       /**
+        * Resets the form values and calls the saved event.
+        */
+       public function reset() {
+               $this->saved();
+               
+               if (!empty($this->i18nValues)) {
+                       foreach ($this->i18nValues as $fieldName => $value) {
+                               $this->{$fieldName} = '';
+                       }
+                       
+                       I18nHandler::getInstance()->reset();
+               }
+               
+               // show success message
+               WCF::getTPL()->assign('success', true);
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               if (!empty($this->i18nValues)) {
+                       $useRequestData = ($this->action === 'add') ? true : !empty($_POST);
+                       
+                       I18nHandler::getInstance()->assignVariables($useRequestData);
+               }
+               
+               WCF::getTPL()->assign([
+                       'action' => $this->action
+               ]);
+       }
+}
index ecd63c9a5d36e65c1f4ab0db5742bfcc3b4d445f..1a9d5c2288605b8ac16fd1ecd48d80c3ffedd1e1 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 namespace wcf\form;
+use wcf\data\AbstractDatabaseObjectAction;
 use wcf\page\AbstractPage;
 use wcf\system\event\EventHandler;
 use wcf\system\exception\UserInputException;
@@ -36,9 +37,9 @@ abstract class AbstractForm extends AbstractPage implements IForm {
        
        /**
         * database object action
-        * @var \wcf\data\AbstractDatabaseObjectAction
+        * @var AbstractDatabaseObjectAction
         */
-       public $objectAction = null;
+       public $objectAction;
        
        /**
         * additional fields
diff --git a/wcfsetup/install/files/lib/system/language/I18nValue.class.php b/wcfsetup/install/files/lib/system/language/I18nValue.class.php
new file mode 100644 (file)
index 0000000..59f5e0b
--- /dev/null
@@ -0,0 +1,138 @@
+<?php
+namespace wcf\system\language;
+use wcf\data\package\PackageCache;
+
+/**
+ * Represents an i18n value for use with `AbstractAcpForm`.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2017 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    WoltLabSuite\Core\System\Language
+ * @since       3.1
+ */
+class I18nValue {
+       /**
+        * field name
+        * @var string
+        */
+       protected $fieldName = '';
+       
+       /**
+        * bit-mask to alter validation rules
+        * @var integer
+        */
+       protected $flags = 0;
+       
+       /**
+        * language item template, placeholder or id will be appended
+        * @var string
+        */
+       protected $languageItem = '';
+       
+       /**
+        * language item category
+        * @var string
+        */
+       protected $languageItemCategory = '';
+       
+       /**
+        * package name used for the `packageID` reference
+        * @var string
+        */
+       protected $languageItemPackage = '';
+       
+       /**
+        * allow an empty value, that includes providing no value at all
+        */
+       const ALLOW_EMPTY = 1;
+       
+       /**
+        * require localized values, disallowing plain values
+        */
+       const REQUIRE_I18N = 2;
+       
+       /**
+        * I18nValue constructor.
+        * 
+        * @param       string          $fieldName
+        */
+       public function __construct($fieldName) {
+               $this->fieldName = $fieldName;
+       }
+       
+       /**
+        * Sets the language item configuration.
+        * 
+        * @param       string          $item
+        * @param       string          $category
+        * @param       string          $package
+        */
+       public function setLanguageItem($item, $category, $package) {
+               $this->languageItem = $item;
+               $this->languageItemCategory = $category;
+               $this->languageItemPackage = $package;
+       }
+       
+       /**
+        * Sets bit flags.
+        * 
+        * @param       integer         $flags
+        */
+       public function setFlags($flags) {
+               $this->flags = $flags;
+       }
+       
+       /**
+        * Returns true if given flag is set.
+        * 
+        * @param       integer         $flag
+        * @return      boolean
+        */
+       public function getFlag($flag) {
+               return (($this->flags & $flag) === $flag);
+       }
+       
+       /**
+        * Returns the field identifier.
+        * 
+        * @return      string
+        */
+       public function getFieldName() {
+               return $this->fieldName;
+       }
+       
+       /**
+        * Returns the language item template.
+        * 
+        * @return      string
+        */
+       public function getLanguageItem() {
+               return $this->languageItem;
+       }
+       
+       /**
+        * Returns the language category.
+        * 
+        * @return      string
+        */
+       public function getLanguageCategory() {
+               return $this->languageItemCategory;
+       }
+       
+       /**
+        * Returns the package id.
+        * 
+        * @return      string
+        */
+       public function getPackageID() {
+               return PackageCache::getInstance()->getPackageID($this->languageItemPackage);
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function __toString() {
+               return $this->getFieldName();
+       }
+}