|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/* |
|
4
|
|
|
* This file is part of the overtrue/easy-sms. |
|
5
|
|
|
* (c) overtrue <[email protected]> |
|
6
|
|
|
* This source file is subject to the MIT license that is bundled |
|
7
|
|
|
* with this source code in the file LICENSE. |
|
8
|
|
|
*/ |
|
9
|
|
|
|
|
10
|
|
|
namespace Overtrue\EasySms; |
|
11
|
|
|
|
|
12
|
|
|
use Closure; |
|
13
|
|
|
use Overtrue\EasySms\Contracts\GatewayInterface; |
|
14
|
|
|
use Overtrue\EasySms\Contracts\StrategyInterface; |
|
15
|
|
|
use Overtrue\EasySms\Exceptions\InvalidArgumentException; |
|
16
|
|
|
use Overtrue\EasySms\Support\Config; |
|
17
|
|
|
use RuntimeException; |
|
18
|
|
|
|
|
19
|
|
|
/** |
|
20
|
|
|
* Class EasySms. |
|
21
|
|
|
*/ |
|
22
|
|
|
class EasySms |
|
23
|
|
|
{ |
|
24
|
|
|
/** |
|
25
|
|
|
* @var \Overtrue\EasySms\Support\Config |
|
26
|
|
|
*/ |
|
27
|
|
|
protected $config; |
|
28
|
|
|
|
|
29
|
|
|
/** |
|
30
|
|
|
* @var string |
|
31
|
|
|
*/ |
|
32
|
|
|
protected $defaultGateway; |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* @var array |
|
36
|
|
|
*/ |
|
37
|
|
|
protected $customCreators = []; |
|
38
|
|
|
|
|
39
|
|
|
/** |
|
40
|
|
|
* @var array |
|
41
|
|
|
*/ |
|
42
|
|
|
protected $gateways = []; |
|
43
|
|
|
|
|
44
|
|
|
/** |
|
45
|
|
|
* @var \Overtrue\EasySms\Messenger |
|
46
|
|
|
*/ |
|
47
|
|
|
protected $messenger; |
|
48
|
|
|
|
|
49
|
|
|
/** |
|
50
|
|
|
* @var array |
|
51
|
|
|
*/ |
|
52
|
|
|
protected $strategies = []; |
|
53
|
|
|
|
|
54
|
|
|
/** |
|
55
|
|
|
* Constructor. |
|
56
|
|
|
* |
|
57
|
|
|
* @param array $config |
|
58
|
|
|
*/ |
|
59
|
|
|
public function __construct(array $config) |
|
60
|
|
|
{ |
|
61
|
|
|
$this->config = new Config($config); |
|
62
|
|
|
|
|
63
|
|
|
if (!empty($config['default'])) { |
|
64
|
|
|
$this->setDefaultGateway($config['default']); |
|
65
|
|
|
} |
|
66
|
|
|
} |
|
67
|
|
|
|
|
68
|
|
|
/** |
|
69
|
|
|
* Send a message. |
|
70
|
|
|
* |
|
71
|
|
|
* @param string|array $to |
|
72
|
|
|
* @param \Overtrue\EasySms\Contracts\MessageInterface $message |
|
73
|
|
|
* @param array $gateways |
|
74
|
|
|
* |
|
75
|
|
|
* @return array |
|
76
|
|
|
*/ |
|
77
|
|
|
public function send($to, $message, array $gateways = []) |
|
78
|
|
|
{ |
|
79
|
|
|
$messenger = $this->getMessenger(); |
|
80
|
|
|
|
|
81
|
|
|
return $messenger->send($to, $message, $gateways); |
|
|
|
|
|
|
82
|
|
|
} |
|
83
|
|
|
|
|
84
|
|
|
/** |
|
85
|
|
|
* Create a gateway. |
|
86
|
|
|
* |
|
87
|
|
|
* @param string $name |
|
88
|
|
|
* |
|
89
|
|
|
* @return \Overtrue\EasySms\Contracts\GatewayInterface |
|
90
|
|
|
*/ |
|
91
|
|
|
public function gateway($name = null) |
|
92
|
|
|
{ |
|
93
|
|
|
$name = $name ?: $this->getDefaultGateway(); |
|
94
|
|
|
|
|
95
|
|
|
if (!isset($this->gateways[$name])) { |
|
96
|
|
|
$this->gateways[$name] = $this->createGateway($name); |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
return $this->gateways[$name]; |
|
100
|
|
|
} |
|
101
|
|
|
|
|
102
|
|
|
/** |
|
103
|
|
|
* Get a strategy instance. |
|
104
|
|
|
* |
|
105
|
|
|
* @param string|null $strategy |
|
106
|
|
|
* |
|
107
|
|
|
* @return StrategyInterface |
|
108
|
|
|
*/ |
|
109
|
|
|
public function strategy($strategy = null) |
|
110
|
|
|
{ |
|
111
|
|
|
if (is_null($strategy)) { |
|
112
|
|
|
$strategy = $this->config->get('default.strategy'); |
|
113
|
|
|
} |
|
114
|
|
|
|
|
115
|
|
|
if (!class_exists($strategy)) { |
|
116
|
|
|
$strategy = __NAMESPACE__.'\Strategies\\'.ucfirst($strategy); |
|
117
|
|
|
} |
|
118
|
|
|
|
|
119
|
|
|
if (!class_exists($strategy)) { |
|
120
|
|
|
throw new InvalidArgumentException("Unsupported strategy \"{$strategy}\""); |
|
121
|
|
|
} |
|
122
|
|
|
|
|
123
|
|
|
if (!($this->strategies[$strategy] instanceof StrategyInterface)) { |
|
124
|
|
|
$this->strategies[$strategy] = new $strategy($this); |
|
125
|
|
|
} |
|
126
|
|
|
|
|
127
|
|
|
return $this->strategies[$strategy]; |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
|
|
/** |
|
131
|
|
|
* Register a custom driver creator Closure. |
|
132
|
|
|
* |
|
133
|
|
|
* @param string $name |
|
134
|
|
|
* @param \Closure $callback |
|
135
|
|
|
* |
|
136
|
|
|
* @return $this |
|
137
|
|
|
*/ |
|
138
|
|
|
public function extend($name, Closure $callback) |
|
139
|
|
|
{ |
|
140
|
|
|
$this->customCreators[$name] = $callback; |
|
141
|
|
|
|
|
142
|
|
|
return $this; |
|
143
|
|
|
} |
|
144
|
|
|
|
|
145
|
|
|
/** |
|
146
|
|
|
* @return \Overtrue\EasySms\Support\Config |
|
147
|
|
|
*/ |
|
148
|
|
|
public function getConfig() |
|
149
|
|
|
{ |
|
150
|
|
|
return $this->config; |
|
151
|
|
|
} |
|
152
|
|
|
|
|
153
|
|
|
/** |
|
154
|
|
|
* Get default gateway name. |
|
155
|
|
|
* |
|
156
|
|
|
* @return string |
|
157
|
|
|
* |
|
158
|
|
|
* @throws if no default gateway configured |
|
159
|
|
|
*/ |
|
160
|
|
|
public function getDefaultGateway() |
|
161
|
|
|
{ |
|
162
|
|
|
if (empty($this->defaultGateway)) { |
|
163
|
|
|
throw new RuntimeException('No default gateway configured.'); |
|
164
|
|
|
} |
|
165
|
|
|
|
|
166
|
|
|
return $this->defaultGateway; |
|
167
|
|
|
} |
|
168
|
|
|
|
|
169
|
|
|
/** |
|
170
|
|
|
* Set default gateway name. |
|
171
|
|
|
* |
|
172
|
|
|
* @param string $name |
|
173
|
|
|
* |
|
174
|
|
|
* @return $this |
|
175
|
|
|
*/ |
|
176
|
|
|
public function setDefaultGateway($name) |
|
177
|
|
|
{ |
|
178
|
|
|
$this->defaultGateway = $name; |
|
179
|
|
|
|
|
180
|
|
|
return $this; |
|
181
|
|
|
} |
|
182
|
|
|
|
|
183
|
|
|
/** |
|
184
|
|
|
* @return \Overtrue\EasySms\Messenger |
|
185
|
|
|
*/ |
|
186
|
|
|
public function getMessenger() |
|
187
|
|
|
{ |
|
188
|
|
|
return $this->messenger ?: $this->messenger = new Messenger($this); |
|
189
|
|
|
} |
|
190
|
|
|
|
|
191
|
|
|
/** |
|
192
|
|
|
* Create a new driver instance. |
|
193
|
|
|
* |
|
194
|
|
|
* @param string $name |
|
195
|
|
|
* |
|
196
|
|
|
* @throws \InvalidArgumentException |
|
197
|
|
|
* |
|
198
|
|
|
* @return GatewayInterface |
|
199
|
|
|
*/ |
|
200
|
|
|
protected function createGateway($name) |
|
201
|
|
|
{ |
|
202
|
|
|
if (isset($this->customCreators[$name])) { |
|
203
|
|
|
$gateway = $this->callCustomCreator($name); |
|
204
|
|
|
} else { |
|
205
|
|
|
$className = $this->formatGatewayClassName($name); |
|
206
|
|
|
$gateway = $this->makeGateway($className, $this->config->get("gateways.{$name}", [])); |
|
207
|
|
|
} |
|
208
|
|
|
|
|
209
|
|
|
if (!($gateway instanceof GatewayInterface)) { |
|
210
|
|
|
throw new InvalidArgumentException(sprintf('Gateway "%s" not inherited from %s.', $name, GatewayInterface::class)); |
|
211
|
|
|
} |
|
212
|
|
|
|
|
213
|
|
|
return $gateway; |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
/** |
|
217
|
|
|
* Make gateway instance. |
|
218
|
|
|
* |
|
219
|
|
|
* @param string $gateway |
|
220
|
|
|
* @param array $config |
|
221
|
|
|
* |
|
222
|
|
|
* @return \Overtrue\EasySms\Contracts\GatewayInterface |
|
223
|
|
|
*/ |
|
224
|
|
|
protected function makeGateway($gateway, $config) |
|
225
|
|
|
{ |
|
226
|
|
|
if (!class_exists($gateway)) { |
|
227
|
|
|
throw new InvalidArgumentException(sprintf('Gateway "%s" not exists.', $gateway)); |
|
228
|
|
|
} |
|
229
|
|
|
|
|
230
|
|
|
return new $gateway($config); |
|
231
|
|
|
} |
|
232
|
|
|
|
|
233
|
|
|
/** |
|
234
|
|
|
* Format gateway name. |
|
235
|
|
|
* |
|
236
|
|
|
* @param string $name |
|
237
|
|
|
* |
|
238
|
|
|
* @return string |
|
239
|
|
|
*/ |
|
240
|
|
|
protected function formatGatewayClassName($name) |
|
241
|
|
|
{ |
|
242
|
|
|
if (class_exists($name)) { |
|
243
|
|
|
return $name; |
|
244
|
|
|
} |
|
245
|
|
|
|
|
246
|
|
|
$name = ucfirst(str_replace(['-', '_', ''], '', $name)); |
|
247
|
|
|
|
|
248
|
|
|
return __NAMESPACE__."\\Gateways\\{$name}Gateway"; |
|
249
|
|
|
} |
|
250
|
|
|
|
|
251
|
|
|
/** |
|
252
|
|
|
* Call a custom gateway creator. |
|
253
|
|
|
* |
|
254
|
|
|
* @param string $gateway |
|
255
|
|
|
* |
|
256
|
|
|
* @return mixed |
|
257
|
|
|
*/ |
|
258
|
|
|
protected function callCustomCreator($gateway) |
|
259
|
|
|
{ |
|
260
|
|
|
return call_user_func($this->customCreators[$gateway], $this->config->get($gateway, [])); |
|
261
|
|
|
} |
|
262
|
|
|
} |
|
263
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.