Completed
Push — master ( 29cfe6...9431fe )
by Yaro
01:55
created

LogEnvelope::getExceptionData()   B

Complexity

Conditions 9
Paths 72

Size

Total Lines 54
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 54
rs 7.255
cc 9
eloc 38
nc 72
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php 
2
3
namespace Yaro\LogEnvelope;
4
5
use Exception;
6
use SplFileObject;
7
use Illuminate\Support\Facades\Log;
8
use Illuminate\Support\Facades\Request;
9
use Illuminate\Support\Facades\Session;
10
use Yaro\LogEnvelope\Drivers\DriverFactory;
11
12
class LogEnvelope
13
{
14
    
15
    private $config = [];
16
    private $cachedConfig = [];
17
18
    public function __construct()
19
    {
20
        $this->config['except'] = config('yaro.log-envelope.except', []);
21
        $this->config['count'] = config('yaro.log-envelope.lines_count', 6);
22
        $this->config['drivers'] = config('yaro.log-envelope.drivers', []);
23
    } // end __construct
24
25
    public function send($exception)
26
    {
27
        $this->onBefore();
28
        
29
        try {
30
            $data = $this->getExceptionData($exception);
31
32
            if ($this->isSkipException($data['class'])) {
33
                return;
34
            }
35
36
            foreach ($this->config['drivers'] as $driver => $driverConfig) {
37
                DriverFactory::create($driver, $data)->setConfig($driverConfig)->send();
38
            }
39
        } catch (Exception $e) {
40
            Log::error($e);
41
        }
42
        
43
        $this->onAfter();
44
    } // end send
45
    
46
    private function onBefore()
47
    {
48
        $this->cachedConfig = [];
49
        $forcedConfig = config('yaro.log-envelope.force_config', []);
50
        foreach ($forcedConfig as $configKey => $configValue) {
51
            $this->cachedConfig[$configKey] = config($configKey);
52
        }
53
        if ($forcedConfig) {
54
            config($forcedConfig);
55
        }
56
    } // end onBefore
57
    
58
    private function onAfter()
59
    {
60
        if ($this->cachedConfig) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cachedConfig 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...
61
            config($this->cachedConfig);
62
        }
63
    } // end onAfter
64
    
65
    public function isSkipException($exceptionClass)
66
    {
67
        return in_array($exceptionClass, $this->config['except']);
68
    } // end isSkipException
69
70
    private function getExceptionData($exception)
0 ignored issues
show
Coding Style introduced by
getExceptionData uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
71
    {
72
        $data = [];
73
74
        $data['host'] = Request::server('HTTP_HOST');
75
        $data['method'] = Request::method();
76
        $data['fullUrl'] = Request::fullUrl();
77
        if (php_sapi_name() === 'cli') {
78
            $data['host'] = parse_url(config('app.url'), PHP_URL_HOST);
79
            $data['method'] = 'CLI';
80
        }
81
        $data['exception'] = $exception->getMessage();
82
        $data['error'] = $exception->getTraceAsString();
83
        $data['line'] = $exception->getLine();
84
        $data['file'] = $exception->getFile();
85
        $data['class'] = get_class($exception);
86
        $data['storage'] = array(
87
            'SERVER'  => Request::server(),
88
            'GET'     => Request::query(),
89
            'POST'    => $_POST,
90
            'FILE'    => Request::file(),
91
            'OLD'     => Request::hasSession() ? Request::old() : [],
92
            'COOKIE'  => Request::cookie(),
93
            'SESSION' => Request::hasSession() ? Session::all() : [],
94
            'HEADERS' => Request::header(),
95
        );
96
97
        $data['storage'] = array_filter($data['storage']);
98
99
        $count = $this->config['count'];
100
        
101
        $data['exegutor']   = [];
102
        $data['file_lines'] = [];
103
        
104
        $file = new SplFileObject($data['file']);
105
        for ($i = -1 * abs($count); $i <= abs($count); $i++) {
106
            list($line, $exegutorLine) = $this->getLineInfo($file, $data['line'], $i);
107
            if (!$line && !$exegutorLine) {
108
                continue;
109
            }
110
            $data['exegutor'][] = $exegutorLine;
111
            $data['file_lines'][$data['line'] + $i] = $line;
112
        }
113
114
        // to make Symfony exception more readable
115
        if ($data['class'] == 'Symfony\Component\Debug\Exception\FatalErrorException') {
116
            preg_match("~^(.+)' in ~", $data['exception'], $matches);
117
            if (isset($matches[1])) {
118
                $data['exception'] = $matches[1];
119
            }
120
        }
121
122
        return $data;
123
    } // end getExceptionData
124
125
    /**
126
     * @param SplFileObject $file
127
     */
128
    private function getLineInfo($file, $line, $i)
129
    {
130
        $currentLine = $line + $i;
131
        // cuz array starts with 0, when file lines start count from 1
132
        $index = $currentLine - 1;
133
        if ($index < 0) {
134
            return [false, false];
135
        }
136
        $file->seek($index);
137
138
        return [
139
            $file->__toString(),
140
            [
141
                'line' => '<span style="color:#aaaaaa;">' . $currentLine . '.</span> ' . SyntaxHighlight::process($file->__toString()),
142
                'wrap_left' => $i ? '' : '<span style="color: #F5F5F5; background-color: #5A3E3E; width: 100%; display: block;">',
143
                'wrap_right' => $i ? '' : '</span>',
144
            ]
145
        ];
146
    } // end getLineInfo
147
148
}
149
150