[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/administrator/components/com_menus/src/Controller/ -> ItemController.php (source)

   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  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer