mirror of
https://github.com/bdnugget/magento2.git
synced 2026-11-07 09:17:35 +00:00
382 lines
13 KiB
PHP
382 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* Copyright © Magento, Inc. All rights reserved.
|
|
* See COPYING.txt for license details.
|
|
*/
|
|
namespace Magento\Bundle\Model\ResourceModel\Selection;
|
|
|
|
use Magento\Framework\DataObject;
|
|
use Magento\Framework\DB\Select;
|
|
use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory;
|
|
use Magento\Framework\App\ObjectManager;
|
|
|
|
/**
|
|
* Bundle Selections Resource Collection
|
|
*
|
|
* @api
|
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
|
* @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
|
|
* @since 100.0.2
|
|
*/
|
|
class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection
|
|
{
|
|
/**
|
|
* Selection table name
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_selectionTable;
|
|
|
|
/**
|
|
* @var DataObject
|
|
*/
|
|
private $itemPrototype = null;
|
|
|
|
/**
|
|
* @var \Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor
|
|
*/
|
|
private $catalogRuleProcessor = null;
|
|
|
|
/**
|
|
* Is website scope prices joined to collection
|
|
*
|
|
* @var bool
|
|
*/
|
|
private $websiteScopePriceJoined = false;
|
|
|
|
/**
|
|
* @var \Magento\CatalogInventory\Model\ResourceModel\Stock\Item
|
|
*/
|
|
private $stockItem;
|
|
|
|
/**
|
|
* Collection constructor.
|
|
* @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
|
|
* @param \Psr\Log\LoggerInterface $logger
|
|
* @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
|
|
* @param \Magento\Framework\Event\ManagerInterface $eventManager
|
|
* @param \Magento\Eav\Model\Config $eavConfig
|
|
* @param \Magento\Framework\App\ResourceConnection $resource
|
|
* @param \Magento\Eav\Model\EntityFactory $eavEntityFactory
|
|
* @param \Magento\Catalog\Model\ResourceModel\Helper $resourceHelper
|
|
* @param \Magento\Framework\Validator\UniversalFactory $universalFactory
|
|
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
|
|
* @param \Magento\Framework\Module\Manager $moduleManager
|
|
* @param \Magento\Catalog\Model\Indexer\Product\Flat\State $catalogProductFlatState
|
|
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
|
|
* @param \Magento\Catalog\Model\Product\OptionFactory $productOptionFactory
|
|
* @param \Magento\Catalog\Model\ResourceModel\Url $catalogUrl
|
|
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
|
|
* @param \Magento\Customer\Model\Session $customerSession
|
|
* @param \Magento\Framework\Stdlib\DateTime $dateTime
|
|
* @param \Magento\Customer\Api\GroupManagementInterface $groupManagement
|
|
* @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection
|
|
* @param ProductLimitationFactory|null $productLimitationFactory
|
|
* @param \Magento\Framework\EntityManager\MetadataPool|null $metadataPool
|
|
* @param \Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer|null $tableMaintainer
|
|
* @param \Magento\CatalogInventory\Model\ResourceModel\Stock\Item|null $stockItem
|
|
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
|
|
*/
|
|
public function __construct(
|
|
\Magento\Framework\Data\Collection\EntityFactory $entityFactory,
|
|
\Psr\Log\LoggerInterface $logger,
|
|
\Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
|
|
\Magento\Framework\Event\ManagerInterface $eventManager,
|
|
\Magento\Eav\Model\Config $eavConfig,
|
|
\Magento\Framework\App\ResourceConnection $resource,
|
|
\Magento\Eav\Model\EntityFactory $eavEntityFactory,
|
|
\Magento\Catalog\Model\ResourceModel\Helper $resourceHelper,
|
|
\Magento\Framework\Validator\UniversalFactory $universalFactory,
|
|
\Magento\Store\Model\StoreManagerInterface $storeManager,
|
|
\Magento\Framework\Module\Manager $moduleManager,
|
|
\Magento\Catalog\Model\Indexer\Product\Flat\State $catalogProductFlatState,
|
|
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
|
|
\Magento\Catalog\Model\Product\OptionFactory $productOptionFactory,
|
|
\Magento\Catalog\Model\ResourceModel\Url $catalogUrl,
|
|
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
|
|
\Magento\Customer\Model\Session $customerSession,
|
|
\Magento\Framework\Stdlib\DateTime $dateTime,
|
|
\Magento\Customer\Api\GroupManagementInterface $groupManagement,
|
|
\Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
|
|
ProductLimitationFactory $productLimitationFactory = null,
|
|
\Magento\Framework\EntityManager\MetadataPool $metadataPool = null,
|
|
\Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer $tableMaintainer = null,
|
|
\Magento\CatalogInventory\Model\ResourceModel\Stock\Item $stockItem = null
|
|
) {
|
|
parent::__construct(
|
|
$entityFactory,
|
|
$logger,
|
|
$fetchStrategy,
|
|
$eventManager,
|
|
$eavConfig,
|
|
$resource,
|
|
$eavEntityFactory,
|
|
$resourceHelper,
|
|
$universalFactory,
|
|
$storeManager,
|
|
$moduleManager,
|
|
$catalogProductFlatState,
|
|
$scopeConfig,
|
|
$productOptionFactory,
|
|
$catalogUrl,
|
|
$localeDate,
|
|
$customerSession,
|
|
$dateTime,
|
|
$groupManagement,
|
|
$connection,
|
|
$productLimitationFactory,
|
|
$metadataPool,
|
|
$tableMaintainer
|
|
);
|
|
$this->stockItem = $stockItem
|
|
?? ObjectManager::getInstance()->get(\Magento\CatalogInventory\Model\ResourceModel\Stock\Item::class);
|
|
}
|
|
|
|
/**
|
|
* Initialize collection
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function _construct()
|
|
{
|
|
parent::_construct();
|
|
$this->setRowIdFieldName('selection_id');
|
|
$this->_selectionTable = $this->getTable('catalog_product_bundle_selection');
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function _resetState(): void
|
|
{
|
|
parent::_resetState();
|
|
$this->itemPrototype = null;
|
|
$this->catalogRuleProcessor = null;
|
|
$this->websiteScopePriceJoined = false;
|
|
}
|
|
|
|
/**
|
|
* Set store id for each collection item when collection was loaded.
|
|
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function _afterLoad()
|
|
{
|
|
return parent::_afterLoad();
|
|
}
|
|
|
|
/**
|
|
* Initialize collection select
|
|
*
|
|
* @return $this|void
|
|
*/
|
|
protected function _initSelect()
|
|
{
|
|
parent::_initSelect();
|
|
$this->getSelect()->join(
|
|
['selection' => $this->_selectionTable],
|
|
'selection.product_id = e.entity_id',
|
|
['*']
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Join website scope prices to collection, override default prices
|
|
*
|
|
* @param int $websiteId
|
|
* @return $this
|
|
*/
|
|
public function joinPrices($websiteId)
|
|
{
|
|
$connection = $this->getConnection();
|
|
$priceType = $connection->getCheckSql(
|
|
'price.selection_price_type IS NOT NULL',
|
|
'price.selection_price_type',
|
|
'selection.selection_price_type'
|
|
);
|
|
$priceValue = $connection->getCheckSql(
|
|
'price.selection_price_value IS NOT NULL',
|
|
'price.selection_price_value',
|
|
'selection.selection_price_value'
|
|
);
|
|
$this->getSelect()->joinLeft(
|
|
['price' => $this->getTable('catalog_product_bundle_selection_price')],
|
|
'selection.selection_id = price.selection_id AND price.website_id = ' . (int)$websiteId .
|
|
' AND selection.parent_product_id = price.parent_product_id',
|
|
[
|
|
'selection_price_type' => $priceType,
|
|
'selection_price_value' => $priceValue,
|
|
'parent_product_id' => 'price.parent_product_id',
|
|
'price_scope' => 'price.website_id'
|
|
]
|
|
);
|
|
$this->websiteScopePriceJoined = true;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Apply option ids filter to collection
|
|
*
|
|
* @param array $optionIds
|
|
* @return $this
|
|
*/
|
|
public function setOptionIdsFilter($optionIds)
|
|
{
|
|
if (!empty($optionIds)) {
|
|
$this->getSelect()->where('selection.option_id IN (?)', $optionIds, \Zend_Db::INT_TYPE);
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Apply selection ids filter to collection
|
|
*
|
|
* @param array $selectionIds
|
|
* @return $this
|
|
*/
|
|
public function setSelectionIdsFilter($selectionIds)
|
|
{
|
|
if (!empty($selectionIds)) {
|
|
$this->getSelect()->where('selection.selection_id IN (?)', $selectionIds, \Zend_Db::INT_TYPE);
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set position order
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function setPositionOrder()
|
|
{
|
|
$this->getSelect()->order('selection.position asc')->order('selection.selection_id asc');
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Add filtering of products that have 0 items left.
|
|
*
|
|
* @return $this
|
|
* @since 100.2.0
|
|
*/
|
|
public function addQuantityFilter()
|
|
{
|
|
$manageStockExpr = $this->stockItem->getManageStockExpr('stock_item');
|
|
$backordersExpr = $this->stockItem->getBackordersExpr('stock_item');
|
|
$minQtyExpr = $this->getConnection()->getCheckSql(
|
|
'selection.selection_can_change_qty',
|
|
$this->stockItem->getMinSaleQtyExpr('stock_item'),
|
|
'selection.selection_qty'
|
|
);
|
|
|
|
$where = $manageStockExpr . ' = 0';
|
|
$where .= ' OR ('
|
|
. 'stock_item.is_in_stock = ' . \Magento\CatalogInventory\Model\Stock::STOCK_IN_STOCK
|
|
. ' AND ('
|
|
. $backordersExpr . ' != ' . \Magento\CatalogInventory\Model\Stock::BACKORDERS_NO
|
|
. ' OR '
|
|
. $minQtyExpr . ' <= stock_item.qty'
|
|
. ')'
|
|
. ')';
|
|
|
|
$this->getSelect()
|
|
->joinInner(
|
|
['stock_item' => $this->stockItem->getMainTable()],
|
|
'selection.product_id = stock_item.product_id',
|
|
[]
|
|
)->where($where);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
* @since 100.2.0
|
|
*/
|
|
public function getNewEmptyItem()
|
|
{
|
|
if (null === $this->itemPrototype) {
|
|
$this->itemPrototype = parent::getNewEmptyItem();
|
|
}
|
|
return clone $this->itemPrototype;
|
|
}
|
|
|
|
/**
|
|
* Add filter by price
|
|
*
|
|
* @param \Magento\Catalog\Model\Product $product
|
|
* @param bool $searchMin
|
|
* @param bool $useRegularPrice
|
|
*
|
|
* @return $this
|
|
* @since 100.2.0
|
|
*/
|
|
public function addPriceFilter($product, $searchMin, $useRegularPrice = false)
|
|
{
|
|
if ($product->getPriceType() == \Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC) {
|
|
if (!$this->getStoreId()) {
|
|
$this->setStoreId($this->_storeManager->getStore()->getId());
|
|
}
|
|
$this->addPriceData();
|
|
if ($useRegularPrice) {
|
|
$minimalPriceExpression = self::INDEX_TABLE_ALIAS . '.price';
|
|
} else {
|
|
$this->getCatalogRuleProcessor()->addPriceData($this, 'selection.product_id');
|
|
$minimalPriceExpression = 'LEAST(minimal_price, IFNULL(catalog_rule_price, minimal_price))';
|
|
}
|
|
$orderByValue = new \Zend_Db_Expr(
|
|
'(' .
|
|
$minimalPriceExpression .
|
|
' * selection.selection_qty' .
|
|
')'
|
|
);
|
|
} else {
|
|
$connection = $this->getConnection();
|
|
$priceType = $connection->getIfNullSql(
|
|
'price.selection_price_type',
|
|
'selection.selection_price_type'
|
|
);
|
|
$priceValue = $connection->getIfNullSql(
|
|
'price.selection_price_value',
|
|
'selection.selection_price_value'
|
|
);
|
|
if (!$this->websiteScopePriceJoined) {
|
|
$websiteId = $this->_storeManager->getStore()->getWebsiteId();
|
|
$this->getSelect()->joinLeft(
|
|
['price' => $this->getTable('catalog_product_bundle_selection_price')],
|
|
'selection.selection_id = price.selection_id AND price.website_id = ' . (int)$websiteId,
|
|
[]
|
|
);
|
|
}
|
|
$price = $connection->getCheckSql(
|
|
$priceType . ' = 1',
|
|
(float) $product->getPrice() . ' * '. $priceValue . ' / 100',
|
|
$priceValue
|
|
);
|
|
$orderByValue = new \Zend_Db_Expr('('. $price. ' * '. 'selection.selection_qty)');
|
|
}
|
|
|
|
$this->getSelect()->reset(Select::ORDER);
|
|
$this->getSelect()->order(new \Zend_Db_Expr($orderByValue . ($searchMin ? Select::SQL_ASC : Select::SQL_DESC)));
|
|
$this->getSelect()->limit(1);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get Catalog Rule Processor.
|
|
*
|
|
* @return \Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor
|
|
*/
|
|
private function getCatalogRuleProcessor()
|
|
{
|
|
if (null === $this->catalogRuleProcessor) {
|
|
$this->catalogRuleProcessor = \Magento\Framework\App\ObjectManager::getInstance()
|
|
->get(\Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor::class);
|
|
}
|
|
|
|
return $this->catalogRuleProcessor;
|
|
}
|
|
}
|