Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
jissereitsma committed Feb 1, 2024
1 parent 8bf3fed commit 2d9b793
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 146 deletions.
19 changes: 10 additions & 9 deletions DataLayer/Mapper/ProductDataMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@
namespace Yireo\GoogleTagManager2\DataLayer\Mapper;

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Pricing\Price\FinalPrice;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Yireo\GoogleTagManager2\Api\Data\ProductTagInterface;
use Yireo\GoogleTagManager2\Api\Data\TagInterface;
use Yireo\GoogleTagManager2\Config\Config;
use Yireo\GoogleTagManager2\Util\Attribute\GetAttributeValue;
use Yireo\GoogleTagManager2\Util\GetCategoryFromProduct;
use Yireo\GoogleTagManager2\Util\CategoryProvider;
use Yireo\GoogleTagManager2\Util\PriceFormatter;

class ProductDataMapper
{
private Config $config;
private GetAttributeValue $getAttributeValue;
private GetCategoryFromProduct $getCategoryFromProduct;
private CategoryProvider $categoryProvider;
private PriceFormatter $priceFormatter;

private array $dataLayerMapping;
Expand All @@ -28,20 +27,20 @@ class ProductDataMapper
/**
* @param Config $config
* @param GetAttributeValue $getAttributeValue
* @param GetCategoryFromProduct $getCategoryFromProduct
* @param CategoryProvider $categoryProvider
* @param PriceFormatter $priceFormatter
* @param array $dataLayerMapping
*/
public function __construct(
Config $config,
GetAttributeValue $getAttributeValue,
GetCategoryFromProduct $getCategoryFromProduct,
CategoryProvider $categoryProvider,
PriceFormatter $priceFormatter,
array $dataLayerMapping = []
) {
$this->config = $config;
$this->getAttributeValue = $getAttributeValue;
$this->getCategoryFromProduct = $getCategoryFromProduct;
$this->categoryProvider = $categoryProvider;
$this->priceFormatter = $priceFormatter;
$this->dataLayerMapping = $dataLayerMapping;
}
Expand Down Expand Up @@ -73,14 +72,16 @@ public function mapByProduct(ProductInterface $product): array
}

try {
$productData[$prefix . 'list_id'] = $this->getCategoryFromProduct->get($product)->getId();
$productData[$prefix . 'list_name'] = $this->getCategoryFromProduct->get($product)->getName();
$category = $this->categoryProvider->getFirstByProduct($product);
$productData[$prefix . 'list_id'] = $category->getId();
$productData[$prefix . 'list_name'] = $category->getName();
} catch (NoSuchEntityException $noSuchEntityException) {
}

$productData['price'] = $this->priceFormatter->format(
(float)$product->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE)->getValue()
);

$productData = $this->attachCategoriesData($product, $productData);
$productData = $this->parseDataLayerMapping($product, $productData);
$productData['index'] = $this->counter++;
Expand All @@ -106,7 +107,7 @@ private function getProductFields(): array
private function attachCategoriesData(ProductInterface $product, array $data): array
{
try {
$categories = $this->getCategoryFromProduct->getAll($product);
$categories = $this->categoryProvider->getAllByProduct($product);
} catch (NoSuchEntityException $e) {
return $data;
}
Expand Down
4 changes: 2 additions & 2 deletions DataLayer/Tag/Cart/CartItems.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function get(): array
return [];
}

$this->productProvider->setProductSkus($this->getSkusFromCartItems($cartItems));
$this->productProvider->addProductSkus($this->getSkusFromCartItems($cartItems));
$cartItemsData = [];

foreach ($cartItems as $cartItem) {
Expand All @@ -65,6 +65,6 @@ private function getSkusFromCartItems(array $cartItems): array
$productSkus[] = $cartItem->getSku();
}

return $productSkus;
return array_unique($productSkus);
}
}
8 changes: 8 additions & 0 deletions Test/Functional/BaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@

