123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Framework\Mview;
- use Magento\Framework\Mview\View\ChangelogTableNotExistsException;
- use Magento\Framework\Mview\View\SubscriptionFactory;
- /**
- * Mview
- *
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- */
- class View extends \Magento\Framework\DataObject implements ViewInterface
- {
- /**
- * Default batch size for partial reindex
- */
- const DEFAULT_BATCH_SIZE = 1000;
- /**
- * Max versions to load from database at a time
- */
- private static $maxVersionQueryBatch = 100000;
- /**
- * @var string
- */
- protected $_idFieldName = 'view_id';
- /**
- * @var ConfigInterface
- */
- protected $config;
- /**
- * @var ActionFactory
- */
- protected $actionFactory;
- /**
- * @var View\ChangelogInterface
- */
- protected $changelog;
- /**
- * @var View\SubscriptionFactory
- */
- protected $subscriptionFactory;
- /**
- * @var \Magento\Framework\Mview\View\StateInterface
- */
- protected $state;
- /**
- * @var array
- */
- private $changelogBatchSize;
- /**
- * @param ConfigInterface $config
- * @param ActionFactory $actionFactory
- * @param View\StateInterface $state
- * @param View\ChangelogInterface $changelog
- * @param SubscriptionFactory $subscriptionFactory
- * @param array $data
- * @param array $changelogBatchSize
- */
- public function __construct(
- ConfigInterface $config,
- ActionFactory $actionFactory,
- View\StateInterface $state,
- View\ChangelogInterface $changelog,
- SubscriptionFactory $subscriptionFactory,
- array $data = [],
- array $changelogBatchSize = []
- ) {
- $this->config = $config;
- $this->actionFactory = $actionFactory;
- $this->state = $state;
- $this->changelog = $changelog;
- $this->subscriptionFactory = $subscriptionFactory;
- $this->changelogBatchSize = $changelogBatchSize;
- parent::__construct($data);
- }
- /**
- * Return ID
- *
- * @return string
- */
- public function getId()
- {
- return $this->getData($this->_idFieldName);
- }
- /**
- * Set ID
- *
- * @param string $id
- * @return $this
- */
- public function setId($id)
- {
- $this->setData($this->_idFieldName, $id);
- return $this;
- }
- /**
- * Id field name setter
- *
- * @param string $name
- * @return $this
- */
- public function setIdFieldName($name)
- {
- $this->_idFieldName = $name;
- return $this;
- }
- /**
- * Id field name getter
- *
- * @return string
- */
- public function getIdFieldName()
- {
- return $this->_idFieldName;
- }
- /**
- * Return view action class
- *
- * @return string
- */
- public function getActionClass()
- {
- return $this->getData('action_class');
- }
- /**
- * Return view group
- *
- * @return string
- */
- public function getGroup()
- {
- return $this->getData('group');
- }
- /**
- * Return view subscriptions
- *
- * @return array
- */
- public function getSubscriptions()
- {
- return $this->getData('subscriptions');
- }
- /**
- * Fill view data from config
- *
- * @param string $viewId
- * @return ViewInterface
- * @throws \InvalidArgumentException
- */
- public function load($viewId)
- {
- $view = $this->config->getView($viewId);
- if (empty($view) || empty($view['view_id']) || $view['view_id'] != $viewId) {
- throw new \InvalidArgumentException("{$viewId} view does not exist.");
- }
- $this->setId($viewId);
- $this->setData($view);
- return $this;
- }
- /**
- * Create subscriptions
- *
- * @throws \Exception
- * @return ViewInterface
- */
- public function subscribe()
- {
- if ($this->getState()->getMode() != View\StateInterface::MODE_ENABLED) {
- try {
- // Create changelog table
- $this->getChangelog()->create();
- // Create subscriptions
- foreach ($this->getSubscriptions() as $subscriptionConfig) {
- /** @var \Magento\Framework\Mview\View\SubscriptionInterface $subscription */
- $subscriptionInstance = $this->subscriptionFactory->create(
- [
- 'view' => $this,
- 'tableName' => $subscriptionConfig['name'],
- 'columnName' => $subscriptionConfig['column'],
- 'subscriptionModel' => !empty($subscriptionConfig['subscription_model'])
- ? $subscriptionConfig['subscription_model']
- : SubscriptionFactory::INSTANCE_NAME,
- ]
- );
- $subscriptionInstance->create();
- }
- // Update view state
- $this->getState()->setMode(View\StateInterface::MODE_ENABLED)->save();
- } catch (\Exception $e) {
- throw $e;
- }
- }
- return $this;
- }
- /**
- * Remove subscriptions
- *
- * @throws \Exception
- * @return ViewInterface
- */
- public function unsubscribe()
- {
- if ($this->getState()->getMode() != View\StateInterface::MODE_DISABLED) {
- try {
- // Remove subscriptions
- foreach ($this->getSubscriptions() as $subscriptionConfig) {
- /** @var \Magento\Framework\Mview\View\SubscriptionInterface $subscription */
- $subscriptionInstance = $this->subscriptionFactory->create(
- [
- 'view' => $this,
- 'tableName' => $subscriptionConfig['name'],
- 'columnName' => $subscriptionConfig['column'],
- 'subscriptionModel' => !empty($subscriptionConfig['subscriptionModel'])
- ? $subscriptionConfig['subscriptionModel']
- : SubscriptionFactory::INSTANCE_NAME,
- ]
- );
- $subscriptionInstance->remove();
- }
- // Update view state
- $this->getState()->setMode(View\StateInterface::MODE_DISABLED)->save();
- } catch (\Exception $e) {
- throw $e;
- }
- }
- return $this;
- }
- /**
- * Materialize view by IDs in changelog
- *
- * @return void
- * @throws \Exception
- */
- public function update()
- {
- if ($this->getState()->getStatus() == View\StateInterface::STATUS_IDLE) {
- try {
- $currentVersionId = $this->getChangelog()->getVersion();
- } catch (ChangelogTableNotExistsException $e) {
- return;
- }
- $lastVersionId = (int) $this->getState()->getVersionId();
- $action = $this->actionFactory->get($this->getActionClass());
- try {
- $this->getState()->setStatus(View\StateInterface::STATUS_WORKING)->save();
- $versionBatchSize = self::$maxVersionQueryBatch;
- $batchSize = isset($this->changelogBatchSize[$this->getChangelog()->getViewId()])
- ? $this->changelogBatchSize[$this->getChangelog()->getViewId()]
- : self::DEFAULT_BATCH_SIZE;
- for ($vsFrom = $lastVersionId; $vsFrom < $currentVersionId; $vsFrom += $versionBatchSize) {
- // Don't go past the current version for atomicy.
- $versionTo = min($currentVersionId, $vsFrom + $versionBatchSize);
- $ids = array_map('intval', $this->getChangelog()->getList($vsFrom, $versionTo));
- // We run the actual indexer in batches.
- // Chunked AFTER loading to avoid duplicates in separate chunks.
- $chunks = array_chunk($ids, $batchSize);
- foreach ($chunks as $ids) {
- $action->execute($ids);
- }
- }
- $this->getState()->loadByView($this->getId());
- $statusToRestore = $this->getState()->getStatus() == View\StateInterface::STATUS_SUSPENDED
- ? View\StateInterface::STATUS_SUSPENDED
- : View\StateInterface::STATUS_IDLE;
- $this->getState()->setVersionId($currentVersionId)->setStatus($statusToRestore)->save();
- } catch (\Exception $exception) {
- $this->getState()->loadByView($this->getId());
- $statusToRestore = $this->getState()->getStatus() == View\StateInterface::STATUS_SUSPENDED
- ? View\StateInterface::STATUS_SUSPENDED
- : View\StateInterface::STATUS_IDLE;
- $this->getState()->setStatus($statusToRestore)->save();
- throw $exception;
- }
- }
- }
- /**
- * Suspend view updates and set version ID to changelog's end
- *
- * @return void
- */
- public function suspend()
- {
- if ($this->getState()->getMode() == View\StateInterface::MODE_ENABLED) {
- $state = $this->getState();
- $state->setVersionId($this->getChangelog()->getVersion());
- $state->setStatus(View\StateInterface::STATUS_SUSPENDED);
- $state->save();
- }
- }
- /**
- * Resume view updates
- *
- * @return void
- */
- public function resume()
- {
- $state = $this->getState();
- if ($state->getStatus() == View\StateInterface::STATUS_SUSPENDED) {
- $state->setStatus(View\StateInterface::STATUS_IDLE);
- $state->save();
- }
- }
- /**
- * Clear precessed changelog entries
- *
- * @return void
- */
- public function clearChangelog()
- {
- if ($this->getState()->getMode() == View\StateInterface::MODE_ENABLED) {
- $this->getChangelog()->clear($this->getState()->getVersionId());
- }
- }
- /**
- * Return related state object
- *
- * @return View\StateInterface
- */
- public function getState()
- {
- if (!$this->state->getViewId()) {
- $this->state->loadByView($this->getId());
- }
- return $this->state;
- }
- /**
- * Set view state object
- *
- * @param View\StateInterface $state
- * @return ViewInterface
- */
- public function setState(View\StateInterface $state)
- {
- $this->state = $state;
- return $this;
- }
- /**
- * Check whether view is enabled
- *
- * @return bool
- */
- public function isEnabled()
- {
- return $this->getState()->getMode() == View\StateInterface::MODE_ENABLED;
- }
- /**
- * Check whether view is idle
- *
- * @return bool
- */
- public function isIdle()
- {
- return $this->getState()->getStatus() == \Magento\Framework\Mview\View\StateInterface::STATUS_IDLE;
- }
- /**
- * Check whether view is working
- *
- * @return bool
- */
- public function isWorking()
- {
- return $this->getState()->getStatus() == \Magento\Framework\Mview\View\StateInterface::STATUS_WORKING;
- }
- /**
- * Check whether view is suspended
- *
- * @return bool
- */
- public function isSuspended()
- {
- return $this->getState()->getStatus() == \Magento\Framework\Mview\View\StateInterface::STATUS_SUSPENDED;
- }
- /**
- * Return view updated datetime
- *
- * @return string
- */
- public function getUpdated()
- {
- return $this->getState()->getUpdated();
- }
- /**
- * Retrieve linked changelog
- *
- * @return View\ChangelogInterface
- */
- public function getChangelog()
- {
- if (!$this->changelog->getViewId()) {
- $this->changelog->setViewId($this->getId());
- }
- return $this->changelog;
- }
- }
|