[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @package Joomla.Administrator 5 * @subpackage com_menus 6 * 7 * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> 8 * @license GNU General Public License version 2 or later; see LICENSE.txt 9 */ 10 11 namespace Joomla\Component\Menus\Administrator\Controller; 12 13 use Joomla\CMS\Component\ComponentHelper; 14 use Joomla\CMS\Filter\InputFilter; 15 use Joomla\CMS\Language\Text; 16 use Joomla\CMS\MVC\Controller\FormController; 17 use Joomla\CMS\Router\Route; 18 use Joomla\CMS\Uri\Uri; 19 20 // phpcs:disable PSR1.Files.SideEffects 21 \defined('_JEXEC') or die; 22 // phpcs:enable PSR1.Files.SideEffects 23 24 /** 25 * The Menu ItemModel Controller 26 * 27 * @since 1.6 28 */ 29 class ItemController extends FormController 30 { 31 /** 32 * Method to check if you can add a new record. 33 * 34 * Extended classes can override this if necessary. 35 * 36 * @param array $data An array of input data. 37 * 38 * @return boolean 39 * 40 * @since 3.6 41 */ 42 protected function allowAdd($data = array()) 43 { 44 $user = $this->app->getIdentity(); 45 46 $menuType = $this->input->getCmd('menutype', $data['menutype'] ?? ''); 47 48 $menutypeID = 0; 49 50 // Load menutype ID 51 if ($menuType) { 52 $menutypeID = (int) $this->getMenuTypeId($menuType); 53 } 54 55 return $user->authorise('core.create', 'com_menus.menu.' . $menutypeID); 56 } 57 58 /** 59 * Method to check if you edit a record. 60 * 61 * Extended classes can override this if necessary. 62 * 63 * @param array $data An array of input data. 64 * @param string $key The name of the key for the primary key; default is id. 65 * 66 * @return boolean 67 * 68 * @since 3.6 69 */ 70 protected function allowEdit($data = array(), $key = 'id') 71 { 72 $user = $this->app->getIdentity(); 73 74 $menutypeID = 0; 75 76 if (isset($data[$key])) { 77 $model = $this->getModel(); 78 $item = $model->getItem($data[$key]); 79 80 if (!empty($item->menutype)) { 81 // Protected menutype, do not allow edit 82 if ($item->menutype == 'main') { 83 return false; 84 } 85 86 $menutypeID = (int) $this->getMenuTypeId($item->menutype); 87 } 88 } 89 90 return $user->authorise('core.edit', 'com_menus.menu.' . (int) $menutypeID); 91 } 92 93 /** 94 * Loads the menutype ID by a given menutype string 95 * 96 * @param string $menutype The given menutype 97 * 98 * @return integer 99 * 100 * @since 3.6 101 */ 102 protected function getMenuTypeId($menutype) 103 { 104 $model = $this->getModel(); 105 $table = $model->getTable('MenuType'); 106 107 $table->load(array('menutype' => $menutype)); 108 109 return (int) $table->id; 110 } 111 112 /** 113 * Method to add a new menu item. 114 * 115 * @return mixed True if the record can be added, otherwise false. 116 * 117 * @since 1.6 118 */ 119 public function add() 120 { 121 $result = parent::add(); 122 123 if ($result) { 124 $context = 'com_menus.edit.item'; 125 126 $this->app->setUserState($context . '.type', null); 127 $this->app->setUserState($context . '.link', null); 128 } 129 130 return $result; 131 } 132 133 /** 134 * Method to run batch operations. 135 * 136 * @param object $model The model. 137 * 138 * @return boolean True if successful, false otherwise and internal error is set. 139 * 140 * @since 1.6 141 */ 142 public function batch($model = null) 143 { 144 $this->checkToken(); 145 146 /** @var \Joomla\Component\Menus\Administrator\Model\ItemModel $model */ 147 $model = $this->getModel('Item', 'Administrator', array()); 148 149 // Preset the redirect 150 $this->setRedirect(Route::_('index.php?option=com_menus&view=items' . $this->getRedirectToListAppend(), false)); 151 152 return parent::batch($model); 153 } 154 155 /** 156 * Method to cancel an edit. 157 * 158 * @param string $key The name of the primary key of the URL variable. 159 * 160 * @return boolean True if access level checks pass, false otherwise. 161 * 162 * @since 1.6 163 */ 164 public function cancel($key = null) 165 { 166 $this->checkToken(); 167 168 $result = parent::cancel(); 169 170 if ($result) { 171 // Clear the ancillary data from the session. 172 $context = 'com_menus.edit.item'; 173 $this->app->setUserState($context . '.type', null); 174 $this->app->setUserState($context . '.link', null); 175 176 // Redirect to the list screen. 177 $this->setRedirect( 178 Route::_( 179 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend() 180 . '&menutype=' . $this->app->getUserState('com_menus.items.menutype'), 181 false 182 ) 183 ); 184 } 185 186 return $result; 187 } 188 189 /** 190 * Method to edit an existing record. 191 * 192 * @param string $key The name of the primary key of the URL variable. 193 * @param string $urlVar The name of the URL variable if different from the primary key 194 * (sometimes required to avoid router collisions). 195 * 196 * @return boolean True if access level check and checkout passes, false otherwise. 197 * 198 * @since 1.6 199 */ 200 public function edit($key = null, $urlVar = null) 201 { 202 $result = parent::edit(); 203 204 if ($result) { 205 // Push the new ancillary data into the session. 206 $this->app->setUserState('com_menus.edit.item.type', null); 207 $this->app->setUserState('com_menus.edit.item.link', null); 208 } 209 210 return $result; 211 } 212 213 /** 214 * Gets the URL arguments to append to an item redirect. 215 * 216 * @param integer $recordId The primary key id for the item. 217 * @param string $urlVar The name of the URL variable for the id. 218 * 219 * @return string The arguments to append to the redirect URL. 220 * 221 * @since 3.0.1 222 */ 223 protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') 224 { 225 $append = parent::getRedirectToItemAppend($recordId, $urlVar); 226 227 if ($recordId) { 228 /** @var \Joomla\Component\Menus\Administrator\Model\ItemModel $model */ 229 $model = $this->getModel(); 230 $item = $model->getItem($recordId); 231 $clientId = $item->client_id; 232 $append = '&client_id=' . $clientId . $append; 233 } else { 234 $clientId = $this->input->get('client_id', '0', 'int'); 235 $menuType = $this->input->get('menutype', 'mainmenu', 'cmd'); 236 $append = '&client_id=' . $clientId . ($menuType ? '&menutype=' . $menuType : '') . $append; 237 } 238 239 return $append; 240 } 241 242 /** 243 * Method to save a record. 244 * 245 * @param string $key The name of the primary key of the URL variable. 246 * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). 247 * 248 * @return boolean True if successful, false otherwise. 249 * 250 * @since 1.6 251 */ 252 public function save($key = null, $urlVar = null) 253 { 254 // Check for request forgeries. 255 $this->checkToken(); 256 257 /** @var \Joomla\Component\Menus\Administrator\Model\ItemModel $model */ 258 $model = $this->getModel('Item', 'Administrator', array()); 259 $table = $model->getTable(); 260 $data = $this->input->post->get('jform', array(), 'array'); 261 $task = $this->getTask(); 262 $context = 'com_menus.edit.item'; 263 $app = $this->app; 264 265 // Set the menutype should we need it. 266 if ($data['menutype'] !== '') { 267 $this->input->set('menutype', $data['menutype']); 268 } 269 270 // Determine the name of the primary key for the data. 271 if (empty($key)) { 272 $key = $table->getKeyName(); 273 } 274 275 // To avoid data collisions the urlVar may be different from the primary key. 276 if (empty($urlVar)) { 277 $urlVar = $key; 278 } 279 280 $recordId = $this->input->getInt($urlVar); 281 282 // Populate the row id from the session. 283 $data[$key] = $recordId; 284 285 // The save2copy task needs to be handled slightly differently. 286 if ($task == 'save2copy') { 287 // Check-in the original row. 288 if ($model->checkin($data['id']) === false) { 289 // Check-in failed, go back to the item and display a notice. 290 $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()), 'warning'); 291 292 return false; 293 } 294 295 // Reset the ID and then treat the request as for Apply. 296 $data['id'] = 0; 297 $data['associations'] = array(); 298 $task = 'apply'; 299 } 300 301 // Access check. 302 if (!$this->allowSave($data, $key)) { 303 $this->setMessage(Text::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error'); 304 305 $this->setRedirect( 306 Route::_( 307 'index.php?option=' . $this->option . '&view=' . $this->view_list 308 . $this->getRedirectToListAppend(), 309 false 310 ) 311 ); 312 313 return false; 314 } 315 316 // Validate the posted data. 317 // This post is made up of two forms, one for the item and one for params. 318 $form = $model->getForm($data); 319 320 if (!$form) { 321 throw new \Exception($model->getError(), 500); 322 } 323 324 if ($data['type'] == 'url') { 325 $data['link'] = str_replace(array('"', '>', '<'), '', $data['link']); 326 327 if (strstr($data['link'], ':')) { 328 $segments = explode(':', $data['link']); 329 $protocol = strtolower($segments[0]); 330 $scheme = array( 331 'http', 'https', 'ftp', 'ftps', 'gopher', 'mailto', 332 'news', 'prospero', 'telnet', 'rlogin', 'tn3270', 'wais', 333 'mid', 'cid', 'nntp', 'tel', 'urn', 'ldap', 'file', 'fax', 334 'modem', 'git', 'sms', 335 ); 336 337 if (!in_array($protocol, $scheme)) { 338 $app->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'warning'); 339 $this->setRedirect( 340 Route::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId), false) 341 ); 342 343 return false; 344 } 345 } 346 } 347 348 $data = $model->validate($form, $data); 349 350 // Preprocess request fields to ensure that we remove not set or empty request params 351 $request = $form->getGroup('request', true); 352 353 // Check for the special 'request' entry. 354 if ($data['type'] == 'component' && !empty($request)) { 355 $removeArgs = array(); 356 357 if (!isset($data['request']) || !is_array($data['request'])) { 358 $data['request'] = array(); 359 } 360 361 foreach ($request as $field) { 362 $fieldName = $field->getAttribute('name'); 363 364 if (!isset($data['request'][$fieldName]) || $data['request'][$fieldName] == '') { 365 $removeArgs[$fieldName] = ''; 366 } 367 } 368 369 // Parse the submitted link arguments. 370 $args = array(); 371 parse_str(parse_url($data['link'], PHP_URL_QUERY), $args); 372 373 // Merge in the user supplied request arguments. 374 $args = array_merge($args, $data['request']); 375 376 // Remove the unused request params 377 if (!empty($args) && !empty($removeArgs)) { 378 $args = array_diff_key($args, $removeArgs); 379 } 380 381 $data['link'] = 'index.php?' . urldecode(http_build_query($args, '', '&')); 382 } 383 384 // Check for validation errors. 385 if ($data === false) { 386 // Get the validation messages. 387 $errors = $model->getErrors(); 388 389 // Push up to three validation messages out to the user. 390 for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++) { 391 if ($errors[$i] instanceof \Exception) { 392 $app->enqueueMessage($errors[$i]->getMessage(), 'warning'); 393 } else { 394 $app->enqueueMessage($errors[$i], 'warning'); 395 } 396 } 397 398 // Save the data in the session. 399 $app->setUserState('com_menus.edit.item.data', $data); 400 401 // Redirect back to the edit screen. 402 $editUrl = 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId); 403 $this->setRedirect(Route::_($editUrl, false)); 404 405 return false; 406 } 407 408 // Attempt to save the data. 409 if (!$model->save($data)) { 410 // Save the data in the session. 411 $app->setUserState('com_menus.edit.item.data', $data); 412 413 // Redirect back to the edit screen. 414 $editUrl = 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId); 415 $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()), 'error'); 416 $this->setRedirect(Route::_($editUrl, false)); 417 418 return false; 419 } 420 421 // Save succeeded, check-in the row. 422 if ($model->checkin($data['id']) === false) { 423 // Check-in failed, go back to the row and display a notice. 424 $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()), 'warning'); 425 $redirectUrl = 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId); 426 $this->setRedirect(Route::_($redirectUrl, false)); 427 428 return false; 429 } 430 431 $this->setMessage(Text::_('COM_MENUS_SAVE_SUCCESS')); 432 433 // Redirect the user and adjust session state based on the chosen task. 434 switch ($task) { 435 case 'apply': 436 // Set the row data in the session. 437 $recordId = $model->getState($this->context . '.id'); 438 $this->holdEditId($context, $recordId); 439 $app->setUserState('com_menus.edit.item.data', null); 440 $app->setUserState('com_menus.edit.item.type', null); 441 $app->setUserState('com_menus.edit.item.link', null); 442 443 // Redirect back to the edit screen. 444 $editUrl = 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId); 445 $this->setRedirect(Route::_($editUrl, false)); 446 break; 447 448 case 'save2new': 449 // Clear the row id and data in the session. 450 $this->releaseEditId($context, $recordId); 451 $app->setUserState('com_menus.edit.item.data', null); 452 $app->setUserState('com_menus.edit.item.type', null); 453 $app->setUserState('com_menus.edit.item.link', null); 454 455 // Redirect back to the edit screen. 456 $this->setRedirect(Route::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend(), false)); 457 break; 458 459 default: 460 // Clear the row id and data in the session. 461 $this->releaseEditId($context, $recordId); 462 $app->setUserState('com_menus.edit.item.data', null); 463 $app->setUserState('com_menus.edit.item.type', null); 464 $app->setUserState('com_menus.edit.item.link', null); 465 466 // Redirect to the list screen. 467 $this->setRedirect( 468 Route::_( 469 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend() 470 . '&menutype=' . $app->getUserState('com_menus.items.menutype'), 471 false 472 ) 473 ); 474 break; 475 } 476 477 return true; 478 } 479 480 /** 481 * Sets the type of the menu item currently being edited. 482 * 483 * @return void 484 * 485 * @since 1.6 486 */ 487 public function setType() 488 { 489 $this->checkToken(); 490 491 $app = $this->app; 492 493 // Get the posted values from the request. 494 $data = $this->input->post->get('jform', array(), 'array'); 495 496 // Get the type. 497 $type = $data['type']; 498 499 $type = json_decode(base64_decode($type)); 500 $title = $type->title ?? null; 501 $recordId = $type->id ?? 0; 502 503 $specialTypes = array('alias', 'separator', 'url', 'heading', 'container'); 504 505 if (!in_array($title, $specialTypes)) { 506 $title = 'component'; 507 } else { 508 // Set correct component id to ensure proper 404 messages with system links 509 $data['component_id'] = 0; 510 } 511 512 $app->setUserState('com_menus.edit.item.type', $title); 513 514 if ($title == 'component') { 515 if (isset($type->request)) { 516 // Clean component name 517 $type->request->option = InputFilter::getInstance()->clean($type->request->option, 'CMD'); 518 519 $component = ComponentHelper::getComponent($type->request->option); 520 $data['component_id'] = $component->id; 521 522 $app->setUserState('com_menus.edit.item.link', 'index.php?' . Uri::buildQuery((array) $type->request)); 523 } 524 } elseif ($title == 'alias') { 525 // If the type is alias you just need the item id from the menu item referenced. 526 $app->setUserState('com_menus.edit.item.link', 'index.php?Itemid='); 527 } 528 529 unset($data['request']); 530 531 $data['type'] = $title; 532 533 if ($this->input->get('fieldtype') == 'type') { 534 $data['link'] = $app->getUserState('com_menus.edit.item.link'); 535 } 536 537 // Save the data in the session. 538 $app->setUserState('com_menus.edit.item.data', $data); 539 540 $this->type = $type; 541 $this->setRedirect( 542 Route::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId), false) 543 ); 544 } 545 546 /** 547 * Gets the parent items of the menu location currently. 548 * 549 * @return void 550 * 551 * @since 3.2 552 */ 553 public function getParentItem() 554 { 555 $app = $this->app; 556 557 $results = array(); 558 $menutype = $this->input->get->get('menutype'); 559 560 if ($menutype) { 561 /** @var \Joomla\Component\Menus\Administrator\Model\ItemsModel $model */ 562 $model = $this->getModel('Items', 'Administrator', array()); 563 $model->getState(); 564 $model->setState('filter.menutype', $menutype); 565 $model->setState('list.select', 'a.id, a.title, a.level'); 566 $model->setState('list.start', '0'); 567 $model->setState('list.limit', '0'); 568 569 $results = $model->getItems(); 570 571 // Pad the option text with spaces using depth level as a multiplier. 572 for ($i = 0, $n = count($results); $i < $n; $i++) { 573 $results[$i]->title = str_repeat(' - ', $results[$i]->level) . $results[$i]->title; 574 } 575 } 576 577 // Output a \JSON object 578 echo json_encode($results); 579 580 $app->close(); 581 } 582 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |