Skip to content

Commit 1fbbd81

Browse files
committed
Merge pull request #3 from magento-nord/develop
NORD + TROLL + GOINC + DRAGONS
2 parents 644da50 + f291b99 commit 1fbbd81

File tree

33 files changed

+1378
-767
lines changed

33 files changed

+1378
-767
lines changed

app/code/Magento/Backend/App/Area/FrontNameResolver.php

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ class FrontNameResolver implements \Magento\Framework\App\Area\FrontNameResolver
2424
*/
2525
const AREA_CODE = 'adminhtml';
2626

27+
/**
28+
* @var array
29+
*/
30+
protected $standardPorts = ['http' => '80', 'https' => '443'];
31+
2732
/**
2833
* @var string
2934
*/
@@ -42,21 +47,21 @@ class FrontNameResolver implements \Magento\Framework\App\Area\FrontNameResolver
4247
protected $deploymentConfig;
4348

4449
/** @var ScopeConfigInterface */
45-
private $configInterface;
50+
private $scopeConfig;
4651

4752
/**
4853
* @param \Magento\Backend\App\Config $config
4954
* @param DeploymentConfig $deploymentConfig
50-
* @param ScopeConfigInterface $configInterface
55+
* @param ScopeConfigInterface $scopeConfig
5156
*/
5257
public function __construct(
5358
\Magento\Backend\App\Config $config,
5459
DeploymentConfig $deploymentConfig,
55-
ScopeConfigInterface $configInterface
60+
ScopeConfigInterface $scopeConfig
5661
) {
5762
$this->config = $config;
5863
$this->defaultFrontName = $deploymentConfig->get(ConfigOptionsList::CONFIG_PATH_BACKEND_FRONTNAME);
59-
$this->configInterface = $configInterface;
64+
$this->scopeConfig = $scopeConfig;
6065
}
6166

6267
/**
@@ -79,13 +84,30 @@ public function getFrontName($checkHost = false)
7984

8085
/**
8186
* Return whether the host from request is the backend host
87+
*
8288
* @return bool
8389
*/
8490
public function isHostBackend()
8591
{
86-
$backendUrl = $this->configInterface->getValue(Store::XML_PATH_UNSECURE_BASE_URL, ScopeInterface::SCOPE_STORE);
87-
$backendHost = parse_url(trim($backendUrl), PHP_URL_HOST);
92+
$backendUrl = $this->scopeConfig->getValue(Store::XML_PATH_UNSECURE_BASE_URL, ScopeInterface::SCOPE_STORE);
8893
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
89-
return (strcasecmp($backendHost, $host) === 0);
94+
return stripos($this->getHostWithPort($backendUrl), $host) !== false;
95+
}
96+
97+
/**
98+
* Get host with port
99+
*
100+
* @param string $url
101+
* @return mixed|string
102+
*/
103+
private function getHostWithPort($url)
104+
{
105+
$scheme = parse_url(trim($url), PHP_URL_SCHEME);
106+
$host = parse_url(trim($url), PHP_URL_HOST);
107+
$port = parse_url(trim($url), PHP_URL_PORT);
108+
if (!$port) {
109+
$port = isset($this->standardPorts[$scheme]) ? $this->standardPorts[$scheme] : null;
110+
}
111+
return isset($port) ? $host . ':' . $port : $host;
90112
}
91113
}

app/code/Magento/Backend/Test/Unit/App/Area/FrontNameResolverTest.php

Lines changed: 73 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,26 @@
77

88
use Magento\Backend\App\Area\FrontNameResolver;
99
use Magento\Backend\Setup\ConfigOptionsList;
10+
use Magento\Framework\App\DeploymentConfig;
11+
use Magento\Store\Model\ScopeInterface;
12+
use Magento\Store\Model\Store;
1013

