10c5eb5e2SMichael Große<?php 20c5eb5e2SMichael Große 30c5eb5e2SMichael Große 40c5eb5e2SMichael Großenamespace dokuwiki\Debug; 50c5eb5e2SMichael Große 68553d24dSAndreas Gohruse dokuwiki\Extension\Event; 7e1d9dcc8SAndreas Gohruse dokuwiki\Extension\EventHandler; 80ecde6ceSAndreas Gohruse dokuwiki\Logger; 90c5eb5e2SMichael Große 100c5eb5e2SMichael Großeclass DebugHelper 110c5eb5e2SMichael Große{ 1274981a4eSAndreas Gohr protected const INFO_DEPRECATION_LOG_EVENT = 'INFO_DEPRECATION_LOG'; 130c5eb5e2SMichael Große 140c5eb5e2SMichael Große /** 1525edeecaSAndreas Gohr * Check if deprecation messages shall be handled 1625edeecaSAndreas Gohr * 1725edeecaSAndreas Gohr * This is either because its logging is not disabled or a deprecation handler was registered 1825edeecaSAndreas Gohr * 1925edeecaSAndreas Gohr * @return bool 2025edeecaSAndreas Gohr */ 2125edeecaSAndreas Gohr public static function isEnabled() 2225edeecaSAndreas Gohr { 2325edeecaSAndreas Gohr /** @var EventHandler $EVENT_HANDLER */ 2425edeecaSAndreas Gohr global $EVENT_HANDLER; 2525edeecaSAndreas Gohr if ( 2625edeecaSAndreas Gohr !Logger::getInstance(Logger::LOG_DEPRECATED)->isLogging() && 271490c177SAndreas Gohr (!$EVENT_HANDLER instanceof EventHandler || !$EVENT_HANDLER->hasHandlerForEvent('INFO_DEPRECATION_LOG')) 2825edeecaSAndreas Gohr ) { 2925edeecaSAndreas Gohr // avoid any work if no one cares 3025edeecaSAndreas Gohr return false; 3125edeecaSAndreas Gohr } 3225edeecaSAndreas Gohr return true; 3325edeecaSAndreas Gohr } 3425edeecaSAndreas Gohr 3525edeecaSAndreas Gohr /** 360c5eb5e2SMichael Große * Log accesses to deprecated fucntions to the debug log 370c5eb5e2SMichael Große * 380c5eb5e2SMichael Große * @param string $alternative (optional) The function or method that should be used instead 390c5eb5e2SMichael Große * @param int $callerOffset (optional) How far the deprecated method is removed from this one 40e4aa0139SAndreas Gohr * @param string $thing (optional) The deprecated thing, defaults to the calling method 410c5eb5e2SMichael Große * @triggers \dokuwiki\Debug::INFO_DEPRECATION_LOG_EVENT 420c5eb5e2SMichael Große */ 43e4aa0139SAndreas Gohr public static function dbgDeprecatedFunction($alternative = '', $callerOffset = 1, $thing = '') 440c5eb5e2SMichael Große { 4525edeecaSAndreas Gohr if (!self::isEnabled()) return; 460c5eb5e2SMichael Große 470c5eb5e2SMichael Große $backtrace = debug_backtrace(); 481490c177SAndreas Gohr for ($i = 0; $i < $callerOffset; ++$i) { 49c0ece86aSAndreas Gohr if(count($backtrace) > 1) array_shift($backtrace); 500c5eb5e2SMichael Große } 510c5eb5e2SMichael Große 521490c177SAndreas Gohr [$self, $call] = $backtrace; 530c5eb5e2SMichael Große 540c5eb5e2SMichael Große self::triggerDeprecationEvent( 550c5eb5e2SMichael Große $backtrace, 560c5eb5e2SMichael Große $alternative, 57*615810c5SAndreas Gohr self::formatCall($self), 58*615810c5SAndreas Gohr self::formatCall($call), 59c243774dSAndreas Gohr $self['file'] ?? $call['file'] ?? '', 60c243774dSAndreas Gohr $self['line'] ?? $call['line'] ?? 0 610c5eb5e2SMichael Große ); 620c5eb5e2SMichael Große } 630c5eb5e2SMichael Große 640c5eb5e2SMichael Große /** 65*615810c5SAndreas Gohr * Format the given backtrace info into a proper function/method call string 66*615810c5SAndreas Gohr * @param array $call 67*615810c5SAndreas Gohr * @return string 68*615810c5SAndreas Gohr */ 69*615810c5SAndreas Gohr protected static function formatCall($call) 70*615810c5SAndreas Gohr { 71*615810c5SAndreas Gohr $thing = ''; 72*615810c5SAndreas Gohr if(!empty($call['class'])) { 73*615810c5SAndreas Gohr $thing .= $call['class'] . '::'; 74*615810c5SAndreas Gohr } 75*615810c5SAndreas Gohr $thing .= $call['function'] . '()'; 76*615810c5SAndreas Gohr return trim($thing, ':'); 77*615810c5SAndreas Gohr } 78*615810c5SAndreas Gohr 79*615810c5SAndreas Gohr /** 800c5eb5e2SMichael Große * This marks logs a deprecation warning for a property that should no longer be used 810c5eb5e2SMichael Große * 820c5eb5e2SMichael Große * This is usually called withing a magic getter or setter. 830c5eb5e2SMichael Große * For logging deprecated functions or methods see dbgDeprecatedFunction() 840c5eb5e2SMichael Große * 850c5eb5e2SMichael Große * @param string $class The class with the deprecated property 860c5eb5e2SMichael Große * @param string $propertyName The name of the deprecated property 870c5eb5e2SMichael Große * 880c5eb5e2SMichael Große * @triggers \dokuwiki\Debug::INFO_DEPRECATION_LOG_EVENT 890c5eb5e2SMichael Große */ 900c5eb5e2SMichael Große public static function dbgDeprecatedProperty($class, $propertyName) 910c5eb5e2SMichael Große { 9225edeecaSAndreas Gohr if (!self::isEnabled()) return; 930c5eb5e2SMichael Große 940c5eb5e2SMichael Große $backtrace = debug_backtrace(); 950c5eb5e2SMichael Große array_shift($backtrace); 960c5eb5e2SMichael Große $call = $backtrace[1]; 970c5eb5e2SMichael Große $caller = trim($call['class'] . '::' . $call['function'] . '()', ':'); 980c5eb5e2SMichael Große $qualifiedName = $class . '::$' . $propertyName; 990c5eb5e2SMichael Große self::triggerDeprecationEvent( 1000c5eb5e2SMichael Große $backtrace, 1010c5eb5e2SMichael Große '', 1020c5eb5e2SMichael Große $qualifiedName, 1030c5eb5e2SMichael Große $caller, 1040c5eb5e2SMichael Große $backtrace[0]['file'], 1050c5eb5e2SMichael Große $backtrace[0]['line'] 1060c5eb5e2SMichael Große ); 1070c5eb5e2SMichael Große } 1080c5eb5e2SMichael Große 1090c5eb5e2SMichael Große /** 1101b008e87SMichael Große * Trigger a custom deprecation event 1111b008e87SMichael Große * 1121b008e87SMichael Große * Usually dbgDeprecatedFunction() or dbgDeprecatedProperty() should be used instead. 1131b008e87SMichael Große * This method is intended only for those situation where they are not applicable. 1141b008e87SMichael Große * 1151b008e87SMichael Große * @param string $alternative 1161b008e87SMichael Große * @param string $deprecatedThing 1171b008e87SMichael Große * @param string $caller 1181b008e87SMichael Große * @param string $file 1191b008e87SMichael Große * @param int $line 1201b008e87SMichael Große * @param int $callerOffset How many lines should be removed from the beginning of the backtrace 1211b008e87SMichael Große */ 1221b008e87SMichael Große public static function dbgCustomDeprecationEvent( 1231b008e87SMichael Große $alternative, 1241b008e87SMichael Große $deprecatedThing, 1251b008e87SMichael Große $caller, 1261b008e87SMichael Große $file, 1271b008e87SMichael Große $line, 1281b008e87SMichael Große $callerOffset = 1 129d868eb89SAndreas Gohr ) { 13025edeecaSAndreas Gohr if (!self::isEnabled()) return; 1311b008e87SMichael Große 1321b008e87SMichael Große $backtrace = array_slice(debug_backtrace(), $callerOffset); 1331b008e87SMichael Große 1341b008e87SMichael Große self::triggerDeprecationEvent( 1351b008e87SMichael Große $backtrace, 1361b008e87SMichael Große $alternative, 1371b008e87SMichael Große $deprecatedThing, 1381b008e87SMichael Große $caller, 1391b008e87SMichael Große $file, 1401b008e87SMichael Große $line 1411b008e87SMichael Große ); 1421b008e87SMichael Große 1431b008e87SMichael Große } 1441b008e87SMichael Große 1451b008e87SMichael Große /** 1460c5eb5e2SMichael Große * @param array $backtrace 1470c5eb5e2SMichael Große * @param string $alternative 1480c5eb5e2SMichael Große * @param string $deprecatedThing 1490c5eb5e2SMichael Große * @param string $caller 1500c5eb5e2SMichael Große * @param string $file 1510c5eb5e2SMichael Große * @param int $line 1520c5eb5e2SMichael Große */ 1530c5eb5e2SMichael Große private static function triggerDeprecationEvent( 1540c5eb5e2SMichael Große array $backtrace, 1550c5eb5e2SMichael Große $alternative, 1560c5eb5e2SMichael Große $deprecatedThing, 1570c5eb5e2SMichael Große $caller, 1580c5eb5e2SMichael Große $file, 1590c5eb5e2SMichael Große $line 160d868eb89SAndreas Gohr ) { 1610c5eb5e2SMichael Große $data = [ 1620c5eb5e2SMichael Große 'trace' => $backtrace, 1630c5eb5e2SMichael Große 'alternative' => $alternative, 1640c5eb5e2SMichael Große 'called' => $deprecatedThing, 1650c5eb5e2SMichael Große 'caller' => $caller, 1660c5eb5e2SMichael Große 'file' => $file, 1670c5eb5e2SMichael Große 'line' => $line, 1680c5eb5e2SMichael Große ]; 1698553d24dSAndreas Gohr $event = new Event(self::INFO_DEPRECATION_LOG_EVENT, $data); 1700c5eb5e2SMichael Große if ($event->advise_before()) { 1710c5eb5e2SMichael Große $msg = $event->data['called'] . ' is deprecated. It was called from '; 1720c5eb5e2SMichael Große $msg .= $event->data['caller'] . ' in ' . $event->data['file'] . ':' . $event->data['line']; 1730c5eb5e2SMichael Große if ($event->data['alternative']) { 1740c5eb5e2SMichael Große $msg .= ' ' . $event->data['alternative'] . ' should be used instead!'; 1750c5eb5e2SMichael Große } 1760ecde6ceSAndreas Gohr Logger::getInstance(Logger::LOG_DEPRECATED)->log($msg); 1770c5eb5e2SMichael Große } 1780c5eb5e2SMichael Große $event->advise_after(); 1790c5eb5e2SMichael Große } 1800c5eb5e2SMichael Große} 181