Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
FacebookFacade.php
1<?php
2
4
14
16{
18 private $processor;
20 private $exportedProductRepository;
21
22 public function __construct(
23 FacebookProductProcessor $processor,
24 FacebookProductRepository $facebookProductRepository
25 )
26 {
27 $this->processor = $processor;
28 $this->exportedProductRepository = $facebookProductRepository;
29
30 if ($this->isExportAvailable() && $this->hasAuth())
31 {
33 \Bitrix\Catalog\v2\Integration\Iblock\BrandProperty::createFacebookBrandProperty();
34 }
35 else
36 {
38 }
39 }
40
41 public function refreshExportedProducts(array $ids): Result
42 {
43 $collection = $this->exportedProductRepository->loadCollection($ids);
44 $exportedProductsIds = $collection->getProductIdList();
45
46 if (!empty($exportedProductsIds))
47 {
48 return $this->exportProductsByIds($exportedProductsIds);
49 }
50
51 return new Result();
52 }
53
54 private function getProductEntitiesByIds(array $ids): array
55 {
56 if (empty($ids))
57 {
58 return [];
59 }
60
61 $skus = [];
62 foreach ($ids as $id)
63 {
64 $sku = ServiceContainer::getRepositoryFacade()->loadVariation($id);
65 if (!$sku)
66 {
67 continue;
68 }
69
70 $skus[] = $sku;
71 }
72
73 return $skus;
74 }
75
76 public function exportProductsByIds(array $ids): Result
77 {
78 $result = $this->checkRequirements();
79 if (!$result->isSuccess())
80 {
81 return $result;
82 }
83
84 $skus = $this->getProductEntitiesByIds($ids);
85
86 $result = $this->validateProducts($skus);
87 if (!$result->isSuccess())
88 {
89 return $result;
90 }
91
92 $preparedSku = $this->prepareProducts($skus);
93 $response =
94 $this
95 ->getCatalog()
96 ->batchCatalogProducts($preparedSku);
97
98 $result = new Result();
99 if ($response->isSuccess())
100 {
101 $responseData = $response->getData();
102 $queueId = $responseData['queue_ids'][0] ?? null;
103 $validationStatus = $responseData['validation_status'] ?? null;
104 $productKeys = array_keys($preparedSku);
105
106 if ($validationStatus)
107 {
108 $errorProducts = $this->parseValidationStatus($validationStatus);
109 $result->setData(['ERROR_PRODUCTS' => $errorProducts]);
110 $errorProductKeys = array_keys($errorProducts);
111 $productKeys = array_diff($productKeys, $errorProductKeys);
112 $this->exportedProductRepository->save($errorProducts);
113 }
114
115 if ($queueId)
116 {
117 \Bitrix\Catalog\v2\Integration\Seo\Entity\ExportedProductQueueTable::add([
118 'QUEUE_ID' => $queueId,
119 'PRODUCT_IDS' => \Bitrix\Main\Web\Json::encode($productKeys),
120 ]);
121 $result->setData(['QUEUE_ID' => $queueId]);
122 }
123 }
124 else
125 {
126 $result->addErrors($response->getErrors());
127 }
128
129 return $result;
130 }
131
132 public function validateProducts($skus): Result
133 {
134 $result = new Result();
135
136 foreach ($skus as $sku)
137 {
138 $res = $this->processor->validate($sku);
139 if (!$res->isSuccess())
140 {
141 $result->addErrors($res->getErrors());
142 }
143 }
144
145 return $result;
146 }
147
148 private function prepareProducts($skus): array
149 {
150 $preparedProducts = [];
151
152 foreach ($skus as $sku)
153 {
154 $result = $this->processor->prepare($sku);
155 if ($result->isSuccess())
156 {
157 foreach ($result->getData() as $key => $value)
158 {
159 $preparedProducts[$key] = $value;
160 }
161 }
162 }
163
164 return $preparedProducts;
165 }
166
167 private function getCatalog(): Catalog
168 {
169 static $catalog = null;
170
171 if ($catalog === null)
172 {
173 $service = Service::getInstance();
174 $catalog = $service->getCatalog($service::TYPE_FACEBOOK);
175 }
176
177 return $catalog;
178 }
179
180 public function isExportAvailable(): bool
181 {
182 // ToDo
183 // if (!ModuleManager::isModuleInstalled('bitrix24'))
184 // {
185 // return false;
186 // }
187
188 $region = \Bitrix\Main\Application::getInstance()->getLicense()->getRegion();
189 if ($region === null || $region === 'ru')
190 {
191 return false;
192 }
193
194 if (Option::get('catalog', 'fb_product_export_enabled', 'N') !== 'Y')
195 {
196 return false;
197 }
198
199 if (!Loader::includeModule('seo'))
200 {
201 return false;
202 }
203
204 return true;
205 }
206
207 public function checkRequirements(): Result
208 {
209 if (!$this->isExportAvailable())
210 {
211 return (new Result())->addError(new Error('Catalog export feature is not available.'));
212 }
213
214 return $this->getAuth();
215 }
216
217 public function hasAuth(): bool
218 {
219 return $this->getAuth()->isSuccess();
220 }
221
222 public function getPageId(): ?string
223 {
224 if ($this->hasAuth())
225 {
226 return $this->getCatalog()->getPageId();
227 }
228
229 return null;
230 }
231
232 public function getCatalogId(): ?string
233 {
234 if ($this->hasAuth())
235 {
236 return $this->getCatalog()->getCatalogId();
237 }
238
239 return null;
240 }
241
242 private function getAuth(): Result
243 {
244 $result = new Result();
245
246 if (!Loader::includeModule('seo'))
247 {
248 return $result->addError(new Error('The SEO module is not installed.'));
249 }
250
251 $service = Service::getInstance();
252
253 if (!$service::getAuthAdapter($service::TYPE_FACEBOOK)->hasAuth())
254 {
255 return $result->addError(new Error('Facebook account with business suite is not authorized.'));
256 }
257
258 if (!$this->getCatalog())
259 {
260 return $result->addError(new Error('Facebook account is not authorized to use catalog features.'));
261 }
262
263 return $result;
264 }
265
266 private function parseValidationStatus(array $validationStatus): array
267 {
268 $parsedProductErrors = [];
269 foreach ($validationStatus as $validationStatusElement)
270 {
271 $id = $this->processor->getProductIdByRetailerId($validationStatusElement['retailer_id']);
272 $error = $validationStatusElement['errors'][0]['message'] ?? null;
273 $parsedProductErrors[$id] = [
274 'ID' => $id,
275 'ERROR' => $error,
276 ];
277 }
278
279 return $parsedProductErrors;
280 }
281
282 public function getExportedProducts(array $productIds): array
283 {
284 return $this->exportedProductRepository->getProductsByIds($productIds);
285 }
286
287 private function getFacebookProductIds(array $productIds): array
288 {
289 $facebookProductIds = [];
290
291 $preparedProductIds = [];
292 foreach ($productIds as $productId)
293 {
294 $preparedProductIds[] = $this->processor->getEntityRetailerId($productId);
295 }
296
297 $response =
298 $this
299 ->getCatalog()
300 ->getProductsInfo($preparedProductIds)
301 ;
302
303 if (!$response->isSuccess())
304 {
305 return $facebookProductIds;
306 }
307
308 $productsInfo = $response->getData();
309 foreach ($productsInfo as $productInfo)
310 {
311 $facebookProductIds[] = $productInfo['id'];
312 }
313
314 return $facebookProductIds;
315 }
316
317 private function processWebhook(int $queueId, array $errors): void
318 {
319 $queueData = ExportedProductQueueTable::getByPrimary($queueId)->fetch();
320 if (!$queueData)
321 {
322 return;
323 }
324 ExportedProductQueueTable::delete($queueId);
325
326 $preparedErrors = [];
327 foreach ($errors as $error)
328 {
329 $preparedErrors[$this->processor->getProductIdByRetailerId($error['id'])] = $error['message'];
330 }
331 $productIds = \Bitrix\Main\Web\Json::decode($queueData['PRODUCT_IDS']);
332 $preparedProducts = [];
333 foreach ($productIds as $productId)
334 {
335 $preparedProducts[$productId] = [
336 'ID' => $productId,
337 'ERROR' => $preparedErrors[$productId],
338 ];
339 }
340
341 $this->exportedProductRepository->save($preparedProducts);
342
343 $facebookProductIds = [];
344 if (empty($preparedErrors))
345 {
346 $facebookProductIds = $this->getFacebookProductIds($productIds);
347 }
348
349 $event = new \Bitrix\Main\Event(
350 'catalog',
351 'onFacebookCompilationExportFinished',
352 [
353 'QUEUE_ID' => $queueId,
354 'ERROR_PRODUCTS' => $preparedErrors,
355 'FACEBOOK_PRODUCT_IDS' => $facebookProductIds,
356 ]
357 );
358 $event->send();
359 }
360
361 public static function onCatalogWebhookHandler($event): void
362 {
363 if (!Loader::includeModule('crm'))
364 {
365 return;
366 }
367 $crmCatalogIblockId = \CCrmCatalog::EnsureDefaultExists() ?: 0;
368 $instance = ServiceContainer::get('integration.seo.facebook.facade', [
369 'iblockId' => $crmCatalogIblockId,
370 ]);
371 $queueId = $event->getParameter('payload')['id'];
372 $errors = Json::decode($event->getParameter('payload')['errors']);
373 $instance->processWebhook($queueId, $errors);
374 }
375}
__construct(FacebookProductProcessor $processor, FacebookProductRepository $facebookProductRepository)
addError(Error $error)
Definition result.php:50