Skip to content

Commit e018561

Browse files
committed
Merge branch 'develop' of https://github.corp.magento.com/magento2/magento2ce into Troll-PR
2 parents 277ebf3 + 66a92cb commit e018561

File tree

11 files changed

+237
-43
lines changed

11 files changed

+237
-43
lines changed

app/code/Magento/Catalog/Model/Product/Copier.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
*/
88
namespace Magento\Catalog\Model\Product;
99

10+
use Magento\Catalog\Api\Data\ProductInterface;
11+
1012
class Copier
1113
{
1214
/**
@@ -24,6 +26,11 @@ class Copier
2426
*/
2527
protected $productFactory;
2628

29+
/**
30+
* @var \Magento\Framework\EntityManager\MetadataPool
31+
*/
32+
protected $metadataPool;
33+
2734
/**
2835
* @param CopyConstructorInterface $copyConstructor
2936
* @param \Magento\Catalog\Model\ProductFactory $productFactory
@@ -73,14 +80,18 @@ public function copy(\Magento\Catalog\Model\Product $product)
7380
} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
7481
}
7582
} while (!$isDuplicateSaved);
76-
7783
$this->getOptionRepository()->duplicate($product, $duplicate);
78-
$product->getResource()->duplicate($product->getEntityId(), $duplicate->getEntityId());
84+
$metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class);
85+
$product->getResource()->duplicate(
86+
$product->getData($metadata->getLinkField()),
87+
$duplicate->getData($metadata->getLinkField())
88+
);
7989
return $duplicate;
8090
}
8191

8292
/**
8393
* @return Option\Repository
94+
* @deprecated
8495
*/
8596
private function getOptionRepository()
8697
{
@@ -90,4 +101,17 @@ private function getOptionRepository()
90101
}
91102
return $this->optionRepository;
92103
}
104+
105+
/**
106+
* @return \Magento\Framework\EntityManager\MetadataPool
107+
* @deprecated
108+
*/
109+
private function getMetadataPool()
110+
{
111+
if (null === $this->metadataPool) {
112+
$this->metadataPool = \Magento\Framework\App\ObjectManager::getInstance()
113+
->get('Magento\Framework\EntityManager\MetadataPool');
114+
}
115+
return $this->metadataPool;
116+
}
93117
}

app/code/Magento/Catalog/Model/Product/Option/Repository.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\Framework\Exception\CouldNotSaveException;
1111
use Magento\Framework\Exception\NoSuchEntityException;
1212
use Magento\Framework\EntityManager\MetadataPool;
13+
use Magento\Framework\EntityManager\HydratorPool;
1314

1415
/**
1516
* Class Repository
@@ -42,6 +43,11 @@ class Repository implements \Magento\Catalog\Api\ProductCustomOptionRepositoryIn
4243
*/
4344
protected $metadataPool;
4445

46+
/**
47+
* @var HydratorPool
48+
*/
49+
protected $hydratorPool;
50+
4551
/**
4652
* @var Converter
4753
*/
@@ -113,10 +119,12 @@ public function duplicate(
113119
\Magento\Catalog\Api\Data\ProductInterface $product,
114120
\Magento\Catalog\Api\Data\ProductInterface $duplicate
115121
) {
122+
$hydrator = $this->getHydratorPool()->getHydrator(ProductInterface::class);
123+
$metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class);
116124
return $this->optionResource->duplicate(
117125
$this->getOptionFactory()->create([]),
118-
$product->getId(),
119-
$duplicate->getId()
126+
$hydrator->extract($product)[$metadata->getLinkField()],
127+
$hydrator->extract($duplicate)[$metadata->getLinkField()]
120128
);
121129
}
122130

@@ -189,6 +197,7 @@ protected function markRemovedValues($newValues, $originalValues)
189197

190198
/**
191199
* @return \Magento\Catalog\Model\Product\OptionFactory
200+
* @deprecated
192201
*/
193202
private function getOptionFactory()
194203
{
@@ -201,6 +210,7 @@ private function getOptionFactory()
201210

202211
/**
203212
* @return \Magento\Catalog\Model\ResourceModel\Product\Option\CollectionFactory
213+
* @deprecated
204214
*/
205215
private function getCollectionFactory()
206216
{
@@ -213,6 +223,7 @@ private function getCollectionFactory()
213223

214224
/**
215225
* @return \Magento\Framework\EntityManager\MetadataPool
226+
* @deprecated
216227
*/
217228
private function getMetadataPool()
218229
{
@@ -222,4 +233,17 @@ private function getMetadataPool()
222233
}
223234
return $this->metadataPool;
224235
}
236+
237+
/**
238+
* @return \Magento\Framework\EntityManager\HydratorPool
239+
* @deprecated
240+
*/
241+
private function getHydratorPool()
242+
{
243+
if (null === $this->hydratorPool) {
244+
$this->hydratorPool = \Magento\Framework\App\ObjectManager::getInstance()
245+
->get('Magento\Framework\EntityManager\HydratorPool');
246+
}
247+
return $this->hydratorPool;
248+
}
225249
}

