Completed
Push — master ( 9b83ff...105c9d )
by Tyler
02:00
created

Recorder::record()   B

Complexity

Conditions 10
Paths 141

Size

Total Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 10

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 45
ccs 26
cts 26
cp 1
rs 7.06
cc 10
nc 141
nop 1
crap 10

How to fix   Complexity   

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 Tylercd100\LERN\Components;
4
5
use Exception;
6
use Illuminate\Support\Facades\Auth;
7
use Illuminate\Support\Facades\Input;
8
use Illuminate\Support\Facades\Request;
9
use Illuminate\Support\Facades\Cache;
10
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
11
use Tylercd100\LERN\Exceptions\RecorderFailedException;
12
use Tylercd100\LERN\Models\ExceptionModel;
13
use Carbon\Carbon;
14
15
class Recorder extends Component {
16
17
    /**
18
     * @var mixed
19
     */
20
    protected $config = [];
21
22
    /**
23
     * @var array
24
     */
25
    protected $absolutelyDontHandle = [
26
        \Tylercd100\LERN\Exceptions\RecorderFailedException::class,
27
    ];
28
29
    /**
30
     * The constructor
31
     */
32 57
    public function __construct() {
33 57
        $this->config = config('lern.record');
34 57
    }
35
36
    /**
37
     * Records an Exception to the database
38
     * @param  Exception $e The exception you want to record
39
     * @return false|ExceptionModel
40
     * @throws RecorderFailedException
41
     */
42 18
    public function record(Exception $e)
43
    {
44 18
        if ($this->shouldntHandle($e)) {
45 6
            return false;
46
        }
47
48
        $opts = [
49 15
            'class'       => get_class($e),
50 15
            'file'        => $e->getFile(),
51 15
            'line'        => $e->getLine(),
52 15
            'code'        => (is_int($e->getCode()) ? $e->getCode() : 0),
53 15
            'message'     => $e->getMessage(),
54 15
            'trace'       => $e->getTraceAsString(),
55
        ];
56
57 15
        $configDependant = array_keys($this->config['collect']);
58
59
        try {
60 15
            foreach ($configDependant as $key) {
61 15
                if ($this->canCollect($key)) {
62 12
                    $value = $this->collect($key, $e);
63 12
                    if ($value !== null) {
64 15
                        $opts[$key] = $value;
65
                    }
66
                }
67
            }
68
69 15
            $class = config('lern.recorder.model');
70 15
            $class = !empty($class) ? $class : ExceptionModel::class;
71
72 15
            $model = new $class();
73 15
            foreach($opts as $key => $value) {
74 15
                $model->{$key} = $value;
75
            }
76
77 15
            $model->save();
78
79 12
            Cache::forever($this->getCacheKey($e), Carbon::now());
80
81 12
            return $model;
82 3
        } catch (Exception $e) {
83 3
            $code = (is_int($e->getCode()) ? $e->getCode() : 0);
84 3
            throw new RecorderFailedException($e->getMessage(), $code, $e);
85
        }
86
    }
87
88
    /**
89
     * Checks the config to see if you can collect certain information
90
     * @param  string $type the config value you want to check
91
     * @return boolean      
92
     */
93 15
    private function canCollect($type) {
94 15
        if (!empty($this->config) && !empty($this->config['collect']) && !empty($this->config['collect'][$type])) {
95 12
            return $this->config['collect'][$type] === true;
96
        }
97 3
        return false;
98
    }
99
100
    /**
101
     * @param string $key
102
     * @param Exception $e
103
     * @return array|int|null|string
104
     * @throws Exception
105
     */
106 12
    protected function collect($key, Exception $e = null) {
107
        switch ($key) {
108 12
            case 'user_id':
109 12
                return $this->getUserId();
110 12
            case 'method':
111 12
                return $this->getMethod();
112 12
            case 'url':
113 12
                return $this->getUrl();
114 12
            case 'data':
115 12
                return $this->getData();
116 12
            case 'ip':
117
                return $this->getIp();
118 12
            case 'status_code':
119 12
                if ($e === null) {
120
                    return 0;
121
                }
122 12
                return $this->getStatusCode($e);
123
            default:
124
                throw new Exception("{$key} is not supported! Therefore it cannot be collected!");
125
        }
126
    }
127
128
    /**
129
     * Gets the ID of the User that is logged in
130
     * @return integer|null The ID of the User or Null if not logged in
131
     */
132 12
    protected function getUserId() {
133 12
        $user = Auth::user();
134 12
        if (is_object($user) && !empty($user->id)) {
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
135
            return $user->id;
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
136
        } else {
137 12
            return null;
138
        }
139
    }
140
141
    /**
142
     * Gets the Method of the Request
143
     * @return string|null Possible values are null or GET, POST, DELETE, PUT, etc...
144
     */
145 12
    protected function getMethod() {
146 12
        $method = Request::method();
147 12
        if (!empty($method)) {
148 12
            return $method;
149
        } else {
150
            return null;
151
        }
152
    }
153
154
    /**
155
     * Gets the input data of the Request
156
     * @return array|null The Input data or null
157
     */
158 15
    protected function getData() {
159 15
        $data = Input::all();
160 15
        if (is_array($data)) {
161 15
            return $this->excludeKeys($data);
162
        } else {
163
            return null;
164
        }
165
    }
166
167
    /**
168
     * Gets the URL of the Request
169
     * @return string|null Returns a URL string or null
170
     */
171 12
    protected function getUrl() {
172 12
        $url = Request::url();
173 12
        if (is_string($url)) {
174 12
            return $url;
175
        } else {
176
            return null;
177
        }
178
    }
179
180
    /**
181
     * Returns the IP from the request
182
     *
183
     * @return string
184
     */
185
    protected function getIp() {
186
        return Request::ip();
187
    }
188
189
    /**
190
     * Gets the status code of the Exception
191
     * @param  Exception $e The Exception to check
192
     * @return string|integer The status code value
193
     */
194 12
    protected function getStatusCode(Exception $e) {
195 12
        if ($e instanceof HttpExceptionInterface) {
196
            return $e->getStatusCode();
197
        } else {
198 12
            return 0;
199
        }
200
    }
201
202
    /**
203
     * This function will remove all keys from an array recursively as defined in the config file
204
     * @param  array $data The array to remove keys from
205
     * @return void
206
     */
207 21
    protected function excludeKeys(array $data) {
208 21
        $keys = isset($this->config['excludeKeys']) ? $this->config['excludeKeys'] : [];
209 21
        foreach ($data as $key => &$value) {
210 9
            if (in_array($key, $keys)) {
211 9
                unset($data[$key]);
212 9
            } else if (is_array($value)) {
213 9
                $value = $this->excludeKeys($value);
214
            }
215
        }
216
217 21
        return $data;
218
    }
219
}
220