Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
importmanager.php
1<?php
2
4
21
23{
24 private const CALENDAR_LIST_URL_CALENDAR_ID = '/users/me/calendarList/%CALENDAR_ID%';
25 private const EVENT_LIST_URL_CALENDAR_ID = '/calendars/%CALENDAR_ID%/events';
26 private const CALENDAR_LIST_URL = '/users/me/calendarList';
27 private const CALENDAR_PRIMARY_ID = 'primary';
28 public const SYNC_EVENTS_DATE_INTERVAL = '1 months';
29 private const SYNC_EVENTS_LIMIT = 50;
30
34 protected ?string $syncToken = null;
38 protected ?string $pageToken = null;
42 protected ?string $etag = null;
46 protected ?array $defaultRemind = null;
50 protected ?Date $modified = null;
54 protected ?string $lastSyncStatus = null;
59
63 public function requestConnectionId(): Result
64 {
65 $result = new Result();
66 try
67 {
68 // TODO: Remake it: move this logic to parent::request().
69 // Or, better, in separate class.
70 $this->httpClient->query(
72 $this->prepareCalendarListUrlWithId(self::CALENDAR_PRIMARY_ID)
73 );
74
75 try
76 {
77 $externalResult = $this->parseResponse($this->httpClient->getResult());
78 }
79 catch (\Exception $e)
80 {
81 return $result->addError(new Error($e->getMessage()));
82 }
83
84 if ($this->isRequestSuccess())
85 {
86 $requestResult = $this->parseResponse($this->httpClient->getResult());
87
88 return $result->setData(['id' => $requestResult['id']]);
89 }
90 $helper = new Helper();
91
92 if ($helper->isNotValidSyncTokenError($this->prepareError($externalResult)))
93 {
94 $this->connection->setToken(null);
95 $result->addError(new Error('Auth error on getting connection Id', 410));
96 return $result;
97 }
98
99 if ($helper->isMissingRequiredAuthCredential($this->prepareError($externalResult)))
100 {
101 $this->handleUnauthorize($this->connection);
102 $result->addError(new Error('Auth error on getting sections', 401));
103
104 return $result;
105 }
106
107 return $result->addError(new Error('Do not sync sections'));
108 }
109 catch (\Exception $e)
110 {
111 return $result->addError(new Error('Failed to get connection name'));
112 }
113 }
114
118 public function getSections(): Result
119 {
120 $result = new Result();
121 //todo handle errors
122 try
123 {
124 // TODO: Remake it: move this logic to parent::request().
125 // Or, better, in separate class.
126 $this->httpClient->query(
128 $this->prepareCalendarListUrl()
129 );
130
131 try
132 {
133 $externalResult = $this->parseResponse($this->httpClient->getResult());
134 }
135 catch (\Exception $e)
136 {
137 return $result->addError(new Error($e->getMessage()));
138 }
139
140 if ($this->isRequestSuccess())
141 {
142 $this->connection->setToken($externalResult['nextSyncToken']);
143 $this->etag = $externalResult['etag'];
144 $this->connection->setStatus('[200] OK')
145 ->setLastSyncTime(new Date())
146 ;
147
148 $map = new SyncSectionMap();
149 if (!empty($externalResult['items']) && is_array($externalResult['items']))
150 {
151 foreach ($externalResult['items'] as $item)
152 {
153 $map->add(
154 (new BuilderSyncSectionFromExternalData($item, $this->connection))->build(),
155 $item['id']
156 );
157 }
158 }
159
160 return $result->setData(['externalSyncSectionMap' => $map]);
161 }
162
163 $helper = new Helper();
164
165 if ($helper->isNotValidSyncTokenError($this->prepareError($externalResult)))
166 {
167 $this->connection->setToken(null);
168
169 return $this->getSections();
170 }
171
172 if ($helper->isMissingRequiredAuthCredential($this->prepareError($externalResult)))
173 {
174 $this->handleUnauthorize($this->connection);
175 $result->addError(new Error('Auth error on getting sections', 401));
176
177 return $result;
178 }
179
180 $result->addError(new Error('Do not sync sections'));
181 }
182 catch (\Exception $e)
183 {
184 $result->addError(new Error('Failed to get sections'));
185 }
186
187 return $result;
188 }
189
194 public function getEvents(SyncSection $syncSection): Result
195 {
196 $map = new SyncEventMap();
197 $result = (new Result())->setData([
198 'externalSyncEventMap' => $map,
199 ]);
200
201 try
202 {
203 // TODO: Remake it: move this logic to parent::request().
204 // Or, better, in separate class.
205 $this->syncSectionConnection = $syncSection->getSectionConnection();
206 $this->httpClient->query(
208 $this->prepareEventListUrl(
209 $this->syncSectionConnection->getVendorSectionId(),
210 $this->prepareRequestParams($this->syncSectionConnection)
211 )
212 );
213
214 try
215 {
216 $externalResult = $this->parseResponse($this->httpClient->getResult());
217 }
218 catch (\Exception $e)
219 {
220 return $result->addError(new Error($e->getMessage()));
221 }
222
223
224 if ($this->isRequestSuccess())
225 {
226 $impatientInstanceListByUid = [];
227
228 $this->etag = $externalResult['etag'];
229 $this->syncToken = $externalResult['nextSyncToken'] ?? null;
230 $this->pageToken = $externalResult['nextPageToken'] ?? null;
231 $this->lastSyncStatus = \Bitrix\Calendar\Sync\Dictionary::SYNC_SECTION_ACTION['success'];
232
233 $this->handleSuccessBehavior($externalResult);
234
235 if (!empty($externalResult['items']) && is_array($externalResult['items']))
236 {
237 foreach ($externalResult['items'] as $item)
238 {
239 $syncEvent = (new BuilderSyncEventFromExternalData($item, $this->connection, $syncSection))
240 ->build();
241
242 if ($syncEvent->isInstance() || $syncEvent->getVendorRecurrenceId())
243 {
245 $masterEvent = $map->has($syncEvent->getVendorRecurrenceId())
246 ? $map->getItem($syncEvent->getVendorRecurrenceId())
247 : null
248 ;
249
250 if (!$masterEvent)
251 {
252 $impatientInstanceListByUid[$syncEvent->getVendorRecurrenceId()][] = $syncEvent;
253 continue;
254 }
255
256 $masterEvent->addInstance($syncEvent);
257 }
258 else
259 {
260 if ($syncEvent->isRecurrence()
261 && ($instanceList = ($impatientInstanceListByUid[$syncEvent->getUid()] ?? null))
262 )
263 {
264 $syncEvent->addInstanceList($instanceList);
265 unset($impatientInstanceListByUid[$syncEvent->getUid()]);
266 }
267
268 $map->add($syncEvent, $syncEvent->getVendorEventId());
269 }
270 }
271 }
272
273 foreach ($impatientInstanceListByUid as $syncEventList)
274 {
275 foreach($syncEventList as $syncEvent)
276 {
277 $map->add($syncEvent, $syncEvent->getVendorEventId());
278 }
279 }
280
281 return $result;
282 }
283
284 $helper = new Helper();
285
286 if ($helper->isNotValidSyncTokenError($this->prepareError($externalResult)))
287 {
288 $syncSection->getSectionConnection()->setSyncToken(null);
289
290 return $this->getEvents($syncSection);
291 }
292
293 if ($helper->isMissingRequiredAuthCredential($this->prepareError($externalResult)))
294 {
295 $this->handleUnauthorize($this->connection);
296 $result->addError(new Error('Auth error on getting events', 401));
297
298 return $result;
299 }
300
301 $this->handleErroneousBehavior($syncSection);
302 }
303 catch (BaseException $e)
304 {
305 $result->addError(new Error($e->getMessage()));
306 }
307
308 return $result;
309 }
310
314 public function getSectionConnection(): Result
315 {
316 return (new Result())->setData(['sectionConnection' => new SectionConnection()]);
317 }
318
322 public function getStatus(): ?string
323 {
325 }
326
330 public function getConnection(): Result
331 {
332 return (new Result())->setData([
333 'connection' => $this->connection,
334 ]);
335 }
336
340 public function getSyncToken(): ?string
341 {
342 return $this->syncToken;
343 }
344
348 public function getPageToken(): ?string
349 {
350 return $this->pageToken;
351 }
352
356 public function getEtag(): ?string
357 {
358 return $this->etag;
359 }
360
364 public function getDefaultRemind(): ?array
365 {
367 }
368
372 public function getModified(): ?Date
373 {
374 return $this->modified;
375 }
376
382 private function prepareSectionResult(string $result)
383 {
384 return Json::decode($result);
385 }
386
390 private function prepareCalendarListUrl(): string
391 {
392 $requestParams = '';
393
394 if ($token = $this->connection->getToken())
395 {
396 $requestParams = '?' . http_build_query([
397 'showDeleted' => 'true',
398 'showHidden' => 'true',
399 'syncToken' => $token,
400 ]);
401 $requestParams = preg_replace('/(%3D)/', '=', $requestParams);
402 }
403
404 return $this->connection->getVendor()->getServer()->getFullPath()
405 . self::CALENDAR_LIST_URL
406 . $requestParams
407 ;
408 }
409
414 private function prepareCalendarListUrlWithId(string $calendarId): string
415 {
416 return Server::mapUri(
417 $this->connection->getVendor()->getServer()->getFullPath() . self::CALENDAR_LIST_URL_CALENDAR_ID,
418 [
419 '%CALENDAR_ID%' => $calendarId,
420 ]
421 );
422 }
423
429 private function prepareEventListUrl(string $calendarId, array $requestParams = []): string
430 {
431 $url = Server::mapUri(
432 $this->connection->getVendor()->getServer()->getFullPath() . self::EVENT_LIST_URL_CALENDAR_ID,
433 [
434 '%CALENDAR_ID%' => urlencode($calendarId),
435 ]
436 );
437
438 if (!empty($requestParams))
439 {
440 $url .= '?' . preg_replace('/(%3D)/', '=', http_build_query($requestParams));
441 }
442
443 return $url;
444 }
445
451 private function parseResponse(string $result)
452 {
453 return Json::decode($result);
454 }
455
460 private function handleErroneousBehavior(SyncSection $syncSection): void
461 {
462 $sectionConnection = $syncSection->getSectionConnection();
463 if ($sectionConnection)
464 {
465 $this->syncToken = $sectionConnection->getSyncToken();
466 $this->pageToken = $sectionConnection->getPageToken();
467 $this->etag = $sectionConnection->getVersionId();
468 $this->modified = $sectionConnection->getLastSyncDate();
469 }
470 }
471
477 private function handleSuccessBehavior($result): void
478 {
479 $this->syncSectionConnection->setSyncToken($result['nextSyncToken'] ?? null);
480 $this->syncSectionConnection->setPageToken($result['nextPageToken'] ?? null);
481 // $this->pageToken = $result['nextPageToken'];
482 // $this->etag = $result['etag'];
483 $this->syncSectionConnection->setVersionId($result['etag'] ?? null);
484 $this->defaultRemind = $result['defaultReminders'][0] ?? null;
485 $this->modified = ($result['updated'] ?? null)
486 ? Date::createDateTimeFromFormat($result['updated'], Helper::DATE_TIME_FORMAT_WITH_MICROSECONDS)
487 : new Date()
488 ;
489 // TODO: Remake it: Overdependence from $this->httpClient
490 $status = $this->httpClient->getStatus();
491 $this->lastSyncStatus = \Bitrix\Calendar\Sync\Dictionary::SYNC_SECTION_ACTION['success'];
492 }
493
498 private function getRequestParamsWithSyncToken(SectionConnection $sectionConnection): array
499 {
500 return [
501 'pageToken' => $sectionConnection->getPageToken(),
502 'syncToken' => $sectionConnection->getSyncToken(),
503 'showDeleted' => 'true',
504 ];
505 }
506
511 private function getRequestParamsForFirstSync(SectionConnection $sectionConnection): array
512 {
513 return [
514 'pageToken' => $sectionConnection->getPageToken(),
515 'showDeleted' => 'true',
516 'maxResults' => self::SYNC_EVENTS_LIMIT,
517 'timeMin' => (new Date())->sub(self::SYNC_EVENTS_DATE_INTERVAL)->format(Helper::DATE_TIME_FORMAT_WITH_MICROSECONDS),
518 ];
519 }
520
526 public function prepareError(array $error = null): string
527 {
528 if (
529 isset($error['error']['code'], $error['error']['message'])
530 && $error !== null
531 )
532 {
533 return '['
534 . $error['error']['code']
535 . ']'
536 . ' '
537 . $error['error']['message']
538 ;
539 }
540
541 return '';
542 }
547 private function prepareRequestParams(SectionConnection $sectionConnection): array
548 {
549 return array_filter($sectionConnection->getSyncToken()
550 ? $this->getRequestParamsWithSyncToken($sectionConnection)
551 : $this->getRequestParamsForFirstSync($sectionConnection)
552 );
553 }
554}
setData(array $data)
Definition result.php:113