Completed
Push — master ( e447da...9ced17 )
by Henry
03:07
created

DebugHelper::dbgDeprecatedFunction()   B

Complexity

Conditions 7
Paths 3

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 3
nop 2
dl 0
loc 33
rs 8.4586
c 0
b 0
f 0
1
<?php
2
3
4
namespace dokuwiki\Debug;
5
6
use Doku_Event;
7
use dokuwiki\Extension\EventHandler;
8
9
class 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