Skip to content

Commit 9c21788

Browse files
committed
Merge branch '2.2-develop' into 11882
2 parents 6730e69 + b05a957 commit 9c21788

File tree

104 files changed

+3067
-963
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+3067
-963
lines changed

app/bootstrap.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,17 @@
4949
unset($_SERVER['ORIG_PATH_INFO']);
5050
}
5151

52-
if (!empty($_SERVER['MAGE_PROFILER'])
52+
if (
53+
(!empty($_SERVER['MAGE_PROFILER']) || file_exists(BP . '/var/profiler.flag'))
5354
&& isset($_SERVER['HTTP_ACCEPT'])
5455
&& strpos($_SERVER['HTTP_ACCEPT'], 'text/html') !== false
5556
) {
57+
$profilerFlag = isset($_SERVER['MAGE_PROFILER']) && strlen($_SERVER['MAGE_PROFILER'])
58+
? $_SERVER['MAGE_PROFILER']
59+
: trim(file_get_contents(BP . '/var/profiler.flag'));
60+
5661
\Magento\Framework\Profiler::applyConfig(
57-
$_SERVER['MAGE_PROFILER'],
62+
$profilerFlag,
5863
BP,
5964
!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'
6065
);

app/code/Magento/Backend/view/adminhtml/templates/admin/access_denied.phtml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
?>
1010
<?php
1111
/**
12-
* @see \Magento\Backend\Block\Template
12+
* @see \Magento\Backend\Block\Denied
1313
*/
1414
?>
1515
<hr class="access-denied-hr"/>
@@ -21,8 +21,13 @@
2121
<li><span><?= $block->escapeHtml(__('Contact a system administrator or store owner to gain permissions.')) ?></span></li>
2222
<li>
2323
<span><?= $block->escapeHtml(__('Return to ')) ?>
24-
<a href="<?= $block->escapeHtmlAttr(__('javascript:history.back()')) ?>">
25-
<?= $block->escapeHtml(__('previous page')) ?></a><?= $block->escapeHtml(__('.')) ?>
24+
<?php if(isset($_SERVER['HTTP_REFERER'])): ?>
25+
<a href="<?= $block->escapeUrl(__($_SERVER['HTTP_REFERER'])) ?>">
26+
<?= $block->escapeHtml(__('previous page')) ?></a><?= $block->escapeHtml(__('.')) ?>
27+
<?php else: ?>
28+
<a href="<?= $block->escapeHtmlAttr(__('javascript:history.back()')) ?>">
29+
<?= $block->escapeHtml(__('previous page')) ?></a><?= $block->escapeHtml(__('.')) ?>
30+
<?php endif ?>
2631
</span>
2732
</li>
2833
</ul>

app/code/Magento/Catalog/Model/Category/Link/SaveHandler.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,9 @@ private function mergeCategoryLinks($newCategoryPositions, $oldCategoryPositions
119119

120120
if ($key === false) {
121121
$result[] = $newCategoryPosition;
122-
} elseif ($oldCategoryPositions[$key]['position'] != $newCategoryPosition['position']) {
122+
} elseif (isset($oldCategoryPositions[$key])
123+
&& $oldCategoryPositions[$key]['position'] != $newCategoryPosition['position']
124+
) {
123125
$result[] = $newCategoryPositions[$key];
124126
unset($oldCategoryPositions[$key]);
125127
}

app/code/Magento/Catalog/Model/ResourceModel/Config.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,7 @@ public function getAttributesUsedForSortBy()
149149
['main_table' => $this->getTable('eav_attribute')]
150150
)->join(
151151
['additional_table' => $this->getTable('catalog_eav_attribute')],
152-
'main_table.attribute_id = additional_table.attribute_id',
153-
[]
152+
'main_table.attribute_id = additional_table.attribute_id'
154153
)->joinLeft(
155154
['al' => $this->getTable('eav_attribute_label')],
156155
'al.attribute_id = main_table.attribute_id AND al.store_id = ' . $this->getStoreId(),

app/code/Magento/Catalog/Test/Unit/Model/Category/Link/SaveHandlerTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,21 @@ public function getCategoryDataProvider()
197197
],
198198
[], //affected category_ids
199199
],
200+
[
201+
[3], //model category_ids
202+
[
203+
['category_id' => 3, 'position' => 20],
204+
['category_id' => 4, 'position' => 30],
205+
], // dto category links
206+
[
207+
['category_id' => 3, 'position' => 10],
208+
],
209+
[
210+
['category_id' => 3, 'position' => 20],
211+
['category_id' => 4, 'position' => 30],
212+
],
213+
[3, 4], //affected category_ids
214+
],
200215
];
201216
}
202217

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Catalog\Test\Unit\Model\ResourceModel;
8+
9+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
10+
11+
/**
12+
* Test for Magento\Catalog\Model\ResourceModel\Config
13+
*/
14+
class ConfigTest extends \PHPUnit\Framework\TestCase
15+
{
16+
/**
17+
* @var \Magento\Catalog\Model\ResourceModel\Config
18+
*/
19+
private $model;
20+
21+
/**
22+
* @var \PHPUnit_Framework_MockObject_MockObject
23+
*/
24+
private $resource;
25+
26+
/**
27+
* @var \PHPUnit_Framework_MockObject_MockObject
28+
*/
29+
private $storeManager;
30+
31+
/**
32+
* @var \PHPUnit_Framework_MockObject_MockObject
33+
*/
34+
private $eavConfig;
35+
36+
protected function setUp()
37+
{
38+
$objectManager = new ObjectManager($this);
39+
40+
$this->resource = $this->createMock(\Magento\Framework\App\ResourceConnection::class);
41+
$this->storeManager = $this->createMock(\Magento\Store\Model\StoreManagerInterface::class);
42+
$this->eavConfig = $this->createMock(\Magento\Eav\Model\Config::class);
43+
44+
$this->model = $objectManager->getObject(
45+
\Magento\Catalog\Model\ResourceModel\Config::class,
46+
[
47+
'resource' => $this->resource,
48+
'storeManager' => $this->storeManager,
49+
'eavConfig' => $this->eavConfig,
50+
]
51+
);
52+
53+
parent::setUp();
54+
}
55+
56+
public function testGetAttributesUsedForSortBy()
57+
{
58+
$expression = 'someExpression';
59+
$storeId = 1;
60+
$entityTypeId = 4;
61+
62+
$connectionMock = $this->createMock(\Magento\Framework\DB\Adapter\AdapterInterface::class);
63+
$selectMock = $this->createMock(\Magento\Framework\DB\Select::class);
64+
$storeMock = $this->createMock(\Magento\Store\Api\Data\StoreInterface::class);
65+
$entityTypeMock = $this->createMock(\Magento\Eav\Model\Entity\Type::class);
66+
67+
$this->resource->expects($this->atLeastOnce())->method('getConnection')->willReturn($connectionMock);
68+
69+
$connectionMock->expects($this->once())->method('getCheckSql')
70+
->with('al.value IS NULL', 'main_table.frontend_label', 'al.value')
71+
->willReturn($expression);
72+
$connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($selectMock);
73+
74+
$this->resource->expects($this->exactly(3))->method('getTableName')->withConsecutive(
75+
['eav_attribute'],
76+
['catalog_eav_attribute'],
77+
['eav_attribute_label']
78+
)->willReturnOnConsecutiveCalls('eav_attribute', 'catalog_eav_attribute', 'eav_attribute_label');
79+
80+
$this->storeManager->expects($this->once())->method('getStore')->willReturn($storeMock);
81+
$storeMock->expects($this->once())->method('getId')->willReturn($storeId);
82+
83+
$this->eavConfig->expects($this->once())->method('getEntityType')->willReturn($entityTypeMock);
84+
$entityTypeMock->expects($this->once())->method('getId')->willReturn($entityTypeId);
85+
86+
$selectMock->expects($this->once())->method('from')
87+
->with(['main_table' => 'eav_attribute'])->willReturn($selectMock);
88+
$selectMock->expects($this->once())->method('join')->with(
89+
['additional_table' => 'catalog_eav_attribute'],
90+
'main_table.attribute_id = additional_table.attribute_id'
91+
)->willReturn($selectMock);
92+
$selectMock->expects($this->once())->method('joinLeft')
93+
->with(
94+
['al' => 'eav_attribute_label'],
95+
'al.attribute_id = main_table.attribute_id AND al.store_id = ' . $storeId,
96+
['store_label' => $expression]
97+
)->willReturn($selectMock);
98+
$selectMock->expects($this->exactly(2))->method('where')->withConsecutive(
99+
['main_table.entity_type_id = ?', $entityTypeId],
100+
['additional_table.used_for_sort_by = ?', 1]
101+
)->willReturn($selectMock);
102+
103+
$connectionMock->expects($this->once())->method('fetchAll')->with($selectMock);
104+
105+
$this->model->getAttributesUsedForSortBy();
106+
}
107+
}