namespace Yireo\GoogleTagManager2\Test\Functional;

use Magento\Framework\App\ObjectManager;
use Magento\Framework\Component\ComponentRegistrar;
use PHPUnit\Framework\TestCase;

class BaseTest extends TestCase
{
public function testIfModuleIsEnabled()
{
$componentRegistrar = ObjectManager::getInstance()->get(ComponentRegistrar::class);
$path = $componentRegistrar->getPath('module', 'Yireo_GoogleTagManager2');
$this->assertTrue(file_exists($path.'/registration.php'));
}
}
55 changes: 55 additions & 0 deletions Test/Functional/Util/CategoryProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
declare(strict_types=1);

namespace Yireo\GoogleTagManager2\Test\Functional\Util;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\App\ObjectManager;
use PHPUnit\Framework\TestCase;
use Yireo\GoogleTagManager2\Exception\NotUsingSetProductSkusException;
use Yireo\GoogleTagManager2\Util\CategoryProvider;

class CategoryProviderTest extends TestCase
{
public function testGetCategoriesWithException()
{
$this->expectException(NotUsingSetProductSkusException::class);
$categoryProvider = ObjectManager::getInstance()->get(CategoryProvider::class);
$categoryProvider->getLoadedCategories();
}

public function testGetById()
{
$categoryProvider = ObjectManager::getInstance()->get(CategoryProvider::class);
$categoryProvider->addCategoryIds([11, 38]);
$category = $categoryProvider->getById(11);
$this->assertEquals(11, $category->getId());
}

public function testGetCategories()
{
$categoryProvider = ObjectManager::getInstance()->get(CategoryProvider::class);
$categoryProvider->addCategoryIds([11, 38]);
$categories = $categoryProvider->getLoadedCategories();
$this->assertEquals(2, count($categories));

$categoryProvider->addCategoryIds(['12', 14]);
$categories = $categoryProvider->getLoadedCategories();
$this->assertEquals(4, count($categories));

$categoryProvider->addCategoryIds([12, 14]);
$categories = $categoryProvider->getLoadedCategories();
$this->assertEquals(4, count($categories));
}

public function testGetByProduct()
{
$productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class);
$product = $productRepository->getById(1);

$categoryProvider = ObjectManager::getInstance()->get(CategoryProvider::class);
$categoryProvider->addCategoryIds([11, 38]);
$categories = $categoryProvider->getAllByProduct($product);
$this->assertEquals(2, count($categories));
}
}
180 changes: 180 additions & 0 deletions Util/CategoryProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<?php declare(strict_types=1);

namespace Yireo\GoogleTagManager2\Util;

use Magento\Catalog\Api\CategoryListInterface;
use Magento\Catalog\Api\Data\CategoryInterface;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Framework\Api\FilterBuilder;
use Magento\Framework\Api\Search\FilterGroup;
use Magento\Framework\Api\Search\FilterGroupBuilder;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Store\Model\Store;
use Magento\Store\Model\StoreManagerInterface;
use Yireo\GoogleTagManager2\Exception\NotUsingSetProductSkusException;

