Completed
Push — master ( e156cb...7b5497 )
by Alessandro
08:02
created

Client::prepareRecipients()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 13
cts 13
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 12
nc 2
nop 1
crap 3
1
<?php
2
3
namespace Fazland\SkebbyRestClient\Client;
4
5
use Fazland\SkebbyRestClient\DataStructure\Response;
6
use Fazland\SkebbyRestClient\DataStructure\Sms;
7
use Fazland\SkebbyRestClient\Exception\NoRecipientsSpecifiedException;
8
use Fazland\SkebbyRestClient\Constant\Charsets;
9
use Fazland\SkebbyRestClient\Constant\EncodingSchemas;
10
use Fazland\SkebbyRestClient\Constant\Endpoints;
11
use Fazland\SkebbyRestClient\Constant\Recipients;
12
use Fazland\SkebbyRestClient\Constant\SendMethods;
13
use Fazland\SkebbyRestClient\Constant\ValidityPeriods;
14
use libphonenumber\NumberParseException;
15
use libphonenumber\PhoneNumberFormat;
16
use libphonenumber\PhoneNumberUtil;
17
use Symfony\Component\OptionsResolver\OptionsResolver;
18
19
/**
20
 * @author Massimiliano Braglia <[email protected]>
21
 */
22
class Client
23
{
24
    /**
25
     * @var array
26
     */
27
    private $config;
28
29
    /**
30
     * @param array $options
31
     */
32 7
    public function __construct(array $options)
33
    {
34 7
        $resolver = new OptionsResolver();
35
36 7
        $this->configureOptions($resolver);
37 7
        $this->config = $resolver->resolve($options);
38 7
    }
39
40
    /**
41
     * @param Sms $sms
42
     *
43
     * @return Response[]
44
     */
45 7
    public function send(Sms $sms)
46
    {
47 7
        $messages = [];
48
49 7
        $recipients = $sms->getRecipients();
50 7
        if (count($recipients) > Recipients::MAX) {
51 1
            foreach (array_chunk($recipients, Recipients::MAX) as $chunk) {
52 1
                $message = clone $sms;
53
                $message
54 1
                    ->setRecipients($chunk)
55 1
                    ->clearRecipientVariables()
56
                ;
57
58 1
                foreach ($chunk as $recipient) {
59 1
                    if (! isset($sms->getRecipientVariables()[$recipient])) {
60 1
                        continue;
61
                    }
62
63 1
                    foreach ($sms->getRecipientVariables()[$recipient] as $variable => $value) {
64 1
                        $message->addRecipientVariable($recipient, $variable, $value);
65 1
                    }
66 1
                }
67
68 1
                $messages[] = $message;
69 1
            }
70 1
        } else {
71 6
            $messages[] = $sms;
72
        }
73
74 7
        $responses = [];
75 7
        foreach ($messages as $message) {
76 7
            $request = $this->prepareRequest($message);
77
78 6
            $responses[] = $this->executeRequest($request);
79 4
        }
80
81 4
        return $responses;
82
    }
83
84
    /**
85
     * @param OptionsResolver $resolver
86
     */
87 7
    private function configureOptions(OptionsResolver $resolver)
88
    {
89
        $resolver
90 7
            ->setRequired([
91 7
                'username',
92 7
                'password',
93 7
                'sender',
94 7
                'method',
95 7
            ])
96 7
            ->setDefined([
97 7
                'delivery_start',
98 7
                'validity_period',
99 7
                'encoding_schema',
100 7
                'charset',
101 7
                'endpoint_uri',
102 7
            ])
103 7
            ->setAllowedTypes('username', 'string')
104 7
            ->setAllowedTypes('password', 'string')
105 7
            ->setAllowedTypes('sender', 'string')
106 7
            ->setAllowedTypes('method', 'string')
107 7
            ->setAllowedTypes('delivery_start', ['null', 'DateTime'])
108 7
            ->setAllowedTypes('validity_period', ['null', 'DateInterval'])
109 7
            ->setAllowedTypes('encoding_schema', 'string')
110 7
            ->setAllowedTypes('charset', 'string')
111 7
            ->setAllowedTypes('endpoint_uri', 'string')
112 7
            ->setAllowedValues('method', [
113 7
                SendMethods::CLASSIC,
114 7
                SendMethods::CLASSIC_PLUS,
115 7
                SendMethods::BASIC,
116 7
                SendMethods::TEST_CLASSIC,
117 7
                SendMethods::TEST_CLASSIC_PLUS,
118 7
                SendMethods::TEST_BASIC,
119 7
            ])
120
            ->setAllowedValues('validity_period', function (\DateInterval $value) {
121 7
                return $value->i >= ValidityPeriods::MIN && $value->i <= ValidityPeriods::MAX;
122 7
            })
123 7
            ->setAllowedValues('encoding_schema', [
124 7
                EncodingSchemas::NORMAL,
125 7
                EncodingSchemas::UCS2,
126 7
            ])
127 7
            ->setAllowedValues('charset', [
128 7
                Charsets::ISO_8859_1,
129 7
                Charsets::UTF8,
130 7
            ])
131 7
            ->setDefaults([
132 7
                'charset' => Charsets::UTF8,
133 7
                'validity_period' => \DateInterval::createFromDateString('2800 minutes'),
134 7
                'encoding_schema' => EncodingSchemas::NORMAL,
135
                'endpoint_uri' => Endpoints::REST_HTTPS
136 7
            ])
137
        ;
138 7
    }
139
140
    /**
141
     * @param Sms $sms
142
     *
143
     * @return array
144
     *
145
     * @throws NoRecipientsSpecifiedException
146
     */
147 7
    private function prepareRequest(Sms $sms)
148
    {
149 7
        if (! $sms->hasRecipients()) {
150 1
            throw new NoRecipientsSpecifiedException();
151
        }
152
153 6
        $sender_string = null;
154 6
        $sender_number = null;
155
        try {
156 6
            $sender_number = $this->normalizePhoneNumber($this->config['sender']);
157 6
        } catch (NumberParseException $e) {
158
            $sender_string = substr($this->config['sender'], 0, 11);
159
        }
160
161 6
        $deliveryStart = isset($this->config['delivery_start']) ? $this->config['delivery_start'] : null;
162 6
        if (null !== ($smsDeliveryStart = $sms->getDeliveryStart())) {
163 1
            $deliveryStart = $smsDeliveryStart;
164 1
        }
165
166 6
        $validityPeriod = isset($this->config['validity_period']) ? $this->config['validity_period'] : null;
167 6
        if (null !== ($smsValidityPeriod = $sms->getValidityPeriod())) {
168 1
            $validityPeriod = $smsValidityPeriod;
169 1
        }
170
171
        $request = [
172 6
            'username' => $this->config['username'],
173 6
            'password' => $this->config['password'],
174 6
            'method' => $this->config['method'],
175 6
            'sender_number' => '"' . $sender_number . '"',
176 6
            'sender_string' => $sender_string,
177 6
            'recipients' => $this->prepareRecipients($sms),
178 6
            'text' => str_replace(' ', '+', $sms->getText()),
179 6
            'user_reference' => $sms->getUserReference(),
180 6
            'delivery_start' => $deliveryStart ? $deliveryStart->format(\DateTime::RFC2822) : null,
181 6
            'validity_period' => $validityPeriod ? $validityPeriod->i : null,
182 6
            'encoding_scheme' => $this->config['encoding_schema'],
183 6
            'charset' => $this->config['charset'],
184 6
        ];
185
186 6
        $serializedRequest = "";
187 6
        foreach ($request as $key => $value) {
188 6
            $serializedRequest .= $key . '=' . $value . '&';
189 6
        }
190
191 6
        return rtrim($serializedRequest, '&');
192
    }
193
194
    /**
195
     * @param Sms $sms
196
     *
197
     * @return string
198
     */
199 6
    private function prepareRecipients(Sms $sms)
200
    {
201 6
        $recipients = $sms->getRecipients();
202
203 6
        if (! $sms->hasRecipientVariables()) {
204 3
            $recipients = array_map([$this, 'normalizePhoneNumber'], $recipients);
205 3
            return json_encode($recipients);
206
        }
207
208 3
        $recipientVariables = $sms->getRecipientVariables();
209
210 3
        return json_encode(array_map(function ($recipient) use ($recipientVariables) {
211 3
            $targetVariables = [];
212 3
            if (isset($recipientVariables[$recipient])) {
213 3
                $targetVariables = $recipientVariables[$recipient];
214 3
            }
215
216 3
            return array_merge(['recipient' => $this->normalizePhoneNumber($recipient)], $targetVariables);
217 3
        }, $recipients));
218
    }
219
220
    /**
221
     * @param string $phoneNumber
222
     *
223
     * @return string
224
     * @throws NumberParseException
225
     */
226 6
    private function normalizePhoneNumber($phoneNumber)
227
    {
228 6
        $utils = PhoneNumberUtil::getInstance();
229 6
        $parsed = $utils->parse(preg_replace('/^00/', '+', $phoneNumber), null);
230
231 6
        $phoneNumber = $utils->format($parsed, PhoneNumberFormat::E164);
232
233 6
        return substr($phoneNumber, 1);
234
    }
235
236
    /**
237
     * @param string $request
238
     *
239
     * @return Response
240
     */
241 6
    private function executeRequest($request)
242
    {
243 6
        $curl = curl_init();
244
245 6
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
246 6
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
247 6
        curl_setopt($curl, CURLOPT_TIMEOUT, 60);
248 6
        curl_setopt($curl, CURLOPT_POST, 1);
249 6
        curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
250 6
        curl_setopt($curl, CURLOPT_URL, $this->config['endpoint_uri']);
251
252 6
        $response = curl_exec($curl);
253
254 6
        curl_close($curl);
255
256 6
        return new Response($response);
257
    }
258
}
259