1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Fenos\Notifynder\Senders; |
4
|
|
|
|
5
|
|
|
use BadMethodCallException; |
6
|
|
|
use Closure; |
7
|
|
|
use Fenos\Notifynder\Contracts\DefaultSender; |
8
|
|
|
use Fenos\Notifynder\Contracts\NotifynderSender; |
9
|
|
|
use Fenos\Notifynder\Contracts\Sender; |
10
|
|
|
use Fenos\Notifynder\Contracts\StoreNotification; |
11
|
|
|
use Illuminate\Contracts\Container\Container; |
12
|
|
|
use LogicException; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Class SenderManager. |
16
|
|
|
*/ |
17
|
|
|
class SenderManager implements NotifynderSender |
18
|
|
|
{ |
19
|
|
|
/** |
20
|
|
|
* @var SenderFactory |
21
|
|
|
*/ |
22
|
|
|
protected $senderFactory; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @var StoreNotification |
26
|
|
|
*/ |
27
|
|
|
protected $storeNotification; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var array |
31
|
|
|
*/ |
32
|
|
|
protected $senders = []; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var Container |
36
|
|
|
*/ |
37
|
|
|
protected $container; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @param SenderFactory $senderFactory |
41
|
|
|
* @param StoreNotification $storeNotification |
42
|
|
|
* @param Container $container |
43
|
|
|
*/ |
44
|
|
|
public function __construct(SenderFactory $senderFactory, |
45
|
|
|
StoreNotification $storeNotification, |
46
|
|
|
Container $container) |
47
|
|
|
{ |
48
|
|
|
$this->senderFactory = $senderFactory; |
49
|
|
|
$this->storeNotification = $storeNotification; |
50
|
|
|
$this->container = $container; |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Send any notifications. |
55
|
|
|
* |
56
|
|
|
* @param array $info |
57
|
|
|
* @param null $category |
58
|
|
|
* @return mixed |
59
|
|
|
*/ |
60
|
|
|
public function send($info, $category = null) |
61
|
|
|
{ |
62
|
|
|
return $this->sendNow($info, $category); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Send now whatever data passed. |
67
|
|
|
* |
68
|
|
|
* @param array $info |
69
|
|
|
* @param $category |
70
|
|
|
* @return mixed |
71
|
|
|
*/ |
72
|
|
|
public function sendNow($info, $category = null) |
73
|
|
|
{ |
74
|
|
|
$sender = $this->senderFactory->getSender($info, $category); |
75
|
|
|
|
76
|
|
|
return $sender->send($this->storeNotification); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Send one method to get fully working |
81
|
|
|
* older version. |
82
|
|
|
* |
83
|
|
|
* @param $info |
84
|
|
|
* @param $category |
85
|
|
|
* @return SendOne |
86
|
|
|
*/ |
87
|
|
|
public function sendOne($info, $category = null) |
88
|
|
|
{ |
89
|
|
|
return $this->senderFactory->sendSingle($info, $category) |
|
|
|
|
90
|
|
|
->send($this->storeNotification, $category); |
|
|
|
|
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Send Multiple method to get fully working |
95
|
|
|
* older version. |
96
|
|
|
* |
97
|
|
|
* @param $info |
98
|
|
|
* @return SendMultiple |
99
|
|
|
*/ |
100
|
|
|
public function sendMultiple($info) |
101
|
|
|
{ |
102
|
|
|
return $this->senderFactory->sendMultiple($info) |
103
|
|
|
->send($this->storeNotification); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Send a group of notifications |
108
|
|
|
* at once. |
109
|
|
|
* |
110
|
|
|
* @param $groupName |
111
|
|
|
* @param array $info |
112
|
|
|
* @return mixed |
113
|
|
|
*/ |
114
|
|
|
public function sendGroup($groupName, $info = []) |
115
|
|
|
{ |
116
|
|
|
return $this->senderFactory->sendGroup( |
117
|
|
|
$groupName, |
118
|
|
|
$info |
119
|
|
|
)->send($this->storeNotification); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* This method allow to Extend |
124
|
|
|
* notifynder with custom sender. |
125
|
|
|
* |
126
|
|
|
* @param $name |
127
|
|
|
* @param callable $extendSender |
128
|
|
|
* @return $this |
129
|
|
|
*/ |
130
|
|
|
public function extend($name, $extendSender) |
131
|
|
|
{ |
132
|
|
|
$this->senders[$name] = $extendSender; |
133
|
|
|
|
134
|
|
|
return $this; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* Call a custom method. |
139
|
|
|
* |
140
|
|
|
* @param $customMethod |
141
|
|
|
* @param $notification |
142
|
|
|
* @return mixed |
143
|
|
|
*/ |
144
|
|
|
public function customSender($customMethod, $notification) |
145
|
|
|
{ |
146
|
|
|
if (array_key_exists($customMethod, $this->senders)) { |
147
|
|
|
|
148
|
|
|
// get the extended method |
149
|
|
|
$extendedSender = $this->senders[$customMethod]; |
150
|
|
|
|
151
|
|
|
// If is a closure means that i'll return an instance |
152
|
|
|
// with the |
153
|
|
|
if ($extendedSender instanceof Closure) { |
154
|
|
|
|
155
|
|
|
// I invoke the closure expecting an Instance of a custom |
156
|
|
|
// Sender |
157
|
|
|
$invoker = call_user_func_array($extendedSender, [$notification, $this->container]); |
158
|
|
|
|
159
|
|
|
// If the invoker is a custom sender |
160
|
|
|
// then I invoke it passing the sender class |
161
|
|
|
if ($invoker instanceof Sender) { |
162
|
|
|
return $invoker->send($this); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
// If the dev is attempting to create a custom |
166
|
|
|
// way of storing notifications then |
167
|
|
|
// i'll pass the store notification contract |
168
|
|
|
if ($invoker instanceof DefaultSender) { |
169
|
|
|
return $invoker->send($this->storeNotification); |
170
|
|
|
} |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
$error = 'The extension must be an instance of Closure'; |
174
|
|
|
throw new LogicException($error); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
$error = "The method $customMethod does not exists on the class ".get_class($this); |
178
|
|
|
throw new BadMethodCallException($error); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
/** |
182
|
|
|
* When calling a not existing method |
183
|
|
|
* try to resolve with an extended. |
184
|
|
|
* |
185
|
|
|
* @param $name |
186
|
|
|
* @param $arguments |
187
|
|
|
* @return mixed |
188
|
|
|
*/ |
189
|
|
|
public function __call($name, $arguments) |
190
|
|
|
{ |
191
|
|
|
if (isset($arguments[0])) { |
192
|
|
|
return $this->customSender($name, $arguments[0]); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
$error = 'No argument passed to the custom sender, |
196
|
|
|
please provide notifications array'; |
197
|
|
|
throw new BadMethodCallException($error); |
198
|
|
|
} |
199
|
|
|
} |
200
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.