ltsecurityinc安防产品在线商城代码

This commit is contained in:
2026-09-14 17:47:10 +08:00
parent 57d8444c15
commit 6a3c9c5bd8
14539 changed files with 1775310 additions and 0 deletions
+149
View File
@@ -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];
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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)
]
);
}
}