Merge branch '5.2' into 5.3
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / acp / form / MenuItemAddForm.class.php
1 <?php
2 namespace wcf\acp\form;
3 use wcf\data\menu\item\MenuItem;
4 use wcf\data\menu\item\MenuItemAction;
5 use wcf\data\menu\item\MenuItemEditor;
6 use wcf\data\menu\item\MenuItemNodeTree;
7 use wcf\data\menu\Menu;
8 use wcf\data\page\Page;
9 use wcf\data\page\PageNodeTree;
10 use wcf\form\AbstractForm;
11 use wcf\system\exception\IllegalLinkException;
12 use wcf\system\exception\UserInputException;
13 use wcf\system\language\I18nHandler;
14 use wcf\system\page\handler\ILookupPageHandler;
15 use wcf\system\request\LinkHandler;
16 use wcf\system\WCF;
17 use wcf\util\StringUtil;
18
19 /**
20 * Shows the menu item add form.
21 *
22 * @author Marcel Werk
23 * @copyright 2001-2019 WoltLab GmbH
24 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
25 * @package WoltLabSuite\Core\Acp\Form
26 * @since 3.0
27 */
28 class MenuItemAddForm extends AbstractForm {
29 /**
30 * @inheritDoc
31 */
32 public $activeMenuItem = 'wcf.acp.menu.link.cms.menu.list';
33
34 /**
35 * @inheritDoc
36 */
37 public $neededPermissions = ['admin.content.cms.canManageMenu'];
38
39 /**
40 * menu id
41 * @var integer
42 */
43 public $menuID = 0;
44
45 /**
46 * menu object
47 * @var Menu
48 */
49 public $menu = null;
50
51 /**
52 * activation state
53 * @var boolean
54 */
55 public $isDisabled = false;
56
57 /**
58 * internal link
59 * @var boolean
60 */
61 public $isInternalLink = true;
62
63 /**
64 * list of page handlers by page id
65 * @var \wcf\system\page\handler\IMenuPageHandler[]
66 */
67 public $pageHandlers = [];
68
69 /**
70 * page id
71 * @var integer
72 */
73 public $pageID = null;
74
75 /**
76 * page object id
77 * @var integer
78 */
79 public $pageObjectID = null;
80
81 /**
82 * menu item title
83 * @var string
84 */
85 public $title = '';
86
87 /**
88 * external url
89 * @var string
90 */
91 public $externalURL = '';
92
93 /**
94 * id of the parent menu item
95 * @var integer
96 */
97 public $parentItemID = null;
98
99 /**
100 * show order
101 * @var integer
102 */
103 public $showOrder = 0;
104
105 /**
106 * menu item node tree
107 * @var MenuItemNodeTree
108 */
109 public $menuItems = null;
110
111 /**
112 * nested list of page nodes
113 * @var \RecursiveIteratorIterator
114 */
115 public $pageNodeList;
116
117 /**
118 * @inheritDoc
119 */
120 public function readParameters() {
121 parent::readParameters();
122
123 if (isset($_REQUEST['menuID'])) $this->menuID = intval($_REQUEST['menuID']);
124 $this->menu = new Menu($this->menuID);
125 if (!$this->menu->menuID) {
126 throw new IllegalLinkException();
127 }
128
129 I18nHandler::getInstance()->register('title');
130 I18nHandler::getInstance()->register('externalURL');
131
132 $this->pageNodeList = (new PageNodeTree())->getNodeList();
133
134 // fetch page handlers
135 foreach ($this->pageNodeList as $pageNode) {
136 $handler = $pageNode->getHandler();
137 if ($handler !== null) {
138 if ($handler instanceof ILookupPageHandler) {
139 $this->pageHandlers[$pageNode->pageID] = $pageNode->requireObjectID;
140 }
141 }
142 }
143 }
144
145 /**
146 * @inheritDoc
147 */
148 public function readFormParameters() {
149 parent::readFormParameters();
150
151 I18nHandler::getInstance()->readValues();
152 if (I18nHandler::getInstance()->isPlainValue('title')) $this->title = I18nHandler::getInstance()->getValue('title');
153 if (I18nHandler::getInstance()->isPlainValue('externalURL')) $this->externalURL = I18nHandler::getInstance()->getValue('externalURL');
154
155 if (isset($_POST['isDisabled'])) $this->isDisabled = true;
156 $this->isInternalLink = false;
157 if (isset($_POST['isInternalLink'])) $this->isInternalLink = (bool) $_POST['isInternalLink'];
158 if (!empty($_POST['pageID'])) $this->pageID = intval($_POST['pageID']);
159 if (!empty($_POST['pageObjectID'])) $this->pageObjectID = intval($_POST['pageObjectID']);
160 if (!empty($_POST['parentItemID'])) $this->parentItemID = intval($_POST['parentItemID']);
161 if (isset($_POST['showOrder'])) $this->showOrder = intval($_POST['showOrder']);
162 }
163
164 /**
165 * @inheritDoc
166 */
167 public function validate() {
168 parent::validate();
169
170 // validate parent menu item
171 if ($this->parentItemID) {
172 $parentMenuItem = new MenuItem($this->parentItemID);
173 if (!$parentMenuItem->itemID || $parentMenuItem->menuID != $this->menuID) {
174 throw new UserInputException('parentItemID', 'invalid');
175 }
176 }
177
178 // validate page menu item name
179 if (!I18nHandler::getInstance()->validateValue('title')) {
180 if (I18nHandler::getInstance()->isPlainValue('title')) {
181 throw new UserInputException('title');
182 }
183 else {
184 throw new UserInputException('title', 'multilingual');
185 }
186 }
187
188 // validate menu item controller
189 if ($this->isInternalLink) {
190 $this->externalURL = '';
191
192 if (!$this->pageID) {
193 throw new UserInputException('pageID');
194 }
195 $page = new Page($this->pageID);
196 if (!$page->pageID) {
197 throw new UserInputException('pageID', 'invalid');
198 }
199
200 // validate page object id
201 if ($page->requireObjectID) {
202 if (isset($this->pageHandlers[$page->pageID])) {
203 if ($this->pageHandlers[$page->pageID] && !$this->pageObjectID) {
204 throw new UserInputException('pageObjectID');
205 }
206
207 /** @var ILookupPageHandler $handler */
208 $handler = $page->getHandler();
209 if ($this->pageObjectID && !$handler->isValid($this->pageObjectID)) {
210 throw new UserInputException('pageObjectID', 'invalid');
211 }
212 }
213 else {
214 // page requires an object id, but no handler is registered
215 throw new UserInputException('pageID', 'invalid');
216 }
217 }
218 }
219 else {
220 $this->pageID = $this->pageObjectID = null;
221
222 // validate external url
223 if (!I18nHandler::getInstance()->validateValue('externalURL')) {
224 throw new UserInputException('externalURL');
225 }
226 }
227 }
228
229 /**
230 * @inheritDoc
231 */
232 public function save() {
233 parent::save();
234
235 $this->objectAction = new MenuItemAction([], 'create', ['data' => array_merge($this->additionalFields, [
236 'isDisabled' => $this->isDisabled ? 1 : 0,
237 'title' => $this->title,
238 'pageID' => $this->pageID,
239 'pageObjectID' => $this->pageObjectID ?: 0,
240 'externalURL' => $this->externalURL,
241 'menuID' => $this->menuID,
242 'parentItemID' => $this->parentItemID,
243 'showOrder' => $this->showOrder,
244 'identifier' => StringUtil::getRandomID(),
245 'packageID' => 1
246 ])]);
247 $this->objectAction->executeAction();
248
249 $returnValues = $this->objectAction->getReturnValues();
250 $menuItem = $returnValues['returnValues'];
251
252 // set generic identifier
253 $data = [
254 'identifier' => 'com.woltlab.wcf.generic'.$menuItem->itemID
255 ];
256 if (!I18nHandler::getInstance()->isPlainValue('title')) {
257 I18nHandler::getInstance()->save('title', 'wcf.menu.item.'.$data['identifier'], 'wcf.menu');
258 $data['title'] = 'wcf.menu.item.'.$data['identifier'];
259 }
260 if (!I18nHandler::getInstance()->isPlainValue('externalURL')) {
261 I18nHandler::getInstance()->save('externalURL', 'wcf.menu.item.externalURL'.$menuItem->itemID, 'wcf.menu');
262 $data['externalURL'] = 'wcf.menu.item.externalURL'.$menuItem->itemID;
263 }
264
265 // update values
266 $menuItemEditor = new MenuItemEditor($menuItem);
267 $menuItemEditor->update($data);
268
269 // call saved event
270 $this->saved();
271
272 // show success message
273 WCF::getTPL()->assign([
274 'success' => true,
275 'objectEditLink' => LinkHandler::getInstance()->getControllerLink(MenuItemEditForm::class, ['id' => $menuItem->itemID]),
276 ]);
277
278 // reset variables
279 $this->isInternalLink = true;
280 $this->isDisabled = false;
281 $this->pageID = $this->pageObjectID = $this->parentItemID = null;
282 $this->externalURL = $this->title = '';
283 $this->showOrder = 0;
284
285 I18nHandler::getInstance()->reset();
286 }
287
288 /**
289 * @inheritDoc
290 */
291 public function readData() {
292 parent::readData();
293
294 $this->menuItems = new MenuItemNodeTree($this->menuID, null, false);
295 }
296
297 /**
298 * @inheritDoc
299 */
300 public function assignVariables() {
301 parent::assignVariables();
302
303 I18nHandler::getInstance()->assignVariables();
304
305 WCF::getTPL()->assign([
306 'action' => 'add',
307 'menuID' => $this->menuID,
308 'menu' => $this->menu,
309 'isDisabled' => $this->isDisabled,
310 'isInternalLink' => $this->isInternalLink,
311 'pageID' => $this->pageID,
312 'pageObjectID' => $this->pageObjectID,
313 'title' => $this->title,
314 'externalURL' => $this->externalURL,
315 'parentItemID' => $this->parentItemID,
316 'showOrder' => $this->showOrder,
317 'menuItemNodeList' => $this->menuItems->getNodeList(),
318 'pageNodeList' => $this->pageNodeList,
319 'pageHandlers' => $this->pageHandlers
320 ]);
321 }
322 }