370 lines
15 KiB
PHP
370 lines
15 KiB
PHP
<?php
|
|
|
|
use KupShop\AdminBundle\Admin\ProductsFilter;
|
|
use KupShop\AdminBundle\Util\Filter\OrdersFilter;
|
|
use KupShop\FeedGeneratorBundle\ContextPropertiesLocator;
|
|
use KupShop\FeedGeneratorBundle\Exception\XMLFeedReader\XMLFeedReaderException;
|
|
use KupShop\FeedGeneratorBundle\Exception\XSDParser\XSDParsingException;
|
|
use KupShop\FeedGeneratorBundle\Expressions\ExpressionInterpreterException;
|
|
use KupShop\FeedGeneratorBundle\V8ErrorException;
|
|
use KupShop\FeedsBundle\FeedLocator;
|
|
use KupShop\FeedsBundle\Utils\FeedUtils;
|
|
use KupShop\KupShopBundle\Context\CountryContext;
|
|
use KupShop\KupShopBundle\Context\CurrencyContext;
|
|
use KupShop\KupShopBundle\Context\DomainContext;
|
|
use KupShop\KupShopBundle\Context\LanguageContext;
|
|
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
|
|
|
$main_class = 'Feeds';
|
|
|
|
class Feeds extends Window
|
|
{
|
|
/** @var FeedLocator */
|
|
private $feedLocator;
|
|
|
|
/** @var LanguageContext */
|
|
private $languageContext;
|
|
|
|
/** @var CurrencyContext */
|
|
private $currencyContext;
|
|
|
|
/** @var CountryContext */
|
|
private $countryContext;
|
|
|
|
/** @var DomainContext */
|
|
private $domainContext;
|
|
|
|
/** @var ContextPropertiesLocator */
|
|
private $contextPropertiesLocator;
|
|
|
|
private FeedUtils $feedUtils;
|
|
|
|
/** @var string */
|
|
private static $defaultTemplate = '{"beginning": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<catalog>", "end": "</catalog>", "nodes": []}';
|
|
|
|
public function __construct()
|
|
{
|
|
$this->feedLocator = ServiceContainer::getService(FeedLocator::class);
|
|
$this->feedUtils = ServiceContainer::getService(FeedUtils::class);
|
|
$this->languageContext = ServiceContainer::getService(LanguageContext::class);
|
|
$this->currencyContext = ServiceContainer::getService(CurrencyContext::class);
|
|
$this->countryContext = ServiceContainer::getService(CountryContext::class);
|
|
$this->domainContext = ServiceContainer::getService(DomainContext::class);
|
|
if (findModule(Modules::FEED_GENERATOR)) {
|
|
$this->contextPropertiesLocator = ServiceContainer::getService(ContextPropertiesLocator::class);
|
|
}
|
|
}
|
|
|
|
public function get_vars()
|
|
{
|
|
$vars = parent::get_vars();
|
|
$ID = $this->getID();
|
|
|
|
$vars['body']['feedTypes'] = $this->feedLocator->getAliases();
|
|
$vars['body']['languages']['null'] = translate('languages_null', 'feeds');
|
|
foreach ($this->languageContext->getSupported() as $language) {
|
|
$vars['body']['languages'][$language->getId()] = $language->getName();
|
|
}
|
|
$vars['body']['countries']['null'] = translate('countries_null', 'feeds');
|
|
foreach ($this->countryContext->getAll() as $country) {
|
|
$vars['body']['countries'][$country->getId()] = $country->getName();
|
|
}
|
|
$vars['body']['currencies']['null'] = translate('currencies_null', 'feeds');
|
|
foreach ($this->currencyContext->getSupported() as $currency) {
|
|
$vars['body']['currencies'][$currency->getId()] = $currency->getName();
|
|
}
|
|
$vars['body']['domains'] = array_combine($this->domainContext->getSupported(), $this->domainContext->getSupported());
|
|
$vars['body']['domainsWithScheme'] = $this->domainContext->getSupportedWithScheme();
|
|
|
|
if (!empty($ID)) {
|
|
$vars['body']['data']['active'] = $vars['body']['data']['active'] ? 'Y' : 'N';
|
|
$vars['body']['data']['id_language'] = $vars['body']['data']['id_language'] ?? 'null';
|
|
$vars['body']['data']['id_currency'] = $vars['body']['data']['id_currency'] ?? 'null';
|
|
if ($vars['body']['data']['settings']) {
|
|
$settings = json_decode_strict($vars['body']['data']['settings'], true);
|
|
$vars['filter'] = $settings['filter'] ?? null;
|
|
}
|
|
}
|
|
|
|
if (empty($vars['body']['data']['template'])) {
|
|
$vars['body']['data']['template'] = static::$defaultTemplate;
|
|
}
|
|
|
|
$vars['body']['configurableFeedTemplates'] = array_map(fn ($x) => $x['name'], $this->getFeedTemplates());
|
|
|
|
if (findModule(Modules::FEED_GENERATOR) && $this->feedLocator->isTypeConfigurable($vars['body']['data']['type'] ?? false)) {
|
|
$vars['body']['enableConfigurator'] = true;
|
|
$vars['body']['contextPropertiesLocator'] = $this->contextPropertiesLocator;
|
|
}
|
|
if ($vars['body']['data']['type'] ?? false) {
|
|
$vars['body']['feedService'] = $this->feedLocator->getServiceByType($vars['body']['data']['type']);
|
|
}
|
|
|
|
$vars['body']['objectID'] = getVal('objectID', null, '');
|
|
|
|
$this->unserializeCustomData($vars['body']['data']);
|
|
|
|
$report = [];
|
|
foreach (json_decode($vars['body']['data']['report'] ?? '') ?? [] as $key => $item) {
|
|
if (str_starts_with($key, 'feed_')) {
|
|
$report[$key] = $item;
|
|
} else {
|
|
$report['last_generated_feed'][$key] = $item;
|
|
}
|
|
}
|
|
|
|
$vars['body']['data']['report_decoded'] = $report;
|
|
|
|
if (($vars['body']['feedService'] ?? false) instanceof \KupShop\FeedsBundle\Feed\IHasCustomData) {
|
|
$template = createSmarty(false, true);
|
|
$template->assign($vars);
|
|
$vars['body']['customDataForm'] = $template->fetch($vars['body']['feedService']->getCustomDataFormTemplate());
|
|
}
|
|
|
|
$formats = $this->feedUtils->getFeedFormats();
|
|
$vars['body']['additionalFormats'] = array_combine($formats, $formats);
|
|
$vars['body']['formatExtension'] = ($vars['body']['data']['data']['format'] ?? false)
|
|
&& !in_array($vars['body']['data']['data']['format'], ['xml', 'xml_pretty'], true) ? $vars['body']['data']['data']['format'] : '';
|
|
|
|
return $vars;
|
|
}
|
|
|
|
public function checkRequired($data)
|
|
{
|
|
// Allow to load all fields from template, skip validity check
|
|
if ($data['fromTemplate'] ?? null) {
|
|
return [];
|
|
}
|
|
|
|
return parent::checkRequired($data);
|
|
}
|
|
|
|
public function getSQLFields($data = null, $fields = null, $defaults = null, $types = null)
|
|
{
|
|
$fields = parent::getSQLFields($data, $fields, $defaults);
|
|
|
|
$fromTemplate = getVal('data')['fromTemplate'] ?? null;
|
|
if ($this->getAction() == 'add' && !empty($fromTemplate)) {
|
|
$templates = $this->getFeedTemplates();
|
|
if (isset($templates[$fromTemplate])) {
|
|
$feedTemplate = $templates[$fromTemplate];
|
|
$feedTemplate['row']['name'] ??= $feedTemplate['name'];
|
|
foreach ($feedTemplate['row'] as $key => $value) {
|
|
// handle merging custom data maybe?
|
|
$fields[$key] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
$fields['active'] = !empty($fields['active']) && $fields['active'] === 'Y';
|
|
$fields['expensive'] = !empty($fields['expensive']) && $fields['expensive'] === 'Y';
|
|
$fields['id_language'] = $fields['id_language'] === 'null' ? null : $fields['id_language'];
|
|
if (array_key_exists('id_country', $fields)) {
|
|
$fields['id_country'] = $fields['id_country'] === 'null' ? null : $fields['id_country'];
|
|
}
|
|
$fields['id_currency'] = $fields['id_currency'] === 'null' ? null : $fields['id_currency'];
|
|
|
|
$ID = $this->getID();
|
|
if (!empty($ID)) {
|
|
$fields['updated'] = (new DateTime())->format('Y-m-d H:i:s');
|
|
}
|
|
|
|
$filter = getVal('filter');
|
|
if ($filter) {
|
|
$feedRow = $this->selectSQL('feeds', ['id' => $this->getID()])->fetch();
|
|
$feedService = $this->feedLocator->getServiceByType($feedRow['type']);
|
|
|
|
$settings = [];
|
|
|
|
if ($feedService && $feedService->getObjectType() === 'order') {
|
|
$settings['filter'] = OrdersFilter::cleanFilter($filter);
|
|
} else {
|
|
$settings['filter'] = ProductsFilter::cleanFilter($filter);
|
|
}
|
|
|
|
$settings_json = json_encode($settings);
|
|
$fields['settings'] = $settings_json;
|
|
}
|
|
|
|
return $fields;
|
|
}
|
|
|
|
public function getData()
|
|
{
|
|
$data = parent::getData();
|
|
$this->serializeCustomData($data);
|
|
|
|
return $data;
|
|
}
|
|
|
|
public function handleUpdate()
|
|
{
|
|
$acn = $this->getAction();
|
|
$SQL = null;
|
|
if ($acn == 'add') {
|
|
$sqlFields = $this->getSQLFields();
|
|
$this->insertSQL($this->getTableName(), $sqlFields);
|
|
$SQL = true;
|
|
if (empty($ID)) {
|
|
if (isset($sqlFields['id'])) {
|
|
$this->setID($sqlFields['id']);
|
|
} else {
|
|
$this->setID(sqlInsertID());
|
|
}
|
|
}
|
|
$this->insertHash();
|
|
|
|
return $SQL;
|
|
} else {
|
|
return parent::handleUpdate();
|
|
}
|
|
}
|
|
|
|
private function insertHash()
|
|
{
|
|
$feed = $this->selectSQL('feeds', ['id' => $this->getID()])->fetch();
|
|
if ($feed) {
|
|
$hash = FeedUtils::createHash([
|
|
$feed['id'],
|
|
$feed['created'],
|
|
]);
|
|
$this->updateSQL('feeds', ['hash' => $hash], ['id' => $feed['id']]);
|
|
}
|
|
}
|
|
|
|
public function handleConfiguratorPreview()
|
|
{
|
|
increaseMemoryLimit(1024);
|
|
$feedID = $this->getID();
|
|
$feedRow = $this->selectSQL('feeds', ['id' => $feedID])->fetch();
|
|
$feedRow['data'] = json_decode($feedRow['data'] ?? '{}', true);
|
|
$response = [];
|
|
|
|
// set language context
|
|
$language = getVal('language');
|
|
if ($language && $language !== 'null') {
|
|
$this->languageContext->activate($language);
|
|
} elseif (isset($feedRow['id_language'])) {
|
|
$this->languageContext->activate($feedRow['id_language']);
|
|
}
|
|
|
|
// set currency context
|
|
$currency = getVal('currency');
|
|
if ($currency && $currency !== 'null') {
|
|
$this->currencyContext->activate($currency);
|
|
} elseif (isset($feedRow['id_currency'])) {
|
|
$this->currencyContext->activate($feedRow['id_currency']);
|
|
}
|
|
|
|
// set country context
|
|
$this->countryContext->activate($this->countryContext->getDefaultId());
|
|
$country = getVal('country');
|
|
if ($country && $country !== 'null') {
|
|
$this->countryContext->activate($country);
|
|
} elseif (isset($feedRow['id_country'])) {
|
|
$this->countryContext->activate($feedRow['id_country']);
|
|
}
|
|
|
|
// set domain context
|
|
if ($domain = getVal('domain')) {
|
|
$this->domainContext->activate($domain);
|
|
}
|
|
|
|
if ($feedRow && $this->feedLocator->isTypeConfigurable($feedRow['type'])) {
|
|
$this->filterByObjectID($feedRow['type']);
|
|
$feedRow['template'] = getVal('wipTemplate', $_POST, static::$defaultTemplate);
|
|
$feedService = $this->feedLocator->getServiceByType($feedRow['type']);
|
|
while (ob_get_level()) {
|
|
ob_end_clean();
|
|
}
|
|
|
|
try {
|
|
ob_start();
|
|
$feedService->renderStrict($feedRow, 1);
|
|
$result = ob_get_contents();
|
|
ob_end_clean();
|
|
// format output
|
|
$dom = new DOMDocument();
|
|
$dom->preserveWhiteSpace = false;
|
|
@$dom->loadXML($result);
|
|
$dom->formatOutput = true;
|
|
|
|
$response['xmlPreview'] = $dom->saveXML();
|
|
} catch (ExpressionInterpreterException|V8ErrorException|XSDParsingException|XMLFeedReaderException $e) {
|
|
$rc = new \ReflectionClass($e);
|
|
$response['xmlPreview'] = $rc->getShortName().': '.$e->getMessage();
|
|
$response['xmlPreview'] .= PHP_EOL.PHP_EOL.'----------'.PHP_EOL.ob_get_contents();
|
|
ob_end_clean();
|
|
}
|
|
|
|
$smarty = createSmarty(true, true);
|
|
$smarty->assign('body', ['feedService' => $feedService, 'data' => $feedRow]);
|
|
$response['dataInfo'] = $smarty->fetch('window/feeds.dataInfo.tpl');
|
|
if ($feedService instanceof \KupShop\FeedGeneratorBundle\Feed\IConfigurableFeed) {
|
|
$response['consoleLogs'] = $feedService->getReport()['consoleLogs'] ?? [];
|
|
}
|
|
}
|
|
|
|
header('Content-Type: application/json');
|
|
echo json_encode($response);
|
|
exit;
|
|
}
|
|
|
|
public function handleLoadTemplate()
|
|
{
|
|
$feedID = $this->getID();
|
|
$feedRow = $this->selectSQL('feeds', ['id' => $feedID])->fetch();
|
|
$service = $this->feedLocator->getServiceByType($feedRow['type']);
|
|
if (!$service instanceof \KupShop\FeedGeneratorBundle\Feed\IConfigurableFeed) {
|
|
$this->returnError('Pro nastavení šablony musí být vybrán konfigurovatelný typ feedu');
|
|
}
|
|
$feedTemplate = getVal('feedTemplate', null, '');
|
|
$templates = $this->getFeedTemplates();
|
|
if (!preg_match('/^[a-zA-Z\_\-]+$/', $feedTemplate) || !isset($templates[$feedTemplate])) {
|
|
$this->returnError('Šablona konfigurovatelného feedu nebyla nalezena');
|
|
}
|
|
|
|
$feedTemplate = $templates[$feedTemplate];
|
|
$this->updateSQL('feeds', [
|
|
'template' => $feedTemplate['row']['template'],
|
|
], ['id' => $feedID]);
|
|
|
|
$this->returnOK(translate('templateLoaded'));
|
|
}
|
|
|
|
protected function getFeedTemplates(): array
|
|
{
|
|
$configurableFeedTemplates = getCache('configurableFeedTemplates');
|
|
if (!$configurableFeedTemplates) {
|
|
$configurableFeedTemplates = ['' => ['name' => translate('selectTemplate', 'feeds')]];
|
|
|
|
$bundleFinder = ServiceContainer::getService(\KupShop\KupShopBundle\Util\System\BundleFinder::class);
|
|
foreach ($bundleFinder->getExistingBundlesPath('Admin/ConfigurableFeedTemplates') as $bundlePath) {
|
|
foreach (glob($bundlePath.'/*.json') as $filePath) {
|
|
try {
|
|
$feedTemplate = json_decode_strict(file_get_contents($filePath), true);
|
|
$configurableFeedTemplates[mb_substr(basename($filePath), 0, -5)] = $feedTemplate;
|
|
} catch (Exception $e) {
|
|
if (isLocalDevelopment()) {
|
|
throw $e;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
setCache('configurableFeedTemplates', $configurableFeedTemplates);
|
|
}
|
|
|
|
return $configurableFeedTemplates;
|
|
}
|
|
|
|
protected function filterByObjectID($feedType)
|
|
{
|
|
$ID = $this->getID();
|
|
$objectID = getVal('objectID');
|
|
$feed = $this->feedLocator->getServiceByType($feedType);
|
|
if ($objectID && !empty($ID) && $feed instanceof \KupShop\FeedGeneratorBundle\Feed\IConfigurableFeed) {
|
|
$feed->filterByObjectID($objectID);
|
|
}
|
|
}
|
|
}
|