1114
class FrontNameResolverTest extends \PHPUnit_Framework_TestCase
1215
{
1316
/**
1417
* @var \Magento\Backend\App\Area\FrontNameResolver
1518
*/
16-
protected $_model;
19+
protected $model;
1720

1821
/**
19-
* @var \PHPUnit_Framework_MockObject_MockObject
22+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Backend\App\Config
2023
*/
21-
protected $_configMock;
24+
protected $configMock;
25+
26+
/**
27+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\Config\ScopeConfigInterface
28+
*/
29+
protected $scopeConfigMock;
2230

2331
/**
2432
* @var string
@@ -27,19 +35,20 @@ class FrontNameResolverTest extends \PHPUnit_Framework_TestCase
2735

2836
protected function setUp()
2937
{
30-
$deploymentConfigMock = $this->getMock('\Magento\Framework\App\DeploymentConfig', [], [], '', false);
38+
/** @var \PHPUnit_Framework_MockObject_MockObject|DeploymentConfig $deploymentConfigMock */
39+
$deploymentConfigMock = $this->getMock('Magento\Framework\App\DeploymentConfig', [], [], '', false);
3140
$deploymentConfigMock->expects($this->once())
3241
->method('get')
3342
->with(ConfigOptionsList::CONFIG_PATH_BACKEND_FRONTNAME)
3443
->will($this->returnValue($this->_defaultFrontName));
35-
$this->_configMock = $this->getMock('\Magento\Backend\App\Config', [], [], '', false);
36-
$configMock = $this->getMock('\Magento\Framework\App\Config\ScopeConfigInterface', [], [], '', false);
37-
$this->_model = new FrontNameResolver($this->_configMock, $deploymentConfigMock, $configMock);
44+
$this->configMock = $this->getMock('Magento\Backend\App\Config', [], [], '', false);
45+
$this->scopeConfigMock = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface', [], [], '', false);
46+
$this->model = new FrontNameResolver($this->configMock, $deploymentConfigMock, $this->scopeConfigMock);
3847
}
3948

