Skip to content

Instantly share code, notes, and snippets.

@alroniks
Created November 7, 2021 18:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alroniks/3a624e4310bf76c648cbc91d519f0ff1 to your computer and use it in GitHub Desktop.
Save alroniks/3a624e4310bf76c648cbc91d519f0ff1 to your computer and use it in GitHub Desktop.
shopmanager.php
<?php
/**
Скрипт, который позволяет принимать запросы от shopmanager и обновлять информацию на сайте на базе MODX и miniSgop2,
при включенной интеграции.
Скрипт не закончен, потому использовать на свой страх и риск.
*/
declare(strict_types = 1);
require __DIR__ . '/config.core.php';
require MODX_CORE_PATH . 'model/modx/modx.class.php';
$modx = new modX();
$modx->initialize('mgr');
$modx->getService('error','error.modError', '', '');
$modx->setLogTarget(['target' => 'FILE', 'options' => ['filename' => 'import.log']]);
$modx->setLogLevel(xPDO::LOG_LEVEL_DEBUG);
/**
* Usage: curl -d '{"products":[{"id":"12345","price":"12.63","origPrice":"10.03","inStock":1,"origStock":34,"delivery":{}}], "staledProductsIds":["501-233","502-230"]}' -H "SMKey: somekey" -X POST https://sitename.com/site-import.php
*/
final class SiteImporter {
private const KEY = 'some key';
private const HEADER_KEY = 'HTTP_SMKEY';
private const HEADER_SYNC_TYPE = 'HTTP_SMSyncType';
private const STATUS_OK = 0;
private const STATUS_UNAUTORIZED = 100;
private const STATUS_ERROR = 101;
private const SYNC_TYPE_FULL = 'full';
private const SYNC_TYPE_PARTIAL = 'partial';
private const STATS_UPDATED = 'updated';
private const STATS_SKIPPED = 'skipped';
private const STATS_ERRORED = 'errored';
private modX $modx;
private string $syncType = self::SYNC_TYPE_PARTIAL;
private array $stats = [
self::STATS_UPDATED => 0,
self::STATS_SKIPPED => 0,
self::STATS_ERRORED => 0,
];
/**
* @throws \JsonException
*/
public function __construct(modX $modx)
{
if ($_SERVER[self::HEADER_KEY] !== self::KEY) {
self::result(self::STATUS_UNAUTORIZED);
}
if (isset($_SERVER[self::HEADER_SYNC_TYPE])) {
$this->syncType = $_SERVER[self::HEADER_SYNC_TYPE];
}
$this->modx = $modx;
$this->modx->log(xPDO::LOG_LEVEL_DEBUG, sprintf('Incoming authorization key: %s', $_SERVER[self::HEADER_KEY]));
$this->modx->log(xPDO::LOG_LEVEL_DEBUG, sprintf('Incoming sync type: %s', $_SERVER[self::HEADER_SYNC_TYPE]));
}
/**
* @throws \JsonException
*/
public function __invoke(): string
{
$data = json_decode(file_get_contents('php://input'), true, 512, JSON_THROW_ON_ERROR);
$this->modx->log(xPDO::LOG_LEVEL_DEBUG, sprintf('Incoming request details: %s', self::arrayOneLine($data)));
if (isset($data['staledProductsIds']) && is_array($data['staledProductsIds']) && count($data['staledProductsIds'])) {
$annulled = 0;
foreach ($data['staledProductsIds'] as $id) {
if ($this->toNullProduct($id)) {
$annulled++;
}
}
$this->modx->log(xPDO::LOG_LEVEL_INFO, sprintf('%s products were annulled', $annulled));
$this->modx->log(xPDO::LOG_LEVEL_DEBUG, sprintf('where touched products with articles: %s', implode(',', $data['staledProductsIds'])));
}
switch ($this->syncType) {
case self::SYNC_TYPE_PARTIAL:
$this->onceProcessing($data['products']);
break;
case self::SYNC_TYPE_FULL:
$this->bulkProcessing($data['products']);
break;
}
self::result(self::STATUS_OK, $this->stats);
}
private function bulkProcessing(array $products): void
{
// return;
// $touchedProducts = $this->modx->getIterator(
// msProductData::class,
// ['article:IN' => array_column($products, 'id')]
// );
//
// //
//
// $prices = [];
// foreach ($touchedProducts as $product) {
// $prices[$product->get('article')] = array_filter(
// $product->toArray(),
// static fn($key) => in_array($key, ['id', 'article', 'price', 'old_price', 'remain']),
// ARRAY_FILTER_USE_KEY
// );
// }
}
/**
* @param array[] $products
*/
private function onceProcessing(array $products): void
{
foreach ($products as $productInfo) {
$this->modx->log(xPDO::LOG_LEVEL_INFO, sprintf('Importing product with id "%s"', $productInfo['id']));
$this->modx->log(xPDO::LOG_LEVEL_DEBUG, self::arrayOneLine($productInfo));
try {
/** @var msProductData $productData */
$productData = $this->modx->getObject(
msProductData::class,
['article' => $productInfo['id']]
);
/** @var msProduct $product */
$product = $productData->getOne('Product');
if ($this->updateProduct($product, $productData['price'], $productData['origPrice'], $productData['origStock'])) {
$this->modx->log(xPDO::LOG_LEVEL_INFO, sprintf('Updated product with id %d', $product->get('id')));
$this->modx->log(xPDO::LOG_LEVEL_DEBUG, sprintf('Updated product with id %d', $product->get('id')));
$this->stats[self::STATS_UPDATED]++;
}
} catch (Exception $e) {
$this->modx->log(xPDO::LOG_LEVEL_ERROR, $e->getMessage());
$this->stats[self::STATS_ERRORED]++;
}
}
}
private function toNullProduct(string $article): bool
{
$product = $this->modx->getObject(msProductData::class, ['article' => $article]);
if (!$product) {
return false;
}
return $this->updateProduct($product->getOne('Product'), '0.00','0.00', 0);
}
/**
* @throws \JsonException
*/
public static function result(int $status = self::STATUS_ERROR, array $stats = []): void
{
$result = ['status' => $status];
if (count($stats)) {
$result = array_merge($result, $stats);
}
header('SMRESULT: ' . json_encode($result, JSON_THROW_ON_ERROR)); exit;
}
private function updateProduct(msProduct $product, string $retailPrice, string $tradePrice, int $balance): bool
{
$product->set('price', $retailPrice);
$product->set('old_price', $tradePrice);
return $product->setTVValue('remain', $balance);
}
private static function arrayOneLine(array $array): string
{
return preg_replace('/\s/', '', str_replace(PHP_EOL, '', var_export($array, true)));
}
}
try {
echo (new SiteImporter($modx))();
exit();
} catch (JsonException $e) {
SiteImporter::result();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment