Skip to content

Commit 273de43

Browse files
committed
BulkSMS: added group filter
1 parent 26d7235 commit 273de43

File tree

7 files changed

+309
-217
lines changed

7 files changed

+309
-217
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
.idea/
2-
modules/
2+
vendor/

Constants.php

+20-3
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313
* @license LICENSE
1414
*/
1515

16-
class Constants
16+
abstract class Constants
1717
{
1818
const API_KEY = 'SMS77_API_KEY';
1919
const BULK = 'SMS77_BULK';
2020
const BULK_COUNTRIES = 'SMS77_BULK_COUNTRIES';
21+
const BULK_GROUPS = 'SMS77_BULK_GROUPS';
2122
const FROM = 'SMS77_FROM';
2223
const MSG_ON_DELIVERY = 'SMS77_MSG_ON_DELIVERY';
2324
const MSG_ON_INVOICE = 'SMS77_MSG_ON_INVOICE';
@@ -30,9 +31,23 @@ class Constants
3031
const SIGNATURE = 'SMS77_SIGNATURE';
3132
const SIGNATURE_POSITION = 'SMS77_SIGNATURE_POSITION';
3233

33-
public static $configuration = [
34+
static function persistedKeys() {
35+
$keys = [];
36+
37+
foreach (self::CONFIGURATION as $k => $v) {
38+
if (!in_array($k, self::NON_PERSISTED_KEYS)) {
39+
$keys[] = $k;
40+
}
41+
}
42+
43+
return $keys;
44+
}
45+
46+
const CONFIGURATION = [
3447
self::API_KEY => '',
3548
self::BULK => '',
49+
self::BULK_COUNTRIES => [],
50+
self::BULK_GROUPS => [],
3651
self::FROM => '',
3752
self::MSG_ON_DELIVERY => false,
3853
self::MSG_ON_INVOICE => false,
@@ -49,5 +64,7 @@ class Constants
4964
self::SIGNATURE_POSITION => 'append',
5065
];
5166

52-
public static $signature_positions = ['append', 'prepend',];
67+
const SIGNATURE_POSITIONS = ['append', 'prepend',];
68+
69+
const NON_PERSISTED_KEYS = [Constants::BULK_COUNTRIES, Constants::BULK_GROUPS,];
5370
}

Form.php

+38-7
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,29 @@ public function __construct($name)
2222
$this->allow_employee_form_lang = $defaultLang;
2323
$this->currentIndex = AdminController::$currentIndex . "&configure=$name";
2424
$this->default_form_language = $defaultLang;
25-
foreach (Configuration::getMultiple(array_keys(Constants::$configuration)) as $k => $v) {
26-
$this->fields_value["config[$k]"] = $v;
25+
26+
$setFieldsValue = function($k, $v) {
27+
$name = "config[$k]";
28+
29+
if (is_array($v)) {
30+
$name .= '[]';
31+
}
32+
33+
$this->fields_value[$name] = $v;
34+
};
35+
36+
foreach (Configuration::getMultiple(Constants::persistedKeys()) as $k => $v) {
37+
$setFieldsValue($k, $v);
2738
}
2839

40+
foreach (Constants::NON_PERSISTED_KEYS as $k) {
41+
$setFieldsValue($k, Constants::CONFIGURATION[$k]);
42+
}
43+
44+
$toName = function($key) {
45+
return "config[$key]";
46+
};
47+
2948
$this->fields_form = [
3049
[
3150
'form' => [
@@ -40,7 +59,7 @@ public function __construct($name)
4059
[
4160
'tab' => 'settings',
4261
'type' => 'text',
43-
'name' => 'config[SMS77_API_KEY]',
62+
'name' => $toName(Constants::API_KEY),
4463
'label' => $this->l('API-Key'),
4564
'hint' => $this->l('Your sms77.io API-Key.'),
4665
'desc' => $this->l('An API-Key is needed for sending. Get yours now at sms77.io'),
@@ -70,7 +89,7 @@ public function __construct($name)
7089
[
7190
'tab' => 'settings',
7291
'type' => 'text',
73-
'name' => 'config[SMS77_FROM]',
92+
'name' => $toName(Constants::FROM),
7493
'label' => $this->l('From'),
7594
'hint' => $this->l('Set a custom sender number or name.'),
7695
'desc' => $this->l('Max 11 alphanumeric or 16 numeric characters.'),
@@ -99,7 +118,7 @@ public function __construct($name)
99118
[
100119
'tab' => 'settings',
101120
'type' => 'radio',
102-
'name' => 'config[SMS77_SIGNATURE_POSITION]',
121+
'name' => $toName(Constants::SIGNATURE_POSITION),
103122
'label' => $this->l('Signature position'),
104123
'hint' => $this->l('Decides at which position the signature gets inserted.'),
105124
'desc' => $this->l('Decides at which position the signature gets inserted.'),
@@ -109,12 +128,12 @@ public function __construct($name)
109128
'label' => $pos,
110129
'value' => $pos,
111130
];
112-
}, Constants::$signature_positions),
131+
}, Constants::SIGNATURE_POSITIONS),
113132
],
114133
[
115134
'label' => $this->l('Countries'),
116135
'multiple' => true,
117-
'name' => 'config[SMS77_BULK_COUNTRIES]',
136+
'name' => $toName(Constants::BULK_COUNTRIES),
118137
'options' => [
119138
'query' => Country::getCountries($this->context->language->id),
120139
'id' => 'id_country',
@@ -123,6 +142,18 @@ public function __construct($name)
123142
'tab' => 'bulk',
124143
'type' => 'select',
125144
],
145+
[
146+
'label' => $this->l('Groups'),
147+
'multiple' => true,
148+
'name' => $toName(Constants::BULK_GROUPS),
149+
'options' => [
150+
'query' => Group::getGroups($this->context->language->id),
151+
'id' => 'id_group',
152+
'name' => 'name'
153+
],
154+
'tab' => 'bulk',
155+
'type' => 'select',
156+
],
126157
$this->makeTextarea(
127158
'BULK',
128159
'Send out any message to all of your customers.',

Personalizer.php

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
/**
3+
* NOTICE OF LICENSE
4+
*
5+
* This file is licenced under the Software License Agreement.
6+
* With the purchase or the installation of the software in your application
7+
* you accept the licence agreement.
8+
*
9+
* You must not modify, adapt or create derivative works of this source code
10+
*
11+
* @author sms77.io
12+
* @copyright 2019-present sms77 e.K.
13+
* @license LICENSE
14+
*/
15+
16+
/**
17+
* @property string $msg
18+
* @property array $address
19+
* @property bool $hasFirstName
20+
* @property bool $hasLastName
21+
* @property bool $hasOrderId
22+
*
23+
*/
24+
class Personalizer
25+
{
26+
public function __construct($msg, $address)
27+
{
28+
$this->msg = $msg;
29+
$this->address = $address;
30+
31+
$this->hasFirstName = false !== strpos($this->msg, '{0}');
32+
$this->hasLastName = false !== strpos($this->msg, '{1}');
33+
$this->hasOrderId = false !== strpos($this->msg, '{2}');
34+
}
35+
36+
function toString($orderId = null)
37+
{
38+
$msg = $this->msg;
39+
40+
if ($this->hasFirstName) {
41+
$msg = str_replace('{0}', $this->address['firstname'], $msg);
42+
}
43+
44+
if ($this->hasLastName) {
45+
$msg = str_replace('{1}', $this->address['lastname'], $msg);
46+
}
47+
48+
if ($this->hasOrderId && $orderId) {
49+
$msg = str_replace('{2}', $orderId, $msg);
50+
}
51+
52+
return $msg;
53+
}
54+
}

Util.php

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<?php
2+
/**
3+
* NOTICE OF LICENSE
4+
*
5+
* This file is licenced under the Software License Agreement.
6+
* With the purchase or the installation of the software in your application
7+
* you accept the licence agreement.
8+
*
9+
* You must not modify, adapt or create derivative works of this source code
10+
*
11+
* @author sms77.io
12+
* @copyright 2019-present sms77 e.K.
13+
* @license LICENSE
14+
*/
15+
16+
use Sms77\Api\Client;
17+
use libphonenumber\NumberParseException;
18+
19+
class Util {
20+
static function getAction(OrderState $orderState) {
21+
$awaitingPayment = in_array($orderState->id, [1, 10, 13], true);
22+
$isShipping = 4 === $orderState->id;
23+
$awaitingDelivery = 5 === $orderState->id;
24+
$isPaid = in_array($orderState->id, [2, 11], true);
25+
26+
$action = null;
27+
28+
if ($awaitingPayment) {
29+
$action = 'INVOICE';
30+
} elseif ($isPaid) {
31+
$action = 'PAYMENT';
32+
} elseif ($isShipping) {
33+
$action = 'SHIPMENT';
34+
} elseif ($awaitingDelivery) {
35+
$action = 'DELIVERY';
36+
}
37+
38+
return $action;
39+
}
40+
41+
static function dbQuery($select, $from, $where)
42+
{
43+
$sql = new DbQuery();
44+
$sql->select($select);
45+
$sql->from($from, 'q');
46+
$sql->where($where);
47+
return Db::getInstance()->executeS($sql);
48+
}
49+
50+
static function validateAndSend($msg, $number)
51+
{
52+
$apiKey = Configuration::get(Constants::API_KEY);
53+
if (!Tools::strlen($number) || !Tools::strlen($apiKey)) {
54+
return null;
55+
}
56+
57+
$signature = Configuration::get(Constants::SIGNATURE);
58+
if (Tools::strlen($signature)) {
59+
if ('append' === Configuration::get(Constants::SIGNATURE_POSITION)) {
60+
$msg .= $signature;
61+
} else {
62+
$msg = $signature . $msg;
63+
}
64+
}
65+
66+
(new Client($apiKey, 'prestashop'))->sms($number, $msg, [
67+
'from' => Configuration::get(Constants::FROM),
68+
]);
69+
}
70+
71+
static function addWhereIfSet($where, $key, $field, $config) {
72+
if (isset($config[$key])) {
73+
$list = implode(',', $config[$key]);
74+
75+
$where .= " AND $field IN ($list)";
76+
}
77+
78+
return $where;
79+
}
80+
81+
static function sendBulk($config, $v) {
82+
$addresses = Util::dbQuery(
83+
'id_country, id_customer, phone, phone_mobile','address', self::addWhereIfSet(
84+
"q.active = 1 AND q.deleted = 0 AND q.id_customer != 0 AND q.phone_mobile<>'0000000000'",
85+
Constants::BULK_COUNTRIES, "q.id_country", $config));
86+
87+
$merged = array_map(static function ($address) use($config) {
88+
$customer = Util::dbQuery('*','customer', self::addWhereIfSet(
89+
'q.active = 1 AND q.deleted = 0 AND q.id_customer = ' . $address['id_customer'],
90+
Constants::BULK_GROUPS, "q.id_default_group", $config));
91+
return $address + array_shift($customer);
92+
}, $addresses);
93+
94+
$valids = array_filter($merged, function ($d) {
95+
$numbers = [];
96+
if (isset($d['phone'])) {
97+
$numbers[] = $d['phone'];
98+
}
99+
if (isset($d['phone_mobile'])) {
100+
$numbers[] = $d['phone_mobile'];
101+
}
102+
103+
$numbers = array_filter($numbers, function ($number) use ($d) {
104+
try {
105+
$isoCode = Util::dbQuery(
106+
'iso_code',
107+
'country',
108+
'q.id_country = ' . $d['id_country']
109+
);
110+
$isoCode = array_shift($isoCode)['iso_code'];
111+
$numberProto = $this->phoneNumberUtil->parse($number, $isoCode);
112+
return $this->phoneNumberUtil->isValidNumber($numberProto);
113+
} catch (NumberParseException $e) {
114+
return false;
115+
}
116+
});
117+
118+
return count($numbers) ? true : false;
119+
});
120+
121+
$hasPlaceholder = preg_match('{0}', $v) || preg_match('{1}', $v);
122+
if ($hasPlaceholder) { // this is a personalized message
123+
$msg = $v;
124+
125+
foreach ($valids as $valid) {
126+
Util::validateAndSend(
127+
(new Personalizer($msg, $valid))->toString(),
128+
'' === $valid['phone'] ? $valid['phone_mobile'] : $valid['phone']
129+
);
130+
}
131+
} else {
132+
$phoneNumbers = array_map(static function ($d) {
133+
return '' === $d['phone_mobile'] ? $d['phone'] : $d['phone_mobile'];
134+
}, $valids);
135+
136+
Util::validateAndSend($v, implode(',', array_unique($phoneNumbers)));
137+
}
138+
}
139+
}

0 commit comments

Comments
 (0)