296 lines
8.3 KiB
PHP
296 lines
8.3 KiB
PHP
<?php
|
|
|
|
namespace External\VarioBundle\Synchronizers;
|
|
|
|
use External\VarioBundle\Exception\SynchronizerException;
|
|
use External\VarioBundle\SoapClient;
|
|
use External\VarioBundle\Util\VarioConfig;
|
|
use External\VarioBundle\Util\VarioHelper;
|
|
use Psr\Log\LoggerInterface;
|
|
use Query\QueryBuilder;
|
|
|
|
abstract class BaseSynchronizer implements SynchronizerInterface
|
|
{
|
|
use \DatabaseCommunication;
|
|
|
|
/** @var string */
|
|
protected static $type;
|
|
/** @var int */
|
|
protected static $batch = 100;
|
|
/** @var int|null Repeat batch and after repeats set data as done */
|
|
protected static $batchRepeat;
|
|
/** @var int|null How many batches can be handled in one request? */
|
|
protected static $maxBatches = 8;
|
|
/** @var bool Ends synchronization after first batch process */
|
|
protected $forceEnd = false;
|
|
/** @var array [syncField => syncMethod without suffix] */
|
|
protected $fields;
|
|
/** @var bool */
|
|
protected $debug = true;
|
|
/** @var bool */
|
|
protected $logging = true;
|
|
|
|
protected $client;
|
|
protected $helper;
|
|
protected $config;
|
|
protected $logger;
|
|
|
|
private $changedItems = [];
|
|
protected $forceSyncID;
|
|
|
|
public function __construct(
|
|
SoapClient $client,
|
|
VarioHelper $helper,
|
|
VarioConfig $config,
|
|
LoggerInterface $logger,
|
|
) {
|
|
$this->client = $client;
|
|
$this->helper = $helper;
|
|
$this->config = $config;
|
|
$this->logger = $logger;
|
|
}
|
|
|
|
public static function getType()
|
|
{
|
|
return static::$type;
|
|
}
|
|
|
|
public function setForceSync(?string $id)
|
|
{
|
|
$this->forceSyncID = $id;
|
|
}
|
|
|
|
/**
|
|
* @throws SynchronizerException
|
|
*/
|
|
public function getEshopID($objectID)
|
|
{
|
|
throw new SynchronizerException(
|
|
sprintf('Class %s should overwrite getEshopID($objectID) method.', get_class($this))
|
|
);
|
|
}
|
|
|
|
public function syncDelete($eshopID)
|
|
{
|
|
}
|
|
|
|
public function sync()
|
|
{
|
|
if (!is_array($this->fields)) {
|
|
throw new SynchronizerException(
|
|
sprintf('Class %s should overwrite $fields attribute.', get_class($this))
|
|
);
|
|
}
|
|
|
|
$this->writeLine('Starting type '.static::getType());
|
|
$loop = 0;
|
|
$batchRepeat = false;
|
|
|
|
$forceEndOriginal = $this->forceEnd;
|
|
|
|
do {
|
|
// fetch data
|
|
if ($forceSync = getVal('force_sync', null, $this->forceSyncID)) {
|
|
$this->writeLine(sprintf('Force fetching %s...', $forceSync));
|
|
if ($forceSync == 'ALL') {
|
|
$items = function () {
|
|
$qb = $this->getSyncAllObjects();
|
|
if ($qb instanceof QueryBuilder) {
|
|
if ($start = getVal('start')) {
|
|
$qb->andWhere('id_vario >= :start')
|
|
->setParameter('start', $start);
|
|
}
|
|
$data = $qb->execute();
|
|
} else {
|
|
$data = $qb;
|
|
}
|
|
|
|
foreach ($data as $row) {
|
|
$this->writeLine($row['id_vario'] ?? $row);
|
|
foreach ($this->client->forceObjectData(static::getType(), $row['id_vario'] ?? $row) as $item) {
|
|
yield $item;
|
|
}
|
|
}
|
|
};
|
|
$items = $items();
|
|
} else {
|
|
$items = $this->client->forceObjectData(static::getType(), $forceSync);
|
|
}
|
|
$this->forceEnd = true;
|
|
} else {
|
|
$this->writeLine('Fetching...');
|
|
if ($batchRepeat === false) {
|
|
$items = $this->client->getJobsData(static::getType(), static::$batch);
|
|
}
|
|
if (empty($items) && $loop == 0) {
|
|
$this->writeLine('No changes to fetch');
|
|
break;
|
|
}
|
|
}
|
|
|
|
$this->writeLine('Processing...');
|
|
// preprocess items
|
|
$this->preprocess($items);
|
|
|
|
$doneJobs = [];
|
|
|
|
// process data
|
|
foreach ($items as $item) {
|
|
// log change
|
|
$this->logItem($item);
|
|
|
|
$objectID = $this->getObjectID($item);
|
|
|
|
$eshopID = $objectID ? $this->getEshopID($objectID) : null;
|
|
|
|
if (!$eshopID) {
|
|
if ($eshopID === null) {
|
|
$doneJobs[] = $item->Job->ID;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// delete action
|
|
if ($item->Job->Action == 'acDelete') {
|
|
$this->syncDelete($eshopID);
|
|
$doneJobs[] = $item->Job->ID;
|
|
continue;
|
|
}
|
|
|
|
foreach ($item->Data as $column => $value) {
|
|
// not defined = ignore
|
|
if (!isset($this->fields[$column])) {
|
|
continue;
|
|
}
|
|
|
|
if (getVal('onlyColumn') && getVal('onlyColumn') != $column) {
|
|
continue;
|
|
}
|
|
|
|
$method = 'sync'.ucfirst($this->fields[$column]);
|
|
if (!method_exists($this, $method)) {
|
|
throw new SynchronizerException(
|
|
sprintf('Method %s() for synchronizer type \'%s\' is not defined!', $method, static::getType())
|
|
);
|
|
}
|
|
|
|
call_user_func_array([$this, $method], [$value, $eshopID, $column, $item]);
|
|
}
|
|
|
|
// this is needed in sections sync for example (to create tree structure correctly)
|
|
$batchRepeat = true;
|
|
if (static::$batchRepeat === null || (($loop % static::$batchRepeat == 0) && $loop != 0)) {
|
|
$doneJobs[] = $item->Job->ID;
|
|
$batchRepeat = false;
|
|
}
|
|
}
|
|
|
|
$doneJobs = array_filter($doneJobs);
|
|
|
|
if (!empty($doneJobs)) {
|
|
$this->client->setJobsDone($doneJobs);
|
|
}
|
|
|
|
if (static::$maxBatches !== null && static::$maxBatches <= $loop) {
|
|
$this->forceEnd = true;
|
|
}
|
|
|
|
$loop++;
|
|
} while (is_countable($items) && count($items) > 0 && $this->forceEnd == false);
|
|
|
|
$this->postprocess();
|
|
|
|
if ($forceSync) {
|
|
$this->forceEnd = $forceEndOriginal;
|
|
}
|
|
|
|
$this->writeLine('Ended type '.static::getType());
|
|
}
|
|
|
|
protected function preprocess($items)
|
|
{
|
|
}
|
|
|
|
protected function postprocess()
|
|
{
|
|
}
|
|
|
|
protected function getObjectID($item)
|
|
{
|
|
return $item->Job->ObjectID;
|
|
}
|
|
|
|
protected function logItem($item)
|
|
{
|
|
if (isDevelopment()) {
|
|
return;
|
|
}
|
|
|
|
if (!$this->logging) {
|
|
return;
|
|
}
|
|
|
|
$this->logger->notice(
|
|
sprintf('VARIO: Processing change of \'%s\', ObjectID: %s', static::getType(), $item->Job->ObjectID),
|
|
[
|
|
'Job' => (array) $item->Job,
|
|
'Data' => (array) $item->Data,
|
|
'Type' => static::getType(),
|
|
]
|
|
);
|
|
}
|
|
|
|
protected function addChangedItem($identifier)
|
|
{
|
|
$this->changedItems[static::getType()][] = $identifier;
|
|
}
|
|
|
|
protected function getChangedItems($type = null)
|
|
{
|
|
if ($type === null) {
|
|
return $this->changedItems;
|
|
}
|
|
|
|
if (isset($this->changedItems[static::getType()])) {
|
|
return $this->changedItems[static::getType()];
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Write text to output.
|
|
*/
|
|
protected function writeLine(string $text)
|
|
{
|
|
if (!$this->debug) {
|
|
return;
|
|
}
|
|
|
|
echo $text.'<br>';
|
|
flush();
|
|
}
|
|
|
|
public function setDebug(bool $bool)
|
|
{
|
|
$this->debug = $bool;
|
|
}
|
|
|
|
/**
|
|
* @return QueryBuilder
|
|
*/
|
|
protected function getSyncAllObjects()
|
|
{
|
|
throw new \Exception('Not implemented');
|
|
}
|
|
|
|
public function prepareVarioID($id): string
|
|
{
|
|
if (empty($id)) {
|
|
return '';
|
|
}
|
|
|
|
return '{'.$id.'}';
|
|
}
|
|
}
|