Skip to content

Commit 6ce0880

Browse files
[Magento Community Engineering] Community Contributions - 2.3-develop
- merged latest code from mainline branch
2 parents df876bb + 2b9ab21 commit 6ce0880

19 files changed

+1719
-132
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Catalog\Model\Product;
9+
10+
use Magento\Catalog\Api\Data\ProductInterface;
11+
use Magento\Catalog\Api\ProductRepositoryInterface;
12+
use Magento\Catalog\Model\ResourceModel\Product\Website\Link;
13+
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\Framework\ObjectManagerInterface;
15+
use Magento\Store\Api\WebsiteRepositoryInterface;
16+
use Magento\TestFramework\Helper\Bootstrap;
17+
use PHPUnit\Framework\TestCase;
18+
19+
/**
20+
* Checks product websites attribute save behaviour
21+
*
22+
* @magentoDbIsolation enabled
23+
*/
24+
class UpdateProductWebsiteTest extends TestCase
25+
{
26+
/** @var ObjectManagerInterface */
27+
private $objectManager;
28+
29+
/** @var Link */
30+
private $productWebsiteLink;
31+
32+
/** @var WebsiteRepositoryInterface */
33+
private $websiteRepository;
34+
35+
/** @var ProductRepositoryInterface */
36+
private $productRepository;
37+
38+
/**
39+
* @inheritdoc
40+
*/
41+
protected function setUp()
42+
{
43+
parent::setUp();
44+
45+
$this->objectManager = Bootstrap::getObjectManager();
46+
$this->productWebsiteLink = $this->objectManager->get(Link::class);
47+
$this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class);
48+
$this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
49+
}
50+
51+
/**
52+
* @magentoDataFixture Magento/Store/_files/website.php
53+
* @magentoDataFixture Magento/Catalog/_files/second_product_simple.php
54+
* @return void
55+
*/
56+
public function testAssignProductToWebsite(): void
57+
{
58+
$defaultWebsiteId = $this->websiteRepository->get('base')->getId();
59+
$secondWebsiteId = $this->websiteRepository->get('test')->getId();
60+
$product = $this->updateProductWebsites('simple2', [$defaultWebsiteId, $secondWebsiteId]);
61+
$this->assertEquals(
62+
[$defaultWebsiteId, $secondWebsiteId],
63+
$this->productWebsiteLink->getWebsiteIdsByProductId($product->getId())
64+
);
65+
}
66+
67+
/**
68+
* @magentoDbIsolation disabled
69+
* @magentoDataFixture Magento/Catalog/_files/product_two_websites.php
70+
* @return void
71+
*/
72+
public function testUnassignProductFromWebsite(): void
73+
{
74+
$secondWebsiteId = $this->websiteRepository->get('test')->getId();
75+
$product = $this->updateProductWebsites('simple-on-two-websites', [$secondWebsiteId]);
76+
$this->assertEquals([$secondWebsiteId], $this->productWebsiteLink->getWebsiteIdsByProductId($product->getId()));
77+
}
78+
79+
/**
80+
* @magentoDataFixture Magento/Catalog/_files/second_product_simple.php
81+
* @return void
82+
*/
83+
public function testAssignNonExistingWebsite(): void
84+
{
85+
$messageFormat = 'The website with id %s that was requested wasn\'t found. Verify the website and try again.';
86+
$nonExistingWebsiteId = 921564;
87+
$this->expectException(NoSuchEntityException::class);
88+
$this->expectExceptionMessage((string)__(sprintf($messageFormat, $nonExistingWebsiteId)));
89+
$this->updateProductWebsites('simple2', [$nonExistingWebsiteId]);
90+
}
91+
92+
/**
93+
* Update product websites attribute
94+
*
95+
* @param string $productSku
96+
* @param array $websiteIds
97+
* @return ProductInterface
98+
*/
99+
private function updateProductWebsites(string $productSku, array $websiteIds): ProductInterface
100+
{
101+
$product = $this->productRepository->get($productSku);
102+
$product->setWebsiteIds($websiteIds);
103+
104+
return $this->productRepository->save($product);
105+
}
106+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
use Magento\Catalog\Api\CategoryRepositoryInterface;
9+
use Magento\Catalog\Api\Data\ProductInterfaceFactory;
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Catalog\Api\Data\CategoryInterfaceFactory;
12+
use Magento\Catalog\Model\Product\Attribute\Source\Status;
13+
use Magento\Catalog\Model\Product\Type;
14+
use Magento\Catalog\Model\Product\Visibility;
15+
use Magento\Store\Model\Store;
16+
use Magento\Store\Model\StoreManagerInterface;
17+
use Magento\TestFramework\Helper\Bootstrap;
18+
19+
$objectManager = Bootstrap::getObjectManager();
20+
$storeManager = $objectManager->get(StoreManagerInterface::class);
21+
$categoryFactory = $objectManager->get(CategoryInterfaceFactory::class);
22+
$productFactory = $objectManager->get(ProductInterfaceFactory::class);
23+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
24+
$categoryRepository = $objectManager->get(CategoryRepositoryInterface::class);
25+
$currentStoreId = $storeManager->getStore()->getId();
26+
27+
$storeManager->setCurrentStore(Store::DEFAULT_STORE_ID);
28+
$category = $categoryFactory->create();
29+
$category->isObjectNew(true);
30+
$category->setName('Category 999')
31+
->setParentId(2)
32+
->setLevel(2)
33+
->setAvailableSortBy('name')
34+
->setDefaultSortBy('name')
35+
->setIsActive(true)
36+
->setPosition(1);
37+
$category = $categoryRepository->save($category);
38+
$storeManager->setCurrentStore($currentStoreId);
39+
40+
$product = $productFactory->create();
41+
$product->setTypeId(Type::TYPE_SIMPLE)
42+
->setAttributeSetId($product->getDefaultAttributeSetId())
43+
->setStoreId(Store::DEFAULT_STORE_ID)
44+
->setWebsiteIds([1])
45+
->setName('Simple Product With Price 10')
46+
->setSku('simple1000')
47+
->setPrice(10)
48+
->setWeight(1)
49+
->setStockData(['use_config_manage_stock' => 0])
50+
->setCategoryIds([$category->getId()])
51+
->setVisibility(Visibility::VISIBILITY_BOTH)
52+
->setStatus(Status::STATUS_ENABLED);
53+
$productRepository->save($product);
54+
55+
$product = $productFactory->create();
56+
$product->setTypeId(Type::TYPE_SIMPLE)
57+
->setAttributeSetId($product->getDefaultAttributeSetId())
58+
->setStoreId(Store::DEFAULT_STORE_ID)
59+
->setWebsiteIds([1])
60+
->setName('Simple Product With Price 20')
61+
->setSku('simple1001')
62+
->setPrice(20)
63+
->setWeight(1)
64+
->setStockData(['use_config_manage_stock' => 0])
65+
->setCategoryIds([$category->getId()])
66+
->setVisibility(Visibility::VISIBILITY_BOTH)
67+
->setStatus(Status::STATUS_ENABLED);
68+
$productRepository->save($product);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
use Magento\Catalog\Api\CategoryRepositoryInterface;
9+
use Magento\Catalog\Api\Data\CategoryInterface;
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory;
12+
use Magento\Framework\Exception\NoSuchEntityException;
13+
use Magento\Framework\Registry;
14+
use Magento\TestFramework\Helper\Bootstrap;
15+
16+
$objectManager = Bootstrap::getObjectManager();
17+
$registry = $objectManager->get(Registry::class);
18+
$registry->unregister('isSecureArea');
19+
$registry->register('isSecureArea', true);
20+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
21+
$categoryCollectionFactory = $objectManager->get(CollectionFactory::class);
22+
$categoryRepository = $objectManager->get(CategoryRepositoryInterface::class);
23+
try {
24+
$productRepository->deleteById('simple1000');
25+
} catch (NoSuchEntityException $e) {
26+
//Already deleted.
27+
}
28+
29+
try {
30+
$productRepository->deleteById('simple1001');
31+
} catch (NoSuchEntityException $e) {
32+
//Already deleted.
33+
}
34+
35+
try {
36+
$categoryCollection = $categoryCollectionFactory->create();
37+
$category = $categoryCollection
38+
->addAttributeToFilter(CategoryInterface::KEY_NAME, 'Category 999')
39+
->setPageSize(1)
40+
->getFirstItem();
41+
$categoryRepository->delete($category);
42+
} catch (NoSuchEntityException $e) {
43+
//Already deleted.
44+
}
45+
$registry->unregister('isSecureArea');
46+
$registry->register('isSecureArea', false);

dev/tests/integration/testsuite/Magento/Catalog/_files/product_boolean_attribute.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
use Magento\Catalog\Setup\CategorySetup;
89
use Magento\Eav\Api\AttributeRepositoryInterface;
910
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
11+
use Magento\Eav\Model\Entity\Attribute\Source\Boolean;
1012
use Magento\TestFramework\Helper\Bootstrap;
1113

1214
$objectManager = Bootstrap::getObjectManager();
1315
/** @var AttributeRepositoryInterface $attributeRepository */
1416
$attributeRepository = $objectManager->get(AttributeRepositoryInterface::class);
1517
/** @var Attribute $attribute */
1618
$attribute = $objectManager->create(Attribute::class);
17-
/** @var $installer \Magento\Catalog\Setup\CategorySetup */
19+
/** @var $installer CategorySetup */
1820
$installer = $objectManager->create(CategorySetup::class);
1921

2022
$attribute->setData(
@@ -37,7 +39,8 @@
3739
'used_in_product_listing' => 1,
3840
'used_for_sort_by' => 0,
3941
'frontend_label' => ['Boolean Attribute'],
40-
'backend_type' => 'int'
42+
'backend_type' => 'int',
43+
'source_model' => Boolean::class
4144
]
4245
);
4346

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogUrlRewrite\Model;
9+
10+
use Magento\Framework\App\Config\ScopeConfigInterface;
11+
use Magento\Framework\ObjectManagerInterface;
12+
use Magento\Store\Api\StoreRepositoryInterface;
13+
use Magento\TestFramework\Helper\Bootstrap;
14+
use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection;
15+
use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollectionFactory;
16+
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
17+
use PHPUnit\Framework\TestCase;
18+
19+
/**
20+
* Base class for url rewrites tests logic
21+
*
22+
* @magentoDbIsolation enabled
23+
* @magentoConfigFixture default/catalog/seo/generate_category_product_rewrites 1
24+
*/
25+
abstract class AbstractUrlRewriteTest extends TestCase
26+
{
27+
/** @var ObjectManagerInterface */
28+
protected $objectManager;
29+
30+
/** @var StoreRepositoryInterface */
31+
protected $storeRepository;
32+
33+
/** @var ScopeConfigInterface */
34+
protected $config;
35+
36+
/** @var UrlRewriteCollectionFactory */
37+
protected $urlRewriteCollectionFactory;
38+
39+
/**
40+
* @inheritdoc
41+
*/
42+
protected function setUp()
43+
{
44+
parent::setUp();
45+
46+
$this->objectManager = Bootstrap::getObjectManager();
47+
$this->storeRepository = $this->objectManager->create(StoreRepositoryInterface::class);
48+
$this->config = $this->objectManager->get(ScopeConfigInterface::class);
49+
$this->urlRewriteCollectionFactory = $this->objectManager->get(UrlRewriteCollectionFactory::class);
50+
}
51+
52+
/**
53+
* Retrieve all rewrite ids
54+
*
55+
* @return array
56+
*/
57+
protected function getAllRewriteIds(): array
58+
{
59+
$urlRewriteCollection = $this->urlRewriteCollectionFactory->create();
60+
61+
return $urlRewriteCollection->getAllIds();
62+
}
63+
64+
/**
65+
* Check that actual data contains of expected values
66+
*
67+
* @param UrlRewriteCollection $collection
68+
* @param array $expectedData
69+
* @return void
70+
*/
71+
protected function assertRewrites(UrlRewriteCollection $collection, array $expectedData): void
72+
{
73+
$collectionItems = $collection->toArray()['items'];
74+
$this->assertTrue(count($collectionItems) === count($expectedData));
75+
foreach ($expectedData as $expectedItem) {
76+
$found = false;
77+
foreach ($collectionItems as $item) {
78+
$found = array_intersect_assoc($item, $expectedItem) == $expectedItem;
79+
if ($found) {
80+
break;
81+
}
82+
}
83+
$this->assertTrue($found, 'The actual data does not contains of expected values');
84+
}
85+
}
86+
87+
/**
88+
* Get category url rewrites collection
89+
*
90+
* @param string|array $entityId
91+
* @return UrlRewriteCollection
92+
*/
93+
protected function getEntityRewriteCollection($entityId): UrlRewriteCollection
94+
{
95+
$condition = is_array($entityId) ? ['in' => $entityId] : $entityId;
96+
$entityRewriteCollection = $this->urlRewriteCollectionFactory->create();
97+
$entityRewriteCollection->addFieldToFilter(UrlRewrite::ENTITY_ID, $condition)
98+
->addFieldToFilter(UrlRewrite::ENTITY_TYPE, ['eq' => $this->getEntityType()]);
99+
100+
return $entityRewriteCollection;
101+
}
102+
103+
/**
104+
* Prepare expected data
105+
*
106+
* @param array $expectedData
107+
* @param int|null $id
108+
* @return array
109+
*/
110+
protected function prepareData(array $expectedData, ?int $id = null): array
111+
{
112+
$newData = [];
113+
foreach ($expectedData as $key => $expectedItem) {
114+
$newData[$key] = str_replace(['%suffix%', '%id%'], [$this->getUrlSuffix(), $id], $expectedItem);
115+
}
116+
117+
return $newData;
118+
}
119+
120+
/**
121+
* Get entity type
122+
*
123+
* @return string
124+
*/
125+
abstract protected function getEntityType(): string;
126+
127+
/**
128+
* Get config value for url suffix
129+
*
130+
* @return string
131+
*/
132+
abstract protected function getUrlSuffix(): string;
133+
}

0 commit comments

Comments
 (0)