xref: /dokuwiki/inc/Debug/DebugHelper.php (revision f216edae611a9a1677577709a8b2e33f231b6a7d)
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($self['class'] . '::' . $self['function'] . '()', ':'),
45            trim($call['class'] . '::' . $call['function'] . '()', ':'),
46            $call['file'],
47            $call['line']
48        );
49    }
50
51    /**
52     * This marks logs a deprecation warning for a property that should no longer be used
53     *
54     * This is usually called withing a magic getter or setter.
55     * For logging deprecated functions or methods see dbgDeprecatedFunction()
56     *
57     * @param string $class        The class with the deprecated property
58     * @param string $propertyName The name of the deprecated property
59     *
60     * @triggers \dokuwiki\Debug::INFO_DEPRECATION_LOG_EVENT
61     */
62    public static function dbgDeprecatedProperty($class, $propertyName)
63    {
64        global $conf;
65        global $EVENT_HANDLER;
66        if (!$conf['allowdebug'] && !$EVENT_HANDLER->hasHandlerForEvent(self::INFO_DEPRECATION_LOG_EVENT)) {
67            // avoid any work if no one cares
68            return;
69        }
70
71        $backtrace = debug_backtrace();
72        array_shift($backtrace);
73        $call = $backtrace[1];
74        $caller = trim($call['class'] . '::' . $call['function'] . '()', ':');
75        $qualifiedName = $class . '::$' . $propertyName;
76        self::triggerDeprecationEvent(
77            $backtrace,
78            '',
79            $qualifiedName,
80            $caller,
81            $backtrace[0]['file'],
82            $backtrace[0]['line']
83        );
84    }
85
86    /**
87     * Trigger a custom deprecation event
88     *
89     * Usually dbgDeprecatedFunction() or dbgDeprecatedProperty() should be used instead.
90     * This method is intended only for those situation where they are not applicable.
91     *
92     * @param string $alternative
93     * @param string $deprecatedThing
94     * @param string $caller
95     * @param string $file
96     * @param int    $line
97     * @param int    $callerOffset How many lines should be removed from the beginning of the backtrace
98     */
99    public static function dbgCustomDeprecationEvent(
100        $alternative,
101        $deprecatedThing,
102        $caller,
103        $file,
104        $line,
105        $callerOffset = 1
106    ) {
107        global $conf;
108        /** @var EventHandler $EVENT_HANDLER */
109        global $EVENT_HANDLER;
110        if (!$conf['allowdebug'] && !$EVENT_HANDLER->hasHandlerForEvent(self::INFO_DEPRECATION_LOG_EVENT)) {
111            // avoid any work if no one cares
112            return;
113        }
114
115        $backtrace = array_slice(debug_backtrace(), $callerOffset);
116
117        self::triggerDeprecationEvent(
118            $backtrace,
119            $alternative,
120            $deprecatedThing,
121            $caller,
122            $file,
123            $line
124        );
125
126    }
127
128    /**
129     * @param array  $backtrace
130     * @param string $alternative
131     * @param string $deprecatedThing
132     * @param string $caller
133     * @param string $file
134     * @param int    $line
135     */
136    private static function triggerDeprecationEvent(
137        array $backtrace,
138        $alternative,
139        $deprecatedThing,
140        $caller,
141        $file,
142        $line
143    ) {
144        $data = [
145            'trace' => $backtrace,
146            'alternative' => $alternative,
147            'called' => $deprecatedThing,
148            'caller' => $caller,
149            'file' => $file,
150            'line' => $line,
151        ];
152        $event = new Doku_Event(self::INFO_DEPRECATION_LOG_EVENT, $data);
153        if ($event->advise_before()) {
154            $msg = $event->data['called'] . ' is deprecated. It was called from ';
155            $msg .= $event->data['caller'] . ' in ' . $event->data['file'] . ':' . $event->data['line'];
156            if ($event->data['alternative']) {
157                $msg .= ' ' . $event->data['alternative'] . ' should be used instead!';
158            }
159            dbglog($msg);
160        }
161        $event->advise_after();
162    }
163}
164