xref: /dokuwiki/inc/Debug/DebugHelper.php (revision 25edeeca14acaa318ea8f0009bd3a8f20921558f)
10c5eb5e2SMichael Große<?php
20c5eb5e2SMichael Große
30c5eb5e2SMichael Große
40c5eb5e2SMichael Großenamespace dokuwiki\Debug;
50c5eb5e2SMichael Große
60c5eb5e2SMichael Großeuse Doku_Event;
7e1d9dcc8SAndreas Gohruse dokuwiki\Extension\EventHandler;
80ecde6ceSAndreas Gohruse dokuwiki\Logger;
90c5eb5e2SMichael Große
100c5eb5e2SMichael Großeclass DebugHelper
110c5eb5e2SMichael Große{
120c5eb5e2SMichael Große    const INFO_DEPRECATION_LOG_EVENT = 'INFO_DEPRECATION_LOG';
130c5eb5e2SMichael Große
140c5eb5e2SMichael Große    /**
15*25edeecaSAndreas Gohr     * Check if deprecation messages shall be handled
16*25edeecaSAndreas Gohr     *
17*25edeecaSAndreas Gohr     * This is either because its logging is not disabled or a deprecation handler was registered
18*25edeecaSAndreas Gohr     *
19*25edeecaSAndreas Gohr     * @return bool
20*25edeecaSAndreas Gohr     */
21*25edeecaSAndreas Gohr    public static function isEnabled()
22*25edeecaSAndreas Gohr    {
23*25edeecaSAndreas Gohr        /** @var EventHandler $EVENT_HANDLER */
24*25edeecaSAndreas Gohr        global $EVENT_HANDLER;
25*25edeecaSAndreas Gohr        if (
26*25edeecaSAndreas Gohr            !Logger::getInstance(Logger::LOG_DEPRECATED)->isLogging() &&
27*25edeecaSAndreas Gohr            ($EVENT_HANDLER === null || !$EVENT_HANDLER->hasHandlerForEvent('INFO_DEPRECATION_LOG'))
28*25edeecaSAndreas Gohr        ) {
29*25edeecaSAndreas Gohr            // avoid any work if no one cares
30*25edeecaSAndreas Gohr            return false;
31*25edeecaSAndreas Gohr        }
32*25edeecaSAndreas Gohr        return true;
33*25edeecaSAndreas Gohr    }
34*25edeecaSAndreas Gohr
35*25edeecaSAndreas 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    {
45*25edeecaSAndreas Gohr        if (!self::isEnabled()) return;
460c5eb5e2SMichael Große
470c5eb5e2SMichael Große        $backtrace = debug_backtrace();
480c5eb5e2SMichael Große        for ($i = 0; $i < $callerOffset; $i += 1) {
490c5eb5e2SMichael Große            array_shift($backtrace);
500c5eb5e2SMichael Große        }
510c5eb5e2SMichael Große
520c5eb5e2SMichael Große        list($self, $call) = $backtrace;
530c5eb5e2SMichael Große
54e4aa0139SAndreas Gohr        if (!$thing) {
55e4aa0139SAndreas Gohr            $thing = trim(
56e4aa0139SAndreas Gohr                (!empty($self['class']) ? ($self['class'] . '::') : '') .
57e4aa0139SAndreas Gohr                $self['function'] . '()', ':');
58e4aa0139SAndreas Gohr        }
59e4aa0139SAndreas Gohr
600c5eb5e2SMichael Große        self::triggerDeprecationEvent(
610c5eb5e2SMichael Große            $backtrace,
620c5eb5e2SMichael Große            $alternative,
63e4aa0139SAndreas Gohr            $thing,
649ced17c4SPhy            trim(
659ced17c4SPhy                (!empty($call['class']) ? ($call['class'] . '::') : '') .
669ced17c4SPhy                $call['function'] . '()', ':'),
675499b0daSAndreas Gohr            $self['file'],
685499b0daSAndreas Gohr            $self['line']
690c5eb5e2SMichael Große        );
700c5eb5e2SMichael Große    }
710c5eb5e2SMichael Große
720c5eb5e2SMichael Große    /**
730c5eb5e2SMichael Große     * This marks logs a deprecation warning for a property that should no longer be used
740c5eb5e2SMichael Große     *
750c5eb5e2SMichael Große     * This is usually called withing a magic getter or setter.
760c5eb5e2SMichael Große     * For logging deprecated functions or methods see dbgDeprecatedFunction()
770c5eb5e2SMichael Große     *
780c5eb5e2SMichael Große     * @param string $class The class with the deprecated property
790c5eb5e2SMichael Große     * @param string $propertyName The name of the deprecated property
800c5eb5e2SMichael Große     *
810c5eb5e2SMichael Große     * @triggers \dokuwiki\Debug::INFO_DEPRECATION_LOG_EVENT
820c5eb5e2SMichael Große     */
830c5eb5e2SMichael Große    public static function dbgDeprecatedProperty($class, $propertyName)
840c5eb5e2SMichael Große    {
85*25edeecaSAndreas Gohr        if (!self::isEnabled()) return;
860c5eb5e2SMichael Große
870c5eb5e2SMichael Große        $backtrace = debug_backtrace();
880c5eb5e2SMichael Große        array_shift($backtrace);
890c5eb5e2SMichael Große        $call = $backtrace[1];
900c5eb5e2SMichael Große        $caller = trim($call['class'] . '::' . $call['function'] . '()', ':');
910c5eb5e2SMichael Große        $qualifiedName = $class . '::$' . $propertyName;
920c5eb5e2SMichael Große        self::triggerDeprecationEvent(
930c5eb5e2SMichael Große            $backtrace,
940c5eb5e2SMichael Große            '',
950c5eb5e2SMichael Große            $qualifiedName,
960c5eb5e2SMichael Große            $caller,
970c5eb5e2SMichael Große            $backtrace[0]['file'],
980c5eb5e2SMichael Große            $backtrace[0]['line']
990c5eb5e2SMichael Große        );
1000c5eb5e2SMichael Große    }
1010c5eb5e2SMichael Große
1020c5eb5e2SMichael Große    /**
1031b008e87SMichael Große     * Trigger a custom deprecation event
1041b008e87SMichael Große     *
1051b008e87SMichael Große     * Usually dbgDeprecatedFunction() or dbgDeprecatedProperty() should be used instead.
1061b008e87SMichael Große     * This method is intended only for those situation where they are not applicable.
1071b008e87SMichael Große     *
1081b008e87SMichael Große     * @param string $alternative
1091b008e87SMichael Große     * @param string $deprecatedThing
1101b008e87SMichael Große     * @param string $caller
1111b008e87SMichael Große     * @param string $file
1121b008e87SMichael Große     * @param int $line
1131b008e87SMichael Große     * @param int $callerOffset How many lines should be removed from the beginning of the backtrace
1141b008e87SMichael Große     */
1151b008e87SMichael Große    public static function dbgCustomDeprecationEvent(
1161b008e87SMichael Große        $alternative,
1171b008e87SMichael Große        $deprecatedThing,
1181b008e87SMichael Große        $caller,
1191b008e87SMichael Große        $file,
1201b008e87SMichael Große        $line,
1211b008e87SMichael Große        $callerOffset = 1
122*25edeecaSAndreas Gohr    )
123*25edeecaSAndreas Gohr    {
124*25edeecaSAndreas Gohr        if (!self::isEnabled()) return;
1251b008e87SMichael Große
1261b008e87SMichael Große        $backtrace = array_slice(debug_backtrace(), $callerOffset);
1271b008e87SMichael Große
1281b008e87SMichael Große        self::triggerDeprecationEvent(
1291b008e87SMichael Große            $backtrace,
1301b008e87SMichael Große            $alternative,
1311b008e87SMichael Große            $deprecatedThing,
1321b008e87SMichael Große            $caller,
1331b008e87SMichael Große            $file,
1341b008e87SMichael Große            $line
1351b008e87SMichael Große        );
1361b008e87SMichael Große
1371b008e87SMichael Große    }
1381b008e87SMichael Große
1391b008e87SMichael Große    /**
1400c5eb5e2SMichael Große     * @param array $backtrace
1410c5eb5e2SMichael Große     * @param string $alternative
1420c5eb5e2SMichael Große     * @param string $deprecatedThing
1430c5eb5e2SMichael Große     * @param string $caller
1440c5eb5e2SMichael Große     * @param string $file
1450c5eb5e2SMichael Große     * @param int $line
1460c5eb5e2SMichael Große     */
1470c5eb5e2SMichael Große    private static function triggerDeprecationEvent(
1480c5eb5e2SMichael Große        array $backtrace,
1490c5eb5e2SMichael Große              $alternative,
1500c5eb5e2SMichael Große              $deprecatedThing,
1510c5eb5e2SMichael Große              $caller,
1520c5eb5e2SMichael Große              $file,
1530c5eb5e2SMichael Große              $line
154*25edeecaSAndreas Gohr    )
155*25edeecaSAndreas Gohr    {
1560c5eb5e2SMichael Große        $data = [
1570c5eb5e2SMichael Große            'trace' => $backtrace,
1580c5eb5e2SMichael Große            'alternative' => $alternative,
1590c5eb5e2SMichael Große            'called' => $deprecatedThing,
1600c5eb5e2SMichael Große            'caller' => $caller,
1610c5eb5e2SMichael Große            'file' => $file,
1620c5eb5e2SMichael Große            'line' => $line,
1630c5eb5e2SMichael Große        ];
1640c5eb5e2SMichael Große        $event = new Doku_Event(self::INFO_DEPRECATION_LOG_EVENT, $data);
1650c5eb5e2SMichael Große        if ($event->advise_before()) {
1660c5eb5e2SMichael Große            $msg = $event->data['called'] . ' is deprecated. It was called from ';
1670c5eb5e2SMichael Große            $msg .= $event->data['caller'] . ' in ' . $event->data['file'] . ':' . $event->data['line'];
1680c5eb5e2SMichael Große            if ($event->data['alternative']) {
1690c5eb5e2SMichael Große                $msg .= ' ' . $event->data['alternative'] . ' should be used instead!';
1700c5eb5e2SMichael Große            }
1710ecde6ceSAndreas Gohr            Logger::getInstance(Logger::LOG_DEPRECATED)->log($msg);
1720c5eb5e2SMichael Große        }
1730c5eb5e2SMichael Große        $event->advise_after();
1740c5eb5e2SMichael Große    }
1750c5eb5e2SMichael Große}
176