Files
2025-08-02 16:30:27 +02:00

414 lines
12 KiB
PHP

<?php
declare(strict_types=1);
namespace External\ZNZBundle\Util;
use External\MSSQLBundle\Util\MoneyConnection;
use External\ZNZBundle\Exception\ZNZException;
use KupShop\KupShopBundle\Util\System\CurlUtil;
use Query\Operator;
class ZNZApi
{
private ?MoneyConnection $connection = null;
private ?array $connectionParameters = null;
public function __construct(
private readonly CurlUtil $curlUtil,
private readonly ZNZConfiguration $configuration,
private readonly ZNZLogger $logger,
) {
}
public function isConnectionWorking(): bool
{
$this->getConnection()->getQueryBuilder()
->select('ID')
->from('wpj.TabZmeny')
->setMaxResults(1)
->execute()->fetchOne();
return true;
}
public function getChangesCount(): int
{
$count = $this->getConnection()->getQueryBuilder()
->select('COUNT(*)')
->from('wpj.TabZmeny')
->execute()->fetchOne();
return (int) $count;
}
public function isProductForCurrentWebsite(int $productId): bool
{
$result = sqlQueryBuilder()
->select('id_znz')
->from('znz_products_website')
->andWhere(Operator::equals(['id_znz' => $productId]))
->andWhere(Operator::inStringArray(array_keys($this->configuration->getSupportedWebsites()), 'id_website'))
->execute()->fetchOne();
if ($result) {
return true;
}
return false;
}
public function getDocument(string $path): ?string
{
$file = $this->configuration->getDocumentsUrl().'/'.ltrim($path, '/');
$response = $this->curlUtil->getClient()->request('GET', $file);
try {
if (!($content = $response->getContent())) {
$content = null;
}
} catch (\Throwable $e) {
$content = null;
}
return $content;
}
public function createOrder(array $data): string
{
// zaloguju do Kibany
$this->logger->kibana('Create order', [
'data' => $data,
]);
$result = $this->procedure(
'wpj.MX_ObjednavkaImportJSON02',
[
'json' => json_encode($data),
],
[
'ErrorText' => [
'type' => 'nvarchar(max)',
'alias' => 'error',
],
'GUIDObjednavka' => [
'type' => 'binary(16)',
'alias' => 'id_znz',
],
]
);
if (empty($result['error']) && empty($result['id_znz'])) {
throw new ZNZException(
sprintf('Unable to create order: %s', $result['error'] ?? 'unexpected response'),
['data' => $data, 'result' => $result]
);
}
if (!empty($result['error'])) {
// pokud je to chyba, ale vrati nam Helios ID, tak nevyhazuju chybu, ale vracim ID
// napr. chyba: Objednavka XXXX už byla naimportována;
if (!empty($result['id_znz'])) {
return base64_encode($result['id_znz']);
}
throw new ZNZException(
sprintf('Unable to create order: %s', $result['error']),
['data' => $data]
);
}
return base64_encode($result['id_znz']);
}
public function updateUser(array $data): int
{
// zaloguju do Kibany
$this->logger->kibana('User: update user', [
'data' => $data,
]);
$result = $this->procedure(
'wpj.MX_ZakaznikImportJSON',
[
'json' => json_encode($data),
],
[
'ErrorText' => [
'type' => 'nvarchar(max)',
'alias' => 'error',
],
'IdZakaznik' => [
'type' => 'int',
'alias' => 'id_znz',
],
]
);
if (!empty($result['error']) && empty($result['id_znz'])) {
throw new ZNZException(
sprintf('Unable to update user: %s', $result['error']),
['data' => $data]
);
}
return (int) $result['id_znz'];
}
public function updateOrderPaymentStatus(array $data): bool
{
$result = $this->procedure(
'wpj.MX_ObjednavkaImportJSONStavPlatby',
[
'json' => json_encode($data),
],
[
'ErrorText' => [
'type' => 'nvarchar(max)',
'alias' => 'error',
],
]
);
if (!empty($result['error'])) {
throw new ZNZException(
sprintf('Unable to update order payment status: %s', $result['error']),
['data' => $data]
);
}
return true;
}
public function updateUserAddress(array $data): int
{
$result = $this->procedure(
'wpj.MX_AdresaImportJSON',
[
'json' => json_encode($data),
],
[
'ErrorText' => [
'type' => 'nvarchar(max)',
'alias' => 'error',
],
'IdAdresa' => [
'type' => 'int',
'alias' => 'id_znz',
],
]
);
if (!empty($result['error']) && preg_match('/IdAdresa=(\d+)/', $result['error'], $match)) {
if (!empty($match[1])) {
$result['id_znz'] = (int) $match[1];
}
}
if (!empty($result['error']) && empty($result['id_znz'])) {
throw new ZNZException(
sprintf('Unable to update user address: %s', $result['error']),
['data' => $data]
);
}
return (int) $result['id_znz'];
}
public function updateProductsBlockToHelios(int $znzId, string $language, array $data, string $plainContent = '', bool $withTriggers = true): void
{
$this->procedure(
'wpj.MX_ProduktPopisImportJSON',
[
'json' => json_encode(
[
'IdProdukt' => $znzId,
'IdLanguage' => $language,
'PopisRich' => json_encode($data),
'PopisPlain' => $plainContent,
]
),
'PrenasetDal' => $withTriggers ? 1 : 0,
],
[
'ErrorText' => [
'type' => 'nvarchar',
'alias' => 'error',
],
]
);
}
public function updateProducersBlockToHelios(int $znzId, string $language, array $data, string $plainContent = '', bool $withTriggers = true): void
{
$this->procedure(
'wpj.MX_ZnackaPopisImportJSON',
[
'json' => json_encode(
[
'IdZnacka' => $znzId,
'IdLanguage' => $language,
'PopisRich' => json_encode($data),
'PopisPlain' => $plainContent,
]
),
'PrenasetDal' => $withTriggers ? 1 : 0,
],
[
'ErrorText' => [
'type' => 'nvarchar',
'alias' => 'error',
],
]
);
}
public function updateSeriesBlockToHelios(int $znzId, string $language, array $data, string $plainContent = '', bool $withTriggers = true): void
{
$this->procedure(
'wpj.MX_RadaPopisImportJSON',
[
'json' => json_encode(
[
'IdRada' => $znzId,
'IdLanguage' => $language,
'PopisRich' => json_encode($data),
'PopisPlain' => $plainContent,
]
),
'PrenasetDal' => $withTriggers ? 1 : 0,
],
[
'ErrorText' => [
'type' => 'nvarchar',
'alias' => 'error',
],
]
);
}
public function procedure(string $name, array $parameters, array $outParameters = [], bool $fetch = true): ?array
{
try {
$conn = $this->getConnection()->getConnection()->getWrappedConnection();
$stmt = $conn->prepare($this->prepareProcedure($name, $parameters, $outParameters));
$stmt->execute($parameters);
} catch (\Throwable $e) {
throw new ZNZException(
sprintf('Failed to execute stored procedure "%s": %s', $name, $e->getMessage()),
[
'name' => $name,
'parameters' => $parameters,
'exceptionMessage' => $e->getMessage(),
],
ZNZException::TYPE_HARD,
500,
$e
);
}
$result = null;
try {
do {
if ($stmt->columnCount() > 0) {
$result = $stmt->fetch(\PDO::FETCH_ASSOC);
break;
}
} while ($stmt->nextRowset());
} catch (\PDOException $e) {
throw new ZNZException(
sprintf('Failed to execute stored procedure "%s": %s', $name, $e->getMessage()),
[
'exceptionMessage' => $e->getMessage(),
'name' => $name,
'parameters' => $parameters,
],
ZNZException::TYPE_HARD,
500,
$e
);
}
return $result ?: null;
}
private function prepareProcedure(string $name, array $parameters, array $outParameters = []): string
{
$SQL = [];
$procedure = 'EXEC '.$name;
$values = [];
$declare = [];
$select = [];
// set procedure values
foreach ($parameters as $name => $_) {
$values[] = '@'.$name.' = :'.$name;
}
// output values definition
foreach ($outParameters as $name => $def) {
$declare[] = '@'.$name.' '.$def['type'];
$select[] = '@'.$name.' as '.$def['alias'];
$values[] = '@'.$name.' = @'.$name.($def['no_output'] ?? false ? '' : ' OUTPUT');
}
if (!empty($declare)) {
$SQL[] = 'DECLARE '.implode(', ', $declare);
}
$SQL[] = $procedure.' '.implode(', ', $values);
if (!empty($select)) {
$SQL[] = 'SELECT '.implode(', ', $select);
}
// return sql
return implode('; ', $SQL);
}
public function getConnection(): MoneyConnection
{
if (!$this->connection) {
$this->connection = new MoneyConnection(
$this->getConnectionParameters()
);
}
return $this->connection;
}
public function closeConnection(): void
{
$this->getConnection()->close();
$this->connection = null;
}
public function setConnectionParameters(array $parameters): void
{
$this->connectionParameters = $parameters;
$this->closeConnection();
}
public function getConnectionParameters(): array
{
if (!$this->connectionParameters) {
return [
'db_name' => $this->configuration->getHeliosConnectionParameters()['dbname'],
'db_user' => $this->configuration->getHeliosConnectionParameters()['user'],
'db_pass' => $this->configuration->getHeliosConnectionParameters()['pass'],
'db_host' => $this->configuration->getHeliosConnectionParameters()['host'],
'db_port' => $this->configuration->getHeliosConnectionParameters()['port'],
'timeout' => 60,
'pooling' => false,
];
}
return $this->connectionParameters;
}
}