Skip to content

Commit 96a4f43

Browse files
committed
Merge remote-tracking branch 'mainline/develop' into SPRINT-30-NORD
2 parents 17d1f19 + 0b25aec commit 96a4f43

File tree

110 files changed

+3870
-728
lines changed

Some content is hidden

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

110 files changed

+3870
-728
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ addons:
99
- postfix
1010
language: php
1111
php:
12-
- 5.6
12+
- 5.6.29
1313
- 7.0
1414
env:
1515
global:

app/code/Magento/Captcha/Test/Unit/Helper/DataTest.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ protected function setUp()
5353
*/
5454
public function testGetCaptcha()
5555
{
56-
if (!function_exists("imageftbbox")) {
57-
$this->markTestSkipped('imageftbbox is not available on the test environment');
58-
}
59-
6056
$this->configMock->expects(
6157
$this->once()
6258
)->method(

app/code/Magento/Captcha/Test/Unit/Model/DefaultTest.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,6 @@ class DefaultTest extends \PHPUnit_Framework_TestCase
8888
*/
8989
protected function setUp()
9090
{
91-
if (!function_exists("imageftbbox")) {
92-
$this->markTestSkipped('imageftbbox is not available on the test environment');
93-
}
9491
$this->session = $this->_getSessionStub();
9592

9693
$this->_storeManager = $this->getMock(

app/code/Magento/Catalog/Model/Indexer/Category/Product/AbstractAction.php

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
namespace Magento\Catalog\Model\Indexer\Category\Product;
1010

11+
use Magento\Framework\DB\Query\BatchIteratorInterface as BatchIteratorInterface;
12+
use Magento\Framework\DB\Query\Generator as QueryGenerator;
1113
use Magento\Framework\App\ResourceConnection;
1214
use Magento\Framework\EntityManager\MetadataPool;
1315

@@ -102,20 +104,29 @@ abstract class AbstractAction
102104
*/
103105
protected $tempTreeIndexTableName;
104106

107+
/**
108+
* @var QueryGenerator
109+
*/
110+
private $queryGenerator;
111+
105112
/**
106113
* @param ResourceConnection $resource
107114
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
108115
* @param \Magento\Catalog\Model\Config $config
116+
* @param QueryGenerator $queryGenerator
109117
*/
110118
public function __construct(
111119
\Magento\Framework\App\ResourceConnection $resource,
112120
\Magento\Store\Model\StoreManagerInterface $storeManager,
113-
\Magento\Catalog\Model\Config $config
121+
\Magento\Catalog\Model\Config $config,
122+
QueryGenerator $queryGenerator = null
114123
) {
115124
$this->resource = $resource;
116125
$this->connection = $resource->getConnection();
117126
$this->storeManager = $storeManager;
118127
$this->config = $config;
128+
$this->queryGenerator = $queryGenerator ?: \Magento\Framework\App\ObjectManager::getInstance()
129+
->get(QueryGenerator::class);
119130
}
120131

121132
/**
@@ -309,15 +320,26 @@ protected function isRangingNeeded()
309320
* @param int $range
310321
* @return \Magento\Framework\DB\Select[]
311322
*/
312-
protected function prepareSelectsByRange(\Magento\Framework\DB\Select $select, $field, $range = self::RANGE_CATEGORY_STEP)
313-
{
314-
return $this->isRangingNeeded() ? $this->connection->selectsByRange(
315-
$field,
316-
$select,
317-
$range
318-
) : [
319-
$select
320-
];
323+
protected function prepareSelectsByRange(
324+
\Magento\Framework\DB\Select $select,
325+
$field,
326+
$range = self::RANGE_CATEGORY_STEP
327+
) {
328+
if($this->isRangingNeeded()) {
329+
$iterator = $this->queryGenerator->generate(
330+
$field,
331+
$select,
332+
$range,
333+
\Magento\Framework\DB\Query\BatchIteratorInterface::NON_UNIQUE_FIELD_ITERATOR
334+
);
335+
336+
$queries = [];
337+
foreach ($iterator as $query) {
338+
$queries[] = $query;
339+
}
340+
return $queries;
341+
}
342+
return [$select];
321343
}
322344

323345
/**

app/code/Magento/Catalog/Model/ProductLink/CollectionProvider.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,21 @@ public function getCollection(\Magento\Catalog\Model\Product $product, $type)
4848
$products = $this->providers[$type]->getLinkedProducts($product);
4949
$converter = $this->converterPool->getConverter($type);
5050
$output = [];
51+
$sorterItems = [];
5152
foreach ($products as $item) {
5253
$output[$item->getId()] = $converter->convert($item);
5354
}
54-
return $output;
55+
56+
foreach ($output as $item) {
57+
$itemPosition = $item['position'];
58+
if (!isset($sorterItems[$itemPosition])) {
59+
$sorterItems[$itemPosition] = $item;
60+
} else {
61+
$newPosition = $itemPosition + 1;
62+
$sorterItems[$newPosition] = $item;
63+
}
64+
}
65+
ksort($sorterItems);
66+
return $sorterItems;
5567
}
5668
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Catalog\Test\Unit\Model;
8+
9+
use Magento\Catalog\Model\ProductLink\CollectionProvider;
10+
use Magento\Catalog\Model\ProductLink\CollectionProviderInterface;
11+
use Magento\Catalog\Model\ProductLink\Converter\ConverterInterface;
12+
use Magento\Catalog\Model\ProductLink\Converter\ConverterPool;
13+
use Magento\Catalog\Model\Product;
14+
15+
class CollectionProviderTest extends \PHPUnit_Framework_TestCase
16+
{
17+
/**
18+
* @var CollectionProvider
19+
*/
20+
private $model;
21+
22+
/**
23+
* @var \PHPUnit_Framework_MockObject_MockObject
24+
*/
25+
private $converterPoolMock;
26+
27+
/**
28+
* @var \PHPUnit_Framework_MockObject_MockObject
29+
*/
30+
private $providerMock;
31+
32+
/**
33+
* @var \PHPUnit_Framework_MockObject_MockObject
34+
*/
35+
private $productMock;
36+
37+
/**
38+
* @var \PHPUnit_Framework_MockObject_MockObject
39+
*/
40+
private $converterMock;
41+
42+
protected function setUp()
43+
{
44+
$this->productMock = $this->getMock(Product::class, [], [], '', false, false);
45+
$this->converterPoolMock = $this->getMock(ConverterPool::class, [], [], '', false, false);
46+
$this->providerMock = $this->getMock(CollectionProviderInterface::class);
47+
$this->converterMock = $this->getMock(ConverterInterface::class);
48+
49+
$this->model = new CollectionProvider($this->converterPoolMock, ['crosssell' => $this->providerMock]);
50+
}
51+
52+
/**
53+
* Test sort order of linked products based on configured item position.
54+
*/
55+
public function testGetCollection()
56+
{
57+
$linkedProductOneMock = $this->getMock(Product::class, [], [], '', false, false);
58+
$linkedProductTwoMock = $this->getMock(Product::class, [], [], '', false, false);
59+
$linkedProductThreeMock = $this->getMock(Product::class, [], [], '', false, false);
60+
61+
$linkedProductOneMock->expects($this->once())->method('getId')->willReturn(1);
62+
$linkedProductTwoMock->expects($this->once())->method('getId')->willReturn(2);
63+
$linkedProductThreeMock->expects($this->once())->method('getId')->willReturn(3);
64+
65+
$this->converterPoolMock->expects($this->once())
66+
->method('getConverter')
67+
->with('crosssell')
68+
->willReturn($this->converterMock);
69+
70+
$map = [
71+
[$linkedProductOneMock, ['name' => 'Product One', 'position' => 10]],
72+
[$linkedProductTwoMock, ['name' => 'Product Two', 'position' => 2]],
73+
[$linkedProductThreeMock, ['name' => 'Product Three', 'position' => 2]],
74+
];
75+
76+
$this->converterMock->expects($this->exactly(3))->method('convert')->willReturnMap($map);
77+
78+
$this->providerMock->expects($this->once())
79+
->method('getLinkedProducts')
80+
->with($this->productMock)
81+
->willReturn(
82+
[
83+
$linkedProductOneMock,
84+
$linkedProductTwoMock,
85+
$linkedProductThreeMock
86+
]
87+
);
88+
89+
$expectedResult = [
90+
2 => ['name' => 'Product Two', 'position' => 2],
91+
3 => ['name' => 'Product Three', 'position' => 2],
92+
10 => ['name' => 'Product One', 'position' => 10],
93+
];
94+
95+
$actualResult = $this->model->getCollection($this->productMock, 'crosssell');
96+
97+
$this->assertEquals($expectedResult, $actualResult, 'Sort order of linked products in incorrect');
98+
}
99+
100+
/**
101+
* Test exception when collection provider is not configured for product link type.
102+
*
103+
* @expectedException \Magento\Framework\Exception\NoSuchEntityException
104+
* @expectedExceptionMessage Collection provider is not registered
105+
*/
106+
public function testGetCollectionWithMissingProviders()
107+
{
108+
$this->model->getCollection($this->productMock, 'upsell');
109+
}
110+
}

app/code/Magento/Catalog/etc/eav_attributes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<field code="is_searchable" locked="true" />
3131
</attribute>
3232
<attribute code="category_ids">
33+
<field code="is_global" locked="true" />
3334
<field code="is_searchable" locked="true" />
3435
<field code="used_for_sort_by" locked="true" />
3536
<field code="is_used_in_grid" locked="true" />

app/code/Magento/Cms/Block/Adminhtml/Wysiwyg/Images/Tree.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,30 @@ class Tree extends \Magento\Backend\Block\Template
2626
*/
2727
protected $_cmsWysiwygImages = null;
2828

29+
/**
30+
* @var \Magento\Framework\Serialize\Serializer\Json
31+
*/
32+
private $serializer;
33+
2934
/**
3035
* @param \Magento\Backend\Block\Template\Context $context
3136
* @param \Magento\Cms\Helper\Wysiwyg\Images $cmsWysiwygImages
3237
* @param \Magento\Framework\Registry $registry
3338
* @param array $data
39+
* @param \Magento\Framework\Serialize\Serializer\Json|null $serializer
40+
* @throws \RuntimeException
3441
*/
3542
public function __construct(
3643
\Magento\Backend\Block\Template\Context $context,
3744
\Magento\Cms\Helper\Wysiwyg\Images $cmsWysiwygImages,
3845
\Magento\Framework\Registry $registry,
39-
array $data = []
46+
array $data = [],
47+
\Magento\Framework\Serialize\Serializer\Json $serializer = null
4048
) {
4149
$this->_coreRegistry = $registry;
4250
$this->_cmsWysiwygImages = $cmsWysiwygImages;
51+
$this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()
52+
->get(\Magento\Framework\Serialize\Serializer\Json::class);
4353
parent::__construct($context, $data);
4454
}
4555

@@ -65,7 +75,7 @@ public function getTreeJson()
6575
'cls' => 'folder',
6676
];
6777
}
68-
return \Zend_Json::encode($jsonArray);
78+
return $this->serializer->serialize($jsonArray);
6979
}
7080

7181
/**

app/code/Magento/Customer/Block/Account/AuthenticationPopup.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,34 @@ class AuthenticationPopup extends \Magento\Framework\View\Element\Template
1515
*/
1616
protected $jsLayout;
1717

18+
/**
19+
* @var \Magento\Framework\Serialize\Serializer\Json
20+
*/
21+
private $serializer;
22+
1823
/**
1924
* @param \Magento\Framework\View\Element\Template\Context $context
2025
* @param array $data
26+
* @param \Magento\Framework\Serialize\Serializer\Json|null $serializer
27+
* @throws \RuntimeException
2128
*/
2229
public function __construct(
2330
\Magento\Framework\View\Element\Template\Context $context,
24-
array $data = []
31+
array $data = [],
32+
\Magento\Framework\Serialize\Serializer\Json $serializer = null
2533
) {
2634
parent::__construct($context, $data);
2735
$this->jsLayout = isset($data['jsLayout']) && is_array($data['jsLayout']) ? $data['jsLayout'] : [];
36+
$this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()
37+
->get(\Magento\Framework\Serialize\Serializer\Json::class);
2838
}
2939

3040
/**
3141
* @return string
3242
*/
3343
public function getJsLayout()
3444
{
35-
return \Zend_Json::encode($this->jsLayout);
45+
return $this->serializer->serialize($this->jsLayout);
3646
}
3747

3848
/**
@@ -50,6 +60,18 @@ public function getConfig()
5060
];
5161
}
5262

63+
/**
64+
* Returns popup config in JSON format.
65+
*
66+
* Added in scope of https://github.com/magento/magento2/pull/8617
67+
*
68+
* @return bool|string
69+
*/
70+
public function getSerializedConfig()
71+
{
72+
return $this->serializer->serialize($this->getConfig());
73+
}
74+
5375
/**
5476
* Is autocomplete enabled for storefront
5577
*

0 commit comments

Comments
 (0)