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