Failed Conditions
Push — master ( 63ec91...ac34b9 )
by Arnold
03:24
created

HandleShutdownError::log()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 1
ccs 0
cts 0
cp 0
nc 1
1
<?php
2
3
namespace Jasny\ErrorHandler;
4
5
/**
6
 * Trait for handling errors on shutdown
7
 */
8
trait HandleShutdownError
9
{
10
    /**
11
     * @var boolean
12
     */
13
    protected $registeredShutdown = false;
14
    
15
    /**
16
     * A string which reserves memory that can be used to log the error in case of an out of memory fatal error
17
     * @var string
18
     */
19
    protected $reservedMemory;
20
    
21
22
    /**
23
     * Run the fatal error callback
24
     * 
25
     * @param \Exception|\Error $error
26
     */
27
    abstract protected function callOnFatalError($error);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
28
29
    /**
30
     * Wrapper method for `error_get_last`
31
     * 
32
     * @return array
33
     */
34
    abstract protected function errorGetLast();
35
    
36
    /**
37
     * Wrapper method for `register_shutdown_function`
38
     * 
39
     * @param callable $callback
40
     */
41
    abstract protected function registerShutdownFunction($callback);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
42
43
    /**
44
     * Log an error or exception
45
     * 
46
     * @param \Exception|\Error $error
47
     */
48
    abstract public function log($error);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
49
50
51
    /**
52
     * Reserve memory for shutdown function in case of out of memory
53
     */
54 32
    protected function reserveMemory()
55
    {
56 32
        $this->reservedMemory = str_repeat(' ', 10 * 1024);
57 32
    }
58
    
59
    /**
60
     * Register the shutdown function
61
     */
62 32
    protected function initShutdownFunction()
63
    {
64 32
        if (!$this->registeredShutdown) {
65 32
            $this->registerShutdownFunction([$this, 'shutdownFunction']) ?: false;
66 32
            $this->registeredShutdown = true;
67
            
68 32
            $this->reserveMemory();
69 16
        }
70 32
    }
71
    
72
    /**
73
     * Called when the script has ends
74
     * @ignore
75
     */
76 16
    public function shutdownFunction()
77
    {
78 16
        $this->reservedMemory = null;
79
        
80 16
        $err = $this->errorGetLast();
81 16
        $unhandled = E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR;
82
        
83 16
        if (!$err || !($err['type'] & $unhandled)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $err of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
84 6
            return;
85
        }
86
        
87 10
        $error = new \ErrorException($err['message'], 0, $err['type'], $err['file'], $err['line']);
88
        
89 10
        if ($err['type'] & $this->logErrorTypes) {
0 ignored issues
show
Bug introduced by
The property logErrorTypes does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
90 4
            $this->log($error);
91 2
        }
92
        
93 10
        $this->callOnFatalError($error);
94 10
    }
95
}
96
97