[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Application/ -> CMSApplication.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright  (C) 2013 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\Application;
  11  
  12  use Joomla\Application\SessionAwareWebApplicationTrait;
  13  use Joomla\Application\Web\WebClient;
  14  use Joomla\CMS\Authentication\Authentication;
  15  use Joomla\CMS\Component\ComponentHelper;
  16  use Joomla\CMS\Event\AbstractEvent;
  17  use Joomla\CMS\Event\ErrorEvent;
  18  use Joomla\CMS\Exception\ExceptionHandler;
  19  use Joomla\CMS\Extension\ExtensionManagerTrait;
  20  use Joomla\CMS\Factory;
  21  use Joomla\CMS\Filter\InputFilter;
  22  use Joomla\CMS\Input\Input;
  23  use Joomla\CMS\Language\Language;
  24  use Joomla\CMS\Language\Text;
  25  use Joomla\CMS\Log\Log;
  26  use Joomla\CMS\Menu\AbstractMenu;
  27  use Joomla\CMS\Menu\MenuFactoryInterface;
  28  use Joomla\CMS\Pathway\Pathway;
  29  use Joomla\CMS\Plugin\PluginHelper;
  30  use Joomla\CMS\Profiler\Profiler;
  31  use Joomla\CMS\Router\Route;
  32  use Joomla\CMS\Router\Router;
  33  use Joomla\CMS\Session\MetadataManager;
  34  use Joomla\CMS\Session\Session;
  35  use Joomla\CMS\Uri\Uri;
  36  use Joomla\DI\Container;
  37  use Joomla\DI\ContainerAwareInterface;
  38  use Joomla\DI\ContainerAwareTrait;
  39  use Joomla\Registry\Registry;
  40  use Joomla\String\StringHelper;
  41  
  42  // phpcs:disable PSR1.Files.SideEffects
  43  \defined('JPATH_PLATFORM') or die;
  44  // phpcs:enable PSR1.Files.SideEffects
  45  
  46  /**
  47   * Joomla! CMS Application class
  48   *
  49   * @since  3.2
  50   */
  51  abstract class CMSApplication extends WebApplication implements ContainerAwareInterface, CMSWebApplicationInterface
  52  {
  53      use ContainerAwareTrait;
  54      use ExtensionManagerTrait;
  55      use ExtensionNamespaceMapper;
  56      use SessionAwareWebApplicationTrait;
  57  
  58      /**
  59       * Array of options for the \JDocument object
  60       *
  61       * @var    array
  62       * @since  3.2
  63       */
  64      protected $docOptions = array();
  65  
  66      /**
  67       * Application instances container.
  68       *
  69       * @var    CmsApplication[]
  70       * @since  3.2
  71       */
  72      protected static $instances = array();
  73  
  74      /**
  75       * The scope of the application.
  76       *
  77       * @var    string
  78       * @since  3.2
  79       */
  80      public $scope = null;
  81  
  82      /**
  83       * The client identifier.
  84       *
  85       * @var    integer
  86       * @since  4.0.0
  87       */
  88      protected $clientId = null;
  89  
  90      /**
  91       * The application message queue.
  92       *
  93       * @var    array
  94       * @since  4.0.0
  95       */
  96      protected $messageQueue = array();
  97  
  98      /**
  99       * The name of the application.
 100       *
 101       * @var    string
 102       * @since  4.0.0
 103       */
 104      protected $name = null;
 105  
 106      /**
 107       * The profiler instance
 108       *
 109       * @var    Profiler
 110       * @since  3.2
 111       */
 112      protected $profiler = null;
 113  
 114      /**
 115       * Currently active template
 116       *
 117       * @var    object
 118       * @since  3.2
 119       */
 120      protected $template = null;
 121  
 122      /**
 123       * The pathway object
 124       *
 125       * @var    Pathway
 126       * @since  4.0.0
 127       */
 128      protected $pathway = null;
 129  
 130      /**
 131       * The authentication plugin type
 132       *
 133       * @var   string
 134       * @since  4.0.0
 135       */
 136      protected $authenticationPluginType = 'authentication';
 137  
 138      /**
 139       * Menu instances container.
 140       *
 141       * @var    AbstractMenu[]
 142       * @since  4.2.0
 143       */
 144      protected $menus = [];
 145  
 146      /**
 147       * The menu factory
 148       *
 149       * @var   MenuFactoryInterface
 150       *
 151       * @since  4.2.0
 152       */
 153      private $menuFactory;
 154  
 155      /**
 156       * Class constructor.
 157       *
 158       * @param   Input      $input      An optional argument to provide dependency injection for the application's input
 159       *                                 object.  If the argument is a JInput object that object will become the
 160       *                                 application's input object, otherwise a default input object is created.
 161       * @param   Registry   $config     An optional argument to provide dependency injection for the application's config
 162       *                                 object.  If the argument is a Registry object that object will become the
 163       *                                 application's config object, otherwise a default config object is created.
 164       * @param   WebClient  $client     An optional argument to provide dependency injection for the application's client
 165       *                                 object.  If the argument is a WebClient object that object will become the
 166       *                                 application's client object, otherwise a default client object is created.
 167       * @param   Container  $container  Dependency injection container.
 168       *
 169       * @since   3.2
 170       */
 171      public function __construct(Input $input = null, Registry $config = null, WebClient $client = null, Container $container = null)
 172      {
 173          $container = $container ?: new Container();
 174          $this->setContainer($container);
 175  
 176          parent::__construct($input, $config, $client);
 177  
 178          // If JDEBUG is defined, load the profiler instance
 179          if (\defined('JDEBUG') && JDEBUG) {
 180              $this->profiler = Profiler::getInstance('Application');
 181          }
 182  
 183          // Enable sessions by default.
 184          if ($this->config->get('session') === null) {
 185              $this->config->set('session', true);
 186          }
 187  
 188          // Set the session default name.
 189          if ($this->config->get('session_name') === null) {
 190              $this->config->set('session_name', $this->getName());
 191          }
 192      }
 193  
 194      /**
 195       * Checks the user session.
 196       *
 197       * If the session record doesn't exist, initialise it.
 198       * If session is new, create session variables
 199       *
 200       * @return  void
 201       *
 202       * @since   3.2
 203       * @throws  \RuntimeException
 204       */
 205      public function checkSession()
 206      {
 207          $this->getContainer()->get(MetadataManager::class)->createOrUpdateRecord($this->getSession(), $this->getIdentity());
 208      }
 209  
 210      /**
 211       * Enqueue a system message.
 212       *
 213       * @param   string  $msg   The message to enqueue.
 214       * @param   string  $type  The message type. Default is message.
 215       *
 216       * @return  void
 217       *
 218       * @since   3.2
 219       */
 220      public function enqueueMessage($msg, $type = self::MSG_INFO)
 221      {
 222          // Don't add empty messages.
 223          if ($msg === null || trim($msg) === '') {
 224              return;
 225          }
 226  
 227          $inputFilter = InputFilter::getInstance(
 228              [],
 229              [],
 230              InputFilter::ONLY_BLOCK_DEFINED_TAGS,
 231              InputFilter::ONLY_BLOCK_DEFINED_ATTRIBUTES
 232          );
 233  
 234          // Build the message array and apply the HTML InputFilter with the default blacklist to the message
 235          $message = array(
 236              'message' => $inputFilter->clean($msg, 'html'),
 237              'type'    => $inputFilter->clean(strtolower($type), 'cmd'),
 238          );
 239  
 240          // For empty queue, if messages exists in the session, enqueue them first.
 241          $messages = $this->getMessageQueue();
 242  
 243          if (!\in_array($message, $this->messageQueue)) {
 244              // Enqueue the message.
 245              $this->messageQueue[] = $message;
 246          }
 247      }
 248  
 249      /**
 250       * Ensure several core system input variables are not arrays.
 251       *
 252       * @return  void
 253       *
 254       * @since   3.9
 255       */
 256      private function sanityCheckSystemVariables()
 257      {
 258          $input = $this->input;
 259  
 260          // Get invalid input variables
 261          $invalidInputVariables = array_filter(
 262              array('option', 'view', 'format', 'lang', 'Itemid', 'template', 'templateStyle', 'task'),
 263              function ($systemVariable) use ($input) {
 264                  return $input->exists($systemVariable) && is_array($input->getRaw($systemVariable));
 265              }
 266          );
 267  
 268          // Unset invalid system variables
 269          foreach ($invalidInputVariables as $systemVariable) {
 270              $input->set($systemVariable, null);
 271          }
 272  
 273          // Abort when there are invalid variables
 274          if ($invalidInputVariables) {
 275              throw new \RuntimeException('Invalid input, aborting application.');
 276          }
 277      }
 278  
 279      /**
 280       * Execute the application.
 281       *
 282       * @return  void
 283       *
 284       * @since   3.2
 285       */
 286      public function execute()
 287      {
 288          try {
 289              $this->sanityCheckSystemVariables();
 290              $this->setupLogging();
 291              $this->createExtensionNamespaceMap();
 292  
 293              // Perform application routines.
 294              $this->doExecute();
 295  
 296              // If we have an application document object, render it.
 297              if ($this->document instanceof \Joomla\CMS\Document\Document) {
 298                  // Render the application output.
 299                  $this->render();
 300              }
 301  
 302              // If gzip compression is enabled in configuration and the server is compliant, compress the output.
 303              if ($this->get('gzip') && !ini_get('zlib.output_compression') && ini_get('output_handler') !== 'ob_gzhandler') {
 304                  $this->compress();
 305  
 306                  // Trigger the onAfterCompress event.
 307                  $this->triggerEvent('onAfterCompress');
 308              }
 309          } catch (\Throwable $throwable) {
 310              /** @var ErrorEvent $event */
 311              $event = AbstractEvent::create(
 312                  'onError',
 313                  [
 314                      'subject'     => $throwable,
 315                      'eventClass'  => ErrorEvent::class,
 316                      'application' => $this,
 317                  ]
 318              );
 319  
 320              // Trigger the onError event.
 321              $this->triggerEvent('onError', $event);
 322  
 323              ExceptionHandler::handleException($event->getError());
 324          }
 325  
 326          // Trigger the onBeforeRespond event.
 327          $this->getDispatcher()->dispatch('onBeforeRespond');
 328  
 329          // Send the application response.
 330          $this->respond();
 331  
 332          // Trigger the onAfterRespond event.
 333          $this->getDispatcher()->dispatch('onAfterRespond');
 334      }
 335  
 336      /**
 337       * Check if the user is required to reset their password.
 338       *
 339       * If the user is required to reset their password will be redirected to the page that manage the password reset.
 340       *
 341       * @param   string  $option  The option that manage the password reset
 342       * @param   string  $view    The view that manage the password reset
 343       * @param   string  $layout  The layout of the view that manage the password reset
 344       * @param   string  $tasks   Permitted tasks
 345       *
 346       * @return  void
 347       *
 348       * @throws  \Exception
 349       */
 350      protected function checkUserRequireReset($option, $view, $layout, $tasks)
 351      {
 352          if (Factory::getUser()->get('requireReset', 0)) {
 353              $redirect = false;
 354  
 355              /*
 356               * By default user profile edit page is used.
 357               * That page allows you to change more than just the password and might not be the desired behavior.
 358               * This allows a developer to override the page that manage the password reset.
 359               * (can be configured using the file: configuration.php, or if extended, through the global configuration form)
 360               */
 361              $name = $this->getName();
 362  
 363              if ($this->get($name . '_reset_password_override', 0)) {
 364                  $option = $this->get($name . '_reset_password_option', '');
 365                  $view   = $this->get($name . '_reset_password_view', '');
 366                  $layout = $this->get($name . '_reset_password_layout', '');
 367                  $tasks  = $this->get($name . '_reset_password_tasks', '');
 368              }
 369  
 370              $task = $this->input->getCmd('task', '');
 371  
 372              // Check task or option/view/layout
 373              if (!empty($task)) {
 374                  $tasks = explode(',', $tasks);
 375  
 376                  // Check full task version "option/task"
 377                  if (array_search($this->input->getCmd('option', '') . '/' . $task, $tasks) === false) {
 378                      // Check short task version, must be on the same option of the view
 379                      if ($this->input->getCmd('option', '') !== $option || array_search($task, $tasks) === false) {
 380                          // Not permitted task
 381                          $redirect = true;
 382                      }
 383                  }
 384              } else {
 385                  if (
 386                      $this->input->getCmd('option', '') !== $option || $this->input->getCmd('view', '') !== $view
 387                      || $this->input->getCmd('layout', '') !== $layout
 388                  ) {
 389                      // Requested a different option/view/layout
 390                      $redirect = true;
 391                  }
 392              }
 393  
 394              if ($redirect) {
 395                  // Redirect to the profile edit page
 396                  $this->enqueueMessage(Text::_('JGLOBAL_PASSWORD_RESET_REQUIRED'), 'notice');
 397  
 398                  $url = Route::_('index.php?option=' . $option . '&view=' . $view . '&layout=' . $layout, false);
 399  
 400                  // In the administrator we need a different URL
 401                  if (strtolower($name) === 'administrator') {
 402                      $user = Factory::getApplication()->getIdentity();
 403                      $url  = Route::_('index.php?option=' . $option . '&task=' . $view . '.' . $layout . '&id=' . $user->id, false);
 404                  }
 405  
 406                  $this->redirect($url);
 407              }
 408          }
 409      }
 410  
 411      /**
 412       * Gets a configuration value.
 413       *
 414       * @param   string  $varname  The name of the value to get.
 415       * @param   string  $default  Default value to return
 416       *
 417       * @return  mixed  The user state.
 418       *
 419       * @since   3.2
 420       * @deprecated  5.0  Use get() instead
 421       */
 422      public function getCfg($varname, $default = null)
 423      {
 424          try {
 425              Log::add(
 426                  sprintf('%s() is deprecated and will be removed in 5.0. Use JFactory->getApplication()->get() instead.', __METHOD__),
 427                  Log::WARNING,
 428                  'deprecated'
 429              );
 430          } catch (\RuntimeException $exception) {
 431              // Informational log only
 432          }
 433  
 434          return $this->get($varname, $default);
 435      }
 436  
 437      /**
 438       * Gets the client id of the current running application.
 439       *
 440       * @return  integer  A client identifier.
 441       *
 442       * @since   3.2
 443       */
 444      public function getClientId()
 445      {
 446          return $this->clientId;
 447      }
 448  
 449      /**
 450       * Returns a reference to the global CmsApplication object, only creating it if it doesn't already exist.
 451       *
 452       * This method must be invoked as: $web = CmsApplication::getInstance();
 453       *
 454       * @param   string     $name       The name (optional) of the CmsApplication class to instantiate.
 455       * @param   string     $prefix     The class name prefix of the object.
 456       * @param   Container  $container  An optional dependency injection container to inject into the application.
 457       *
 458       * @return  CmsApplication
 459       *
 460       * @since       3.2
 461       * @throws      \RuntimeException
 462       * @deprecated  5.0 Use \Joomla\CMS\Factory::getContainer()->get($name) instead
 463       */
 464      public static function getInstance($name = null, $prefix = '\JApplication', Container $container = null)
 465      {
 466          if (empty(static::$instances[$name])) {
 467              // Create a CmsApplication object.
 468              $classname = $prefix . ucfirst($name);
 469  
 470              if (!$container) {
 471                  $container = Factory::getContainer();
 472              }
 473  
 474              if ($container->has($classname)) {
 475                  static::$instances[$name] = $container->get($classname);
 476              } elseif (class_exists($classname)) {
 477                  // @todo This creates an implicit hard requirement on the ApplicationCms constructor
 478                  static::$instances[$name] = new $classname(null, null, null, $container);
 479              } else {
 480                  throw new \RuntimeException(Text::sprintf('JLIB_APPLICATION_ERROR_APPLICATION_LOAD', $name), 500);
 481              }
 482  
 483              static::$instances[$name]->loadIdentity(Factory::getUser());
 484          }
 485  
 486          return static::$instances[$name];
 487      }
 488  
 489      /**
 490       * Returns the application \JMenu object.
 491       *
 492       * @param   string  $name     The name of the application/client.
 493       * @param   array   $options  An optional associative array of configuration settings.
 494       *
 495       * @return  AbstractMenu
 496       *
 497       * @since   3.2
 498       */
 499      public function getMenu($name = null, $options = array())
 500      {
 501          if (!isset($name)) {
 502              $name = $this->getName();
 503          }
 504  
 505          // Inject this application object into the \JMenu tree if one isn't already specified
 506          if (!isset($options['app'])) {
 507              $options['app'] = $this;
 508          }
 509  
 510          if (array_key_exists($name, $this->menus)) {
 511              return $this->menus[$name];
 512          }
 513  
 514          if ($this->menuFactory === null) {
 515              @trigger_error('Menu factory must be set in 5.0', E_USER_DEPRECATED);
 516              $this->menuFactory = $this->getContainer()->get(MenuFactoryInterface::class);
 517          }
 518  
 519          $this->menus[$name] = $this->menuFactory->createMenu($name, $options);
 520  
 521          // Make sure the abstract menu has the instance too, is needed for BC and will be removed with version 5
 522          AbstractMenu::$instances[$name] = $this->menus[$name];
 523  
 524          return $this->menus[$name];
 525      }
 526  
 527      /**
 528       * Get the system message queue.
 529       *
 530       * @param   boolean  $clear  Clear the messages currently attached to the application object
 531       *
 532       * @return  array  The system message queue.
 533       *
 534       * @since   3.2
 535       */
 536      public function getMessageQueue($clear = false)
 537      {
 538          // For empty queue, if messages exists in the session, enqueue them.
 539          if (!\count($this->messageQueue)) {
 540              $sessionQueue = $this->getSession()->get('application.queue', []);
 541  
 542              if ($sessionQueue) {
 543                  $this->messageQueue = $sessionQueue;
 544                  $this->getSession()->set('application.queue', []);
 545              }
 546          }
 547  
 548          $messageQueue = $this->messageQueue;
 549  
 550          if ($clear) {
 551              $this->messageQueue = array();
 552          }
 553  
 554          return $messageQueue;
 555      }
 556  
 557      /**
 558       * Gets the name of the current running application.
 559       *
 560       * @return  string  The name of the application.
 561       *
 562       * @since   3.2
 563       */
 564      public function getName()
 565      {
 566          return $this->name;
 567      }
 568  
 569      /**
 570       * Returns the application Pathway object.
 571       *
 572       * @return  Pathway
 573       *
 574       * @since   3.2
 575       */
 576      public function getPathway()
 577      {
 578          if (!$this->pathway) {
 579              $resourceName = ucfirst($this->getName()) . 'Pathway';
 580  
 581              if (!$this->getContainer()->has($resourceName)) {
 582                  throw new \RuntimeException(
 583                      Text::sprintf('JLIB_APPLICATION_ERROR_PATHWAY_LOAD', $this->getName()),
 584                      500
 585                  );
 586              }
 587  
 588              $this->pathway = $this->getContainer()->get($resourceName);
 589          }
 590  
 591          return $this->pathway;
 592      }
 593  
 594      /**
 595       * Returns the application Router object.
 596       *
 597       * @param   string  $name     The name of the application.
 598       * @param   array   $options  An optional associative array of configuration settings.
 599       *
 600       * @return  Router
 601       *
 602       * @since      3.2
 603       *
 604       * @deprecated 5.0 Inject the router or load it from the dependency injection container
 605       */
 606      public static function getRouter($name = null, array $options = array())
 607      {
 608          $app = Factory::getApplication();
 609  
 610          if (!isset($name)) {
 611              $name = $app->getName();
 612          }
 613  
 614          $options['mode'] = $app->get('sef');
 615  
 616          return Router::getInstance($name, $options);
 617      }
 618  
 619      /**
 620       * Gets the name of the current template.
 621       *
 622       * @param   boolean  $params  An optional associative array of configuration settings
 623       *
 624       * @return  mixed  System is the fallback.
 625       *
 626       * @since   3.2
 627       */
 628      public function getTemplate($params = false)
 629      {
 630          if ($params) {
 631              $template = new \stdClass();
 632  
 633              $template->template    = 'system';
 634              $template->params      = new Registry();
 635              $template->inheritable = 0;
 636              $template->parent      = '';
 637  
 638              return $template;
 639          }
 640  
 641          return 'system';
 642      }
 643  
 644      /**
 645       * Gets a user state.
 646       *
 647       * @param   string  $key      The path of the state.
 648       * @param   mixed   $default  Optional default value, returned if the internal value is null.
 649       *
 650       * @return  mixed  The user state or null.
 651       *
 652       * @since   3.2
 653       */
 654      public function getUserState($key, $default = null)
 655      {
 656          $registry = $this->getSession()->get('registry');
 657  
 658          if ($registry !== null) {
 659              return $registry->get($key, $default);
 660          }
 661  
 662          return $default;
 663      }
 664  
 665      /**
 666       * Gets the value of a user state variable.
 667       *
 668       * @param   string  $key      The key of the user state variable.
 669       * @param   string  $request  The name of the variable passed in a request.
 670       * @param   string  $default  The default value for the variable if not found. Optional.
 671       * @param   string  $type     Filter for the variable, for valid values see {@link InputFilter::clean()}. Optional.
 672       *
 673       * @return  mixed  The request user state.
 674       *
 675       * @since   3.2
 676       */
 677      public function getUserStateFromRequest($key, $request, $default = null, $type = 'none')
 678      {
 679          $cur_state = $this->getUserState($key, $default);
 680          $new_state = $this->input->get($request, null, $type);
 681  
 682          if ($new_state === null) {
 683              return $cur_state;
 684          }
 685  
 686          // Save the new value only if it was set in this request.
 687          $this->setUserState($key, $new_state);
 688  
 689          return $new_state;
 690      }
 691  
 692      /**
 693       * Initialise the application.
 694       *
 695       * @param   array  $options  An optional associative array of configuration settings.
 696       *
 697       * @return  void
 698       *
 699       * @since   3.2
 700       */
 701      protected function initialiseApp($options = array())
 702      {
 703          // Check that we were given a language in the array (since by default may be blank).
 704          if (isset($options['language'])) {
 705              $this->set('language', $options['language']);
 706          }
 707  
 708          // Build our language object
 709          $lang = Language::getInstance($this->get('language'), $this->get('debug_lang'));
 710  
 711          // Load the language to the API
 712          $this->loadLanguage($lang);
 713  
 714          // Register the language object with Factory
 715          Factory::$language = $this->getLanguage();
 716  
 717          // Load the library language files
 718          $this->loadLibraryLanguage();
 719  
 720          // Set user specific editor.
 721          $user = Factory::getUser();
 722          $editor = $user->getParam('editor', $this->get('editor'));
 723  
 724          if (!PluginHelper::isEnabled('editors', $editor)) {
 725              $editor = $this->get('editor');
 726  
 727              if (!PluginHelper::isEnabled('editors', $editor)) {
 728                  $editor = 'none';
 729              }
 730          }
 731  
 732          $this->set('editor', $editor);
 733  
 734          // Load the behaviour plugins
 735          PluginHelper::importPlugin('behaviour');
 736  
 737          // Trigger the onAfterInitialise event.
 738          PluginHelper::importPlugin('system');
 739          $this->triggerEvent('onAfterInitialise');
 740      }
 741  
 742      /**
 743       * Checks if HTTPS is forced in the client configuration.
 744       *
 745       * @param   integer  $clientId  An optional client id (defaults to current application client).
 746       *
 747       * @return  boolean  True if is forced for the client, false otherwise.
 748       *
 749       * @since   3.7.3
 750       */
 751      public function isHttpsForced($clientId = null)
 752      {
 753          $clientId = (int) ($clientId !== null ? $clientId : $this->getClientId());
 754          $forceSsl = (int) $this->get('force_ssl');
 755  
 756          if ($clientId === 0 && $forceSsl === 2) {
 757              return true;
 758          }
 759  
 760          if ($clientId === 1 && $forceSsl >= 1) {
 761              return true;
 762          }
 763  
 764          return false;
 765      }
 766  
 767      /**
 768       * Check the client interface by name.
 769       *
 770       * @param   string  $identifier  String identifier for the application interface
 771       *
 772       * @return  boolean  True if this application is of the given type client interface.
 773       *
 774       * @since   3.7.0
 775       */
 776      public function isClient($identifier)
 777      {
 778          return $this->getName() === $identifier;
 779      }
 780  
 781      /**
 782       * Load the library language files for the application
 783       *
 784       * @return  void
 785       *
 786       * @since   3.6.3
 787       */
 788      protected function loadLibraryLanguage()
 789      {
 790          $this->getLanguage()->load('lib_joomla', JPATH_ADMINISTRATOR);
 791      }
 792  
 793      /**
 794       * Login authentication function.
 795       *
 796       * Username and encoded password are passed the onUserLogin event which
 797       * is responsible for the user validation. A successful validation updates
 798       * the current session record with the user's details.
 799       *
 800       * Username and encoded password are sent as credentials (along with other
 801       * possibilities) to each observer (authentication plugin) for user
 802       * validation.  Successful validation will update the current session with
 803       * the user details.
 804       *
 805       * @param   array  $credentials  Array('username' => string, 'password' => string)
 806       * @param   array  $options      Array('remember' => boolean)
 807       *
 808       * @return  boolean|\Exception  True on success, false if failed or silent handling is configured, or a \Exception object on authentication error.
 809       *
 810       * @since   3.2
 811       */
 812      public function login($credentials, $options = array())
 813      {
 814          // Get the global Authentication object.
 815          $authenticate = Authentication::getInstance($this->authenticationPluginType);
 816          $response = $authenticate->authenticate($credentials, $options);
 817  
 818          // Import the user plugin group.
 819          PluginHelper::importPlugin('user');
 820  
 821          if ($response->status === Authentication::STATUS_SUCCESS) {
 822              /*
 823               * Validate that the user should be able to login (different to being authenticated).
 824               * This permits authentication plugins blocking the user.
 825               */
 826              $authorisations = $authenticate->authorise($response, $options);
 827              $denied_states = Authentication::STATUS_EXPIRED | Authentication::STATUS_DENIED;
 828  
 829              foreach ($authorisations as $authorisation) {
 830                  if ((int) $authorisation->status & $denied_states) {
 831                      // Trigger onUserAuthorisationFailure Event.
 832                      $this->triggerEvent('onUserAuthorisationFailure', array((array) $authorisation));
 833  
 834                      // If silent is set, just return false.
 835                      if (isset($options['silent']) && $options['silent']) {
 836                          return false;
 837                      }
 838  
 839                      // Return the error.
 840                      switch ($authorisation->status) {
 841                          case Authentication::STATUS_EXPIRED:
 842                              Factory::getApplication()->enqueueMessage(Text::_('JLIB_LOGIN_EXPIRED'), 'error');
 843  
 844                              return false;
 845  
 846                          case Authentication::STATUS_DENIED:
 847                              Factory::getApplication()->enqueueMessage(Text::_('JLIB_LOGIN_DENIED'), 'error');
 848  
 849                              return false;
 850  
 851                          default:
 852                              Factory::getApplication()->enqueueMessage(Text::_('JLIB_LOGIN_AUTHORISATION'), 'error');
 853  
 854                              return false;
 855                      }
 856                  }
 857              }
 858  
 859              // OK, the credentials are authenticated and user is authorised.  Let's fire the onLogin event.
 860              $results = $this->triggerEvent('onUserLogin', array((array) $response, $options));
 861  
 862              /*
 863               * If any of the user plugins did not successfully complete the login routine
 864               * then the whole method fails.
 865               *
 866               * Any errors raised should be done in the plugin as this provides the ability
 867               * to provide much more information about why the routine may have failed.
 868               */
 869              $user = Factory::getUser();
 870  
 871              if ($response->type === 'Cookie') {
 872                  $user->set('cookieLogin', true);
 873              }
 874  
 875              if (\in_array(false, $results, true) == false) {
 876                  $options['user'] = $user;
 877                  $options['responseType'] = $response->type;
 878  
 879                  // The user is successfully logged in. Run the after login events
 880                  $this->triggerEvent('onUserAfterLogin', array($options));
 881  
 882                  return true;
 883              }
 884          }
 885  
 886          // Trigger onUserLoginFailure Event.
 887          $this->triggerEvent('onUserLoginFailure', array((array) $response));
 888  
 889          // If silent is set, just return false.
 890          if (isset($options['silent']) && $options['silent']) {
 891              return false;
 892          }
 893  
 894          // If status is success, any error will have been raised by the user plugin
 895          if ($response->status !== Authentication::STATUS_SUCCESS) {
 896              $this->getLogger()->warning($response->error_message, array('category' => 'jerror'));
 897          }
 898  
 899          return false;
 900      }
 901  
 902      /**
 903       * Logout authentication function.
 904       *
 905       * Passed the current user information to the onUserLogout event and reverts the current
 906       * session record back to 'anonymous' parameters.
 907       * If any of the authentication plugins did not successfully complete
 908       * the logout routine then the whole method fails. Any errors raised
 909       * should be done in the plugin as this provides the ability to give
 910       * much more information about why the routine may have failed.
 911       *
 912       * @param   integer  $userid   The user to load - Can be an integer or string - If string, it is converted to ID automatically
 913       * @param   array    $options  Array('clientid' => array of client id's)
 914       *
 915       * @return  boolean  True on success
 916       *
 917       * @since   3.2
 918       */
 919      public function logout($userid = null, $options = array())
 920      {
 921          // Get a user object from the Application.
 922          $user = Factory::getUser($userid);
 923  
 924          // Build the credentials array.
 925          $parameters['username'] = $user->get('username');
 926          $parameters['id'] = $user->get('id');
 927  
 928          // Set clientid in the options array if it hasn't been set already and shared sessions are not enabled.
 929          if (!$this->get('shared_session', '0') && !isset($options['clientid'])) {
 930              $options['clientid'] = $this->getClientId();
 931          }
 932  
 933          // Import the user plugin group.
 934          PluginHelper::importPlugin('user');
 935  
 936          // OK, the credentials are built. Lets fire the onLogout event.
 937          $results = $this->triggerEvent('onUserLogout', array($parameters, $options));
 938  
 939          // Check if any of the plugins failed. If none did, success.
 940          if (!\in_array(false, $results, true)) {
 941              $options['username'] = $user->get('username');
 942              $this->triggerEvent('onUserAfterLogout', array($options));
 943  
 944              return true;
 945          }
 946  
 947          // Trigger onUserLogoutFailure Event.
 948          $this->triggerEvent('onUserLogoutFailure', array($parameters));
 949  
 950          return false;
 951      }
 952  
 953      /**
 954       * Redirect to another URL.
 955       *
 956       * If the headers have not been sent the redirect will be accomplished using a "301 Moved Permanently"
 957       * or "303 See Other" code in the header pointing to the new location. If the headers have already been
 958       * sent this will be accomplished using a JavaScript statement.
 959       *
 960       * @param   string   $url     The URL to redirect to. Can only be http/https URL
 961       * @param   integer  $status  The HTTP 1.1 status code to be provided. 303 is assumed by default.
 962       *
 963       * @return  void
 964       *
 965       * @since   3.2
 966       */
 967      public function redirect($url, $status = 303)
 968      {
 969          // Persist messages if they exist.
 970          if (\count($this->messageQueue)) {
 971              $this->getSession()->set('application.queue', $this->messageQueue);
 972          }
 973  
 974          // Hand over processing to the parent now
 975          parent::redirect($url, $status);
 976      }
 977  
 978      /**
 979       * Rendering is the process of pushing the document buffers into the template
 980       * placeholders, retrieving data from the document and pushing it into
 981       * the application response buffer.
 982       *
 983       * @return  void
 984       *
 985       * @since   3.2
 986       */
 987      protected function render()
 988      {
 989          // Setup the document options.
 990          $this->docOptions['template']         = $this->get('theme');
 991          $this->docOptions['file']             = $this->get('themeFile', 'index.php');
 992          $this->docOptions['params']           = $this->get('themeParams');
 993          $this->docOptions['csp_nonce']        = $this->get('csp_nonce');
 994          $this->docOptions['templateInherits'] = $this->get('themeInherits');
 995  
 996          if ($this->get('themes.base')) {
 997              $this->docOptions['directory'] = $this->get('themes.base');
 998          } else {
 999              // Fall back to constants.
1000              $this->docOptions['directory'] = \defined('JPATH_THEMES') ? JPATH_THEMES : (\defined('JPATH_BASE') ? JPATH_BASE : __DIR__) . '/themes';
1001          }
1002  
1003          // Parse the document.
1004          $this->document->parse($this->docOptions);
1005  
1006          // Trigger the onBeforeRender event.
1007          PluginHelper::importPlugin('system');
1008          $this->triggerEvent('onBeforeRender');
1009  
1010          $caching = false;
1011  
1012          if ($this->isClient('site') && $this->get('caching') && $this->get('caching', 2) == 2 && !Factory::getUser()->get('id')) {
1013              $caching = true;
1014          }
1015  
1016          // Render the document.
1017          $data = $this->document->render($caching, $this->docOptions);
1018  
1019          // Set the application output data.
1020          $this->setBody($data);
1021  
1022          // Trigger the onAfterRender event.
1023          $this->triggerEvent('onAfterRender');
1024  
1025          // Mark afterRender in the profiler.
1026          JDEBUG ? $this->profiler->mark('afterRender') : null;
1027      }
1028  
1029      /**
1030       * Route the application.
1031       *
1032       * Routing is the process of examining the request environment to determine which
1033       * component should receive the request. The component optional parameters
1034       * are then set in the request object to be processed when the application is being
1035       * dispatched.
1036       *
1037       * @return     void
1038       *
1039       * @since      3.2
1040       *
1041       * @deprecated 5.0 Implement the route functionality in the extending class, this here will be removed without replacement
1042       */
1043      protected function route()
1044      {
1045          // Get the full request URI.
1046          $uri = clone Uri::getInstance();
1047  
1048          $router = static::getRouter();
1049          $result = $router->parse($uri, true);
1050  
1051          $active = $this->getMenu()->getActive();
1052  
1053          if (
1054              $active !== null
1055              && $active->type === 'alias'
1056              && $active->getParams()->get('alias_redirect')
1057              && \in_array($this->input->getMethod(), array('GET', 'HEAD'), true)
1058          ) {
1059              $item = $this->getMenu()->getItem($active->getParams()->get('aliasoptions'));
1060  
1061              if ($item !== null) {
1062                  $oldUri = clone Uri::getInstance();
1063  
1064                  if ($oldUri->getVar('Itemid') == $active->id) {
1065                      $oldUri->setVar('Itemid', $item->id);
1066                  }
1067  
1068                  $base = Uri::base(true);
1069                  $oldPath = StringHelper::strtolower(substr($oldUri->getPath(), \strlen($base) + 1));
1070                  $activePathPrefix = StringHelper::strtolower($active->route);
1071  
1072                  $position = strpos($oldPath, $activePathPrefix);
1073  
1074                  if ($position !== false) {
1075                      $oldUri->setPath($base . '/' . substr_replace($oldPath, $item->route, $position, \strlen($activePathPrefix)));
1076  
1077                      $this->setHeader('Expires', 'Wed, 17 Aug 2005 00:00:00 GMT', true);
1078                      $this->setHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT', true);
1079                      $this->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate', false);
1080                      $this->sendHeaders();
1081  
1082                      $this->redirect((string) $oldUri, 301);
1083                  }
1084              }
1085          }
1086  
1087          foreach ($result as $key => $value) {
1088              $this->input->def($key, $value);
1089          }
1090  
1091          // Trigger the onAfterRoute event.
1092          PluginHelper::importPlugin('system');
1093          $this->triggerEvent('onAfterRoute');
1094      }
1095  
1096      /**
1097       * Sets the value of a user state variable.
1098       *
1099       * @param   string  $key    The path of the state.
1100       * @param   mixed   $value  The value of the variable.
1101       *
1102       * @return  mixed|void  The previous state, if one existed.
1103       *
1104       * @since   3.2
1105       */
1106      public function setUserState($key, $value)
1107      {
1108          $session  = $this->getSession();
1109          $registry = $session->get('registry');
1110  
1111          if ($registry !== null) {
1112              return $registry->set($key, $value);
1113          }
1114      }
1115  
1116      /**
1117       * Sends all headers prior to returning the string
1118       *
1119       * @param   boolean  $compress  If true, compress the data
1120       *
1121       * @return  string
1122       *
1123       * @since   3.2
1124       */
1125      public function toString($compress = false)
1126      {
1127          // Don't compress something if the server is going to do it anyway. Waste of time.
1128          if ($compress && !ini_get('zlib.output_compression') && ini_get('output_handler') !== 'ob_gzhandler') {
1129              $this->compress();
1130          }
1131  
1132          if ($this->allowCache() === false) {
1133              $this->setHeader('Cache-Control', 'no-cache', false);
1134          }
1135  
1136          $this->sendHeaders();
1137  
1138          return $this->getBody();
1139      }
1140  
1141      /**
1142       * Method to determine a hash for anti-spoofing variable names
1143       *
1144       * @param   boolean  $forceNew  If true, force a new token to be created
1145       *
1146       * @return  string  Hashed var name
1147       *
1148       * @since   4.0.0
1149       */
1150      public function getFormToken($forceNew = false)
1151      {
1152          /** @var Session $session */
1153          $session = $this->getSession();
1154  
1155          return $session->getFormToken($forceNew);
1156      }
1157  
1158      /**
1159       * Checks for a form token in the request.
1160       *
1161       * Use in conjunction with getFormToken.
1162       *
1163       * @param   string  $method  The request method in which to look for the token key.
1164       *
1165       * @return  boolean  True if found and valid, false otherwise.
1166       *
1167       * @since   4.0.0
1168       */
1169      public function checkToken($method = 'post')
1170      {
1171          /** @var Session $session */
1172          $session = $this->getSession();
1173  
1174          return $session->checkToken($method);
1175      }
1176  
1177      /**
1178       * Flag if the application instance is a CLI or web based application.
1179       *
1180       * Helper function, you should use the native PHP functions to detect if it is a CLI application.
1181       *
1182       * @return  boolean
1183       *
1184       * @since       4.0.0
1185       * @deprecated  5.0  Will be removed without replacements
1186       */
1187      public function isCli()
1188      {
1189          return false;
1190      }
1191  
1192      /**
1193       * No longer used
1194       *
1195       * @return  boolean
1196       *
1197       * @since   4.0.0
1198       *
1199       * @throws \Exception
1200       * @deprecated 4.2.0  Will be removed in 5.0 without replacement.
1201       */
1202      protected function isTwoFactorAuthenticationRequired(): bool
1203      {
1204          return false;
1205      }
1206  
1207      /**
1208       * No longer used
1209       *
1210       * @return  boolean
1211       *
1212       * @since   4.0.0
1213       *
1214       * @throws \Exception
1215       * @deprecated 4.2.0  Will be removed in 5.0 without replacement.
1216       */
1217      private function hasUserConfiguredTwoFactorAuthentication(): bool
1218      {
1219          return false;
1220      }
1221  
1222      /**
1223       * Setup logging functionality.
1224       *
1225       * @return void
1226       *
1227       * @since   4.0.0
1228       */
1229      private function setupLogging(): void
1230      {
1231          // Add InMemory logger that will collect all log entries to allow to display them later by extensions
1232          if ($this->get('debug')) {
1233              Log::addLogger(['logger' => 'inmemory']);
1234          }
1235  
1236          // Log the deprecated API.
1237          if ($this->get('log_deprecated')) {
1238              Log::addLogger(['text_file' => 'deprecated.php'], Log::ALL, ['deprecated']);
1239          }
1240  
1241          // We only log errors unless Site Debug is enabled
1242          $logLevels = Log::ERROR | Log::CRITICAL | Log::ALERT | Log::EMERGENCY;
1243  
1244          if ($this->get('debug')) {
1245              $logLevels = Log::ALL;
1246          }
1247  
1248          Log::addLogger(['text_file' => 'joomla_core_errors.php'], $logLevels, ['system']);
1249  
1250          // Log everything (except deprecated APIs, these are logged separately with the option above).
1251          if ($this->get('log_everything')) {
1252              Log::addLogger(['text_file' => 'everything.php'], Log::ALL, ['deprecated', 'deprecation-notes', 'databasequery'], true);
1253          }
1254  
1255          if ($this->get('log_categories')) {
1256              $priority = 0;
1257  
1258              foreach ($this->get('log_priorities', ['all']) as $p) {
1259                  $const = '\\Joomla\\CMS\\Log\\Log::' . strtoupper($p);
1260  
1261                  if (defined($const)) {
1262                      $priority |= constant($const);
1263                  }
1264              }
1265  
1266              // Split into an array at any character other than alphabet, numbers, _, ., or -
1267              $categories = preg_split('/[^\w.-]+/', $this->get('log_categories', ''), -1, PREG_SPLIT_NO_EMPTY);
1268              $mode       = (bool) $this->get('log_category_mode', false);
1269  
1270              if (!$categories) {
1271                  return;
1272              }
1273  
1274              Log::addLogger(['text_file' => 'custom-logging.php'], $priority, $categories, $mode);
1275          }
1276      }
1277  
1278      /**
1279       * Sets the internal menu factory.
1280       *
1281       * @param  MenuFactoryInterface  $menuFactory  The menu factory
1282       *
1283       * @return void
1284       *
1285       * @since  4.2.0
1286       */
1287      public function setMenuFactory(MenuFactoryInterface $menuFactory): void
1288      {
1289          $this->menuFactory = $menuFactory;
1290      }
1291  }


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