4049
public function testIfCustomPathUsed()
4150
{
42-
$this->_configMock->expects(
51+
$this->configMock->expects(
4352
$this->at(0)
4453
)->method(
4554
'getValue'
@@ -48,7 +57,7 @@ public function testIfCustomPathUsed()
4857
)->will(
4958
$this->returnValue(true)
5059
);
51-
$this->_configMock->expects(
60+
$this->configMock->expects(
5261
$this->at(1)
5362
)->method(
5463
'getValue'
@@ -57,12 +66,12 @@ public function testIfCustomPathUsed()
5766
)->will(
5867
$this->returnValue('expectedValue')
5968
);
60-
$this->assertEquals('expectedValue', $this->_model->getFrontName());
69+
$this->assertEquals('expectedValue', $this->model->getFrontName());
6170
}
6271

6372
public function testIfCustomPathNotUsed()
6473
{
65-
$this->_configMock->expects(
74+
$this->configMock->expects(
6675
$this->once()
6776
)->method(
6877
'getValue'
@@ -71,6 +80,58 @@ public function testIfCustomPathNotUsed()
7180
)->will(
7281
$this->returnValue(false)
7382
);
74-
$this->assertEquals($this->_defaultFrontName, $this->_model->getFrontName());
83+
$this->assertEquals($this->_defaultFrontName, $this->model->getFrontName());
84+
}
85+
86+
/**
87+
* @param $url
88+
* @param $host
89+
* @dataProvider hostsDataProvider
90+
*/
91+
public function testIsHostBackend($url, $host, $expectedValue)
92+
{
93+
$backendUrl = $url;
94+
$_SERVER['HTTP_HOST'] = $host;
95+
$this->scopeConfigMock->expects($this->once())
96+
->method('getValue')
97+
->with(Store::XML_PATH_UNSECURE_BASE_URL, ScopeInterface::SCOPE_STORE)
98+
->willReturn($backendUrl);
99+
$this->assertEquals($this->model->isHostBackend(), $expectedValue);
100+
}
101+
102+
public function hostsDataProvider()
103+
{
104+
return [
105+
'withoutPort' => [
106+
'url' => 'http://magento2.loc/',
107+
'host' => 'magento2.loc',
108+
'expectedValue' => true
109+
],
110+
'withPort' => [
111+
'url' => 'http://magento2.loc:8080/',
112+
'host' => 'magento2.loc:8080',
113+
'expectedValue' => true
114+
],
115+
'withStandartPortInUrlWithoutPortInHost' => [
116+
'url' => 'http://magento2.loc:80/',
117+
'host' => 'magento2.loc',
118+
'expectedValue' => true
119+
],
120+
'withoutStandartPortInUrlWithPortInHost' => [
121+
'url' => 'https://magento2.loc/',
122+
'host' => 'magento2.loc:443',
123+
'expectedValue' => true
124+
],
125+
'differentHosts' => [
126+
'url' => 'http://m2.loc/',
127+
'host' => 'magento2.loc',
128+
'expectedValue' => false
129+
],
130+
'differentPortsOnOneHost' => [
131+
'url' => 'http://magento2.loc/',
132+
'host' => 'magento2.loc:8080',
133+
'expectedValue' => false
134+
]
135+
];
75136
}
76137
}

app/code/Magento/Catalog/Model/CategoryRepository.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ public function save(\Magento\Catalog\Api\Data\CategoryInterface $category)
106106
*/
107107
public function get($categoryId, $storeId = null)
108108
{
109-
if (!isset($this->instances[$categoryId])) {
109+
$cacheKey = null !== $storeId ? $storeId : 'all';
110+
if (!isset($this->instances[$categoryId][$cacheKey])) {
110111
/** @var Category $category */
111112
$category = $this->categoryFactory->create();
112113
if (null !== $storeId) {
@@ -116,9 +117,9 @@ public function get($categoryId, $storeId = null)
116117
if (!$category->getId()) {
117118
throw NoSuchEntityException::singleField('id', $categoryId);
118119
}
119-
$this->instances[$categoryId] = $category;
120+
$this->instances[$categoryId][$cacheKey] = $category;
120121
}
121-
return $this->instances[$categoryId];
122+
return $this->instances[$categoryId][$cacheKey];
122123
}
123124

124125
/**

app/code/Magento/Catalog/Model/ProductRepository.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,29 @@ protected function initializeProductData(array $productData, $createNew)
301301
foreach ($productData as $key => $value) {
302302
$product->setData($key, $value);
303303
}
304+
$this->assignProductToWebsites($product);
304305

305306
return $product;
306307
}
307308

309+
/**
310+
* @param \Magento\Catalog\Model\Product $product
311+
* @return void
312+
*/
313+
private function assignProductToWebsites(\Magento\Catalog\Model\Product $product)
314+
{
315+
if (!$this->storeManager->hasSingleStore()) {
316+
317+
if ($this->storeManager->getStore()->getCode() == \Magento\Store\Model\Store::ADMIN_CODE) {
318+
$websiteIds = array_keys($this->storeManager->getWebsites());
319+
} else {
320+
$websiteIds = [$this->storeManager->getStore()->getWebsiteId()];
321+
}
322+
323+
$product->setWebsiteIds(array_unique(array_merge($product->getWebsiteIds(), $websiteIds)));
324+
}
325+
}
326+
308327
/**
309328
* Process product options, creating new options, updating and deleting existing options
310329
*

app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ protected function setUp()
146146
$this->initializedProductMock = $this->getMock(
147147
'Magento\Catalog\Model\Product',
148148
[
149+
'getWebsiteIds',
149150
'setProductOptions',
150151
'load',
151152
'getOptions',
@@ -444,6 +445,8 @@ public function testSaveExisting()
444445
->expects($this->once())
445446
->method('toNestedArray')
446447
->will($this->returnValue($this->productData));
448+
$this->productMock->expects($this->once())->method('getWebsiteIds')->willReturn([]);
449+
447450
$this->assertEquals($this->productMock, $this->model->save($this->productMock));
448451
}
449452

@@ -462,6 +465,8 @@ public function testSaveNew()
462465
->expects($this->once())
463466
->method('toNestedArray')
464467
->will($this->returnValue($this->productData));
468+
$this->productMock->expects($this->once())->method('getWebsiteIds')->willReturn([]);
469+
465470
$this->assertEquals($this->productMock, $this->model->save($this->productMock));
466471
}
467472

@@ -484,6 +489,8 @@ public function testSaveUnableToSaveException()
484489
->expects($this->once())
485490
->method('toNestedArray')
486491
->will($this->returnValue($this->productData));
492+
$this->productMock->expects($this->once())->method('getWebsiteIds')->willReturn([]);
493+
487494
$this->model->save($this->productMock);
488495
}
489496

@@ -507,6 +514,8 @@ public function testSaveException()
507514
->expects($this->once())
508515
->method('toNestedArray')
509516
->will($this->returnValue($this->productData));
517+
$this->productMock->expects($this->once())->method('getWebsiteIds')->willReturn([]);
518+
510519
$this->model->save($this->productMock);
511520
}
512521

@@ -528,6 +537,8 @@ public function testSaveInvalidProductException()
528537
->expects($this->once())
529538
->method('toNestedArray')
530539
->will($this->returnValue($this->productData));
540+
$this->productMock->expects($this->once())->method('getWebsiteIds')->willReturn([]);
541+
531542
$this->model->save($this->productMock);
532543
}
533544

@@ -732,6 +743,8 @@ public function testSaveExistingWithOptions(array $newOptions, array $existingOp
732743
->method('setProductOptions')
733744
->with($expectedData);
734745

746+
$this->initializedProductMock->expects($this->once())->method('getWebsiteIds')->willReturn([]);
747+
735748
$this->assertEquals($this->initializedProductMock, $this->model->save($this->productMock));
736749
}
737750

@@ -963,6 +976,7 @@ public function testSaveWithLinks(array $newLinks, array $existingLinks, array $
963976
$outputLinks[] = $outputLink;
964977
}
965978
}
979+
$this->initializedProductMock->expects($this->once())->method('getWebsiteIds')->willReturn([]);
966980

967981
$results = $this->model->save($this->initializedProductMock);
968982
$this->assertEquals($this->initializedProductMock, $results);
@@ -1131,6 +1145,7 @@ public function testSaveExistingWithNewMediaGalleryEntries()
11311145
'media_type' => 'media_type',
11321146
]
11331147
);
1148+
$this->initializedProductMock->expects($this->once())->method('getWebsiteIds')->willReturn([]);
11341149

11351150
$this->model->save($this->productMock);
11361151
}
@@ -1206,6 +1221,7 @@ public function testSaveExistingWithMediaGalleryEntries()
12061221
$galleryAttributeBackendMock->expects($this->once())
12071222
->method('setMediaAttribute')
12081223
->with($this->initializedProductMock, ['image', 'small_image'], 'filename1');
1224+
$this->initializedProductMock->expects($this->once())->method('getWebsiteIds')->willReturn([]);
12091225

12101226
$this->model->save($this->productMock);
12111227
$this->assertEquals($expectedResult, $this->initializedProductMock->getMediaGallery('images'));

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,8 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
283283
'small_image_label',
284284
'thumbnail_image',
285285
'thumbnail_image_label',
286+
'swatch_image',
287+
'swatch_image_label',
286288
'created_at',
287289
'updated_at',
288290
'new_from_date',

app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Simple.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,9 @@ class Simple extends \Magento\CatalogImportExport\Model\Export\Product\Type\Abst
3333
'old_id',
3434
'tier_price',
3535
'category_ids',
36+
'has_options',
37+
'is_returnable',
38+
'required_options',
39+
'quantity_and_stock_status'
3640
];
3741
}

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
363363
*
364364
* @var string[]
365365
*/
366-
protected $_imagesArrayKeys = ['_media_image', 'image', 'small_image', 'thumbnail'];
366+
protected $_imagesArrayKeys = ['_media_image', 'image', 'small_image', 'thumbnail', 'swatch_image'];
367367

368368
/**
369369
* Permanent entity columns.
@@ -2110,7 +2110,13 @@ public function validateRow(array $rowData, $rowNum)
21102110

21112111
$rowScope = $this->getRowScope($rowData);
21122112

2113-
// BEHAVIOR_DELETE use specific validation logic
2113+
// BEHAVIOR_DELETE and BEHAVIOR_REPLACE use specific validation logic
2114+
if (Import::BEHAVIOR_REPLACE == $this->getBehavior()) {
2115+
if (self::SCOPE_DEFAULT == $rowScope && !isset($this->_oldSku[$rowData[self::COL_SKU]])) {
2116+
$this->addRowError(ValidatorInterface::ERROR_SKU_NOT_FOUND_FOR_DELETE, $rowNum);
2117+
return false;
2118+
}
2119+
}
21142120
if (Import::BEHAVIOR_DELETE == $this->getBehavior()) {
21152121
if (self::SCOPE_DEFAULT == $rowScope && !isset($this->_oldSku[$rowData[self::COL_SKU]])) {
21162122
$this->addRowError(ValidatorInterface::ERROR_SKU_NOT_FOUND_FOR_DELETE, $rowNum);

0 commit comments

Comments
 (0)