app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ class CopierTest extends \PHPUnit_Framework_TestCase
3434
*/
3535
protected $productMock;
3636

37+
/**
38+
* @var \PHPUnit_Framework_MockObject_MockObject
39+
*/
40+
protected $metadata;
41+
3742
protected function setUp()
3843
{
3944
$this->copyConstructorMock = $this->getMock('\Magento\Catalog\Model\Product\CopyConstructorInterface');
@@ -54,22 +59,33 @@ protected function setUp()
5459
$this->optionRepositoryMock;
5560
$this->productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false);
5661
$this->productMock->expects($this->any())->method('getEntityId')->willReturn(1);
57-
$this->productMock->expects($this->any())->method('getData')->will($this->returnValue('product data'));
5862

63+
$this->metadata = $this->getMockBuilder('Magento\Framework\EntityManager\EntityMetadata')
64+
->disableOriginalConstructor()
65+
->getMock();
66+
$metadataPool = $this->getMockBuilder('Magento\Framework\EntityManager\MetadataPool')
67+
->disableOriginalConstructor()
68+
->getMock();
69+
$metadataPool->expects($this->any())->method('getMetadata')->willReturn($this->metadata);
5970
$this->_model = new Copier(
6071
$this->copyConstructorMock,
6172
$this->productFactoryMock
6273
);
6374

6475
$this->setProperties($this->_model, [
65-
'optionRepository' => $this->optionRepositoryMock
76+
'optionRepository' => $this->optionRepositoryMock,
77+
'metadataPool' => $metadataPool,
6678
]);
6779
}
6880

