ltsecurityinc安防产品在线商城代码
This commit is contained in:
+149
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel;
|
||||
|
||||
class Inventory extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $stockIds;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $sourceCodes;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $stockStatus;
|
||||
|
||||
/**
|
||||
* @var \Magento\Framework\Module\Manager
|
||||
*/
|
||||
private $moduleManager;
|
||||
|
||||
/**
|
||||
* @var \Magento\CatalogInventory\Api\StockRegistryInterface
|
||||
*/
|
||||
private $stockRegistry;
|
||||
|
||||
public function __construct(
|
||||
\Magento\Framework\Module\Manager $moduleManager,
|
||||
\Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
|
||||
\Magento\Framework\Model\ResourceModel\Db\Context $context,
|
||||
$connectionName = null
|
||||
) {
|
||||
parent::__construct($context, $connectionName);
|
||||
$this->moduleManager = $moduleManager;
|
||||
$this->stockRegistry = $stockRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function _construct()
|
||||
{
|
||||
$this->stockIds = [];
|
||||
$this->sourceCodes = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $productSku
|
||||
* @param $websiteCode
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @throws \Magento\Framework\Exception\NoSuchEntityException
|
||||
*/
|
||||
public function getStockStatus($productSku, $websiteCode)
|
||||
{
|
||||
if ($this->moduleManager->isEnabled('Magento_Inventory')) {
|
||||
$stockStatus = $this->getMsiStock($productSku, $websiteCode);
|
||||
} else {
|
||||
$stockStatus = $this->getStockItem($productSku, $websiteCode)->getIsInStock();
|
||||
}
|
||||
|
||||
return $stockStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $productSku
|
||||
* @param $websiteCode
|
||||
*
|
||||
* @return \Magento\CatalogInventory\Api\Data\StockItemInterface
|
||||
*
|
||||
* @throws \Magento\Framework\Exception\NoSuchEntityException
|
||||
*/
|
||||
private function getStockItem($productSku, $websiteCode)
|
||||
{
|
||||
return $this->stockRegistry->getStockItemBySku($productSku, $websiteCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $productSku
|
||||
* @param string $websiteCode
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @throws \Magento\Framework\Exception\NoSuchEntityException
|
||||
*/
|
||||
public function getMsiStock($productSku, $websiteCode)
|
||||
{
|
||||
if (!isset($this->stockStatus[$websiteCode][$productSku])) {
|
||||
$select = $this->getConnection()->select()
|
||||
->from($this->getTable('inventory_stock_' . $this->getStockId($websiteCode)), ['is_salable'])
|
||||
->where('sku = ?', $productSku)
|
||||
->group('sku');
|
||||
$this->stockStatus[$websiteCode][$productSku] = (int) $this->getConnection()->fetchOne($select);
|
||||
}
|
||||
|
||||
return $this->stockStatus[$websiteCode][$productSku];
|
||||
}
|
||||
|
||||
/**
|
||||
* For MSI.
|
||||
*
|
||||
* @param string $websiteCode
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStockId(string $websiteCode): int
|
||||
{
|
||||
if (!isset($this->stockIds[$websiteCode])) {
|
||||
$select = $this->getConnection()->select()
|
||||
->from($this->getTable('inventory_stock_sales_channel'), ['stock_id'])
|
||||
->where('type = \'website\' AND code = ?', $websiteCode);
|
||||
|
||||
$this->stockIds[$websiteCode] = (int)$this->getConnection()->fetchOne($select);
|
||||
}
|
||||
|
||||
return $this->stockIds[$websiteCode];
|
||||
}
|
||||
|
||||
/**
|
||||
* For MSI.
|
||||
*
|
||||
* @param string $websiteCode
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSourceCodes($websiteCode)
|
||||
{
|
||||
if (!isset($this->sourceCodes[$websiteCode])) {
|
||||
$select = $this->getConnection()->select()
|
||||
->from($this->getTable('inventory_source_stock_link'), ['source_code'])
|
||||
->where('stock_id = ?', $this->getStockId($websiteCode));
|
||||
|
||||
$this->sourceCodes[$websiteCode] = $this->getConnection()->fetchCol($select);
|
||||
}
|
||||
|
||||
return $this->sourceCodes[$websiteCode];
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Inventory;
|
||||
|
||||
use Amasty\Sorting\Model\ResourceModel\Inventory;
|
||||
use Magento\Catalog\Api\Data\ProductInterface;
|
||||
use Magento\Framework\App\ResourceConnection;
|
||||
use Magento\Framework\EntityManager\MetadataPool;
|
||||
|
||||
class GetConfigurableQty
|
||||
{
|
||||
/**
|
||||
* @var ResourceConnection
|
||||
*/
|
||||
private $resourceConnection;
|
||||
|
||||
/**
|
||||
* @var MetadataPool
|
||||
*/
|
||||
private $metadataPool;
|
||||
|
||||
/**
|
||||
* @var Inventory
|
||||
*/
|
||||
private $inventory;
|
||||
|
||||
public function __construct(
|
||||
ResourceConnection $resourceConnection,
|
||||
MetadataPool $metadataPool,
|
||||
Inventory $inventory
|
||||
) {
|
||||
$this->resourceConnection = $resourceConnection;
|
||||
$this->metadataPool = $metadataPool;
|
||||
$this->inventory = $inventory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $productSku
|
||||
* @param string $websiteCode
|
||||
* @return null|float
|
||||
*/
|
||||
public function execute(string $productSku, string $websiteCode): ?float
|
||||
{
|
||||
$connection = $this->resourceConnection->getConnection();
|
||||
|
||||
$metadata = $this->metadataPool->getMetadata(ProductInterface::class);
|
||||
$linkField = $metadata->getLinkField();
|
||||
|
||||
$select = $connection->select()->from(
|
||||
['source_item' => $this->resourceConnection->getTableName('inventory_source_item')],
|
||||
['SUM(quantity)']
|
||||
)->joinInner(
|
||||
['product_entity' => $this->resourceConnection->getTableName('catalog_product_entity')],
|
||||
'product_entity.sku = source_item.sku',
|
||||
[]
|
||||
)->joinInner(
|
||||
['parent_link' => $this->resourceConnection->getTableName('catalog_product_super_link')],
|
||||
'parent_link.product_id = product_entity.entity_id',
|
||||
[]
|
||||
)->joinInner(
|
||||
['parent_product_entity' => $this->resourceConnection->getTableName('catalog_product_entity')],
|
||||
'parent_product_entity.' . $linkField . ' = parent_link.parent_id',
|
||||
[]
|
||||
)->where(
|
||||
'source_code IN (?)',
|
||||
$this->inventory->getSourceCodes($websiteCode)
|
||||
)->where(
|
||||
'parent_product_entity.sku = ?',
|
||||
$productSku
|
||||
)->group(
|
||||
'parent_product_entity.sku'
|
||||
);
|
||||
$qty = $connection->fetchOne($select);
|
||||
|
||||
return $qty ? (float) $qty : null;
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Inventory;
|
||||
|
||||
use Magento\Framework\App\ResourceConnection;
|
||||
|
||||
class GetReservationQty
|
||||
{
|
||||
/**
|
||||
* @var ResourceConnection
|
||||
*/
|
||||
private $resourceConnection;
|
||||
|
||||
public function __construct(ResourceConnection $resourceConnection)
|
||||
{
|
||||
$this->resourceConnection = $resourceConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sku
|
||||
* @param int $stockId
|
||||
* @return null|float
|
||||
*/
|
||||
public function execute(string $sku, int $stockId): ?float
|
||||
{
|
||||
$connection = $this->resourceConnection->getConnection();
|
||||
$select = $connection->select()
|
||||
->from($this->resourceConnection->getTableName('inventory_reservation'), ['quantity' => 'SUM(quantity)'])
|
||||
->where('sku = ?', $sku)
|
||||
->where('stock_id = ?', $stockId)
|
||||
->limit(1);
|
||||
|
||||
$reservationQty = $connection->fetchOne($select);
|
||||
|
||||
return $reservationQty ? (float) $reservationQty : 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Inventory;
|
||||
|
||||
use Amasty\Sorting\Model\ResourceModel\Inventory;
|
||||
use Magento\Framework\App\ResourceConnection;
|
||||
|
||||
class GetSimpleQty
|
||||
{
|
||||
/**
|
||||
* @var ResourceConnection
|
||||
*/
|
||||
private $resourceConnection;
|
||||
|
||||
/**
|
||||
* @var Inventory
|
||||
*/
|
||||
private $inventory;
|
||||
|
||||
public function __construct(ResourceConnection $resourceConnection, Inventory $inventory)
|
||||
{
|
||||
$this->resourceConnection = $resourceConnection;
|
||||
$this->inventory = $inventory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $productSku
|
||||
* @param string $websiteCode
|
||||
* @return null|float
|
||||
*/
|
||||
public function execute(string $productSku, string $websiteCode): ?float
|
||||
{
|
||||
$connection = $this->resourceConnection->getConnection();
|
||||
$select = $connection->select()
|
||||
->from($this->resourceConnection->getTableName('inventory_source_item'), ['SUM(quantity)'])
|
||||
->where('source_code IN (?)', $this->inventory->getSourceCodes($websiteCode))
|
||||
->where('sku = ?', $productSku)
|
||||
->group('sku');
|
||||
$qty = $connection->fetchOne($select);
|
||||
|
||||
return $qty ? (float) $qty : null;
|
||||
}
|
||||
}
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
use Amasty\Sorting\Api\IndexedMethodInterface;
|
||||
use Magento\Framework\DB\Query\BatchIteratorInterface;
|
||||
use Magento\Framework\DB\Query\Generator as BatchQueryGenerator;
|
||||
use Magento\Framework\DB\Select;
|
||||
use Magento\Framework\Exception\LocalizedException;
|
||||
use Magento\Framework\Exception\CouldNotDeleteException;
|
||||
|
||||
abstract class AbstractIndexMethod extends AbstractMethod implements IndexedMethodInterface
|
||||
{
|
||||
protected function _construct()
|
||||
{
|
||||
// product_id can be not unique
|
||||
$this->_init($this->getIndexTableName(), 'product_id');
|
||||
}
|
||||
|
||||
abstract public function doReindex();
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
* @throws CouldNotDeleteException
|
||||
*/
|
||||
public function beforeReindex()
|
||||
{
|
||||
try {
|
||||
if ($this->getMethodCode() != 'rating_summary') {
|
||||
$this->getConnection()->truncateTable($this->getMainTable());
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
throw new CouldNotDeleteException(__('Error while clear index amasty sorting method: '), $e);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function reindex()
|
||||
{
|
||||
if ($this->getConnection()->getTransactionLevel() == 0) {
|
||||
$this->beforeReindex();
|
||||
|
||||
try {
|
||||
if ($this->indexConnection) {
|
||||
$this->doReindex();
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->critical(
|
||||
$e,
|
||||
['method_code' => $this->getMethodCode()]
|
||||
);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$this->afterReindex();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function afterReindex()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMainTable()
|
||||
{
|
||||
return $this->getTable($this->getIndexTableName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIndexTableName()
|
||||
{
|
||||
return 'amasty_sorting_' . $this->getMethodCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSortingColumnName()
|
||||
{
|
||||
return $this->getMethodCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAlias()
|
||||
{
|
||||
return $this->getMethodCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function apply($collection, $direction)
|
||||
{
|
||||
try {
|
||||
$collection->joinField(
|
||||
$this->getAlias(), // alias
|
||||
$this->getIndexTableName(), // table
|
||||
$this->getSortingColumnName(), // field
|
||||
'product_id = entity_id', // bind
|
||||
['store_id' => $this->storeManager->getStore()->getId()], // conditions
|
||||
'left' // join type
|
||||
);
|
||||
} catch (LocalizedException $e) {
|
||||
// A joined field with this alias is already declared.
|
||||
$this->logger->warning(
|
||||
'Failed on join table for amasty sorting method: ' . $e->getMessage(),
|
||||
['method_code' => $this->getMethodCode()]
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->critical($e, ['method_code' => $this->getMethodCode()]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getBatchSelectIterator(string $rangeField, Select $select): BatchIteratorInterface
|
||||
{
|
||||
return $this->getBatchQueryGenerator()->generate(
|
||||
$rangeField,
|
||||
$select,
|
||||
$this->getBatchSize(),
|
||||
BatchIteratorInterface::NON_UNIQUE_FIELD_ITERATOR
|
||||
);
|
||||
}
|
||||
|
||||
private function getBatchSize(): int
|
||||
{
|
||||
return (int) ($this->getAdditionalData('batchSize') ?? 1000);
|
||||
}
|
||||
|
||||
protected function getBatchQueryGenerator(): BatchQueryGenerator
|
||||
{
|
||||
return $this->getAdditionalData('batchQueryGenerator');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
use Amasty\Sorting\Api\MethodInterface;
|
||||
use Amasty\Sorting\Model\ConfigProvider;
|
||||
use Amasty\Sorting\Model\Elasticsearch\IsElasticSort;
|
||||
use Magento\Catalog\Model\ResourceModel\Product\Collection;
|
||||
use Magento\Framework\DB\Adapter\AdapterInterface;
|
||||
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
|
||||
|
||||
abstract class AbstractMethod extends AbstractDb implements MethodInterface
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public const ENABLED = true;
|
||||
|
||||
/**
|
||||
* @var \Magento\Framework\App\Config\ScopeConfigInterface
|
||||
*/
|
||||
protected $scopeConfig;
|
||||
|
||||
/**
|
||||
* @var \Magento\Store\Model\StoreManagerInterface
|
||||
*/
|
||||
protected $storeManager;
|
||||
|
||||
/**
|
||||
* @var \Magento\Framework\App\RequestInterface
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $methodCode;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $methodName;
|
||||
|
||||
/**
|
||||
* @var \Amasty\Sorting\Helper\Data
|
||||
*/
|
||||
protected $helper;
|
||||
|
||||
/**
|
||||
* @var \Psr\Log\LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var \Magento\Framework\Stdlib\DateTime\DateTime
|
||||
*/
|
||||
protected $date;
|
||||
|
||||
/**
|
||||
* @var AdapterInterface|null
|
||||
*/
|
||||
protected $indexConnection = null;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* @var \Magento\Framework\Escaper
|
||||
*/
|
||||
private $escaper;
|
||||
|
||||
/**
|
||||
* @var ConfigProvider
|
||||
*/
|
||||
protected $configProvider;
|
||||
|
||||
public function __construct(
|
||||
Context $context,
|
||||
\Magento\Framework\Escaper $escaper,
|
||||
ConfigProvider $configProvider,
|
||||
?IsElasticSort $isElasticSort, // @deprecated
|
||||
$connectionName = null,
|
||||
$methodCode = '',
|
||||
$methodName = '',
|
||||
AbstractDb $indexResource = null,
|
||||
$data = []
|
||||
) {
|
||||
$this->scopeConfig = $context->getScopeConfig();
|
||||
$this->storeManager = $context->getStoreManager();
|
||||
$this->helper = $context->getHelper();
|
||||
$this->logger = $context->getLogger();
|
||||
$this->date = $context->getDate();
|
||||
$this->methodCode = $methodCode;
|
||||
$this->methodName = $methodName;
|
||||
$this->data = $data;
|
||||
$this->escaper = $escaper;
|
||||
$this->configProvider = $configProvider;
|
||||
|
||||
if ($indexResource) {
|
||||
$this->indexConnection = $indexResource->getConnection();
|
||||
}
|
||||
|
||||
parent::__construct($context, $connectionName);
|
||||
}
|
||||
|
||||
//@codingStandardsIgnoreStart
|
||||
protected function _construct()
|
||||
{
|
||||
// dummy
|
||||
}
|
||||
//@codingStandardsIgnoreEnd
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
abstract public function apply($collection, $direction);
|
||||
|
||||
//phpcs:ignore Magento2.CodeAnalysis.EmptyBlock.DetectedFunction
|
||||
public function applyCustomAttribute(Collection $collection, string $direction): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $collection
|
||||
* @return bool
|
||||
*/
|
||||
protected function isMethodAlreadyApplied($collection)
|
||||
{
|
||||
return (bool) $collection->getFlag($this->getFlagName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $collection
|
||||
*/
|
||||
protected function markApplied($collection)
|
||||
{
|
||||
$collection->setFlag($this->getFlagName(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getFlagName()
|
||||
{
|
||||
return 'sorted_by_' . $this->getMethodCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $storeId
|
||||
* @param array|null $entityIds
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function getIndexedValues(int $storeId, ?array $entityIds = []);
|
||||
|
||||
/**
|
||||
* Is sorting method enabled by config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isActive()
|
||||
{
|
||||
return !$this->helper->isMethodDisabled($this->getMethodCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMethodCode()
|
||||
{
|
||||
if (empty($this->methodCode)) {
|
||||
$this->logger->warning('Undefined Amasty sorting method code, add method code to di.xml');
|
||||
}
|
||||
return $this->methodCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMethodName()
|
||||
{
|
||||
if (empty($this->methodCode)) {
|
||||
$this->logger->warning('Undefined Amasty sorting method code, add method code to di.xml');
|
||||
}
|
||||
return $this->methodName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMethodLabel($store = null)
|
||||
{
|
||||
$label = $this->helper->getScopeValue($this->getMethodCode() . '/label', $store);
|
||||
if (!$label) {
|
||||
$label = __($this->getMethodName());
|
||||
}
|
||||
|
||||
return $this->escaper->escapeHtml($label);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getAdditionalData($key)
|
||||
{
|
||||
$result = null;
|
||||
if (isset($this->data[$key])) {
|
||||
$result = $this->data[$key];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
class Commented extends Toprated
|
||||
{
|
||||
/**
|
||||
* Returns Sorting method Table Column name
|
||||
* which is using for order collection
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSortingColumnName()
|
||||
{
|
||||
return 'reviews_count';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSortingFieldName()
|
||||
{
|
||||
return $this->helper->isYotpoEnabled() ? 'total_reviews' : 'reviews_count';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
use Magento\Framework\App\Config\ScopeConfigInterface;
|
||||
use Magento\Framework\Model\ResourceModel\Db\ObjectRelationProcessor;
|
||||
use Magento\Framework\Model\ResourceModel\Db\TransactionManagerInterface;
|
||||
use Magento\Framework\ObjectManager\ContextInterface;
|
||||
use Magento\Store\Model\StoreManagerInterface;
|
||||
|
||||
class Context extends \Magento\Framework\Model\ResourceModel\Db\Context implements ContextInterface
|
||||
{
|
||||
/**
|
||||
* @var ScopeConfigInterface
|
||||
*/
|
||||
private $scopeConfig;
|
||||
|
||||
/**
|
||||
* @var StoreManagerInterface
|
||||
*/
|
||||
private $storeManager;
|
||||
|
||||
/**
|
||||
* @var \Amasty\Sorting\Helper\Data
|
||||
*/
|
||||
private $helper;
|
||||
|
||||
/**
|
||||
* @var \Psr\Log\LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var \Magento\Framework\Stdlib\DateTime\DateTime
|
||||
*/
|
||||
private $date;
|
||||
|
||||
/**
|
||||
* @var \Amasty\Sorting\Model\IsSearchPage
|
||||
*/
|
||||
private $isSearchPage;
|
||||
|
||||
public function __construct(
|
||||
\Magento\Framework\App\ResourceConnection $resource,
|
||||
TransactionManagerInterface $transactionManager,
|
||||
ObjectRelationProcessor $objectRelationProcessor,
|
||||
ScopeConfigInterface $scopeConfig,
|
||||
StoreManagerInterface $storeManager,
|
||||
\Amasty\Sorting\Helper\Data $helper,
|
||||
\Psr\Log\LoggerInterface $logger,
|
||||
\Magento\Framework\Stdlib\DateTime\DateTime $date,
|
||||
\Amasty\Sorting\Model\IsSearchPage $isSearchPage
|
||||
) {
|
||||
parent::__construct($resource, $transactionManager, $objectRelationProcessor);
|
||||
$this->scopeConfig = $scopeConfig;
|
||||
$this->storeManager = $storeManager;
|
||||
$this->helper = $helper;
|
||||
$this->logger = $logger;
|
||||
$this->date = $date;
|
||||
$this->isSearchPage = $isSearchPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ScopeConfigInterface
|
||||
*/
|
||||
public function getScopeConfig()
|
||||
{
|
||||
return $this->scopeConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return StoreManagerInterface
|
||||
*/
|
||||
public function getStoreManager()
|
||||
{
|
||||
return $this->storeManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Amasty\Sorting\Helper\Data
|
||||
*/
|
||||
public function getHelper()
|
||||
{
|
||||
return $this->helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Psr\Log\LoggerInterface
|
||||
*/
|
||||
public function getLogger()
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Magento\Framework\Stdlib\DateTime\DateTime
|
||||
*/
|
||||
public function getDate()
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Amasty\Sorting\Model\IsSearchPage
|
||||
*/
|
||||
public function getIsSearchPage(): \Amasty\Sorting\Model\IsSearchPage
|
||||
{
|
||||
return $this->isSearchPage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
use Amasty\Sorting\Model\ConfigProvider;
|
||||
use Amasty\Sorting\Model\Elasticsearch\IsElasticSort;
|
||||
use Amasty\Sorting\Model\IsSearchPage;
|
||||
use Amasty\Sorting\Model\Source\Image as ImageSource;
|
||||
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
|
||||
use Magento\Framework\DB\Select;
|
||||
use Magento\Framework\Escaper;
|
||||
use Magento\Sitemap\Model\ResourceModel\Catalog\Product as ProductResource;
|
||||
|
||||
/**
|
||||
* Class Image
|
||||
* Method Using like additional sorting and not visible in the list of methods
|
||||
*/
|
||||
class Image extends AbstractMethod
|
||||
{
|
||||
/**
|
||||
* @var IsSearchPage
|
||||
*/
|
||||
private $isSearchPage;
|
||||
|
||||
public function __construct(
|
||||
Context $context,
|
||||
Escaper $escaper,
|
||||
ConfigProvider $configProvider,
|
||||
IsElasticSort $isElasticSort,
|
||||
$connectionName = null,
|
||||
$methodCode = '',
|
||||
$methodName = ''
|
||||
) {
|
||||
parent::__construct(
|
||||
$context,
|
||||
$escaper,
|
||||
$configProvider,
|
||||
$isElasticSort,
|
||||
$connectionName,
|
||||
$methodCode,
|
||||
$methodName
|
||||
);
|
||||
$this->isSearchPage = $context->getIsSearchPage();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSortingColumnName()
|
||||
{
|
||||
return 'small_image';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function apply($collection, $direction = '')
|
||||
{
|
||||
if (!$this->isMethodActive($collection) || $this->isMethodAlreadyApplied($collection)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$attribute = $this->getSortingColumnName();
|
||||
|
||||
$collection->addAttributeToSelect($attribute, 'left');
|
||||
$collection->getSelect()->order($this->getSortExpression($attribute));
|
||||
|
||||
$orders = $collection->getSelect()->getPart(Select::ORDER);
|
||||
// move from the last to the the first position
|
||||
array_unshift($orders, array_pop($orders));
|
||||
$collection->getSelect()->setPart(Select::ORDER, $orders);
|
||||
|
||||
$this->markApplied($collection);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function isMethodActive(ProductCollection $collection): bool
|
||||
{
|
||||
$show = $this->helper->getNonImageLast();
|
||||
|
||||
if (!$show || ($show == ImageSource::SHOW_LAST_FOR_CATALOG && $this->isSearchPage->execute())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If image value is no_selection then drop value to down of the list
|
||||
* return IF(IFNULL(e.small_image, 'no_selection')='no_selection', 1, 0)
|
||||
*
|
||||
* @return \Zend_Db_Expr
|
||||
*/
|
||||
private function getSortExpression($imageColumn)
|
||||
{
|
||||
$connection = $this->getConnection();
|
||||
$noSelection = $connection->quote(ProductResource::NOT_SELECTED_IMAGE);
|
||||
/** IFNULL(e.small_image, 'no_selection') */
|
||||
$ifNull = $connection->getIfNullSql($imageColumn, $noSelection);
|
||||
/** IFNULL(e.small_image, 'no_selection')='no_selection' */
|
||||
$ifNull .= '=' . $noSelection;
|
||||
|
||||
/** IF(IFNULL(e.small_image, 'no_selection')='no_selection', 1, 0) */
|
||||
return $connection->getCheckSql($ifNull, 1, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getIndexedValues(int $storeId, ?array $entityIds = [])
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
use Amasty\Sorting\Model\ConfigProvider;
|
||||
use Amasty\Sorting\Model\Elasticsearch\IsElasticSort;
|
||||
use Amasty\Sorting\Model\IsSearchPage;
|
||||
use Amasty\Sorting\Model\Source\Stock as StockSource;
|
||||
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
|
||||
use Magento\Framework\DB\Select;
|
||||
|
||||
/**
|
||||
* Class Instock
|
||||
* Method Using like additional sorting and not visible in the list of methods
|
||||
*/
|
||||
class Instock extends AbstractMethod
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \Magento\Framework\Module\Manager
|
||||
*/
|
||||
private $moduleManager;
|
||||
|
||||
/**
|
||||
* @var \Magento\CatalogInventory\Helper\Stock
|
||||
*/
|
||||
private $stockHelper;
|
||||
|
||||
/**
|
||||
* Used for MSI
|
||||
*
|
||||
* @var null|int
|
||||
*/
|
||||
private $stockId = null;
|
||||
|
||||
/**
|
||||
* @var IsSearchPage
|
||||
*/
|
||||
private $isSearchPage;
|
||||
|
||||
public function __construct(
|
||||
\Magento\Framework\Module\Manager $moduleManager,
|
||||
\Magento\CatalogInventory\Helper\Stock $stockHelper,
|
||||
Context $context,
|
||||
\Magento\Framework\Escaper $escaper,
|
||||
ConfigProvider $configProvider,
|
||||
IsElasticSort $isElasticSort,
|
||||
$connectionName = null,
|
||||
$methodCode = '',
|
||||
$methodName = ''
|
||||
) {
|
||||
parent::__construct(
|
||||
$context,
|
||||
$escaper,
|
||||
$configProvider,
|
||||
$isElasticSort,
|
||||
$connectionName,
|
||||
$methodCode,
|
||||
$methodName
|
||||
);
|
||||
$this->moduleManager = $moduleManager;
|
||||
$this->stockHelper = $stockHelper;
|
||||
$this->isSearchPage = $context->getIsSearchPage();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function apply($collection, $direction = '')
|
||||
{
|
||||
if (!$this->isMethodActive($collection) || $this->isMethodAlreadyApplied($collection)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$fromTables = $collection->getSelect()->getPart('from');
|
||||
if (!isset($fromTables['stock_status_index'])) {
|
||||
$this->stockHelper->addIsInStockFilterToCollection($collection);
|
||||
$fromTables = $collection->getSelect()->getPart('from');
|
||||
}
|
||||
|
||||
$catalogInventoryTable = $collection->getResource()->getTable('cataloginventory_stock_status');
|
||||
if ($this->isMsiEnabled() && $fromTables['stock_status_index']['tableName'] != $catalogInventoryTable) {
|
||||
$qtyColumn = 'quantity';
|
||||
$salableColumn = 'is_salable';
|
||||
} else {
|
||||
$qtyColumn = 'qty';
|
||||
$salableColumn = 'stock_status';
|
||||
}
|
||||
$qtyAlias = 'stock_status_index.' . $qtyColumn;
|
||||
|
||||
if ($this->isMsiEnabled()) {
|
||||
if (!isset($fromTables['reservation'])) {
|
||||
$reservedTable = $collection->getConnection()->select()
|
||||
->from($this->getTable('inventory_reservation'), ['sku', 'quantity' => 'SUM(quantity)'])
|
||||
->where('stock_id = ?', $this->getStockId())
|
||||
->group('sku');
|
||||
$collection->getSelect()->joinLeft(
|
||||
['reservation' => $reservedTable],
|
||||
'reservation.sku = e.sku',
|
||||
['reserved_qty' => 'quantity']
|
||||
);
|
||||
}
|
||||
$qtyAlias .= ' + IF(reserved_qty IS NOT NULL, reserved_qty, 0)';
|
||||
}
|
||||
|
||||
/**
|
||||
* join in @see \Magento\CatalogInventory\Model\AddStockStatusToCollection
|
||||
* so we don't need to process join, only add sorting
|
||||
*/
|
||||
if ($this->helper->isOutOfStockByQty()) {
|
||||
$ignoreTypes = [
|
||||
'\'grouped\'',
|
||||
'\'bundle\''
|
||||
];
|
||||
$collection->getSelect()->order(
|
||||
/** in result something like this IF(qty > 0, 0, 1) . bundles and grouped not processing */
|
||||
$this->getConnection()->getCheckSql(
|
||||
sprintf(
|
||||
'%s > %s OR e.type_id in (%s)',
|
||||
$qtyAlias,
|
||||
$this->helper->getQtyOutStock(),
|
||||
implode(',', $ignoreTypes)
|
||||
),
|
||||
'0',
|
||||
'1'
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$collection->getSelect()->order(
|
||||
'stock_status_index.' . $salableColumn . ' ' . $collection::SORT_ORDER_DESC
|
||||
);
|
||||
}
|
||||
|
||||
$orders = $collection->getSelect()->getPart(Select::ORDER);
|
||||
// move from the last to the the first position
|
||||
array_unshift($orders, array_pop($orders));
|
||||
$collection->getSelect()->setPart(Select::ORDER, $orders);
|
||||
|
||||
$this->markApplied($collection);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function isMethodActive(ProductCollection $collection): bool
|
||||
{
|
||||
// is out of stock is not displayed, method don't need to be applied
|
||||
$isShowOutOfStock = $this->scopeConfig->getValue(
|
||||
\Magento\CatalogInventory\Model\Configuration::XML_PATH_SHOW_OUT_OF_STOCK,
|
||||
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
|
||||
);
|
||||
if (!$isShowOutOfStock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$show = $this->helper->getOutOfStockLast();
|
||||
|
||||
if (!$show || ($show == StockSource::SHOW_LAST_FOR_CATALOG && $this->isSearchPage->execute())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getIndexedValues(int $storeId, ?array $entityIds = [])
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* For MSI.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function getStockId()
|
||||
{
|
||||
if ($this->stockId === null) {
|
||||
$select = $this->getConnection()->select()
|
||||
->from($this->getTable('inventory_stock_sales_channel'), ['stock_id'])
|
||||
->where('type = \'website\' AND code = ?', $this->storeManager->getWebsite()->getCode());
|
||||
|
||||
$this->stockId = (int)$this->getConnection()->fetchOne($select);
|
||||
}
|
||||
|
||||
return $this->stockId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function isMsiEnabled()
|
||||
{
|
||||
return $this->moduleManager->isEnabled('Magento_Inventory');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
use Magento\Catalog\Model\ResourceModel\Product\Collection;
|
||||
|
||||
class MostViewed extends AbstractIndexMethod
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIndexTableName()
|
||||
{
|
||||
return 'amasty_sorting_most_viewed';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSortingColumnName()
|
||||
{
|
||||
return 'views_num';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function doReindex()
|
||||
{
|
||||
$select = $this->indexConnection->select();
|
||||
|
||||
$select->group(['source_table.store_id', 'source_table.object_id']);
|
||||
|
||||
$viewsNumExpr = new \Zend_Db_Expr('COUNT(source_table.event_id)');
|
||||
|
||||
$columns = [
|
||||
'product_id' => 'source_table.object_id',
|
||||
'store_id' => 'source_table.store_id',
|
||||
'views_num' => $viewsNumExpr,
|
||||
];
|
||||
|
||||
$select->from(
|
||||
['source_table' => $this->getTable('report_event')],
|
||||
$columns
|
||||
)->where(
|
||||
'source_table.event_type_id = ?',
|
||||
\Magento\Reports\Model\Event::EVENT_PRODUCT_VIEW
|
||||
);
|
||||
|
||||
$this->addFromDate($select);
|
||||
|
||||
$havingPart = $this->indexConnection->prepareSqlCondition($viewsNumExpr, ['gt' => 0]);
|
||||
$select->having($havingPart);
|
||||
|
||||
$select->useStraightJoin();
|
||||
|
||||
foreach ($this->getBatchSelectIterator('object_id', $select) as $select) {
|
||||
$viewedInfo = $this->indexConnection->fetchAll($select);
|
||||
if ($viewedInfo) {
|
||||
$this->getConnection()->insertOnDuplicate($this->getMainTable(), $viewedInfo, [
|
||||
$this->getSortingColumnName()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Magento\Framework\DB\Select $select
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function addFromDate($select)
|
||||
{
|
||||
$period = (int)$this->helper->getScopeValue('most_viewed/viewed_period');
|
||||
if ($period) {
|
||||
$from = $this->date->date(
|
||||
\Magento\Framework\DB\Adapter\Pdo\Mysql::TIMESTAMP_FORMAT,
|
||||
$this->date->timestamp() - $period * 24 * 3600
|
||||
);
|
||||
$select->where('source_table.logged_at >= ?', $from);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function applyCustomAttribute(Collection $collection, string $direction): void
|
||||
{
|
||||
if ($attributeCode = $this->helper->getScopeValue('most_viewed/viewed_attr')) {
|
||||
$collection->setOrder($attributeCode, $direction);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getIndexedValues(int $storeId, ?array $entityIds = [])
|
||||
{
|
||||
$select = $this->getConnection()->select()->from(
|
||||
$this->getMainTable(),
|
||||
['product_id', 'value' => 'views_num']
|
||||
)->where('store_id = ?', $storeId);
|
||||
|
||||
if (!empty($entityIds)) {
|
||||
$select->where('product_id in(?)', $entityIds);
|
||||
}
|
||||
|
||||
return $this->getConnection()->fetchPairs($select);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
class Newest extends AbstractMethod
|
||||
{
|
||||
public function getSortingColumnName()
|
||||
{
|
||||
$attributeCode = $this->helper->getScopeValue('new/new_attr');
|
||||
if ($attributeCode) {
|
||||
return $attributeCode;
|
||||
}
|
||||
|
||||
return 'created_at';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAlias()
|
||||
{
|
||||
return $this->getSortingColumnName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function apply($collection, $direction)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIndexedValues(int $storeId, ?array $entityIds = [])
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
use Magento\Catalog\Model\ResourceModel\Product\Collection;
|
||||
use Magento\Framework\DB\Adapter\Pdo\Mysql;
|
||||
use Magento\Framework\Db\Select;
|
||||
use Magento\GroupedProduct\Model\Product\Type\Grouped;
|
||||
use Magento\Sales\Model\ResourceModel\Order\Item\Collection as OrderItemCollection;
|
||||
|
||||
class OrderBasedSorting extends AbstractIndexMethod
|
||||
{
|
||||
public const PRODUCT_ID = 'product_id';
|
||||
|
||||
public const STORE_ID = 'store_id';
|
||||
|
||||
public function getSortingColumnName(): string
|
||||
{
|
||||
return $this->getAdditionalData('sortingColumn');
|
||||
}
|
||||
|
||||
public function getOrderColumnName(): string
|
||||
{
|
||||
return $this->getAdditionalData('orderColumn');
|
||||
}
|
||||
|
||||
public function doReindex(): void
|
||||
{
|
||||
$needCalculateGrouped = !in_array(
|
||||
\Magento\GroupedProduct\Model\Product\Type\Grouped::TYPE_CODE,
|
||||
$this->getAdditionalData('ignoredProductTypes')
|
||||
);
|
||||
$select = $this->indexConnection->select();
|
||||
$select->group(['source_table.store_id', 'order_item.product_id']);
|
||||
|
||||
$columns = [
|
||||
self::PRODUCT_ID => 'order_item.product_id',
|
||||
self::STORE_ID => 'source_table.store_id',
|
||||
$this->getSortingColumnName() =>
|
||||
new \Zend_Db_Expr(sprintf('SUM(order_item.%s)', $this->getOrderColumnName())),
|
||||
];
|
||||
|
||||
$select->from(
|
||||
['source_table' => $this->getTable('sales_order')]
|
||||
)->joinInner(
|
||||
['order_item' => $this->getTable('sales_order_item')],
|
||||
'order_item.order_id = source_table.entity_id',
|
||||
[]
|
||||
)->joinLeft(
|
||||
['order_item_parent' => $this->getTable('sales_order_item')],
|
||||
'order_item.parent_item_id = order_item_parent.item_id',
|
||||
[]
|
||||
);
|
||||
|
||||
$this->addIgnoreProductTypes($select, $needCalculateGrouped);
|
||||
$this->addIgnoreStatus($select);
|
||||
$this->addFromDate($select);
|
||||
$select->reset(Select::COLUMNS)->columns($columns);
|
||||
$select->useStraightJoin();
|
||||
|
||||
foreach ($this->getBatchSelectIterator('entity_id', $select) as $select) {
|
||||
$resultInfo = $this->indexConnection->fetchAll($select);
|
||||
if ($resultInfo) {
|
||||
$this->insertData($resultInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if ($needCalculateGrouped) {
|
||||
$this->calculateGrouped();
|
||||
}
|
||||
}
|
||||
|
||||
private function insertData(array $data): void
|
||||
{
|
||||
$this->getConnection()->insertOnDuplicate($this->getMainTable(), $data);
|
||||
}
|
||||
|
||||
private function addIgnoreStatus(Select $select): void
|
||||
{
|
||||
$excludedOrderStatuses = $this->getExcludedOrderStatuses();
|
||||
|
||||
if ($excludedOrderStatuses) {
|
||||
$select->where('source_table.status NOT IN(?)', $excludedOrderStatuses);
|
||||
}
|
||||
}
|
||||
|
||||
private function getExcludedOrderStatuses(): array
|
||||
{
|
||||
return $this->getSortingColumnName() === 'revenue'
|
||||
? $this->configProvider->getExcludedOrderStatusesForRevenue()
|
||||
: $this->configProvider->getExcludedOrderStatusesForBestsellers();
|
||||
}
|
||||
|
||||
private function getPeriod(): int
|
||||
{
|
||||
return $this->getSortingColumnName() === 'revenue'
|
||||
? $this->configProvider->getRevenuePeriod()
|
||||
: $this->configProvider->getBestsellersPeriod();
|
||||
}
|
||||
|
||||
private function getSortingAttributeCode(): string
|
||||
{
|
||||
return $this->getSortingColumnName() === 'revenue'
|
||||
? $this->configProvider->getRevenueAttributeCode()
|
||||
: $this->configProvider->getBestsellerAttributeCode();
|
||||
}
|
||||
|
||||
private function addFromDate(Select $select): void
|
||||
{
|
||||
$period = $this->getPeriod();
|
||||
|
||||
if ($period) {
|
||||
$from = $this->date->date(
|
||||
Mysql::TIMESTAMP_FORMAT,
|
||||
$this->date->timestamp() - $period * 24 * 3600
|
||||
);
|
||||
$select->where('source_table.created_at >= ?', $from);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Count grouped products ordered qty
|
||||
* Sum of all simple qty which grouped by parent product and store
|
||||
*/
|
||||
private function calculateGrouped(): void
|
||||
{
|
||||
$collection = $this->getAdditionalData('orderItemCollectionFactory')->create();
|
||||
$collection->addFieldToFilter('product_type', Grouped::TYPE_CODE);
|
||||
$select = $collection->getSelect();
|
||||
$select->joinLeft(
|
||||
['source_table' => $this->getTable('sales_order')],
|
||||
'main_table.order_id = source_table.entity_id',
|
||||
[]
|
||||
);
|
||||
|
||||
$this->addIgnoreStatus($select);
|
||||
$this->addFromDate($select);
|
||||
$result = $this->calculateItemsQty($collection);
|
||||
|
||||
if (empty($result)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$insert = [];
|
||||
|
||||
foreach ($result as $storeId => $itemCounts) {
|
||||
foreach ($itemCounts as $productId => $count) {
|
||||
$insert[] = [
|
||||
self::PRODUCT_ID => $productId,
|
||||
self::STORE_ID => $storeId,
|
||||
$this->getSortingColumnName() => $count,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$columns = [self::PRODUCT_ID, self::STORE_ID, $this->getSortingColumnName()];
|
||||
$this->getConnection()->insertArray($this->getMainTable(), $columns, $insert);
|
||||
}
|
||||
|
||||
private function calculateItemsQty(OrderItemCollection $collection): array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($collection->getItems() as $item) {
|
||||
$config = $item->getProductOptionByCode('super_product_config');
|
||||
$groupedId = $config[self::PRODUCT_ID];
|
||||
$storeId = $item->getStoreId();
|
||||
|
||||
if (!isset($result[$storeId][$groupedId])) {
|
||||
$result[$storeId][$groupedId] = 0;
|
||||
}
|
||||
// Sum of all simple qty which grouped by parent product
|
||||
$result[$storeId][$groupedId] += $item->getQtyOrdered();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function addIgnoreProductTypes(
|
||||
Select $select,
|
||||
bool $needCalculateGrouped = false
|
||||
): void {
|
||||
$select->where('order_item.product_type NOT IN(?)', $this->getAdditionalData('ignoredProductTypes'));
|
||||
|
||||
if ($needCalculateGrouped) {
|
||||
$connection = $this->getConnection();
|
||||
|
||||
$groupedIdsSelect = $connection->select()->from(
|
||||
['main_table' => $this->getTable('catalog_product_entity')],
|
||||
['entity_id']
|
||||
)->where(
|
||||
'main_table.type_id = ?',
|
||||
\Magento\GroupedProduct\Model\Product\Type\Grouped::TYPE_CODE
|
||||
);
|
||||
$groupedIds = $connection->fetchCol($groupedIdsSelect);
|
||||
|
||||
if ($groupedIds) {
|
||||
$select->where(
|
||||
'order_item.product_id NOT IN (?)',
|
||||
$groupedIds
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function applyCustomAttribute(Collection $collection, string $direction): void
|
||||
{
|
||||
if ($attributeCode = $this->getSortingAttributeCode()) {
|
||||
$collection->setOrder($attributeCode, $direction);
|
||||
}
|
||||
}
|
||||
|
||||
public function getIndexedValues(int $storeId, ?array $entityIds = []): array
|
||||
{
|
||||
$select = $this->getConnection()->select()->from(
|
||||
$this->getMainTable(),
|
||||
[self::PRODUCT_ID, 'value' => $this->getSortingColumnName()]
|
||||
)->where(
|
||||
sprintf('%s = ?', self::STORE_ID),
|
||||
$storeId
|
||||
);
|
||||
|
||||
if (!empty($entityIds)) {
|
||||
$select->where(
|
||||
sprintf('%s in(?)', self::PRODUCT_ID),
|
||||
$entityIds
|
||||
);
|
||||
}
|
||||
|
||||
return $this->getConnection()->fetchPairs($select);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
class Price extends AbstractMethod
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function apply($collection, $direction)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getAlias()
|
||||
{
|
||||
return 'price';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getIndexedValues(int $storeId, ?array $entityIds = [])
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
use Magento\Catalog\Model\ResourceModel\Product\Collection;
|
||||
use Magento\Framework\DB\Select;
|
||||
|
||||
class Saving extends AbstractMethod
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $limitColumns = false;
|
||||
|
||||
/**
|
||||
* @param Collection $collection
|
||||
* @param $direction
|
||||
* @param bool $limitColumns
|
||||
* @return $this|AbstractMethod
|
||||
*/
|
||||
public function apply($collection, $direction)
|
||||
{
|
||||
$connection = $this->getConnection();
|
||||
$collection->addPriceData();
|
||||
$table = $this->getPriceAlias($collection);
|
||||
|
||||
/** LEAST(min_price, tier_price) */
|
||||
$least = $connection->getLeastSql(["$table.min_price", "$table.tier_price"]);
|
||||
$price = $table . '.price';
|
||||
/** tier_price IS NOT NULL */
|
||||
$tpNotNull = $connection->prepareSqlCondition("$table.tier_price", ['notnull' => true]);
|
||||
/** IF (tier_price IS NOT NULL, LEAST(min_price, tier_price), min_price) */
|
||||
$minPrice = $connection->getCheckSql($tpNotNull, $least, "$table.min_price");
|
||||
|
||||
if ($this->helper->getScopeValue('saving/saving')) {
|
||||
$percent = "($price - $minPrice) * 100 / $price";
|
||||
$saving = $connection->getCheckSql($price, $percent, 0);
|
||||
} else {
|
||||
$saving = "($price - $minPrice)";
|
||||
}
|
||||
|
||||
if ($this->isLimitColumns()) {
|
||||
$collection->getSelect()->reset(Select::COLUMNS);
|
||||
$collection->getSelect()->columns(['product_id' => 'e.entity_id']);
|
||||
$alias = 'value';
|
||||
} else {
|
||||
$alias = $this->getMethodCode();
|
||||
}
|
||||
|
||||
$collection->getSelect()->columns([$alias => new \Zend_Db_Expr($saving)]);
|
||||
|
||||
if (!$this->isLimitColumns()) {
|
||||
$collection->addExpressionAttributeToSelect($this->getMethodCode(), $this->getMethodCode(), []);
|
||||
|
||||
// remove last item from columns because e.saving from addExpressionAttributeToSelect not exist
|
||||
$columns = $collection->getSelect()->getPart(Select::COLUMNS);
|
||||
array_pop($columns);
|
||||
$collection->getSelect()->setPart(Select::COLUMNS, $columns);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAlias()
|
||||
{
|
||||
return $this->getMethodCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Magento\Catalog\Model\ResourceModel\Product\Collection $collection
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getPriceAlias($collection)
|
||||
{
|
||||
$tableAliases = array_keys($collection->getSelect()->getPart(Select::FROM));
|
||||
if (in_array($collection::INDEX_TABLE_ALIAS, $tableAliases)) {
|
||||
return $collection::INDEX_TABLE_ALIAS;
|
||||
}
|
||||
|
||||
return reset($tableAliases);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getIndexedValues(int $storeId, ?array $entityIds = [])
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isLimitColumns()
|
||||
{
|
||||
return $this->limitColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $limitColumns
|
||||
*/
|
||||
public function setLimitColumns($limitColumns)
|
||||
{
|
||||
$this->limitColumns = $limitColumns;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
use Amasty\Sorting\Model\ConfigProvider;
|
||||
use Amasty\Sorting\Model\Elasticsearch\IsElasticSort;
|
||||
use Magento\Framework\Exception\LocalizedException;
|
||||
use Magento\Sales\Model\ResourceModel\Order\Item\CollectionFactory;
|
||||
|
||||
class Toprated extends AbstractMethod
|
||||
{
|
||||
public const MAIN_TABLE = 'review_entity_summary';
|
||||
|
||||
/**
|
||||
* @var \Magento\Review\Model\ResourceModel\Review
|
||||
*/
|
||||
protected $reviewResource;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $entityTypeId = null;
|
||||
|
||||
public function __construct(
|
||||
Context $context,
|
||||
\Magento\Framework\Escaper $escaper,
|
||||
ConfigProvider $configProvider,
|
||||
IsElasticSort $isElasticSort,
|
||||
\Magento\Review\Model\ResourceModel\Review $reviewResource,
|
||||
$connectionName = null,
|
||||
$methodCode = '',
|
||||
$methodName = ''
|
||||
) {
|
||||
parent::__construct(
|
||||
$context,
|
||||
$escaper,
|
||||
$configProvider,
|
||||
$isElasticSort,
|
||||
$connectionName,
|
||||
$methodCode,
|
||||
$methodName
|
||||
);
|
||||
$this->reviewResource = $reviewResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Sorting method Table Column name
|
||||
* which is using for order collection
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSortingColumnName()
|
||||
{
|
||||
return 'rating_summary_field';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSortingFieldName()
|
||||
{
|
||||
return 'rating_summary';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAlias()
|
||||
{
|
||||
return $this->getSortingColumnName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* This method is also used for @see Commented
|
||||
*/
|
||||
public function apply($collection, $direction)
|
||||
{
|
||||
try {
|
||||
$collection->joinField(
|
||||
$this->getSortingColumnName(), // alias
|
||||
$this->getIndexTableName(), // table
|
||||
$this->getSortingFieldName(), // field
|
||||
$this->getProductColumn() . '=entity_id', // bind
|
||||
$this->getConditions(), // conditions
|
||||
'left' // join type
|
||||
);
|
||||
} catch (LocalizedException $e) {
|
||||
// A joined field with this alias is already declared.
|
||||
$this->logger->warning(
|
||||
'Failed on join table for amasty sorting method: ' . $e->getMessage(),
|
||||
['method_code' => $this->getMethodCode()]
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->critical($e, ['method_code' => $this->getMethodCode()]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Review entity type id for product
|
||||
*
|
||||
* @return bool|int|null
|
||||
*/
|
||||
private function getEntityTypeId()
|
||||
{
|
||||
if ($this->entityTypeId === null) {
|
||||
$this->entityTypeId = $this->reviewResource->getEntityIdByCode(
|
||||
\Magento\Review\Model\Review::ENTITY_PRODUCT_CODE
|
||||
);
|
||||
}
|
||||
|
||||
return $this->entityTypeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIndexTableName()
|
||||
{
|
||||
if ($this->helper->isYotpoEnabled()) {
|
||||
$table = \Amasty\Yotpo\Model\ResourceModel\YotpoReview::MAIN_TABLE;
|
||||
} else {
|
||||
$table = self::MAIN_TABLE;
|
||||
}
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
private function getConditions(?int $storeId = null): array
|
||||
{
|
||||
$conditions = ['store_id' => $this->getStoreId($storeId)];
|
||||
if (!$this->helper->isYotpoEnabled()) {
|
||||
$conditions['entity_type'] = $this->getEntityTypeId();
|
||||
}
|
||||
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getProductColumn()
|
||||
{
|
||||
$column = $this->helper->isYotpoEnabled() ?
|
||||
'product_id' :
|
||||
'entity_pk_value';
|
||||
|
||||
return $column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getIndexedValues(int $storeId, ?array $entityIds = [])
|
||||
{
|
||||
$select = $this->getConnection()->select()->from(
|
||||
$this->getTable($this->getIndexTableName()),
|
||||
['product_id' => $this->getProductColumn(), 'value' => $this->getSortingFieldName()]
|
||||
);
|
||||
foreach ($this->getConditions($storeId) as $field => $value) {
|
||||
$select->where($field . ' = ?', $value);
|
||||
}
|
||||
|
||||
if (!empty($entityIds)) {
|
||||
$select->where($this->getProductColumn() . ' in(?)', $entityIds);
|
||||
}
|
||||
|
||||
return $this->getConnection()->fetchPairs($select);
|
||||
}
|
||||
|
||||
private function getStoreId(?int $preferredStoreId = null): int
|
||||
{
|
||||
return $preferredStoreId ?? (int)$this->storeManager->getStore()->getId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Method;
|
||||
|
||||
/**
|
||||
* Class Wished
|
||||
* Sorting adapter for wished method
|
||||
*/
|
||||
class Wished extends AbstractIndexMethod
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIndexTableName()
|
||||
{
|
||||
return 'amasty_sorting_wished';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSortingColumnName()
|
||||
{
|
||||
return 'wished';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function doReindex()
|
||||
{
|
||||
$select = $this->indexConnection->select();
|
||||
|
||||
$select->group(['source_table.store_id', 'source_table.product_id']);
|
||||
|
||||
$viewsNumExpr = new \Zend_Db_Expr('COUNT(source_table.wishlist_item_id)');
|
||||
|
||||
$columns = [
|
||||
'product_id' => 'source_table.product_id',
|
||||
'store_id' => 'source_table.store_id',
|
||||
'wished' => $viewsNumExpr,
|
||||
];
|
||||
|
||||
$select->from(
|
||||
['source_table' => $this->getTable('wishlist_item')],
|
||||
$columns
|
||||
);
|
||||
|
||||
$this->addFromDate($select);
|
||||
|
||||
$select->useStraightJoin();
|
||||
|
||||
foreach ($this->getBatchSelectIterator('wishlist_item_id', $select) as $select) {
|
||||
$wishedInfo = $this->indexConnection->fetchAll($select);
|
||||
if ($wishedInfo) {
|
||||
$this->getConnection()->insertOnDuplicate($this->getMainTable(), $wishedInfo, [
|
||||
$this->getSortingColumnName()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Magento\Framework\DB\Select $select
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function addFromDate($select)
|
||||
{
|
||||
$period = (int)$this->helper->getScopeValue('wished/wished_period');
|
||||
if ($period) {
|
||||
$from = $this->date->date(
|
||||
\Magento\Framework\DB\Adapter\Pdo\Mysql::TIMESTAMP_FORMAT,
|
||||
$this->date->timestamp() - $period * 24 * 3600
|
||||
);
|
||||
$select->where('source_table.added_at >= ?', $from);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getIndexedValues(int $storeId, ?array $entityIds = [])
|
||||
{
|
||||
$select = $this->getConnection()->select()->from(
|
||||
$this->getMainTable(),
|
||||
['product_id', 'value' => 'wished']
|
||||
)->where('store_id = ?', $storeId);
|
||||
|
||||
if (!empty($entityIds)) {
|
||||
$select->where('product_id in(?)', $entityIds);
|
||||
}
|
||||
|
||||
return $this->getConnection()->fetchPairs($select);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Product;
|
||||
|
||||
use Magento\Catalog\Api\Data\ProductInterface;
|
||||
use Magento\Framework\App\ResourceConnection;
|
||||
|
||||
class LoadSkuMap
|
||||
{
|
||||
private const ENTITY_ID_FIELD = 'entity_id';
|
||||
|
||||
/**
|
||||
* @var ResourceConnection
|
||||
*/
|
||||
private $resourceConnection;
|
||||
|
||||
public function __construct(ResourceConnection $resourceConnection)
|
||||
{
|
||||
$this->resourceConnection = $resourceConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $entityIds
|
||||
* @return array
|
||||
*/
|
||||
public function execute(array $entityIds): array
|
||||
{
|
||||
$select = $this->resourceConnection->getConnection()->select()->from(
|
||||
$this->resourceConnection->getTableName('catalog_product_entity'),
|
||||
[self::ENTITY_ID_FIELD, ProductInterface::SKU]
|
||||
)->where(
|
||||
sprintf('%s IN (?)', self::ENTITY_ID_FIELD),
|
||||
$entityIds
|
||||
);
|
||||
|
||||
return $this->resourceConnection->getConnection()->fetchPairs($select);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel\Product;
|
||||
|
||||
use Magento\Catalog\Api\Data\ProductInterface;
|
||||
use Magento\Framework\App\ResourceConnection;
|
||||
|
||||
class LoadTypeMap
|
||||
{
|
||||
/**
|
||||
* @var ResourceConnection
|
||||
*/
|
||||
private $resourceConnection;
|
||||
|
||||
public function __construct(ResourceConnection $resourceConnection)
|
||||
{
|
||||
$this->resourceConnection = $resourceConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $skus
|
||||
* @return array
|
||||
*/
|
||||
public function execute(array $skus): array
|
||||
{
|
||||
$select = $this->resourceConnection->getConnection()->select()->from(
|
||||
$this->resourceConnection->getTableName('catalog_product_entity'),
|
||||
[ProductInterface::SKU, ProductInterface::TYPE_ID]
|
||||
)->where(
|
||||
sprintf('%s IN (?)', ProductInterface::SKU),
|
||||
$skus
|
||||
);
|
||||
|
||||
return $this->resourceConnection->getConnection()->fetchPairs($select);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @author Amasty Team
|
||||
* @copyright Copyright (c) Amasty (https://www.amasty.com)
|
||||
* @package Improved Sorting for Magento 2
|
||||
*/
|
||||
|
||||
namespace Amasty\Sorting\Model\ResourceModel;
|
||||
|
||||
use Amasty\Sorting\Api\ProductReviewLinkProcessorInterface;
|
||||
use Magento\Framework\App\ResourceConnection;
|
||||
use Magento\Framework\DB\Adapter\AdapterInterface;
|
||||
use Magento\Framework\DB\Adapter\DuplicateException;
|
||||
|
||||
class ProductReviewLinkProcessor implements ProductReviewLinkProcessorInterface
|
||||
{
|
||||
public const TABLE_NAME = 'amasty_sorting_reviews_link';
|
||||
public const PRODUCT_ID = 'product_id';
|
||||
public const REVIEW_ID = 'review_id';
|
||||
|
||||
/**
|
||||
* @var ResourceConnection
|
||||
*/
|
||||
private $resourceConnection;
|
||||
|
||||
public function __construct(
|
||||
ResourceConnection $resourceConnection
|
||||
) {
|
||||
$this->resourceConnection = $resourceConnection;
|
||||
}
|
||||
|
||||
public function create(int $productId, int $reviewId): void
|
||||
{
|
||||
try {
|
||||
$connection = $this->resourceConnection->getConnection();
|
||||
$connection->insert(
|
||||
$this->getTableName(),
|
||||
[
|
||||
self::PRODUCT_ID => $productId,
|
||||
self::REVIEW_ID => $reviewId,
|
||||
]
|
||||
);
|
||||
} catch (DuplicateException $e) {
|
||||
$this->remove($productId, $reviewId);
|
||||
}
|
||||
}
|
||||
|
||||
public function getTableName(): string
|
||||
{
|
||||
return $this->resourceConnection->getTableName(self::TABLE_NAME);
|
||||
}
|
||||
|
||||
public function remove(int $productId, int $reviewId): void
|
||||
{
|
||||
$connection = $this->resourceConnection->getConnection();
|
||||
$connection->delete(
|
||||
$this->getTableName(),
|
||||
[
|
||||
$connection->prepareSqlCondition(self::REVIEW_ID, $reviewId),
|
||||
$connection->prepareSqlCondition(self::PRODUCT_ID, $productId)
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user