Passed
Push — developer ( 222604...e778d2 )
by Radosław
18:37
created

SMSAPI::setPhone()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
dl 0
loc 8
rs 10
c 1
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * SMSAPI - sms provider file.
4
 *
5
 * The file is part of the paid functionality. Using the file is allowed only after purchasing a subscription.
6
 * File modification allowed only with the consent of the system producer.
7
 *
8
 * @copyright YetiForce S.A.
9
 * @license   YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com)
10
 * @author    Radosław Skrzypczak <[email protected]>
11
 */
12
13
namespace App\Integrations\SMSProvider;
14
15
/**
16
 * SMSAPI - sms provider class.
17
 */
18
class SMSAPI extends Provider
19
{
20
	/** {@inheritdoc} */
21
	protected $name = 'SMSAPI';
22
23
	/** {@inheritdoc} */
24
	protected $url = 'https://api.smsapi.pl/sms.do';
25
26
	/** @var string Backup address URL */
27
	protected $urlBackup = 'https://api2.smsapi.pl/sms.do';
28
29
	/** @var string Encoding */
30
	public $encoding = 'utf-8';
31
32
	/** @var string Format */
33
	public $format = 'json';
34
35
	/** @var \GuzzleHttp\Psr7\Response Response object */
36
	private $response;
37
38
	/** @var array Response body */
39
	private $responseData;
40
41
	/**
42
	 * Required fields.
43
	 *
44
	 * @return string[]
45
	 */
46
	public function getRequiredParams(): array
47
	{
48
		return ['to', 'idx', 'from', 'message'];
49
	}
50
51
	/**
52
	 * Function to get service URL.
53
	 *
54
	 * @param bool $useBackup
55
	 *
56
	 * @return string
57
	 */
58
	public function getUrl(bool $useBackup = false): string
59
	{
60
		return $useBackup ? $this->urlBackup : $this->url;
61
	}
62
63
	/**
64
	 * Set response.
65
	 *
66
	 * @param \GuzzleHttp\Psr7\Response $response
67
	 *
68
	 * @return $this
69
	 */
70
	public function setResponse($response): self
71
	{
72
		$this->response = $response;
73
		$this->responseData = \App\Json::decode($this->response->getBody()) ?? [];
0 ignored issues
show
Documentation Bug introduced by
It seems like App\Json::decode($this->...->getBody()) ?? array() can also be of type string. However, the property $responseData is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
74
75
		return $this;
76
	}
77
78
	/**
79
	 * Check if the message was sent successfully.
80
	 *
81
	 * @return bool
82
	 */
83
	public function isSuccess(): bool
84
	{
85
		return $this->response && 200 === $this->response->getStatusCode() && empty($this->responseData['error']);
86
	}
87
88
	/**
89
	 * Set phone number.
90
	 *
91
	 * @param string $phoneNumber
92
	 *
93
	 * @return $this
94
	 */
95
	public function setPhone(string $phoneNumber): self
96
	{
97
		$phoneNumber = preg_replace_callback('/[^\d]/s', function () {
98
			return '';
99
		}, $phoneNumber);
100
		$this->set('to', $phoneNumber);
101
102
		return $this;
103
	}
104
105
	/**
106
	 * Get body data.
107
	 *
108
	 * @return array
109
	 */
110
	private function getBody(): array
111
	{
112
		$params = [
113
			'encoding' => $this->encoding,
114
			'format' => $this->format
115
		];
116
		foreach ($this->getRequiredParams() as $key) {
117
			$params[$key] = $this->get($key) ?? '';
118
		}
119
120
		return $params;
121
	}
122
123
	/** {@inheritdoc} */
124
	public function send(bool $useBackup = false): bool
125
	{
126
		try {
127
			$uri = $this->getUrl($useBackup);
128
			\App\Log::beginProfile('POST|' . __METHOD__ . "|{$uri}", 'SMSNotifier');
129
			$response = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->request('POST', $uri, [
130
				'headers' => $this->getHeaders(),
131
				'json' => $this->getBody()
132
			]);
133
			$this->setResponse($response);
134
			\App\Log::endProfile('POST|' . __METHOD__ . "|{$uri}", 'SMSNotifier');
135
		} catch (\Throwable $e) {
136
			\App\Log::error($e->__toString());
137
			return false;
138
		}
139
140
		return $this->isSuccess();
141
	}
142
143
	/** {@inheritdoc} */
144
	public function getEditFields(): array
145
	{
146
		$fields = [];
147
		foreach (['api_key', 'from', 'type'] as $fieldName) {
148
			$fields[$fieldName] = $this->getFieldInstanceByName($fieldName);
149
		}
150
151
		return $fields;
152
	}
153
154
	/**
155
	 * Fields to edit in settings.
156
	 *
157
	 * @param string $name
158
	 *
159
	 * @return \Vtiger_Field_Model
160
	 */
161
	public function getFieldInstanceByName(string $name)
162
	{
163
		$moduleName = 'Settings:SMSNotifier';
164
		$field = ['uitype' => 16, 'column' => $name, 'name' => $name, 'displaytype' => 1, 'typeofdata' => 'V~M', 'presence' => 0, 'isEditableReadOnly' => false];
165
		switch ($name) {
166
				case 'api_key':
167
					$field['uitype'] = 99;
168
					$field['label'] = 'FL_API_KEY';
169
					$field['purifyType'] = \App\Purifier::ALNUM;
170
					$field['fromOutsideList'] = true;
171
					$field['maximumlength'] = '100';
172
					$field['fieldvalue'] = $this->has($name) ? $this->get($name) : '';
173
					break;
174
				case 'from':
175
					$field['uitype'] = 1;
176
					$field['label'] = 'FL_SMSAPI_FROM';
177
					$field['typeofdata'] = 'V~O';
178
					$field['maximumlength'] = '11';
179
					$field['purifyType'] = \App\Purifier::TEXT;
180
					$field['fieldvalue'] = $this->has($name) ? $this->get($name) : '';
181
					break;
182
				case 'type':
183
					$field['uitype'] = 16;
184
					$field['label'] = 'FL_SMSAPI_TYPE';
185
					$field['typeofdata'] = 'V~O';
186
					$field['purifyType'] = \App\Purifier::STANDARD;
187
					$field['fieldvalue'] = $this->has($name) ? $this->get($name) : '';
188
					$field['picklistValues'] = ['SMS' => 'SMS', 'VMS' => 'VMS', 'MMS' => 'MMS'];
189
					break;
190
				case 'tts_lector':
191
					$field['uitype'] = 1;
192
					$field['label'] = 'FL_SMSAPI_TTS_LECTOR';
193
					$field['purifyType'] = \App\Purifier::STANDARD;
194
					$field['fieldvalue'] = $this->has($name) ? $this->get($name) : '';
195
					break;
196
				default:
197
					$field = [];
198
					break;
199
			}
200
201
		return $field ? \Vtiger_Field_Model::init($moduleName, $field, $name) : null;
202
	}
203
204
	/**
205
	 * Function to get Edit view url.
206
	 *
207
	 * @return string Url
208
	 */
209
	public function getEditViewUrl(): string
210
	{
211
		$model = \Settings_Vtiger_Module_Model::getInstance('Settings:SMSNotifier');
212
		return "index.php?module={$model->getName()}&parent={$model->getParentName()}&view={$this->name}&provider={$this->name}";
213
	}
214
215
	/**
216
	 * Callback service URL.
217
	 *
218
	 * @param array  $service
219
	 * @param string $type    Action name for werservice
220
	 *
221
	 * @return string
222
	 */
223
	public function getCallBackUrlByService(array $service, string $type): string
224
	{
225
		$callBackUrl = \App\Config::main('site_URL') . 'webservice.php?';
226
		$serviceId = (int) $service['server_id'];
227
		$server = \Settings_WebserviceApps_Record_Model::getInstanceById($serviceId);
228
		$apiKey = \App\Encryption::getInstance()->decrypt($server->get('api_key'));
229
		$params = [
230
			'_container' => 'SMS',
231
			'module' => 'SMSAPI',
232
			'action' => $type,
233
			'x-api-key' => $apiKey,
234
			'x-token' => $service['token'],
235
		];
236
237
		return $callBackUrl . http_build_query($params);
238
	}
239
240
	/** {@inheritdoc} */
241
	public function sendByRecord(\Vtiger_Record_Model $recordModel): bool
242
	{
243
		$this->setPhone($recordModel->get('phone'));
244
		$this->set('idx', $recordModel->getId());
245
		$this->set('message', $recordModel->get('message'));
246
		$result = $this->send() ?: $this->send(true);
247
		if ($result && !empty($this->responseData['list'][0]['id'])) {
248
			$recordModel->set('msgid', $this->responseData['list'][0]['id']);
249
		}
250
251
		return $result;
252
	}
253
}
254