src/module-elasticsuite-virtual-category/Model/ResourceModel/Category/Product/Position.php
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer
* versions in the future.
*
* @category Smile
* @package Smile\ElasticsuiteVirtualCategory
* @author Aurelien FOUCRET <aurelien.foucret@smile.fr>
* @copyright 2020 Smile
* @license Open Software License ("OSL") v. 3.0
*/
namespace Smile\ElasticsuiteVirtualCategory\Model\ResourceModel\Category\Product;
use Magento\Catalog\Api\Data\CategoryInterface;
/**
* Product position resource model.
*
* @category Smile
* @package Smile\ElasticsuiteVirtualCategory
* @author Aurelien FOUCRET <aurelien.foucret@smile.fr>
*/
class Position extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
/**
* @var string
*/
const TABLE_NAME = 'smile_virtualcategory_catalog_category_product_position';
/**
* Get product positions for a given categoryId and Store Id.
*
* @param int $categoryId The Category Id.
* @param int $storeId The Store Id.
*
* @return array
*/
public function getProductPositions($categoryId, $storeId)
{
$select = $this->getBaseSelect()
->where('category_id = ?', (int) $categoryId)
->where('store_id = ?', (int) $storeId)
->where('position IS NOT NULL')
->columns(['product_id', 'position']);
return $this->getConnection()->fetchPairs($select);
}
/**
* Get product blacklist for a given categoryId and Store Id.
*
* @param int $categoryId The Category Id.
* @param int $storeId The Store Id.
*
* @return array
*/
public function getProductBlacklist($categoryId, $storeId)
{
$select = $this->getBaseSelect()
->columns(['product_id'])
->where('category_id = ?', (int) $categoryId)
->where('store_id = ?', (int) $storeId)
->where('is_blacklisted = ?', (int) true);
return $this->getConnection()->fetchCol($select);
}
/**
* Load product positions for the given category.
*
* @param CategoryInterface|int $category Category.
*
* @return array
*/
public function getProductPositionsByCategory($category)
{
$storeId = \Magento\Store\Model\Store::DEFAULT_STORE_ID;
if (is_object($category)) {
if ($category->getUseStorePositions()) {
$storeId = $category->getStoreId();
}
$category = $category->getId();
}
return $this->getProductPositions($category, $storeId);
}
/**
* Load blacklisted products for the given query.
*
* @param CategoryInterface|int $category Category.
*
* @return array
*/
public function getProductBlacklistByCategory($category)
{
$storeId = \Magento\Store\Model\Store::DEFAULT_STORE_ID;
if (is_object($category)) {
if ($category->getUseStorePositions()) {
$storeId = $category->getStoreId();
}
$category = $category->getId();
}
return $this->getProductBlacklist($category, $storeId);
}
/**
* Save the product positions.
*
* @param CategoryInterface $category Saved category.
*
* @return \Smile\ElasticsuiteVirtualCategory\Model\ResourceModel\Category\Product\Position
*/
public function saveProductPositions(CategoryInterface $category)
{
// Can be 0 if not on a store view.
$storeId = (int) $category->getStoreId();
// If on a store view, and no store override of positions, clean up existing store records.
if ($storeId && !$category->getUseStorePositions()) {
$category->setSortedProducts([]);
$category->setBlacklistedProducts([]);
}
$newProductPositions = $category->getSortedProducts();
$blacklistedProducts = $category->getBlacklistedProducts() ?? [];
$deleteConditions = [
$this->getConnection()->quoteInto('category_id = ?', (int) $category->getId()),
$this->getConnection()->quoteInto('store_id = ?', $storeId),
];
if (!empty($newProductPositions) || !empty($blacklistedProducts)) {
$insertData = [];
$updatedProductIds = array_merge(array_keys($newProductPositions), $blacklistedProducts);
foreach ($updatedProductIds as $productId) {
$insertData[] = [
'category_id' => $category->getId(),
'product_id' => $productId,
'store_id' => $storeId,
'position' => $newProductPositions[$productId] ?? null,
'is_blacklisted' => in_array($productId, $blacklistedProducts),
];
}
$deleteConditions[] = $this->getConnection()->quoteInto('product_id NOT IN (?)', $updatedProductIds);
$this->getConnection()->insertOnDuplicate($this->getMainTable(), $insertData, array_keys(current($insertData)));
}
$this->getConnection()->delete($this->getMainTable(), implode(' AND ', $deleteConditions));
return $this;
}
/**
* @SuppressWarnings(PHPMD.CamelCaseMethodName)
* {@inheritDoc}
*/
protected function _construct()
{
$this->_setMainTable(self::TABLE_NAME);
}
/**
* Init a base select with the main table.
*
* @return \Zend_Db_Select
*/
private function getBaseSelect()
{
$select = $this->getConnection()->select();
$select->from(['main_table' => $this->getMainTable()], []);
return $select;
}
}