Use FormBuilder for menus
authorCyperghost <olaf_schmitz_1@t-online.de>
Tue, 19 Nov 2024 10:27:12 +0000 (11:27 +0100)
committerCyperghost <olaf_schmitz_1@t-online.de>
Tue, 19 Nov 2024 10:27:12 +0000 (11:27 +0100)
wcfsetup/install/files/acp/templates/menuAdd.tpl
wcfsetup/install/files/lib/acp/form/MenuAddForm.class.php
wcfsetup/install/files/lib/acp/form/MenuEditForm.class.php
wcfsetup/install/files/lib/data/menu/Menu.class.php
wcfsetup/install/files/lib/data/menu/MenuAction.class.php
wcfsetup/install/files/lib/system/form/builder/field/PagesFormField.class.php

index 600058f4192c5e70c256fc96d0efd901d85ce757..c64392465bccf1197b6f5733de5bed714b2568c4 100644 (file)
@@ -8,7 +8,7 @@
        <nav class="contentHeaderNavigation">
                <ul>
                        {if $action == 'edit'}
-                               <li><a href="{link controller='MenuItemList' id=$menuID}{/link}" class="button">{icon name='list'} <span>{lang}wcf.acp.menu.item.list{/lang}</span></a></li>
+                               <li><a href="{link controller='MenuItemList' id=$formObject->menuID}{/link}" class="button">{icon name='list'} <span>{lang}wcf.acp.menu.item.list{/lang}</span></a></li>
                        {/if}
                        <li><a href="{link controller='MenuList'}{/link}" class="button">{icon name='list'} <span>{lang}wcf.acp.menu.list{/lang}</span></a></li>
                        
        </nav>
 </header>
 
-{include file='shared_formNotice'}
-
-<form method="post" action="{if $action == 'add'}{link controller='MenuAdd'}{/link}{else}{link controller='MenuEdit' id=$menuID}{/link}{/if}">
-       {if $action == 'edit' && $menu->identifier == 'com.woltlab.wcf.MainMenu'}
-               {* editing the main menu *}
-               <div class="section">
-                       <dl{if $errorField == 'title'} class="formError"{/if}>
-                               <dt><label for="title">{lang}wcf.global.title{/lang}</label></dt>
-                               <dd>
-                                       <input type="text" id="title" name="title" value="{$i18nPlainValues['title']}" autofocus class="long">
-                                       {if $errorField == 'title'}
-                                               <small class="innerError">
-                                                       {if $errorType == 'empty' || $errorType == 'multilingual'}
-                                                               {lang}wcf.global.form.error.{@$errorType}{/lang}
-                                                       {else}
-                                                               {lang}wcf.acp.menu.title.error.{@$errorType}{/lang}
-                                                       {/if}
-                                               </small>
-                                       {/if}
-                                       {include file='shared_multipleLanguageInputJavascript' elementIdentifier='title' forceSelection=false}
-                               </dd>
-                       </dl>
-               </div>
-       {else}
-               {* anything, but the main menu *}
-               <div class="section tabMenuContainer" data-active="{$activeTabMenuItem}" data-store="activeTabMenuItem" id="pageTabMenuContainer">
-                       <nav class="tabMenu">
-                               <ul>
-                                       <li><a href="#general">{lang}wcf.global.form.data{/lang}</a></li>
-                                       <li><a href="#pages">{lang}wcf.acp.page.list{/lang}</a></li>
-                                       <li><a href="#acl">{lang}wcf.acl.access{/lang}</a></li>
-                                       
-                                       {event name='tabMenuTabs'}
-                               </ul>
-                       </nav>
-                       
-                       <div id="general" class="tabMenuContent">
-                               <div class="section">
-                                       <dl{if $errorField == 'title'} class="formError"{/if}>
-                                               <dt><label for="title">{lang}wcf.global.title{/lang}</label></dt>
-                                               <dd>
-                                                       <input type="text" id="title" name="title" value="{$i18nPlainValues['title']}" autofocus class="long">
-                                                       {if $errorField == 'title'}
-                                                               <small class="innerError">
-                                                                       {if $errorType == 'empty' || $errorType == 'multilingual'}
-                                                                               {lang}wcf.global.form.error.{@$errorType}{/lang}
-                                                                       {else}
-                                                                               {lang}wcf.acp.menu.title.error.{@$errorType}{/lang}
-                                                                       {/if}
-                                                               </small>
-                                                       {/if}
-                                                       {include file='shared_multipleLanguageInputJavascript' elementIdentifier='title' forceSelection=false}
-                                               </dd>
-                                       </dl>
-                                       
-                                       <dl{if $errorField == 'position'} class="formError"{/if}>
-                                               <dt><label for="position">{lang}wcf.acp.box.position{/lang}</label></dt>
-                                               <dd>
-                                                       <select name="position" id="position">
-                                                               {foreach from=$availablePositions item=availablePosition}
-                                                                       <option value="{$availablePosition}"{if $availablePosition == $position} selected{/if}>{lang}wcf.acp.box.position.{@$availablePosition}{/lang}</option>
-                                                               {/foreach}
-                                                       </select>
-                                                       
-                                                       {if $errorField == 'position'}
-                                                               <small class="innerError">
-                                                                       {if $errorType == 'empty'}
-                                                                               {lang}wcf.global.form.error.empty{/lang}
-                                                                       {else}
-                                                                               {lang}wcf.acp.box.position.error.{@$errorType}{/lang}
-                                                                       {/if}
-                                                               </small>
-                                                       {/if}
-                                               </dd>
-                                       </dl>
-                                       
-                                       <dl>
-                                               <dt><label for="showOrder">{lang}wcf.global.showOrder{/lang}</label></dt>
-                                               <dd>
-                                                       <input type="number" id="showOrder" name="showOrder" value="{$showOrder}" class="tiny" min="0">
-                                               </dd>
-                                       </dl>
-                                       
-                                       <dl{if $errorField == 'cssClassName'} class="formError"{/if}>
-                                               <dt><label for="cssClassName">{lang}wcf.acp.box.cssClassName{/lang}</label></dt>
-                                               <dd>
-                                                       <input type="text" id="cssClassName" name="cssClassName" value="{$cssClassName}" class="long">
-                                                       {if $errorField == 'cssClassName'}
-                                                               <small class="innerError">
-                                                                       {if $errorType == 'empty'}
-                                                                               {lang}wcf.global.form.error.empty{/lang}
-                                                                       {else}
-                                                                               {lang}wcf.acp.box.cssClassName.error.{@$errorType}{/lang}
-                                                                       {/if}
-                                                               </small>
-                                                       {/if}
-                                               </dd>
-                                       </dl>
-                                       
-                                       <dl>
-                                               <dt></dt>
-                                               <dd>
-                                                       <label><input type="checkbox" id="showHeader" name="showHeader" value="1"{if $showHeader} checked{/if}> {lang}wcf.acp.box.showHeader{/lang}</label>
-                                               </dd>
-                                       </dl>
-                               </div>
-                       </div>
-                       
-                       <div id="pages" class="tabMenuContent">
-                               <div class="section">
-                                       <dl>
-                                               <dt></dt>
-                                               <dd>
-                                                       <label><input type="checkbox" id="visibleEverywhere" name="visibleEverywhere" value="1"{if $visibleEverywhere} checked{/if}> {lang}wcf.acp.box.visibleEverywhere{/lang}</label>
-                                                       <script data-relocate="true">
-                                                               elById('visibleEverywhere').addEventListener('change', function() {
-                                                                       if (this.checked) {
-                                                                               elShow(elById('visibilityExceptionHidden'));
-                                                                               elHide(elById('visibilityExceptionVisible'));
-                                                                       }
-                                                                       else {
-                                                                               elHide(elById('visibilityExceptionHidden'));
-                                                                               elShow(elById('visibilityExceptionVisible'));
-                                                                       }
-                                                               });
-                                                       </script>
-                                               </dd>
-                                       </dl>
-                                       
-                                       <dl>
-                                               <dt>
-                                                       <span id="visibilityExceptionVisible"{if $visibleEverywhere} style="display: none"{/if}>{lang}wcf.acp.box.visibilityException.visible{/lang}</span>
-                                                       <span id="visibilityExceptionHidden"{if !$visibleEverywhere} style="display: none"{/if}>{lang}wcf.acp.box.visibilityException.hidden{/lang}</span>
-                                               </dt>
-                                               <dd>
-                                                       {include file='shared_scrollablePageCheckboxList' pageCheckboxListContainerID='menuVisibilitySettings' pageCheckboxID='pageIDs'}
-                                               </dd>
-                                       </dl>
-                                       
-                                       {event name='dataFields'}
-                               </div>
-                       </div>
-                       
-                       <div id="acl" class="tabMenuContent">
-                               {include file='shared_aclSimple'}
-                       </div>
-               </div>
-       {/if}
-       
-       {event name='sections'}
-       
-       <div class="formSubmit">
-               <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
-               {csrfToken}
-       </div>
-</form>
+{unsafe:$form->getHtml()}
 
 {include file='footer'}
