171 lines
5.2 KiB
PHP
171 lines
5.2 KiB
PHP
<?php
|
|
|
|
namespace KupShop\FeedGeneratorBundle\Feed;
|
|
|
|
use KupShop\FeedGeneratorBundle\Exception\XMLFeedReader\UnreadableXMLException;
|
|
use KupShop\FeedGeneratorBundle\Exception\XMLFeedReader\XMLFeedReaderException;
|
|
use KupShop\FeedGeneratorBundle\Exception\XSDParser\XSDParsingException;
|
|
use KupShop\FeedGeneratorBundle\Utils\ExternalFeedCache;
|
|
use KupShop\FeedGeneratorBundle\V8FeedGenerator;
|
|
use KupShop\FeedGeneratorBundle\Wrapper\ExternalFeedObjectWrapper;
|
|
use KupShop\FeedGeneratorBundle\XMLFeedReader;
|
|
use KupShop\FeedGeneratorBundle\XSD\Parser;
|
|
use KupShop\FeedsBundle\FeedProductList;
|
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
|
|
|
class ExternalFeed implements IExternalFeed
|
|
{
|
|
use ConfigurableFeedTrait;
|
|
|
|
public const TYPE_DESCRIPTION = 'feed_description_url';
|
|
public const TYPE_SOURCE = 'feed_source_url';
|
|
|
|
protected static $type = 'external';
|
|
protected static $objectType = 'external';
|
|
protected static $alias = 'Externí';
|
|
|
|
private HttpClientInterface $http;
|
|
private V8FeedGenerator $generator;
|
|
|
|
private Parser $parser;
|
|
private XMLFeedReader $feedReader;
|
|
private ?string $searchValue = null;
|
|
|
|
/** @var FeedProductList */
|
|
protected $productList; // only declared to avoid redefining whole render() method
|
|
|
|
public static function isAllowed(): bool
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public function __construct(HttpClientInterface $httpClient, V8FeedGenerator $generator, ExternalFeedObjectWrapper $objectWrapper)
|
|
{
|
|
$this->http = $httpClient;
|
|
$this->generator = $generator;
|
|
$this->objectWrapper = $objectWrapper;
|
|
|
|
$this->parser = new Parser();
|
|
$this->feedReader = new XMLFeedReader();
|
|
$this->setFeedGenerator($generator);
|
|
}
|
|
|
|
private function initParser(array $feedRow): void
|
|
{
|
|
$cache = new ExternalFeedCache($feedRow);
|
|
$this->parser->loadFile($cache->getDescriptionUrl());
|
|
}
|
|
|
|
/**
|
|
* @throws UnreadableXMLException
|
|
*/
|
|
private function initReader(array $feedRow, ?array $basePath = null): void
|
|
{
|
|
$cache = new ExternalFeedCache($feedRow, $basePath);
|
|
$this->feedReader->openFile($cache->getSourceUrl());
|
|
}
|
|
|
|
/**
|
|
* Called from template, shows in data tab in feed configuration.
|
|
*/
|
|
public function fetchDataDescription(array $feedRow): array
|
|
{
|
|
if (is_string($feedRow['data'])) {
|
|
$feedRow['data'] = json_decode($feedRow['data'], true);
|
|
}
|
|
$this->initParser($feedRow);
|
|
$data = $this->parser->getFeedRootElement()->serialize();
|
|
$data['children'] = $data['children'] ?? [];
|
|
$data['children'][] = ['type' => 'xs:string', 'name' => '__search', 'minOccurs' => '0'];
|
|
usort($data['children'], function ($a, $b) {
|
|
return strcmp($a['name'], $b['name']);
|
|
});
|
|
|
|
return $data;
|
|
}
|
|
|
|
private function doSearch(string $searchQuery): ?array
|
|
{
|
|
try {
|
|
return $this->feedReader->findElementBySearchAttribute($searchQuery);
|
|
} catch (XMLFeedReaderException $e) {
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* @throws XSDParsingException|XMLFeedReaderException
|
|
*/
|
|
public function getData(array $feedRow, ?int $limit = null): \Generator
|
|
{
|
|
if (is_string($feedRow['data'])) {
|
|
$feedRow['data'] = json_decode($feedRow['data'], true);
|
|
}
|
|
|
|
$this->initParser($feedRow);
|
|
|
|
$feedElementPath = $this->parser->getFeedRootElementPath();
|
|
|
|
$types = $this->parser->getTypeConstraints();
|
|
|
|
$this->initReader($feedRow, $feedElementPath);
|
|
$this->feedReader->setBasePath($feedElementPath);
|
|
$this->feedReader->setTypeCorrectionMap($types);
|
|
|
|
if ($this->searchValue !== null) {
|
|
$cache = new ExternalFeedCache($feedRow, $feedElementPath);
|
|
$res = $cache->getCacheItem($this->searchValue);
|
|
|
|
if ($res !== null) {
|
|
return yield $this->prepareSingleObject($res);
|
|
}
|
|
|
|
$found = $this->doSearch($this->searchValue);
|
|
if ($found === null) {
|
|
return new \EmptyIterator();
|
|
} else {
|
|
$res = $found;
|
|
$cache->setCacheItem($this->searchValue, $res);
|
|
}
|
|
|
|
return yield $this->prepareSingleObject($res);
|
|
}
|
|
|
|
$counter = 0;
|
|
foreach ($this->feedReader->read() as $feedItem) {
|
|
if ($limit !== null && $counter >= $limit) {
|
|
break;
|
|
}
|
|
yield $this->prepareSingleObject($feedItem);
|
|
$counter++;
|
|
}
|
|
}
|
|
|
|
public function getDataNoThrow(array $feedRow, ?int $limit = null): \Generator
|
|
{
|
|
try {
|
|
$data = $this->getData($feedRow, $limit);
|
|
foreach ($data as $elem) {
|
|
yield $elem;
|
|
}
|
|
} catch (\Throwable $ignore) {
|
|
return new \EmptyIterator();
|
|
}
|
|
}
|
|
|
|
public function fetchDataDescriptionNoThrow(array $feedRow): array
|
|
{
|
|
try {
|
|
return $this->fetchDataDescription($feedRow);
|
|
} catch (\Throwable $ignore) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
public function filterByObjectID($objectID): void
|
|
{
|
|
$this->searchValue = trim($objectID);
|
|
}
|
|
}
|