Skip to content

Instantly share code, notes, and snippets.

@sandipklevu
Last active January 31, 2024 09:17
Show Gist options
  • Save sandipklevu/ab2909c35c37018cf0f0b710b1b342bb to your computer and use it in GitHub Desktop.
Save sandipklevu/ab2909c35c37018cf0f0b710b1b342bb to your computer and use it in GitHub Desktop.
\Klevu\Search\Model\Product\Product
<?php
namespace Klevu\Search\Model\Product;
use Klevu\Search\Api\Service\Catalog\Product\GetReviewCountInterface;
use Klevu\Logger\Constants as LoggerConstants;
use Klevu\Search\Api\Service\Catalog\Product\Review\ConvertRatingToStarsInterface;
use Klevu\Search\Api\Service\Catalog\Product\Review\GetAverageRatingInterface;
use Klevu\Search\Helper\Compat as CompatHelper;
use Klevu\Search\Helper\Config as ConfigHelper;
use Klevu\Search\Helper\Data as DataHelper;
use Klevu\Search\Helper\Image as ImageHelper;
use Klevu\Search\Helper\Price as PriceHelper;
use Klevu\Search\Model\Context;
use Magento\Catalog\Api\Data\ProductInterface as MagentoProductInterface;
use Magento\Catalog\Model\Product as MagentoProduct;
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as ProductCollectionFactory;
use Magento\Catalog\Pricing\Price\TierPrice;
use Magento\Customer\Model\Group as CustomerGroup;
use Magento\Framework\DataObject;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\UrlInterface;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\App\ResourceConnection;
class Product extends DataObject implements ProductInterface
{
/**
* @var StoreManagerInterface
*/
protected $_storeModelStoreManagerInterface;
/**
* @var DataHelper
*/
protected $_searchHelperData;
/**
* @var ImageHelper
*/
protected $_imageHelper;
/**
* @var PriceHelper
*/
protected $_priceHelper;
/**
* @var ConfigHelper
*/
protected $_configHelper;
/**
* @var CompatHelper
*/
protected $_searchHelperCompat;
/**
* @var CustomerGroup
*/
protected $_customerModelGroup;
/**
* @var GetReviewCountInterface
*/
private $getRatingsCount;
/**
* @var GetAverageRatingInterface
*/
private $getAverageRating;
/**
* @var ConvertRatingToStarsInterface
*/
private $convertRatingToStars;
/**
* @var ProductCollectionFactory
*/
private $productCollectionFactory;
private $resourceConnection;
/**
* @param Context $context
* @param array $data
* @param ResourceConnection $resourceConnection
* @param GetReviewCountInterface|null $getRatingsCount
* @param GetAverageRatingInterface|null $getAverageRating
* @param ConvertRatingToStarsInterface|null $convertRatingToStars
* @param ProductCollectionFactory|null $productCollectionFactory
*/
public function __construct(
Context $context,
array $data = [],
ResourceConnection $resourceConnection = null,
GetReviewCountInterface $getRatingsCount = null,
GetAverageRatingInterface $getAverageRating = null,
ConvertRatingToStarsInterface $convertRatingToStars = null,
ProductCollectionFactory $productCollectionFactory = null
) {
$this->_storeModelStoreManagerInterface = $context->getStoreManagerInterface();
$this->_searchHelperData = $context->getHelperManager()->getDataHelper();
$this->_imageHelper = $context->getHelperManager()->getImageHelper();
$this->_priceHelper = $context->getHelperManager()->getPriceHelper();
$this->_configHelper = $context->getHelperManager()->getConfigHelper();
$this->_searchHelperCompat = $context->getHelperManager()->getCompatHelper();
$this->_customerModelGroup = $context->getKlevuCustomerGroup();
$objectManager = ObjectManager::getInstance();
$this->getRatingsCount = $getRatingsCount
?: $objectManager->get(GetReviewCountInterface::class);
$this->getAverageRating = $getAverageRating
?: $objectManager->get(GetAverageRatingInterface::class);
$this->convertRatingToStars = $convertRatingToStars
?: $objectManager->get(ConvertRatingToStarsInterface::class);
$this->productCollectionFactory = $productCollectionFactory
?: $objectManager->get(ProductCollectionFactory::class);
$this->resourceConnection = $resourceConnection
?: $objectManager->get(
\Magento\Framework\App\ResourceConnection::class
);
parent::__construct($data);
}
/**
* @param MagentoProductInterface|null $parent
* @param MagentoProductInterface $item
*
* @return array
*/
public function getListCategory($parent, $item)
{
if ($parent) {
$product['listCategory'] = $this->getCategoryNames($parent->getCategoryIds());
} elseif ($item->getCategoryIds()) {
$product['listCategory'] = $this->getCategoryNames($item->getCategoryIds());
} else {
$product['listCategory'] = ["KLEVU_PRODUCT"];
}
return $product['listCategory'];
}
/**
* @param MagentoProductInterface|null $parent
* @param MagentoProductInterface $item
*
* @return string
*/
public function getAllCategoryId($parent, $item)
{
if ($parent) {
//category ids parent
$product['categoryIds'] = $this->getAllCategoryIdProcessed($parent);
} elseif ($item->getCategoryIds()) {
$product['categoryIds'] = $this->getAllCategoryIdProcessed($item);
} else {
$product['categoryIds'] = "";
}
return $product['categoryIds'];
}
/**
* @param MagentoProductInterface $item
*
* @return string
*/
private function getAllCategoryIdProcessed($item)
{
$itemCategories = $item->getCategoryIds();
$category_paths_ids = $this->getCategoryPathIds();
if ($category_paths_ids) {
$itemCategories = array_intersect($itemCategories, array_keys($category_paths_ids));
}
$category_anchors = $this->getCategoryAnchors();
$return = [];
$storeId = null;
try {
$store = $this->_storeModelStoreManagerInterface->getStore();
$storeId = $store->getId();
} catch (NoSuchEntityException $exception) {
$this->_searchHelperData->log(LoggerConstants::ZEND_LOG_ERR, $exception->getMessage());
}
$isCatAnchorSingle = $this->_configHelper->getTreatCategoryAnchorAsSingle($storeId);
if ($isCatAnchorSingle && is_array($itemCategories)) {
foreach ($itemCategories as $id) {
if (!isset($category_paths_ids[$id]) || !count($category_paths_ids[$id])) {
continue;
}
foreach ($category_paths_ids[$id] as $catIsAnchor) {
if (!isset($category_anchors[$catIsAnchor], $category_paths_ids[$catIsAnchor])) {
continue;
}
$return[] = end($category_paths_ids[$catIsAnchor]);
}
}
$return = array_merge($return, $itemCategories);
$itemCategories = array_unique($return);
}
return implode(";",
(is_array($itemCategories)
? $itemCategories
: []));
}
/**
* @param MagentoProductInterface|null $parent
* @param MagentoProductInterface $item
*
* @return string|null
*/
public function getAllCategoryPaths($parent, $item)
{
if ($parent) {
$product['categoryPaths'] = $this->getCategoryNamesAndPath($parent->getCategoryIds());
} elseif ($item->getCategoryIds()) {
$product['categoryPaths'] = $this->getCategoryNamesAndPath($item->getCategoryIds());
} else {
$product['categoryPaths'] = "";
}
return isset($product['categoryPaths'])
? (string)$product['categoryPaths']
: null;
}
/**
* Given a list of category IDs, return the name of the category
* in that list that has the longest path.
*
* @param array $categories
*
* @return string
*/
public function getLongestPathCategoryName(array $categories)
{
$storeId = null;
try {
$store = $this->_storeModelStoreManagerInterface->getStore();
$storeId = $store->getId();
} catch (NoSuchEntityException $e) {
$this->_searchHelperData->log(LoggerConstants::ZEND_LOG_ERR, $e->getMessage());
}
$category_paths = $this->getCategoryPaths();
$category_anchors = $this->getCategoryAnchors();
$category_paths_ids = $this->getCategoryPathIds();
$isCatAnchorSingle = $this->_configHelper->getTreatCategoryAnchorAsSingle($storeId);
$name = [];
foreach ($categories as $id) {
if (!isset($category_paths[$id])) {
continue;
}
$name[] = end($category_paths[$id]) . ";";
//added to support category anchors
if (!$isCatAnchorSingle || empty($category_paths_ids) || !count($category_paths[$id])) {
continue;
}
foreach ($category_paths_ids[$id] as $catIsAnchor) {
if (!isset($category_anchors[$catIsAnchor], $category_paths[$catIsAnchor])) {
continue;
}
$name[] = end($category_paths[$catIsAnchor]) . ";";
}
}
$name = array_unique($name);
$name = implode("", $name);
return substr($name, 0, strrpos($name, ";") + 1 - 1);
}
/**
* Return a list of the names of all the categories in the
* paths of the given categories (including the given categories)
* up to, but not including the store root.
*
* @param array $categories
*
* @return array
*/
public function getCategoryNames(array $categories)
{
$storeId = null;
try {
$store = $this->_storeModelStoreManagerInterface->getStore();
$storeId = $store->getId();
} catch (NoSuchEntityException $e) {
$this->_searchHelperData->log(LoggerConstants::ZEND_LOG_ERR, $e->getMessage());
}
$category_paths = $this->getCategoryPaths();
$category_paths_ids = $this->getCategoryPathIds();
$category_anchors = $this->getCategoryAnchors();
$isCatAnchorSingle = $this->_configHelper->getTreatCategoryAnchorAsSingle($storeId);
$catPaths = [];
foreach ($categories as $category) {
if (!isset($category_paths[$category])) {
continue;
}
if (count($category_paths[$category]) > 0) {
$catPaths[$category][] = implode(";", $category_paths[$category]);
//added to support category anchors
if (!$isCatAnchorSingle) {
continue;
}
foreach ($category_paths_ids[$category] as $catIsAnchor) {
if (!isset($category_anchors[$catIsAnchor], $category_paths[$catIsAnchor])) {
continue;
}
if (count($category_paths[$catIsAnchor]) > 0) {
$catPaths[$catIsAnchor][] = implode(";", $category_paths[$catIsAnchor]);
} else {
$catPaths[$catIsAnchor] = $category_paths[$catIsAnchor];
}
}
} else {
$catPaths[$category] = $category_paths[$category];
}
}
$result = array_merge(["KLEVU_PRODUCT"], ...$catPaths);
return array_values(
array_unique($result)
);
}
/**
* Return a list of the names of all the categories in the
* paths of the given categories (including the given categories)
* up to, but not including the store root.
*
* @param array $categories
*
* @return string
*/
public function getCategoryNamesAndPath(array $categories)
{
$storeId = null;
try {
$store = $this->_storeModelStoreManagerInterface->getStore();
$storeId = $store->getId();
} catch (NoSuchEntityException $e) {
$this->_searchHelperData->log(LoggerConstants::ZEND_LOG_ERR, $e->getMessage());
}
$categoryPaths = $this->getCategoryPathsAndIds();
$categoryIds = $this->getCategoryPathIds();
$categoryAnchors = $this->getCategoryAnchors();
$isCatAnchorSingle = $this->_configHelper->getTreatCategoryAnchorAsSingle($storeId);
$catPath = [];
foreach ($categories as $category) {
if (!isset($categoryPaths[$category])) {
continue;
}
if (count($categoryPaths[$category]) > 0) {
$catName = implode(";", $categoryPaths[$category]);
$catId = implode("/", $categoryIds[$category]);
$catPath[$category][] = $catName . '::' . $catId;
// check if need to treat anchors as standalone
if (!$isCatAnchorSingle) {
continue;
}
foreach ($categoryIds[$category] as $isCatAnchor) {
if (!isset($categoryAnchors[$isCatAnchor], $categoryPaths[$isCatAnchor])) {
continue;
}
if (count($categoryPaths[$isCatAnchor]) > 0) {
$catName = implode(";", $categoryPaths[$isCatAnchor]);
$catId = implode("/", $categoryIds[$isCatAnchor]);
$catPath[$isCatAnchor][] = $catName . '::' . $catId;
} else {
$catName = $categoryPaths[$isCatAnchor];
$catId = $categoryIds[$isCatAnchor];
$catPath[$isCatAnchor] = (!is_array($catName) && !is_array($catId))
?
$catName . '::' . $catId
:
[];
}
}
} else {
$catName = $categoryPaths[$category];
$catId = $categoryIds[$category];
if (!is_array($catName) && !is_array($catId)) {
$catPath[$category] = $catName . '::' . $catId;
} else {
$catPath[$category] = [];
}
}
}
$result = (count($catPath))
? array_merge(...$catPath)
: [];
return implode(";;", array_unique($result));
}
/**
* Return an array of category paths for all the categories in the
* current store, not including the store root.
*
* @return array A list of category paths where each key is a category
* ID and each value is an array of category names for
* each category in the path, the last element being the
* name of the category referenced by the ID.
*/
public function getCategoryPaths()
{
$categoryPaths = $this->getData('category_paths');
try {
$store = $this->_storeModelStoreManagerInterface->getStore();
$storeId = $store->getId();
$rootId = $store->getRootCategoryId();
} catch (NoSuchEntityException $e) {
$this->_searchHelperData->log(LoggerConstants::ZEND_LOG_ERR, $e->getMessage());
return $categoryPaths;
}
if (($categoryPaths) && ((int)$storeId === (int)$this->getData('catFieldStoreID'))) {
return $categoryPaths;
}
$this->setData('catFieldStoreID', $storeId);
$categoryPaths = [];
$categoryIds = [];
$categoryPathsAndIds = [];
try {
$collection = $this->productCollectionFactory->create();
$collection->setStoreId($storeId);
$collection->addAttributeToSelect('is_exclude_cat');
$collection->addAttributeToSelect('is_anchor');
$collection->addAttributeToSelect('is_active');
$collection->addFieldToFilter('level', ['gt' => 1]);
$collection->addFieldToFilter('path', ['like' => "1/$rootId/%"]);
$collection->addNameToResult();
$this->_searchHelperData->log(
LoggerConstants::ZEND_LOG_INFO,
'CategoryCollection:'
);
$this->_searchHelperData->log(
LoggerConstants::ZEND_LOG_INFO,
$collection->getSelect()->__toString()
);
} catch (LocalizedException $e) {
$this->_searchHelperData->log(LoggerConstants::ZEND_LOG_ERR, $e->getMessage());
return $categoryPaths;
}
$categoryAnchors = [];
$connection = $this->resourceConnection->getConnection();
$tableNameCategoryEntity = $this->resourceConnection->getTableName('catalog_category_entity');
$tableNameCategoryEntityInt = $this->resourceConnection->getTableName('catalog_category_entity_int');
//change row_id to entity_id if it is open source edition
$select = $connection->select()
->from(['ce' => $tableNameCategoryEntity], ['row_id' => 'ce.row_id'])
->joinLeft(
['cpei' => $tableNameCategoryEntityInt],
'ce.row_id = cpei.row_id',
['store_id', 'attribute_id', 'store_value' => 'value']
)
//Change 180 attribute_id value as per your system, you can write subquery to pull dynamic
->where('cpei.attribute_id = ?', 180)
->where('cpei.value = ?', 1)
->where('cpei.store_id = ?', 0);
$listOfCategoriesIsExcludeOnGlobal = $connection->fetchAll($select);
//$listOfCategoriesIsExcludeOnGlobal will have similar below array,
/*(
[row_id] => 30
[store_id] => 0
[attribute_id] => 180
[store_value] => 1
)*/
$this->_searchHelperData->log(
LoggerConstants::ZEND_LOG_INFO,
print_r($listOfCategoriesIsExcludeOnGlobal, true)
);
$isExcludeCategoryIds = [];
foreach ($listOfCategoriesIsExcludeOnGlobal as $isExcludeCategory) {
$isExcludeCategoryIds['row_id'] = $isExcludeCategory['row_id'];
}
foreach ($collection as $category) {
//This will prevent if value is 1 then it won't included in `listCategory`.
if (in_array($category->getId(), $isExcludeCategoryIds)) {
continue;
}
if ($category->getIsExcludeCat() || !(int)$category->getIsActive()) {
continue;
}
if ($category->getIsAnchor()) {
$categoryAnchors[$category->getId()] = $category->getId();
}
$categoryPaths[$category->getId()] = [];
$categoryPathsAndIds[$category->getId()] = [];
$categoryIds[$category->getId()] = [];
$pathIds = $category->getPathIds();
foreach ($pathIds as $id) {
$item = $collection->getItemById($id);
if (!$item) {
continue;
}
$categoryIds[$category->getId()][] = $item->getId();
$categoryPathsAndIds[$category->getId()][] = $item->getName();
$categoryPaths[$category->getId()][] = $item->getName();
}
}
$this->setData('category_anchors', $categoryAnchors);
$this->setData('category_paths_and_ids', $categoryPathsAndIds);
$this->setData('category_path_ids', $categoryIds);
$this->setData('category_paths', $categoryPaths);
$this->_searchHelperData->log(
LoggerConstants::ZEND_LOG_INFO,
print_r($categoryPaths, true)
);
return $categoryPaths;
}
/**
* Ref: KS-7557 Added to triage temporal coupling with getCategoryPaths()
* setting additional data
*
* @return array
*/
public function getCategoryAnchors()
{
if (!$this->hasData('category_anchors')) {
$this->getCategoryPaths();
}
return $this->getData('category_anchors');
}
/**
* Ref: KS-7557 Added to triage temporal coupling with getCategoryPaths()
* setting additional data
*
* @return array
*/
public function getCategoryPathsAndIds()
{
if (!$this->hasData('category_paths_and_ids')) {
$this->getCategoryPaths();
}
return $this->getData('category_paths_and_ids');
}
/**
* Ref: KS-7557 Added to triage temporal coupling with getCategoryPaths()
* setting additional data
*
* @return array
*/
public function getCategoryPathIds()
{
if (!$this->hasData('category_path_ids')) {
$this->getCategoryPaths();
}
return $this->getData('category_path_ids');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment