[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Log/Logger/ -> FormattedtextLogger.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\Logger;
  11  
  12  use Joomla\CMS\Factory;
  13  use Joomla\CMS\Filesystem\File;
  14  use Joomla\CMS\Filesystem\Folder;
  15  use Joomla\CMS\Log\LogEntry;
  16  use Joomla\CMS\Log\Logger;
  17  use Joomla\CMS\Version;
  18  use Joomla\Utilities\IpHelper;
  19  
  20  // phpcs:disable PSR1.Files.SideEffects
  21  \defined('JPATH_PLATFORM') or die;
  22  // phpcs:enable PSR1.Files.SideEffects
  23  
  24  /**
  25   * Joomla! Formatted Text File Log class
  26   *
  27   * This class is designed to use as a base for building formatted text files for output. By
  28   * default it emulates the Syslog style format output. This is a disk based output format.
  29   *
  30   * @since  1.7.0
  31   */
  32  class FormattedtextLogger extends Logger
  33  {
  34      /**
  35       * The format which each entry follows in the log file.
  36       *
  37       * All fields must be named in all caps and be within curly brackets eg. {FOOBAR}.
  38       *
  39       * @var    string
  40       * @since  1.7.0
  41       */
  42      protected $format = '{DATETIME}    {PRIORITY} {CLIENTIP}    {CATEGORY}    {MESSAGE}';
  43  
  44      /**
  45       * The parsed fields from the format string.
  46       *
  47       * @var    array
  48       * @since  1.7.0
  49       */
  50      protected $fields = array();
  51  
  52      /**
  53       * The full filesystem path for the log file.
  54       *
  55       * @var    string
  56       * @since  1.7.0
  57       */
  58      protected $path;
  59  
  60      /**
  61       * If true, all writes will be deferred as long as possible.
  62       * NOTE: Deferred logs may never be written if the application encounters a fatal error.
  63       *
  64       * @var    boolean
  65       * @since  3.9.0
  66       */
  67      protected $defer = false;
  68  
  69      /**
  70       * If deferring, entries will be stored here prior to writing.
  71       *
  72       * @var    array
  73       * @since  3.9.0
  74       */
  75      protected $deferredEntries = array();
  76  
  77      /**
  78       * Constructor.
  79       *
  80       * @param   array  &$options  Log object options.
  81       *
  82       * @since   1.7.0
  83       */
  84      public function __construct(array &$options)
  85      {
  86          // Call the parent constructor.
  87          parent::__construct($options);
  88  
  89          // The name of the text file defaults to 'error.php' if not explicitly given.
  90          if (empty($this->options['text_file'])) {
  91              $this->options['text_file'] = 'error.php';
  92          }
  93  
  94          // The name of the text file path defaults to that which is set in configuration if not explicitly given.
  95          if (empty($this->options['text_file_path'])) {
  96              $this->options['text_file_path'] = Factory::getApplication()->get('log_path', JPATH_ADMINISTRATOR . '/logs');
  97          }
  98  
  99          // False to treat the log file as a php file.
 100          if (empty($this->options['text_file_no_php'])) {
 101              $this->options['text_file_no_php'] = false;
 102          }
 103  
 104          // Build the full path to the log file.
 105          $this->path = $this->options['text_file_path'] . '/' . $this->options['text_file'];
 106  
 107          // Use the default entry format unless explicitly set otherwise.
 108          if (!empty($this->options['text_entry_format'])) {
 109              $this->format = (string) $this->options['text_entry_format'];
 110          }
 111  
 112          // Wait as long as possible before writing logs
 113          if (!empty($this->options['defer'])) {
 114              $this->defer = (bool) $this->options['defer'];
 115          }
 116  
 117          // Build the fields array based on the format string.
 118          $this->parseFields();
 119      }
 120  
 121      /**
 122       * If deferred, write all pending logs.
 123       *
 124       * @since  3.9.0
 125       */
 126      public function __destruct()
 127      {
 128          // Nothing to do
 129          if (!$this->defer || empty($this->deferredEntries)) {
 130              return;
 131          }
 132  
 133          // Initialise the file if not already done.
 134          $this->initFile();
 135  
 136          // Format all lines and write to file.
 137          $lines = array_map(array($this, 'formatLine'), $this->deferredEntries);
 138  
 139          if (!File::append($this->path, implode("\n", $lines) . "\n")) {
 140              throw new \RuntimeException('Cannot write to log file.');
 141          }
 142      }
 143  
 144      /**
 145       * Method to add an entry to the log.
 146       *
 147       * @param   LogEntry  $entry  The log entry object to add to the log.
 148       *
 149       * @return  void
 150       *
 151       * @since   1.7.0
 152       * @throws  \RuntimeException
 153       */
 154      public function addEntry(LogEntry $entry)
 155      {
 156          // Store the entry to be written later.
 157          if ($this->defer) {
 158              $this->deferredEntries[] = $entry;
 159          } else {
 160              // Write it immediately.
 161              // Initialise the file if not already done.
 162              $this->initFile();
 163  
 164              // Write the new entry to the file.
 165              $line = $this->formatLine($entry);
 166              $line .= "\n";
 167  
 168              if (!File::append($this->path, $line)) {
 169                  throw new \RuntimeException('Cannot write to log file.');
 170              }
 171          }
 172      }
 173  
 174      /**
 175       * Format a line for the log file.
 176       *
 177       * @param   LogEntry  $entry  The log entry to format as a string.
 178       *
 179       * @return  String
 180       *
 181       * @since  3.9.0
 182       */
 183      protected function formatLine(LogEntry $entry)
 184      {
 185          // Set some default field values if not already set.
 186          if (!isset($entry->clientIP)) {
 187              $ip = IpHelper::getIp();
 188  
 189              if ($ip !== '') {
 190                  $entry->clientIP = $ip;
 191              }
 192          }
 193  
 194          // If the time field is missing or the date field isn't only the date we need to rework it.
 195          if ((\strlen($entry->date) != 10) || !isset($entry->time)) {
 196              // Get the date and time strings in GMT.
 197              $entry->datetime = $entry->date->toISO8601();
 198              $entry->time = $entry->date->format('H:i:s', false);
 199              $entry->date = $entry->date->format('Y-m-d', false);
 200          }
 201  
 202          // Get a list of all the entry keys and make sure they are upper case.
 203          $tmp = array_change_key_case(get_object_vars($entry), CASE_UPPER);
 204  
 205          // Decode the entry priority into an English string.
 206          $tmp['PRIORITY'] = $this->priorities[$entry->priority];
 207  
 208          // Fill in field data for the line.
 209          $line = $this->format;
 210  
 211          foreach ($this->fields as $field) {
 212              $line = str_replace('{' . $field . '}', $tmp[$field] ?? '-', $line);
 213          }
 214  
 215          return $line;
 216      }
 217  
 218      /**
 219       * Method to generate the log file header.
 220       *
 221       * @return  string  The log file header
 222       *
 223       * @since   1.7.0
 224       */
 225      protected function generateFileHeader()
 226      {
 227          $head = array();
 228  
 229          // Build the log file header.
 230  
 231          // If the no php flag is not set add the php die statement.
 232          if (empty($this->options['text_file_no_php'])) {
 233              // Blank line to prevent information disclose: https://bugs.php.net/bug.php?id=60677
 234              $head[] = '#';
 235              $head[] = '#<?php die(\'Forbidden.\'); ?>';
 236          }
 237  
 238          $head[] = '#Date: ' . gmdate('Y-m-d H:i:s') . ' UTC';
 239          $head[] = '#Software: ' . (new Version())->getLongVersion();
 240          $head[] = '';
 241  
 242          // Prepare the fields string
 243          $head[] = '#Fields: ' . strtolower(str_replace('}', '', str_replace('{', '', $this->format)));
 244          $head[] = '';
 245  
 246          return implode("\n", $head);
 247      }
 248  
 249      /**
 250       * Method to initialise the log file.  This will create the folder path to the file if it doesn't already
 251       * exist and also get a new file header if the file doesn't already exist.  If the file already exists it
 252       * will simply open it for writing.
 253       *
 254       * @return  void
 255       *
 256       * @since   1.7.0
 257       * @throws  \RuntimeException
 258       */
 259      protected function initFile()
 260      {
 261          // We only need to make sure the file exists
 262          if (File::exists($this->path)) {
 263              return;
 264          }
 265  
 266          // Make sure the folder exists in which to create the log file.
 267          Folder::create(\dirname($this->path));
 268  
 269          // Build the log file header.
 270          $head = $this->generateFileHeader();
 271  
 272          if (!File::write($this->path, $head)) {
 273              throw new \RuntimeException('Cannot write to log file.');
 274          }
 275      }
 276  
 277      /**
 278       * Method to parse the format string into an array of fields.
 279       *
 280       * @return  void
 281       *
 282       * @since   1.7.0
 283       */
 284      protected function parseFields()
 285      {
 286          $this->fields = array();
 287          $matches = array();
 288  
 289          // Get all of the available fields in the format string.
 290          preg_match_all('/{(.*?)}/i', $this->format, $matches);
 291  
 292          // Build the parsed fields list based on the found fields.
 293          foreach ($matches[1] as $match) {
 294              $this->fields[] = strtoupper($match);
 295          }
 296      }
 297  }


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