index 51c369c0759ccb7b541a35d39553a59a6f6dc4b5..9f1eb123a276c670a915eecde2ad74f19636a38a 100644 (file)
@@ -3,29 +3,37 @@
 namespace wcf\acp\form;
 
 use wcf\data\box\Box;
+use wcf\data\box\BoxAction;
+use wcf\data\IStorableObject;
+use wcf\data\menu\Menu;
 use wcf\data\menu\MenuAction;
-use wcf\data\menu\MenuEditor;
-use wcf\data\page\PageNodeTree;
-use wcf\form\AbstractForm;
+use wcf\form\AbstractFormBuilderForm;
 use wcf\system\acl\simple\SimpleAclHandler;
-use wcf\system\database\util\PreparedStatementConditionBuilder;
-use wcf\system\exception\UserInputException;
-use wcf\system\language\I18nHandler;
+use wcf\system\form\builder\container\FormContainer;
+use wcf\system\form\builder\container\TabFormContainer;
+use wcf\system\form\builder\container\TabMenuFormContainer;
+use wcf\system\form\builder\data\processor\CustomFormDataProcessor;
+use wcf\system\form\builder\field\acl\simple\SimpleAclFormField;
+use wcf\system\form\builder\field\BooleanFormField;
+use wcf\system\form\builder\field\IntegerFormField;
+use wcf\system\form\builder\field\PagesFormField;
+use wcf\system\form\builder\field\SingleSelectionFormField;
+use wcf\system\form\builder\field\TextFormField;
+use wcf\system\form\builder\field\TitleFormField;
+use wcf\system\form\builder\IFormDocument;
 use wcf\system\language\LanguageFactory;
-use wcf\system\request\LinkHandler;
-use wcf\system\WCF;
-use wcf\util\ArrayUtil;
-use wcf\util\StringUtil;
 
 /**
  * Shows the menu add form.
  *
- * @author  Marcel Werk
- * @copyright   2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @since   3.0
+ * @author      Olaf Braun, Marcel Werk
+ * @copyright   2001-2024 WoltLab GmbH
+ * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since       3.0
+ *
+ * @property Menu $formObject
  */
