[ Index ]

PHP Cross Reference of YOURLS

title

Body

[close]

/includes/Database/ -> Logger.php (source)

   1  <?php
   2  
   3  /**
   4   * Custom logger for YOURLS that logs debug messages and queries.
   5   *
   6   * Based on \Aura\Sql\Profiler\MemoryLogger
   7   *
   8   * @since 1.7.10
   9   */
  10  
  11  namespace YOURLS\Database;
  12  
  13  use Psr\Log\AbstractLogger;
  14  
  15  class Logger extends AbstractLogger {
  16      /**
  17       * Log messages.
  18       *
  19       * @var array
  20       */
  21      protected $messages = [];
  22  
  23      /**
  24       * Logs a message.
  25       *
  26       * @param string  $level    The log level (ie type of message)
  27       * @param string  $message  The log message.
  28       * @param array   $context  Data to interpolate into the message.
  29       *
  30       * The logger receives the following:
  31       *
  32       * From yourls_debug("something went wrong") :
  33       *    $level   : string 'debug'
  34       *    $message : string 'something went wrong'
  35       *    $context : array()
  36       * See yourls_debug() in includes/functions-debug.php
  37       *
  38       * From a query that triggers the internal logging of Aura SQL :
  39       *    $level   : string 'query'
  40       *    $message : string '{function} ({duration} seconds): {statement} {backtrace}'
  41       *               (which is the default $logFormat from Aura\Sql\Profiler\Profiler), we're not using it)
  42       *    $context : array(
  43       *               'function' => string 'perform'
  44       *               'duration' => float 0.0025360584259033
  45       *               'statement' => string 'SELECT `keyword`,`url` FROM `yourls_url` WHERE `url` LIKE (:url)'
  46       *               'values' => array('url' => '%rss%')
  47       *               )
  48       * See finish() in Aura\Sql\Profiler\Profiler
  49       *
  50       * @return void
  51       */
  52      public function log($level, string|\Stringable $message, array $context = []): void {
  53          // if it's an internal SQL query, format the message, otherwise store a string
  54          if($level === 'query') {
  55              // Get the real function name that called the query (not just "perform")
  56              $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 4);
  57              $context['function'] = $backtrace[3]['function'] ?? 'perform';
  58              $this->messages[] = sprintf(
  59                  'SQL %s: %s (%s s)',
  60                  $context['function'],
  61                  $this->pretty_format($context['statement'], $context['values']),
  62                  number_format($context['duration'], 5)
  63              );
  64          } else {
  65              $this->messages[] = (string)$message;
  66          }
  67      }
  68  
  69      /**
  70       * Returns the logged messages.
  71       *
  72       * @return array
  73       */
  74      public function getMessages() {
  75          return $this->messages;
  76      }
  77  
  78      /**
  79       * Format PDO statement with bind/values replacement
  80       *
  81       * This replaces PDO binds such as 'key_name = :name' with corresponding array values, eg array('name'=>'some value')
  82       * This is merely a cosmetic replacement to allow for readability: the result WILL NOT be valid SQL! (eg no proper quotes)
  83       *
  84       * @since  1.7.3
  85       * @param  string $statement  SQL query with PDO style named placeholders
  86       * @param  array  $values     Optional array of values corresponding to placeholders
  87       * @return string             Readable SQL query with placeholders replaced
  88       */
  89      public function pretty_format($statement, array $values = array() ) {
  90          if (!$values) {
  91              return $statement;
  92          }
  93  
  94          return preg_replace_callback(
  95              '/:([^\s;)]*)/',
  96  
  97              /**
  98               * @param string $matches
  99               */
 100              function ($matches) use ($values) {
 101                  $replacement = isset( $values[$matches[1]] ) ? $values[$matches[1]] : '';
 102                  if(is_array($replacement)) {
 103                      $replacement = implode(",", $replacement);
 104                  }
 105                  return "'$replacement'";
 106              },
 107              $statement
 108          );
 109      }
 110  
 111  }


Generated: Wed Apr 8 05:10:41 2026 Cross-referenced by PHPXref 0.7.1