Skip to content

Commit 49e55db

Browse files
committed
Merge remote-tracking branch 'magento2/develop' into develop
2 parents 0e11c35 + f4ae285 commit 49e55db

File tree

88 files changed

+1597
-1476
lines changed

Some content is hidden

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

88 files changed

+1597
-1476
lines changed

app/code/Magento/Backend/view/adminhtml/web/template/dynamic-rows/cells/action-delete.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
-->
77
<button class="action-delete"
88
data-bind="
9-
click: function(){ $parents[1].deleteRecord($parent.index, $parent.recordId); },
9+
click: function(){ $parent.processingDeleteRecord($record().index, $record().recordId); },
1010
attr: {
11-
title: $parents[1].deleteButtonLabel
11+
title: $parent.deleteButtonLabel
1212
}
1313
">
14-
<span data-bind="text: $parents[1].deleteButtonLabel"></span>
14+
<span data-bind="text: $parent.deleteButtonLabel"></span>
1515
</button>

app/code/Magento/Backend/view/adminhtml/web/template/dynamic-rows/grid.html

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,36 +34,44 @@
3434
</label>
3535

3636
<div class="admin__field-control" data-role="grid-wrapper">
37+
<div class="admin__control-table-pagination" visible="!!$data.recordData().length">
38+
<div class="admin__data-grid-pager">
39+
<button class="action-previous" type="button" data-bind="attr: {title: $t('Previous Page')}, click: previousPage, disable: isFirst()"></button>
40+
<input class="admin__control-text" type="number" data-bind="attr: {id: ++ko.uid}, value: currentPage">
41+
<label class="admin__control-support-text" data-bind="attr: {for: ko.uid}, text: 'of ' + pages()"></label>
42+
<button class="action-next" type="button" data-bind="attr: {title: $t('Next Page')}, click: nextPage, disable: isLast()"></button>
43+
</div>
44+
</div>
3745
<div class="admin__control-table-wrapper">
3846
<table class="admin__dynamic-rows data-grid" data-role="grid">
3947
<thead if="element.columnsHeader">
4048
<tr>
4149
<th if="dndConfig.enabled"
4250
class="data-grid-draggable-row-cell"/>
4351

44-
<!-- ko foreach: {data: labels, as: 'item'} -->
45-
<th class="data-grid-th"
46-
text="item.label"
47-
visible="item.visible"
48-
disabled="item.disabled"
49-
css="$parent.setClasses(item)">
52+
<th repeat="foreach: labels, item: '$label'"
53+
class="data-grid-th"
54+
text="$label().label"
55+
visible="$label().visible"
56+
disable="$label().disabled"
57+
css="setClasses($label())">
5058
</th>
51-
<!-- /ko -->
5259
</tr>
5360
</thead>
5461

5562
<tbody data-bind="foreach: elems">
56-
<tr class="data-row"
57-
css="'_odd-row': $index() % 2">
58-
<td if="$parent.dndConfig.enabled"
63+
<tr repeat="foreach: elems, item: '$record'"
64+
class="data-row"
65+
css="'_odd-row': $index % 2">
66+
<td if="dndConfig.enabled"
5967
class="data-grid-draggable-row-cell"
60-
template="name: $parent.dndConfig.template, data: $parent.dnd"/>
68+
template="name: dndConfig.template, data: dnd"/>
6169

62-
<!-- ko foreach: { data: elems, as: 'elem'} -->
70+
<!-- ko fastForEach: { data: $record().elems, as: 'elem'} -->
6371
<td if="elem.template"
6472
visible="elem.visible"
65-
disabled="elem.disabled"
66-
css="$parents[1].setClasses(elem)"
73+
disable="elem.disabled"
74+
css="$parent.setClasses(elem)"
6775
template="elem.template"
6876
attr="'data-index': index"/>
6977
<!-- /ko -->