-class MenuAddForm extends AbstractForm
+class MenuAddForm extends AbstractFormBuilderForm
 {
     /**
      * @inheritDoc
@@ -37,247 +45,192 @@ class MenuAddForm extends AbstractForm
      */
     public $neededPermissions = ['admin.content.cms.canManageMenu'];
 
-    /**
-     * menu title
-     * @var string
-     */
-    public $title = '';
-
-    /**
-     * box position
-     * @var string
-     */
-    public $position = '';
-
-    /**
-     * show order
-     * @var int
-     */
-    public $showOrder = 0;
-
-    /**
-     * true if created box is visible everywhere
-     * @var bool
-     */
-    public $visibleEverywhere = 1;
-
-    /**
-     * css class name of created box
-     * @var string
-     */
-    public $cssClassName = '';
-
-    /**
-     * true if box header is visible
-     * @var bool
-     */
-    public $showHeader = 1;
-
-    /**
-     * page ids
-     * @var int[]
-     */
-    public $pageIDs = [];
-
-    /**
-     * acl values
-     * @var array
-     */
-    public $aclValues = [];
-
     /**
      * @inheritDoc
      */
-    public function readParameters()
-    {
-        parent::readParameters();
-
-        I18nHandler::getInstance()->register('title');
-    }
+    public $objectEditLinkController = MenuEditForm::class;
 
     /**
      * @inheritDoc
      */
-    public function readFormParameters()
-    {
-        parent::readFormParameters();
+    public $objectActionClass = MenuAction::class;
 
-        I18nHandler::getInstance()->readValues();
+    #[\Override]
+    protected function createForm()
+    {
+        parent::createForm();
 
-        if (I18nHandler::getInstance()->isPlainValue('title')) {
-            $this->title = I18nHandler::getInstance()->getValue('title');
-        }
+        $tabMenu = TabMenuFormContainer::create('tabMenu');
+        $tabMenu->appendChildren([
+            $this->getGeneralTabContainer(),
+            $this->getPagesTabContainer(),
+            $this->getAclTabContainer(),
+        ]);
 
-        $this->visibleEverywhere = $this->showHeader = $this->showOrder = 0;
-        if (isset($_POST['position'])) {
-            $this->position = $_POST['position'];
-        }
-        if (isset($_POST['showOrder'])) {
-            $this->showOrder = \intval($_POST['showOrder']);
-        }
-        if (isset($_POST['visibleEverywhere'])) {
-            $this->visibleEverywhere = \intval($_POST['visibleEverywhere']);
-        }
-        if (isset($_POST['cssClassName'])) {
-            $this->cssClassName = StringUtil::trim($_POST['cssClassName']);
-        }
-        if (isset($_POST['showHeader'])) {
-            $this->showHeader = \intval($_POST['showHeader']);
-        }
-        if (isset($_POST['pageIDs']) && \is_array($_POST['pageIDs'])) {
-            $this->pageIDs = ArrayUtil::toIntegerArray($_POST['pageIDs']);
-        }
-        if (isset($_POST['aclValues']) && \is_array($_POST['aclValues'])) {
-            $this->aclValues = $_POST['aclValues'];
-        }
+        $this->form->appendChildren([$tabMenu]);
     }
 
-    /**
-     * @inheritDoc
-     */
-    public function validate()
+    protected function getGeneralTabContainer(): TabFormContainer
     {
-        parent::validate();
-
-        // validate menu title
-        if (!I18nHandler::getInstance()->validateValue('title')) {
-            if (I18nHandler::getInstance()->isPlainValue('title')) {
-                throw new UserInputException('title');
-            } else {
-                throw new UserInputException('title', 'multilingual');
-            }
-        }
-
-        // validate box position
-        $this->validatePosition();
-
-        // validate page ids
-        if (!empty($this->pageIDs)) {
-            $conditionBuilder = new PreparedStatementConditionBuilder();
-            $conditionBuilder->add('pageID IN (?)', [$this->pageIDs]);
-            $sql = "SELECT  pageID
-                    FROM    wcf1_page
-                    " . $conditionBuilder;
-            $statement = WCF::getDB()->prepare($sql);
-            $statement->execute($conditionBuilder->getParameters());
-            $this->pageIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
-        }
+        return TabFormContainer::create('generalTab')
+            ->label('wcf.global.form.data')
+            ->appendChildren([
+                FormContainer::create('generalContainer')
+                    ->appendChildren([
+                        TitleFormField::create()
+                            ->required()
+                            ->i18n()
+                            ->languageItemPattern('wcf.menu.(com.woltlab.wcf.genericMenu\d+|[\w\.]+)'),
+                        SingleSelectionFormField::create('position')
+                            ->label('wcf.acp.box.position')
+                            ->options(
+                                \array_combine(
+                                    Box::$availableMenuPositions,
+                                    \array_map(function (string $postion): string {
+                                        return 'wcf.acp.box.position.' . $postion;
+                                    }, Box::$availableMenuPositions)
+                                )
+                            )
+                            ->required(),
+                        IntegerFormField::create('showOrder')
+                            ->label('wcf.global.showOrder')
+                            ->value(0)
+                            ->required(),
+                        TextFormField::create('cssClassName')
+                            ->label('wcf.acp.box.cssClassName'),
+                        BooleanFormField::create('showHeader')
+                            ->label('wcf.acp.box.showHeader')
+                            ->value(true),
+                    ])
+            ]);
     }
 
-    /**
-     * Validates box position.
-     *
-     * @throws  UserInputException
-     */
-    protected function validatePosition()
+    #[\Override]
+    public function finalizeForm()
     {
-        if (!\in_array($this->position, Box::$availablePositions)) {
-            throw new UserInputException('position');
-        }
+        parent::finalizeForm();
+
+        $this->form->getDataHandler()
+            ->addProcessor(
+                new CustomFormDataProcessor(
+                    'defaultDataProcessor',
+                    function (IFormDocument $document, array $parameters) {
+                        $parameters['boxData'] = [];
+
+                        if ($this->formAction === 'create') {
+                            $parameters['data']['packageID'] = PACKAGE_ID;
+                            $parameters['data']['identifier'] = '';
+                            $parameters['boxData']['packageID'] = PACKAGE_ID;
+                            $parameters['boxData']['boxType'] = 'menu';
+                        }
+
+                        return $parameters;
+                    }
+                )
+            )
+            ->addProcessor(
+                new CustomFormDataProcessor(
+                    'boxDataProcessor',
+                    function (IFormDocument $document, array $parameters) {
+                        if ($this->formObject?->isMainMenu()) {
+                            return $parameters;
+                        }
+
+                        $parameters['boxData']['name'] = $parameters['data']['title']
+                            ?? $parameters['title_i18n'][LanguageFactory::getInstance()->getDefaultLanguageID()];
+                        $parameters['boxData']['cssClassName'] = $parameters['data']['cssClassName'];
+                        $parameters['boxData']['showOrder'] = $parameters['data']['showOrder'];
+                        $parameters['boxData']['showHeader'] = $parameters['data']['showHeader'];
+                        $parameters['boxData']['visibleEverywhere'] = $parameters['data']['visibleEverywhere'];
+                        $parameters['boxData']['position'] = $parameters['data']['position'];
+
+                        unset(
+                            $parameters['data']['cssClassName'],
+                            $parameters['data']['showOrder'],
+                            $parameters['data']['showHeader'],
+                            $parameters['data']['visibleEverywhere'],
+                            $parameters['data']['position']
+                        );
+
+                        return $parameters;
+                    },
+                    function (IFormDocument $document, array $data, IStorableObject $object) {
+                        \assert($object instanceof Menu);
+
+                        $data['position'] = $object->getBox()->position;
+                        $data['cssClassName'] = $object->getBox()->cssClassName;
+                        $data['showOrder'] = $object->getBox()->showOrder;
+                        $data['visibleEverywhere'] = $object->getBox()->visibleEverywhere;
+                        $data['pageIDs'] = $object->getBox()->getPageIDs();
+                        $data['showHeader'] = $object->getBox()->showHeader;
+
+                        $data['acl'] = SimpleAclHandler::getInstance()->getValues(
+                            'com.woltlab.wcf.box',
+                            $object->getBox()->boxID
+                        );
+
+                        return $data;
+                    }
+                )
+            );
     }
 
-    /**
-     * @inheritDoc
-     */
-    public function save()
+    #[\Override]
+    public function saved()
     {
-        parent::save();
+        $formData = $this->form->getData();
 
-        $boxName = $this->title;
-        if (!I18nHandler::getInstance()->isPlainValue('title')) {
-            $values = I18nHandler::getInstance()->getValues('title');
-            $boxName = $values[LanguageFactory::getInstance()->getDefaultLanguageID()];
+        if ($this->formAction == 'create') {
+            $menu = $this->objectAction->getReturnValues()['returnValues'];
+            \assert($menu instanceof Menu);
+        } else {
+            $menu = new Menu($this->formObject->menuID);
         }
 
-        // save label
-        $this->objectAction = new MenuAction([], 'create', [
-            'data' => \array_merge($this->additionalFields, [
-                'title' => $this->title,
-                'packageID' => 1,
-                'identifier' => '',
-            ]),
-            'boxData' => [
-                'name' => $boxName,
-                'boxType' => 'menu',
-                'position' => $this->position,
-                'visibleEverywhere' => $this->visibleEverywhere ? 1 : 0,
-                'showHeader' => $this->showHeader ? 1 : 0,
-                'showOrder' => $this->showOrder,
-                'cssClassName' => $this->cssClassName,
-                'packageID' => 1,
-            ],
-            'pageIDs' => $this->pageIDs,
-        ]);
-        $returnValues = $this->objectAction->executeAction();
-        // set generic identifier
-        $menuEditor = new MenuEditor($returnValues['returnValues']);
-        $menuEditor->update([
-            'identifier' => 'com.woltlab.wcf.genericMenu' . $menuEditor->menuID,
-        ]);
-        // save i18n
-        if (!I18nHandler::getInstance()->isPlainValue('title')) {
-            I18nHandler::getInstance()->save(
-                'title',
-                'wcf.menu.com.woltlab.wcf.genericMenu' . $menuEditor->menuID,
-                'wcf.menu',
-                1
-            );
+        if ($this->formAction !== 'create' && !$menu->isMainMenu()) {
+            $formData['data'] = $formData['boxData'];
+            unset($formData['boxData']);
 
-            // update title
-            $menuEditor->update([
-                'title' => 'wcf.menu.com.woltlab.wcf.genericMenu' . $menuEditor->menuID,
-            ]);
+            $boxAction = new BoxAction([$menu->getBox()->boxID], 'update', $formData);
+            $boxAction->executeAction();
         }
 
-        // save acl
-        SimpleAclHandler::getInstance()->setValues(
-            'com.woltlab.wcf.box',
-            $menuEditor->getDecoratedObject()->getBox()->boxID,
-            $this->aclValues
-        );
-
-        $this->saved();
-
-        // reset values
-        $this->cssClassName = $this->title = '';
-        $this->position = 'contentTop';
-        $this->showOrder = 0;
-        $this->visibleEverywhere = $this->showHeader = 1;
-        $this->pageIDs = $this->aclValues = [];
-
-        // show success message
-        WCF::getTPL()->assign([
-            'success' => true,
-            'objectEditLink' => LinkHandler::getInstance()->getControllerLink(
-                MenuEditForm::class,
-                ['id' => $menuEditor->menuID]
-            ),
-        ]);
+        if (!$menu->isMainMenu()) {
+            SimpleAclHandler::getInstance()->setValues(
+                'com.woltlab.wcf.box',
+                $menu->getBox()->boxID,
+                $formData['acl']
+            );
+        }
 
-        I18nHandler::getInstance()->reset();
+        parent::saved();
     }
 
-    /**
-     * @inheritDoc
-     */
-    public function assignVariables()
+    protected function getPagesTabContainer(): TabFormContainer
     {
-        parent::assignVariables();
-
-        I18nHandler::getInstance()->assignVariables();
+        return TabFormContainer::create('pagesTab')
+            ->label('wcf.acp.page.list')
+            ->appendChildren([
+                FormContainer::create('pagesContainer')
+                    ->appendChildren([
+                        BooleanFormField::create('visibleEverywhere')
+                            ->label('wcf.acp.box.visibleEverywhere')
+                            ->value(true),
+                        PagesFormField::create()
+                            ->visibleEverywhereFieldId('visibleEverywhere')
+                    ])
+            ]);
+    }
 
-        WCF::getTPL()->assign([
-            'action' => 'add',
-            'title' => 'title',
-            'position' => $this->position,
-            'cssClassName' => $this->cssClassName,
-            'showOrder' => $this->showOrder,
-            'visibleEverywhere' => $this->visibleEverywhere,
-            'showHeader' => $this->showHeader,
-            'pageIDs' => $this->pageIDs,
-            'availablePositions' => Box::$availableMenuPositions,
-            'pageNodeList' => (new PageNodeTree())->getNodeList(),
-            'aclValues' => SimpleAclHandler::getInstance()->getOutputValues($this->aclValues),
-        ]);
+    protected function getAclTabContainer(): TabFormContainer
+    {
+        return TabFormContainer::create('aclTab')
+            ->label('wcf.acl.access')
+            ->appendChildren([
+                FormContainer::create('aclContainer')
+                    ->appendChildren([
+                        SimpleAclFormField::create('acl')
+                    ])
+            ]);
     }
 }
index 1a1db4b677fc76f2fb161a9dd7171921be7e5965..9be1603118a10bb2c1752386f482d7c842d9e12d 100644 (file)
@@ -2,15 +2,12 @@
 
 namespace wcf\acp\form;
 
-use wcf\data\box\BoxAction;
+use CuyZ\Valinor\Mapper\MappingError;
 use wcf\data\menu\Menu;
-use wcf\data\menu\MenuAction;
-use wcf\form\AbstractForm;
-use wcf\system\acl\simple\SimpleAclHandler;
+use wcf\form\AbstractFormBuilderForm;
+use wcf\http\Helper;
 use wcf\system\exception\IllegalLinkException;
-use wcf\system\language\I18nHandler;
-use wcf\system\language\LanguageFactory;
-use wcf\system\WCF;
+use wcf\system\form\builder\field\TitleFormField;
 
 /**
  * Shows the menu edit form.
@@ -28,145 +25,50 @@ class MenuEditForm extends MenuAddForm
     public $activeMenuItem = 'wcf.acp.menu.link.cms.menu.list';
 
     /**
-     * menu id
-     * @var int
-     */
-    public $menuID = 0;
-
-    /**
-     * menu object
-     * @var Menu
+     * @inheritDoc
      */
-    public $menu;
+    public $formAction = 'edit';
 
     /**
      * @inheritDoc
      */
     public function readParameters()
     {
-        parent::readParameters();
+        AbstractFormBuilderForm::readParameters();
+
+        try {
+            $queryParameters = Helper::mapQueryParameters(
+                $_GET,
+                <<<'EOT'
+                    array {
+                        id: positive-int
+                    }
+                    EOT
+            );
+            $this->formObject = new Menu($queryParameters['id']);
 
-        if (isset($_REQUEST['id'])) {
-            $this->menuID = \intval($_REQUEST['id']);
-        }
-        $this->menu = new Menu($this->menuID);
-        if (!$this->menu->menuID) {
+            if (!$this->formObject->getObjectID()) {
+                throw new IllegalLinkException();
+            }
+        } catch (MappingError) {
             throw new IllegalLinkException();
         }
     }
 
-    /**
-     * @inheritDoc
-     */
-    protected function validatePosition()
+    #[\Override]
+    protected function createForm()
     {
-        if ($this->menu->identifier != 'com.woltlab.wcf.MainMenu') {
-            parent::validatePosition();
-        }
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public function save()
-    {
-        AbstractForm::save();
-
-        $boxName = $this->title;
-        if (!I18nHandler::getInstance()->isPlainValue('title')) {
-            $values = I18nHandler::getInstance()->getValues('title');
-            $boxName = $values[LanguageFactory::getInstance()->getDefaultLanguageID()];
-        }
-
-        $this->title = 'wcf.menu.' . $this->menu->identifier;
-        if (I18nHandler::getInstance()->isPlainValue('title')) {
-            I18nHandler::getInstance()->remove($this->title);
-            $this->title = I18nHandler::getInstance()->getValue('title');
-        } else {
-            I18nHandler::getInstance()->save('title', $this->title, 'wcf.menu', 1);
-        }
-
-        // update menu
-        $this->objectAction = new MenuAction([$this->menuID], 'update', [
-            'data' => \array_merge($this->additionalFields, [
-                'title' => $this->title,
-            ]),
-        ]);
-        $this->objectAction->executeAction();
-
-        // update box
-        if ($this->menu->identifier != 'com.woltlab.wcf.MainMenu') {
-            $boxAction = new BoxAction([$this->menu->getBox()->boxID], 'update', [
-                'data' => \array_merge($this->additionalFields, [
-                    'position' => $this->position,
-                    'visibleEverywhere' => $this->visibleEverywhere ? 1 : 0,
-                    'showHeader' => $this->showHeader ? 1 : 0,
-                    'showOrder' => $this->showOrder,
-                    'cssClassName' => $this->cssClassName,
-                    'name' => $boxName,
-                ]),
-                'pageIDs' => $this->pageIDs,
+        if ($this->formObject->isMainMenu()) {
+            AbstractFormBuilderForm::createForm();
+
+            $this->form->appendChildren([
+                TitleFormField::create()
+                    ->required()
+                    ->i18n()
+                    ->languageItemPattern('wcf.menu.(com.woltlab.wcf.genericMenu\d+|[\w\.]+)'),
             ]);
-            $boxAction->executeAction();
-        }
-
-        if ($this->menu->identifier !== 'com.woltlab.wcf.MainMenu') {
-            SimpleAclHandler::getInstance()->setValues(
-                'com.woltlab.wcf.box',
-                $this->menu->getBox()->boxID,
-                $this->aclValues
-            );
-        }
-
-        $this->saved();
-
-        // show success message
-        WCF::getTPL()->assign('success', true);
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public function readData()
-    {
-        parent::readData();
-
-        if (empty($_POST)) {
-            I18nHandler::getInstance()->setOptions(
-                'title',
-                1,
-                $this->menu->title,
-                'wcf.menu.' . $this->menu->identifier
-            );
-
-            $this->title = $this->menu->title;
-            $this->position = $this->menu->getBox()->position;
-            $this->cssClassName = $this->menu->getBox()->cssClassName;
-            $this->showOrder = $this->menu->getBox()->showOrder;
-            $this->visibleEverywhere = $this->menu->getBox()->visibleEverywhere;
-            $this->pageIDs = $this->menu->getBox()->getPageIDs();
-            $this->showHeader = $this->menu->getBox()->showHeader;
-
-            $this->aclValues = SimpleAclHandler::getInstance()->getValues(
-                'com.woltlab.wcf.box',
-                $this->menu->getBox()->boxID
-            );
+        } else {
+            parent::createForm();
         }
     }
-
-    /**
-     * @inheritDoc
-     */
-    public function assignVariables()
-    {
-        parent::assignVariables();
-
-        I18nHandler::getInstance()->assignVariables(!empty($_POST));
-
-        WCF::getTPL()->assign([
-            'action' => 'edit',
-            'menuID' => $this->menuID,
-            'menu' => $this->menu,
-        ]);
-    }
 }
index 05a94d707b9ebdd4b17738617d9b308cdab24b1e..acc62d8158ea0178abf1b1888936646a4bf9a517 100644 (file)
@@ -125,4 +125,9 @@ class Menu extends DatabaseObject implements ITitledObject
 
         return $this->menuItemNodeTree;
     }
+
+    public function isMainMenu(): bool
+    {
+        return $this->identifier === 'com.woltlab.wcf.MainMenu';
+    }
 }
index 0ab56641e973a0a6bdfee7c6a21a18f54ff8c0eb..fc426a5117a14737615f18163f376019ce0c38e3 100644 (file)
@@ -5,6 +5,7 @@ namespace wcf\data\menu;
 use wcf\data\AbstractDatabaseObjectAction;
 use wcf\data\box\BoxAction;
 use wcf\data\box\BoxEditor;
+use wcf\data\TI18nDatabaseObjectAction;
 use wcf\system\exception\PermissionDeniedException;
 
 /**
@@ -20,6 +21,8 @@ use wcf\system\exception\PermissionDeniedException;
  */
 class MenuAction extends AbstractDatabaseObjectAction
 {
+    use TI18nDatabaseObjectAction;
+
     /**
      * @inheritDoc
      */
@@ -51,14 +54,23 @@ class MenuAction extends AbstractDatabaseObjectAction
      */
     public function create()
     {
+        // `title` column doesn't have a default value
+        $this->parameters['data']['title'] = $this->parameters['data']['title'] ?? '';
+
         /** @var Menu $menu */
         $menu = parent::create();
 
+        $this->saveI18nValue($menu);
+
         // create box
         $boxData = $this->parameters['boxData'];
         $boxData['menuID'] = $menu->menuID;
         $boxData['identifier'] = '';
-        $boxAction = new BoxAction([], 'create', ['data' => $boxData, 'pageIDs' => $this->parameters['pageIDs'] ?? []]);
+        $boxAction = new BoxAction([], 'create', [
+            'data' => $boxData,
+            'pageIDs' => $this->parameters['pageIDs'] ?? [],
+            'acl' => $this->parameters['acl'] ?? []
+        ]);
         $returnValues = $boxAction->executeAction();
 
         // set generic box identifier
@@ -71,6 +83,16 @@ class MenuAction extends AbstractDatabaseObjectAction
         return $menu;
     }
 
+    #[\Override]
+    public function update()
+    {
+        parent::update();
+
+        foreach ($this->getObjects() as $menu) {
+            $this->saveI18nValue($menu->getDecoratedObject());
+        }
+    }
+
     /**
      * @inheritDoc
      */
@@ -84,4 +106,24 @@ class MenuAction extends AbstractDatabaseObjectAction
             }
         }
     }
+
+    #[\Override]
+    public function getI18nSaveTypes(): array
+    {
+        return [
+            'title' => 'wcf.menu.com.woltlab.wcf.genericMenu\d+'
+        ];
+    }
+
+    #[\Override]
+    public function getLanguageCategory(): string
+    {
+        return 'wcf.menu';
+    }
+
+    #[\Override]
+    public function getPackageID(): int
+    {
+        return PACKAGE_ID;
+    }
 }
index 601ced010625144374b9ed8705950fb85f518e79..7b7dd0e0a805fb8ea583da1f2d7cb46847ede6f9 100644 (file)
@@ -28,6 +28,8 @@ final class PagesFormField extends MultipleSelectionFormField
     public function __construct()
     {
         $this
+            ->label('wcf.acp.box.visibilityException.visible')
+            ->invertedLabel('wcf.acp.box.visibilityException.hidden')
             ->options((new PageNodeTree())->getNodeList(), true)
             ->filterable();
     }