245 lines
7.0 KiB
PHP
245 lines
7.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace External\HannahBundle\SAP\Synchronizer;
|
|
|
|
use Doctrine\DBAL\Exception\DeadlockException;
|
|
use Doctrine\DBAL\Exception\LockWaitTimeoutException;
|
|
use External\HannahBundle\SAP\Exception\SAPException;
|
|
use External\HannahBundle\SAP\Util\SAPUtil;
|
|
use External\HannahBundle\Util\Configuration;
|
|
use KupShop\AdminBundle\Util\ActivityLog;
|
|
use KupShop\KupShopBundle\Util\Logging\SentryLogger;
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
abstract class BaseSynchronizer implements SynchronizerInterface
|
|
{
|
|
protected static $type;
|
|
protected $logging = true;
|
|
|
|
protected bool $allowFullSync = false;
|
|
|
|
/** @required */
|
|
public Configuration $configuration;
|
|
|
|
protected $sapUtil;
|
|
|
|
protected $activityLog;
|
|
|
|
protected $sentryLogger;
|
|
|
|
protected string $currentImportType = 'DIFF';
|
|
protected bool $isFileImport = false;
|
|
|
|
protected array $context = [];
|
|
|
|
protected $logger;
|
|
|
|
protected $processItemCallback;
|
|
|
|
public function __construct(
|
|
SAPUtil $sapUtil,
|
|
LoggerInterface $logger,
|
|
ActivityLog $activityLog,
|
|
SentryLogger $sentryLogger,
|
|
) {
|
|
$this->sapUtil = $sapUtil;
|
|
$this->activityLog = $activityLog;
|
|
$this->logger = $logger;
|
|
$this->sentryLogger = $sentryLogger;
|
|
}
|
|
|
|
public static function getType(): string
|
|
{
|
|
if (empty(static::$type)) {
|
|
throw new SAPException('Missing required property "$type" of synchronizer service');
|
|
}
|
|
|
|
return static::$type;
|
|
}
|
|
|
|
public function setProcessItemCallback(?callable $callback): void
|
|
{
|
|
$this->processItemCallback = $callback;
|
|
}
|
|
|
|
public function setAllowFullSync(bool $allowFullSync): void
|
|
{
|
|
$this->allowFullSync = $allowFullSync;
|
|
}
|
|
|
|
public function process(array $data): void
|
|
{
|
|
$this->createContext($data);
|
|
|
|
foreach ($this->getHandledFields() as $field => $methodName) {
|
|
// missing data, or not expected structure
|
|
if (!isset($data[$field]['item'])) {
|
|
if (!array_key_exists($field, $data)) {
|
|
// kibana log
|
|
$this->log($data, sprintf('Unexpected data of "%s"', static::getType()));
|
|
// activity log
|
|
$this->activityLog->addActivityLog(
|
|
ActivityLog::SEVERITY_WARNING,
|
|
ActivityLog::TYPE_SYNC,
|
|
sprintf('Data has unexpected format! Missing "%s" field of type "%s".', $field, static::getType()),
|
|
$this->currentImportType === 'FULL' ? [] : ['data' => $data]
|
|
);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
$method = 'process'.ucfirst($methodName);
|
|
if (!method_exists($this, $method)) {
|
|
throw new SAPException(
|
|
sprintf('Missing "%s:%s" method', static::class, $method)
|
|
);
|
|
}
|
|
|
|
// process data
|
|
foreach (((array) $data[$field]['item']) as $item) {
|
|
// zalogovat prichozi data
|
|
$this->log((array) $item);
|
|
|
|
// process data
|
|
try {
|
|
$this->{$method}((array) $item);
|
|
} catch (LockWaitTimeoutException|DeadlockException $e) {
|
|
if ($this->currentImportType === 'FULL' && $this->isFileImport) {
|
|
$this->onDeadLockFailure((array) $item);
|
|
continue;
|
|
}
|
|
|
|
throw $e;
|
|
}
|
|
|
|
if ($this->processItemCallback) {
|
|
call_user_func($this->processItemCallback, (array) $item);
|
|
}
|
|
}
|
|
}
|
|
|
|
try {
|
|
$this->postprocess();
|
|
|
|
if ($this->context['isFileImport'] ?? false) {
|
|
// prejmenuju soubor na FTP, aby koncil na ".done"
|
|
if (!empty($this->context['filename'])) {
|
|
$this->sapUtil->updateJSONFileAsDone($this->context['filename']);
|
|
}
|
|
|
|
$this->sapUtil->addActivityLog('Úspěšně zpracován JSON: '.$this->context['filename'], severity: ActivityLog::SEVERITY_SUCCESS);
|
|
}
|
|
} catch (\Throwable $e) {
|
|
if (isDevelopment()) {
|
|
throw $e;
|
|
}
|
|
|
|
$this->sentryLogger->captureException($e);
|
|
}
|
|
}
|
|
|
|
public function processToSAP(): void
|
|
{
|
|
throw new SAPException('Process to SAP method is not implemented');
|
|
}
|
|
|
|
protected function postprocess(): void
|
|
{
|
|
}
|
|
|
|
protected function onDeadlockFailure(array $item): void
|
|
{
|
|
// v BaseSynchronizer se nic nestane -> pouze az v CatalogSynchronizer
|
|
}
|
|
|
|
abstract protected function getHandledFields(): array;
|
|
|
|
protected function createContext(array $data): void
|
|
{
|
|
$this->currentImportType = $data['ImportType'] ?? 'DIFF';
|
|
$this->isFileImport = $data['isFileImport'] ?? false;
|
|
|
|
$context = [
|
|
'importType' => $data['ImportType'] ?? 'DIFF',
|
|
'isFileImport' => $data['isFileImport'] ?? false,
|
|
'process' => $data['Process'] ?? 'WPJPL',
|
|
];
|
|
|
|
$context['language'] = $this->configuration->getLanguageByProcess($context['process']);
|
|
|
|
if ($context['isFileImport']) {
|
|
$context['filename'] = $data['filename'] ?? null;
|
|
}
|
|
|
|
$this->context = $context;
|
|
}
|
|
|
|
public function getContext(): array
|
|
{
|
|
return $this->context;
|
|
}
|
|
|
|
protected function log(array $item, ?string $message = null): void
|
|
{
|
|
if (isLocalDevelopment()) {
|
|
return;
|
|
}
|
|
|
|
if (!$this->isLoggingEnabled()) {
|
|
return;
|
|
}
|
|
|
|
if (!$message) {
|
|
$message = sprintf('SAP: Processing change of \'%s\'', static::getType());
|
|
}
|
|
|
|
$this->logger->notice(
|
|
$message,
|
|
[
|
|
'Type' => static::getType(),
|
|
'Item' => $item,
|
|
]
|
|
);
|
|
}
|
|
|
|
protected function isLoggingEnabled(): bool
|
|
{
|
|
// vypinam logovani, protoze ho ted nevyuzivama a generuje to obrovske mnozstvi dat do Kibany
|
|
return false;
|
|
|
|
// plne logovani pouze pro monobrandy
|
|
if (in_array($this->configuration->getShopId(), [Configuration::SHOP_KEEN, Configuration::SHOP_HANNAH, Configuration::SHOP_RAFIKI])) {
|
|
return true;
|
|
}
|
|
|
|
return $this->logging;
|
|
}
|
|
|
|
private $tmpLastSync;
|
|
|
|
protected function getLastSyncTime(?string $type = null): ?int
|
|
{
|
|
$dbcfg = \Settings::getDefault();
|
|
$sap = $dbcfg->loadValue('SAP');
|
|
|
|
$this->tmpLastSync = time() - (60 * 2);
|
|
|
|
return $sap[$type ?: static::getType()] ?? null;
|
|
}
|
|
|
|
protected function updateLastSyncTime(): void
|
|
{
|
|
$dbcfg = \Settings::getDefault();
|
|
|
|
if (!($sap = $dbcfg->loadValue('SAP'))) {
|
|
$sap = [];
|
|
}
|
|
|
|
$sap[static::getType()] = $this->tmpLastSync ?: (time() - (60 * 2));
|
|
|
|
$dbcfg->saveValue('SAP', $sap, false);
|
|
}
|
|
}
|