[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/Debug/ -> DebugHelper.php (source)

   1  <?php
   2  
   3  namespace dokuwiki\Debug;
   4  
   5  use dokuwiki\Extension\Event;
   6  use dokuwiki\Extension\EventHandler;
   7  use dokuwiki\Logger;
   8  
   9  class DebugHelper
  10  {
  11      protected const INFO_DEPRECATION_LOG_EVENT = 'INFO_DEPRECATION_LOG';
  12  
  13      /**
  14       * Check if deprecation messages shall be handled
  15       *
  16       * This is either because its logging is not disabled or a deprecation handler was registered
  17       *
  18       * @return bool
  19       */
  20      public static function isEnabled()
  21      {
  22          /** @var EventHandler $EVENT_HANDLER */
  23          global $EVENT_HANDLER;
  24          if (
  25              !Logger::getInstance(Logger::LOG_DEPRECATED)->isLogging() &&
  26              (!$EVENT_HANDLER instanceof EventHandler || !$EVENT_HANDLER->hasHandlerForEvent('INFO_DEPRECATION_LOG'))
  27          ) {
  28              // avoid any work if no one cares
  29              return false;
  30          }
  31          return true;
  32      }
  33  
  34      /**
  35       * Log accesses to deprecated fucntions to the debug log
  36       *
  37       * @param string $alternative (optional) The function or method that should be used instead
  38       * @param int $callerOffset (optional) How far the deprecated method is removed from this one
  39       * @param string $thing (optional) The deprecated thing, defaults to the calling method
  40       * @triggers \dokuwiki\Debug::INFO_DEPRECATION_LOG_EVENT
  41       */
  42      public static function dbgDeprecatedFunction($alternative = '', $callerOffset = 1, $thing = '')
  43      {
  44          if (!self::isEnabled()) return;
  45  
  46          $backtrace = debug_backtrace();
  47          for ($i = 0; $i < $callerOffset; ++$i) {
  48              if (count($backtrace) > 1) array_shift($backtrace);
  49          }
  50  
  51          [$self, $call] = $backtrace;
  52  
  53          self::triggerDeprecationEvent(
  54              $backtrace,
  55              $alternative,
  56              self::formatCall($self),
  57              self::formatCall($call),
  58              $self['file'] ?? $call['file'] ?? '',
  59              $self['line'] ?? $call['line'] ?? 0
  60          );
  61      }
  62  
  63      /**
  64       * Format the given backtrace info into a proper function/method call string
  65       * @param array $call
  66       * @return string
  67       */
  68      protected static function formatCall($call)
  69      {
  70          $thing = '';
  71          if (!empty($call['class'])) {
  72              $thing .= $call['class'] . '::';
  73          }
  74          $thing .= $call['function'] . '()';
  75          return trim($thing, ':');
  76      }
  77  
  78      /**
  79       * This marks logs a deprecation warning for a property that should no longer be used
  80       *
  81       * This is usually called withing a magic getter or setter.
  82       * For logging deprecated functions or methods see dbgDeprecatedFunction()
  83       *
  84       * @param string $class The class with the deprecated property
  85       * @param string $propertyName The name of the deprecated property
  86       *
  87       * @triggers \dokuwiki\Debug::INFO_DEPRECATION_LOG_EVENT
  88       */
  89      public static function dbgDeprecatedProperty($class, $propertyName)
  90      {
  91          if (!self::isEnabled()) return;
  92  
  93          $backtrace = debug_backtrace();
  94          array_shift($backtrace);
  95          $call = $backtrace[1];
  96          $caller = trim($call['class'] . '::' . $call['function'] . '()', ':');
  97          $qualifiedName = $class . '::$' . $propertyName;
  98          self::triggerDeprecationEvent(
  99              $backtrace,
 100              '',
 101              $qualifiedName,
 102              $caller,
 103              $backtrace[0]['file'],
 104              $backtrace[0]['line']
 105          );
 106      }
 107  
 108      /**
 109       * Trigger a custom deprecation event
 110       *
 111       * Usually dbgDeprecatedFunction() or dbgDeprecatedProperty() should be used instead.
 112       * This method is intended only for those situation where they are not applicable.
 113       *
 114       * @param string $alternative
 115       * @param string $deprecatedThing
 116       * @param string $caller
 117       * @param string $file
 118       * @param int $line
 119       * @param int $callerOffset How many lines should be removed from the beginning of the backtrace
 120       */
 121      public static function dbgCustomDeprecationEvent(
 122          $alternative,
 123          $deprecatedThing,
 124          $caller,
 125          $file,
 126          $line,
 127          $callerOffset = 1
 128      ) {
 129          if (!self::isEnabled()) return;
 130  
 131          $backtrace = array_slice(debug_backtrace(), $callerOffset);
 132  
 133          self::triggerDeprecationEvent(
 134              $backtrace,
 135              $alternative,
 136              $deprecatedThing,
 137              $caller,
 138              $file,
 139              $line
 140          );
 141      }
 142  
 143      /**
 144       * @param array $backtrace
 145       * @param string $alternative
 146       * @param string $deprecatedThing
 147       * @param string $caller
 148       * @param string $file
 149       * @param int $line
 150       */
 151      private static function triggerDeprecationEvent(
 152          array $backtrace,
 153          $alternative,
 154          $deprecatedThing,
 155          $caller,
 156          $file,
 157          $line
 158      ) {
 159          $data = [
 160              'trace' => $backtrace,
 161              'alternative' => $alternative,
 162              'called' => $deprecatedThing,
 163              'caller' => $caller,
 164              'file' => $file,
 165              'line' => $line,
 166          ];
 167          $event = new Event(self::INFO_DEPRECATION_LOG_EVENT, $data);
 168          if ($event->advise_before()) {
 169              $msg = $event->data['called'] . ' is deprecated. It was called from ';
 170              $msg .= $event->data['caller'] . ' in ' . $event->data['file'] . ':' . $event->data['line'];
 171              if ($event->data['alternative']) {
 172                  $msg .= ' ' . $event->data['alternative'] . ' should be used instead!';
 173              }
 174              Logger::getInstance(Logger::LOG_DEPRECATED)->log($msg);
 175          }
 176          $event->advise_after();
 177      }
 178  }