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