6981
public function testCopy()
7082
{
7183
$this->productMock->expects($this->atLeastOnce())->method('getWebsiteIds');
7284
$this->productMock->expects($this->atLeastOnce())->method('getCategoryIds');
85+
$this->productMock->expects($this->any())->method('getData')->willReturnMap([
86+
['', null, 'product data'],
87+
['linkField', null, '1'],
88+
]);
7389

7490
$resourceMock = $this->getMock('\Magento\Catalog\Model\ResourceModel\Product', [], [], '', false);
7591
$this->productMock->expects($this->once())->method('getResource')->will($this->returnValue($resourceMock));
@@ -80,6 +96,7 @@ public function testCopy()
8096
'__wakeup',
8197
'setData',
8298
'setOptions',
99+
'getData',
83100
'setIsDuplicate',
84101
'setOriginalId',
85102
'setStatus',
@@ -123,8 +140,12 @@ public function testCopy()
123140
$duplicateMock->expects($this->once())->method('getUrlKey')->willReturn('urk-key-1');
124141
$duplicateMock->expects($this->once())->method('setUrlKey')->with('urk-key-2');
125142
$duplicateMock->expects($this->once())->method('save');
126-
$duplicateMock->expects($this->any())->method('getEntityId')->willReturn(2);
127-
$this->optionRepositoryMock->expects($this->once())
143+
144+
$this->metadata->expects($this->any())->method('getLinkField')->willReturn('linkField');
145+
146+
$duplicateMock->expects($this->any())->method('getData')->willReturnMap([
147+
['linkField', null, '2'],
148+
]); $this->optionRepositoryMock->expects($this->once())
128149
->method('duplicate')
129150
->with($this->productMock, $duplicateMock);
130151
$resourceMock->expects($this->once())->method('duplicate')->with(1, 2);
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\CatalogUrlRewrite\Model\Product;
7+
8+
use Magento\Catalog\Api\CategoryRepositoryInterface;
9+
use Magento\Catalog\Model\Product;
10+
use Magento\CatalogUrlRewrite\Model\ObjectRegistry;
11+
use Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator;
12+
use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator;
13+
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
15+
use Magento\UrlRewrite\Service\V1\Data\UrlRewriteFactory;
16+
17+
class AnchorUrlRewriteGenerator
18+
{
19+
/** @var ProductUrlPathGenerator */
20+
protected $urlPathGenerator;
21+
22+
/** @var UrlRewriteFactory */
23+
protected $urlRewriteFactory;
24+
25+
/** @var CategoryRepositoryInterface */
26+
private $categoryRepository;
27+
28+
/**
29+
* @param ProductUrlPathGenerator $urlPathGenerator
30+
* @param UrlRewriteFactory $urlRewriteFactory
31+
* @param CategoryRepositoryInterface $categoryRepository
32+
*/
33+
public function __construct(
34+
ProductUrlPathGenerator $urlPathGenerator,
35+
UrlRewriteFactory $urlRewriteFactory,
36+
CategoryRepositoryInterface $categoryRepository
37+
) {
38+
$this->urlPathGenerator = $urlPathGenerator;
39+
$this->urlRewriteFactory = $urlRewriteFactory;
40+
$this->categoryRepository = $categoryRepository;
41+
}
42+
43+
/**
44+
* Generate list based on categories
45+
*
46+
* @param int $storeId
47+
* @param Product $product
48+
* @param ObjectRegistry $productCategories
49+
* @return UrlRewrite[]
50+
*/
51+
public function generate($storeId, Product $product, ObjectRegistry $productCategories)
52+
{
53+
$urls = [];
54+
foreach ($productCategories->getList() as $category) {
55+
$anchorCategoryIds = $category->getAnchorsAbove();
56+
if ($anchorCategoryIds) {
57+
foreach ($anchorCategoryIds as $anchorCategoryId) {
58+
$anchorCategory = $this->categoryRepository->get($anchorCategoryId);
59+
$urls[] = $this->urlRewriteFactory->create()
60+
->setEntityType(ProductUrlRewriteGenerator::ENTITY_TYPE)
61+
->setEntityId($product->getId())
62+
->setRequestPath(
63+
$this->urlPathGenerator->getUrlPathWithSuffix(
64+
$product,
65+
$storeId,
66+
$anchorCategory
67+
)
68+
)
69+
->setTargetPath(
70+
$this->urlPathGenerator->getCanonicalUrlPath(
71+
$product,
72+
$anchorCategory
73+
)
74+
)
75+
->setStoreId($storeId)
76+
->setMetadata(['category_id' => $anchorCategory->getId()]);
77+
}
78+
}
79+
}
80+
81+
return $urls;
82+
}
83+
}

app/code/Magento/CatalogUrlRewrite/Model/ProductUrlRewriteGenerator.php

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@
99
use Magento\CatalogUrlRewrite\Model\Product\CanonicalUrlRewriteGenerator;
1010
use Magento\CatalogUrlRewrite\Model\Product\CategoriesUrlRewriteGenerator;
1111
use Magento\CatalogUrlRewrite\Model\Product\CurrentUrlRewritesRegenerator;
12+
use Magento\CatalogUrlRewrite\Model\Product\AnchorUrlRewriteGenerator;
1213
use Magento\CatalogUrlRewrite\Service\V1\StoreViewService;
1314
use Magento\Store\Model\Store;
1415

16+
/**
17+
* Class ProductUrlRewriteGenerator
18+
* @package Magento\CatalogUrlRewrite\Model
19+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
20+
*/
1521
class ProductUrlRewriteGenerator
1622
{
1723
/**
@@ -43,6 +49,9 @@ class ProductUrlRewriteGenerator
4349
/** @var \Magento\Store\Model\StoreManagerInterface */
4450
protected $storeManager;
4551

52+
/** @var AnchorUrlRewriteGenerator */
53+
private $anchorUrlRewriteGenerator;
54+
4655
/**
4756
* @param \Magento\CatalogUrlRewrite\Model\Product\CanonicalUrlRewriteGenerator $canonicalUrlRewriteGenerator
4857
* @param \Magento\CatalogUrlRewrite\Model\Product\CurrentUrlRewritesRegenerator $currentUrlRewritesRegenerator
@@ -67,6 +76,20 @@ public function __construct(
6776
$this->storeManager = $storeManager;
6877
}
6978

79+
/**
80+
* @return AnchorUrlRewriteGenerator
81+
*
82+
* @deprecated
83+
*/
84+
private function getAnchorUrlRewriteGenerator()
85+
{
86+
if ($this->anchorUrlRewriteGenerator === null) {
87+
$this->anchorUrlRewriteGenerator = \Magento\Framework\App\ObjectManager::getInstance()
88+
->get('Magento\CatalogUrlRewrite\Model\Product\AnchorUrlRewriteGenerator');
89+
}
90+
return $this->anchorUrlRewriteGenerator;
91+
}
92+
7093
/**
7194
* Generate product url rewrites
7295
*
@@ -143,7 +166,8 @@ protected function generateForSpecificStoreView($storeId, $productCategories)
143166
$urls = array_merge(
144167
$this->canonicalUrlRewriteGenerator->generate($storeId, $this->product),
145168
$this->categoriesUrlRewriteGenerator->generate($storeId, $this->product, $this->productCategories),
146-
$this->currentUrlRewritesRegenerator->generate($storeId, $this->product, $this->productCategories)
169+
$this->currentUrlRewritesRegenerator->generate($storeId, $this->product, $this->productCategories),
170+
$this->getAnchorUrlRewriteGenerator()->generate($storeId, $this->product, $this->productCategories)
147171
);
148172

149173
/* Reduce duplicates. Last wins */

app/code/Magento/CatalogUrlRewrite/Observer/CategoryProcessUrlRewriteSavingObserver.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ public function execute(\Magento\Framework\Event\Observer $observer)
4949
if ($category->getParentId() == Category::TREE_ROOT_ID) {
5050
return;
5151
}
52-
if ($category->dataHasChangedFor('url_key') || $category->getIsChangedProductList()) {
52+
if ($category->dataHasChangedFor('url_key')
53+
|| $category->dataHasChangedFor('is_anchor')
54+
|| $category->getIsChangedProductList()
55+
) {
5356
$urlRewrites = array_merge(
5457
$this->categoryUrlRewriteGenerator->generate($category),
5558
$this->urlRewriteHandler->generateProductUrlRewrites($category)

0 commit comments

Comments
 (0)