app/code/Magento/CatalogImportExport/Model/Import/Product.php

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Magento\Catalog\Model\Product\Visibility;
1010
use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface as ValidatorInterface;
1111
use Magento\Framework\App\Filesystem\DirectoryList;
12+
use Magento\Framework\Exception\LocalizedException;
1213
use Magento\Framework\Filesystem;
1314
use Magento\Framework\Model\ResourceModel\Db\ObjectRelationProcessor;
1415
use Magento\Framework\Model\ResourceModel\Db\TransactionManagerInterface;
@@ -712,7 +713,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
712713
* @param \Magento\CatalogInventory\Model\Spi\StockStateProviderInterface $stockStateProvider
713714
* @param \Magento\Catalog\Helper\Data $catalogData
714715
* @param \Magento\ImportExport\Model\Import\Config $importConfig
715-
* @param Proxy\Product\ResourceFactory $resourceFactory
716+
* @param Proxy\Product\ResourceModelFactory $resourceFactory
716717
* @param Product\OptionFactory $optionFactory
717718
* @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $setColFactory
718719
* @param Product\Type\Factory $productTypeFactory
@@ -1084,12 +1085,12 @@ protected function _initTypeModels()
10841085
$params = [$this, $productTypeName];
10851086
if (!($model = $this->_productTypeFactory->create($productTypeConfig['model'], ['params' => $params]))
10861087
) {
1087-
throw new \Magento\Framework\Exception\LocalizedException(
1088+
throw new LocalizedException(
10881089
__('Entity type model \'%1\' is not found', $productTypeConfig['model'])
10891090
);
10901091
}
10911092
if (!$model instanceof \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType) {
1092-
throw new \Magento\Framework\Exception\LocalizedException(
1093+
throw new LocalizedException(
10931094
__(
10941095
'Entity type model must be an instance of '
10951096
. \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType::class
@@ -1551,6 +1552,7 @@ public function getImagesFromRow(array $rowData)
15511552
* @SuppressWarnings(PHPMD.NPathComplexity)
15521553
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
15531554
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
1555+
* @throws LocalizedException
15541556
*/
15551557
protected function _saveProducts()
15561558
{
@@ -1611,7 +1613,7 @@ protected function _saveProducts()
16111613

16121614
// wrong attribute_set_code was received
16131615
if (!$attributeSetId) {
1614-
throw new \Magento\Framework\Exception\LocalizedException(
1616+
throw new LocalizedException(
16151617
__(
16161618
'Wrong attribute set code "%1", please correct it and try again.',
16171619
$rowData['attribute_set_code']
@@ -1998,7 +2000,7 @@ protected function _getUploader()
19982000
}
19992001

20002002
if (!$this->_fileUploader->setTmpDir($tmpPath)) {
2001-
throw new \Magento\Framework\Exception\LocalizedException(
2003+
throw new LocalizedException(
20022004
__('File directory \'%1\' is not readable.', $tmpPath)
20032005
);
20042006
}
@@ -2007,7 +2009,7 @@ protected function _getUploader()
20072009

20082010
$this->_mediaDirectory->create($destinationPath);
20092011
if (!$this->_fileUploader->setDestDir($destinationPath)) {
2010-
throw new \Magento\Framework\Exception\LocalizedException(
2012+
throw new LocalizedException(
20112013
__('File directory \'%1\' is not writable.', $destinationPath)
20122014
);
20132015
}
@@ -2029,6 +2031,7 @@ public function getUploader()
20292031
* Return a new file name if the same file is already exists.
20302032
*
20312033
* @param string $fileName
2034+
* @param bool $renameFileOff
20322035
* @return string
20332036
*/
20342037
protected function uploadMediaFiles($fileName, $renameFileOff = false)
@@ -2753,9 +2756,7 @@ private function _customFieldsMapping($rowData)
27532756
}
27542757

27552758
/**
2756-
* Validate data rows and save bunches to DB
2757-
*
2758-
* @return $this
2759+
* {@inheritdoc}
27592760
*/
27602761
protected function _saveValidatedBunches()
27612762
{

app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ public function prepareAttributesWithDefaultValueForSave(array $rowData, $withDe
534534
public function clearEmptyData(array $rowData)
535535
{
536536
foreach ($this->_getProductAttributes($rowData) as $attrCode => $attrParams) {
537-
if (!$attrParams['is_static'] && empty($rowData[$attrCode])) {
537+
if (!$attrParams['is_static'] && !isset($rowData[$attrCode])) {
538538
unset($rowData[$attrCode]);
539539
}
540540
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\CatalogInventory\Observer;
8+
9+
use Magento\Catalog\Model\Product;
10+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
11+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
12+
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
13+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
14+
use Magento\Framework\Event\Observer;
15+
use Magento\Framework\Event\ObserverInterface;
16+
17+
/**
18+
* Add Stock items to product collection.
19+
*/
20+
class AddStockItemsObserver implements ObserverInterface
21+
{
22+
/**
23+
* @var StockItemCriteriaInterfaceFactory
24+
*/
25+
private $criteriaInterfaceFactory;
26+
27+
/**
28+
* @var StockItemRepositoryInterface
29+
*/
30+
private $stockItemRepository;
31+
32+
/**
33+
* @var StockConfigurationInterface
34+
*/
35+
private $stockConfiguration;
36+
37+
/**
38+
* AddStockItemsObserver constructor.
39+
*
40+
* @param StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory
41+
* @param StockItemRepositoryInterface $stockItemRepository
42+
* @param StockConfigurationInterface $stockConfiguration
43+
*/
44+
public function __construct(
45+
StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory,
46+
StockItemRepositoryInterface $stockItemRepository,
47+
StockConfigurationInterface $stockConfiguration
48+
) {
49+
$this->criteriaInterfaceFactory = $criteriaInterfaceFactory;
50+
$this->stockItemRepository = $stockItemRepository;
51+
$this->stockConfiguration = $stockConfiguration;
52+
}
53+
54+
/**
55+
* Add stock items to products in collection.
56+
*
57+
* @param Observer $observer
58+
* @return void
59+
*/
60+
public function execute(Observer $observer)
61+
{
62+
/** @var Collection $productCollection */
63+
$productCollection = $observer->getData('collection');
64+
$productIds = array_keys($productCollection->getItems());
65+
$criteria = $this->criteriaInterfaceFactory->create();
66+
$criteria->setProductsFilter($productIds);
67+
$criteria->setScopeFilter($this->stockConfiguration->getDefaultScopeId());
68+
$stockItemCollection = $this->stockItemRepository->getList($criteria);
69+
foreach ($stockItemCollection->getItems() as $item) {
70+
/** @var Product $product */
71+
$product = $productCollection->getItemById($item->getProductId());
72+
$productExtension = $product->getExtensionAttributes();
73+
$productExtension->setStockItem($item);
74+
$product->setExtensionAttributes($productExtension);
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)