PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 All 36 releases
vikbooking / libraries / adapter / sms / driver.php

driver.php in VikBooking Hotel Booking Engine & PMS trunk, at libraries/adapter/sms/driver.php

542 lines 12.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikWP - Libraries
4 * @subpackage adapter.sms
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2023 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 JLoader::import('adapter.sms.status');
15
16 /**
17 * This class describes the events that an abstract sms driver should handle.
18 *
19 * @since 10.1.30
20 */
21 abstract class JSmsDriver
22 {
23 /**
24 * The name of the plugin that has requested the sms.
25 *
26 * @var string
27 */
28 protected $caller;
29
30 /**
31 * The driver identifier.
32 *
33 * @var string
34 */
35 protected $driver;
36
37 /**
38 * The order details.
39 *
40 * @var JObject
41 */
42 protected $order;
43
44 /**
45 * The driver configuration parameters.
46 *
47 * @var JObject
48 */
49 protected $params;
50
51 /**
52 * Class constructor.
53 *
54 * @param string $caller The name of the plugin that requested the sms.
55 * @param mixed $order The order details to start the transaction.
56 * @param mixed $params The configuration of the driver.
57 */
58 public function __construct($caller, $order, $params = array())
59 {
60 if (is_string($params))
61 {
62 $params = (array) json_decode($params);
63 }
64
65 $this->caller = $caller;
66 $this->order = new JObject($order);
67 $this->params = new JObject($params);
68 }
69
70 /**
71 * Returns the name of the plugin that dispatched the sms.
72 *
73 * @return string
74 */
75 public function getCaller()
76 {
77 return $this->caller;
78 }
79
80 /**
81 * Checks if the given caller matches the current one.
82 *
83 * @param string $caller The caller to check.
84 *
85 * @return boolean True if the callers are equal, otherwise false.
86 *
87 * @uses getCaller()
88 */
89 public function isCaller($caller)
90 {
91 return !strcasecmp($this->getCaller(), $caller);
92 }
93
94 /**
95 * Returns the name of the driver.
96 *
97 * @return string
98 */
99 public function getDriver()
100 {
101 if (!$this->driver)
102 {
103 $class = get_class($this);
104
105 // extract driver name from classname
106 $this->driver = preg_replace_callback("/{$this->caller}Sms(.*?)/i", function($match)
107 {
108 return $match[1];
109 }, $class);
110
111 $this->driver = strtolower($this->driver);
112 }
113
114 return $this->driver;
115 }
116
117 /**
118 * Checks if the given driver matches the current one.
119 *
120 * @param string $driver The driver to check.
121 *
122 * @return boolean True if the drivers are equal, otherwise false.
123 *
124 * @uses getDriver()
125 */
126 public function isDriver($driver)
127 {
128 return !strcasecmp($this->getDriver(), $driver);
129 }
130
131 /**
132 * Returns the order detail related to the specified key.
133 *
134 * @param string $key The registry key.
135 * @param mixed $def The default value if the key is not set.
136 *
137 * @return mixed The registry value, or the default one.
138 */
139 public function get($key, $def = null)
140 {
141 return $this->order->get($key, $def);
142 }
143
144 /**
145 * Updates the specified key into the order details object.
146 *
147 * @param string $key The registry key.
148 * @param mixed $val The value to update.
149 *
150 * @param mixed The old value.
151 */
152 public function set($key, $val)
153 {
154 return $this->order->set($key, $val);
155 }
156
157 /**
158 * Returns an associative array containing the order details.
159 *
160 * @return array
161 */
162 public function getOrder()
163 {
164 return $this->order->getProperties();
165 }
166
167 /**
168 * Replaces the internal order details with the specified ones.
169 *
170 * @param array|object $order
171 *
172 * @return void
173 *
174 * @since 10.1.69
175 */
176 public function setOrder($order)
177 {
178 $this->order = new JObject($order);
179 }
180
181 /**
182 * Returns the configuration parameter related to the specified key.
183 *
184 * @param string $key The registry key.
185 * @param mixed $def The default value if the key is not set.
186 *
187 * @return mixed The registry value, or the default one.
188 */
189 public function getParam($key, $def = null)
190 {
191 return $this->params->get($key, $def);
192 }
193
194 /**
195 * Updates the specified key into the configuration object.
196 *
197 * @param string $key The registry key.
198 * @param mixed $val The value to update.
199 *
200 * @param mixed The old value.
201 */
202 public function setParam($key, $val)
203 {
204 return $this->params->set($key, $val);
205 }
206
207 /**
208 * Returns an associative array containing the driver parameters.
209 *
210 * @return array
211 */
212 public function getParams()
213 {
214 return $this->params->getProperties();
215 }
216
217 /**
218 * Returns an associative array containing the form
219 * fields used to construct the configuration of the driver.
220 *
221 * This method triggers two ACTIONS to manipulate the
222 * configuration array before it is returned:
223 * - sms_driver_before_admin_params
224 * - sms_driver_after_admin_params
225 *
226 * @return array The sms driver configuration.
227 *
228 * @uses buildAdminParameters()
229 */
230 public function getAdminParameters()
231 {
232 /**
233 * Plugins can manipulate the properties of this object.
234 * Fires before the configuration array is generated.
235 *
236 * @param self A reference to this object.
237 *
238 * @since 10.1.30
239 */
240 do_action('sms_driver_before_admin_params_' . $this->caller, array(&$this));
241
242 // children drivers will create the configuration form (as array)
243 $config = $this->buildAdminParameters();
244
245 /**
246 * Plugins can manipulate the configuration form of the driver.
247 * Fires after generating the config form.
248 *
249 * @param self A reference to this object.
250 * @param array A reference to the configuration array.
251 *
252 * @since 10.1.30
253 */
254 do_action_ref_array('sms_driver_after_admin_params_' . $this->caller, array(&$this, &$config));
255
256 return $config;
257 }
258
259 /**
260 * Abstract method used to build the associative array
261 * to allow the plugins to construct a configuration form.
262 *
263 * In case the driver needs an API Key, the array should
264 * be built as follows:
265 *
266 * {"apikey": {"type": "text", "label": "API Key"}}
267 *
268 * @return array The associative array.
269 */
270 protected function buildAdminParameters()
271 {
272 // return an empty array because a sms driver
273 // may not need a configuration
274 return array();
275 }
276
277 /**
278 * Dispatches the SMS to the specified phone number.
279 *
280 * This method triggers the ACTIONS below:
281 * - sms_driver_before_send
282 * - sms_driver_after_send
283 *
284 * @param string $phone The sms receiver.
285 * @param string $text The message to send.
286 *
287 * @return mixed An object describing the status of the sms.
288 *
289 * @uses dispatch()
290 */
291 public function sendMessage($phone, $text)
292 {
293 /**
294 * Plugins can manipulate the properties of this object.
295 * Fires before sending the SMS.
296 *
297 * @param self A reference to this object.
298 * @param string The sms receiver.
299 * @param string The message to send.
300 *
301 * @since 10.1.30
302 */
303 do_action('sms_driver_before_send_' . $this->caller, array(&$this, &$phone, &$text));
304
305 $status = new JSmsStatus();
306
307 // sanitize phone number
308 $phone = $this->sanitizePhone($phone);
309
310 // children drivers will dispatch the message
311 $this->dispatch($phone, $text, $status);
312
313 // inject receiver and SMS within the status object
314 $status->setData('phone', $phone);
315 $status->setData('sms', $text);
316
317 $response = null;
318
319 /**
320 * Plugins can manipulate the response object to return.
321 * By filling the &$response variable, this method will return
322 * it instead of the default &$status one.
323 * Fires after dispatching the sms.
324 *
325 * @param self A reference to this object.
326 * @param JSmsStatus A reference to the status object.
327 * @param mixed A reference to the final response (null by default).
328 *
329 * @since 10.1.30
330 */
331 do_action_ref_array('sms_driver_after_send_' . $this->caller, array(&$this, &$status, &$response));
332
333 if (is_null($response))
334 {
335 // no hook fired, the response will be equals to the status object
336 $response = $status;
337 }
338
339 return $response;
340 }
341
342 /**
343 * Abstract method used to dispatch a SMS to the specified phone.
344 *
345 * @param string $phone The sms receiver.
346 * @param string $text The message to send.
347 * @param JSmsStatus &$status The status of the notification.
348 *
349 * @return void
350 */
351 abstract protected function dispatch($phone, $text, JSmsStatus &$status);
352
353 /**
354 * Checks whether the current driver is able to estimate the credit.
355 *
356 * @return boolean
357 */
358 public function canEstimate()
359 {
360 // inherit in chidlren classes
361 return false;
362 }
363
364 /**
365 * Tries to recover the remaining balance.
366 *
367 * This method triggers the ACTIONS below:
368 * - sms_driver_before_estimate
369 * - sms_driver_after_estimate
370 *
371 * @param string $phone An optional receiver.
372 * @param string $text An optional message.
373 *
374 * @return mixed The remaining balance on success, false otherwise.
375 *
376 * @uses estimate()
377 */
378 public function getCredit($phone = null, $text = null)
379 {
380 /**
381 * Plugins can manipulate the properties of this object.
382 * Fires before estimating the remaining credit.
383 *
384 * @param self A reference to this object.
385 * @param string The sms receiver.
386 * @param string The message to send.
387 *
388 * @since 10.1.30
389 */
390 do_action('sms_driver_before_estimate_' . $this->caller, array(&$this, &$phone, &$text));
391
392 // sanitize phone number
393 $phone = $this->sanitizePhone($phone);
394
395 try
396 {
397 // children drivers will estimate the credit
398 $credit = $this->estimateCredit($phone, $text);
399 }
400 catch (Exception $e)
401 {
402 $credit = false;
403 }
404
405 /**
406 * Plugins can manipulate the resulting credit.
407 * Fires after estimating the user credit.
408 *
409 * @param self A reference to this object.
410 * @param mixed A reference to the user credit (null by default).
411 *
412 * @since 10.1.30
413 */
414 do_action_ref_array('sms_driver_after_estimate_' . $this->caller, array(&$this, &$credit));
415
416 return $credit;
417 }
418
419 /**
420 * Tries to estimate the remaining user credit.
421 *
422 * @param string $phone An optional receiver.
423 * @param string $text An optional message.
424 *
425 * @return mixed The remaining balance on success, false otherwise.
426 *
427 * @throws Exception
428 */
429 protected function estimateCredit($phone, $text)
430 {
431 // inherit in children classes to estimate credit
432 throw new Exception('Not implemented', 501);
433 }
434
435 /**
436 * Validates the response.
437 * Implement for platform BC.
438 *
439 * @param mixed $response
440 *
441 * @return boolean
442 */
443 public function validateResponse($response)
444 {
445 // reset log
446 $this->log = '';
447
448 if (!$response instanceof JSmsStatus)
449 {
450 // invalid argument
451 return false;
452 }
453
454 // register log
455 $this->log = $response->log;
456
457 // check sms status
458 return $response->isVerified();
459 }
460
461 /**
462 * Returns the latest logs.
463 *
464 * @return string
465 */
466 public function getLog()
467 {
468 return isset($this->log) ? $this->log : '';
469 }
470
471 /**
472 * Helper method used to sanitize phone numbers.
473 *
474 * @param string $phone The phone number to sanitize.
475 *
476 * @return string The cleansed number.
477 */
478 public function sanitizePhone($phone)
479 {
480 // trim unexpected characters
481 $phone = preg_replace("/[^0-9+]/", '', $phone);
482
483 // replace 00 dial code with +
484 if (substr($phone, 0, 2) == '00')
485 {
486 $phone = '+' . substr($phone, 2);
487 }
488
489 return $phone;
490 }
491
492 /**
493 * Adds the dial code to the phone number.
494 *
495 * @param string $prefix The dial code to prepend.
496 * @param string $phone The phone number.
497 *
498 * @return string The resulting phone number.
499 */
500 public function addDialCode($prefix, $phone)
501 {
502 // check if the phone number already owns a dial code
503 if ($prefix && !preg_match("/^\+/", $phone))
504 {
505 // sanitize dial code
506 $prefix = $this->sanitizePhone($prefix);
507
508 // normalize dial code
509 $prefix = '+' . ltrim($prefix, '+');
510
511 // prepend dial code
512 $phone = $prefix . $phone;
513 }
514
515 return $phone;
516 }
517
518 /**
519 * Check if the specified message contains UTF-8 characters.
520 *
521 * @param string $message The string to check.
522 *
523 * @return boolean True if unicode, otherwise false.
524 */
525 public function isUnicode($message)
526 {
527 if (function_exists('iconv'))
528 {
529 $latin = @iconv('UTF-8', 'ISO-8859-1', $message);
530
531 if (strcmp($latin, $message))
532 {
533 $arr = unpack('H*hex', @iconv('UTF-8', 'UCS-2BE', $message));
534 //return strtoupper($arr['hex']);
535 return true;
536 }
537 }
538
539 return false;
540 }
541 }
542