<?php
/**
* Created by PhpStorm.
* User: adv
* Date: 29.11.15
* Time: 15:30
*/
namespace Slivki\Repository;
use Slivki\Entity\CacheReloadScheduler;
use Slivki\Entity\Category;
use Slivki\Entity\City;
use Slivki\Entity\FavouriteCategory;
use Slivki\Entity\Media;
use Slivki\Entity\PopularCategory;
use Slivki\Entity\Sale;
use Slivki\Entity\Seo;
use Slivki\Entity\User;
use Slivki\Entity\VisitCounter;
use Slivki\Util\SoftCache;
class CategoryRepository extends CategoryRepositoryBase {
const FAVOURITE_CATEGORIES_COUNT = 3;
const SORTED_SALE_CATEGORIES_CACHE_KEY = "sorted_sale_categories";
public function getSupplierCategories(Category $category) {
return $this->getActiveCategories($category->getID(), array(Category::SUPPLIER_CATEGORY_TYPE), $category->getDomainObjectID());
}
/** @deprecated use CategoryCacheService */
public function reloadCategoryCache($categoryID) {
$softCache = new SoftCache(self::CACHE_NAME);
//$this->reloadEntityList($categoryID);
$categoryCached = $softCache->getWithLock($categoryID);
$category = $this->find($categoryID);
if (!$category) {
$softCache->delete($categoryID);
return false;
}
$category->getBanners()->toArray();
$category->getParentCategories()->toArray();
$city = $category->getCity();
if ($city) {
$city->getID();
} else {
$city = $this->getEntityManager()->find(City::class, City::DEFAULT_CITY_ID);
$category->setCity($city);
}
$category->getMobileMenuIconMedia();
$category->getAppIconMedia();
/*if (!isset($categoryCached['entityList']) || !$categoryCached['entityList'] || count($categoryCached['entityList'] == 0)) {
$this->removeCategoryFromCache($categoryID);
return false;
}*/
if (isset($categoryCached['entityList'])) {
$category->setEntityCount(count($categoryCached['entityList']));
} else {
$this->reloadEntityList($categoryID);
}
$this->getEntityManager()->flush($category);
$mediaRepository = $this->getEntityManager()->getRepository(Media::class);
$category->setHotFeedMedia($mediaRepository->getСategoryHotFeedImageMedia($categoryID));
$category->setHotFeedIconMedia($mediaRepository->getСategoryHotFeedIconMedia($categoryID));
$categoryCached['category'] = $category;
$softCache->set($categoryID, $categoryCached, 0);
$allCategoriesCached = $softCache->getWithLock(self::ALL_CATEGORIES_CACHE_KEY);
$allCategoriesCached[$categoryID] = $categoryCached;
$softCache->set(self::ALL_CATEGORIES_CACHE_KEY, $allCategoriesCached, 0);
$softCache->set($categoryID, $categoryCached, 0);
switch ($category->getDomainObjectID()) {
case Category::OFFER_CATEGORY_ID:
$this->getEntityManager()->getRepository(Seo::class)->reloadCacheForEntity(SeoRepository::RESOURCE_URL_OFFER_CATEGORY, $categoryID);
break;
case Category::SALE_CATEGORY_ID:
$this->getEntityManager()->getRepository(Seo::class)->reloadCacheForEntity(SeoRepository::RESOURCE_URL_SALE_CATEGORY, $categoryID);
break;
}
return $categoryCached;
}
public function scheduleCategoryReload($categoryID) {
$scheduler = new CacheReloadScheduler();
$scheduler->setType(CacheReloadScheduler::TYPE_CATEGORY);
$scheduler->setEntityID($categoryID);
$entityManager = $this->getEntityManager();
$entityManager->persist($scheduler);
$entityManager->flush($scheduler);
}
//TODO: Store entityList in class field
public function putCategoryToCache($category) {
if (!$category['category']->isActive() || $category['category']->isPast()) {
return;
}
$entityCount = count($category['entityList']);
$category['category']->setEntityCount($entityCount);
$category['category']->getParentCategories()->toArray();
$category['category']->getCity()->getID();
$softCache = new SoftCache(self::CACHE_NAME);
$categoryList = $softCache->get(self::ALL_CATEGORIES_CACHE_KEY);
$categoryList[$category['category']->getID()] = $category;
$softCache->set(self::ALL_CATEGORIES_CACHE_KEY, $categoryList, 0);
$softCache->set($category['category']->getID(), $category, 0);
$category = $this->find($category['category']->getID());
if (!$category) {
return;
}
$category->setEntityCount($entityCount);
$this->getEntityManager()->flush($category);
$this->scheduleCategoryReload($category->getID());//Workaround for tarantool. TODO: remove
}
public function removeCategoryFromCache($categoryID) {
$softCache = new SoftCache(self::CACHE_NAME);
$categoryList = $softCache->get(self::ALL_CATEGORIES_CACHE_KEY);
unset($categoryList[$categoryID]);
$softCache->set(self::ALL_CATEGORIES_CACHE_KEY, $categoryList, 0);
$softCache->delete($categoryID);
}
public function getPayedOffersByCategoryID($categoryID, $sales = false) {
if ($sales) {
$dql = "select sale.ID, offerPayedCategory.position from Slivki:Sale sale index by sale.ID
join sale.categories category
join Slivki:OfferPayedCategory offerPayedCategory
with offerPayedCategory.entityID = sale.ID and offerPayedCategory.categoryID = :categoryID
where category.ID = :categoryID
order by offerPayedCategory.position";
} else {
$dql = "select offer.ID, offerPayedCategory.position from Slivki:Offer offer index by offer.ID
join offer.categories category
join Slivki:OfferPayedCategory offerPayedCategory
with offerPayedCategory.entityID = offer.ID and offerPayedCategory.categoryID = :categoryID
where category.ID = :categoryID
order by offerPayedCategory.position";
}
return $this->getEntityManager()->createQuery($dql)->setParameter('categoryID', $categoryID)->getResult();
}
/**
* @deprecated use CategoryService -> getCategoryNameWithBreadcrumbs
*/
public function getCategoryBreadcrumbs(Category $category) {
$breadcrumbs = '';
foreach ($this->getCategoryParentList($category) as $category) {
$breadcrumbs .= $category->getName() . ' > ';
}
return $breadcrumbs;
}
public function reloadEntityList($categoryID) {
$category = $this->findCached($categoryID);
if (!$category) {
$this->reloadCategoryCache($categoryID);//TODO: move to service
$category = $this->findCached($categoryID);
}
if (!$category || !isset($category['category'])) {
return;
}
if ($category['category']->getDomainObjectID() == Category::OFFER_CATEGORY_ID) {
$sql = "select distinct(offer.id) from category2entity
inner join offer on offer.id = category2entity.entity_id
where category2entity.category_id = $categoryID and offer.active
and now() between offer.active_since and offer.active_till and not offer.hidden;";
$category['entityList'] = $this->getEntityManager()->getConnection()->executeQuery($sql)->fetchAll(\PDO::FETCH_COLUMN);
$this->putCategoryToCache($category);
} else if ($category['category']->getDomainObjectID() == Category::SALE_CATEGORY_ID) {
$sql = 'select sale.id from sale inner join category2entity on sale.id = category2entity.entity_id
where category2entity.category_id = ' . (int)$categoryID . ' and now() between sale.since and sale.till and sale.active';
$category['entityList'] = $this->getEntityManager()->getConnection()->executeQuery($sql)->fetchAll(\PDO::FETCH_COLUMN);
$this->putCategoryToCache($category);
}
}
public function getActiveEntityListByCategory($categoryID) {
$softCache = new SoftCache(self::CACHE_NAME);
$category = $softCache->get($categoryID);
if (!$category) {
return [];
}
$cacheName = false;
switch ($category['category']->getDomainObjectID()) {
case 1:
$cacheName = OfferRepository::CACHE_NAME;
break;
case Category::SALE_CATEGORY_ID:
$cacheName = SaleRepository::CACHE_NAME;
break;
case 4:
$cacheName = PartnerOfferRepository::CACHE_NAME;
break;
case Category::INSTALLMENT_CATEGORY_ID:
$cacheName = InstallmentRepository::CACHE_NAME;
break;
}
if (!$cacheName) {
return [];
}
$softCache = new SoftCache($cacheName);
$entityList = $softCache->getMulti($category['entityList']);
return $entityList ? $entityList : [];
}
public function getRootCategoryList($domainObjectID, $cityID = null) {
$cityCondition = '';
if ($cityID) {
$cityCondition = ' and city.ID = :cityID ';
}
$dql = 'select category from Slivki:Category category join category.city city where category.active = true and category.past = false and category.domainObjectID = :domainObjectID ' . $cityCondition . ' and category.parents is empty order by category.sortOrder';
$query = $this->getEntityManager()->createQuery($dql);
$query->setParameter('domainObjectID', $domainObjectID);
if ($cityID) {
$query->setParameter('cityID', $cityID);
}
return $query->getResult();
}
public function getUserFavouriteCategories(User $user = null) {
$favouriteCategoryList = $this->getEntityManager()->getRepository(PopularCategory::class)->findBy([], ['sortOrder' => 'asc'], self::FAVOURITE_CATEGORIES_COUNT);
$mediaRepository = $this->getEntityManager()->getRepository(Media::class);
foreach ($favouriteCategoryList as $key => $category) {
$favouriteCategoryList[$key] = [
'category' => $category->getCategory(),
'media' => $mediaRepository->getLandingCategoryMedia($category->getCategory())
];
}
return $favouriteCategoryList;
}
public function getCategoriesCached(array $categoryIDList) {
$softCache = new SoftCache(self::CACHE_NAME);
return $softCache->getMulti($categoryIDList);
}
public function getSaleCategoriesSortedBySaleVisits() {
$softCache = new SoftCache(self::CACHE_NAME);
$saleCategoriesSortedBySaleVisits = $softCache->get(self::SORTED_SALE_CATEGORIES_CACHE_KEY);
return $saleCategoriesSortedBySaleVisits ? $saleCategoriesSortedBySaleVisits : [];
}
public function reloadSaleCategoriesSortedBySaleVisitsCache() {
$sql = "select category.id, coalesce(max(v.visit), 0) as cnt from category
inner join category2entity on category.id = category2entity.category_id
left join (select entity_id, count(*) as visit from visit
where visit.entity_type_id = " . Category::SALE_CATEGORY_ID . " and visit.created_on > now() - interval '1 day'
group by 1) as v on category2entity.entity_id = v.entity_id
where category.active and category.domain_object_id = " . Category::SALE_CATEGORY_ID . " and category.id not in (select child_id from category_child_relation) group by 1 order by 2 desc;";
$sortedSaleCategoryIDList = $this->getEntityManager()->getConnection()->executeQuery($sql)->fetchAll(\PDO::FETCH_COLUMN);
$sortedSaleCategoryList = self::getCategoriesCached($sortedSaleCategoryIDList);
$result = [];
$resultWithPosition = [];
foreach ($sortedSaleCategoryList as $key => $sortedSaleCategoryItem) {
if ($sortedSaleCategoryItem) {
$category = $sortedSaleCategoryItem['category'];
$categoryPosition = $category->getSortOrder();
if ($categoryPosition > 0) {
while (isset($resultWithPosition[$categoryPosition])) {
$categoryPosition++;
}
$resultWithPosition[$categoryPosition] = $category;
} else {
$result[] = $category;
}
}
}
ksort($resultWithPosition);
foreach ($resultWithPosition as $key => $item) {
array_splice($result, $key - 1, 0, [$item]);
}
$softCache = new SoftCache(self::CACHE_NAME);
$softCache->set(self::SORTED_SALE_CATEGORIES_CACHE_KEY, $result, 0);
}
public function getSaleVideoguideCategoryMenu() {
$saleVideoguideCategory = $this->getEntityManager()->getRepository(Category::class)->findCached(Category::SALE_VIDEO_GUIDE_CATEGORY_ID);
return $this->getSubCategories($saleVideoguideCategory['category']);
}
public function getSaleVideoguideAutorsCategoryMenu() {
$entityManager = $this->getEntityManager();
$saleVideoguideAutorsCategory = $entityManager->getRepository(Category::class)->findCached(Category::SALE_VIDEO_GUIDE_AUTORS_CATEGORY_ID);
$autorsMenu = [];
$saleRepository = $entityManager->getRepository(Sale::class);
$visitCounterRepository = $entityManager->getRepository(VisitCounter::class);
/** @var Category $category */
foreach ($this->getSubCategories($saleVideoguideAutorsCategory['category']) as $category) {
$visitCount = 0;
/** @var Sale $sale */
foreach ($saleRepository->getActiveSalesByCategoryID($category->getID()) as $sale) {
$visitCount += $visitCounterRepository->getVisitCount($sale->getID(), VisitCounter::TYPE_SALE, false);
}
$autorsMenu[] = [
'category' => $category,
'visitCount' => $visitCount
];
}
return $autorsMenu;
}
public function getParentCategoryIDsByOfferID($offerID) {
$sql = 'select category_id from category2entity left join category_child_relation on category2entity.category_id = category_child_relation.child_id where child_id is null and entity_id = ' . $offerID;
return $this->getEntityManager()->getConnection()->executeQuery($sql)->fetchAll(\PDO::FETCH_COLUMN);
}
public function scheduleCategoryBannerReload($categoryID) {
$scheduler = new CacheReloadScheduler();
$scheduler->setType(CacheReloadScheduler::TYPE_CATEGORY_BANNER);
$scheduler->setEntityID($categoryID);
$entityManager = $this->getEntityManager();
$entityManager->persist($scheduler);
$entityManager->flush($scheduler);
}
public function getCategoryForMobileApi($categoryID) {
$dql = 'select category, appIconMedia from Slivki:Category category left join category.appIconMedias appIconMedia where category.ID = :categoryID';
$query = $this->getEntityManager()->createQuery($dql);
$query->setParameter('categoryID', $categoryID);
$result = $query->getResult();
if ($result && count($result) > 0) {
return $result[0];
}
}
}