Completed
Push — master ( d5fca1...7488d9 )
by Bjørn
03:06
created

WarningLoggerTrait::reenableWarnings()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace WebPConvert\Convert\Converters\BaseTraits;
4
5
/**
6
 * Trait for handling warnings (by logging them)
7
 *
8
 * This trait is currently only used in the AbstractConverter class. It has been extracted into a
9
 * trait in order to bundle the methods concerning options.
10
 *
11
 * @package    WebPConvert
12
 * @author     Bjørn Rosell <[email protected]>
13
 * @since      Class available since Release 2.0.0
14
 */
15
trait WarningLoggerTrait
16
{
17
    abstract protected function logLn($msg, $style = '');
18
19
    /** @var string|array|null  Previous error handler (stored in order to be able pass warnings on) */
20
    private $previousErrorHandler;
21
22
    /** @var boolean  Suppress ALL warnings? (both from log and from bubbling up) */
23
    private $suppressWarnings;
24
25
    /** @var int  Count number of warnings */
26
    private $warningCounter;
27
28
    /**
29
     *  Handle warnings and notices during conversion by logging them and passing them on.
30
     *
31
     *  The function is a callback used with "set_error_handler".
32
     *  It is declared public because it needs to be accessible from the point where the warning is triggered.
33
     *
34
     *  @param  integer  $errno
35
     *  @param  string   $errstr
36
     *  @param  string   $errfile
37
     *  @param  integer  $errline
38
     *
39
     *  @return false|null|void
40
     */
41 1
    public function warningHandler($errno, $errstr, $errfile, $errline)
42
    {
43
        /*
44
        We do NOT do the following (even though it is generally recommended):
45
46
        if (!(error_reporting() & $errno)) {
47
            // This error code is not included in error_reporting, so let it fall
48
            // through to the standard PHP error handler
49
            return false;
50
        }
51
52
        - Because we want to log all warnings and errors (also the ones that was suppressed with @)
53
        https://secure.php.net/manual/en/language.operators.errorcontrol.php
54
55
        If we were to decide suppressing the ones with @, I could do this:
56
57
        if (error_reporting() == 0) {
58
            /// @ sign temporary disabled error reporting
59
            return;
60
        }
61
        [https://stackoverflow.com/questions/7380782/error-suppression-operator-and-set-error-handler]
62
63
        However, that would also disable the warnings on systems with error reporting set to E_NONE.
64
        And I really want the conversion log file to contain these warnings on all systems.
65
66
        If it was possible to suppress the warnings with @ without suppressing warnings on systems
67
        with error reporting set to E_NONE, I would do that.
68
        */
69
70 1
        $this->warningCounter++;
71 1
        if ($this->suppressWarnings) {
72
            return;
73
        }
74
75
        $errorTypes = [
76 1
            E_WARNING =>             "Warning",
77 1
            E_NOTICE =>              "Notice",
78 1
            E_STRICT =>              "Strict Notice",
79 1
            E_DEPRECATED =>          "Deprecated",
80 1
            E_USER_DEPRECATED =>     "User Deprecated",
81
82
            /*
83
            The following can never be catched by a custom error handler:
84
            E_PARSE, E_ERROR, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING
85
86
            We do do not currently trigger the following:
87
            E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE
88
89
            But we may want to do that at some point, like this:
90
            trigger_error('Your version of Gd is very old', E_USER_WARNING);
91
            in that case, remember to add them to this array
92
            */
93
        ];
94
95 1
        if (isset($errorTypes[$errno])) {
96 1
            $errType = $errorTypes[$errno];
97
        } else {
98
            $errType = "Unknown error/warning/notice ($errno)";
99
        }
100
101 1
        $msg = $errType . ': ' . $errstr . ' in ' . $errfile . ', line ' . $errline . ', PHP ' . PHP_VERSION .
102 1
            ' (' . PHP_OS . ')';
103 1
        $this->logLn('');
104 1
        $this->logLn($msg, 'italic');
105 1
        $this->logLn('');
106
107 1
        if (!is_null($this->previousErrorHandler)) {
108
            // If previousErrorHandler is this very error handler, exit to avoid recursion
109
            // (this could happen if ::activateWarningLogger() were called twice)
110 1
            if (is_array($this->previousErrorHandler) &&
111 1
                isset($this->previousErrorHandler[0]) &&
112 1
                ($this->previousErrorHandler[0] == $this)
113
            ) {
114
                return false;
115
            } else {
116 1
                return call_user_func($this->previousErrorHandler, $errno, $errstr, $errfile, $errline);
117
            }
118
        } else {
119
            return false;
120
        }
121
    }
122
123
    /**
124
     *  Activate warning logger.
125
     *
126
     *  Sets the error handler and stores the previous so our error handler can bubble up warnings
127
     *
128
     *  @return  void
129
     */
130 12
    protected function activateWarningLogger()
131
    {
132 12
        $this->suppressWarnings = false;
133 12
        $this->warningCounter = 0;
134 12
        $this->previousErrorHandler = set_error_handler(
135 12
            array($this, "warningHandler"),
136 12
            E_WARNING | E_USER_WARNING | E_NOTICE | E_USER_NOTICE
137
        );
138 12
    }
139
140
    /**
141
     *  Deactivate warning logger.
142
     *
143
     *  Restores the previous error handler.
144
     *
145
     *  @return  void
146
     */
147 3
    protected function deactivateWarningLogger()
148
    {
149 3
        restore_error_handler();
150 3
    }
151
152
    protected function disableWarningsTemporarily()
153
    {
154
        $this->suppressWarnings = true;
155
    }
156
157
    protected function reenableWarnings()
158
    {
159
        $this->suppressWarnings = false;
160
    }
161
162
    protected function getWarningCount()
163
    {
164
        return $this->warningCounter;
165
    }
166
167
    protected function resetWarningCount()
168
    {
169
        $this->warningCounter = 0;
170
    }
171
}
172