diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php
index 08e75ceebecc6..337134c9453c0 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext.php
@@ -6,11 +6,16 @@
namespace Magento\CatalogSearch\Model\Indexer;
use Magento\CatalogSearch\Model\Indexer\Fulltext\Action\FullFactory;
+use Magento\CatalogSearch\Model\Indexer\Scope\State;
use Magento\CatalogSearch\Model\ResourceModel\Fulltext as FulltextResource;
-use \Magento\Framework\Search\Request\Config as SearchRequestConfig;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Search\Request\Config as SearchRequestConfig;
use Magento\Framework\Search\Request\DimensionFactory;
use Magento\Store\Model\StoreManagerInterface;
+/**
+ * Provide functionality for Fulltext Search indexing
+ */
class Fulltext implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
{
/**
@@ -18,34 +23,51 @@ class Fulltext implements \Magento\Framework\Indexer\ActionInterface, \Magento\F
*/
const INDEXER_ID = 'catalogsearch_fulltext';
- /** @var array index structure */
+ /**
+ * @var array index structure
+ */
protected $data;
/**
* @var IndexerHandlerFactory
*/
private $indexerHandlerFactory;
+
/**
* @var StoreManagerInterface
*/
private $storeManager;
+
/**
- * @var DimensionFactory
+ * @var \Magento\Framework\Search\Request\DimensionFactory
*/
private $dimensionFactory;
+
/**
- * @var Full
+ * @var \Magento\CatalogSearch\Model\Indexer\Fulltext\Action\Full
*/
private $fullAction;
+
/**
* @var FulltextResource
*/
private $fulltextResource;
+
/**
- * @var SearchRequestConfig
+ * @var \Magento\Framework\Search\Request\Config
*/
private $searchRequestConfig;
+ /**
+ * @var IndexSwitcherInterface
+ */
+ private $indexSwitcher;
+
+ /**
+ * @var \Magento\CatalogSearch\Model\Indexer\Scope\State
+ */
+ private $indexScopeState;
+
/**
* @param FullFactory $fullActionFactory
* @param IndexerHandlerFactory $indexerHandlerFactory
@@ -54,6 +76,8 @@ class Fulltext implements \Magento\Framework\Indexer\ActionInterface, \Magento\F
* @param FulltextResource $fulltextResource
* @param SearchRequestConfig $searchRequestConfig
* @param array $data
+ * @param IndexSwitcherInterface $indexSwitcher
+ * @param Scope\State $indexScopeState
*/
public function __construct(
FullFactory $fullActionFactory,
@@ -62,7 +86,9 @@ public function __construct(
DimensionFactory $dimensionFactory,
FulltextResource $fulltextResource,
SearchRequestConfig $searchRequestConfig,
- array $data
+ array $data,
+ IndexSwitcherInterface $indexSwitcher = null,
+ State $indexScopeState = null
) {
$this->fullAction = $fullActionFactory->create(['data' => $data]);
$this->indexerHandlerFactory = $indexerHandlerFactory;
@@ -71,6 +97,14 @@ public function __construct(
$this->fulltextResource = $fulltextResource;
$this->searchRequestConfig = $searchRequestConfig;
$this->data = $data;
+ if (null === $indexSwitcher) {
+ $indexSwitcher = ObjectManager::getInstance()->get(IndexSwitcherInterface::class);
+ }
+ if (null === $indexScopeState) {
+ $indexScopeState = ObjectManager::getInstance()->get(State::class);
+ }
+ $this->indexSwitcher = $indexSwitcher;
+ $this->indexScopeState = $indexScopeState;
}
/**
@@ -106,10 +140,14 @@ public function executeFull()
'data' => $this->data
]);
foreach ($storeIds as $storeId) {
- $dimension = $this->dimensionFactory->create(['name' => 'scope', 'value' => $storeId]);
- $saveHandler->cleanIndex([$dimension]);
- $saveHandler->saveIndex([$dimension], $this->fullAction->rebuildStoreIndex($storeId));
+ $dimensions = [$this->dimensionFactory->create(['name' => 'scope', 'value' => $storeId])];
+ $this->indexScopeState->useTemporaryIndex();
+
+ $saveHandler->cleanIndex($dimensions);
+ $saveHandler->saveIndex($dimensions, $this->fullAction->rebuildStoreIndex($storeId));
+ $this->indexSwitcher->switchIndex($dimensions);
+ $this->indexScopeState->useRegularIndex();
}
$this->fulltextResource->resetSearchResults();
$this->searchRequestConfig->reset();
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructure.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructure.php
index 9a2bb76c04ce7..d2d76bc71ccbf 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructure.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructure.php
@@ -12,6 +12,7 @@
use Magento\Framework\Search\Request\Dimension;
use Magento\Framework\Indexer\IndexStructureInterface;
use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
+use Magento\Framework\Search\Request\IndexScopeResolverInterface;
class IndexStructure implements IndexStructureInterface
{
@@ -19,6 +20,7 @@ class IndexStructure implements IndexStructureInterface
* @var Resource
*/
private $resource;
+
/**
* @var IndexScopeResolver
*/
@@ -26,11 +28,11 @@ class IndexStructure implements IndexStructureInterface
/**
* @param ResourceConnection $resource
- * @param IndexScopeResolver $indexScopeResolver
+ * @param IndexScopeResolverInterface $indexScopeResolver
*/
public function __construct(
ResourceConnection $resource,
- IndexScopeResolver $indexScopeResolver
+ IndexScopeResolverInterface $indexScopeResolver
) {
$this->resource = $resource;
$this->indexScopeResolver = $indexScopeResolver;
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexSwitcherInterface.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexSwitcherInterface.php
new file mode 100644
index 0000000000000..ba5fb461dde35
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexSwitcherInterface.php
@@ -0,0 +1,22 @@
+objectManager = $objectManager;
+ $this->scopeConfig = $scopeConfig;
+ $this->configPath = $configPath;
+ $this->handlers = $handlers;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * As index switcher is an optional part of the search SPI, it may be not defined by a search engine.
+ * It is especially reasonable for search engines with pre-defined indexes declaration (like old SOLR and Sphinx)
+ * which cannot create temporary indexes on the fly.
+ * That's the reason why this method do nothing for the case
+ * when switcher is not defined for a specific search engine.
+ */
+ public function switchIndex(array $dimensions)
+ {
+ $currentHandler = $this->scopeConfig->getValue($this->configPath, ScopeInterface::SCOPE_STORE);
+ if (!isset($this->handlers[$currentHandler])) {
+ return;
+ }
+ $this->create($currentHandler)->switchIndex($dimensions);
+ }
+
+ /**
+ * Create indexer handler
+ *
+ * @param string $handler
+ * @return IndexSwitcherInterface
+ */
+ private function create($handler)
+ {
+ $indexSwitcher = $this->objectManager->create($this->handlers[$handler]);
+
+ if (!$indexSwitcher instanceof IndexSwitcherInterface) {
+ throw new \InvalidArgumentException(
+ $handler . ' index switcher doesn\'t implement ' . IndexSwitcherInterface::class
+ );
+ }
+
+ return $indexSwitcher;
+ }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php
index 8d99cd4492bf5..2aa9a418bd725 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php
@@ -7,13 +7,11 @@
use Magento\Eav\Model\Config;
use Magento\Framework\App\ResourceConnection;
-use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\Indexer\SaveHandler\IndexerInterface;
use Magento\Framework\Indexer\IndexStructureInterface;
use Magento\Framework\Search\Request\Dimension;
use Magento\Framework\Search\Request\IndexScopeResolverInterface;
use Magento\Framework\Indexer\SaveHandler\Batch;
-use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
class IndexerHandler implements IndexerInterface
{
@@ -62,7 +60,7 @@ class IndexerHandler implements IndexerInterface
* @param ResourceConnection $resource
* @param Config $eavConfig
* @param Batch $batch
- * @param \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver $indexScopeResolver
+ * @param IndexScopeResolverInterface $indexScopeResolver
* @param array $data
* @param int $batchSize
*/
@@ -71,7 +69,7 @@ public function __construct(
ResourceConnection $resource,
Config $eavConfig,
Batch $batch,
- IndexScopeResolver $indexScopeResolver,
+ IndexScopeResolverInterface $indexScopeResolver,
array $data,
$batchSize = 100
) {
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Scope/IndexSwitcher.php b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/IndexSwitcher.php
new file mode 100644
index 0000000000000..87a7b7110d3aa
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/IndexSwitcher.php
@@ -0,0 +1,76 @@
+resource = $resource;
+ $this->resolver = $indexScopeResolver;
+ $this->state = $state;
+ }
+
+ /**
+ * {@inheritdoc}
+ * @throws IndexTableNotExistException
+ */
+ public function switchIndex(array $dimensions)
+ {
+ if (State::USE_TEMPORARY_INDEX === $this->state->getState()) {
+ $index = \Magento\CatalogSearch\Model\Indexer\Fulltext::INDEXER_ID;
+
+ $temporalIndexTable = $this->resolver->resolve($index, $dimensions);
+ if (!$this->resource->getConnection()->isTableExists($temporalIndexTable)) {
+ throw new IndexTableNotExistException(
+ __(
+ "Temporary table for index $index doesn't exist,"
+ . " which is inconsistent with state of scope resolver"
+ )
+ );
+ }
+
+ $this->state->useRegularIndex();
+ $tableName = $this->resolver->resolve($index, $dimensions);
+ if ($this->resource->getConnection()->isTableExists($tableName)) {
+ $this->resource->getConnection()->dropTable($tableName);
+ }
+
+ $this->resource->getConnection()->renameTable($temporalIndexTable, $tableName);
+ $this->state->useTemporaryIndex();
+ }
+ }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Scope/IndexTableNotExistException.php b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/IndexTableNotExistException.php
new file mode 100644
index 0000000000000..6974f8c278ab5
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/IndexTableNotExistException.php
@@ -0,0 +1,18 @@
+objectManager = $objectManager;
+ $this->scopeState = $scopeState;
+ $this->states = $states;
+ }
+
+ /**
+ * Creates class instance with specified parameters
+ *
+ * @param string $state
+ * @return \Magento\Framework\Search\Request\IndexScopeResolverInterface
+ * @throws UnknownStateException
+ */
+ private function create($state)
+ {
+ if (!array_key_exists($state, $this->states)) {
+ throw new UnknownStateException(__("Requested resolver for unknown indexer state: $state"));
+ }
+ return $this->objectManager->create($this->states[$state]);
+ }
+
+ /**
+ * @param string $index
+ * @param Dimension[] $dimensions
+ * @return string
+ */
+ public function resolve($index, array $dimensions)
+ {
+ return $this->create($this->scopeState->getState())->resolve($index, $dimensions);
+ }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Scope/State.php b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/State.php
new file mode 100644
index 0000000000000..2bba29ae8d842
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/State.php
@@ -0,0 +1,65 @@
+state = self::USE_TEMPORARY_INDEX;
+ }
+
+ /**
+ * Set the state to use regular Index
+ * @return void
+ */
+ public function useRegularIndex()
+ {
+ $this->state = self::USE_REGULAR_INDEX;
+ }
+
+ /**
+ * @return string
+ */
+ public function getState()
+ {
+ return $this->state;
+ }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Scope/TemporaryResolver.php b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/TemporaryResolver.php
new file mode 100644
index 0000000000000..51037eb637cf3
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/TemporaryResolver.php
@@ -0,0 +1,43 @@
+indexScopeResolver = $indexScopeResolver;
+ }
+
+ /**
+ * @param string $index
+ * @param Dimension[] $dimensions
+ * @return string
+ */
+ public function resolve($index, array $dimensions)
+ {
+ $tableName = $this->indexScopeResolver->resolve($index, $dimensions);
+ $tableName .= \Magento\Framework\Indexer\Table\StrategyInterface::TMP_SUFFIX;
+
+ return $tableName;
+ }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Scope/UnknownStateException.php b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/UnknownStateException.php
new file mode 100644
index 0000000000000..04803ef27480e
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/Scope/UnknownStateException.php
@@ -0,0 +1,18 @@
+fullAction = $this->getClassMock(\Magento\CatalogSearch\Model\Indexer\Fulltext\Action\Full::class);
@@ -80,27 +88,29 @@ protected function setUp()
[]
);
- $this->dimension = $this->getClassMock(\Magento\Framework\Search\Request\Dimension::class);
- $dimensionFactory = $this->getMock(
- \Magento\Framework\Search\Request\DimensionFactory::class,
- ['create'],
- [],
- '',
- false
- );
- $dimensionFactory->expects($this->any())->method('create')->willReturn($this->dimension);
+ $this->dimensionFactory = $this->getMock(DimensionFactory::class, ['create'], [], '', false);
$this->fulltextResource = $this->getClassMock(\Magento\CatalogSearch\Model\ResourceModel\Fulltext::class);
$this->searchRequestConfig = $this->getClassMock(\Magento\Framework\Search\Request\Config::class);
- $this->model = new \Magento\CatalogSearch\Model\Indexer\Fulltext(
- $fullActionFactory,
- $indexerHandlerFactory,
- $this->storeManager,
- $dimensionFactory,
- $this->fulltextResource,
- $this->searchRequestConfig,
- []
+ $this->indexSwitcher = $this->getMockBuilder(\Magento\CatalogSearch\Model\Indexer\Scope\IndexSwitcher::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['switchIndex'])
+ ->getMock();
+
+ $objectManagerHelper = new ObjectManagerHelper($this);
+ $this->model = $objectManagerHelper->getObject(
+ \Magento\CatalogSearch\Model\Indexer\Fulltext::class,
+ [
+ 'fullActionFactory' => $fullActionFactory,
+ 'indexerHandlerFactory' => $indexerHandlerFactory,
+ 'storeManager' => $this->storeManager,
+ 'dimensionFactory' => $this->dimensionFactory,
+ 'fulltextResource' => $this->fulltextResource,
+ 'searchRequestConfig' => $this->searchRequestConfig,
+ 'data' => [],
+ 'indexSwitcher' => $this->indexSwitcher,
+ ]
);
}
@@ -131,13 +141,38 @@ public function testExecute()
public function testExecuteFull()
{
$stores = [0 => 'Store 1', 1 => 'Store 2'];
- $indexData = new \ArrayObject([]);
+ $indexData = new \ArrayObject([new \ArrayObject([]), new \ArrayObject([])]);
$this->storeManager->expects($this->once())->method('getStores')->willReturn($stores);
- $this->saveHandler->expects($this->exactly(count($stores)))->method('cleanIndex');
- $this->saveHandler->expects($this->exactly(2))->method('saveIndex');
+
+ $dimensionScope1 = $this->getMock(Dimension::class, [], ['scope', '1']);
+ $dimensionScope2 = $this->getMock(Dimension::class, [], ['scope', '2']);
+
+ $this->dimensionFactory->expects($this->any())->method('create')->willReturnOnConsecutiveCalls(
+ $dimensionScope1,
+ $dimensionScope2
+ );
+ $this->indexSwitcher->expects($this->exactly(2))->method('switchIndex')
+ ->withConsecutive(
+ [$this->equalTo([$dimensionScope1])],
+ [$this->equalTo([$dimensionScope2])]
+ );
+
+ $this->saveHandler->expects($this->exactly(count($stores)))->method('cleanIndex')
+ ->withConsecutive(
+ [$this->equalTo([$dimensionScope1])],
+ [$this->equalTo([$dimensionScope2])]
+ );
+
+ $this->saveHandler->expects($this->exactly(2))->method('saveIndex')
+ ->withConsecutive(
+ [$this->equalTo([$dimensionScope1]), $this->equalTo($indexData)],
+ [$this->equalTo([$dimensionScope2]), $this->equalTo($indexData)]
+ );
$this->fullAction->expects($this->exactly(2))
->method('rebuildStoreIndex')
- ->willReturn(new \ArrayObject([$indexData, $indexData]));
+ ->withConsecutive([0], [1])
+ ->willReturn($indexData);
+
$this->fulltextResource->expects($this->once())->method('resetSearchResults');
$this->searchRequestConfig->expects($this->once())->method('reset');
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Scope/IndexSwitcherTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Scope/IndexSwitcherTest.php
new file mode 100644
index 0000000000000..31bec5906ae5a
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Scope/IndexSwitcherTest.php
@@ -0,0 +1,212 @@
+resource = $this->getMockBuilder(ResourceConnection::class)
+ ->setMethods(['getConnection'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->connection = $this->getMockBuilder(\Magento\Framework\DB\Adapter\AdapterInterface::class)
+ ->setMethods(['isTableExists', 'dropTable', 'renameTable'])
+ ->getMockForAbstractClass();
+ $this->resource->expects($this->any())
+ ->method('getConnection')
+ ->willReturn($this->connection);
+ $this->indexScopeResolver = $this->getMockBuilder(
+ \Magento\Framework\Search\Request\IndexScopeResolverInterface::class
+ )
+ ->setMethods(['resolve'])
+ ->getMockForAbstractClass();
+ $this->scopeState = $this->getMockBuilder(State::class)
+ ->setMethods(['getState', 'useRegularIndex', 'useTemporaryIndex'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectManagerHelper = new ObjectManagerHelper($this);
+ $this->indexSwitcher = $objectManagerHelper->getObject(
+ \Magento\CatalogSearch\Model\Indexer\Scope\IndexSwitcher::class,
+ [
+ 'resource' => $this->resource,
+ 'indexScopeResolver' => $this->indexScopeResolver,
+ 'state' => $this->scopeState,
+ ]
+ );
+ }
+
+ public function testSwitchRegularIndex()
+ {
+ $dimensions = [$this->getMockBuilder(Dimension::class)->setConstructorArgs(['scope', '1'])];
+
+ $this->scopeState->expects($this->once())
+ ->method('getState')
+ ->willReturn(State::USE_REGULAR_INDEX);
+
+ $this->indexScopeResolver->expects($this->never())->method('resolve');
+ $this->connection->expects($this->never())->method('renameTable');
+
+ $this->indexSwitcher->switchIndex($dimensions);
+ }
+
+ public function testSwitchIndexWithUnknownState()
+ {
+ $dimensions = [$this->getMockBuilder(Dimension::class)->setConstructorArgs(['scope', '1'])];
+
+ $this->scopeState->expects($this->once())
+ ->method('getState')
+ ->willReturn('unknown_state');
+
+ $this->indexScopeResolver->expects($this->never())->method('resolve');
+ $this->connection->expects($this->never())->method('renameTable');
+
+ $this->indexSwitcher->switchIndex($dimensions);
+ }
+
+ public function testSwitchTemporaryIndexWhenRegularIndexExist()
+ {
+ $dimensions = [$this->getMockBuilder(Dimension::class)->setConstructorArgs(['scope', '1'])];
+
+ $this->scopeState->expects($this->once())
+ ->method('getState')
+ ->willReturn(State::USE_TEMPORARY_INDEX);
+
+ $this->scopeState->expects($this->at(1))->method('useRegularIndex');
+ $this->scopeState->expects($this->at(2))->method('useTemporaryIndex');
+
+ $this->indexScopeResolver->expects($this->exactly(2))->method('resolve')
+ ->withConsecutive(
+ [$this->equalTo(FulltextIndexer::INDEXER_ID), $this->equalTo($dimensions)],
+ [$this->equalTo(FulltextIndexer::INDEXER_ID), $this->equalTo($dimensions)]
+ )
+ ->willReturnOnConsecutiveCalls(
+ 'catalogsearch_fulltext_scope1_tmp1',
+ 'catalogsearch_fulltext_scope1'
+ );
+
+ $this->connection->expects($this->exactly(2))->method('isTableExists')
+ ->withConsecutive(
+ [$this->equalTo('catalogsearch_fulltext_scope1_tmp1'), $this->equalTo(null)],
+ [$this->equalTo('catalogsearch_fulltext_scope1'), $this->equalTo(null)]
+ )
+ ->willReturnOnConsecutiveCalls(
+ true,
+ true
+ );
+
+ $this->connection->expects($this->once())->method('dropTable')->with('catalogsearch_fulltext_scope1', null);
+ $this->connection->expects($this->once())
+ ->method('renameTable')
+ ->with('catalogsearch_fulltext_scope1_tmp1', 'catalogsearch_fulltext_scope1');
+
+ $this->indexSwitcher->switchIndex($dimensions);
+ }
+
+ public function testSwitchTemporaryIndexWhenRegularIndexNotExist()
+ {
+ $dimensions = [$this->getMockBuilder(Dimension::class)->setConstructorArgs(['scope', '1'])];
+
+ $this->scopeState->expects($this->once())
+ ->method('getState')
+ ->willReturn(State::USE_TEMPORARY_INDEX);
+
+ $this->scopeState->expects($this->at(1))->method('useRegularIndex');
+ $this->scopeState->expects($this->at(2))->method('useTemporaryIndex');
+
+ $this->indexScopeResolver->expects($this->exactly(2))->method('resolve')
+ ->withConsecutive(
+ [$this->equalTo(FulltextIndexer::INDEXER_ID), $this->equalTo($dimensions)],
+ [$this->equalTo(FulltextIndexer::INDEXER_ID), $this->equalTo($dimensions)]
+ )
+ ->willReturnOnConsecutiveCalls(
+ 'catalogsearch_fulltext_scope1_tmp1',
+ 'catalogsearch_fulltext_scope1'
+ );
+
+ $this->connection->expects($this->exactly(2))->method('isTableExists')
+ ->withConsecutive(
+ [$this->equalTo('catalogsearch_fulltext_scope1_tmp1'), $this->equalTo(null)],
+ [$this->equalTo('catalogsearch_fulltext_scope1'), $this->equalTo(null)]
+ )
+ ->willReturnOnConsecutiveCalls(
+ true,
+ false
+ );
+
+ $this->connection->expects($this->never())->method('dropTable')->with('catalogsearch_fulltext_scope1', null);
+ $this->connection->expects($this->once())
+ ->method('renameTable')
+ ->with('catalogsearch_fulltext_scope1_tmp1', 'catalogsearch_fulltext_scope1');
+
+ $this->indexSwitcher->switchIndex($dimensions);
+ }
+
+ /**
+ * @expectedException \Magento\CatalogSearch\Model\Indexer\Scope\IndexTableNotExistException
+ * @expectedExceptionMessage Temporary table for index catalogsearch_fulltext doesn't exist
+ */
+ public function testSwitchWhenTemporaryIndexNotExist()
+ {
+ $dimensions = [$this->getMockBuilder(Dimension::class)->setConstructorArgs(['scope', '1'])];
+
+ $this->scopeState->expects($this->once())
+ ->method('getState')
+ ->willReturn(State::USE_TEMPORARY_INDEX);
+
+ $this->scopeState->expects($this->never())->method('useRegularIndex');
+ $this->scopeState->expects($this->never())->method('useTemporaryIndex');
+
+ $this->indexScopeResolver->expects($this->once())->method('resolve')
+ ->with(FulltextIndexer::INDEXER_ID, $dimensions)
+ ->willReturn('catalogsearch_fulltext_scope1_tmp1');
+
+ $this->connection->expects($this->once())
+ ->method('isTableExists')
+ ->with('catalogsearch_fulltext_scope1_tmp1', null)
+ ->willReturn(false);
+
+ $this->connection->expects($this->never())->method('dropTable')->with('catalogsearch_fulltext_scope1', null);
+ $this->connection->expects($this->never())->method('renameTable');
+
+ $this->indexSwitcher->switchIndex($dimensions);
+ }
+}
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php
index 4b04e7d66ab56..d44fef54683fc 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php
@@ -74,7 +74,10 @@ protected function setUp()
$productLimitationMock = $this->getMock(
\Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class
);
- $productLimitationFactoryMock = $this->getMock(ProductLimitationFactory::class, ['create']);
+ $productLimitationFactoryMock = $this->getMockBuilder(ProductLimitationFactory::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['create'])
+ ->getMock();
$productLimitationFactoryMock->method('create')
->willReturn($productLimitationMock);
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php
index 5e56a25356359..5732ed2c8aee1 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php
@@ -80,7 +80,10 @@ protected function setUp()
$productLimitationMock = $this->getMock(
\Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class
);
- $productLimitationFactoryMock = $this->getMock(ProductLimitationFactory::class, ['create']);
+ $productLimitationFactoryMock = $this->getMockBuilder(ProductLimitationFactory::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['create'])
+ ->getMock();
$productLimitationFactoryMock->method('create')
->willReturn($productLimitationMock);
diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/Indexer/IndexStructureTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/Indexer/IndexStructureTest.php
index 3bb270e990617..8f4bb7736cd37 100644
--- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/Indexer/IndexStructureTest.php
+++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/Indexer/IndexStructureTest.php
@@ -48,9 +48,8 @@ protected function setUp()
->method('getConnection')
->willReturn($this->connection);
$this->indexScopeResolver = $this->getMockBuilder(
- \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver::class
+ \Magento\Framework\Search\Request\IndexScopeResolverInterface::class
)->setMethods(['resolve'])
- ->disableOriginalConstructor()
->getMock();
$objectManager = new ObjectManager($this);
@@ -64,11 +63,6 @@ protected function setUp()
);
}
- /**
- * @param string $table
- * @param array $dimensions
- * @param bool $isTableExist
- */
public function testDelete()
{
$index = 'index_name';
diff --git a/app/code/Magento/CatalogSearch/etc/di.xml b/app/code/Magento/CatalogSearch/etc/di.xml
index 7e9451f9b83e7..7116abf263b0d 100644
--- a/app/code/Magento/CatalogSearch/etc/di.xml
+++ b/app/code/Magento/CatalogSearch/etc/di.xml
@@ -12,6 +12,7 @@