class CategoryProvider
{
/**
* @var int[]
*/
private array $categoryIds = [];

/**
* @var CategoryInterface[]
*/
private array $loadedCategories = [];

private CategoryListInterface $categoryListRepository;
private FilterBuilder $filterBuilder;
private SearchCriteriaBuilder $searchCriteriaBuilder;
private FilterGroupBuilder $filterGroupBuilder;
private StoreManagerInterface $storeManager;

public function __construct(
CategoryListInterface $categoryListRepository,
FilterBuilder $filterBuilder,
SearchCriteriaBuilder $searchCriteriaBuilder,
FilterGroupBuilder $filterGroupBuilder,
StoreManagerInterface $storeManager
) {
$this->categoryListRepository = $categoryListRepository;
$this->filterBuilder = $filterBuilder;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
$this->filterGroupBuilder = $filterGroupBuilder;
$this->storeManager = $storeManager;
}

/**
* @param int[] $categoryIds
* @return void
* @throws NoSuchEntityException
*/
public function addCategoryIds(array $categoryIds)
{
$rootCategoryId = $this->getRootCategoryId();
$categoryIds = array_filter($categoryIds, function($categoryId) use ($rootCategoryId) {
return (int)$categoryId !== $rootCategoryId;
});
$this->categoryIds = array_unique(array_merge($this->categoryIds, $categoryIds));
}

/**
* @param int $categoryId
* @return CategoryInterface
* @throws NoSuchEntityException
*/
public function getById(int $categoryId): CategoryInterface
{
foreach ($this->getLoadedCategories() as $category) {
if ((int)$category->getId() === $categoryId) {
return $category;
}
}

throw new NotUsingSetProductSkusException('Using getCategoryById() delivers no result');
}

/**
* @return CategoryInterface[]
* @throws NoSuchEntityException
*/
public function getLoadedCategories(): array
{
if (empty($this->categoryIds)) {
throw new NotUsingSetProductSkusException('Using getCategories() before setCategoryIds()');
}

$loadCategoryIds = array_diff($this->categoryIds, array_keys($this->loadedCategories));
if (count($loadCategoryIds) > 0) {
foreach ($this->loadCategoriesByIds($loadCategoryIds) as $category) {
$this->loadedCategories[(int)$category->getId()] = $category;
}
}

return array_filter($this->loadedCategories, function(CategoryInterface $category) {
return $category->getIsActive();
});
}

/**
* @param ProductInterface $product
* @return CategoryInterface
* @throws NoSuchEntityException
*/
public function getFirstByProduct(ProductInterface $product): CategoryInterface
{
$productCategoryIds = $product->getCategoryIds();
$productCategoryId = array_shift($productCategoryIds);
$this->addCategoryIds([$productCategoryId]);

return $this->getLoadedCategories()[$productCategoryId];
}

/**
* @param ProductInterface $product
* @return CategoryInterface[]
* @throws NoSuchEntityException
*/
public function getAllByProduct(ProductInterface $product): array
{
$productCategoryIds = $product->getCategoryIds();
$this->addCategoryIds($productCategoryIds);

return array_filter(
$this->getLoadedCategories(),
function (CategoryInterface $category) use ($productCategoryIds) {
return in_array($category->getId(), $productCategoryIds);
}
);
}

/**
* @param array $categoryIds
* @return CategoryInterface[]
* @throws NoSuchEntityException
*/
private function loadCategoriesByIds(array $categoryIds): array
{
/** @var FilterGroup $entityIdFilterGroup */
$entityIdFilterGroup = $this->filterGroupBuilder->create();
$entityIdFilterGroup->setFilters([
$this->filterBuilder
->setField('entity_id')
->setConditionType('in')
->setValue($categoryIds)
->create(),
]);

/** @var FilterGroup $rootCategoryFilterGroup */
$rootCategoryFilterGroup = $this->filterGroupBuilder->create();
$rootCategoryFilterGroup->setFilters([
$this->filterBuilder
->setField('path')
->setConditionType('like')
->setValue('1/'.$this->getRootCategoryId().'/%')
->create(),
]);

$this->searchCriteriaBuilder->setFilterGroups([
$entityIdFilterGroup,
$rootCategoryFilterGroup,
]);

$searchCriteria = $this->searchCriteriaBuilder->create();

return $this->categoryListRepository->getList($searchCriteria)->getItems();
}

/**
* @return int
* @throws NoSuchEntityException
*/
private function getRootCategoryId(): int
{
/** @var Store $store */
$store = $this->storeManager->getStore();
return (int)$store->getRootCategoryId();
}
}
Loading

0 comments on commit 2d9b793

Please sign in to comment.