[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Menu/ -> AbstractMenu.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright  (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
   7   * @license    GNU General Public License version 2 or later; see LICENSE.txt
   8   */
   9  
  10  namespace Joomla\CMS\Menu;
  11  
  12  use Joomla\CMS\Factory;
  13  use Joomla\CMS\Language\Text;
  14  use Joomla\CMS\User\User;
  15  use Joomla\Registry\Registry;
  16  
  17  // phpcs:disable PSR1.Files.SideEffects
  18  \defined('JPATH_PLATFORM') or die;
  19  // phpcs:enable PSR1.Files.SideEffects
  20  
  21  /**
  22   * Menu class
  23   *
  24   * @since  1.5
  25   */
  26  abstract class AbstractMenu
  27  {
  28      /**
  29       * Array to hold the menu items
  30       *
  31       * @var    MenuItem[]
  32       *
  33       * @since  4.0.0
  34       */
  35      protected $items = array();
  36  
  37      /**
  38       * Identifier of the default menu item. Key of the array is the language.
  39       *
  40       * @var    integer[]
  41       *
  42       * @since  4.0.0
  43       */
  44      protected $default = array();
  45  
  46      /**
  47       * Identifier of the active menu item
  48       *
  49       * @var    integer
  50       *
  51       * @since  4.0.0
  52       */
  53      protected $active = 0;
  54  
  55      /**
  56       * Menu instances container.
  57       *
  58       * @var    AbstractMenu[]
  59       *
  60       * @since  1.7
  61       *
  62       * @deprecated 5.0 Use the MenuFactoryInterface from the container instead
  63       */
  64      public static $instances = array();
  65  
  66      /**
  67       * User object to check access levels for
  68       *
  69       * @var    User
  70       *
  71       * @since  3.9.26
  72       */
  73      protected $storedUser;
  74  
  75      /**
  76       * Flag for checking if the menu items have been loaded
  77       *
  78       * @var    boolean
  79       *
  80       * @since  4.0.0
  81       */
  82      private $itemsLoaded = false;
  83  
  84      /**
  85       * Class constructor
  86       *
  87       * @param   array  $options  An array of configuration options.
  88       *
  89       * @since   1.5
  90       */
  91      public function __construct($options = array())
  92      {
  93          /**
  94           * It is preferred NOT to inject and store the user when constructing the menu object,
  95           * at least for the Menu object used by Joomla.
  96           * The menu object can be built very early in the request, from an onAfterInitialise event
  97           * but the user can be updated later (by the Remember me plugin for instance). As the stored
  98           * user object is not updated, the menu will render incorrectly, not complying with
  99           * menu items access levels.
 100           *
 101           * @see https://github.com/joomla/joomla-cms/issues/11541
 102           */
 103          $this->storedUser = isset($options['user']) && $options['user'] instanceof User ? $options['user'] : null;
 104      }
 105  
 106      /**
 107       * Returns a Menu object
 108       *
 109       * @param   string  $client   The name of the client
 110       * @param   array   $options  An associative array of options
 111       *
 112       * @return  AbstractMenu  A menu object.
 113       *
 114       * @since       1.5
 115       *
 116       * @throws      \Exception
 117       *
 118       * @deprecated  5.0 Use the MenuFactoryInterface from the container instead
 119       */
 120      public static function getInstance($client, $options = array())
 121      {
 122          if (!$client) {
 123              throw new \Exception(Text::sprintf('JLIB_APPLICATION_ERROR_MENU_LOAD', $client), 500);
 124          }
 125  
 126          if (empty(self::$instances[$client])) {
 127              self::$instances[$client] = Factory::getContainer()->get(MenuFactoryInterface::class)->createMenu($client, $options);
 128          }
 129  
 130          return self::$instances[$client];
 131      }
 132  
 133      /**
 134       * Setter for the current user used to build menu.
 135       *
 136       * @param   User  $user  The new user to set.
 137       *
 138       * @return  void
 139       *
 140       * @since 3.9.26
 141       */
 142      public function setUser($user)
 143      {
 144          $this->storedUser = $user;
 145      }
 146  
 147      /**
 148       * Get menu item by id
 149       *
 150       * @param   integer  $id  The item id
 151       *
 152       * @return  MenuItem|null  The item object if the ID exists or null if not found
 153       *
 154       * @since   1.5
 155       */
 156      public function getItem($id)
 157      {
 158          $result = null;
 159  
 160          if (isset($this->getMenu()[$id])) {
 161              $result = &$this->getMenu()[$id];
 162          }
 163  
 164          return $result;
 165      }
 166  
 167      /**
 168       * Set the default item by id and language code.
 169       *
 170       * @param   integer  $id        The menu item id.
 171       * @param   string   $language  The language code (since 1.6).
 172       *
 173       * @return  boolean  True if a menu item with the given ID exists
 174       *
 175       * @since   1.5
 176       */
 177      public function setDefault($id, $language = '*')
 178      {
 179          if (isset($this->getMenu()[$id])) {
 180              $this->default[$language] = $id;
 181  
 182              return true;
 183          }
 184  
 185          return false;
 186      }
 187  
 188      /**
 189       * Get the default item by language code.
 190       *
 191       * @param   string  $language  The language code, default value of * means all.
 192       *
 193       * @return  MenuItem|void  The item object or null when not found for given language
 194       *
 195       * @since   1.5
 196       */
 197      public function getDefault($language = '*')
 198      {
 199          // Get menu items first to ensure defaults have been populated
 200          $items = $this->getMenu();
 201  
 202          if (\array_key_exists($language, $this->default)) {
 203              return $items[$this->default[$language]];
 204          }
 205  
 206          if (\array_key_exists('*', $this->default)) {
 207              return $items[$this->default['*']];
 208          }
 209      }
 210  
 211      /**
 212       * Set the default item by id
 213       *
 214       * @param   integer  $id  The item id
 215       *
 216       * @return  MenuItem|void  The menu item representing the given ID if present or null otherwise
 217       *
 218       * @since   1.5
 219       */
 220      public function setActive($id)
 221      {
 222          if (isset($this->getMenu()[$id])) {
 223              $this->active = $id;
 224  
 225              return $this->getMenu()[$id];
 226          }
 227      }
 228  
 229      /**
 230       * Get menu item by id.
 231       *
 232       * @return  MenuItem|void  The item object if an active menu item has been set or null
 233       *
 234       * @since   1.5
 235       */
 236      public function getActive()
 237      {
 238          if ($this->active) {
 239              return $this->getMenu()[$this->active];
 240          }
 241      }
 242  
 243      /**
 244       * Gets menu items by attribute
 245       *
 246       * @param   mixed    $attributes  The field name(s).
 247       * @param   mixed    $values      The value(s) of the field. If an array, need to match field names
 248       *                                each attribute may have multiple values to lookup for.
 249       * @param   boolean  $firstonly   If true, only returns the first item found
 250       *
 251       * @return  MenuItem|MenuItem[]  An array of menu item objects or a single object if the $firstonly parameter is true
 252       *
 253       * @since   1.5
 254       */
 255      public function getItems($attributes, $values, $firstonly = false)
 256      {
 257          $items      = array();
 258          $attributes = (array) $attributes;
 259          $values     = (array) $values;
 260          $count      = \count($attributes);
 261  
 262          foreach ($this->getMenu() as $item) {
 263              if (!\is_object($item)) {
 264                  continue;
 265              }
 266  
 267              $test = true;
 268  
 269              for ($i = 0; $i < $count; $i++) {
 270                  if (\is_array($values[$i])) {
 271                      if (!\in_array($item->{$attributes[$i]}, $values[$i])) {
 272                          $test = false;
 273                          break;
 274                      }
 275                  } else {
 276                      if ($item->{$attributes[$i]} != $values[$i]) {
 277                          $test = false;
 278                          break;
 279                      }
 280                  }
 281              }
 282  
 283              if ($test) {
 284                  if ($firstonly) {
 285                      return $item;
 286                  }
 287  
 288                  $items[] = $item;
 289              }
 290          }
 291  
 292          return $items;
 293      }
 294  
 295      /**
 296       * Gets the parameter object for a certain menu item
 297       *
 298       * @param   integer  $id  The item id
 299       *
 300       * @return  Registry
 301       *
 302       * @since   1.5
 303       */
 304      public function getParams($id)
 305      {
 306          if ($menu = $this->getItem($id)) {
 307              return $menu->getParams();
 308          }
 309  
 310          return new Registry();
 311      }
 312  
 313      /**
 314       * Getter for the menu array
 315       *
 316       * @return  MenuItem[]
 317       *
 318       * @since   1.5
 319       */
 320      public function getMenu()
 321      {
 322          if (!$this->itemsLoaded) {
 323              $this->load();
 324  
 325              foreach ($this->items as $item) {
 326                  if ($item->home) {
 327                      $this->default[trim($item->language)] = $item->id;
 328                  }
 329              }
 330  
 331              $this->itemsLoaded = true;
 332          }
 333  
 334          return $this->items;
 335      }
 336  
 337      /**
 338       * Method to check Menu object authorization against an access control object and optionally an access extension object
 339       *
 340       * @param   integer  $id  The menu id
 341       *
 342       * @return  boolean
 343       *
 344       * @since   1.5
 345       */
 346      public function authorise($id)
 347      {
 348          $menu = $this->getItem($id);
 349  
 350          if ($menu) {
 351              $access = (int) $menu->access;
 352  
 353              // If the access level is public we don't need to load the user session
 354              if ($access === 1) {
 355                  return true;
 356              }
 357  
 358              return \in_array($access, $this->user->getAuthorisedViewLevels(), true);
 359          }
 360  
 361          return true;
 362      }
 363  
 364      /**
 365       * Loads the menu items
 366       *
 367       * @return  array
 368       *
 369       * @since   1.5
 370       */
 371      abstract public function load();
 372  
 373      /**
 374       * Internal getter for the user. Returns the injected
 375       * one if any, or the current one if none.
 376       *
 377       * @return User
 378       *
 379       * @since 3.9.26
 380       */
 381      protected function getUser()
 382      {
 383          return empty($this->storedUser)
 384              ? Factory::getUser()
 385              : $this->storedUser;
 386      }
 387  
 388      /**
 389       * Magic getter for the user object. Returns the injected
 390       * one if any, or the current one if none.
 391       *
 392       * Using a magic getter to preserve B/C when we stopped storing the user object upon construction of the menu object.
 393       * As the user property is not initialized anymore, this getter ensures any class extending
 394       * this one can still use $instance->user and get a proper value.
 395       *
 396       * @param   string  $propName  Name of the missing or protected property.
 397       *
 398       * @return User|null
 399       *
 400       * @since 3.9.26
 401       */
 402      public function __get($propName)
 403      {
 404          if ($propName === 'user') {
 405              return empty($this->storedUser)
 406                  ? Factory::getUser()
 407                  : $this->storedUser;
 408          }
 409  
 410          return null;
 411      }
 412  }


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