[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Log/ -> Log.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright  (C) 2011 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\Log;
  11  
  12  // phpcs:disable PSR1.Files.SideEffects
  13  \defined('JPATH_PLATFORM') or die;
  14  // phpcs:enable PSR1.Files.SideEffects
  15  
  16  /**
  17   * Joomla! Log Class
  18   *
  19   * This class hooks into the global log configuration settings to allow for user configured
  20   * logging events to be sent to where the user wishes them to be sent. On high load sites
  21   * Syslog is probably the best (pure PHP function), then the text file based loggers (CSV, W3c
  22   * or plain Formattedtext) and finally MySQL offers the most features (e.g. rapid searching)
  23   * but will incur a performance hit due to INSERT being issued.
  24   *
  25   * @since  1.7.0
  26   */
  27  class Log
  28  {
  29      /**
  30       * All log priorities.
  31       *
  32       * @var    integer
  33       * @since  1.7.0
  34       */
  35      public const ALL = 30719;
  36  
  37      /**
  38       * The system is unusable.
  39       *
  40       * @var    integer
  41       * @since  1.7.0
  42       */
  43      public const EMERGENCY = 1;
  44  
  45      /**
  46       * Action must be taken immediately.
  47       *
  48       * @var    integer
  49       * @since  1.7.0
  50       */
  51      public const ALERT = 2;
  52  
  53      /**
  54       * Critical conditions.
  55       *
  56       * @var    integer
  57       * @since  1.7.0
  58       */
  59      public const CRITICAL = 4;
  60  
  61      /**
  62       * Error conditions.
  63       *
  64       * @var    integer
  65       * @since  1.7.0
  66       */
  67      public const ERROR = 8;
  68  
  69      /**
  70       * Warning conditions.
  71       *
  72       * @var    integer
  73       * @since  1.7.0
  74       */
  75      public const WARNING = 16;
  76  
  77      /**
  78       * Normal, but significant condition.
  79       *
  80       * @var    integer
  81       * @since  1.7.0
  82       */
  83      public const NOTICE = 32;
  84  
  85      /**
  86       * Informational message.
  87       *
  88       * @var    integer
  89       * @since  1.7.0
  90       */
  91      public const INFO = 64;
  92  
  93      /**
  94       * Debugging message.
  95       *
  96       * @var    integer
  97       * @since  1.7.0
  98       */
  99      public const DEBUG = 128;
 100  
 101      /**
 102       * The global Log instance.
 103       *
 104       * @var    Log
 105       * @since  1.7.0
 106       */
 107      protected static $instance;
 108  
 109      /**
 110       * Container for Logger configurations.
 111       *
 112       * @var    array
 113       * @since  1.7.0
 114       */
 115      protected $configurations = array();
 116  
 117      /**
 118       * Container for Logger objects.
 119       *
 120       * @var    Logger[]
 121       * @since  1.7.0
 122       */
 123      protected $loggers = array();
 124  
 125      /**
 126       * Lookup array for loggers.
 127       *
 128       * @var    array
 129       * @since  1.7.0
 130       */
 131      protected $lookup = array();
 132  
 133      /**
 134       * The registry of available loggers
 135       *
 136       * @var    LoggerRegistry
 137       * @since  4.0.0
 138       */
 139      protected $loggerRegistry;
 140  
 141      /**
 142       * Constructor.
 143       *
 144       * @since   1.7.0
 145       */
 146      protected function __construct()
 147      {
 148          $this->loggerRegistry = new LoggerRegistry();
 149      }
 150  
 151      /**
 152       * Method to add an entry to the log.
 153       *
 154       * @param   mixed    $entry     The LogEntry object to add to the log or the message for a new LogEntry object.
 155       * @param   integer  $priority  Message priority.
 156       * @param   string   $category  Type of entry
 157       * @param   string   $date      Date of entry (defaults to now if not specified or blank)
 158       * @param   array    $context   An optional array with additional message context.
 159       *
 160       * @return  void
 161       *
 162       * @since   1.7.0
 163       */
 164      public static function add($entry, $priority = self::INFO, $category = '', $date = null, array $context = array())
 165      {
 166          // Automatically instantiate the singleton object if not already done.
 167          if (empty(static::$instance)) {
 168              static::setInstance(new static());
 169          }
 170  
 171          // If the entry object isn't a LogEntry object let's make one.
 172          if (!($entry instanceof LogEntry)) {
 173              $entry = new LogEntry((string) $entry, $priority, $category, $date, $context);
 174          }
 175  
 176          static::$instance->addLogEntry($entry);
 177      }
 178  
 179      /**
 180       * Add a logger to the Log instance.  Loggers route log entries to the correct files/systems to be logged.
 181       *
 182       * @param   array    $options     The object configuration array.
 183       * @param   integer  $priorities  Message priority
 184       * @param   array    $categories  Types of entry
 185       * @param   boolean  $exclude     If true, all categories will be logged except those in the $categories array
 186       *
 187       * @return  void
 188       *
 189       * @since   1.7.0
 190       */
 191      public static function addLogger(array $options, $priorities = self::ALL, $categories = array(), $exclude = false)
 192      {
 193          // Automatically instantiate the singleton object if not already done.
 194          if (empty(static::$instance)) {
 195              static::setInstance(new static());
 196          }
 197  
 198          static::$instance->addLoggerInternal($options, $priorities, $categories, $exclude);
 199      }
 200  
 201      /**
 202       * Register a logger to the registry
 203       *
 204       * @param   string   $key      The service key to be registered
 205       * @param   string   $class    The class name of the logger
 206       * @param   boolean  $replace  Flag indicating the service key may replace an existing definition
 207       *
 208       * @return  void
 209       *
 210       * @since   4.0.0
 211       */
 212      public function registerLogger(string $key, string $class, bool $replace = false)
 213      {
 214          // Automatically instantiate the singleton object if not already done.
 215          if (empty(static::$instance)) {
 216              static::setInstance(new static());
 217          }
 218  
 219          static::$instance->loggerRegistry->register($key, $class, $replace);
 220      }
 221  
 222      /**
 223       * Add a logger to the Log instance.  Loggers route log entries to the correct files/systems to be logged.
 224       * This method allows you to extend Log completely.
 225       *
 226       * @param   array    $options     The object configuration array.
 227       * @param   integer  $priorities  Message priority
 228       * @param   array    $categories  Types of entry
 229       * @param   boolean  $exclude     If true, all categories will be logged except those in the $categories array
 230       *
 231       * @return  void
 232       *
 233       * @since   1.7.0
 234       */
 235      protected function addLoggerInternal(array $options, $priorities = self::ALL, $categories = array(), $exclude = false)
 236      {
 237          // The default logger is the formatted text log file.
 238          if (empty($options['logger'])) {
 239              $options['logger'] = 'formattedtext';
 240          }
 241  
 242          $options['logger'] = strtolower($options['logger']);
 243  
 244          // Special case - if a Closure object is sent as the callback (in case of CallbackLogger)
 245          // Closure objects are not serializable so swap it out for a unique id first then back again later
 246          if (isset($options['callback'])) {
 247              if (is_a($options['callback'], 'closure')) {
 248                  $callback = $options['callback'];
 249                  $options['callback'] = spl_object_hash($options['callback']);
 250              } elseif (\is_array($options['callback']) && \count($options['callback']) == 2 && \is_object($options['callback'][0])) {
 251                  $callback = $options['callback'];
 252                  $options['callback'] = spl_object_hash($options['callback'][0]) . '::' . $options['callback'][1];
 253              }
 254          }
 255  
 256          // Generate a unique signature for the Log instance based on its options.
 257          $signature = md5(serialize($options));
 258  
 259          // Now that the options array has been serialized, swap the callback back in
 260          if (isset($callback)) {
 261              $options['callback'] = $callback;
 262          }
 263  
 264          // Register the configuration if it doesn't exist.
 265          if (empty($this->configurations[$signature])) {
 266              $this->configurations[$signature] = $options;
 267          }
 268  
 269          $this->lookup[$signature] = (object) array(
 270              'priorities' => $priorities,
 271              'categories' => array_map('strtolower', (array) $categories),
 272              'exclude' => (bool) $exclude,
 273          );
 274      }
 275  
 276      /**
 277       * Creates a delegated PSR-3 compatible logger from the current singleton instance. This method always returns a new delegated logger.
 278       *
 279       * @return  DelegatingPsrLogger
 280       *
 281       * @since   3.8.0
 282       */
 283      public static function createDelegatedLogger()
 284      {
 285          // Ensure a singleton instance has been created first
 286          if (empty(static::$instance)) {
 287              static::setInstance(new static());
 288          }
 289  
 290          return new DelegatingPsrLogger(static::$instance);
 291      }
 292  
 293      /**
 294       * Returns a reference to the a Log object, only creating it if it doesn't already exist.
 295       * Note: This is principally made available for testing and internal purposes.
 296       *
 297       * @param   Log  $instance  The logging object instance to be used by the static methods.
 298       *
 299       * @return  void
 300       *
 301       * @since   1.7.0
 302       */
 303      public static function setInstance($instance)
 304      {
 305          if (($instance instanceof Log) || $instance === null) {
 306              static::$instance = & $instance;
 307          }
 308      }
 309  
 310      /**
 311       * Method to add an entry to the appropriate loggers.
 312       *
 313       * @param   LogEntry  $entry  The LogEntry object to send to the loggers.
 314       *
 315       * @return  void
 316       *
 317       * @since   1.7.0
 318       * @throws  \RuntimeException
 319       */
 320      protected function addLogEntry(LogEntry $entry)
 321      {
 322          // Find all the appropriate loggers based on priority and category for the entry.
 323          $loggers = $this->findLoggers($entry->priority, $entry->category);
 324  
 325          foreach ((array) $loggers as $signature) {
 326              // Attempt to instantiate the logger object if it doesn't already exist.
 327              if (empty($this->loggers[$signature])) {
 328                  if ($this->loggerRegistry->hasLogger($this->configurations[$signature]['logger'])) {
 329                      $class = $this->loggerRegistry->getLoggerClass($this->configurations[$signature]['logger']);
 330                  } else {
 331                      @trigger_error(
 332                          sprintf(
 333                              'Attempting to automatically resolve loggers to the %s namespace is deprecated as of 4.0 and will be removed in 5.0.'
 334                              . ' Use the logger registry instead.',
 335                              __NAMESPACE__
 336                          ),
 337                          E_USER_DEPRECATED
 338                      );
 339  
 340                      $class = __NAMESPACE__ . '\\Logger\\' . ucfirst($this->configurations[$signature]['logger']) . 'Logger';
 341  
 342                      if (!class_exists($class)) {
 343                          throw new \RuntimeException('Unable to create a Logger instance: ' . $class);
 344                      }
 345                  }
 346  
 347                  $this->loggers[$signature] = new $class($this->configurations[$signature]);
 348              }
 349  
 350              // Add the entry to the logger.
 351              $this->loggers[$signature]->addEntry(clone $entry);
 352          }
 353      }
 354  
 355      /**
 356       * Method to find the loggers to use based on priority and category values.
 357       *
 358       * @param   integer  $priority  Message priority.
 359       * @param   string   $category  Type of entry
 360       *
 361       * @return  array  The array of loggers to use for the given priority and category values.
 362       *
 363       * @since   1.7.0
 364       */
 365      protected function findLoggers($priority, $category)
 366      {
 367          $loggers = array();
 368  
 369          // Sanitize inputs.
 370          $priority = (int) $priority;
 371          $category = strtolower((string) $category);
 372  
 373          // Let's go iterate over the loggers and get all the ones we need.
 374          foreach ((array) $this->lookup as $signature => $rules) {
 375              // Check to make sure the priority matches the logger.
 376              if ($priority & $rules->priorities) {
 377                  if ($rules->exclude) {
 378                      // If either there are no set categories or the category (including the empty case) is not in the list of excluded categories, add this logger.
 379                      if (empty($rules->categories) || !\in_array($category, $rules->categories)) {
 380                          $loggers[] = $signature;
 381                      }
 382                  } else {
 383                      // If either there are no set categories (meaning all) or the specific category is set, add this logger.
 384                      if (empty($rules->categories) || \in_array($category, $rules->categories)) {
 385                          $loggers[] = $signature;
 386                      }
 387                  }
 388              }
 389          }
 390  
 391          return $loggers;
 392      }
 393  }


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