app/code/Magento/Bundle/Model/LinkManagement.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ protected function mapProductLinkToSelectionModel(
204204

205205
/**
206206
* {@inheritdoc}
207+
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
207208
*/
208209
public function addChild(
209210
\Magento\Catalog\Api\Data\ProductInterface $product,
@@ -238,19 +239,25 @@ public function addChild(
238239
if ($linkProductModel->isComposite()) {
239240
throw new InputException(__('Bundle product could not contain another composite product'));
240241
}
242+
241243
if ($selections) {
242244
foreach ($selections as $selection) {
243245
if ($selection['option_id'] == $optionId &&
244246
$selection['product_id'] == $linkProductModel->getEntityId()) {
245-
throw new CouldNotSaveException(
246-
__(
247-
'Child with specified sku: "%1" already assigned to product: "%2"',
248-
[$linkedProduct->getSku(), $product->getSku()]
249-
)
250-
);
247+
if (!$product->getCopyFromView()) {
248+
throw new CouldNotSaveException(
249+
__(
250+
'Child with specified sku: "%1" already assigned to product: "%2"',
251+
[$linkedProduct->getSku(), $product->getSku()]
252+
)
253+
);
254+
} else {
255+
return $this->bundleSelection->create()->load($linkProductModel->getEntityId());
256+
}
251257
}
252258
}
253259
}
260+
254261
$selectionModel = $this->bundleSelection->create();
255262
$selectionModel = $this->mapProductLinkToSelectionModel(
256263
$selectionModel,

app/code/Magento/Bundle/Model/OptionRepository.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ public function save(
189189
$option->setStoreId($product->getStoreId());
190190
$option->setParentId($product->getData($metadata->getLinkField()));
191191
$linksToAdd = [];
192-
$option->setDefaultTitle($option->getTitle());
192+
$option->setDefaultTitle($option->getDefaultTitle() ?: $option->getTitle());
193193
if (is_array($option->getProductLinks())) {
194194
$linksToAdd = $option->getProductLinks();
195195
}

app/code/Magento/Bundle/Model/Product/OptionList.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public function getItems(\Magento\Catalog\Api\Data\ProductInterface $product)
7575
);
7676
$optionDataObject->setOptionId($option->getOptionId())
7777
->setTitle($option->getTitle() === null ? $option->getDefaultTitle() : $option->getTitle())
78+
->setDefaultTitle($option->getDefaultTitle())
7879
->setSku($product->getSku())
7980
->setProductLinks($productLinks);
8081
$optionList[] = $optionDataObject;

app/code/Magento/Bundle/Model/Product/SaveHandler.php

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,26 @@ public function execute($entityType, $entity, $arguments = [])
5959
if ($entity->getTypeId() !== 'bundle' || empty($bundleProductOptions)) {
6060
return $entity;
6161
}
62-
/** @var \Magento\Catalog\Api\Data\ProductInterface $entity */
63-
foreach ($this->optionRepository->getList($entity->getSku()) as $option) {
64-
$this->removeOptionLinks($entity->getSku(), $option);
65-
$this->optionRepository->delete($option);
66-
}
6762

68-
$options = $bundleProductOptions ?: [];
69-
foreach ($options as $option) {
70-
$option->setOptionId(null);
71-
$this->optionRepository->save($entity, $option);
63+
if (!$entity->getCopyFromView()) {
64+
/** @var \Magento\Catalog\Api\Data\ProductInterface $entity */
65+
foreach ($this->optionRepository->getList($entity->getSku()) as $option) {
66+
$this->removeOptionLinks($entity->getSku(), $option);
67+
$this->optionRepository->delete($option);
68+
}
69+
70+
$options = $bundleProductOptions ?: [];
71+
foreach ($options as $option) {
72+
$option->setOptionId(null);
73+
$this->optionRepository->save($entity, $option);
74+
}
75+
} else {
76+
//save only labels and not selections + product links
77+
$options = $bundleProductOptions ?: [];
78+
foreach ($options as $option) {
79+
$this->optionRepository->save($entity, $option);
80+
$entity->setCopyFromView(false);
81+
}
7282
}
7383
return $entity;
7484
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Bundle\Model\ResourceModel\Selection\Plugin;
7+
8+
use Magento\Store\Model\Store;
9+
10+
class Collection
11+
{
12+
/**
13+
* Join website product limitation override
14+
* we don't need the website->product filter for children on selections
15+
*
16+
* @param \Magento\Bundle\Model\ResourceModel\Selection\Collection $subject
17+
* @param \Closure $proceed
18+
* @param null|string|bool|int|Store $store
19+
* @return $this
20+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
21+
*/
22+
public function aroundAddStoreFilter(
23+
\Magento\Bundle\Model\ResourceModel\Selection\Collection $subject,
24+
\Closure $proceed,
25+
$store = null
26+
) {
27+
return $subject;
28+
}
29+
}

app/code/Magento/Bundle/Test/Unit/Model/LinkManagementTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ public function testAddChildProductAlreadyExistsInOption()
417417
->method('getData')
418418
->with($this->linkField)
419419
->willReturn($this->linkField);
420+
$productMock->expects($this->any())->method('getCopyFromView')->will($this->returnValue(false));
420421

421422
$linkedProductMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false);
422423
$linkedProductMock->expects($this->any())->method('getEntityId')->will($this->returnValue(13));

app/code/Magento/Bundle/Test/Unit/Model/Product/OptionListTest.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,16 @@ public function testGetItems()
104104
$optionMock->expects($this->exactly(2))->method('getOptionId')->willReturn($optionId);
105105
$optionMock->expects($this->once())->method('getData')->willReturn($optionData);
106106
$optionMock->expects($this->once())->method('getTitle')->willReturn(null);
107-
$optionMock->expects($this->once())->method('getDefaultTitle')->willReturn($optionData['title']);
107+
$optionMock->expects($this->exactly(2))->method('getDefaultTitle')->willReturn($optionData['title']);
108108

109109
$linkMock = $this->getMock('\Magento\Bundle\Api\Data\LinkInterface');
110110
$this->linkListMock->expects($this->once())
111111
->method('getItems')
112112
->with($productMock, $optionId)
113113
->willReturn([$linkMock]);
114-
$newOptionMock = $this->getMock('\Magento\Bundle\Api\Data\OptionInterface');
114+
$newOptionMock = $this->getMockBuilder('\Magento\Bundle\Api\Data\OptionInterface')
115+
->setMethods(['setDefaultTitle'])
116+
->getMockForAbstractClass();
115117
$this->dataObjectHelperMock->expects($this->once())
116118
->method('populateWithArray')
117119
->with($newOptionMock, $optionData, '\Magento\Bundle\Api\Data\OptionInterface')
@@ -121,6 +123,10 @@ public function testGetItems()
121123
->method('setTitle')
122124
->with($optionData['title'])
123125
->willReturnSelf();
126+
$newOptionMock->expects($this->once())
127+
->method('setDefaultTitle')
128+
->with($optionData['title'])
129+
->willReturnSelf();
124130
$newOptionMock->expects($this->once())->method('setSku')->with($productSku)->willReturnSelf();
125131
$newOptionMock->expects($this->once())
126132
->method('setProductLinks')

app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\Bundle\Ui\DataProvider\Product\Form\Modifier;
77

8+
use Magento\Catalog\Model\Locator\LocatorInterface;
89
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
910
use Magento\Framework\UrlInterface;
1011
use Magento\Bundle\Model\Product\Attribute\Source\Shipment\Type as ShipmentType;
@@ -44,15 +45,23 @@ class BundlePanel extends AbstractModifier
4445
protected $arrayManager;
4546

4647
/**
48+
* @var LocatorInterface
49+
*/
50+
protected $locator;
51+
52+
/**
53+
* @param LocatorInterface $locator
4754
* @param UrlInterface $urlBuilder
4855
* @param ShipmentType $shipmentType
4956
* @param ArrayManager $arrayManager
5057
*/
5158
public function __construct(
59+
LocatorInterface $locator,
5260
UrlInterface $urlBuilder,
5361
ShipmentType $shipmentType,
5462
ArrayManager $arrayManager
5563
) {
64+
$this->locator = $locator;
5665
$this->urlBuilder = $urlBuilder;
5766
$this->shipmentType = $shipmentType;
5867
$this->arrayManager = $arrayManager;
@@ -411,14 +420,46 @@ protected function getModalSet()
411420
];
412421
}
413422

423+
/**
424+
* Get configuration for option title
425+
*
426+
* @return array
427+
*/
428+
protected function getTitleConfiguration()
429+
{
430+
$result['title']['arguments']['data']['config'] = [
431+
'dataType' => Form\Element\DataType\Text::NAME,
432+
'formElement' => Form\Element\Input::NAME,
433+
'componentType' => Form\Field::NAME,
434+
'dataScope' => $this->isDefaultStore() ? 'title' : 'default_title',
435+
'label' => $this->isDefaultStore() ? __('Option Title') : __('Default Title'),
436+
'sortOrder' => 10,
437+
'validation' => ['required-entry' => true],
438+
];
439+
440+
if (!$this->isDefaultStore()) {
441+
$result['store_title']['arguments']['data']['config'] = [
442+
'dataType' => Form\Element\DataType\Text::NAME,
443+
'formElement' => Form\Element\Input::NAME,
444+
'componentType' => Form\Field::NAME,
445+
'dataScope' => 'title',
446+
'label' => __('Store View Title'),
447+
'sortOrder' => 15,
448+
'validation' => ['required-entry' => true],
449+
];
450+
}
451+
452+
return $result;
453+
}
454+
414455
/**
415456
* Get option info
416457
*
417458
* @return array
418459
*/
419460
protected function getOptionInfo()
420461
{
421-
return [
462+
$result = [
422463
'arguments' => [
423464
'data' => [
424465
'config' => [
@@ -433,21 +474,6 @@ protected function getOptionInfo()
433474
],
434475
],
435476
'children' => [
436-
'title' => [
437-
'arguments' => [
438-
'data' => [
439-
'config' => [
440-
'dataType' => Form\Element\DataType\Text::NAME,
441-
'formElement' => Form\Element\Input::NAME,
442-
'componentType' => Form\Field::NAME,
443-
'dataScope' => 'title',
444-
'label' => __('Option Title'),
445-
'sortOrder' => 10,
446-
'validation' => ['required-entry' => true],
447-
],
448-
],
449-
],
450-
],
451477
'type' => [
452478
'arguments' => [
453479
'data' => [
@@ -513,6 +539,8 @@ protected function getOptionInfo()
513539
],
514540
],
515541
];
542+
543+
return $this->arrayManager->merge('children', $result, $this->getTitleConfiguration());
516544
}
517545

518546
/**
@@ -715,4 +743,14 @@ protected function getSelectionPriceType()
715743
],
716744
];
717745
}
746+
747+
/**
748+
* Check that store is default
749+
*
750+
* @return bool
751+
*/
752+
protected function isDefaultStore()
753+
{
754+
return $this->locator->getProduct()->getStoreId() == 0;
755+
}
718756
}

0 commit comments

Comments
 (0)