Completed
Pull Request — master (#35)
by Tyler
06:55 queued 04:27
created

Notifier::pushHandler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
cc 1
eloc 3
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Tylercd100\LERN\Components;
4
5
use Exception;
6
use Monolog\Handler\HandlerInterface;
7
use Monolog\Logger;
8
use Tylercd100\LERN\Exceptions\NotifierFailedException;
9
use Tylercd100\Notify\Drivers\FromConfig as Notify;
10
11
class Notifier extends Component {
12
    protected $config;
13
    protected $log;
14
    protected $messageCb;
15
    protected $subjectCb;
16
    protected $contextCb;
17
18
    /**
19
     * You can provide a Monolog Logger instance to use in the constructor 
20
     * @param Logger|null $log Logger instance to use
21
     */
22 60
    public function __construct(Logger $log = null) {
23 60
        if ($log === null) {
24 60
            $log = new Logger(config('lern.notify.channel'));
25 60
        }
26
27 60
        $this->config = config('lern.notify');
28 60
        $this->log = $log;
29 60
    }
30
31
    /**
32
     * Transforms a value into a closure that returns itself when called
33
     * @param  callable|string $cb The value that you want to wrap in a closure
34
     * @return callable
35
     */
36 15
    private function wrapValueInClosure($cb) {
37 15
        if (is_callable($cb)) {
38 9
            return $cb;
39
        } else {
40
            return function() use ($cb) { return $cb; };
41
        }
42
    }
43
44
    /**
45
     * Set a string or a closure to be called that will generate the message body for the notification
46
     * @param callable|string $cb A closure or string that will be set for the message
47
     * @return $this
48 6
     */
49
    public function setMessage($cb)
50 6
    {
51 6
        $this->messageCb = $this->wrapValueInClosure($cb);
52
        return $this;
53
    }
54
55
    /**
56
     * Returns the result of the message closure
57
     * @param  Exception $e The Exception instance that you want to build the message around
58
     * @return string       The message string
59 18
     */
60 18
    public function getMessage(Exception $e) {
61 6
        if (is_callable($this->messageCb)) {
62
            return $this->messageCb->__invoke($e);
63 12
        } else {
64 12
            $msg = get_class($e)." was thrown! \n".$e->getMessage();
65 12
            if ($this->config['includeExceptionStackTrace'] === true) {
66 12
                $msg .= "\n\n".$e->getTraceAsString();
67 12
            }
68
            return $msg;
69
        }
70
    }
71
72
    /**
73
     * Set a string or a closure to be called that will generate the subject line for the notification
74
     * @param callable|string $cb A closure or string that will be set for the subject line
75 6
     * @return $this
76
     */
77 6
    public function setSubject($cb)
78 6
    {
79
        $this->subjectCb = $this->wrapValueInClosure($cb);
80
        return $this;
81
    }
82
83
    /**
84
     * Returns the result of the subject closure
85
     * @param  Exception $e The Exception instance that you want to build the subject around
86 18
     * @return string       The subject string
87 18
     */
88 6
    public function getSubject(Exception $e) {
89
        if (is_callable($this->subjectCb)) {
90 12
            return $this->subjectCb->__invoke($e);
91
        } else {
92
            return get_class($e);
93
        }
94
    }
95
96
    /**
97
     * Set an array or a closure to be called that will generate the context array for the notification
98 3
     * @param callable|array $cb A closure or array that will be set for the context
99
     * @return $this
100 3
     */
101 3
    public function setContext($cb)
102
    {
103
        $this->contextCb = $this->wrapValueInClosure($cb);
104
        return $this;
105
    }
106
107
    /**
108
     * Returns the result of the context closure
109 15
     * @param  Exception $e The Exception instance that you want to build the context around
110
     * @return array        The context array
111
     */
112 15
    public function getContext(Exception $e, $context = []) {
113 12
114 12
        //This needs a better solution. How do I set specific context needs for different drivers?
115
        if (in_array('pushover', $this->config['drivers'])) {
116
            $context['sound'] = $this->config['pushover']['sound'];
117 15
        }
118 3
119
        // Call the callback or return the default
120 12
        if (is_callable($this->contextCb)) {
121
            return $this->contextCb->__invoke($e, $context);
122
        } else {
123
            return $context;
124
        }
125
    }
126
127
    /**
128
     * Pushes on another Monolog Handler
129 6
     * @param  HandlerInterface $handler The handler instance to add on
130 6
     * @return Notifier                  Returns this
131 6
     */
132
    public function pushHandler(HandlerInterface $handler) {
133
        $this->log->pushHandler($handler);
134
        return $this;
135
    }
136
137
    /**
138
     * Triggers the Monolog Logger instance to log an error to all handlers
139
     * @param  Exception $e The exception to use
140 15
     * @param  array $context Additional information that you would like to pass to Monolog
141
     * @return bool
142 15
     * @throws NotifierFailedException
143 3
     */
144
    public function send(Exception $e, array $context = []) {
145
        
146 12
        if ($this->shouldntHandle($e)) {
147 12
            return false;
148 12
        }
149
150
        $message = $this->getMessage($e);
151 12
        $subject = $this->getSubject($e);
152
        $context = $this->getContext($e, $context);
153 12
        
154 12
        try {
155 12
            $notify = new Notify($this->config, $this->log, $subject);
156
157 12
            $level = (array_key_exists('log_level', $this->config) && !empty($this->config['log_level']))
158
                ? $this->config['log_level'] 
159 9
                : 'critical';
160 3
161 3
            $notify->{$level}($message, $context);
162 3
163
            return true;
164
        } catch (Exception $e) {
165
            $code = (is_int($e->getCode()) ? $e->getCode() : 0);
166
            throw new NotifierFailedException($e->getMessage(), $code, $e);
167
        }
168
    }
169
}