diff --git a/app/code/Magento/Customer/Model/Customer.php b/app/code/Magento/Customer/Model/Customer.php index 2692d1edf0143..ea52994735c63 100644 --- a/app/code/Magento/Customer/Model/Customer.php +++ b/app/code/Magento/Customer/Model/Customer.php @@ -21,6 +21,7 @@ use Magento\Store\Model\ScopeInterface; use Magento\Framework\App\ObjectManager; use Magento\Framework\Math\Random; +use Magento\Framework\Indexer\IndexerInterface; /** * Customer model @@ -62,8 +63,7 @@ class Customer extends \Magento\Framework\Model\AbstractModel const XML_PATH_RESET_PASSWORD_TEMPLATE = 'customer/password/reset_password_template'; /** - * @deprecated - * @see AccountConfirmation::XML_PATH_IS_CONFIRM + * @deprecated @see \Magento\Customer\Model\AccountConfirmation::XML_PATH_IS_CONFIRM */ const XML_PATH_IS_CONFIRM = 'customer/create_account/confirm'; @@ -227,6 +227,11 @@ class Customer extends \Magento\Framework\Model\AbstractModel */ private $storedAddress; + /** + * @var IndexerInterface|null + */ + private $indexer; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -304,6 +309,19 @@ public function __construct( ); } + /** + * Micro-caching optimization + * + * @return IndexerInterface + */ + private function getIndexer() : IndexerInterface + { + if ($this->indexer === null) { + $this->indexer = $this->indexerRegistry->get(self::CUSTOMER_GRID_INDEXER_ID); + } + return $this->indexer; + } + /** * Initialize customer model * @@ -985,6 +1003,7 @@ public function getSharedWebsiteIds() */ public function getAttributeSetId() { + // phpstan:ignore "Call to an undefined static method*" return parent::getAttributeSetId() ?: CustomerMetadataInterface::ATTRIBUTE_SET_ID_CUSTOMER; } @@ -1075,8 +1094,7 @@ public function resetErrors() */ public function afterSave() { - $indexer = $this->indexerRegistry->get(self::CUSTOMER_GRID_INDEXER_ID); - if ($indexer->getState()->getStatus() == StateInterface::STATUS_VALID) { + if ($this->getIndexer()->getState()->getStatus() == StateInterface::STATUS_VALID) { $this->_getResource()->addCommitCallback([$this, 'reindex']); } return parent::afterSave(); @@ -1100,9 +1118,7 @@ public function afterDeleteCommit() */ public function reindex() { - /** @var \Magento\Framework\Indexer\IndexerInterface $indexer */ - $indexer = $this->indexerRegistry->get(self::CUSTOMER_GRID_INDEXER_ID); - $indexer->reindexRow($this->getId()); + $this->getIndexer()->reindexRow($this->getId()); } /** diff --git a/app/code/Magento/Customer/Setup/RecurringData.php b/app/code/Magento/Customer/Setup/RecurringData.php index fbef4c05d126d..76ff818ca7e5e 100644 --- a/app/code/Magento/Customer/Setup/RecurringData.php +++ b/app/code/Magento/Customer/Setup/RecurringData.php @@ -7,6 +7,7 @@ namespace Magento\Customer\Setup; use Magento\Framework\Indexer\IndexerRegistry; +use Magento\Framework\Indexer\StateInterface; use Magento\Framework\Setup\InstallDataInterface; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; @@ -27,17 +28,34 @@ class RecurringData implements InstallDataInterface * * @param IndexerRegistry $indexerRegistry */ - public function __construct(IndexerRegistry $indexerRegistry) - { + public function __construct( + IndexerRegistry $indexerRegistry + ) { $this->indexerRegistry = $indexerRegistry; } /** - * {@inheritdoc} + * @inheritDoc */ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) { - $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID); - $indexer->reindexAll(); + if ($this->isNeedToDoReindex($setup)) { + $indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID); + $indexer->reindexAll(); + } + } + + /** + * Check is re-index needed + * + * @param ModuleDataSetupInterface $setup + * @return bool + */ + private function isNeedToDoReindex(ModuleDataSetupInterface $setup) : bool + { + return !$setup->tableExists('customer_grid_flat') + || $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID) + ->getState() + ->getStatus() == StateInterface::STATUS_INVALID; } } diff --git a/app/code/Magento/Customer/Test/Unit/Setup/RecurringDataTest.php b/app/code/Magento/Customer/Test/Unit/Setup/RecurringDataTest.php new file mode 100644 index 0000000000000..ee1af91552f6d --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Setup/RecurringDataTest.php @@ -0,0 +1,129 @@ +objectManagerHelper = new ObjectManagerHelper($this); + $this->state = $this->getMockBuilder(StateInterface::class) + ->setMethods(['getStatus']) + ->getMockForAbstractClass(); + $this->indexer = $this->getMockBuilder(IndexerInterface::class) + ->setMethods(['getState', 'reindexAll']) + ->getMockForAbstractClass(); + $this->indexer->expects($this->any()) + ->method('getState') + ->willReturn($this->state); + $this->indexerRegistry = $this->getMockBuilder(IndexerRegistry::class) + ->disableOriginalConstructor() + ->setMethods(['get']) + ->getMock(); + $this->indexerRegistry->expects($this->any()) + ->method('get') + ->with(Customer::CUSTOMER_GRID_INDEXER_ID) + ->willReturn($this->indexer); + $this->setup = $this->getMockBuilder(ModuleDataSetupInterface::class) + ->setMethods(['tableExists']) + ->getMockForAbstractClass(); + $this->context = $this->getMockBuilder(ModuleContextInterface::class) + ->getMockForAbstractClass(); + + $this->recurringData = $this->objectManagerHelper->getObject( + RecurringData::class, + [ + 'indexerRegistry' => $this->indexerRegistry + ] + ); + } + + /** + * @param bool $isTableExists + * @param string $indexerState + * @param int $countReindex + * @return void + * @dataProvider installDataProvider + */ + public function testInstall(bool $isTableExists, string $indexerState, int $countReindex) + { + $this->setup->expects($this->any()) + ->method('tableExists') + ->with('customer_grid_flat') + ->willReturn($isTableExists); + $this->state->expects($this->any()) + ->method('getStatus') + ->willReturn($indexerState); + $this->indexer->expects($this->exactly($countReindex)) + ->method('reindexAll'); + $this->recurringData->install($this->setup, $this->context); + } + + /** + * @return array + */ + public function installDataProvider() : array + { + return [ + [true, StateInterface::STATUS_INVALID, 1], + [false, StateInterface::STATUS_INVALID, 1], + [true, StateInterface::STATUS_VALID, 0], + [false, StateInterface::STATUS_VALID, 1], + ]; + } +}