/** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @return void */ protected function setUp() { $this->select = $this->getMockBuilder('\\Magento\\Framework\\DB\\Select')->disableOriginalConstructor()->setMethods(['from', 'joinLeft', 'where', 'joinInner'])->getMock(); $this->connection = $this->getMockBuilder('\\Magento\\Framework\\DB\\Adapter\\AdapterInterface')->disableOriginalConstructor()->setMethods(['select', 'quoteInto'])->getMockForAbstractClass(); $this->connection->expects($this->once())->method('select')->will($this->returnValue($this->select)); $this->resource = $this->getMockBuilder('\\Magento\\Framework\\App\\ResourceConnection')->disableOriginalConstructor()->setMethods(['getConnection', 'getTableName'])->getMock(); $this->resource->expects($this->any())->method('getConnection')->will($this->returnValue($this->connection)); $this->request = $this->getMockBuilder('\\Magento\\Framework\\Search\\RequestInterface')->disableOriginalConstructor()->setMethods(['getIndex', 'getDimensions', 'getQuery'])->getMockForAbstractClass(); $this->config = $this->getMockBuilder('\\Magento\\Framework\\App\\Config\\ScopeConfigInterface')->disableOriginalConstructor()->setMethods(['isSetFlag'])->getMockForAbstractClass(); $this->storeManager = $this->getMockBuilder('Magento\\Store\\Model\\StoreManagerInterface')->getMock(); $this->scopeResolver = $this->getMockBuilder('\\Magento\\Framework\\Indexer\\ScopeResolver\\IndexScopeResolver')->disableOriginalConstructor()->getMock(); $this->conditionManager = $this->getMockBuilder('\\Magento\\Framework\\Search\\Adapter\\Mysql\\ConditionManager')->setMethods(['combineQueries', 'wrapBrackets', 'generateCondition'])->disableOriginalConstructor()->getMock(); $this->conditionManager->expects($this->any())->method('combineQueries')->willReturnCallback(function (array $queries, $expression) { return implode(' ' . $expression . ' ', $queries); }); $this->conditionManager->expects($this->any())->method('wrapBrackets')->willReturnCallback(function ($expression) { return '(' . $expression . ')'; }); $this->conditionManager->expects($this->any())->method('generateCondition')->willReturnCallback(function ($left, $operator, $right) { return $left . $operator . $right; }); $this->tableMapper = $this->getMockBuilder('\\Magento\\CatalogSearch\\Model\\Search\\TableMapper')->disableOriginalConstructor()->getMock(); $this->tableMapper->expects($this->once())->method('addTables')->with($this->select, $this->request)->willReturnArgument(0); $this->dimensionScopeResolver = $this->getMockForAbstractClass('\\Magento\\Framework\\App\\ScopeResolverInterface', [], '', false); $this->scopeInterface = $this->getMockForAbstractClass('\\Magento\\Framework\\App\\ScopeInterface', [], '', false); $this->stockConfiguration = $this->getMockBuilder('\\Magento\\CatalogInventory\\Api\\StockConfigurationInterface')->getMock(); $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->target = $objectManagerHelper->getObject('Magento\\CatalogSearch\\Model\\Search\\IndexBuilder', ['resource' => $this->resource, 'config' => $this->config, 'storeManager' => $this->storeManager, 'conditionManager' => $this->conditionManager, 'scopeResolver' => $this->scopeResolver, 'tableMapper' => $this->tableMapper, 'dimensionScopeResolver' => $this->dimensionScopeResolver]); // Todo: \Magento\Framework\TestFramework\Unit\Helper\ObjectManager to do this automatically (MAGETWO-49793) $reflection = new \ReflectionClass(get_class($this->target)); $reflectionProperty = $reflection->getProperty('stockConfiguration'); $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($this->target, $this->stockConfiguration); }
/** * Build index query * * @param RequestInterface $request * @return Select */ public function build(RequestInterface $request) { $searchIndexTable = $this->scopeResolver->resolve($request->getIndex(), $request->getDimensions()); $select = $this->resource->getConnection()->select()->from(['search_index' => $searchIndexTable], ['entity_id' => 'entity_id'])->joinLeft(['cea' => $this->resource->getTableName('catalog_eav_attribute')], 'search_index.attribute_id = cea.attribute_id', []); $select = $this->tableMapper->addTables($select, $request); $select = $this->processDimensions($request, $select); $isShowOutOfStock = $this->config->isSetFlag('cataloginventory/options/show_out_of_stock', ScopeInterface::SCOPE_STORE); if ($isShowOutOfStock === false) { $select->joinLeft(['stock_index' => $this->resource->getTableName('cataloginventory_stock_status')], 'search_index.entity_id = stock_index.product_id' . $this->resource->getConnection()->quoteInto(' AND stock_index.website_id = ?', $this->storeManager->getWebsite()->getId()), []); $select->where('stock_index.stock_status = ?', 1); } return $select; }
/** * @param FilterInterface $filter * @param bool $isNegation * @param string $query * @return string */ private function processQueryWithField(FilterInterface $filter, $isNegation, $query) { /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */ $attribute = $this->config->getAttribute(Product::ENTITY, $filter->getField()); if ($filter->getField() === 'price') { $resultQuery = str_replace($this->connection->quoteIdentifier('price'), $this->connection->quoteIdentifier('price_index.min_price'), $query); } elseif ($filter->getField() === 'category_ids') { return 'category_ids_index.category_id = ' . $filter->getValue(); } elseif ($attribute->isStatic()) { $alias = $this->tableMapper->getMappingAlias($filter); $resultQuery = str_replace($this->connection->quoteIdentifier($attribute->getAttributeCode()), $this->connection->quoteIdentifier($alias . '.' . $attribute->getAttributeCode()), $query); } elseif ($filter->getType() === FilterInterface::TYPE_TERM && in_array($attribute->getFrontendInput(), ['select', 'multiselect'], true)) { $alias = $this->tableMapper->getMappingAlias($filter); if (is_array($filter->getValue())) { $value = sprintf('%s IN (%s)', $isNegation ? 'NOT' : '', implode(',', $filter->getValue())); } else { $value = ($isNegation ? '!' : '') . '= ' . $filter->getValue(); } $resultQuery = sprintf('%1$s.value %2$s', $alias, $value); } else { $table = $attribute->getBackendTable(); $select = $this->connection->select(); $ifNullCondition = $this->connection->getIfNullSql('current_store.value', 'main_table.value'); $currentStoreId = $this->scopeResolver->getScope()->getId(); $select->from(['main_table' => $table], 'entity_id')->joinLeft(['current_store' => $table], 'current_store.attribute_id = main_table.attribute_id AND current_store.store_id = ' . $currentStoreId, null)->columns([$filter->getField() => $ifNullCondition])->where('main_table.attribute_id = ?', $attribute->getAttributeId())->where('main_table.store_id = ?', Store::DEFAULT_STORE_ID)->having($query); $resultQuery = 'search_index.entity_id IN ( select entity_id from ' . $this->conditionManager->wrapBrackets($select) . ' as filter )'; } return $resultQuery; }
/** * @param FilterInterface $filter * @param bool $isNegation * @return string */ private function processTermSelect(FilterInterface $filter, $isNegation) { $alias = $this->tableMapper->getMappingAlias($filter); if (is_array($filter->getValue())) { $value = sprintf('%s IN (%s)', $isNegation ? 'NOT' : '', implode(',', $filter->getValue())); } else { $value = ($isNegation ? '!' : '') . '= ' . $filter->getValue(); } $resultQuery = sprintf('%1$s.value %2$s', $alias, $value); return $resultQuery; }
/** * @dataProvider testTermFilterDataProvider */ public function testProcessTermFilter($frontendInput, $fieldValue, $isNegation, $expected) { $this->config->expects($this->exactly(1))->method('getAttribute')->with(\Magento\Catalog\Model\Product::ENTITY, 'termField')->will($this->returnValue($this->attribute)); $this->attribute->expects($this->once())->method('isStatic')->will($this->returnValue(false)); $this->filter->expects($this->once())->method('getType')->willReturn(FilterInterface::TYPE_TERM); $this->attribute->expects($this->once())->method('getFrontendInput')->willReturn($frontendInput); $this->tableMapper->expects($this->once())->method('getMappingAlias')->willReturn('termAttrAlias'); $this->filter->expects($this->exactly(3))->method('getField')->willReturn('termField'); $this->filter->expects($this->exactly(2))->method('getValue')->willReturn($fieldValue); $actualResult = $this->target->process($this->filter, $isNegation, 'This filter is not depends on used query'); $this->assertSame($expected, $this->removeWhitespaces($actualResult)); }
public function testAddBoolFilterWithBoolFiltersInside() { $this->createAttributeMock('must1', null, null, 101, 'select', 0); $this->createAttributeMock('should1', null, null, 102, 'select', 1); $this->createAttributeMock('mustNot1', null, null, 103, 'select', 2); $query = $this->createFilterQuery($this->createBoolFilter([$this->createBoolFilter([$this->createTermFilter('must1')], [], [])], [$this->createBoolFilter([$this->createTermFilter('should1')], [], [])], [$this->createBoolFilter([$this->createTermFilter('mustNot1')], [], [])])); $this->request->expects($this->once())->method('getQuery')->willReturn($query); $this->select->expects($this->at(0))->method('joinLeft')->with(['must1_filter' => 'prefix_catalog_product_index_eav'], 'search_index.entity_id = must1_filter.entity_id' . ' AND must1_filter.attribute_id = 101' . ' AND must1_filter.store_id = 2514', [])->willReturnSelf(); $this->select->expects($this->at(1))->method('joinLeft')->with(['should1_filter' => 'prefix_catalog_product_index_eav'], 'search_index.entity_id = should1_filter.entity_id' . ' AND should1_filter.attribute_id = 102' . ' AND should1_filter.store_id = 2514', [])->willReturnSelf(); $this->select->expects($this->at(2))->method('joinLeft')->with(['mustNot1_filter' => 'prefix_catalog_product_index_eav'], 'search_index.entity_id = mustNot1_filter.entity_id' . ' AND mustNot1_filter.attribute_id = 103' . ' AND mustNot1_filter.store_id = 2514', [])->willReturnSelf(); $select = $this->target->addTables($this->select, $this->request); $this->assertEquals($this->select, $select, 'Returned results isn\'t equal to passed select'); }