Model/Product/Feed/Method/BatchApi.php (87 lines of code) (raw):
<?php /** @noinspection PhpUndefinedFieldInspection */
/**
* Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Product\Feed\Method;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Model\Product\Feed\Builder;
use Facebook\BusinessExtension\Model\Product\Feed\ProductRetriever\Configurable as ConfigurableProductRetriever;
use Facebook\BusinessExtension\Model\Product\Feed\ProductRetriever\Simple as SimpleProductRetriever;
use Facebook\BusinessExtension\Model\Product\Feed\ProductRetrieverInterface;
use Magento\Catalog\Model\Product;
use Magento\Framework\Exception\LocalizedException;
class BatchApi
{
const ATTR_METHOD = 'method';
const ATTR_UPDATE = 'UPDATE';
const ATTR_DATA = 'data';
// Process only the maximum allowed by API per request
const BATCH_MAX = 4999;
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var ProductRetrieverInterface[]
*/
protected $productRetrievers;
/**
* @var Builder
*/
protected $builder;
/**
* @param FBEHelper $helper
* @param SimpleProductRetriever $simpleProductRetriever
* @param ConfigurableProductRetriever $configurableProductRetriever
* @param Builder $builder
*/
public function __construct(
FBEHelper $helper,
SimpleProductRetriever $simpleProductRetriever,
ConfigurableProductRetriever $configurableProductRetriever,
Builder $builder
) {
$this->fbeHelper = $helper;
$this->productRetrievers = [
$simpleProductRetriever,
$configurableProductRetriever
];
$this->builder = $builder;
}
/**
* @param Product $product
* @param string $method
* @return array
* @throws LocalizedException
*/
public function buildProductRequest(Product $product, $method = self::ATTR_UPDATE)
{
return [
self::ATTR_METHOD => $method,
self::ATTR_DATA => $this->builder->buildProductEntry($product)
];
}
/**
* @param null $accessToken
* @return array
* @throws \Exception
*/
public function generateProductRequestData($accessToken = null)
{
$currentBatch = 1;
$requests = [];
$responses = [];
$exceptions = 0;
foreach ($this->productRetrievers as $productRetriever) {
$offset = 0;
$limit = $productRetriever->getLimit();
do {
$products = $productRetriever->retrieve($offset);
$offset += $limit;
if (empty($products)) {
break;
}
foreach ($products as $product) {
try {
$requests[] = $this->buildProductRequest($product);
} catch (\Exception $e) {
$exceptions++;
// Don't overload the logs, log the first 3 exceptions
if ($exceptions <= 3) {
$this->fbeHelper->logException($e);
}
// If it looks like a systemic failure : stop feed generation
if ($exceptions > 100) {
throw $e;
}
}
if (count($requests) === self::BATCH_MAX) {
$this->fbeHelper->log(
sprintf('Pushing batch %d with %d products', $currentBatch, count($requests))
);
$response = $this->fbeHelper->makeHttpRequest($requests, $accessToken);
$this->fbeHelper->log('Product push response ' . json_encode($response));
$responses[] = $response;
unset($requests);
$currentBatch++;
}
}
} while (true);
}
if (!empty($requests)) {
$this->fbeHelper->log(sprintf('Pushing batch %d with %d products', $currentBatch, count($requests)));
$response = $this->fbeHelper->makeHttpRequest($requests, $accessToken);
$this->fbeHelper->log('Product push response ' . json_encode($response));
$responses[] = $response;
}
return $responses;
}
}