From e59c27a96ec17a85b4cbd287d9e66f6cdb33c014 Mon Sep 17 00:00:00 2001 From: mutec Date: Sun, 29 Jan 2023 13:36:08 +0100 Subject: [PATCH] Convert `Language*Form` to form builder see #5252 [Tim: Performed some final adjustments] --- .../files/acp/templates/languageAdd.tpl | 111 +------ .../lib/acp/form/LanguageAddForm.class.php | 311 ++++++++---------- .../lib/acp/form/LanguageEditForm.class.php | 104 ++---- .../data/language/LanguageAction.class.php | 28 +- wcfsetup/install/lang/de.xml | 1 + wcfsetup/install/lang/en.xml | 1 + 6 files changed, 180 insertions(+), 376 deletions(-) diff --git a/wcfsetup/install/files/acp/templates/languageAdd.tpl b/wcfsetup/install/files/acp/templates/languageAdd.tpl index 0ab57b2dfc..7ca72d82fc 100644 --- a/wcfsetup/install/files/acp/templates/languageAdd.tpl +++ b/wcfsetup/install/files/acp/templates/languageAdd.tpl @@ -14,115 +14,6 @@ -{include file='formNotice'} - -
-
- -
-
- - {if $errorField == 'languageName'} - - {if $errorType == 'empty'} - {lang}wcf.global.form.error.empty{/lang} - {else} - {lang}wcf.acp.language.add.languageName.error.{@$errorType}{/lang} - {/if} - - {/if} - {lang}wcf.acp.language.name.description{/lang} -
- - - -
-
- - {if $errorField == 'languageCode'} - - {if $errorType == 'empty'} - {lang}wcf.global.form.error.empty{/lang} - {else} - {lang}wcf.acp.language.add.languageCode.error.{@$errorType}{/lang} - {/if} - - {/if} - {lang}wcf.acp.language.code.description{/lang} -
- - - -
-
- - {if $errorField == 'countryCode'} - - {if $errorType == 'empty'} - {lang}wcf.global.form.error.empty{/lang} - {else} - {lang}wcf.acp.language.add.countryCode.error.{@$errorType}{/lang} - {/if} - - {/if} - {lang}wcf.acp.language.countryCode.description{/lang} -
- - - -
-
- - {if $errorField == 'locale'} - - {if $errorType == 'empty'} - {lang}wcf.global.form.error.empty{/lang} - {else} - {lang}wcf.acp.language.add.locale.error.{@$errorType}{/lang} - {/if} - - {/if} - {lang}wcf.acp.language.locale.description{/lang} -
- - - {if $action == 'add'} - -
-
- - {if $errorField == 'sourceLanguageID'} - - {if $errorType == 'empty'} - {lang}wcf.global.form.error.empty{/lang} - {else} - {lang}wcf.acp.language.add.source.error.{@$errorType}{/lang} - {/if} - - {/if} - {lang}wcf.acp.language.add.source.description{/lang} -
- - {/if} - - {event name='fields'} -
- - {event name='sections'} - -
- - {csrfToken} -
-
+{@$form->getHtml()} {include file='footer'} diff --git a/wcfsetup/install/files/lib/acp/form/LanguageAddForm.class.php b/wcfsetup/install/files/lib/acp/form/LanguageAddForm.class.php index 8a1378a52c..bf03b27e87 100644 --- a/wcfsetup/install/files/lib/acp/form/LanguageAddForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/LanguageAddForm.class.php @@ -3,82 +3,54 @@ namespace wcf\acp\form; use wcf\data\language\Language; -use wcf\data\language\LanguageEditor; -use wcf\form\AbstractForm; -use wcf\system\exception\UserInputException; +use wcf\data\language\LanguageAction; +use wcf\form\AbstractFormBuilderForm; +use wcf\system\form\builder\container\FormContainer; +use wcf\system\form\builder\data\processor\CustomFormDataProcessor; +use wcf\system\form\builder\field\SingleSelectionFormField; +use wcf\system\form\builder\field\TextFormField; +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\language\LanguageFactory; -use wcf\system\request\LinkHandler; use wcf\system\WCF; -use wcf\util\StringUtil; /** * Shows the language add form. * - * @author Marcel Werk - * @copyright 2001-2019 WoltLab GmbH + * @property LanguageAction $objectAction + * + * @author Florian Gail, Marcel Werk + * @copyright 2001-2023 WoltLab GmbH * @license GNU Lesser General Public License */ -class LanguageAddForm extends AbstractForm +class LanguageAddForm extends AbstractFormBuilderForm { /** * @inheritDoc */ public $activeMenuItem = 'wcf.acp.menu.link.language.list'; - /** - * country code - * @var string - */ - public $countryCode = ''; - /** * @inheritDoc */ public $neededPermissions = ['admin.language.canManageLanguage']; /** - * language object - * @var Language - */ - public $language; - - /** - * language name - * @var string - */ - public $languageName = ''; - - /** - * language code - * @var string - */ - public $languageCode = ''; - - /** - * list of available languages - * @var Language[] - */ - public $languages = []; - - /** - * source language object - * @var Language + * @inheritDoc */ - public $sourceLanguage; + public $objectActionClass = LanguageAction::class; /** - * source language id - * @var int + * @inheritDoc */ - public $sourceLanguageID = 0; + public $objectEditLinkController = LanguageEditForm::class; /** * @var string[] */ public array $locales; - public string $locale = ''; - /** * @inheritDoc */ @@ -103,149 +75,124 @@ class LanguageAddForm extends AbstractForm /** * @inheritDoc */ - public function readFormParameters() + protected function createForm() { - parent::readFormParameters(); - - if (isset($_POST['countryCode'])) { - $this->countryCode = StringUtil::trim($_POST['countryCode']); - } - if (isset($_POST['languageName'])) { - $this->languageName = StringUtil::trim($_POST['languageName']); - } - if (isset($_POST['languageCode'])) { - $this->languageCode = StringUtil::trim($_POST['languageCode']); - } - if (isset($_POST['sourceLanguageID'])) { - $this->sourceLanguageID = \intval($_POST['sourceLanguageID']); - } - if (isset($_POST['locale'])) { - $this->locale = $_POST['locale']; - } - } - - /** - * @inheritDoc - */ - public function validate() - { - parent::validate(); - - // language name - if (empty($this->languageName)) { - throw new UserInputException('languageName'); - } - - // country code - if (empty($this->countryCode)) { - throw new UserInputException('countryCode'); - } - - // language code - $this->validateLanguageCode(); - - // source language id - $this->validateSource(); - - if (!isset($this->locales[$this->locale])) { - throw new UserInputException('locale'); - } - } - - /** - * Validates the language code. - */ - protected function validateLanguageCode() - { - if (empty($this->languageCode)) { - throw new UserInputException('languageCode'); - } - if (LanguageFactory::getInstance()->getLanguageByCode($this->languageCode)) { - throw new UserInputException('languageCode', 'notUnique'); - } - } - - /** - * Validates given source language. - */ - protected function validateSource() - { - if (empty($this->sourceLanguageID)) { - throw new UserInputException('sourceLanguageID'); - } - - // get language - $this->sourceLanguage = LanguageFactory::getInstance()->getLanguage($this->sourceLanguageID); - if (!$this->sourceLanguage->languageID) { - throw new UserInputException('sourceLanguageID'); - } - } - - /** - * @inheritDoc - */ - public function save() - { - parent::save(); - - $this->language = LanguageEditor::create(\array_merge($this->additionalFields, [ - 'countryCode' => \mb_strtolower($this->countryCode), - 'languageName' => $this->languageName, - 'languageCode' => \mb_strtolower($this->languageCode), - 'locale' => $this->locale, - ])); - $languageEditor = new LanguageEditor($this->sourceLanguage); - $languageEditor->copy($this->language); - - // copy content - LanguageEditor::copyLanguageContent($this->sourceLanguage->languageID, $this->language->languageID); - - // reset caches - LanguageFactory::getInstance()->clearCache(); - LanguageFactory::getInstance()->deleteLanguageCache(); - - $this->saved(); - - // show success message - WCF::getTPL()->assign([ - 'success' => true, - 'objectEditLink' => LinkHandler::getInstance()->getControllerLink( - LanguageEditForm::class, - ['id' => $this->language->languageID] - ), + parent::createForm(); + + $locales = [ + '' => WCF::getLanguage()->get('wcf.global.noSelection'), + ...$this->locales, + ]; + + $this->form->appendChildren([ + FormContainer::create('data') + ->appendChildren([ + TextFormField::create('languageName') + ->label('wcf.global.name') + ->description('wcf.acp.language.name.description') + ->maximumLength(255) + ->required(), + TextFormField::create('languageCode') + ->label('wcf.acp.language.code') + ->description('wcf.acp.language.code.description') + ->maximumLength(20) + ->required() + ->addValidator(new FormFieldValidator('unique', function (TextFormField $formField) { + if ($formField->getValidationErrors() !== []) { + return; + } + + if ( + $this->formObject instanceof Language + && \mb_strtolower($this->formObject->languageCode) === $formField->getValue() + ) { + return; + } + + if (LanguageFactory::getInstance()->getLanguageByCode($formField->getValue())) { + $formField->addValidationError(new FormFieldValidationError( + 'notUnique', + 'wcf.acp.language.add.languageCode.error.notUnique' + )); + } + })), + TextFormField::create('countryCode') + ->label('wcf.acp.language.countryCode') + ->description('wcf.acp.language.countryCode.description') + ->maximumLength(10) + ->required(), + SingleSelectionFormField::create('locale') + ->label('wcf.acp.language.locale') + ->description('wcf.acp.language.locale.description') + ->options($locales) + ->addValidator(new FormFieldValidator( + 'locale', + static function (SingleSelectionFormField $formField) { + if ($formField->getValue() === '') { + return; + } + + if ($formField->getValidationErrors() !== []) { + return; + } + + $languageCodeField = $formField->getDocument()->getNodeById('languageCode'); + \assert($languageCodeField instanceof TextFormField); + + [$languageCode] = \explode('_', $formField->getValue()); + if ($languageCodeField->getValue() !== $languageCode) { + $formField->addValidationError( + new FormFieldValidationError( + 'languageCodeMismatch', + 'wcf.acp.language.add.locale.error.languageCodeMismatch', + [ + 'locale' => $formField->getValue(), + ] + ) + ); + } + } + )), + SingleSelectionFormField::create('sourceLanguageID') + ->label('wcf.acp.language.add.source') + ->description('wcf.acp.language.add.source.description') + ->options(LanguageFactory::getInstance()->getLanguages()) + ->available($this->formAction === IFormDocument::FORM_MODE_CREATE) + ->required(), + ]), ]); - - // reset values - $this->countryCode = $this->languageCode = $this->languageName = $this->locale = ''; - $this->sourceLanguageID = 0; } /** * @inheritDoc */ - public function readData() + public function buildForm() { - parent::readData(); - - $this->languages = LanguageFactory::getInstance()->getLanguages(); - } - - /** - * @inheritDoc - */ - public function assignVariables() - { - parent::assignVariables(); - - WCF::getTPL()->assign([ - 'countryCode' => $this->countryCode, - 'languageName' => $this->languageName, - 'languageCode' => $this->languageCode, - 'sourceLanguageID' => $this->sourceLanguageID, - 'languages' => $this->languages, - 'locale' => $this->locale, - 'locales' => $this->locales, - 'action' => 'add', - ]); + parent::buildForm(); + + $this->form->getDataHandler()->addProcessor(new CustomFormDataProcessor( + 'lowercase', + static function (IFormDocument $document, array $parameters) { + $parameters['data']['languageCode'] = \mb_strtolower($parameters['data']['languageCode']); + $parameters['data']['countryCode'] = \mb_strtolower($parameters['data']['countryCode']); + + return $parameters; + } + )); + $this->form->getDataHandler()->addProcessor(new CustomFormDataProcessor( + 'sourceLanguage', + function (IFormDocument $document, array $parameters) { + if ($this->formAction !== IFormDocument::FORM_MODE_CREATE) { + return $parameters; + } + + if (isset($parameters['data']['sourceLanguageID'])) { + $parameters['sourceLanguageID'] = $parameters['data']['sourceLanguageID']; + unset($parameters['data']['sourceLanguageID']); + } + + return $parameters; + } + )); } } diff --git a/wcfsetup/install/files/lib/acp/form/LanguageEditForm.class.php b/wcfsetup/install/files/lib/acp/form/LanguageEditForm.class.php index 71a3137c48..fc2ee83fcf 100644 --- a/wcfsetup/install/files/lib/acp/form/LanguageEditForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/LanguageEditForm.class.php @@ -2,27 +2,26 @@ namespace wcf\acp\form; +use CuyZ\Valinor\Mapper\MappingError; use wcf\data\language\Language; -use wcf\data\language\LanguageEditor; -use wcf\form\AbstractForm; +use wcf\http\Helper; use wcf\system\exception\IllegalLinkException; -use wcf\system\language\LanguageFactory; -use wcf\system\WCF; /** * Shows the language edit form. * - * @author Marcel Werk - * @copyright 2001-2019 WoltLab GmbH + * @property Language $formObject + * + * @author Florian Gail + * @copyright 2001-2023 WoltLab GmbH * @license GNU Lesser General Public License */ class LanguageEditForm extends LanguageAddForm { /** - * language id - * @var int + * @inheritDoc */ - public $languageID = 0; + public $formAction = 'edit'; /** * @inheritDoc @@ -31,79 +30,22 @@ class LanguageEditForm extends LanguageAddForm { parent::readParameters(); - if (isset($_REQUEST['id'])) { - $this->languageID = \intval($_REQUEST['id']); - } - $this->language = new Language($this->languageID); - if (!$this->language->languageID) { + try { + $queryParameters = Helper::mapQueryParameters( + $_GET, + <<<'EOT' + array { + id: positive-int + } + EOT + ); + $this->formObject = new Language($queryParameters['id']); + + if (!$this->formObject->getObjectID()) { + throw new IllegalLinkException(); + } + } catch (MappingError) { throw new IllegalLinkException(); } } - - /** - * @inheritDoc - */ - protected function validateLanguageCode() - { - if ($this->language->languageCode != \mb_strtolower($this->languageCode)) { - parent::validateLanguageCode(); - } - } - - /** - * @inheritDoc - */ - protected function validateSource() - { - } - - /** - * @inheritDoc - */ - public function save() - { - AbstractForm::save(); - - $editor = new LanguageEditor($this->language); - $editor->update(\array_merge($this->additionalFields, [ - 'countryCode' => \mb_strtolower($this->countryCode), - 'languageName' => $this->languageName, - 'languageCode' => \mb_strtolower($this->languageCode), - 'locale' => $this->locale, - ])); - LanguageFactory::getInstance()->clearCache(); - $this->saved(); - - // show success message - WCF::getTPL()->assign('success', true); - } - - /** - * @inheritDoc - */ - public function readData() - { - parent::readData(); - - if (!\count($_POST)) { - $this->countryCode = $this->language->countryCode; - $this->languageName = $this->language->languageName; - $this->languageCode = $this->language->languageCode; - $this->locale = $this->language->locale; - } - } - - /** - * @inheritDoc - */ - public function assignVariables() - { - parent::assignVariables(); - - WCF::getTPL()->assign([ - 'languageID' => $this->languageID, - 'language' => $this->language, - 'action' => 'edit', - ]); - } } diff --git a/wcfsetup/install/files/lib/data/language/LanguageAction.class.php b/wcfsetup/install/files/lib/data/language/LanguageAction.class.php index 38ab1ee494..ee70f510f4 100644 --- a/wcfsetup/install/files/lib/data/language/LanguageAction.class.php +++ b/wcfsetup/install/files/lib/data/language/LanguageAction.class.php @@ -6,16 +6,16 @@ use wcf\data\AbstractDatabaseObjectAction; use wcf\data\IToggleAction; use wcf\data\TDatabaseObjectToggle; use wcf\system\exception\UserInputException; +use wcf\system\language\LanguageFactory; use wcf\system\WCF; /** * Executes language-related actions. * - * @author Alexander Ebert - * @copyright 2001-2019 WoltLab GmbH + * @author Alexander Ebert, Florian Gail + * @copyright 2001-2023 WoltLab GmbH * @license GNU Lesser General Public License * - * @method Language create() * @method LanguageEditor[] getObjects() * @method LanguageEditor getSingleObject() */ @@ -54,6 +54,28 @@ class LanguageAction extends AbstractDatabaseObjectAction implements IToggleActi */ protected $requireACP = ['create', 'delete', 'setAsDefault', 'update']; + /** + * @inheritDoc + * @return Language + */ + public function create() + { + $object = parent::create(); + \assert($object instanceof Language); + + if (isset($this->parameters['sourceLanguageID']) && $this->parameters['sourceLanguageID']) { + $sourceLanguage = LanguageFactory::getInstance()->getLanguage($this->parameters['sourceLanguageID']); + + LanguageEditor::copyLanguageContent($sourceLanguage->getObjectID(), $object->getObjectID()); + (new LanguageEditor($sourceLanguage))->copy($object); + + LanguageFactory::getInstance()->clearCache(); + LanguageFactory::getInstance()->deleteLanguageCache(); + } + + return $object; + } + /** * Validates permission to set a language as default. */ diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index d27649e25e..f5549b2ae5 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -1012,6 +1012,7 @@ Sie erreichen das Fehlerprotokoll unter: {link controller='ExceptionLogView' isE + {$locale}) entspricht nicht dem angegebenen Sprachcode.]]> ISO 639-1 an. Weitere Informationen zu Sprachcodes {if LANGUAGE_USE_INFORMAL_VARIANT}findest du{else}finden Sie{/if} unter https://de.wikipedia.org/wiki/ISO_639-1.]]> diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index a62028cf96..c3f3ec932e 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -991,6 +991,7 @@ You can access the error log at: {link controller='ExceptionLogView' isEmail=tru + {$locale}) does not match the language code.]]> ISO 639-1 language code, you can look up the language code at https://en.wikipedia.org/wiki/ISO_639-1.]]> -- 2.20.1