Completed
Push — fix/56 ( 07c17d...0aa823 )
by Tyler
02:08
created

Notifier::getMessageViaView()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
ccs 0
cts 11
cp 0
rs 9.7998
cc 3
nc 2
nop 1
crap 12
1
<?php
2
3
namespace Tylercd100\LERN\Components;
4
5
use Auth;
6
use Exception;
7
use Illuminate\Support\Facades\Input;
8
use Monolog\Handler\HandlerInterface;
9
use Monolog\Logger;
10
use Request;
11
use Tylercd100\LERN\Exceptions\NotifierFailedException;
12
use Tylercd100\Notify\Drivers\FromConfig as Notify;
13
use View;
14
15
class Notifier extends Component
16
{
17
    protected $config;
18
    protected $log;
19
    protected $messageCb;
20
    protected $subjectCb;
21
    protected $contextCb;
22
23
    /**
24
     * @var array
25
     */
26
    protected $absolutelyDontHandle = [
27
        \Tylercd100\LERN\Exceptions\NotifierFailedException::class,
28
    ];
29
30
    /**
31
     * You can provide a Monolog Logger instance to use in the constructor
32
     * @param Logger|null $log Logger instance to use
33
     */
34 33
    public function __construct(Logger $log = null)
35
    {
36 33
        if ($log === null) {
37 33
            $log = new Logger(config('lern.notify.channel'));
38
        }
39
40 33
        $this->config = config('lern.notify');
41 33
        $this->log = $log;
42 33
    }
43
44
    /**
45
     * Transforms a value into a closure that returns itself when called
46
     * @param  callable|string $cb The value that you want to wrap in a closure
47
     * @return callable
48
     */
49
    private function wrapValueInClosure($cb)
50
    {
51
        if (is_callable($cb)) {
52
            return $cb;
53
        } else {
54
            return function () use ($cb) { return $cb; };
55
        }
56
    }
57
58
    /**
59
     * Set a string or a closure to be called that will generate the message body for the notification
60
     * @param callable|string $cb A closure or string that will be set for the message
61
     * @return $this
62
     */
63
    public function setMessage($cb)
64
    {
65
        $this->messageCb = $this->wrapValueInClosure($cb);
66
        return $this;
67
    }
68
69
    /**
70
     * Returns the result of the message closure
71
     * @param  Exception $e The Exception instance that you want to build the message around
72
     * @return string       The message string
73
     */
74
    public function getMessage(Exception $e)
75
    {
76
        $msg = $this->getMessageViaView($e);
77
78
        if ($msg === false) {
79
            $msg = $this->getMessageViaCallback($e);
80
        }
81
82
        if ($msg === false) {
83
            $msg = $this->getMessageViaDefault($e);
84
        }
85
        
86
        return $msg;
87
    }
88
89
    /**
90
     * Gets a basic Exception message
91
     * @param  Exception $e The Exception instance that you want to build the message around
92
     * @return String       Returns the message string
93
     */
94
    public function getMessageViaDefault(Exception $e)
95
    {
96
        $msg = get_class($e)." was thrown! \n".$e->getMessage();
97
        if ($this->config['includeExceptionStackTrace'] === true) {
98
            $msg .= "\n\n".$e->getTraceAsString();
99
        }
100
        return $msg;
101
    }
102
103
    /**
104
     * Gets the Exception message using a callback if it is set
105
     * @param  Exception    $e The Exception instance that you want to build the message around
106
     * @return String|false    Returns the message string or false
107
     */
108
    public function getMessageViaCallback(Exception $e)
109
    {
110
        if (is_callable($this->messageCb)) {
111
            return $this->messageCb->__invoke($e);
112
        }
113
        return false;
114
    }
115
116
    /**
117
     * Gets the Exception message using a Laravel view file
118
     * @param  Exception    $e The Exception instance that you want to build the message around
119
     * @return String|false    Returns the message string or false
120
     */
121
    public function getMessageViaView(Exception $e)
122
    {
123
        $path = @$this->config["view"];
124
        if (!empty($path) && View::exists($path)) {
125
            return View::make($path, [
126
                "exception" => $e,
127
                "url" => Request::url(),
128
                "method" => Request::method(),
129
                "input" => Input::all(),
130
                "user" => Auth::user(),
131
            ])->render();
132
        }
133
        return false;
134
    }
135
136
    /**
137
     * Set a string or a closure to be called that will generate the subject line for the notification
138
     * @param callable|string $cb A closure or string that will be set for the subject line
139
     * @return $this
140
     */
141
    public function setSubject($cb)
142
    {
143
        $this->subjectCb = $this->wrapValueInClosure($cb);
144
        return $this;
145
    }
146
147
    /**
148
     * Returns the result of the subject closure
149
     * @param  Exception $e The Exception instance that you want to build the subject around
150
     * @return string       The subject string
151
     */
152
    public function getSubject(Exception $e)
153
    {
154
        if (is_callable($this->subjectCb)) {
155
            return $this->subjectCb->__invoke($e);
156
        } else {
157
            return get_class($e);
158
        }
159
    }
160
161
    /**
162
     * Set an array or a closure to be called that will generate the context array for the notification
163
     * @param callable|array $cb A closure or array that will be set for the context
164
     * @return $this
165
     */
166
    public function setContext($cb)
167
    {
168
        $this->contextCb = $this->wrapValueInClosure($cb);
169
        return $this;
170
    }
171
172
    /**
173
     * Returns the result of the context closure
174
     * @param  Exception $e The Exception instance that you want to build the context around
175
     * @return array        The context array
176
     */
177
    public function getContext(Exception $e, $context = [])
178
    {
179
        //This needs a better solution. How do I set specific context needs for different drivers?
180
        if (in_array('pushover', $this->config['drivers'])) {
181
            $context['sound'] = $this->config['pushover']['sound'];
182
        }
183
184
        // Call the callback or return the default
185
        if (is_callable($this->contextCb)) {
186
            return $this->contextCb->__invoke($e, $context);
187
        } else {
188
            return $context;
189
        }
190
    }
191
192
    /**
193
     * Get the log level
194
     * @return string 
195
     */
196 3
    public function getLogLevel()
197
    {
198 3
        return $this->config['log_level'];
199
    }
200
201
    /**
202
     * Set the log level
203
     * @param string $level The log level
204
     * @return \Tylercd100\LERN\LERN
205
     */
206 3
    public function setLogLevel($level)
207
    {
208 3
        $this->config['log_level'] = $level;
209 3
        return $this;
210
    }
211
212
    /**
213
     * Pushes on another Monolog Handler
214
     * @param  HandlerInterface $handler The handler instance to add on
215
     * @return Notifier                  Returns this
216
     */
217
    public function pushHandler(HandlerInterface $handler)
218
    {
219
        $this->log->pushHandler($handler);
220
        return $this;
221
    }
222
223
    /**
224
     * Triggers the Monolog Logger instance to log an error to all handlers
225
     * @param  Exception $e The exception to use
226
     * @param  array $context Additional information that you would like to pass to Monolog
227
     * @return bool
228
     * @throws NotifierFailedException
229
     */
230
    public function send(Exception $e, array $context = [])
231
    {
232
        if ($this->shouldntHandle($e)) {
233
            return false;
234
        }
235
236
        $message = $this->getMessage($e);
237
        $subject = $this->getSubject($e);
238
        $context = $this->getContext($e, $context);
239
240
        try {
241
            $notify = new Notify($this->config, $this->log, $subject);
242
243
            $level = (array_key_exists('log_level', $this->config) && !empty($this->config['log_level']))
244
                ? $this->config['log_level']
245
                : 'critical';
246
247
            $notify->{$level}($message, $context);
248
249
            return true;
250
        } catch (Exception $e) {
251
            $code = (is_int($e->getCode()) ? $e->getCode() : 0);
252
            throw new NotifierFailedException($e->getMessage(), $code, $e);
253
        }
254
    }
255
}
256