1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Comarch abstract base map file. |
5
|
|
|
* |
6
|
|
|
* The file is part of the paid functionality. Using the file is allowed only after purchasing a subscription. |
7
|
|
|
* File modification allowed only with the consent of the system producer. |
8
|
|
|
* |
9
|
|
|
* @package Integration |
10
|
|
|
* |
11
|
|
|
* @copyright YetiForce S.A. |
12
|
|
|
* @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) |
13
|
|
|
* @author Mariusz Krzaczkowski <[email protected]> |
14
|
|
|
*/ |
15
|
|
|
|
16
|
|
|
namespace App\Integrations\Comarch; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* Comarch abstract base map class. |
20
|
|
|
*/ |
21
|
|
|
abstract class Map |
22
|
|
|
{ |
23
|
|
|
/** @var string The name of the field with the identifier in Comarch */ |
24
|
|
|
const FIELD_NAME_ID = 'comarch_id'; |
25
|
|
|
/** @var string The name of the key with the identifier from Comarch */ |
26
|
|
|
const API_NAME_ID = 'id'; |
27
|
|
|
/** @var string Skip mode when data is incomplete */ |
28
|
|
|
public $skip = false; |
29
|
|
|
/** @var string Map module name. */ |
30
|
|
|
protected $moduleName; |
31
|
|
|
/** @var array Mapped fields. */ |
32
|
|
|
protected $fieldMap = []; |
33
|
|
|
/** @var array Data from Comarch. */ |
34
|
|
|
protected $dataApi = []; |
35
|
|
|
/** @var array Default data from Comarch. */ |
36
|
|
|
protected $defaultDataApi = []; |
37
|
|
|
/** @var array Data from YetiForce. */ |
38
|
|
|
protected $dataYf = []; |
39
|
|
|
/** @var array Default data from YetiForce. */ |
40
|
|
|
protected $defaultDataYf = []; |
41
|
|
|
/** @var \App\Integrations\Comarch\Synchronizer Synchronizer instance */ |
42
|
|
|
protected $synchronizer; |
43
|
|
|
/** @var array Dependent synchronizations to be performed during the operation */ |
44
|
|
|
protected $dependentSynchronizations = []; |
45
|
|
|
/** @var \Vtiger_Module_Model Module model instance */ |
46
|
|
|
protected $moduleModel; |
47
|
|
|
/** @var \Vtiger_Record_Model Record model instance */ |
48
|
|
|
protected $recordModel; |
49
|
|
|
/** @var string API map mode: create, update, get. */ |
50
|
|
|
protected $modeApi; |
51
|
|
|
|
52
|
|
|
/** @var string[] Mapped address fields. */ |
53
|
|
|
protected $addressMapFields = [ |
54
|
|
|
'addresslevel1' => [ |
55
|
|
|
'names' => ['get' => 'knt_Kraj', 'create' => 'Kraj', 'update' => 'Kraj'], 'fn' => 'convertCountry' |
56
|
|
|
], |
57
|
|
|
'addresslevel2' => ['names' => ['get' => 'knt_Wojewodztwo', 'create' => 'Wojewodztwo', 'update' => 'Wojewodztwo']], |
58
|
|
|
'addresslevel3' => ['names' => ['get' => 'knt_Powiat', 'create' => 'Powiat', 'update' => 'Powiat']], |
59
|
|
|
'addresslevel4' => ['names' => ['get' => 'knt_Gmina', 'create' => 'Gmina', 'update' => 'Gmina']], |
60
|
|
|
'addresslevel5' => ['names' => ['get' => 'knt_Miasto', 'create' => 'Miasto', 'update' => 'Miasto']], |
61
|
|
|
'addresslevel7' => ['names' => ['get' => 'knt_KodP', 'create' => 'KodP', 'update' => 'KodP']], |
62
|
|
|
'addresslevel8' => ['names' => ['get' => 'knt_Ulica', 'create' => 'Ulica', 'update' => 'Ulica']], |
63
|
|
|
'first_name_' => 'first_name', |
64
|
|
|
'last_name_' => 'last_name', |
65
|
|
|
'phone_' => ['name' => 'phone', 'fn' => 'convertPhone'], |
66
|
|
|
'email_' => 'email', |
67
|
|
|
'company_name_' => 'company', |
68
|
|
|
]; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Constructor. |
72
|
|
|
* |
73
|
|
|
* @param \App\Integrations\Comarch\Synchronizer $synchronizer |
74
|
|
|
*/ |
75
|
|
|
public function __construct(Synchronizer $synchronizer) |
76
|
|
|
{ |
77
|
|
|
$this->synchronizer = $synchronizer; |
78
|
|
|
$this->moduleModel = \Vtiger_Module_Model::getInstance($this->moduleName); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Set data from/for API. |
83
|
|
|
* |
84
|
|
|
* @param array $data |
85
|
|
|
*/ |
86
|
|
|
public function setDataApi(array $data): void |
87
|
|
|
{ |
88
|
|
|
if ($data) { |
|
|
|
|
89
|
|
|
$this->dataApi = $data; |
90
|
|
|
$this->modeApi = 'get'; |
91
|
|
|
} else { |
92
|
|
|
$this->dataApi = $this->defaultDataApi; |
93
|
|
|
$this->modeApi = ''; |
94
|
|
|
} |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* Set data from/for YetiForce. YetiForce data is read-only. |
99
|
|
|
* |
100
|
|
|
* @param array $data |
101
|
|
|
* @param bool $updateRecordModel |
102
|
|
|
* |
103
|
|
|
* @return void |
104
|
|
|
*/ |
105
|
|
|
public function setDataYf(array $data, bool $updateRecordModel = false): void |
106
|
|
|
{ |
107
|
|
|
$this->dataYf = $data; |
108
|
|
|
if ($updateRecordModel) { |
109
|
|
|
$this->recordModel = \Vtiger_Module_Model::getInstance($this->moduleName)->getRecordFromArray($data); |
110
|
|
|
} |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Set data from/for YetiForce by record ID. Read/Write YetiForce data. |
115
|
|
|
* |
116
|
|
|
* @param int $id |
117
|
|
|
* |
118
|
|
|
* @return void |
119
|
|
|
*/ |
120
|
|
|
public function setDataYfById(int $id): void |
121
|
|
|
{ |
122
|
|
|
$this->recordModel = \Vtiger_Record_Model::getInstanceById($id, $this->moduleName); |
123
|
|
|
$this->dataYf = $this->recordModel->getData(); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Checking what is the mode of operation to be performed in the API, |
128
|
|
|
* along with searching for the same entry in the API. |
129
|
|
|
* |
130
|
|
|
* @return void |
131
|
|
|
*/ |
132
|
|
|
public function loadModeApi(): void |
133
|
|
|
{ |
134
|
|
|
if (empty($this->modeApi)) { |
135
|
|
|
$this->modeApi = empty($this->dataYf[$this::FIELD_NAME_ID]) ? 'create' : 'update'; |
136
|
|
|
if (empty($this->dataApi['id']) && ($id = $this->findRecordInApi())) { |
137
|
|
|
$this->dataApi['id'] = $id; |
138
|
|
|
$this->modeApi = 'update'; |
139
|
|
|
} |
140
|
|
|
} |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Get API mode. |
145
|
|
|
* |
146
|
|
|
* @return string|null |
147
|
|
|
*/ |
148
|
|
|
public function getModeApi(): ?string |
149
|
|
|
{ |
150
|
|
|
return $this->modeApi; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* Load record model. |
155
|
|
|
* |
156
|
|
|
* @param int|null $id |
157
|
|
|
*/ |
158
|
|
|
public function loadRecordModel(?int $id = null): void |
159
|
|
|
{ |
160
|
|
|
if ($id) { |
|
|
|
|
161
|
|
|
$this->recordModel = \Vtiger_Record_Model::getInstanceById($id, $this->moduleName); |
162
|
|
|
} else { |
163
|
|
|
$this->recordModel = \Vtiger_Record_Model::getCleanInstance($this->moduleName); |
164
|
|
|
} |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* Get record model. |
169
|
|
|
* |
170
|
|
|
* @return \Vtiger_Record_Model |
171
|
|
|
*/ |
172
|
|
|
public function getRecordModel(): \Vtiger_Record_Model |
173
|
|
|
{ |
174
|
|
|
return $this->recordModel; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* Get module name. |
179
|
|
|
* |
180
|
|
|
* @return string |
181
|
|
|
*/ |
182
|
|
|
public function getModule(): string |
183
|
|
|
{ |
184
|
|
|
return $this->moduleName; |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* Return fields list. |
189
|
|
|
* |
190
|
|
|
* @return array |
191
|
|
|
*/ |
192
|
|
|
public function getFields(): array |
193
|
|
|
{ |
194
|
|
|
return $this->fieldMap; |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Return parsed data in YetiForce format. |
199
|
|
|
* |
200
|
|
|
* @param string $type |
201
|
|
|
* @param bool $mapped |
202
|
|
|
* |
203
|
|
|
* @return array |
204
|
|
|
*/ |
205
|
|
|
public function getDataYf(string $type = 'fieldMap', bool $mapped = true): array |
206
|
|
|
{ |
207
|
|
|
if ($mapped) { |
208
|
|
|
$this->dataYf = $this->defaultDataYf[$type] ?? []; |
209
|
|
|
foreach ($this->{$type} as $fieldCrm => $field) { |
210
|
|
|
if ($this->skip) { |
211
|
|
|
continue; |
212
|
|
|
} |
213
|
|
|
if (\is_array($field)) { |
214
|
|
|
if (!empty($field['direction']) && 'api' === $field['direction']) { |
215
|
|
|
continue; |
216
|
|
|
} |
217
|
|
|
$key = $field['name'] ?? ($field['names'][$this->modeApi] ?? ''); |
218
|
|
|
$field['fieldCrm'] = $fieldCrm; |
219
|
|
|
if (empty($key)) { |
220
|
|
|
$this->synchronizer->controller->log( |
221
|
|
|
"[API>YF][1] No key ($fieldCrm)", |
222
|
|
|
['fieldConfig' => $field, 'data' => $this->dataApi], |
223
|
|
|
null, |
224
|
|
|
true |
225
|
|
|
); |
226
|
|
|
} elseif (\is_array($key)) { |
227
|
|
|
$field['name'] = $key; |
228
|
|
|
$this->loadDataYfMultidimensional($fieldCrm, $field); |
229
|
|
|
} elseif (\array_key_exists($key, $this->dataApi)) { |
230
|
|
|
$this->loadDataYfMap($fieldCrm, $field); |
231
|
|
|
} elseif (!\array_key_exists('optional', $field) || empty($field['optional'])) { |
232
|
|
|
$error = "[API>YF][1] No column {$key} ($fieldCrm)"; |
233
|
|
|
\App\Log::warning($error, $this->synchronizer::LOG_CATEGORY); |
234
|
|
|
$this->synchronizer->controller->log($error, ['fieldConfig' => $field, 'data' => $this->dataApi], null, true); |
235
|
|
|
} |
236
|
|
|
} else { |
237
|
|
|
$this->dataYf[$fieldCrm] = $this->dataApi[$field] ?? null; |
238
|
|
|
if (!\array_key_exists($field, $this->dataApi)) { |
239
|
|
|
$error = "[API>YF][2] No column $field ($fieldCrm)"; |
240
|
|
|
\App\Log::warning($error, $this->synchronizer::LOG_CATEGORY); |
241
|
|
|
$this->synchronizer->controller->log($error, $this->dataApi, null, true); |
242
|
|
|
} |
243
|
|
|
} |
244
|
|
|
} |
245
|
|
|
} |
246
|
|
|
return $this->dataYf; |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
/** |
250
|
|
|
* Return parsed data in YetiForce format. |
251
|
|
|
* |
252
|
|
|
* @param bool $mapped |
253
|
|
|
* |
254
|
|
|
* @return array |
255
|
|
|
*/ |
256
|
|
|
public function getDataApi(bool $mapped = true): array |
257
|
|
|
{ |
258
|
|
|
if ($mapped) { |
259
|
|
|
if (!empty($this->dataYf[$this::FIELD_NAME_ID])) { |
260
|
|
|
$this->dataApi['id'] = $this->dataYf[$this::FIELD_NAME_ID]; |
261
|
|
|
} |
262
|
|
|
foreach ($this->fieldMap as $fieldCrm => $field) { |
263
|
|
|
if ($this->skip) { |
264
|
|
|
continue; |
265
|
|
|
} |
266
|
|
|
if (\is_array($field)) { |
267
|
|
|
if (!empty($field['direction']) && 'yf' === $field['direction']) { |
268
|
|
|
continue; |
269
|
|
|
} |
270
|
|
|
if (\array_key_exists($fieldCrm, $this->dataYf)) { |
271
|
|
|
$field['fieldCrm'] = $fieldCrm; |
272
|
|
|
if (isset($field['map'])) { |
273
|
|
|
$mapValue = array_search($this->dataYf[$fieldCrm], $field['map']); |
274
|
|
|
if (false !== $mapValue) { |
275
|
|
|
$this->setApiData($mapValue, $field); |
276
|
|
|
} elseif (empty($field['mayNotExist'])) { |
277
|
|
|
$error = "[YF>API] No value `{$this->dataYf[$fieldCrm]}` in map {$fieldCrm}"; |
278
|
|
|
\App\Log::warning($error, $this->synchronizer::LOG_CATEGORY); |
279
|
|
|
$this->synchronizer->controller->log($error, ['fieldConfig' => $field, 'data' => $this->dataYf], null, true); |
280
|
|
|
} |
281
|
|
|
} elseif (isset($field['fn'])) { |
282
|
|
|
$this->setApiData($this->{$field['fn']}($this->dataYf[$fieldCrm], $field, false), $field); |
283
|
|
|
} else { |
284
|
|
|
$this->setApiData($this->dataYf[$fieldCrm], $field); |
285
|
|
|
} |
286
|
|
|
} elseif (!\array_key_exists('optional', $field) || empty($field['optional'])) { |
287
|
|
|
$error = '[YF>API] No field ' . $fieldCrm; |
288
|
|
|
\App\Log::warning($error, $this->synchronizer::LOG_CATEGORY); |
289
|
|
|
$this->synchronizer->controller->log($error, ['fieldConfig' => $field, 'data' => $this->dataYf], null, true); |
290
|
|
|
} |
291
|
|
|
} else { |
292
|
|
|
$this->dataApi[$field] = $this->dataYf[$fieldCrm] ?? null; |
293
|
|
|
if (!\array_key_exists($fieldCrm, $this->dataYf)) { |
294
|
|
|
$error = '[YF>API] No field ' . $fieldCrm; |
295
|
|
|
\App\Log::warning($error, $this->synchronizer::LOG_CATEGORY); |
296
|
|
|
$this->synchronizer->controller->log($error, ['fieldConfig' => $field, 'data' => $this->dataYf], null, true); |
297
|
|
|
} |
298
|
|
|
} |
299
|
|
|
} |
300
|
|
|
} |
301
|
|
|
return $this->dataApi; |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
/** |
305
|
|
|
* Set the data to in the appropriate key structure. |
306
|
|
|
* |
307
|
|
|
* @param mixed $value |
308
|
|
|
* @param array $field |
309
|
|
|
* |
310
|
|
|
* @return void |
311
|
|
|
*/ |
312
|
|
|
public function setApiData($value, array $field): void |
313
|
|
|
{ |
314
|
|
|
$key = $field['name'] ?? ($field['names'][$this->modeApi] ?? ''); |
315
|
|
|
if (empty($key)) { |
316
|
|
|
$this->synchronizer->controller->log( |
317
|
|
|
"[API>YF][1] No key ({$field['fieldCrm']})", |
318
|
|
|
['fieldConfig' => $field, 'data' => $this->dataApi], |
319
|
|
|
null, |
320
|
|
|
true |
321
|
|
|
); |
322
|
|
|
} elseif (\is_array($key)) { |
323
|
|
|
foreach (array_reverse($key) as $name) { |
324
|
|
|
$value = [$name => $value]; |
325
|
|
|
} |
326
|
|
|
$this->dataApi = \App\Utils::merge($this->dataApi, $value); |
327
|
|
|
} else { |
328
|
|
|
$this->dataApi[$key] = $value; |
329
|
|
|
} |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
/** |
333
|
|
|
* Create/update product in YF. |
334
|
|
|
* |
335
|
|
|
* @return void |
336
|
|
|
*/ |
337
|
|
|
public function saveInYf(): void |
338
|
|
|
{ |
339
|
|
|
$moduleModel = $this->recordModel->getModule(); |
340
|
|
|
$errorLog = []; |
341
|
|
|
foreach ($this->dataYf as $key => $value) { |
342
|
|
|
if ($fieldModel = $moduleModel->getFieldByName($key)) { |
343
|
|
|
try { |
344
|
|
|
$fieldModel->getUITypeModel()->validate($value); |
345
|
|
|
$this->recordModel->set($key, $value); |
346
|
|
|
} catch (\Throwable $th) { |
347
|
|
|
$errorLog[$key] = [$value, $th->getMessage()]; // TODO weryfikacja |
348
|
|
|
} |
349
|
|
|
} |
350
|
|
|
} |
351
|
|
|
$this->setErrorLog($errorLog); |
352
|
|
|
if ($this->recordModel->isEmpty('assigned_user_id')) { |
353
|
|
|
$this->recordModel->set('assigned_user_id', $this->synchronizer->config->get('assigned_user_id')); |
354
|
|
|
} |
355
|
|
|
if ( |
356
|
|
|
$this->recordModel->isEmpty($this::FIELD_NAME_ID) |
357
|
|
|
&& ($id = $this->dataApi['id'] ?? $this->dataApi[$this::API_NAME_ID] ?? 0) |
358
|
|
|
&& $moduleModel->getFieldByName($this::FIELD_NAME_ID) |
359
|
|
|
&& !empty($id) |
360
|
|
|
) { |
361
|
|
|
$this->recordModel->set($this::FIELD_NAME_ID, $id); |
362
|
|
|
} |
363
|
|
|
$this->recordModel->set('comarch_server_id', $this->synchronizer->config->get('id')); |
364
|
|
|
$isNew = empty($this->recordModel->getId()); |
365
|
|
|
$this->recordModel->save(); |
366
|
|
|
$this->recordModel->ext['isNew'] = $isNew; |
367
|
|
|
if ($isNew && $this->recordModel->get($this::FIELD_NAME_ID)) { |
368
|
|
|
$this->synchronizer->updateMapIdCache( |
369
|
|
|
$this->recordModel->getModuleName(), |
370
|
|
|
$this->recordModel->get($this::FIELD_NAME_ID), |
371
|
|
|
$this->recordModel->getId() |
372
|
|
|
); |
373
|
|
|
} |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
/** |
377
|
|
|
* Create/update product by API. |
378
|
|
|
* |
379
|
|
|
* @return void |
380
|
|
|
*/ |
381
|
|
|
public function saveInApi(): void |
382
|
|
|
{ |
383
|
|
|
throw new \App\Exceptions\AppException('Method not implemented'); |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
/** |
387
|
|
|
* Save record in YF from relation action. |
388
|
|
|
* |
389
|
|
|
* @param array $field |
390
|
|
|
* |
391
|
|
|
* @return int |
392
|
|
|
*/ |
393
|
|
|
public function saveFromRelation(array $field): int |
394
|
|
|
{ |
395
|
|
|
$id = 0; |
396
|
|
|
if ($dataYf = $this->getDataYf()) { |
397
|
|
|
try { |
398
|
|
|
$id = $this->findRecordInYf(); |
399
|
|
|
if (empty($field['onlyCreate']) || empty($id)) { |
400
|
|
|
$this->loadRecordModel($id); |
401
|
|
|
$this->loadAdditionalData(); |
402
|
|
|
$this->saveInYf(); |
403
|
|
|
$id = $this->getRecordModel()->getId(); |
404
|
|
|
} |
405
|
|
|
} catch (\Throwable $ex) { |
406
|
|
|
$error = "[API>YF] Import {$this->moduleName}"; |
407
|
|
|
\App\Log::warning($error . "\n" . $ex->getMessage(), $this->synchronizer::LOG_CATEGORY); |
408
|
|
|
$this->synchronizer->controller->log($error, ['YF' => $dataYf, 'API' => $this->dataApi], $ex); |
409
|
|
|
} |
410
|
|
|
} |
411
|
|
|
return $id; |
|
|
|
|
412
|
|
|
} |
413
|
|
|
|
414
|
|
|
/** |
415
|
|
|
* Find record in YetiFoce. It can only be based on data from CRM `$this->dataApi`. |
416
|
|
|
* |
417
|
|
|
* @return int|null |
418
|
|
|
*/ |
419
|
|
|
public function findRecordInYf(): ?int |
420
|
|
|
{ |
421
|
|
|
return $this->synchronizer->getYfId($this->dataApi['id'], $this->moduleName); |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
/** |
425
|
|
|
* Find record in API. It can only be based on data from CRM `$this->dataYf`. |
426
|
|
|
* |
427
|
|
|
* @return int |
428
|
|
|
*/ |
429
|
|
|
public function findRecordInApi(): int |
430
|
|
|
{ |
431
|
|
|
return $this->synchronizer->getApiId($this->dataYf['id'], $this->moduleName); |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
/** |
435
|
|
|
* Load additional data. |
436
|
|
|
* |
437
|
|
|
* @return void |
438
|
|
|
*/ |
439
|
|
|
public function loadAdditionalData(): void |
440
|
|
|
{ |
441
|
|
|
} |
442
|
|
|
|
443
|
|
|
/** |
444
|
|
|
* Parse data to YetiForce format from multidimensional array. |
445
|
|
|
* |
446
|
|
|
* @param string $fieldCrm |
447
|
|
|
* @param array $field |
448
|
|
|
* |
449
|
|
|
* @return void |
450
|
|
|
*/ |
451
|
|
|
protected function loadDataYfMultidimensional(string $fieldCrm, array $field): void |
452
|
|
|
{ |
453
|
|
|
$value = $this->dataApi; |
454
|
|
|
$field['fieldCrm'] = $fieldCrm; |
455
|
|
|
foreach ($field['name'] as $name) { |
456
|
|
|
if (\array_key_exists($name, $value)) { |
457
|
|
|
$value = $value[$name]; |
458
|
|
|
} else { |
459
|
|
|
$error = "[API>YF][3] No column $name ($fieldCrm)"; |
460
|
|
|
if (!\array_key_exists('optional', $field) || empty($field['optional'])) { |
461
|
|
|
\App\Log::warning($error, $this->synchronizer::LOG_CATEGORY); |
462
|
|
|
$this->synchronizer->controller->log($error, ['fieldConfig' => $field, 'data' => $this->dataApi], null, true); |
463
|
|
|
} |
464
|
|
|
} |
465
|
|
|
} |
466
|
|
|
if (empty($error)) { |
467
|
|
|
$this->loadDataYfMap($fieldCrm, $field, $value); |
468
|
|
|
} |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
/** |
472
|
|
|
* Parse data to YetiForce format from map. |
473
|
|
|
* |
474
|
|
|
* @param string $fieldCrm |
475
|
|
|
* @param array $field |
476
|
|
|
* @param mixed|null $value |
477
|
|
|
* |
478
|
|
|
* @return void |
479
|
|
|
*/ |
480
|
|
|
protected function loadDataYfMap(string $fieldCrm, array $field, $value = null): void |
481
|
|
|
{ |
482
|
|
|
$key = $field['name'] ?? $field['names']['get']; |
483
|
|
|
$value ??= $this->dataApi[$key]; |
484
|
|
|
if (isset($field['map'])) { |
485
|
|
|
if (\array_key_exists($value, $field['map'])) { |
486
|
|
|
$this->dataYf[$fieldCrm] = $field['map'][$value]; |
487
|
|
|
} elseif (empty($field['mayNotExist'])) { |
488
|
|
|
$value = print_r($value, true); |
489
|
|
|
$error = "[API>YF] No value `{$value}` in map {$key}"; |
490
|
|
|
\App\Log::warning($error, $this->synchronizer::LOG_CATEGORY); |
491
|
|
|
$this->synchronizer->controller->log($error, ['fieldConfig' => $field, 'data' => $this->dataApi], null, true); |
492
|
|
|
} |
493
|
|
|
} elseif (isset($field['fn'])) { |
494
|
|
|
$this->dataYf[$fieldCrm] = $this->{$field['fn']}($value, $field, true); |
495
|
|
|
} else { |
496
|
|
|
$this->dataYf[$fieldCrm] = $value; |
497
|
|
|
} |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
/** |
501
|
|
|
* Find by relationship in YF by API ID. |
502
|
|
|
* |
503
|
|
|
* @param mixed $value |
504
|
|
|
* @param array $field |
505
|
|
|
* @param bool $fromApi |
506
|
|
|
* |
507
|
|
|
* @return int |
508
|
|
|
*/ |
509
|
|
|
protected function findByRelationship($value, array $field, bool $fromApi): int |
510
|
|
|
{ |
511
|
|
|
$moduleName = $field['moduleName'] ?? $this->moduleName; |
512
|
|
|
if (empty($value)) { |
513
|
|
|
return 0; |
514
|
|
|
} |
515
|
|
|
if ($fromApi) { |
516
|
|
|
return $this->synchronizer->getYfId($value, $moduleName); |
|
|
|
|
517
|
|
|
} |
518
|
|
|
return $this->synchronizer->getApiId($value, $moduleName); |
519
|
|
|
} |
520
|
|
|
|
521
|
|
|
/** |
522
|
|
|
* Add relationship in YF by API ID.findByRelationship. |
523
|
|
|
* |
524
|
|
|
* @param mixed $value |
525
|
|
|
* @param array $field |
526
|
|
|
* @param bool $fromApi |
527
|
|
|
* |
528
|
|
|
* @return string|array string (YF) or string (API) |
529
|
|
|
*/ |
530
|
|
|
protected function addRelationship($value, array $field, bool $fromApi) |
531
|
|
|
{ |
532
|
|
|
$moduleName = rtrim($field['moduleName'], 's'); |
533
|
|
|
$key = mb_strtolower($moduleName); |
534
|
|
|
if (null === $this->{$key}) { |
535
|
|
|
$this->{$key} = $this->synchronizer->getMapModel($moduleName); |
536
|
|
|
} |
537
|
|
|
$this->{$key}->setDataApi($this->dataApi); |
538
|
|
|
return $this->{$key}->saveFromRelation($field); |
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
/** |
542
|
|
|
* Find relationship in YF by API ID. |
543
|
|
|
* |
544
|
|
|
* @param mixed $value |
545
|
|
|
* @param array $field |
546
|
|
|
* @param bool $fromApi |
547
|
|
|
* |
548
|
|
|
* @return mixed |
549
|
|
|
*/ |
550
|
|
|
protected function findBySynchronizer($value, array $field, bool $fromApi) |
551
|
|
|
{ |
552
|
|
|
$synchronizer = $this->synchronizer->controller->getSync($field['synchronizer']); |
553
|
|
|
if ($fromApi) { |
554
|
|
|
$return = $synchronizer->getYfValue($value, $field); |
555
|
|
|
} else { |
556
|
|
|
$return = $synchronizer->getApiValue($value, $field); |
557
|
|
|
} |
558
|
|
|
if (null === $return && (!\array_key_exists('optional', $field) || empty($field['optional']))) { |
|
|
|
|
559
|
|
|
$this->skip = true; |
560
|
|
|
$this->synchronizer->controller->log( |
561
|
|
|
($fromApi ? '[API>YF]' : '[YF>API]') . |
562
|
|
|
"Skip value: {$value} (Field: {$field['fieldCrm']} ,Sync: {$field['synchronizer']})", |
563
|
|
|
['fieldConfig' => $field, 'data' => $this->dataApi], |
564
|
|
|
null, |
565
|
|
|
true |
566
|
|
|
); |
567
|
|
|
$this->setErrorLog([ |
568
|
|
|
$field['fieldCrm'] => [$value, 'ERR_REQUIRED_VALUE_MISSING'] // TODO weryfikacja |
569
|
|
|
]); |
570
|
|
|
} |
571
|
|
|
return $return; |
572
|
|
|
} |
573
|
|
|
|
574
|
|
|
/** |
575
|
|
|
* Run dependent synchronizer. |
576
|
|
|
* |
577
|
|
|
* @param bool $fromApi |
578
|
|
|
* |
579
|
|
|
* @return void |
580
|
|
|
*/ |
581
|
|
|
protected function runDependentSynchronizer(bool $fromApi): void |
582
|
|
|
{ |
583
|
|
|
if (empty($this->dependentSynchronizations)) { |
584
|
|
|
return; |
585
|
|
|
} |
586
|
|
|
foreach ($this->dependentSynchronizations as $synchronizer) { |
587
|
|
|
$synchronizer = $this->synchronizer->controller->getSync($synchronizer); |
588
|
|
|
if ($fromApi) { |
589
|
|
|
if (method_exists($synchronizer, 'importFromDependent')) { |
590
|
|
|
$synchronizer->importFromDependent($this); |
591
|
|
|
} |
592
|
|
|
} else { |
593
|
|
|
if (method_exists($synchronizer, 'exportFromDependent')) { |
594
|
|
|
$synchronizer->exportFromDependent($this); |
595
|
|
|
} |
596
|
|
|
} |
597
|
|
|
} |
598
|
|
|
} |
599
|
|
|
|
600
|
|
|
/** |
601
|
|
|
* Convert phone number to system YF format. |
602
|
|
|
* |
603
|
|
|
* @param mixed $value |
604
|
|
|
* @param array $field |
605
|
|
|
* @param bool $fromApi |
606
|
|
|
* |
607
|
|
|
* @return string |
608
|
|
|
*/ |
609
|
|
|
protected function convertPhone($value, array $field, bool $fromApi) |
610
|
|
|
{ |
611
|
|
|
if (empty($value) || !$fromApi) { |
612
|
|
|
return $value; |
613
|
|
|
} |
614
|
|
|
$fieldCrm = $field['fieldCrm']; |
615
|
|
|
$parsedData = [$fieldCrm => $value]; |
616
|
|
|
$parsedData = \App\Fields\Phone::parsePhone($fieldCrm, $parsedData); |
617
|
|
|
if (empty($parsedData[$fieldCrm])) { |
618
|
|
|
foreach ($parsedData as $key => $value) { |
|
|
|
|
619
|
|
|
$this->dataYf[$key] = $value; |
620
|
|
|
} |
621
|
|
|
return ''; |
622
|
|
|
} |
623
|
|
|
return $parsedData[$fieldCrm]; |
624
|
|
|
} |
625
|
|
|
|
626
|
|
|
/** |
627
|
|
|
* Convert country to system format. |
628
|
|
|
* |
629
|
|
|
* @param mixed $value |
630
|
|
|
* @param array $field |
631
|
|
|
* @param bool $fromApi |
632
|
|
|
* |
633
|
|
|
* @return string|null Country name (YF) or Country code (API) |
634
|
|
|
*/ |
635
|
|
|
protected function convertCountry($value, array $field, bool $fromApi) |
636
|
|
|
{ |
637
|
|
|
if (empty($value)) { |
638
|
|
|
return $value; |
639
|
|
|
} |
640
|
|
|
return $fromApi ? \App\Fields\Country::getCountryName($value) : \App\Fields\Country::getCountryCode($value); |
641
|
|
|
} |
642
|
|
|
|
643
|
|
|
/** |
644
|
|
|
* Convert currency. |
645
|
|
|
* |
646
|
|
|
* @param mixed $value |
647
|
|
|
* @param array $field |
648
|
|
|
* @param bool $fromApi |
649
|
|
|
* |
650
|
|
|
* @return int|string int (YF) or string (API) |
651
|
|
|
*/ |
652
|
|
|
protected function convertCurrency($value, array $field, bool $fromApi) |
653
|
|
|
{ |
654
|
|
|
if ($fromApi) { |
655
|
|
|
$currency = \App\Fields\Currency::getIdByCode($value); |
656
|
|
|
if (empty($currency)) { |
657
|
|
|
$currency = \App\Fields\Currency::addCurrency($value); |
658
|
|
|
} |
659
|
|
|
} else { |
660
|
|
|
$currency = \App\Fields\Currency::getById($value)['currency_code']; |
661
|
|
|
} |
662
|
|
|
return $currency; |
663
|
|
|
} |
664
|
|
|
|
665
|
|
|
/** |
666
|
|
|
* Set error logs. |
667
|
|
|
* |
668
|
|
|
* @param array $errorLog |
669
|
|
|
* |
670
|
|
|
* @return void |
671
|
|
|
*/ |
672
|
|
|
private function setErrorLog(array $errorLog): void |
673
|
|
|
{ |
674
|
|
|
$sid = $this->synchronizer->config->get('id'); |
675
|
|
|
$log = $this->recordModel->get('log_comarch'); |
676
|
|
|
$errors = \App\Json::isEmpty($log) ? [] : \App\Json::decode($log); |
677
|
|
|
if (!empty($errorLog)) { |
678
|
|
|
$errors[$sid] = $errorLog; |
679
|
|
|
} elseif (isset($errors[$sid])) { |
680
|
|
|
unset($errors[$sid]); |
681
|
|
|
} |
682
|
|
|
$this->recordModel->set('log_comarch', empty($errors) ? null : \App\Json::encode($log)); |
683
|
|
|
} |
684
|
|
|
} |
685
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.