first commit
This commit is contained in:
170
bundles/KupShop/FeedGeneratorBundle/Feed/ExternalFeed.php
Normal file
170
bundles/KupShop/FeedGeneratorBundle/Feed/ExternalFeed.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user