<?php
namespace Klaravik\Category\Cache;
use Klaravik\Category\Cache\Model\CacheCategory;
use Klaravik\Common\Collections\ArrayCollection;
use Klaravik\Exception\CategoryCacheException;
final class CacheCategoryCollection extends ArrayCollection
{
/** @var CacheCategory[] */
protected $elements;
/**
* @param int $level
*
* @return static
*/
public function getByLevel($level)
{
return new static(array_filter($this->elements, function($cacheCategory) use($level) {
return $cacheCategory->getLevel() === $level;
}));
}
/**
* Get top level of categories
*
* @return $this
*/
public function getTopLevel()
{
return $this->getByLevel(0);
}
/**
* @param int $categoryId
*
* @return CacheCategory
*
* @throws CategoryCacheException
*/
public function findById($categoryId)
{
foreach ($this->elements as $cacheCategory) {
if ($cacheCategory->getId() === $categoryId) {
return $cacheCategory;
}
}
throw new CategoryCacheException('Missing category for id '. $categoryId);
}
/**
* Filter out collection on showOnlyInParent
*
* @param bool $value
*
* @return CacheCategoryCollection
*/
public function showOnlyInParent($value)
{
return new static(array_filter($this->elements, function(CacheCategory $cacheCategory) use ($value) {
return $cacheCategory->isShowOnlyInParent() === $value;
}));
}
/**
* Filter out categories that has products in them
*
* @return $this
*/
public function hasProductCount()
{
return new static(array_filter($this->elements, function(CacheCategory $cacheCategory) {
return $cacheCategory->getNumberOfProducts() > 0;
}));
}
/**
* Flatten the collection
*
* @return array|mixed
*/
public function flatten()
{
$return = array();
foreach ($this->elements as $cacheCategory) {
$return[] = $cacheCategory;
if ($cacheCategory->getChildren()->count()) {
$return = array_merge($return, $cacheCategory->getChildren()->flatten());
}
}
return $return;
}
/**
* @return CacheCategory[]
*/
public function toArray()
{
return $this->elements;
}
/**
* Sort collection by order
*
* @return CacheCategoryCollection
*
* @throws \Exception
*/
public function sortByOrder()
{
$iterator = $this->getIterator();
$iterator->uasort(function($a, $b) {
return ($a->getOrder() < $b->getOrder()) ? -1 : 1;
});
return new self(iterator_to_array($iterator));
}
/**
* @param null|int $selectedCategoryId
*
* @return int
*/
public function totalNumberOfProducts($selectedCategoryId = null)
{
try {
return $this->findById($selectedCategoryId)->getNumberOfProducts();
} catch (CategoryCacheException $e) {
}
return array_reduce($this->getTopLevel()->elements, function($count, CacheCategory $cacheCategory) {
return $count + $cacheCategory->getNumberOfProducts();
}, 0);
}
/**
* @param string $urlName
*
* @return CacheCategory|null
*/
public function findOneByUrlName(string $urlName): ?CacheCategory
{
foreach ($this->elements as $category) {
if ($category->getUrl() === $urlName) {
return $category;
}
}
return null;
}
}