<?php
declare(strict_types=1);
namespace Slivki\Services\MeOnMap;
use Slivki\Dao\Category\CategoryDaoInterface;
use Slivki\Dao\MeOnMap\OfferPositionPaidDaoInterface;
use Slivki\Entity\Category;
use Slivki\Entity\MainMenu;
use Slivki\Factory\Category\CategoryWithGeoLocationsDtoFactoryInterface;
use Slivki\Factory\MeOnMap\OfferFeaturedPaidFactoryInterface;
use Slivki\Repository\Category\CategoryRepositoryInterface;
use Slivki\Repository\MainMenu\MainMenuRepositoryInterface;
use Slivki\Response\MeOnMap\GetCategoriesWithGeoLocationsResponse;
use Slivki\Serializer\Config\SerializerConfig;
use Slivki\Util\SoftCache;
use Symfony\Component\Serializer\SerializerInterface;
use function sprintf;
use function array_map;
use function count;
final class GetCategoriesWithGeoLocationsResponseCacheService
{
private const CACHE_NAME = 'me-on-map';
private const CACHE_KEY = 'get-categories-with-geo-location-response-city-%s';
private const CACHE_TIME_SECONDS = 3600;
private MainMenuRepositoryInterface $mainMenuRepository;
private CategoryRepositoryInterface $categoryRepository;
private CategoryWithGeoLocationsDtoFactoryInterface $categoryWithGeoLocationsDtoFactory;
private CategoryDaoInterface $categoryDao;
private OfferPositionPaidDaoInterface $offerPositionPaidDao;
private OfferFeaturedPaidFactoryInterface $offerFeaturedPaidFactory;
private SerializerInterface $serializer;
public function __construct(
MainMenuRepositoryInterface $mainMenuRepository,
CategoryRepositoryInterface $categoryRepository,
CategoryWithGeoLocationsDtoFactoryInterface $categoryWithGeoLocationsDtoFactory,
CategoryDaoInterface $categoryDao,
OfferPositionPaidDaoInterface $offerPositionPaidDao,
OfferFeaturedPaidFactoryInterface $offerFeaturedPaidFactory,
SerializerInterface $serializer
) {
$this->mainMenuRepository = $mainMenuRepository;
$this->categoryRepository = $categoryRepository;
$this->categoryWithGeoLocationsDtoFactory = $categoryWithGeoLocationsDtoFactory;
$this->categoryDao = $categoryDao;
$this->offerPositionPaidDao = $offerPositionPaidDao;
$this->offerFeaturedPaidFactory = $offerFeaturedPaidFactory;
$this->serializer = $serializer;
}
public function getByCityId(int $cityId): GetCategoriesWithGeoLocationsResponse
{
$cache = new SoftCache(self::CACHE_NAME);
$json = $cache->get($this->getCacheKeyByCityId($cityId));
if (empty($json)) {
$this->reloadByCityId($cityId);
$json = $cache->get($this->getCacheKeyByCityId($cityId));
}
return $this->serializer->deserialize($json, GetCategoriesWithGeoLocationsResponse::class, SerializerConfig::JSON);
}
public function reloadByCityId(int $cityId): void
{
$cache = new SoftCache(self::CACHE_NAME);
$activeMeOnMapCategories = $this->categoryRepository->findActiveMeOnMapCategoriesByCityId($cityId);
if (0 === count($activeMeOnMapCategories)) {
$activeMeOnMapCategories = array_map(
fn (MainMenu $mainMenuItem): Category =>
$this->categoryRepository->findCategoryByMainMenu($mainMenuItem),
$this->mainMenuRepository->findWithActiveOfferCategoriesByCityId($cityId),
);
}
$activeMeOnMapFeaturedCategories = $this->categoryRepository->findActiveMeOnMapFeaturedCategoriesByCityId($cityId);
if (0 === count($activeMeOnMapFeaturedCategories)) {
$featuredOnMapFilterCategoriesId = $this->categoryDao->getFeaturedOnMapFilterCategoriesId($cityId);
$activeMeOnMapFeaturedCategories = $this->categoryRepository->findByIds($featuredOnMapFilterCategoriesId);
} else {
$featuredOnMapFilterCategoriesId = array_map(
static fn(Category $category): int => $category->getID(),
$activeMeOnMapFeaturedCategories,
);
}
$response = new GetCategoriesWithGeoLocationsResponse(
array_map([$this->categoryWithGeoLocationsDtoFactory, 'create'], $activeMeOnMapCategories),
array_map([$this->categoryWithGeoLocationsDtoFactory, 'create'], $activeMeOnMapFeaturedCategories),
$featuredOnMapFilterCategoriesId,
array_map([$this->offerFeaturedPaidFactory, 'create'], $this->offerPositionPaidDao->findAllByCityId($cityId)),
);
$cache->set(
$this->getCacheKeyByCityId($cityId),
$this->serializer->serialize($response, SerializerConfig::JSON),
self::CACHE_TIME_SECONDS
);
}
private function getCacheKeyByCityId(int $cityId): string
{
return sprintf(self::CACHE_KEY, $cityId);
}
}