<?php declare(strict_types=1);
namespace GlobusSW6\Service\App;
use Doctrine\DBAL\Connection;
use GlobusSW6\Core\Content\Devices\DeviceEntity;
use Psr\Log\LoggerInterface;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Uuid\Uuid;
use Symfony\Component\HttpFoundation\Session\Session;
class AppService
{
/** @var Connection */
private $connection;
/** @var EntityRepositoryInterface */
private $deviceRepository;
/** @var LoggerInterface */
private $logger;
/**
* @param Connection $connection
* @param EntityRepositoryInterface $deviceRepository
* @param LoggerInterface $logger
*/
public function __construct(Connection $connection, EntityRepositoryInterface $deviceRepository, LoggerInterface $logger)
{
$this->connection = $connection;
$this->deviceRepository = $deviceRepository;
$this->logger = $logger;
}
public function getSalesChannelApiPayload(string $token)
{
$payload = $this->connection->fetchAssoc('
SELECT payload
FROM sales_channel_api_context scac
WHERE scac.token = :token;
', [
'token' => $token
]);
return $payload;
}
public function isAppFromSession(Session $session): bool
{
return !is_null($session->get('ianeo_hitseller_app_device_id'));
}
/**
* @param string $token
* @return string|null
*
* Given a string token, this method checks if the token is listed in the sales_channel_api_context.
* If yes, it checks whether the payload contains the flag ianeoCurrentStore and returns the selected store for this user.
* Otherwise, null is returned.
*/
public function getSelectedStoreInApp(string $token)
{
$payload = $this->getSalesChannelApiPayload($token);
if (!$payload) {
return null;
}
$payloadArray = json_decode((string)$payload['payload'], true);
if (!array_key_exists('ianeoCurrentStore', $payloadArray)) {
return null;
}
return $payloadArray['ianeoCurrentStore'];
}
/**
* @param string $deviceId
* @return DeviceEntity|null
*/
public function getAppDeviceById(string $deviceId): ?DeviceEntity
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('deviceId', $deviceId));
/** @var DeviceEntity $device */
return $this->deviceRepository->search($criteria, Context::createDefaultContext())->first();
}
public function saveDevice(string $deviceId, string $token)
{
try {
// perfomance improvement from 0.099 (DAL) to 0,001 (SQL)
$device = $this->connection->fetchAllAssociative('
SELECT *
FROM ianeo_device
WHERE device_id = :deviceId
LIMIT 1;
', ['deviceId' => $deviceId]);
$deviceUuid = Uuid::randomHex();
if (empty($device)) {
$this->deviceRepository->upsert([
[
'id' => $deviceUuid,
'deviceId' => $deviceId,
'swContextToken' => $token
]
], Context::createDefaultContext());
}
} catch (\Throwable $t) {
$this->logger->info('Unable to upsert device in saveDevice() - DeviceId: ' . $deviceId);
$this->logger->info('Unable to upsert device in saveDevice() - swContextToken: ' . $token);
$this->logger->info('Unable to upsert device in saveDevice() - Reason: ' . $t->getMessage());
throw new \Exception($t->getMessage());
}
return $deviceUuid;
}
public function saveStoreForDevice(string $contextToken, int $storeLegacyId, string $deviceId)
{
// perfomance test showed 1/1000 second better performance with sql
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('swContextToken', $contextToken));
$criteria->addFilter(new EqualsFilter('deviceId', $deviceId));
try {
/** @var DeviceEntity $device */
$deviceUuId = $this->deviceRepository->searchIds($criteria, Context::createDefaultContext())->firstId();
if (is_null($deviceUuId)) {
$this->logger->info('Unable to find id for device ' . $deviceId);
$this->logger->info('Unable to find id for device (token) ' . $contextToken);
$deviceUuId = $this->saveDevice($deviceId, $contextToken);
}
$this->connection->executeStatement("
UPDATE ianeo_device idv
SET idv.store_legacy_id = :storeId
WHERE idv.device_id = :deviceId
", ['storeId' => $storeLegacyId, 'deviceId' => $deviceId]);
} catch (\Throwable $t) {
$this->logger->info('Unable to upsert device in saveStoreForDevice() - DeviceUuid: ' . $deviceUuId);
$this->logger->info('Unable to upsert device in saveStoreForDevice() - DeviceId: ' . $deviceId);
$this->logger->info('Unable to upsert device in saveStoreForDevice() - swContextToken: ' . $contextToken);
$this->logger->info('Unable to upsert device in saveStoreForDevice() - storeLegacyId: ' . $storeLegacyId);
$this->logger->info('Unable to upsert device in saveStoreForDevice() - Reason: ' . $t->getMessage());
throw new \Exception($t->getMessage());
}
}
public function saveCustomerForDevice(string $deviceId, string $customerId)
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('deviceId', $deviceId));
try {
/** @var DeviceEntity $device */
$deviceUuId = $this->deviceRepository->searchIds($criteria, Context::createDefaultContext())->firstId();
$this->deviceRepository->update([
[
'id' => $deviceUuId,
'customerId' => $customerId
]
], Context::createDefaultContext());
} catch (\Throwable $t) {
$this->logger->info('Unable to upsert device in saveCustomerForDevice() - DeviceId: ' . $deviceUuId);
$this->logger->info('Unable to upsert device in saveCustomerForDevice() - customerId: ' . $customerId);
$this->logger->info('Unable to upsert device in saveCustomerForDevice() - Reason: ' . $t->getMessage());
throw new \Exception($t->getMessage());
}
}
public function deleteToken(string $deviceId)
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('deviceId', $deviceId));
try {
/** @var DeviceEntity $device */
$deviceUuId = $this->deviceRepository->searchIds($criteria, Context::createDefaultContext())->firstId();
$this->deviceRepository->update([
[
'id' => $deviceUuId,
'swContextToken' => null
]
], Context::createDefaultContext());
} catch (\Throwable $t) {
$this->logger->info('Unable to update device in deleteToken() - DeviceId: ' . $deviceUuId);
$this->logger->info('Unable to upsert device in deleteToken() - Reason: ' . $t->getMessage());
throw new \Exception($t->getMessage());
}
}
public function setNewToken(string $deviceId, string $token)
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('deviceId', $deviceId));
try {
/** @var DeviceEntity $device */
$deviceUuId = $this->deviceRepository->searchIds($criteria, Context::createDefaultContext())->firstId();
$this->deviceRepository->upsert([
[
'id' => $deviceUuId,
'swContextToken' => $token
]
], Context::createDefaultContext());
} catch (\Throwable $t) {
$this->logger->info('Unable to upsert device in setNewToken() - DeviceId: ' . $deviceUuId);
$this->logger->info('Unable to upsert device in setNewToken() - swContextToken: ' . $token);
$this->logger->info('Unable to upsert device in setNewToken() - Reason: ' . $t->getMessage());
throw new \Exception($t->getMessage());
}
}
}