text: <?php
  namespace wcf\acp\form;
  use wcf\data\language\category\LanguageCategoryList;
  use wcf\data\language\item\LanguageItemAction;
  use wcf\data\language\item\LanguageItemList;
  use wcf\form\AbstractFormBuilderForm;
  use wcf\system\form\builder\container\FormContainer;
  use wcf\system\form\builder\data\processor\CustomFormDataProcessor;
  use wcf\system\form\builder\data\processor\VoidFormDataProcessor;
  use wcf\system\form\builder\field\dependency\ValueFormFieldDependency;
  use wcf\system\form\builder\field\MultilineTextFormField;
  use wcf\system\form\builder\field\RadioButtonFormField;
  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;
  
  /**
   * Shows the form to create a new language item.
   * 
   * @author	Matthias Schmidt
   * @copyright	2001-2019 WoltLab GmbH
   * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
   * @package	WoltLabSuite\Core\Acp\Form
   * @since	5.2
   */
  class LanguageItemAddForm extends AbstractFormBuilderForm {
  	/**
  	 * @inheritDoc
  	 */
  	public $formAction = 'create';
  	
  	/**
  	 * @inheritDoc
  	 */
  	public $objectActionClass = LanguageItemAction::class;
  	
  	/**
  	 * @inheritDoc
  	 */
  	public $activeMenuItem = 'wcf.acp.menu.link.language.item.add';
  	
  	/**
  	 * @inheritDoc
  	 */
  	public $neededPermissions = ['admin.language.canManageLanguage'];
  	
  	/**
  	 * @inheritDoc
  	 */
  	public $objectActionName = 'createLanguageItems';
  	
  	/**
  	 * @inheritDoc
  	 */
  	protected function createForm() {
  		parent::createForm();
  		
  		$dataContainer = FormContainer::create('data')
  			->label('wcf.global.form.data')
  			->appendChildren([
  				RadioButtonFormField::create('languageCategoryIDMode')
  					->label('wcf.acp.language.item.languageCategoryID.mode')
  					->options([
  						'automatic' => 'wcf.acp.language.item.languageCategoryID.mode.automatic',
  						'selection' => 'wcf.acp.language.item.languageCategoryID.mode.selection'
  					])
  					->value('automatic'),
  				
  				SingleSelectionFormField::create('languageCategoryID')
  					->label('wcf.acp.language.item.languageCategoryID')
  					->description('wcf.acp.language.item.languageCategoryID.description')
  					->options(function() {
  						$list = new LanguageCategoryList();
  						$list->sqlOrderBy = 'languageCategory ASC';
  						
  						return $list;
  					}, false, false)
  					->required()
  					->filterable(),
  				
  				TextFormField::create('languageItem')
  					->label('wcf.acp.language.item.languageItem')
  					->description('wcf.acp.language.item.languageItem.description')
  					->required()
  					->maximumLength(191)
  					->addValidator(new FormFieldValidator('format', function(TextFormField $formField) {
  						if (!preg_match('~^[A-z0-9-_]+(\.[A-z0-9-_]+){2,}$~', $formField->getSaveValue(), $m)) {
  							$formField->addValidationError(
  								new FormFieldValidationError(
  									'format',
  									'wcf.acp.language.item.languageItem.error.format'
  								)
  							);
  						}
  					}))
  					->addValidator(new FormFieldValidator('languageCategory', function(TextFormField $formField) {
  						/** @var RadioButtonFormField $languageCategoryIDMode */
  						$languageCategoryIDMode = $formField->getDocument()->getNodeById('languageCategoryIDMode');
  						
  						switch ($languageCategoryIDMode->getSaveValue()) {
  							case 'automatic':
  								$languageItemPieces = explode('.', $formField->getSaveValue());
  								
  								$category = LanguageFactory::getInstance()->getCategory(
  									$languageItemPieces[0] . '.' . $languageItemPieces[1] . '.' . $languageItemPieces[2]
  								);
  								if ($category === null) {
  									$category = LanguageFactory::getInstance()->getCategory(
  										$languageItemPieces[0] . '.' . $languageItemPieces[1]
  									);
  								}
  								
  								if ($category === null) {
  									$languageCategoryIDMode->addValidationError(
  										new FormFieldValidationError(
  											'automatic',
  											'wcf.acp.language.item.languageCategoryID.mode.error.automaticImpossible'
  										)
  									);
  								}
  								
  								break;
  								
  							case 'selection':
  								/** @var SingleSelectionFormField $languageCategoryID */
  								$languageCategoryID = $formField->getDocument()->getNodeById('languageCategoryID');
  								
  								if ($languageCategory = LanguageFactory::getInstance()->getCategoryByID($languageCategoryID->getSaveValue())) {
  									if (strpos($formField->getSaveValue(), $languageCategory->languageCategory . '.') !== 0) {
  										$formField->addValidationError(
  											new FormFieldValidationError(
  												'prefixMismatch',
  												'wcf.acp.language.item.languageItem.error.prefixMismatch'
  											)
  										);
  									}
  								}
  								
  								break;
  						}
  					}))
  					->addValidator(new FormFieldValidator('uniqueness', function(TextFormField $formField) {
  						$languageItemList = new LanguageItemList();
  						$languageItemList->getConditionBuilder()->add('languageItem = ?', [$formField->getSaveValue()]);
  						
  						if ($languageItemList->countObjects() > 0) {
  							$formField->addValidationError(
  								new FormFieldValidationError(
  									'notUnique',
  									'wcf.acp.language.item.languageItem.error.notUnique'
  								)
  							);
  						}
  					})),
  				
  				MultilineTextFormField::create('languageItemValue')
  					->label('wcf.acp.language.item.value')
  					->required()
  					->i18n()
  					->i18nRequired()
  			]);
  		
  		$this->form->appendChild($dataContainer);
  		
  		// `languageCategoryIDMode` is an internal field not meant to be
  		// treated as real data
  		$this->form->getDataHandler()->addProcessor(new VoidFormDataProcessor('languageCategoryIDMode'));
  		
  		$this->form->getDataHandler()->addProcessor(
  			new CustomFormDataProcessor('languageItemOriginIsSystem', function(IFormDocument $document, array $parameters) {
  				$parameters['data']['languageItemOriginIsSystem'] = 0;
  				$parameters['data']['isCustomLanguageItem'] = 1;
  				
  				/** @var RadioButtonFormField $languageCategoryIDMode */
  				$languageCategoryIDMode = $document->getNodeById('languageCategoryIDMode');
  				
  				// automatically determine language item
  				if ($languageCategoryIDMode->getSaveValue() === 'automatic') {
  					/** @var TextFormField $languageItemField */
  					$languageItemField = $document->getNodeById('languageItem');
  					$languageItemPieces = explode('.', $languageItemField->getSaveValue());
  					
  					$category = LanguageFactory::getInstance()->getCategory(
  						$languageItemPieces[0] . '.' . $languageItemPieces[1] . '.' . $languageItemPieces[2]
  					);
  					if ($category === null) {
  						$category = LanguageFactory::getInstance()->getCategory(
  							$languageItemPieces[0] . '.' . $languageItemPieces[1]
  						);
  					}
  					
  					if ($category === null) {
  						throw new \UnexpectedValueException("Cannot automatically determine language category for item '{$languageItemField->getSaveValue()}'.");
  					}
  					
  					$parameters['data']['languageCategoryID'] = $category->languageCategoryID;
  				}
  				
  				return $parameters;
  			})
  		);
  		
  		/** @var RadioButtonFormField $modeField */
  		$modeField = $dataContainer->getNodeById('languageCategoryIDMode');
  		
  		$dataContainer->getNodeById('languageCategoryID')->addDependency(
  			ValueFormFieldDependency::create('mode')
  				->field($modeField)
  				->values(['selection'])
  		);
  	}
  }
  