Completed
Pull Request — master (#13)
by
unknown
01:03
created

Whoops_Run_Composite::pushHandler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
namespace Rarst\wps;
3
4
use Whoops\Exception\ErrorException;
5
use Whoops\Exception\Inspector;
6
use Whoops\Run;
7
use Whoops\Util\SystemFacade;
8
9
/**
10
 * This class will show Errors and Warnings only if they are coming from
11
 * Specific Plugin
12
 */
13
class Whoops_Run_Composite {
14
15
    /**
16
     * @var SystemFacade
17
     */
18
    private $system;
19
    
20
    /**
21
     * @var Run
22
     */
23
    private $run;
24
    
25
    private $skipAllNoticesAndWarnings = false;
26
27
    private $watchSpecificPlugins = [];
28
29
    private $watchSpecificThemes = [];
30
31
    public function __construct(SystemFacade $system = null)
32
    {
33
        $this->system = $system ?: new SystemFacade;
34
        $this->run = new Run($this->system);
35
    }
36
37
    public function register() {
38
        class_exists("\\Whoops\\Exception\\ErrorException");
39
        class_exists("\\Whoops\\Exception\\FrameCollection");
40
        class_exists("\\Whoops\\Exception\\Frame");
41
        class_exists("\\Whoops\\Exception\\Inspector");
42
43
        $this->system->setErrorHandler([$this, Run::ERROR_HANDLER]);
44
        $this->system->setExceptionHandler([$this->run, Run::EXCEPTION_HANDLER]);
45
        $this->system->registerShutdownFunction([$this->run, Run::SHUTDOWN_HANDLER]);
46
    }
47
48
    public function unregister() {
49
        $this->system->restoreExceptionHandler();
50
        $this->system->restoreErrorHandler();
51
    }
52
53
    public function pushHandler($handler) {
54
        $this->run->pushHandler($handler);
55
    }
56
57
    public function skipAllNoticesAndWarnings() {
58
        $this->skipAllNoticesAndWarnings = true;
59
    }
60
61
    public function watchSpecificPlugins($plugins) {
62
        $this->watchSpecificPlugins = $plugins;
63
    }
64
65
    public function watchSpecificThemes($themes) {
66
        $this->watchSpecificThemes = $themes;
67
    }
68
69
    /**
70
     * Silence particular errors in particular files
71
     * @param  array|string $patterns List or a single regex pattern to match
72
     * @param  int          $levels   Defaults to E_STRICT | E_DEPRECATED
73
     * @return Run
74
     * @see https://maximivanov.github.io/php-error-reporting-calculator/
75
     */
76
    public function silenceErrorsInPaths($patterns, $levels = 10240) {
77
        $this->run->silenceErrorsInPaths($patterns, $levels);
78
    }
79
80
    /**
81
     * Converts generic PHP errors to \ErrorException
82
     * instances, before passing them off to be handled.
83
     *
84
     * This method MUST be compatible with set_error_handler.
85
     *
86
     * @param int    $level
87
     * @param string $message
88
     * @param string $file
89
     * @param int    $line
90
     *
91
     * @return bool
92
     * @throws ErrorException
93
     */
94
    public function handleError($level, $message, $file = null, $line = null) {
95
96
        // Handle all fatals, exceptions etc.
97
        if(in_array(
98
            $level, 
99
            [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR]
100
        )) {
101
            $this->run->handleError($level, $message, $file, $line);
102
            return false;
103
        }
104
105
        // If All Notices and Warnings should be skipped, then short-circuit
106
        // error handler.
107
        if($this->skipAllNoticesAndWarnings) {
108
            return false;
109
        }
110
111
        // Watch for all plugins and Themes
112
        if( empty($this->watchSpecificPlugins) && empty($this->watchSpecificThemes ) ) {
113
            $this->run->handleError($level, $message, $file, $line);
114
            return false;
115
        }
116
117
        $watchablePlugins = empty($this->watchSpecificPlugins) ? [] : array_map(function($pluginBaseFolder){
118
            return 'plugins/' . $pluginBaseFolder;
119
        }, $this->watchSpecificPlugins);
120
121
        $watchableThemes = empty($this->watchSpecificThemes) ? [] : array_map(function($themeBaseFolder){
122
            return 'themes/' . $themeBaseFolder;
123
        }, $this->watchSpecificThemes);
124
125
        $directoriesToWatchFor = array_merge($watchablePlugins, $watchableThemes);
126
        $errorBelongsToWatchCriteria = false;
127
        
128
        // We are creating an exception object because Inspector Class needs it.
129
        $exception = new ErrorException($message, /*code*/ $level, /*severity*/ $level, $file, $line);
130
        $frames = (new Inspector($exception))->getFrames();
0 ignored issues
show
Documentation introduced by
$exception is of type object<Whoops\Exception\ErrorException>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
131
        foreach( $frames as $frame ) {
132
            foreach($directoriesToWatchFor as $directory) {
133
                if (strpos($frame->getFile(), $directory) !== false) {
134
                    $errorBelongsToWatchCriteria = true;
135
                    break 2;
136
                }
137
            }
138
        }
139
140
        if($errorBelongsToWatchCriteria) {
141
            $this->run->handleError($level, $message, $file, $line);
142
        }
143
144
        return false;
145
    }
146
}