diff --git a/app/code/Magento/Backend/App/BackendAppList.php b/app/code/Magento/Backend/App/BackendAppList.php index 224ce9893100c6b416da0362ca9a0e3af569bf1e..afb812b823488b29898a2027afa87b6980d9974c 100644 --- a/app/code/Magento/Backend/App/BackendAppList.php +++ b/app/code/Magento/Backend/App/BackendAppList.php @@ -44,6 +44,7 @@ class BackendAppList if ($appName && isset($this->backendApps[$appName])) { return $this->backendApps[$appName]; } + return null; } /** diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Stock.php b/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Stock.php index 0013ba1f17f1bb404640c5da4b3f8ddb2d77d632..86ed5c6a10766bb8a3f475e9b2bf70e0d4c9e279 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Stock.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Stock.php @@ -59,33 +59,27 @@ class Stock extends \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\ "bo.parent_id = product.$linkField", [] ); - $this->_addWebsiteJoinToSelect($select, false); $status = new \Zend_Db_Expr( 'MAX(' . $connection->getCheckSql('e.required_options = 0', 'i.stock_status', '0') . ')' ); - $select->columns( - 'website_id', - 'cw' - )->join( + $select->join( ['cis' => $this->getTable('cataloginventory_stock')], '', - ['stock_id'] + ['website_id', 'stock_id'] )->joinLeft( ['bs' => $this->getTable('catalog_product_bundle_selection')], 'bs.option_id = bo.option_id', [] )->joinLeft( ['i' => $idxTable], - 'i.product_id = bs.product_id AND i.website_id = cw.website_id AND i.stock_id = cis.stock_id', + 'i.product_id = bs.product_id AND i.website_id = cis.website_id AND i.stock_id = cis.stock_id', [] )->joinLeft( ['e' => $this->getTable('catalog_product_entity')], 'e.entity_id = bs.product_id', [] - )->where( - 'cw.website_id != 0' )->group( - ['product.entity_id', 'cw.website_id', 'cis.stock_id', 'bo.option_id'] + ['product.entity_id', 'cis.website_id', 'cis.stock_id', 'bo.option_id'] )->columns( ['option_id' => 'bo.option_id', 'status' => $status] ); @@ -118,45 +112,19 @@ class Stock extends \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\ protected function _getStockStatusSelect($entityIds = null, $usePrimaryTable = false) { $this->_prepareBundleOptionStockData($entityIds, $usePrimaryTable); - $linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField(); $connection = $this->getConnection(); - $select = $connection->select()->from( - ['e' => $this->getTable('catalog_product_entity')], - ['entity_id'] - ); - $this->_addWebsiteJoinToSelect($select, true); - $this->_addProductWebsiteJoinToSelect($select, 'cw.website_id', 'e.entity_id'); - $select->columns( - 'cw.website_id' - )->join( - ['cis' => $this->getTable('cataloginventory_stock')], - '', - ['stock_id'] - )->joinLeft( - ['cisi' => $this->getTable('cataloginventory_stock_item')], - 'cisi.stock_id = cis.stock_id AND cisi.product_id = e.entity_id', - [] + $select = parent::_getStockStatusSelect($entityIds, $usePrimaryTable); + $select->reset( + \Magento\Framework\DB\Select::COLUMNS + )->columns( + ['e.entity_id', 'cis.website_id', 'cis.stock_id'] )->joinLeft( ['o' => $this->_getBundleOptionTable()], - 'o.entity_id = e.entity_id AND o.website_id = cw.website_id AND o.stock_id = cis.stock_id', + 'o.entity_id = e.entity_id AND o.website_id = cis.website_id AND o.stock_id = cis.stock_id', [] )->columns( ['qty' => new \Zend_Db_Expr('0')] - )->where( - 'cw.website_id != 0' - )->where( - 'e.type_id = ?', - $this->getTypeId() - )->group( - ['e.entity_id', 'cw.website_id', 'cis.stock_id'] - ); - - // add limitation of status - $condition = $connection->quoteInto( - '=?', - \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED ); - $this->_addAttributeToSelect($select, 'status', "e.$linkField", 'cs.store_id', $condition); $statusExpr = $this->getStatusExpression($connection); $select->columns( diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php index d8ac9fdf9131d8dbab66cde7181dfa23b28ec63c..0ec9ddf3298f9daec7ab9dfec22765ad95521919 100644 --- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php +++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php @@ -458,7 +458,8 @@ class BundlePanel extends AbstractModifier 'component' => 'Magento_Bundle/js/components/bundle-input-type', 'parentContainer' => 'product_bundle_container', 'selections' => 'bundle_selections', - 'targetIndex' => 'is_default', + 'isDefaultIndex' => 'is_default', + 'userDefinedIndex' => 'selection_can_change_qty', 'dataScope' => 'type', 'label' => __('Input Type'), 'sortOrder' => 20, diff --git a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-input-type.js b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-input-type.js index e52856e53891c64981c9e617afb01c77b453363a..14dd426ed02aa7f144c109a0ac17016be2d56329 100644 --- a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-input-type.js +++ b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-input-type.js @@ -26,36 +26,42 @@ define([ if (type !== this.previousType) { this.previousType = type; - - if (type === 'radio') { - this.clearValues(); - } + this.processSelections(type === 'radio'); } this._super(); }, /** - * Clears values in components like this. + * Toggle 'User Defined' column and clears values + * @param {Boolean} isRadio */ - clearValues: function () { + processSelections: function (isRadio) { var records = registry.get(this.retrieveParentName(this.parentContainer) + '.' + this.selections), checkedFound = false; records.elems.each(function (record) { record.elems.filter(function (comp) { - return comp.index === this.targetIndex; + return comp.index === this.userDefinedIndex; }, this).each(function (comp) { - if (comp.checked()) { - if (checkedFound) { - comp.clearing = true; - comp.clear(); - comp.clearing = false; - } - - checkedFound = true; - } + comp.visible(isRadio); }); + + if (isRadio) { + record.elems.filter(function (comp) { + return comp.index === this.isDefaultIndex; + }, this).each(function (comp) { + if (comp.checked()) { + if (checkedFound) { + comp.clearing = true; + comp.clear(); + comp.clearing = false; + } + + checkedFound = true; + } + }); + } }, this); }, diff --git a/app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php b/app/code/Magento/Catalog/Plugin/Block/Topmenu.php similarity index 74% rename from app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php rename to app/code/Magento/Catalog/Plugin/Block/Topmenu.php index 608c7ee74b7cdda6409432f968734f2d1171a088..098b3282a1b107e56703ee4889f9ce005f25d223 100644 --- a/app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php +++ b/app/code/Magento/Catalog/Plugin/Block/Topmenu.php @@ -3,17 +3,16 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Catalog\Observer; +namespace Magento\Catalog\Plugin\Block; use Magento\Catalog\Model\Category; use Magento\Framework\Data\Collection; use Magento\Framework\Data\Tree\Node; -use Magento\Framework\Event\ObserverInterface; /** - * Observer that add Categories Tree to Topmenu + * Plugin for top menu block */ -class AddCatalogToTopmenuItemsObserver implements ObserverInterface +class Topmenu { /** * Catalog category @@ -38,11 +37,11 @@ class AddCatalogToTopmenuItemsObserver implements ObserverInterface private $layerResolver; /** + * Initialize dependencies. + * * @param \Magento\Catalog\Helper\Category $catalogCategory - * @param \Magento\Catalog\Model\Indexer\Category\Flat\State $categoryFlatState * @param \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Catalog\Helper\Category $catalogCategory * @param \Magento\Catalog\Model\Layer\Resolver $layerResolver */ public function __construct( @@ -58,26 +57,27 @@ class AddCatalogToTopmenuItemsObserver implements ObserverInterface } /** - * Checking whether the using static urls in WYSIWYG allowed event + * Build category tree for menu block. * - * @param \Magento\Framework\Event\Observer $observer + * @param \Magento\Theme\Block\Html\Topmenu $subject + * @param string $outermostClass + * @param string $childrenWrapClass + * @param int $limit * @return void + * @SuppressWarnings("PMD.UnusedFormalParameter") */ - public function execute(\Magento\Framework\Event\Observer $observer) - { - $block = $observer->getEvent()->getBlock(); - $menuRootNode = $observer->getEvent()->getMenu(); - $block->addIdentity(Category::CACHE_TAG); - + public function beforeGetHtml( + \Magento\Theme\Block\Html\Topmenu $subject, + $outermostClass = '', + $childrenWrapClass = '', + $limit = 0 + ) { $rootId = $this->storeManager->getStore()->getRootCategoryId(); $storeId = $this->storeManager->getStore()->getId(); - /** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */ $collection = $this->getCategoryTree($storeId, $rootId); - $currentCategory = $this->getCurrentCategory(); - - $mapping = [$rootId => $menuRootNode]; // use nodes stack to avoid recursion + $mapping = [$rootId => $subject->getMenu()]; // use nodes stack to avoid recursion foreach ($collection as $category) { if (!isset($mapping[$category->getParentId()])) { continue; @@ -94,8 +94,28 @@ class AddCatalogToTopmenuItemsObserver implements ObserverInterface $parentCategoryNode->addChild($categoryNode); $mapping[$category->getId()] = $categoryNode; //add node in stack + } + } - $block->addIdentity(Category::CACHE_TAG . '_' . $category->getId()); + /** + * Add list of associated identities to the top menu block for caching purposes. + * + * @param \Magento\Theme\Block\Html\Topmenu $subject + * @return void + */ + public function beforeGetIdentities(\Magento\Theme\Block\Html\Topmenu $subject) + { + $subject->addIdentity(Category::CACHE_TAG); + $rootId = $this->storeManager->getStore()->getRootCategoryId(); + $storeId = $this->storeManager->getStore()->getId(); + /** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */ + $collection = $this->getCategoryTree($storeId, $rootId); + $mapping = [$rootId => $subject->getMenu()]; // use nodes stack to avoid recursion + foreach ($collection as $category) { + if (!isset($mapping[$category->getParentId()])) { + continue; + } + $subject->addIdentity(Category::CACHE_TAG . '_' . $category->getId()); } } diff --git a/app/code/Magento/Catalog/Setup/UpgradeData.php b/app/code/Magento/Catalog/Setup/UpgradeData.php index 2e05d5b0ac770bdeaacd056a52819a0c582ca1e5..542fea6770fab226e2bb7d22643d0dc74f66218e 100644 --- a/app/code/Magento/Catalog/Setup/UpgradeData.php +++ b/app/code/Magento/Catalog/Setup/UpgradeData.php @@ -257,6 +257,12 @@ class UpgradeData implements UpgradeDataInterface 'frontend_label', 'Small' ); + $categorySetup->updateAttribute( + ProductAttributeInterface::ENTITY_TYPE_CODE, + 'image', + 'frontend_input_renderer', + null + ); //Design tab $categorySetup->updateAttribute( diff --git a/app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php b/app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php similarity index 81% rename from app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php rename to app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php index 393cf8223d2a2d40ed54802515cdc91fa5fc804a..e0fe2deb232f68b989abb72463268d531e5e81cd 100644 --- a/app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php @@ -6,16 +6,16 @@ // @codingStandardsIgnoreFile -namespace Magento\Catalog\Test\Unit\Observer; +namespace Magento\Catalog\Test\Unit\Plugin\Block; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; -class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase +class TopmenuTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Catalog\Observer\AddCatalogToTopmenuItemsObserver + * @var \Magento\Catalog\Plugin\Block\Topmenu */ - protected $_observer; + protected $block; /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Helper\Category @@ -100,8 +100,8 @@ class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase $collection->expects($this->once())->method('getIterator') ->willReturn(new \ArrayIterator([])); - $this->_observer = (new ObjectManager($this))->getObject( - 'Magento\Catalog\Observer\AddCatalogToTopmenuItemsObserver', + $this->block = (new ObjectManager($this))->getObject( + \Magento\Catalog\Plugin\Block\Topmenu::class, [ 'catalogCategory' => $this->_catalogCategory, 'menuCategoryData' => $this->menuCategoryData, @@ -142,23 +142,11 @@ class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase ); $blockMock = $this->_getCleanMock('\Magento\Theme\Block\Html\Topmenu'); - - $eventMock = $this->getMock('\Magento\Framework\Event', ['getBlock'], [], '', false); - $eventMock->expects($this->once()) - ->method('getBlock') - ->will($this->returnValue($blockMock)); - - $observerMock = $this->getMock('\Magento\Framework\Event\Observer', ['getEvent', 'getMenu'], [], '', false); - $observerMock->expects($this->any()) - ->method('getEvent') - ->will($this->returnValue($eventMock)); - - return $observerMock; + return $blockMock; } public function testAddCatalogToTopMenuItems() { - $observer = $this->_preparationData(); - $this->_observer->execute($observer); + $this->block->beforeGetHtml($this->_preparationData()); } } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php index 473d1d423067478ea94d0c8b5afcc88c68de40c2..61141072f7725e165cb29938e7878b6b240ef6a6 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php @@ -319,8 +319,7 @@ class CustomOptions extends AbstractModifier 'sortOrder' => 20, 'actions' => [ [ - 'targetName' => static::FORM_NAME . '.' . static::FORM_NAME . '.' - . static::GROUP_CUSTOM_OPTIONS_NAME . '.' . static::GRID_OPTIONS_NAME, + 'targetName' => 'ns = ${ $.ns }, index = ' . static::GRID_OPTIONS_NAME, 'actionName' => 'addChild', ] ] diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index 19a4f22a3c8e9425d474873f321f08baf062113c..78e46f0c39205ee7172c890739fa60a23946affa 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -46,6 +46,9 @@ <type name="Magento\Customer\Model\ResourceModel\Visitor"> <plugin name="catalogLog" type="Magento\Catalog\Model\Plugin\Log" /> </type> + <type name="Magento\Theme\Block\Html\Topmenu"> + <plugin name="catalogTopmenu" type="Magento\Catalog\Plugin\Block\Topmenu" /> + </type> <type name="Magento\Framework\Mview\View\StateInterface"> <plugin name="setStatusForMview" type="Magento\Catalog\Model\Indexer\Category\Product\Plugin\MviewState" /> </type> diff --git a/app/code/Magento/Catalog/etc/frontend/events.xml b/app/code/Magento/Catalog/etc/frontend/events.xml index afb3c70a14ade23fc8caab37ab4f3b564ae1f917..5ef8c724683141c38d735fcd0e321615d562ce6a 100644 --- a/app/code/Magento/Catalog/etc/frontend/events.xml +++ b/app/code/Magento/Catalog/etc/frontend/events.xml @@ -12,7 +12,4 @@ <event name="customer_logout"> <observer name="catalog" instance="Magento\Catalog\Observer\Compare\BindCustomerLogoutObserver" shared="false" /> </event> - <event name="page_block_html_topmenu_gethtml_before"> - <observer name="catalog_add_topmenu_items" instance="Magento\Catalog\Observer\AddCatalogToTopmenuItemsObserver" /> - </event> </config> diff --git a/app/code/Magento/CatalogInventory/Helper/Stock.php b/app/code/Magento/CatalogInventory/Helper/Stock.php index 599b2d44e2ae38e45e7477a5c45edb426e0a164b..13e311d1fe5aeb4af1282edcf29215fe67570199 100644 --- a/app/code/Magento/CatalogInventory/Helper/Stock.php +++ b/app/code/Magento/CatalogInventory/Helper/Stock.php @@ -12,9 +12,11 @@ use Magento\CatalogInventory\Model\ResourceModel\Stock\StatusFactory; use Magento\CatalogInventory\Model\ResourceModel\Stock\Status; use Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection; use Magento\Catalog\Model\Product; +use Magento\CatalogInventory\Api\StockConfigurationInterface; /** * Class Stock + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Stock { @@ -47,6 +49,11 @@ class Stock */ private $stockRegistryProvider; + /** + * @var StockConfigurationInterface + */ + private $stockConfiguration; + /** * @param StoreManagerInterface $storeManager * @param ScopeConfigInterface $scopeConfig @@ -75,7 +82,7 @@ class Stock public function assignStatusToProduct(Product $product, $status = null) { if ($status === null) { - $websiteId = $product->getStore()->getWebsiteId(); + $websiteId = $this->getStockConfiguration()->getDefaultScopeId(); $stockStatus = $this->stockRegistryProvider->getStockStatus($product->getId(), $websiteId); $status = $stockStatus->getStockStatus(); } @@ -90,7 +97,7 @@ class Stock */ public function addStockStatusToProducts(AbstractCollection $productCollection) { - $websiteId = $this->storeManager->getStore($productCollection->getStoreId())->getWebsiteId(); + $websiteId = $this->getStockConfiguration()->getDefaultScopeId(); foreach ($productCollection as $product) { $productId = $product->getId(); $stockStatus = $this->stockRegistryProvider->getStockStatus($productId, $websiteId); @@ -161,4 +168,18 @@ class Stock } return $this->stockStatusResource; } + + /** + * @return StockConfigurationInterface + * + * @deprecated + */ + private function getStockConfiguration() + { + if ($this->stockConfiguration === null) { + $this->stockConfiguration = \Magento\Framework\App\ObjectManager::getInstance() + ->get('Magento\CatalogInventory\Api\StockConfigurationInterface'); + } + return $this->stockConfiguration; + } } diff --git a/app/code/Magento/CatalogInventory/Model/Config/Backend/Backorders.php b/app/code/Magento/CatalogInventory/Model/Config/Backend/Backorders.php index db78c8e17322bd12129cc488248cd0703bb83781..1915a576939ac0aca869e5072abb3e828820dea6 100644 --- a/app/code/Magento/CatalogInventory/Model/Config/Backend/Backorders.php +++ b/app/code/Magento/CatalogInventory/Model/Config/Backend/Backorders.php @@ -25,7 +25,6 @@ class Backorders extends AbstractValue || $this->getValue() == \Magento\CatalogInventory\Model\Stock::BACKORDERS_NO ) ) { - $this->stockIndex->rebuild(); $this->_stockIndexerProcessor->markIndexerAsInvalid(); } return parent::afterSave(); diff --git a/app/code/Magento/CatalogInventory/Model/Config/Backend/Managestock.php b/app/code/Magento/CatalogInventory/Model/Config/Backend/Managestock.php index 559e6235951dbae06698ce2def0eccbbd5dfd915..6edab6f3d4eb629e2947676c21d07fe827d52cdd 100644 --- a/app/code/Magento/CatalogInventory/Model/Config/Backend/Managestock.php +++ b/app/code/Magento/CatalogInventory/Model/Config/Backend/Managestock.php @@ -20,7 +20,6 @@ class Managestock extends AbstractValue public function afterSave() { if ($this->isValueChanged()) { - $this->stockIndex->rebuild(); $this->_stockIndexerProcessor->markIndexerAsInvalid(); } return parent::afterSave(); diff --git a/app/code/Magento/CatalogInventory/Model/Configuration.php b/app/code/Magento/CatalogInventory/Model/Configuration.php index 445057c4c08d8174768a9237359bdb4f830066cd..d1509eec3d4adce87cfd4b8ecf75f63485bbeff5 100644 --- a/app/code/Magento/CatalogInventory/Model/Configuration.php +++ b/app/code/Magento/CatalogInventory/Model/Configuration.php @@ -148,7 +148,9 @@ class Configuration implements StockConfigurationInterface */ public function getDefaultScopeId() { - return (int) $this->storeManager->getWebsite()->getId(); + // TODO: should be fixed in MAGETWO-46043 + // "0" is id of admin website, which is used in backend during save entity + return 0; } /** diff --git a/app/code/Magento/CatalogInventory/Model/Plugin/AroundProductRepositorySave.php b/app/code/Magento/CatalogInventory/Model/Plugin/AroundProductRepositorySave.php index 82e9e1b1c94c607103230917753f0aa1c5afaede..df910254082185145212c325568a971a75a9bd85 100644 --- a/app/code/Magento/CatalogInventory/Model/Plugin/AroundProductRepositorySave.php +++ b/app/code/Magento/CatalogInventory/Model/Plugin/AroundProductRepositorySave.php @@ -24,6 +24,7 @@ class AroundProductRepositorySave /** * @var StoreManagerInterface + * @deprecated */ protected $storeManager; @@ -80,7 +81,7 @@ class AroundProductRepositorySave // set fields that the customer should not care about $stockItem->setProductId($product->getId()); - $stockItem->setWebsiteId($this->storeManager->getStore($product->getStoreId())->getWebsiteId()); + $stockItem->setWebsiteId($this->stockConfiguration->getDefaultScopeId()); $this->stockRegistry->updateStockItemBySku($product->getSku(), $stockItem); diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php index 3bb9ef4c4d5c6f847d17365df179f54b0b678752..40245db2f3372234ad18a988140195e88a11b971 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php @@ -9,6 +9,7 @@ namespace Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock; use Magento\Catalog\Model\ResourceModel\Product\Indexer\AbstractIndexer; use Magento\CatalogInventory\Model\Stock; use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\CatalogInventory\Api\StockConfigurationInterface; /** * CatalogInventory Default Stock Status Indexer Resource Model @@ -42,6 +43,11 @@ class DefaultStock extends AbstractIndexer implements StockInterface */ private $queryProcessorComposite; + /** + * @var StockConfigurationInterface + */ + protected $stockConfiguration; + /** * Class constructor * @@ -176,43 +182,29 @@ class DefaultStock extends AbstractIndexer implements StockInterface */ protected function _getStockStatusSelect($entityIds = null, $usePrimaryTable = false) { - $metadata = $this->getMetadataPool()->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class); $connection = $this->getConnection(); $qtyExpr = $connection->getCheckSql('cisi.qty > 0', 'cisi.qty', 0); $select = $connection->select()->from( ['e' => $this->getTable('catalog_product_entity')], ['entity_id'] ); - $this->_addWebsiteJoinToSelect($select, true); - $this->_addProductWebsiteJoinToSelect($select, 'cw.website_id', 'e.entity_id'); - $select->columns('cw.website_id')->join( + $select->join( ['cis' => $this->getTable('cataloginventory_stock')], '', - ['stock_id'] - )->joinLeft( + ['website_id', 'stock_id'] + )->joinInner( ['cisi' => $this->getTable('cataloginventory_stock_item')], 'cisi.stock_id = cis.stock_id AND cisi.product_id = e.entity_id', [] - )->columns(['qty' => new \Zend_Db_Expr('SUM(' . $qtyExpr . ')')]) - ->where('cw.website_id != 0') - ->where('e.type_id = ?', $this->getTypeId()) - ->group(['e.entity_id', 'cw.website_id']); - - // add limitation of status - $condition = $connection->quoteInto( - '=?', - \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED - ); - $this->_addAttributeToSelect( - $select, - 'status', - 'e.' . $metadata->getLinkField(), - 'cs.store_id', - $condition - ); + )->columns( + ['qty' => $qtyExpr] + )->where( + 'cis.website_id = ?', + $this->getStockConfiguration()->getDefaultScopeId() + )->where('e.type_id = ?', $this->getTypeId()) + ->group(['e.entity_id', 'cis.website_id', 'cis.stock_id']); $select->columns(['status' => $this->getStatusExpression($connection, true)]); - if ($entityIds !== null) { $select->where('e.entity_id IN(?)', $entityIds); } @@ -325,6 +317,20 @@ class DefaultStock extends AbstractIndexer implements StockInterface return $statusExpr; } + /** + * @return StockConfigurationInterface + * + * @deprecated + */ + protected function getStockConfiguration() + { + if ($this->stockConfiguration === null) { + $this->stockConfiguration = \Magento\Framework\App\ObjectManager::getInstance() + ->get('Magento\CatalogInventory\Api\StockConfigurationInterface'); + } + return $this->stockConfiguration; + } + /** * @return QueryProcessorComposite */ diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock.php index f4877e6a3de68fd72a6550d1b6bf6c5b611593bb..17a3e0c9a99494de5efdb4f6825c33fae9e41e54 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock.php @@ -75,6 +75,7 @@ class Stock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb impleme /** * @var StoreManagerInterface + * @deprecated */ protected $storeManager; @@ -189,11 +190,12 @@ class Stock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb impleme * Set items out of stock basing on their quantities and config settings * * @param string|int $website + * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @return void */ public function updateSetOutOfStock($website = null) { - $websiteId = $this->storeManager->getWebsite($website)->getId(); + $websiteId = $this->stockConfiguration->getDefaultScopeId(); $this->_initConfig(); $connection = $this->getConnection(); $values = ['is_in_stock' => 0, 'stock_status_changed_auto' => 1]; @@ -223,11 +225,12 @@ class Stock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb impleme * Set items in stock basing on their quantities and config settings * * @param int|string $website + * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @return void */ public function updateSetInStock($website) { - $websiteId = $this->storeManager->getWebsite($website)->getId(); + $websiteId = $this->stockConfiguration->getDefaultScopeId(); $this->_initConfig(); $connection = $this->getConnection(); $values = ['is_in_stock' => 1]; @@ -255,11 +258,12 @@ class Stock extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb impleme * Update items low stock date basing on their quantities and config settings * * @param int|string $website + * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @return void */ public function updateLowStockDate($website) { - $websiteId = $this->storeManager->getWebsite($website)->getId(); + $websiteId = $this->stockConfiguration->getDefaultScopeId(); $this->_initConfig(); $connection = $this->getConnection(); diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item.php index d08bd31df9eeb517f3577ce3aff34de85c42479f..32d21f388f03e30510dfb1179fdf335654b4c0a4 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item.php @@ -57,13 +57,13 @@ class Item extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb * * @param \Magento\CatalogInventory\Api\Data\StockItemInterface $item * @param int $productId - * @param int $websiteId + * @param int $stockId * @return $this */ - public function loadByProductId(\Magento\CatalogInventory\Api\Data\StockItemInterface $item, $productId, $websiteId) + public function loadByProductId(\Magento\CatalogInventory\Api\Data\StockItemInterface $item, $productId, $stockId) { - $select = $this->_getLoadSelect('product_id', $productId, $item)->where('website_id = :website_id'); - $data = $this->getConnection()->fetchRow($select, [':website_id' => $websiteId]); + $select = $this->_getLoadSelect('product_id', $productId, $item)->where('stock_id = :stock_id'); + $data = $this->getConnection()->fetchRow($select, [':stock_id' => $stockId]); if ($data) { $item->setData($data); } else { diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item/StockItemCriteriaMapper.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item/StockItemCriteriaMapper.php index 551f5e0c3b8fffd04eaac0e5c18bd1a1977990d6..d1e038071ecc52a7adf9f5452076e95cd06358e5 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item/StockItemCriteriaMapper.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item/StockItemCriteriaMapper.php @@ -13,6 +13,7 @@ use Magento\Framework\Data\ObjectFactory; use Magento\Store\Model\StoreManagerInterface; use Psr\Log\LoggerInterface as Logger; use Magento\Framework\Data\Collection\Db\FetchStrategyInterface; +use Magento\CatalogInventory\Api\StockConfigurationInterface; /** * Interface StockItemCriteriaMapper @@ -20,6 +21,17 @@ use Magento\Framework\Data\Collection\Db\FetchStrategyInterface; */ class StockItemCriteriaMapper extends GenericMapper { + /** + * @var StockConfigurationInterface + */ + private $stockConfiguration; + + /** + * @var StoreManagerInterface + * @deprecated + */ + private $storeManager; + /** * @param Logger $logger * @param FetchStrategyInterface $fetchStrategy @@ -107,10 +119,11 @@ class StockItemCriteriaMapper extends GenericMapper /** * @inheritdoc + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function mapStockStatus($storeId = null) { - $websiteId = $this->storeManager->getStore($storeId)->getWebsiteId(); + $websiteId = $this->getStockConfiguration()->getDefaultScopeId(); $this->getSelect()->joinLeft( ['status_table' => $this->getTable('cataloginventory_stock_status')], 'main_table.product_id=status_table.product_id' . @@ -149,4 +162,18 @@ class StockItemCriteriaMapper extends GenericMapper } $this->addFieldToFilter('main_table.qty', [$methods[$comparisonMethod] => $qty]); } + + /** + * @return StockConfigurationInterface + * + * @deprecated + */ + private function getStockConfiguration() + { + if ($this->stockConfiguration === null) { + $this->stockConfiguration = \Magento\Framework\App\ObjectManager::getInstance() + ->get('Magento\CatalogInventory\Api\StockConfigurationInterface'); + } + return $this->stockConfiguration; + } } diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Status.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Status.php index 75b325458ccaa2c9c4bfb3c0c16ffc381c7cab90..f7410de156fb42e4549b3d1910d5c5d9d5fb0d27 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Status.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Status.php @@ -6,9 +6,11 @@ namespace Magento\CatalogInventory\Model\ResourceModel\Stock; use Magento\CatalogInventory\Model\Stock; +use Magento\CatalogInventory\Api\StockConfigurationInterface; /** * CatalogInventory Stock Status per website Resource Model + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb { @@ -16,6 +18,7 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb * Store model manager * * @var \Magento\Store\Model\StoreManagerInterface + * @deprecated */ protected $_storeManager; @@ -31,6 +34,11 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb */ protected $eavConfig; + /** + * @var StockConfigurationInterface + */ + private $stockConfiguration; + /** * @param \Magento\Framework\Model\ResourceModel\Db\Context $context * @param \Magento\Store\Model\StoreManagerInterface $storeManager @@ -190,11 +198,12 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb * * @param \Magento\Framework\DB\Select $select * @param \Magento\Store\Model\Website $website + * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @return Status */ public function addStockStatusToSelect(\Magento\Framework\DB\Select $select, \Magento\Store\Model\Website $website) { - $websiteId = $website->getId(); + $websiteId = $this->getStockConfiguration()->getDefaultScopeId(); $select->joinLeft( ['stock_status' => $this->getMainTable()], 'e.entity_id = stock_status.product_id AND stock_status.website_id=' . $websiteId, @@ -211,7 +220,7 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb */ public function addStockDataToCollection($collection, $isFilterInStock) { - $websiteId = $this->_storeManager->getStore($collection->getStoreId())->getWebsiteId(); + $websiteId = $this->getStockConfiguration()->getDefaultScopeId(); $joinCondition = $this->getConnection()->quoteInto( 'e.entity_id = stock_status_index.product_id' . ' AND stock_status_index.website_id = ?', $websiteId @@ -245,7 +254,7 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb */ public function addIsInStockFilterToCollection($collection) { - $websiteId = $this->_storeManager->getStore($collection->getStoreId())->getWebsiteId(); + $websiteId = $this->getStockConfiguration()->getDefaultScopeId(); $joinCondition = $this->getConnection()->quoteInto( 'e.entity_id = stock_status_index.product_id' . ' AND stock_status_index.website_id = ?', $websiteId @@ -325,4 +334,18 @@ class Status extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb } return $statuses; } + + /** + * @return StockConfigurationInterface + * + * @deprecated + */ + private function getStockConfiguration() + { + if ($this->stockConfiguration === null) { + $this->stockConfiguration = \Magento\Framework\App\ObjectManager::getInstance() + ->get('Magento\CatalogInventory\Api\StockConfigurationInterface'); + } + return $this->stockConfiguration; + } } diff --git a/app/code/Magento/CatalogInventory/Model/StockIndex.php b/app/code/Magento/CatalogInventory/Model/StockIndex.php index a30bc203c638f251e167fa5f88eb6d9eaca6ef21..226293c8205e67acd32953463485713d64729128 100644 --- a/app/code/Magento/CatalogInventory/Model/StockIndex.php +++ b/app/code/Magento/CatalogInventory/Model/StockIndex.php @@ -78,6 +78,7 @@ class StockIndex implements StockIndexInterface * * @param int $productId * @param int $scopeId + * @deprecated * @return true * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ @@ -108,6 +109,7 @@ class StockIndex implements StockIndexInterface * * @param int $productId * @param int $websiteId + * @deprecated * @return void */ public function updateProductStockStatus($productId, $websiteId) diff --git a/app/code/Magento/CatalogInventory/Model/StockState.php b/app/code/Magento/CatalogInventory/Model/StockState.php index a5f60dce93ca7b45d3d4c4aa8783df95e72a7d80..0c8b84d473e45a47ab2ceaf69cf5089f5818a9b3 100644 --- a/app/code/Magento/CatalogInventory/Model/StockState.php +++ b/app/code/Magento/CatalogInventory/Model/StockState.php @@ -52,9 +52,9 @@ class StockState implements StockStateInterface */ public function verifyStock($productId, $scopeId = null) { - if ($scopeId === null) { + // if ($scopeId === null) { $scopeId = $this->stockConfiguration->getDefaultScopeId(); - } + // } $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId); return $this->stockStateProvider->verifyStock($stockItem); } @@ -66,9 +66,9 @@ class StockState implements StockStateInterface */ public function verifyNotification($productId, $scopeId = null) { - if ($scopeId === null) { + // if ($scopeId === null) { $scopeId = $this->stockConfiguration->getDefaultScopeId(); - } + // } $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId); return $this->stockStateProvider->verifyNotification($stockItem); } @@ -84,9 +84,9 @@ class StockState implements StockStateInterface */ public function checkQty($productId, $qty, $scopeId = null) { - if ($scopeId === null) { + // if ($scopeId === null) { $scopeId = $this->stockConfiguration->getDefaultScopeId(); - } + // } $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId); return $this->stockStateProvider->checkQty($stockItem, $qty); } @@ -102,9 +102,9 @@ class StockState implements StockStateInterface */ public function suggestQty($productId, $qty, $scopeId = null) { - if ($scopeId === null) { + // if ($scopeId === null) { $scopeId = $this->stockConfiguration->getDefaultScopeId(); - } + // } $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId); return $this->stockStateProvider->suggestQty($stockItem, $qty); } @@ -118,9 +118,9 @@ class StockState implements StockStateInterface */ public function getStockQty($productId, $scopeId = null) { - if ($scopeId === null) { + // if ($scopeId === null) { $scopeId = $this->stockConfiguration->getDefaultScopeId(); - } + // } $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId); return $this->stockStateProvider->getStockQty($stockItem); } @@ -133,9 +133,9 @@ class StockState implements StockStateInterface */ public function checkQtyIncrements($productId, $qty, $websiteId = null) { - if ($websiteId === null) { + // if ($websiteId === null) { $websiteId = $this->stockConfiguration->getDefaultScopeId(); - } + // } $stockItem = $this->stockRegistryProvider->getStockItem($productId, $websiteId); return $this->stockStateProvider->checkQtyIncrements($stockItem, $qty); } @@ -150,9 +150,9 @@ class StockState implements StockStateInterface */ public function checkQuoteItemQty($productId, $itemQty, $qtyToCheck, $origQty, $scopeId = null) { - if ($scopeId === null) { + // if ($scopeId === null) { $scopeId = $this->stockConfiguration->getDefaultScopeId(); - } + // } $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId); return $this->stockStateProvider->checkQuoteItemQty($stockItem, $itemQty, $qtyToCheck, $origQty); } diff --git a/app/code/Magento/CatalogInventory/Observer/SaveInventoryDataObserver.php b/app/code/Magento/CatalogInventory/Observer/SaveInventoryDataObserver.php index d700b296871aa2faf5fcc62a5ef3b6822c2cbe24..72c9b35394717deb7b22b24fa89236d5e559e1bd 100644 --- a/app/code/Magento/CatalogInventory/Observer/SaveInventoryDataObserver.php +++ b/app/code/Magento/CatalogInventory/Observer/SaveInventoryDataObserver.php @@ -17,6 +17,7 @@ class SaveInventoryDataObserver implements ObserverInterface { /** * @var StockIndexInterface + * @deprecated */ protected $stockIndex; @@ -96,14 +97,7 @@ class SaveInventoryDataObserver implements ObserverInterface public function execute(EventObserver $observer) { $product = $observer->getEvent()->getProduct(); - if ($product->getStockData() === null) { - if ($product->getIsChangedWebsites() || $product->dataHasChangedFor('status')) { - $this->stockIndex->rebuild( - $product->getId(), - $product->getStore()->getWebsiteId() - ); - } return $this; } diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Helper/StockTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Helper/StockTest.php index 1f1c7a98f0907a6cea0b863477a6f57af1200f7d..df5ea40e933075bb07dd398ab3514e2cf18960d6 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Helper/StockTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Helper/StockTest.php @@ -37,6 +37,11 @@ class StockTest extends \PHPUnit_Framework_TestCase */ protected $statusFactoryMock; + /** + * @var \Magento\CatalogInventory\Api\StockConfigurationInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $stockConfiguration; + protected function setUp() { $this->stockRegistryProviderMock = $this->getMockBuilder( @@ -55,12 +60,20 @@ class StockTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); + $this->stockConfiguration = $this->getMockBuilder('Magento\CatalogInventory\Api\StockConfigurationInterface') + ->getMock(); $this->stock = new Stock( $this->storeManagerMock, $this->scopeConfigMock, $this->statusFactoryMock, $this->stockRegistryProviderMock ); + + // Todo: \Magento\Framework\TestFramework\Unit\Helper\ObjectManager to do this automatically (MAGETWO-49793) + $reflection = new \ReflectionClass(get_class($this->stock)); + $reflectionProperty = $reflection->getProperty('stockConfiguration'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->stock, $this->stockConfiguration); } public function testAssignStatusToProduct() @@ -77,19 +90,12 @@ class StockTest extends \PHPUnit_Framework_TestCase $this->stockRegistryProviderMock->expects($this->any()) ->method('getStockStatus') ->willReturn($stockStatusMock); - $storeMock = $this->getMockBuilder('Magento\Store\Model\Store') - ->disableOriginalConstructor() - ->getMock(); - $storeMock->expects($this->once()) - ->method('getWebsiteId') - ->willReturn($websiteId); + $this->stockConfiguration->expects($this->once())->method('getDefaultScopeId')->willReturn($websiteId); + $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') ->disableOriginalConstructor() - ->setMethods(['setIsSalable', 'getStore', 'getId']) + ->setMethods(['setIsSalable', 'getId']) ->getMock(); - $productMock->expects($this->any()) - ->method('getStore') - ->willReturn($storeMock); $productMock->expects($this->once()) ->method('setIsSalable') ->with($status); @@ -134,12 +140,6 @@ class StockTest extends \PHPUnit_Framework_TestCase $productCollectionMock->expects($this->any()) ->method('getIterator') ->willReturn($iteratorMock); - $storeMock = $this->getMockBuilder('Magento\Store\Model\Store') - ->disableOriginalConstructor() - ->getMock(); - $this->storeManagerMock->expects($this->once()) - ->method('getStore') - ->willReturn($storeMock); $this->stockRegistryProviderMock->expects($this->once()) ->method('getStockStatus') ->withAnyParameters() diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Config/Backend/ManagestockTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Config/Backend/ManagestockTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b180ba0e035173514ebb444bec4e2c4487567577 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Config/Backend/ManagestockTest.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogInventory\Test\Unit\Model\Config\Backend; + +class ManagestockTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\CatalogInventory\Model\Indexer\Stock\Processor|\PHPUnit_Framework_MockObject_MockObject */ + protected $stockIndexerProcessor; + + /** @var \Magento\CatalogInventory\Model\Config\Backend\Managestock */ + protected $model; + + protected function setUp() + { + $this->stockIndexerProcessor = $this->getMockBuilder('Magento\CatalogInventory\Model\Indexer\Stock\Processor') + ->disableOriginalConstructor() + ->getMock(); + $this->model = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( + 'Magento\CatalogInventory\Model\Config\Backend\Managestock', + [ + 'stockIndexerProcessor' => $this->stockIndexerProcessor, + ] + ); + } + + /** + * Data provider for testSaveAndRebuildIndex + * @return array + */ + public function saveAndRebuildIndexDataProvider() + { + return [ + [1, 1], + [0, 0], + ]; + } + + /** + * @dataProvider saveAndRebuildIndexDataProvider + * + * @param int $newStockValue new value for stock status + * @param int $callCount count matcher + */ + public function testSaveAndRebuildIndex($newStockValue, $callCount) + { + $this->model->setValue($newStockValue); + $this->stockIndexerProcessor->expects($this->exactly($callCount))->method('markIndexerAsInvalid'); + $this->model->afterSave(); + } +} diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/ConfigurationTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/ConfigurationTest.php index 90b05b2d10649ce527debbea0f368d5e385f55bc..a0b2cc7225c9efe60c158b0e71946a22d5cb5512 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/ConfigurationTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/ConfigurationTest.php @@ -61,17 +61,7 @@ class ConfigurationTest extends \PHPUnit_Framework_TestCase public function testGetDefaultWebsiteId() { - $id = 1; - $websiteMock = $this->getMockBuilder('Magento\Store\Model\Website') - ->disableOriginalConstructor() - ->getMock(); - $websiteMock->expects($this->once()) - ->method('getId') - ->willReturn($id); - $this->storeManagerMock->expects($this->once()) - ->method('getWebsite') - ->willReturn($websiteMock); - $this->assertEquals($id, $this->model->getDefaultScopeId()); + $this->assertEquals(0, $this->model->getDefaultScopeId()); } public function testGetIsQtyTypeIds() diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php index 534960b4397833d268c56ab62c9a45d46cc997f9..cb26fda9be79e928dac5585694e71778661bf0f6 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php @@ -154,11 +154,7 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase ->method('getStockItem') ->willReturn(null); - $storeMock = $this->getMockBuilder('\Magento\Store\Model\Store') - ->disableOriginalConstructor()->getMock(); - $storeMock->expects($this->once())->method('getWebsiteId')->willReturn(1); - $this->storeManager->expects($this->once())->method('getStore')->willReturn($storeMock); - + $this->stockConfiguration->expects($this->once())->method('getDefaultScopeId')->willReturn(1); $this->stockRegistry->expects($this->once())->method('getStockItem')->willReturn($this->stockItem); $this->stockRegistry->expects($this->once())->method('updateStockItemBySku'); @@ -180,11 +176,10 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase public function testAroundSave() { $productId = 5494; - $websiteId = 1; $storeId = 2; $sku = 'my product that needs saving'; $defaultScopeId = 100; - $this->stockConfiguration->expects($this->once()) + $this->stockConfiguration->expects($this->exactly(2)) ->method('getDefaultScopeId') ->willReturn($defaultScopeId); $this->stockRegistry->expects($this->once()) @@ -209,17 +204,12 @@ class AroundProductRepositorySaveTest extends \PHPUnit_Framework_TestCase ->method('getStockItem') ->willReturn($storedStockItem); - $storeMock = $this->getMockBuilder('\Magento\Store\Model\Store') - ->disableOriginalConstructor()->getMock(); - $storeMock->expects($this->once())->method('getWebsiteId')->willReturn($websiteId); - $this->storeManager->expects($this->once())->method('getStore')->with($storeId)->willReturn($storeMock); - $this->product->expects(($this->exactly(2)))->method('getId')->willReturn($productId); $this->product->expects(($this->atLeastOnce()))->method('getStoreId')->willReturn($storeId); $this->product->expects($this->atLeastOnce())->method('getSku')->willReturn($sku); $this->stockItem->expects($this->once())->method('setProductId')->with($productId); - $this->stockItem->expects($this->once())->method('setWebsiteId')->with($websiteId); + $this->stockItem->expects($this->once())->method('setWebsiteId')->with($defaultScopeId); $this->stockRegistry->expects($this->once()) ->method('updateStockItemBySku') diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Observer/SaveInventoryDataObserverTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Observer/SaveInventoryDataObserverTest.php deleted file mode 100644 index 1b8347539485d11ff30b22ea3803201cf08004f2..0000000000000000000000000000000000000000 --- a/app/code/Magento/CatalogInventory/Test/Unit/Observer/SaveInventoryDataObserverTest.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\CatalogInventory\Test\Unit\Observer; - -use Magento\CatalogInventory\Observer\SaveInventoryDataObserver; - -class SaveInventoryDataObserverTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var SaveInventoryDataObserver - */ - protected $observer; - - /** - * @var \Magento\CatalogInventory\Api\StockIndexInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $stockIndex; - - /** - * @var \Magento\Framework\Event|\PHPUnit_Framework_MockObject_MockObject - */ - protected $event; - - /** - * @var \Magento\Framework\Event\Observer|\PHPUnit_Framework_MockObject_MockObject - */ - protected $eventObserver; - - protected function setUp() - { - $this->stockIndex = $this->getMockForAbstractClass( - 'Magento\CatalogInventory\Api\StockIndexInterface', - ['rebuild'], - '', - false - ); - - $this->event = $this->getMockBuilder('Magento\Framework\Event') - ->disableOriginalConstructor() - ->setMethods(['getProduct']) - ->getMock(); - - $this->eventObserver = $this->getMockBuilder('Magento\Framework\Event\Observer') - ->disableOriginalConstructor() - ->setMethods(['getEvent']) - ->getMock(); - - $this->eventObserver->expects($this->atLeastOnce()) - ->method('getEvent') - ->will($this->returnValue($this->event)); - - $this->observer = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( - 'Magento\CatalogInventory\Observer\SaveInventoryDataObserver', - [ - 'stockIndex' => $this->stockIndex, - ] - ); - } - - public function testSaveInventoryData() - { - $productId = 4; - $websiteId = 5; - $stockData = null; - $websitesChanged = true; - $statusChanged = true; - - $store = $this->getMock('Magento\Store\Model\Store', ['getWebsiteId'], [], '', false); - $store->expects($this->once())->method('getWebsiteId')->will($this->returnValue($websiteId)); - - $product = $this->getMock( - 'Magento\Catalog\Model\Product', - ['getStockData', 'getIsChangedWebsites', 'dataHasChangedFor', 'getId', 'getStore'], - [], - '', - false - ); - $product->expects($this->once())->method('getStockData')->will($this->returnValue($stockData)); - $product->expects($this->any())->method('getIsChangedWebsites')->will($this->returnValue($websitesChanged)); - $product->expects($this->any())->method('dataHasChangedFor')->will($this->returnValue($statusChanged)); - $product->expects($this->once())->method('getId')->will($this->returnValue($productId)); - $product->expects($this->once())->method('getStore')->will($this->returnValue($store)); - - $this->stockIndex->expects($this->once())->method('rebuild')->will($this->returnValue(true)); - - $this->event->expects($this->once()) - ->method('getProduct') - ->will($this->returnValue($product)); - - $this->observer->execute($this->eventObserver); - } -} diff --git a/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php b/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php index 72134fb16912939f5a80e42e8803fd7120e6f3a5..31ce6d550b116455052cf674e99155db3e3f7af2 100644 --- a/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php +++ b/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php @@ -6,20 +6,18 @@ namespace Magento\CatalogSearch\Model\Search; -use Magento\CatalogSearch\Model\Search\TableMapper; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Select; use Magento\Framework\Search\Adapter\Mysql\ConditionManager; use Magento\Framework\Search\Adapter\Mysql\IndexBuilderInterface; use Magento\Framework\Search\Request\Dimension; -use Magento\Framework\Search\Request\Filter\BoolExpression; -use Magento\Framework\Search\Request\FilterInterface; -use Magento\Framework\Search\Request\QueryInterface as RequestQueryInterface; use Magento\Framework\Search\RequestInterface; use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver; use Magento\Store\Model\ScopeInterface; use Magento\Store\Model\StoreManagerInterface; +use Magento\CatalogInventory\Api\StockConfigurationInterface; +use Magento\CatalogInventory\Model\Stock; use Magento\Framework\App\ScopeResolverInterface; /** @@ -40,6 +38,7 @@ class IndexBuilder implements IndexBuilderInterface /** * @var StoreManagerInterface + * @deprecated */ private $storeManager; @@ -63,6 +62,11 @@ class IndexBuilder implements IndexBuilderInterface */ private $dimensionScopeResolver; + /** + * @var StockConfigurationInterface + */ + private $stockConfiguration; + /** * @param \Magento\Framework\App\ResourceConnection $resource * @param ScopeConfigInterface $config @@ -124,16 +128,30 @@ class IndexBuilder implements IndexBuilderInterface 'search_index.entity_id = stock_index.product_id' . $this->resource->getConnection()->quoteInto( ' AND stock_index.website_id = ?', - $this->storeManager->getWebsite()->getId() + $this->getStockConfiguration()->getDefaultScopeId() ), [] ); - $select->where('stock_index.stock_status = ?', 1); + $select->where('stock_index.stock_status = ?', Stock::DEFAULT_STOCK_ID); } return $select; } + /** + * @return StockConfigurationInterface + * + * @deprecated + */ + private function getStockConfiguration() + { + if ($this->stockConfiguration === null) { + $this->stockConfiguration = \Magento\Framework\App\ObjectManager::getInstance() + ->get('Magento\CatalogInventory\Api\StockConfigurationInterface'); + } + return $this->stockConfiguration; + } + /** * Add filtering by dimensions * diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php index 73dfd3867b0dcaf870794e6195d508309f440600..32176594936b2d996b1e14c758cf0671c76a73f5 100644 --- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php @@ -40,6 +40,9 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Search\Model\IndexScopeResolver|\PHPUnit_Framework_MockObject_MockObject */ private $resource; + /** @var \Magento\CatalogInventory\Api\StockConfigurationInterface|MockObject */ + private $stockConfiguration; + /** * @var \Magento\CatalogSearch\Model\Search\IndexBuilder */ @@ -55,6 +58,10 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase */ private $scopeInterface; + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @return void + */ protected function setUp() { $this->select = $this->getMockBuilder('\Magento\Framework\DB\Select') @@ -139,6 +146,9 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase '', false ); + $this->stockConfiguration = $this + ->getMockBuilder('\Magento\CatalogInventory\Api\StockConfigurationInterface') + ->getMock(); $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->target = $objectManagerHelper->getObject( @@ -153,6 +163,12 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase '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); } public function testBuildWithOutOfStock() @@ -198,15 +214,13 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase $this->mockBuild($index, $tableSuffix, false); + $this->stockConfiguration->expects($this->once())->method('getDefaultScopeId')->willReturn(1); $this->config->expects($this->once()) ->method('isSetFlag') ->with('cataloginventory/options/show_out_of_stock') ->will($this->returnValue(false)); $this->connection->expects($this->once())->method('quoteInto') ->with(' AND stock_index.website_id = ?', 1)->willReturn(' AND stock_index.website_id = 1'); - $website = $this->getMockBuilder('Magento\Store\Model\Website')->disableOriginalConstructor()->getMock(); - $website->expects($this->once())->method('getId')->willReturn(1); - $this->storeManager->expects($this->once())->method('getWebsite')->willReturn($website); $this->select->expects($this->at(2)) ->method('where') ->with('(someName=someValue)') diff --git a/app/code/Magento/CatalogSearch/composer.json b/app/code/Magento/CatalogSearch/composer.json index 709009300b724a41dbca6c80773684af9c15e91e..860d5080b9bdffd0282c5b989c8373b886d498af 100644 --- a/app/code/Magento/CatalogSearch/composer.json +++ b/app/code/Magento/CatalogSearch/composer.json @@ -11,6 +11,7 @@ "magento/module-eav": "100.0.*", "magento/module-backend": "100.0.*", "magento/module-theme": "100.0.*", + "magento/module-catalog-inventory": "100.0.*", "magento/framework": "100.0.*" }, "type": "magento2-module", diff --git a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php index 386e77580fa4abab025f3119b056f08b2be88084..6f2cd40e97f7ad19fb5cd217881403a11a594268 100644 --- a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php +++ b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php @@ -71,7 +71,9 @@ class Combine extends \Magento\Rule\Model\Condition\Combine */ public function collectValidatedAttributes($productCollection) { + $alias = array_keys($productCollection->getSelect()->getPart('from'))[0]; foreach ($this->getConditions() as $condition) { + $condition->setData('attribute', $alias . '.' . $condition->getData('attribute')); $condition->addToCollection($productCollection); } return $this; diff --git a/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php b/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php index 34c14626d8bf7423d435c62e952c663a8b52f9ae..b0a3fdab8eb32c6c97ef798a94390f7a942f04a2 100644 --- a/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php +++ b/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php @@ -73,8 +73,13 @@ class CombineTest extends \PHPUnit_Framework_TestCase public function testCollectValidatedAttributes() { $collection = $this->getMockBuilder('\Magento\Catalog\Model\ResourceModel\Product\Collection') - ->disableOriginalConstructor() + ->disableOriginalConstructor()->setMethods(['getSelect']) + ->getMock(); + $select = $this->getMockBuilder('\Magento\Framework\DB\Select') + ->disableOriginalConstructor()->setMethods(['getPart']) ->getMock(); + $select->expects($this->any())->method('getPart')->with('from')->willReturn(['alias_table' => 'table_name']); + $collection->expects($this->any())->method('getSelect')->willReturn($select); $condition = $this->getMockBuilder('Magento\CatalogWidget\Model\Rule\Condition\Combine') ->disableOriginalConstructor()->setMethods(['addToCollection']) ->getMock(); diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_edit.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_edit.xml index dbc98c4b59d52a82d3af8c01851f7ac9625e6f22..2b57747de4fcaee6268c3e77d800f45df7a95549 100644 --- a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_edit.xml +++ b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_edit.xml @@ -6,7 +6,6 @@ */ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> - <update handle="styles"/> <body> <referenceContainer name="content"> <uiComponent name="cms_page_form"/> diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php index 2fc849be10f10988356b977298168173a18a4f7b..fc496b83febb52d1ce0eaaa400e0d1faf65c8d8a 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php @@ -509,8 +509,8 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType ->addAttributeToSelect('name') ->addAttributeToSelect('price') ->addAttributeToSelect('weight') -// ->addAttributeToSelect('msrp') -// ->addAttributeToSelect('media_gallery') + ->addAttributeToSelect('image') + ->addAttributeToSelect('status') ->addFilterByRequiredOptions() ->setStoreId($product->getStoreId()); diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php index 551df288ebcb03e2941a618ec28e667265b0af99..6f2b989e5e9bfaa9fa91643b1958be6a99c0fdc1 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php @@ -28,19 +28,11 @@ class Configurable extends \Magento\CatalogInventory\Model\ResourceModel\Indexer $metadata = $this->getMetadataPool()->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class); $connection = $this->getConnection(); $idxTable = $usePrimaryTable ? $this->getMainTable() : $this->getIdxTable(); - $select = $connection->select()->from(['e' => $this->getTable('catalog_product_entity')], ['entity_id']); - $this->_addWebsiteJoinToSelect($select, true); - $this->_addProductWebsiteJoinToSelect($select, 'cw.website_id', 'e.entity_id'); - $select->columns( - 'cw.website_id' - )->join( - ['cis' => $this->getTable('cataloginventory_stock')], - '', - ['stock_id'] - )->joinLeft( - ['cisi' => $this->getTable('cataloginventory_stock_item')], - 'cisi.stock_id = cis.stock_id AND cisi.product_id = e.entity_id', - [] + $select = parent::_getStockStatusSelect($entityIds, $usePrimaryTable); + $select->reset( + \Magento\Framework\DB\Select::COLUMNS + )->columns( + ['e.entity_id', 'cis.website_id', 'cis.stock_id'] )->joinLeft( ['l' => $this->getTable('catalog_product_super_link')], 'l.parent_id = e.' . $metadata->getLinkField(), @@ -51,24 +43,14 @@ class Configurable extends \Magento\CatalogInventory\Model\ResourceModel\Indexer [] )->joinLeft( ['i' => $idxTable], - 'i.product_id = l.product_id AND cw.website_id = i.website_id AND cis.stock_id = i.stock_id', + 'i.product_id = l.product_id AND cis.website_id = i.website_id AND cis.stock_id = i.stock_id', [] )->columns( ['qty' => new \Zend_Db_Expr('0')] - )->where( - 'cw.website_id != 0' - )->where( - 'e.type_id = ?', - $this->getTypeId() - )->group( - ['e.entity_id', 'cw.website_id', 'cis.stock_id'] ); - $psExpr = $this->_addAttributeToSelect($select, 'status', 'e.' . $metadata->getLinkField(), 'cs.store_id'); - $psCond = $connection->quoteInto($psExpr . '=?', ProductStatus::STATUS_ENABLED); - $statusExpr = $this->getStatusExpression($connection); - $optExpr = $connection->getCheckSql("{$psCond} AND le.required_options = 0", 'i.stock_status', 0); + $optExpr = $connection->getCheckSql("le.required_options = 0", 'i.stock_status', 0); $stockStatusExpr = $connection->getLeastSql(["MAX({$optExpr})", "MIN({$statusExpr})"]); $select->columns(['status' => $stockStatusExpr]); diff --git a/app/code/Magento/Downloadable/view/adminhtml/web/js/components/is-downloadable-handler.js b/app/code/Magento/Downloadable/view/adminhtml/web/js/components/is-downloadable-handler.js index 5e619b76c7ecd8ba22fd1e8ff3f25786ac93d33e..8fc6508cd877d752eb94640abeebbc895ec1a716 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/web/js/components/is-downloadable-handler.js +++ b/app/code/Magento/Downloadable/view/adminhtml/web/js/components/is-downloadable-handler.js @@ -22,7 +22,7 @@ define([ * Change visibility for samplesFieldset & linksFieldset based on current statuses of checkbox. */ changeVisibility: function () { - if (this.samplesFieldset && this.linksFieldset) { + if (this.samplesFieldset() && this.linksFieldset()) { if (this.checked() && !this.disabled()) { this.samplesFieldset().visible(true); this.linksFieldset().visible(true); diff --git a/app/code/Magento/GroupedProduct/Model/ResourceModel/Indexer/Stock/Grouped.php b/app/code/Magento/GroupedProduct/Model/ResourceModel/Indexer/Stock/Grouped.php index 9587a195b5e7c67d06f8a76b89d6957b5d62c403..8a3f0f1d0e900a5f4d3283076bb6ed8831c9f47a 100644 --- a/app/code/Magento/GroupedProduct/Model/ResourceModel/Indexer/Stock/Grouped.php +++ b/app/code/Magento/GroupedProduct/Model/ResourceModel/Indexer/Stock/Grouped.php @@ -26,23 +26,12 @@ class Grouped extends \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stoc { $connection = $this->getConnection(); $idxTable = $usePrimaryTable ? $this->getMainTable() : $this->getIdxTable(); - $select = $connection->select()->from( - ['e' => $this->getTable('catalog_product_entity')], - ['entity_id'] - ); - $this->_addWebsiteJoinToSelect($select, true); - $this->_addProductWebsiteJoinToSelect($select, 'cw.website_id', 'e.entity_id'); $metadata = $this->getMetadataPool()->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class); - $select->columns( - 'cw.website_id' - )->join( - ['cis' => $this->getTable('cataloginventory_stock')], - '', - ['stock_id'] - )->joinLeft( - ['cisi' => $this->getTable('cataloginventory_stock_item')], - 'cisi.stock_id = cis.stock_id AND cisi.product_id = e.entity_id', - [] + $select = parent::_getStockStatusSelect($entityIds, $usePrimaryTable); + $select->reset( + \Magento\Framework\DB\Select::COLUMNS + )->columns( + ['e.entity_id', 'cis.website_id', 'cis.stock_id'] )->joinLeft( ['l' => $this->getTable('catalog_product_link')], 'e.' . $metadata->getLinkField() . ' = l.product_id AND l.link_type_id=' . @@ -54,31 +43,15 @@ class Grouped extends \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stoc [] )->joinLeft( ['i' => $idxTable], - 'i.product_id = l.linked_product_id AND cw.website_id = i.website_id AND cis.stock_id = i.stock_id', + 'i.product_id = l.linked_product_id AND cis.website_id = i.website_id AND cis.stock_id = i.stock_id', [] )->columns( ['qty' => new \Zend_Db_Expr('0')] - )->where( - 'cw.website_id != 0' - )->where( - 'e.type_id = ?', - $this->getTypeId() - )->group( - ['e.entity_id', 'cw.website_id', 'cis.stock_id'] - ); - - // add limitation of status - $productStatusExpr = $this->_addAttributeToSelect( - $select, - 'status', - 'e.' . $metadata->getLinkField(), - 'cs.store_id' ); - $productStatusCond = $connection->quoteInto($productStatusExpr . '=?', ProductStatus::STATUS_ENABLED); $statusExpression = $this->getStatusExpression($connection); - $optExpr = $connection->getCheckSql("{$productStatusCond} AND le.required_options = 0", 'i.stock_status', 0); + $optExpr = $connection->getCheckSql("le.required_options = 0", 'i.stock_status', 0); $stockStatusExpr = $connection->getLeastSql(["MAX({$optExpr})", "MIN({$statusExpression})"]); $select->columns(['status' => $stockStatusExpr]); diff --git a/app/code/Magento/Theme/Block/Html/Topmenu.php b/app/code/Magento/Theme/Block/Html/Topmenu.php index d0205f51453bc4d003e6347af7b5754ac40d6d4c..52a4714fea8db053b49790a548538644866744cc 100644 --- a/app/code/Magento/Theme/Block/Html/Topmenu.php +++ b/app/code/Magento/Theme/Block/Html/Topmenu.php @@ -330,7 +330,9 @@ class Topmenu extends Template implements IdentityInterface */ public function addIdentity($identity) { - $this->identities[] = $identity; + if (!in_array($identity, $this->identities)) { + $this->identities[] = $identity; + } } /** @@ -364,4 +366,14 @@ class Topmenu extends Template implements IdentityInterface { return array_merge(parent::getCacheTags(), $this->getIdentities()); } + + /** + * Get menu object. + * + * @return Node + */ + public function getMenu() + { + return $this->_menu; + } } diff --git a/app/code/Magento/Ui/view/base/templates/stepswizard.phtml b/app/code/Magento/Ui/view/base/templates/stepswizard.phtml index b6f74dda267eb9dcbf30932a6659989a934b8046..82cc34b42b12088f781629fac0a8a53948437d0e 100644 --- a/app/code/Magento/Ui/view/base/templates/stepswizard.phtml +++ b/app/code/Magento/Ui/view/base/templates/stepswizard.phtml @@ -64,7 +64,7 @@ "component": "Magento_Ui/js/lib/step-wizard", "initData": <?= /* @escapeNotVerified */ $this->helper("Magento\Framework\Json\Helper\Data")->jsonEncode($block->getInitData()) ?>, "stepsNames": <?= /* @escapeNotVerified */ $this->helper("Magento\Framework\Json\Helper\Data")->jsonEncode($block->getStepComponents()) ?>, - "modalClass": "<?= /* @noEscape */ $block->getData('config/modal')?>" + "modalClass": "<?= /* @noEscape */ $block->getData('config/dataScope')?>" } } } diff --git a/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php b/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php index d5c0bcc678f6a4af813fe88d6f2419f9561a5134..038f5cdcfc444802259049eac10e371fba17edec 100644 --- a/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php +++ b/app/code/Magento/Webapi/Model/Soap/Wsdl/Generator.php @@ -12,6 +12,7 @@ use Magento\Webapi\Model\Soap\Wsdl; use Magento\Webapi\Model\Soap\WsdlFactory; use Magento\Framework\Webapi\Authorization; use Magento\Webapi\Model\ServiceMetadata; +use Magento\Framework\Exception\AuthorizationException; /** * WSDL generator. @@ -364,4 +365,21 @@ class Generator extends AbstractSchemaGenerator { return $this->serviceMetadata->getServiceMetadata($serviceName); } + + /** + * {@inheritdoc} + */ + protected function getAllowedServicesMetadata($requestedServices) + { + $allowedServicesMetadata = parent::getAllowedServicesMetadata($requestedServices); + if (!$allowedServicesMetadata) { + throw new AuthorizationException( + __( + AuthorizationException::NOT_AUTHORIZED, + ['resources' => implode(', ', $requestedServices)] + ) + ); + } + return $allowedServicesMetadata; + } } diff --git a/app/code/Magento/Widget/Model/Widget.php b/app/code/Magento/Widget/Model/Widget.php index fbf2485d37542a489d3a8e6b8bf447a6d94e81c5..2235df9aff0772f05eb7ea71d0ebf60010893570 100644 --- a/app/code/Magento/Widget/Model/Widget.php +++ b/app/code/Magento/Widget/Model/Widget.php @@ -309,7 +309,7 @@ class Widget } elseif (trim($value) == '') { $widget = $this->getConfigAsObject($type); $parameters = $widget->getParameters(); - if (is_object($parameters[$name])) { + if (isset($parameters[$name]) && is_object($parameters[$name])) { $value = $parameters[$name]->getValue(); } } diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php index eff0dbba735f6295e4084f10bb8228f56ee04539..88d4e559e16d52967f1d452bfd95791765cd1255 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/BaseService.php @@ -25,7 +25,7 @@ abstract class BaseService extends \Magento\TestFramework\TestCase\WebapiAbstrac $this->_assertSoapException( $serviceInfo, $requestData, - 'SOAP-ERROR: Parsing WSDL: Couldn\'t bind to service' + 'Consumer is not authorized to access %resources' ); } elseif (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) { $this->_assertRestUnauthorizedException($serviceInfo, $requestData); @@ -111,7 +111,7 @@ abstract class BaseService extends \Magento\TestFramework\TestCase\WebapiAbstrac } if ($expectedMessage) { - $this->assertEquals($expectedMessage, $e->getMessage()); + $this->assertContains($expectedMessage, $e->getMessage()); } } } diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php index c7ef1d00e02fad6a9311240065b3c32a247e2065..8cd95ef23a47e75b7915e7c114c1968833d81125 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/Routing/SoapErrorHandlingTest.php @@ -110,8 +110,8 @@ class SoapErrorHandlingTest extends \Magento\TestFramework\TestCase\WebapiAbstra } catch (\SoapFault $e) { $this->checkSoapFault( $e, - 'SOAP-ERROR: Parsing WSDL: Couldn\'t bind to service', - 'WSDL' + 'Consumer is not authorized to access %resources', + 'env:Sender' ); } } diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php index 2593e9d12f5f94c4e18f12e3f9720747994e1b56..9afdb1f26067a769726fd4d44f235d3c5958ba48 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/WsdlGenerationFromDataObjectTest.php @@ -65,6 +65,16 @@ class WsdlGenerationFromDataObjectTest extends \Magento\TestFramework\TestCase\W $this->_checkFaultsDeclaration($wsdlContent); } + public function testNoAuthorizedServices() + { + $wsdlUrl = $this->_getBaseWsdlUrl() . 'testModule5AllSoapAndRestV2'; + $connection = curl_init($wsdlUrl); + curl_setopt($connection, CURLOPT_RETURNTRANSFER, 1); + $responseContent = curl_exec($connection); + $this->assertEquals(curl_getinfo($connection, CURLINFO_HTTP_CODE), 401); + $this->assertContains("Consumer is not authorized to access %resources", $responseContent); + } + public function testInvalidWsdlUrlNoServices() { $responseContent = $this->_getWsdlContent($this->_getBaseWsdlUrl()); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/_files/products_advanced.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/_files/products_advanced.php index 8146a04b34398a758c815c787feb9cfe047c786d..2ae37ed9b71946b9924064a3cd1fa0a30e6b3c88 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/_files/products_advanced.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/_files/products_advanced.php @@ -80,6 +80,11 @@ foreach ($prices as $price) { 'simple-' . $productId )->setPrice( $price + )->setStockData( + [ + 'qty' => 100, + 'is_in_stock' => 1, + ] )->setWeight( 18 )->setCategoryIds( diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php index 4992805824538bc35ec803abea5056b6456bb134..7ec85f110a5b58bc9c721593e50e2c6fb4fbb682 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_virtual.php @@ -16,4 +16,9 @@ $product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL) ->setTaxClassId(0) ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->save(); + ->setStockData( + [ + 'qty' => 100, + 'is_in_stock' => 1, + ] + )->save(); diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/ManagestockTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/ManagestockTest.php deleted file mode 100644 index 12aae4429203d85c9095ba607dfe25f620852353..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/Config/Backend/ManagestockTest.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\CatalogInventory\Model\Config\Backend; - -use Magento\TestFramework\Helper\Bootstrap as Bootstrap; - -/** - * Class ManagestockTest - */ -class ManagestockTest extends \PHPUnit_Framework_TestCase -{ - /** - * Data provider for testSaveAndRebuildIndex - * @return array - */ - public function saveAndRebuildIndexDataProvider() - { - return [ - [1, 1], - [0, 0], - ]; - } - - /** - * Test rebuild stock indexer on stock status config save - * - * @dataProvider saveAndRebuildIndexDataProvider - * - * @magentoAppIsolation enabled - * @magentoDbIsolation enabled - * @magentoConfigFixture default/cataloginventory/item_options/manage_stock 0 - * - * @param int $newStockValue new value for stock status - * @param int $callCount count matcher - */ - public function testSaveAndRebuildIndex($newStockValue, $callCount) - { - /** @var \Magento\CatalogInventory\Model\StockIndex */ - $stockManagement = $this->getMock( - '\Magento\CatalogInventory\Model\StockIndex', - ['rebuild'], - [], - '', - false - ); - - $stockManagement->expects($this->exactly($callCount)) - ->method('rebuild'); - - $manageStock = new Managestock( - Bootstrap::getObjectManager()->get('Magento\Framework\Model\Context'), - Bootstrap::getObjectManager()->get('Magento\Framework\Registry'), - Bootstrap::getObjectManager()->get('Magento\Framework\App\Config\ScopeConfigInterface'), - Bootstrap::getObjectManager()->get('Magento\Framework\App\Cache\TypeListInterface'), - $stockManagement, - Bootstrap::getObjectManager()->get('Magento\CatalogInventory\Model\Indexer\Stock\Processor'), - Bootstrap::getObjectManager()->get('Magento\Config\Model\ResourceModel\Config') - ); - - $manageStock->setPath('cataloginventory/item_options/manage_stock'); - $manageStock->setScope('default'); - $manageStock->setScopeId(0); - $manageStock->setValue($newStockValue); - - // assert - $manageStock->save(); - } -} diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStockTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStockTest.php index 8fbcad5267cf774401910a63b7dcf7b2c8bcd427..02ddb8e23b9924bc2acd357831724196ae1fbcf8 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStockTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/ResourceModel/Indexer/Stock/DefaultStockTest.php @@ -17,12 +17,19 @@ class DefaultStockTest extends \PHPUnit_Framework_TestCase */ private $indexer; + /** + * @var \Magento\CatalogInventory\Api\StockConfigurationInterface + */ + private $stockConfiguration; + protected function setUp() { $this->indexer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\DefaultStock::class ); - + $this->stockConfiguration = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\CatalogInventory\Api\StockConfigurationInterface::class + ); } /** @@ -53,7 +60,7 @@ class DefaultStockTest extends \PHPUnit_Framework_TestCase ); $criteria = $criteriaFactory->create(); $criteria->setProductsFilter([$product->getId()]); - $criteria->addFilter('website', 'website_id', $testWebsite->getId()); + $criteria->addFilter('website', 'website_id', $this->stockConfiguration->getDefaultScopeId()); $items = $stockStatusRepository->getList($criteria)->getItems(); $this->assertEquals($product->getId(), $items[$product->getId()]->getProductId()); } diff --git a/dev/tests/integration/testsuite/Magento/Downloadable/_files/product_downloadable.php b/dev/tests/integration/testsuite/Magento/Downloadable/_files/product_downloadable.php index 7ccfba9b3c1b7cf743cfeb30512ffc11902ddf80..4c15a2a9e08877c2b3516ad86f5458df7ed5acd3 100644 --- a/dev/tests/integration/testsuite/Magento/Downloadable/_files/product_downloadable.php +++ b/dev/tests/integration/testsuite/Magento/Downloadable/_files/product_downloadable.php @@ -17,7 +17,13 @@ $product ->setPrice(10) ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setLinksPurchasedSeparately(true); + ->setLinksPurchasedSeparately(true) + ->setStockData( + [ + 'qty' => 100, + 'is_in_stock' => 1, + ] + ); /** * @var \Magento\Downloadable\Api\Data\LinkInterfaceFactory $linkFactory diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php index c94078c41d741682c467819a704610ec5cdad799..8fb3c96eae0b5993b4ec93b3eac13cfccb2de97e 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php @@ -28,7 +28,12 @@ $product->setTypeId('simple') ->setPrice(10) ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->save(); + ->setStockData( + [ + 'qty' => 100, + 'is_in_stock' => 1, + ] + )->save(); $product->load(1); $billingData = [ diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quote.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote.php index 2304dcdc21399e3dbe7936c83fc880ab06b38139..95f387213d16ccb97ffb4d41321cd2aa941f8fef 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/quote.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote.php @@ -17,7 +17,12 @@ $product->setTypeId('simple') ->setMetaDescription('meta description') ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->save(); + ->setStockData( + [ + 'qty' => 100, + 'is_in_stock' => 1, + ] + )->save(); $productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create('Magento\Catalog\Api\ProductRepositoryInterface'); diff --git a/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php index bad169e114754ee24dd850c636b2f27b3e9e76d0..ee5a42069fb0cca56c7bac2065ec7f3ac6607182 100644 --- a/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php +++ b/setup/src/Magento/Setup/Module/Di/Code/Reader/ClassesScanner.php @@ -6,7 +6,7 @@ namespace Magento\Setup\Module\Di\Code\Reader; use Magento\Framework\Exception\FileSystemException; -use Zend\Code\Scanner\FileScanner; +use Magento\Setup\Module\Di\Code\Reader\FileScanner; class ClassesScanner implements ClassesScannerInterface { diff --git a/setup/src/Magento/Setup/Module/Di/Code/Reader/FileScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Reader/FileScanner.php new file mode 100644 index 0000000000000000000000000000000000000000..5293b782064242a571cb7580835abb6586d2a454 --- /dev/null +++ b/setup/src/Magento/Setup/Module/Di/Code/Reader/FileScanner.php @@ -0,0 +1,367 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +namespace Magento\Setup\Module\Di\Code\Reader; + +/** + * @SuppressWarnings(PHPMD) + */ +class FileScanner extends \Zend\Code\Scanner\FileScanner +{ + /** + * @var int + */ + private $tokenType; + + /** + * {@inheritdoc} + */ + protected function scan() + { + if ($this->isScanned) { + return; + } + + if (!$this->tokens) { + throw new \Zend\Code\Exception\RuntimeException('No tokens were provided'); + } + + /** + * Define PHP 5.4 'trait' token constant. + */ + if (!defined('T_TRAIT')) { + define('T_TRAIT', 42001); + } + + /** + * Variables & Setup + */ + + $tokens = &$this->tokens; // localize + $infos = &$this->infos; // localize + $tokenIndex = null; + $token = null; + $this->tokenType = null; + $tokenContent = null; + $tokenLine = null; + $namespace = null; + $docCommentIndex = false; + $infoIndex = 0; + + /* + * MACRO creation + */ + $MACRO_TOKEN_ADVANCE = function () use (&$tokens, &$tokenIndex, &$token, &$tokenContent, &$tokenLine) { + $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1; + if (!isset($tokens[$tokenIndex])) { + $token = false; + $tokenContent = false; + $this->tokenType = false; + $tokenLine = false; + + return false; + } + if (is_string($tokens[$tokenIndex]) && $tokens[$tokenIndex] === '"') { + do { + $tokenIndex++; + } while (!(is_string($tokens[$tokenIndex]) && $tokens[$tokenIndex] === '"')); + } + $token = $tokens[$tokenIndex]; + if (is_array($token)) { + list($this->tokenType, $tokenContent, $tokenLine) = $token; + } else { + $this->tokenType = null; + $tokenContent = $token; + } + + return $tokenIndex; + }; + $MACRO_TOKEN_LOGICAL_START_INDEX = function () use (&$tokenIndex, &$docCommentIndex) { + return ($docCommentIndex === false) ? $tokenIndex : $docCommentIndex; + }; + $MACRO_DOC_COMMENT_START = function () use (&$tokenIndex, &$docCommentIndex) { + $docCommentIndex = $tokenIndex; + + return $docCommentIndex; + }; + $MACRO_DOC_COMMENT_VALIDATE = function () use (&$docCommentIndex) { + static $validTrailingTokens = null; + if ($validTrailingTokens === null) { + $validTrailingTokens = array(T_WHITESPACE, T_FINAL, T_ABSTRACT, T_INTERFACE, T_CLASS, T_FUNCTION); + } + if ($docCommentIndex !== false && !in_array($this->tokenType, $validTrailingTokens)) { + $docCommentIndex = false; + } + + return $docCommentIndex; + }; + $MACRO_INFO_ADVANCE = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) { + $infos[$infoIndex]['tokenEnd'] = $tokenIndex; + $infos[$infoIndex]['lineEnd'] = $tokenLine; + $infoIndex++; + + return $infoIndex; + }; + + /** + * START FINITE STATE MACHINE FOR SCANNING TOKENS + */ + + // Initialize token + $MACRO_TOKEN_ADVANCE(); + + SCANNER_TOP: + + if ($token === false) { + goto SCANNER_END; + } + + // Validate current doc comment index + $MACRO_DOC_COMMENT_VALIDATE(); + + switch ($this->tokenType) { + + case T_DOC_COMMENT: + + $MACRO_DOC_COMMENT_START(); + goto SCANNER_CONTINUE; + //goto no break needed + + case T_NAMESPACE: + + $infos[$infoIndex] = array( + 'type' => 'namespace', + 'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(), + 'tokenEnd' => null, + 'lineStart' => $token[2], + 'lineEnd' => null, + 'namespace' => null, + ); + + // start processing with next token + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + + SCANNER_NAMESPACE_TOP: + + if ($this->tokenType === null && $tokenContent === ';' || $tokenContent === '{') { + goto SCANNER_NAMESPACE_END; + } + + if ($this->tokenType === T_WHITESPACE) { + goto SCANNER_NAMESPACE_CONTINUE; + } + + if ($this->tokenType === T_NS_SEPARATOR || $this->tokenType === T_STRING) { + $infos[$infoIndex]['namespace'] .= $tokenContent; + } + + SCANNER_NAMESPACE_CONTINUE: + + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + goto SCANNER_NAMESPACE_TOP; + + SCANNER_NAMESPACE_END: + + $namespace = $infos[$infoIndex]['namespace']; + + $MACRO_INFO_ADVANCE(); + goto SCANNER_CONTINUE; + //goto no break needed + + case T_USE: + + $infos[$infoIndex] = array( + 'type' => 'use', + 'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(), + 'tokenEnd' => null, + 'lineStart' => $tokens[$tokenIndex][2], + 'lineEnd' => null, + 'namespace' => $namespace, + 'statements' => array(0 => array('use' => null, + 'as' => null)), + ); + + $useStatementIndex = 0; + $useAsContext = false; + + // start processing with next token + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + + SCANNER_USE_TOP: + + if ($this->tokenType === null) { + if ($tokenContent === ';') { + goto SCANNER_USE_END; + } elseif ($tokenContent === ',') { + $useAsContext = false; + $useStatementIndex++; + $infos[$infoIndex]['statements'][$useStatementIndex] = array('use' => null, + 'as' => null); + } + } + + // ANALYZE + if ($this->tokenType !== null) { + if ($this->tokenType == T_AS) { + $useAsContext = true; + goto SCANNER_USE_CONTINUE; + } + + if ($this->tokenType == T_NS_SEPARATOR || $this->tokenType == T_STRING) { + if ($useAsContext == false) { + $infos[$infoIndex]['statements'][$useStatementIndex]['use'] .= $tokenContent; + } else { + $infos[$infoIndex]['statements'][$useStatementIndex]['as'] = $tokenContent; + } + } + } + + SCANNER_USE_CONTINUE: + + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + goto SCANNER_USE_TOP; + + SCANNER_USE_END: + + $MACRO_INFO_ADVANCE(); + goto SCANNER_CONTINUE; + //goto no break needed + + case T_INCLUDE: + case T_INCLUDE_ONCE: + case T_REQUIRE: + case T_REQUIRE_ONCE: + + // Static for performance + static $includeTypes = array( + T_INCLUDE => 'include', + T_INCLUDE_ONCE => 'include_once', + T_REQUIRE => 'require', + T_REQUIRE_ONCE => 'require_once' + ); + + $infos[$infoIndex] = array( + 'type' => 'include', + 'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(), + 'tokenEnd' => null, + 'lineStart' => $tokens[$tokenIndex][2], + 'lineEnd' => null, + 'includeType' => $includeTypes[$tokens[$tokenIndex][0]], + 'path' => '', + ); + + // start processing with next token + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + + SCANNER_INCLUDE_TOP: + + if ($this->tokenType === null && $tokenContent === ';') { + goto SCANNER_INCLUDE_END; + } + + $infos[$infoIndex]['path'] .= $tokenContent; + + SCANNER_INCLUDE_CONTINUE: + + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + goto SCANNER_INCLUDE_TOP; + + SCANNER_INCLUDE_END: + + $MACRO_INFO_ADVANCE(); + goto SCANNER_CONTINUE; + //goto no break needed + + case T_FUNCTION: + case T_FINAL: + case T_ABSTRACT: + case T_CLASS: + case T_INTERFACE: + case T_TRAIT: + + $infos[$infoIndex] = array( + 'type' => ($this->tokenType === T_FUNCTION) ? 'function' : 'class', + 'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(), + 'tokenEnd' => null, + 'lineStart' => $tokens[$tokenIndex][2], + 'lineEnd' => null, + 'namespace' => $namespace, + 'uses' => $this->getUsesNoScan($namespace), + 'name' => null, + 'shortName' => null, + ); + + $classBraceCount = 0; + + // start processing with current token + + SCANNER_CLASS_TOP: + + // process the name + if ($infos[$infoIndex]['shortName'] == '' + && (($this->tokenType === T_CLASS || $this->tokenType === T_INTERFACE || $this->tokenType === T_TRAIT) && $infos[$infoIndex]['type'] === 'class' + || ($this->tokenType === T_FUNCTION && $infos[$infoIndex]['type'] === 'function')) + ) { + $infos[$infoIndex]['shortName'] = $tokens[$tokenIndex + 2][1]; + $infos[$infoIndex]['name'] = (($namespace !== null) ? $namespace . '\\' : '') . $infos[$infoIndex]['shortName']; + } + + if ($this->tokenType === null) { + if ($tokenContent == '{') { + $classBraceCount++; + } + if ($tokenContent == '}') { + $classBraceCount--; + if ($classBraceCount === 0) { + goto SCANNER_CLASS_END; + } + } + } + + SCANNER_CLASS_CONTINUE: + + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + goto SCANNER_CLASS_TOP; + + SCANNER_CLASS_END: + + $MACRO_INFO_ADVANCE(); + goto SCANNER_CONTINUE; + + } + + SCANNER_CONTINUE: + + if ($MACRO_TOKEN_ADVANCE() === false) { + goto SCANNER_END; + } + goto SCANNER_TOP; + + SCANNER_END: + + /** + * END FINITE STATE MACHINE FOR SCANNING TOKENS + */ + + $this->isScanned = true; + } +} \ No newline at end of file diff --git a/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php b/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php index 135e03ae69b800d593bf6c0592f7454c7b9f1da2..2d98bc58f789ad4b8476fa057e615c27d7093253 100644 --- a/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php +++ b/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php @@ -123,16 +123,20 @@ class InitParamListener implements ListenerAggregateInterface, FactoryInterface /** @var \Magento\Framework\App\State $adminAppState */ $adminAppState = $objectManager->get('Magento\Framework\App\State'); $adminAppState->setAreaCode(\Magento\Framework\App\Area::AREA_ADMIN); + /** @var \Magento\Backend\Model\Session\AdminConfig $sessionConfig */ + $sessionConfig = $objectManager->get(\Magento\Backend\Model\Session\AdminConfig::class); + $cookiePath = $this->getSetupCookiePath($objectManager); + $sessionConfig->setCookiePath($cookiePath); /** @var \Magento\Backend\Model\Auth\Session $adminSession */ $adminSession = $objectManager->create( \Magento\Backend\Model\Auth\Session::class, [ - 'sessionConfig' => $objectManager->get(\Magento\Backend\Model\Session\AdminConfig::class), + 'sessionConfig' => $sessionConfig, 'appState' => $adminAppState ] ); if (!$objectManager->get(\Magento\Backend\Model\Auth::class)->isLoggedIn()) { - $adminSession->expireSessionCookie(); + $adminSession->destroy(); $response = $event->getResponse(); $response->getHeaders()->addHeaderLine('Location', 'index.php/session/unlogin'); $response->setStatusCode(302); @@ -145,6 +149,25 @@ class InitParamListener implements ListenerAggregateInterface, FactoryInterface return false; } + /** + * Get cookie path + * + * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @return string + */ + private function getSetupCookiePath(\Magento\Framework\ObjectManagerInterface $objectManager) + { + /** @var \Magento\Backend\App\BackendAppList $backendAppList */ + $backendAppList = $objectManager->get(\Magento\Backend\App\BackendAppList::class); + $backendApp = $backendAppList->getBackendApp('setup'); + /** @var \Magento\Backend\Model\UrlFactory $backendUrlFactory */ + $backendUrlFactory = $objectManager->get(\Magento\Backend\Model\UrlFactory::class); + $baseUrl = parse_url($backendUrlFactory->create()->getBaseUrl(), PHP_URL_PATH); + $baseUrl = \Magento\Framework\App\Request\Http::getUrlNoScript($baseUrl); + $cookiePath = $baseUrl . $backendApp->getCookiePath(); + return $cookiePath; + } + /** * {@inheritdoc} */