diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Duplicate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Duplicate.php
index 90b8ee3164183..6a5c69a83331d 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Duplicate.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Duplicate.php
@@ -5,57 +5,68 @@
*/
namespace Magento\Catalog\Controller\Adminhtml\Product;
-use Magento\Backend\App\Action;
+use Magento\Backend\App\Action\Context;
+use Magento\Backend\Model\View\Result\Redirect;
use Magento\Catalog\Controller\Adminhtml\Product;
+use Magento\Catalog\Model\Product\Copier;
+use Magento\Catalog\Model\ProductFactory;
+use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\ObjectManager;
+use Psr\Log\LoggerInterface;
/**
- * Class Duplicate
+ * Class Duplicate product
*/
-class Duplicate extends \Magento\Catalog\Controller\Adminhtml\Product implements
- \Magento\Framework\App\Action\HttpGetActionInterface
+class Duplicate extends Product implements HttpGetActionInterface
{
/**
- * @var \Magento\Catalog\Model\Product\Copier
+ * @var Copier
*/
protected $productCopier;
/**
- * @var \Psr\Log\LoggerInterface
+ * @var LoggerInterface
*/
private $logger;
/**
- * @param Action\Context $context
+ * @var ProductFactory
+ */
+ private $productFactory;
+
+ /**
+ * @param Context $context
* @param Builder $productBuilder
- * @param \Magento\Catalog\Model\Product\Copier $productCopier
- * @param \Psr\Log\LoggerInterface $logger
+ * @param Copier $productCopier
+ * @param LoggerInterface|null $logger
+ * @param ProductFactory|null $productFactory
*/
public function __construct(
- \Magento\Backend\App\Action\Context $context,
+ Context $context,
Product\Builder $productBuilder,
- \Magento\Catalog\Model\Product\Copier $productCopier,
- \Psr\Log\LoggerInterface $logger = null
+ Copier $productCopier,
+ LoggerInterface $logger = null,
+ ?ProductFactory $productFactory = null
) {
$this->productCopier = $productCopier;
- $this->logger = $logger ?: ObjectManager::getInstance()
- ->get(\Psr\Log\LoggerInterface::class);
+ $this->logger = $logger ?: ObjectManager::getInstance()->get(LoggerInterface::class);
+ $this->productFactory = $productFactory ?: ObjectManager::getInstance()->get(ProductFactory::class);
parent::__construct($context, $productBuilder);
}
/**
* Create product duplicate
*
- * @return \Magento\Backend\Model\View\Result\Redirect
+ * @return Redirect
*/
public function execute()
{
- /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
+ /** @var Redirect $resultRedirect */
$resultRedirect = $this->resultRedirectFactory->create();
$product = $this->productBuilder->build($this->getRequest());
try {
- $newProduct = $this->productCopier->copy($product);
+ $newProduct = $this->productCopier->copy($product, $this->productFactory->create());
$this->messageManager->addSuccessMessage(__('You duplicated the product.'));
$resultRedirect->setPath('catalog/*/edit', ['_current' => true, 'id' => $newProduct->getId()]);
} catch (\Exception $e) {
diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php
index 97b57317851fc..ca2d80bcc99ce 100644
--- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php
+++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php
@@ -6,20 +6,28 @@
namespace Magento\Catalog\Controller\Adminhtml\Product;
-use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
-use Magento\Backend\App\Action;
+use Magento\Backend\App\Action\Context;
+use Magento\Backend\Model\View\Result\Redirect;
+use Magento\Catalog\Api\CategoryLinkManagementInterface;
use Magento\Catalog\Api\Data\ProductInterface;
+use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Controller\Adminhtml\Product;
+use Magento\Catalog\Model\Product\Copier;
+use Magento\Catalog\Model\Product\TypeTransitionManager;
+use Magento\Catalog\Model\ProductFactory;
+use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
use Magento\Framework\App\ObjectManager;
-use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\App\Request\DataPersistorInterface;
+use Magento\Framework\Escaper;
+use Magento\Store\Model\StoreManagerInterface;
+use Psr\Log\LoggerInterface;
/**
* Product save controller
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
-class Save extends \Magento\Catalog\Controller\Adminhtml\Product implements HttpPostActionInterface
+class Save extends Product implements HttpPostActionInterface
{
/**
* @var Initialization\Helper
@@ -27,22 +35,22 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product implements Http
protected $initializationHelper;
/**
- * @var \Magento\Catalog\Model\Product\Copier
+ * @var Copier
*/
protected $productCopier;
/**
- * @var \Magento\Catalog\Model\Product\TypeTransitionManager
+ * @var TypeTransitionManager
*/
protected $productTypeManager;
/**
- * @var \Magento\Catalog\Api\CategoryLinkManagementInterface
+ * @var CategoryLinkManagementInterface
*/
protected $categoryLinkManagement;
/**
- * @var \Magento\Catalog\Api\ProductRepositoryInterface
+ * @var ProductRepositoryInterface
*/
protected $productRepository;
@@ -57,61 +65,66 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product implements Http
private $storeManager;
/**
- * @var \Magento\Framework\Escaper
+ * @var Escaper
*/
private $escaper;
/**
- * @var \Psr\Log\LoggerInterface
+ * @var LoggerInterface
*/
private $logger;
+ /**
+ * @var ProductFactory
+ */
+ private $productFactory;
+
/**
* Save constructor.
*
- * @param Action\Context $context
+ * @param Context $context
* @param Builder $productBuilder
* @param Initialization\Helper $initializationHelper
- * @param \Magento\Catalog\Model\Product\Copier $productCopier
- * @param \Magento\Catalog\Model\Product\TypeTransitionManager $productTypeManager
- * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
- * @param \Magento\Framework\Escaper $escaper
- * @param \Psr\Log\LoggerInterface $logger
- * @param \Magento\Catalog\Api\CategoryLinkManagementInterface $categoryLinkManagement
- * @param StoreManagerInterface $storeManager
+ * @param Copier $productCopier
+ * @param TypeTransitionManager $productTypeManager
+ * @param ProductRepositoryInterface $productRepository
+ * @param Escaper|null $escaper
+ * @param LoggerInterface|null $logger
+ * @param CategoryLinkManagementInterface|null $categoryLinkManagement
+ * @param StoreManagerInterface|null $storeManager
+ * @param ProductFactory|null $productFactory
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
- \Magento\Backend\App\Action\Context $context,
+ Context $context,
Product\Builder $productBuilder,
Initialization\Helper $initializationHelper,
- \Magento\Catalog\Model\Product\Copier $productCopier,
- \Magento\Catalog\Model\Product\TypeTransitionManager $productTypeManager,
- \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
- \Magento\Framework\Escaper $escaper = null,
- \Psr\Log\LoggerInterface $logger = null,
- \Magento\Catalog\Api\CategoryLinkManagementInterface $categoryLinkManagement = null,
- \Magento\Store\Model\StoreManagerInterface $storeManager = null
+ Copier $productCopier,
+ TypeTransitionManager $productTypeManager,
+ ProductRepositoryInterface $productRepository,
+ Escaper $escaper = null,
+ LoggerInterface $logger = null,
+ CategoryLinkManagementInterface $categoryLinkManagement = null,
+ StoreManagerInterface $storeManager = null,
+ ?ProductFactory $productFactory = null
) {
parent::__construct($context, $productBuilder);
$this->initializationHelper = $initializationHelper;
$this->productCopier = $productCopier;
$this->productTypeManager = $productTypeManager;
$this->productRepository = $productRepository;
- $this->escaper = $escaper ?: ObjectManager::getInstance()
- ->get(\Magento\Framework\Escaper::class);
- $this->logger = $logger ?: ObjectManager::getInstance()
- ->get(\Psr\Log\LoggerInterface::class);
+ $this->escaper = $escaper ?: ObjectManager::getInstance()->get(Escaper::class);
+ $this->logger = $logger ?: ObjectManager::getInstance()->get(LoggerInterface::class);
$this->categoryLinkManagement = $categoryLinkManagement ?: ObjectManager::getInstance()
- ->get(\Magento\Catalog\Api\CategoryLinkManagementInterface::class);
- $this->storeManager = $storeManager ?: ObjectManager::getInstance()
- ->get(\Magento\Store\Model\StoreManagerInterface::class);
+ ->get(CategoryLinkManagementInterface::class);
+ $this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class);
+ $this->productFactory = $productFactory ?: ObjectManager::getInstance()->get(ProductFactory::class);
}
/**
* Save product action
*
- * @return \Magento\Backend\Model\View\Result\Redirect
+ * @return Redirect
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
@@ -166,7 +179,7 @@ public function execute()
if ($redirectBack === 'duplicate') {
$product->unsetData('quantity_and_stock_status');
- $newProduct = $this->productCopier->copy($product);
+ $newProduct = $this->productCopier->copy($product, $this->productFactory->create());
$this->checkUniqueAttributes($product);
$this->messageManager->addSuccessMessage(__('You duplicated the product.'));
}
diff --git a/app/code/Magento/Catalog/Model/Product/Copier.php b/app/code/Magento/Catalog/Model/Product/Copier.php
index b04d3da8f0223..6959813b3e6d3 100644
--- a/app/code/Magento/Catalog/Model/Product/Copier.php
+++ b/app/code/Magento/Catalog/Model/Product/Copier.php
@@ -11,10 +11,8 @@
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Catalog\Model\Product\Option\Repository as OptionRepository;
use Magento\Catalog\Model\ProductFactory;
-use Magento\Framework\App\ObjectManager;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Store\Model\Store;
-use Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException;
/**
* Catalog product copier.
@@ -75,20 +73,19 @@ public function __construct(
* Create product duplicate
*
* @param Product $product
+ * @param Product $duplicate
* @return Product
*/
- public function copy(Product $product): Product
+ public function copy(Product $product, Product $duplicate): Product
{
$product->getWebsiteIds();
$product->getCategoryIds();
$metadata = $this->metadataPool->getMetadata(ProductInterface::class);
- /** @var Product $duplicate */
- $duplicate = $this->productFactory->create();
$productData = $product->getData();
$productData = $this->removeStockItem($productData);
- $duplicate->setData($productData);
+ $duplicate->addData($productData);
$duplicate->setOptions([]);
$duplicate->setMetaTitle(null);
$duplicate->setMetaKeyword(null);
@@ -101,95 +98,12 @@ public function copy(Product $product): Product
$duplicate->setId(null);
$duplicate->setStoreId(Store::DEFAULT_STORE_ID);
$this->copyConstructor->build($product, $duplicate);
- $this->setDefaultUrl($product, $duplicate);
- $this->setStoresUrl($product, $duplicate);
+ $duplicate->save();
$this->optionRepository->duplicate($product, $duplicate);
return $duplicate;
}
- /**
- * Set default URL.
- *
- * @param Product $product
- * @param Product $duplicate
- * @return void
- */
- private function setDefaultUrl(Product $product, Product $duplicate) : void
- {
- $duplicate->setStoreId(Store::DEFAULT_STORE_ID);
- $resource = $product->getResource();
- $attribute = $resource->getAttribute('url_key');
- $productId = $product->getId();
- $urlKey = $resource->getAttributeRawValue($productId, 'url_key', Store::DEFAULT_STORE_ID);
- do {
- $urlKey = $this->modifyUrl($urlKey);
- $duplicate->setUrlKey($urlKey);
- } while (!$attribute->getEntity()->checkAttributeUniqueValue($attribute, $duplicate));
- $duplicate->setData('url_path', null);
- $duplicate->save();
- }
-
- /**
- * Set URL for each store.
- *
- * @param Product $product
- * @param Product $duplicate
- *
- * @return void
- * @throws UrlAlreadyExistsException
- */
- private function setStoresUrl(Product $product, Product $duplicate) : void
- {
- $storeIds = $duplicate->getStoreIds();
- $productId = $product->getId();
- $productResource = $product->getResource();
- $attribute = $productResource->getAttribute('url_key');
- $duplicate->setData('save_rewrites_history', false);
- foreach ($storeIds as $storeId) {
- $useDefault = !$this->scopeOverriddenValue->containsValue(
- ProductInterface::class,
- $product,
- 'url_key',
- $storeId
- );
- if ($useDefault) {
- continue;
- }
-
- $duplicate->setStoreId($storeId);
- $urlKey = $productResource->getAttributeRawValue($productId, 'url_key', $storeId);
- $iteration = 0;
-
- do {
- if ($iteration === 10) {
- throw new UrlAlreadyExistsException();
- }
-
- $urlKey = $this->modifyUrl($urlKey);
- $duplicate->setUrlKey($urlKey);
- $iteration++;
- } while (!$attribute->getEntity()->checkAttributeUniqueValue($attribute, $duplicate));
- $duplicate->setData('url_path', null);
- $productResource->saveAttribute($duplicate, 'url_path');
- $productResource->saveAttribute($duplicate, 'url_key');
- }
- $duplicate->setStoreId(Store::DEFAULT_STORE_ID);
- }
-
- /**
- * Modify URL key.
- *
- * @param string $urlKey
- * @return string
- */
- private function modifyUrl(string $urlKey) : string
- {
- return preg_match('/(.*)-(\d+)$/', $urlKey, $matches)
- ? $matches[1] . '-' . ($matches[2] + 1)
- : $urlKey . '-1';
- }
-
/**
* Remove stock item
*
@@ -204,6 +118,7 @@ private function removeStockItem(array $productData): array
$extensionAttributes->setData('stock_item', null);
}
}
+
return $productData;
}
}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php
index d3a4494c071b7..6574a9701777d 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php
@@ -20,9 +20,12 @@
use Magento\CatalogInventory\Api\Data\StockItemInterface;
use Magento\Eav\Model\Entity\AbstractEntity;
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
+use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\EntityManager\EntityMetadata;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException;
+use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollectionFactory;
+use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@@ -68,6 +71,16 @@ class CopierTest extends TestCase
*/
private $metadata;
+ /**
+ * @var ScopeConfigInterface|MockObject
+ */
+ private $scopeConfigMock;
+
+ /**
+ * @var UrlRewriteCollection|MockObject
+ */
+ private $urlRewriteCollectionMock;
+
/**
* @ingeritdoc
*/
@@ -78,6 +91,14 @@ protected function setUp(): void
$this->scopeOverriddenValueMock = $this->createMock(ScopeOverriddenValue::class);
$this->optionRepositoryMock = $this->createMock(Repository::class);
$this->productMock = $this->createMock(Product::class);
+ $this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class);
+
+ $this->urlRewriteCollectionMock = $this->createMock(UrlRewriteCollection::class);
+ $this->urlRewriteCollectionMock->method('addFieldToFilter')
+ ->willReturnSelf();
+ $urlRewriteCollectionFactoryMock = $this->createMock(UrlRewriteCollectionFactory::class);
+ $urlRewriteCollectionFactoryMock->method('create')
+ ->willReturn($this->urlRewriteCollectionMock);
$this->metadata = $this->getMockBuilder(EntityMetadata::class)
->disableOriginalConstructor()
@@ -95,7 +116,9 @@ protected function setUp(): void
$this->productFactoryMock,
$this->scopeOverriddenValueMock,
$this->optionRepositoryMock,
- $metadataPool
+ $metadataPool,
+ $this->scopeConfigMock,
+ $urlRewriteCollectionFactoryMock
);
}
@@ -144,37 +167,6 @@ public function testCopy(): void
true,
['checkAttributeUniqueValue']
);
- $entityMock->expects($this->once())
- ->method('checkAttributeUniqueValue')
- ->willReturn(true);
-
- $attributeMock = $this->getMockForAbstractClass(
- AbstractAttribute::class,
- [],
- '',
- false,
- true,
- true,
- ['getEntity']
- );
- $attributeMock->expects($this->once())
- ->method('getEntity')
- ->willReturn($entityMock);
-
- $resourceMock = $this->getMockBuilder(ProductResourceModel::class)
- ->disableOriginalConstructor()
- ->setMethods(['getAttributeRawValue', 'duplicate', 'getAttribute'])
- ->getMock();
- $resourceMock->expects($this->once())
- ->method('getAttributeRawValue')
- ->willReturn('urk-key-1');
- $resourceMock->expects($this->exactly(2))
- ->method('getAttribute')
- ->willReturn($attributeMock);
-
- $this->productMock->expects($this->exactly(2))
- ->method('getResource')
- ->willReturn($resourceMock);
$duplicateMock = $this->getMockBuilder(Product::class)
->addMethods(
@@ -204,9 +196,6 @@ public function testCopy(): void
)
->disableOriginalConstructor()
->getMock();
- $this->productFactoryMock->expects($this->once())
- ->method('create')
- ->willReturn($duplicateMock);
$duplicateMock->expects($this->once())->method('setOptions')->with([]);
$duplicateMock->expects($this->once())->method('setIsDuplicate')->with(true);
@@ -233,18 +222,14 @@ public function testCopy(): void
$duplicateMock->expects($this->once())
->method('setMetaDescription')
->with(null);
- $duplicateMock->expects($this->atLeastOnce())
- ->method('getStoreIds')->willReturn([]);
+
$duplicateMock->expects($this->atLeastOnce())
->method('setData')
->willReturn($duplicateMock);
$this->copyConstructorMock->expects($this->once())
->method('build')
->with($this->productMock, $duplicateMock);
- $duplicateMock->expects($this->once())
- ->method('setUrlKey')
- ->with('urk-key-2')
- ->willReturn($duplicateMock);
+
$duplicateMock->expects($this->once())
->method('save');
$this->metadata->expects($this->once())
@@ -256,7 +241,7 @@ public function testCopy(): void
->method('duplicate')
->with($this->productMock, $duplicateMock);
- $this->assertEquals($duplicateMock, $this->_model->copy($this->productMock));
+ $this->assertEquals($duplicateMock, $this->_model->copy($this->productMock, $duplicateMock));
}
/**
@@ -301,9 +286,6 @@ public function testUrlAlreadyExistsExceptionWhileCopyStoresUrl(): void
true,
['checkAttributeUniqueValue']
);
- $entityMock->expects($this->exactly(11))
- ->method('checkAttributeUniqueValue')
- ->willReturn(true, false);
$attributeMock = $this->getMockForAbstractClass(
AbstractAttribute::class,
@@ -322,9 +304,6 @@ public function testUrlAlreadyExistsExceptionWhileCopyStoresUrl(): void
->disableOriginalConstructor()
->setMethods(['getAttributeRawValue', 'duplicate', 'getAttribute'])
->getMock();
- $resourceMock->expects($this->any())
- ->method('getAttributeRawValue')
- ->willReturn('urk-key-1');
$resourceMock->expects($this->any())
->method('getAttribute')
->willReturn($attributeMock);
@@ -350,7 +329,6 @@ public function testUrlAlreadyExistsExceptionWhileCopyStoresUrl(): void
)
->disableOriginalConstructor()
->getMock();
- $this->productFactoryMock->expects($this->once())->method('create')->willReturn($duplicateMock);
$duplicateMock->expects($this->once())->method('setOptions')->with([]);
$duplicateMock->expects($this->once())->method('setIsDuplicate')->with(true);
@@ -366,21 +344,10 @@ public function testUrlAlreadyExistsExceptionWhileCopyStoresUrl(): void
$duplicateMock->expects($this->once())->method('setCreatedAt')->with(null);
$duplicateMock->expects($this->once())->method('setUpdatedAt')->with(null);
$duplicateMock->expects($this->once())->method('setId')->with(null);
- $duplicateMock->expects($this->atLeastOnce())->method('getStoreIds')->willReturn([1]);
$duplicateMock->expects($this->atLeastOnce())->method('setData')->willReturn($duplicateMock);
$this->copyConstructorMock->expects($this->once())->method('build')->with($this->productMock, $duplicateMock);
- $duplicateMock->expects(
- $this->exactly(11)
- )->method(
- 'setUrlKey'
- )->with(
- $this->stringContains('urk-key-')
- )->willReturn(
- $duplicateMock
- );
- $duplicateMock->expects($this->once())->method('save');
- $this->scopeOverriddenValueMock->expects($this->once())->method('containsValue')->willReturn(true);
+ $duplicateMock->expects($this->once())->method('save');
$this->metadata->expects($this->any())->method('getLinkField')->willReturn('linkField');
@@ -388,7 +355,6 @@ public function testUrlAlreadyExistsExceptionWhileCopyStoresUrl(): void
['linkField', null, '2'],
]);
- $this->expectException(UrlAlreadyExistsException::class);
- $this->_model->copy($this->productMock);
+ $this->_model->copy($this->productMock, $duplicateMock);
}
}
diff --git a/app/code/Magento/CatalogUrlRewrite/Plugin/Catalog/Model/Product/SetUrlsToCopiedProduct.php b/app/code/Magento/CatalogUrlRewrite/Plugin/Catalog/Model/Product/SetUrlsToCopiedProduct.php
new file mode 100644
index 0000000000000..8ea3fee9f6c56
--- /dev/null
+++ b/app/code/Magento/CatalogUrlRewrite/Plugin/Catalog/Model/Product/SetUrlsToCopiedProduct.php
@@ -0,0 +1,220 @@
+productResource = $productResource;
+ $this->scopeOverriddenValue = $scopeOverriddenValue;
+ $this->scopeConfig = $scopeConfig;
+ $this->urlRewriteCollectionFactory = $urlRewriteCollectionFactory;
+ $this->optionRepository = $optionRepository;
+ }
+
+ /**
+ * Sets default url to duplicated product
+ *
+ * @param Copier $subject
+ * @param Product $duplicate
+ * @param Product $product
+ * @return array
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function beforeCopy(Copier $subject, Product $product, Product $duplicate): array
+ {
+ $this->setDefaultUrl($product, $duplicate);
+ $product->unsetData('url_key');
+
+ return [$product, $duplicate];
+ }
+
+ /**
+ * Sets stores urls to duplicated product
+ *
+ * @param Copier $subject
+ * @param Product $duplicate
+ * @param Product $product
+ * @return Product
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function afterCopy(Copier $subject, Product $duplicate, Product $product): Product
+ {
+ $this->setStoresUrl($product, $duplicate);
+
+ return $duplicate;
+ }
+
+ /**
+ * Set default URL.
+ *
+ * @param Product $product
+ * @param Product $duplicate
+ * @return void
+ */
+ private function setDefaultUrl(Product $product, Product $duplicate): void
+ {
+ $duplicate->setStoreId(Store::DEFAULT_STORE_ID);
+ $productId = $product->getId();
+ $urlKey = $this->productResource->getAttributeRawValue(
+ $productId,
+ self::URL_KEY_ATTRIBUTE,
+ Store::DEFAULT_STORE_ID
+ );
+ do {
+ $urlKey = $this->modifyUrl($urlKey);
+ $duplicate->setUrlKey($urlKey);
+ } while ($this->isUrlRewriteExists($urlKey));
+ $duplicate->setData(self::URL_PATH_ATTRIBUTE, null);
+ }
+
+ /**
+ * Set URL for each store.
+ *
+ * @param Product $product
+ * @param Product $duplicate
+ * @return void
+ * @throws UrlAlreadyExistsException
+ * @throws LocalizedException
+ */
+ private function setStoresUrl(Product $product, Product $duplicate): void
+ {
+ $productId = $product->getId();
+ $attribute = $this->productResource->getAttribute(self::URL_KEY_ATTRIBUTE);
+ $duplicate->setData('save_rewrites_history', false);
+ foreach ($duplicate->getStoreIds() as $storeId) {
+ $useDefault = !$this->scopeOverriddenValue->containsValue(
+ ProductInterface::class,
+ $product,
+ self::URL_KEY_ATTRIBUTE,
+ $storeId
+ );
+ if ($useDefault) {
+ continue;
+ }
+
+ $duplicate->setStoreId($storeId);
+ $urlKey = $this->productResource->getAttributeRawValue($productId, self::URL_KEY_ATTRIBUTE, $storeId);
+ $iteration = 0;
+
+ do {
+ if ($iteration === 10) {
+ throw new UrlAlreadyExistsException();
+ }
+
+ $urlKey = $this->modifyUrl($urlKey);
+ $duplicate->setUrlKey($urlKey);
+ $iteration++;
+ } while (!$attribute->getEntity()->checkAttributeUniqueValue($attribute, $duplicate));
+ $duplicate->setData(self::URL_PATH_ATTRIBUTE, null);
+ $this->productResource->saveAttribute($duplicate, self::URL_PATH_ATTRIBUTE);
+ $this->productResource->saveAttribute($duplicate, self::URL_KEY_ATTRIBUTE);
+ }
+ }
+
+ /**
+ * Modify URL key.
+ *
+ * @param string $urlKey
+ * @return string
+ */
+ private function modifyUrl(string $urlKey): string
+ {
+ return preg_match(self::URL_PATTERN, $urlKey, $matches)
+ ? $matches[1] . '-' . ($matches[2] + 1)
+ : $urlKey . '-1';
+ }
+
+ /**
+ * Verify if generated url rewrite exists in url_rewrite table
+ *
+ * @param string $urlKey
+ * @return bool
+ */
+ private function isUrlRewriteExists(string $urlKey): bool
+ {
+ $urlRewriteCollection = $this->urlRewriteCollectionFactory->create();
+ $urlRewriteCollection->addFieldToFilter(UrlRewrite::ENTITY_TYPE, self::ENTITY_TYPE)
+ ->addFieldToFilter(UrlRewrite::REQUEST_PATH, $urlKey . $this->getUrlSuffix());
+
+ return $urlRewriteCollection->getSize() !== 0;
+ }
+
+ /**
+ * Returns default product url suffix config
+ *
+ * @return string|null
+ */
+ private function getUrlSuffix(): ?string
+ {
+ return $this->scopeConfig->getValue(ProductUrlPathGenerator::XML_PATH_PRODUCT_URL_SUFFIX);
+ }
+}
diff --git a/app/code/Magento/CatalogUrlRewrite/etc/di.xml b/app/code/Magento/CatalogUrlRewrite/etc/di.xml
index 5c25d11986eb9..0b3de5035d76f 100644
--- a/app/code/Magento/CatalogUrlRewrite/etc/di.xml
+++ b/app/code/Magento/CatalogUrlRewrite/etc/di.xml
@@ -70,4 +70,8 @@
+
+
+
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/SkuTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/SkuTest.php
index f557919897869..e70d57042d562 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/SkuTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/SkuTest.php
@@ -3,22 +3,32 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
+
namespace Magento\Catalog\Model\Product\Attribute\Backend;
+use Magento\Catalog\Model\Product;
+use Magento\Catalog\Model\Product\Attribute\Source\Status;
+use Magento\Catalog\Model\Product\Copier;
+use Magento\Catalog\Model\Product\Type;
+use Magento\Catalog\Model\Product\Visibility;
+use Magento\Catalog\Model\ProductFactory;
+use Magento\Catalog\Model\ProductRepository;
+use Magento\TestFramework\Helper\Bootstrap;
+use PHPUnit\Framework\TestCase;
+
/**
* Test class for \Magento\Catalog\Model\Product\Attribute\Backend\Sku.
* @magentoAppArea adminhtml
*/
-class SkuTest extends \PHPUnit\Framework\TestCase
+class SkuTest extends TestCase
{
/**
* @magentoDataFixture Magento/Catalog/_files/product_simple.php
*/
- public function testGenerateUniqueSkuExistingProduct()
+ public function testGenerateUniqueSkuExistingProduct(): void
{
- $repository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
- \Magento\Catalog\Model\ProductRepository::class
- );
+ $repository = Bootstrap::getObjectManager()->create(ProductRepository::class);
$product = $repository->get('simple');
$product->setId(null);
$this->assertEquals('simple', $product->getSku());
@@ -27,10 +37,10 @@ public function testGenerateUniqueSkuExistingProduct()
}
/**
- * @param $product \Magento\Catalog\Model\Product
+ * @param $product Product
* @dataProvider uniqueSkuDataProvider
*/
- public function testGenerateUniqueSkuNotExistingProduct($product)
+ public function testGenerateUniqueSkuNotExistingProduct(Product $product): void
{
$this->assertEquals('simple', $product->getSku());
$product->getResource()->getAttribute('sku')->getBackend()->beforeSave($product);
@@ -42,19 +52,16 @@ public function testGenerateUniqueSkuNotExistingProduct($product)
* @magentoAppArea adminhtml
* @magentoDbIsolation enabled
*/
- public function testGenerateUniqueLongSku()
+ public function testGenerateUniqueLongSku(): void
{
- $repository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
- \Magento\Catalog\Model\ProductRepository::class
- );
+ $repository = Bootstrap::getObjectManager()->create(ProductRepository::class);
+ $productFactory = Bootstrap::getObjectManager()->create(ProductFactory::class);
$product = $repository->get('simple');
$product->setSku('0123456789012345678901234567890123456789012345678901234567890123');
- /** @var \Magento\Catalog\Model\Product\Copier $copier */
- $copier = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
- \Magento\Catalog\Model\Product\Copier::class
- );
- $copier->copy($product);
+ /** @var Copier $copier */
+ $copier = Bootstrap::getObjectManager()->get(Copier::class);
+ $copier->copy($product, $productFactory->create());
$this->assertEquals('0123456789012345678901234567890123456789012345678901234567890123', $product->getSku());
$product->getResource()->getAttribute('sku')->getBackend()->beforeSave($product);
$this->assertEquals('01234567890123456789012345678901234567890123456789012345678901-1', $product->getSku());
@@ -65,48 +72,34 @@ public function testGenerateUniqueLongSku()
*
* @return array
*/
- public function uniqueSkuDataProvider()
+ public function uniqueSkuDataProvider(): array
{
- $product = $this->_getProduct();
+ $product = $this->getProduct();
return [[$product]];
}
/**
* Get product form data provider
*
- * @return \Magento\Catalog\Model\Product
+ * @return Product
*/
- protected function _getProduct()
+ private function getProduct(): Product
{
- /** @var $product \Magento\Catalog\Model\Product */
- $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
- \Magento\Catalog\Model\Product::class
- );
- $product->setTypeId(
- \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE
- )->setId(
- 1
- )->setAttributeSetId(
- 4
- )->setWebsiteIds(
- [1]
- )->setName(
- 'Simple Product'
- )->setSku(
- 'simple'
- )->setPrice(
- 10
- )->setDescription(
- 'Description with html tag'
- )->setVisibility(
- \Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH
- )->setStatus(
- \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED
- )->setCategoryIds(
- [2]
- )->setStockData(
- ['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]
- );
+ /** @var $product Product */
+ $product = Bootstrap::getObjectManager()->create(Product::class);
+ $product->setTypeId(Type::TYPE_SIMPLE)
+ ->setId(1)
+ ->setAttributeSetId(4)
+ ->setWebsiteIds([1])
+ ->setName('Simple Product')
+ ->setSku('simple')
+ ->setPrice(10)
+ ->setDescription('Description with html tag')
+ ->setVisibility(Visibility::VISIBILITY_BOTH)
+ ->setStatus(Status::STATUS_ENABLED)
+ ->setCategoryIds([2])
+ ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]);
+
return $product;
}
}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/CopierTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/CopierTest.php
index 6510e048f0e2d..9444f5914c944 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/CopierTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/CopierTest.php
@@ -7,36 +7,62 @@
namespace Magento\Catalog\Model\Product;
-use Magento\Catalog\Model\ProductRepository;
+use Magento\Catalog\Api\ProductRepositoryInterface;
+use Magento\Catalog\Model\ProductFactory;
use Magento\Store\Model\Store;
use Magento\TestFramework\Helper\Bootstrap;
use PHPUnit\Framework\TestCase;
/**
* Tests product copier.
+ * @magentoAppArea adminhtml
*/
class CopierTest extends TestCase
{
+ /**
+ * @var Copier
+ */
+ private $copier;
+
+ /**
+ * @var ProductRepositoryInterface
+ */
+ private $productRepository;
+
+ /**
+ * @var ProductFactory
+ */
+ private $productFactory;
+
+ /**
+ * @inheritdoc
+ */
+ protected function setUp(): void
+ {
+ $objectManager = Bootstrap::getObjectManager();
+ $this->copier = $objectManager->get(Copier::class);
+ $this->productRepository = $objectManager->get(ProductRepositoryInterface::class);
+ $this->productFactory = $objectManager->get(ProductFactory::class);
+ }
+
/**
* Tests copying of product.
*
* Case when url_key is set for store view and has equal value to default store.
*
* @magentoDataFixture Magento/Catalog/_files/product_simple_multistore_with_url_key.php
- * @magentoAppArea adminhtml
+ *
+ * @return void
*/
- public function testProductCopyWithExistingUrlKey()
+ public function testProductCopyWithExistingUrlKey(): void
{
$productSKU = 'simple_100';
- /** @var ProductRepository $productRepository */
- $productRepository = Bootstrap::getObjectManager()->get(ProductRepository::class);
- $copier = Bootstrap::getObjectManager()->get(Copier::class);
+ $product = $this->productRepository->get($productSKU);
+ $newProduct = $this->productFactory->create();
+ $duplicate = $this->copier->copy($product, $newProduct);
- $product = $productRepository->get($productSKU);
- $duplicate = $copier->copy($product);
-
- $duplicateStoreView = $productRepository->getById($duplicate->getId(), false, Store::DISTRO_STORE_ID);
- $productStoreView = $productRepository->get($productSKU, false, Store::DISTRO_STORE_ID);
+ $duplicateStoreView = $this->productRepository->getById($duplicate->getId(), false, Store::DISTRO_STORE_ID);
+ $productStoreView = $this->productRepository->get($productSKU, false, Store::DISTRO_STORE_ID);
$this->assertNotEquals(
$duplicateStoreView->getUrlKey(),
@@ -44,4 +70,30 @@ public function testProductCopyWithExistingUrlKey()
'url_key of product duplicate should be different then url_key of the product for the same store view'
);
}
+
+ /**
+ * Tests copying of product when url_key exists.
+ *
+ * @magentoDataFixture Magento/CatalogUrlRewrite/_files/product_simple.php
+ * @magentoDbIsolation disabled
+ *
+ * @return void
+ */
+ public function testProductCopyWithExistingUrlKeyPermanentType(): void
+ {
+ $product = $this->productRepository->get('simple');
+ $duplicate = $this->copier->copy($product, $this->productFactory->create());
+
+ $data = [
+ 'url_key' => 'new-url-key',
+ 'url_key_create_redirect' => $duplicate->getUrlKey(),
+ 'save_rewrites_history' => true,
+ ];
+ $duplicate->addData($data);
+ $this->productRepository->save($duplicate);
+
+ $secondDuplicate = $this->copier->copy($product, $this->productFactory->create());
+
+ $this->assertNotNull($secondDuplicate->getId());
+ }
}
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php
index 8acb243a706c2..47d0d9e77d11e 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php
@@ -40,18 +40,23 @@ class ProductTest extends \PHPUnit\Framework\TestCase
/**
* @var ProductRepositoryInterface
*/
- protected $productRepository;
+ private $productRepository;
/**
* @var Product
*/
- protected $_model;
+ private $model;
/**
* @var ObjectManagerInterface
*/
private $objectManager;
+ /**
+ * @var ProductFactory
+ */
+ private $productFactory;
+
/**
* @inheritdoc
*/
@@ -59,7 +64,8 @@ protected function setUp(): void
{
$this->objectManager = Bootstrap::getObjectManager();
$this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class);
- $this->_model = $this->objectManager->create(Product::class);
+ $this->model = $this->objectManager->create(Product::class);
+ $this->productFactory = $this->objectManager->create(ProductFactory::class);
}
/**
@@ -93,9 +99,9 @@ public static function tearDownAfterClass(): void
*/
public function testCanAffectOptions()
{
- $this->assertFalse($this->_model->canAffectOptions());
- $this->_model->canAffectOptions(true);
- $this->assertTrue($this->_model->canAffectOptions());
+ $this->assertFalse($this->model->canAffectOptions());
+ $this->model->canAffectOptions(true);
+ $this->assertTrue($this->model->canAffectOptions());
}
/**
@@ -107,7 +113,7 @@ public function testCanAffectOptions()
*/
public function testCRUD()
{
- $this->_model->setTypeId(
+ $this->model->setTypeId(
'simple'
)->setAttributeSetId(
4
@@ -128,7 +134,7 @@ public function testCRUD()
)->setStatus(
Status::STATUS_ENABLED
);
- $crud = new \Magento\TestFramework\Entity($this->_model, ['sku' => uniqid()]);
+ $crud = new \Magento\TestFramework\Entity($this->model, ['sku' => uniqid()]);
$crud->testCrud();
}
@@ -150,7 +156,7 @@ public function testMaximumDescriptionLength()
$random = Bootstrap::getObjectManager()->get(Random::class);
$longDescription = $random->getRandomString(70000);
- $this->_model->setTypeId(
+ $this->model->setTypeId(
'simple'
)->setAttributeSetId(
4
@@ -174,7 +180,7 @@ public function testMaximumDescriptionLength()
Status::STATUS_ENABLED
);
- $this->productRepository->save($this->_model);
+ $this->productRepository->save($this->model);
$product = $this->productRepository->get($sku);
$this->assertEquals($longDescription, $product->getDescription());
@@ -195,7 +201,7 @@ public function testCleanCache()
['catalog_product_999']
);
// potential bug: it cleans by cache tags, generated from its ID, which doesn't make much sense
- $this->_model->setId(999)->cleanCache();
+ $this->model->setId(999)->cleanCache();
$this->assertFalse(
\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
\Magento\Framework\App\CacheInterface::class
@@ -215,8 +221,8 @@ public function testAddImageToMediaGallery()
// Model accepts only files in tmp media path, we need to copy fixture file there
$mediaFile = $this->_copyFileToBaseTmpMediaPath(dirname(__DIR__) . '/_files/magento_image.jpg');
- $this->_model->addImageToMediaGallery($mediaFile);
- $gallery = $this->_model->getData('media_gallery');
+ $this->model->addImageToMediaGallery($mediaFile);
+ $gallery = $this->model->getData('media_gallery');
$this->assertNotEmpty($gallery);
$this->assertTrue(isset($gallery['images'][0]['file']));
$this->assertStringStartsWith('/m/a/magento_image', $gallery['images'][0]['file']);
@@ -259,18 +265,18 @@ protected function _copyFileToBaseTmpMediaPath($sourceFile)
*/
public function testDuplicate()
{
- $this->_model = $this->productRepository->get('simple');
+ $this->model = $this->productRepository->get('simple');
// fixture
/** @var \Magento\Catalog\Model\Product\Copier $copier */
$copier = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
\Magento\Catalog\Model\Product\Copier::class
);
- $duplicate = $copier->copy($this->_model);
+ $duplicate = $copier->copy($this->model, $this->productFactory->create());
try {
$this->assertNotEmpty($duplicate->getId());
- $this->assertNotEquals($duplicate->getId(), $this->_model->getId());
- $this->assertNotEquals($duplicate->getSku(), $this->_model->getSku());
+ $this->assertNotEquals($duplicate->getId(), $this->model->getId());
+ $this->assertNotEquals($duplicate->getSku(), $this->model->getSku());
$this->assertEquals(
Status::STATUS_DISABLED,
$duplicate->getStatus()
@@ -290,14 +296,14 @@ public function testDuplicate()
*/
public function testDuplicateSkuGeneration()
{
- $this->_model = $this->productRepository->get('simple');
+ $this->model = $this->productRepository->get('simple');
- $this->assertEquals('simple', $this->_model->getSku());
+ $this->assertEquals('simple', $this->model->getSku());
/** @var \Magento\Catalog\Model\Product\Copier $copier */
$copier = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
\Magento\Catalog\Model\Product\Copier::class
);
- $duplicate = $copier->copy($this->_model);
+ $duplicate = $copier->copy($this->model, $this->productFactory->create());
$this->assertEquals('simple-5', $duplicate->getSku());
}
@@ -329,18 +335,18 @@ public function testVisibilityApi()
{
$this->assertEquals(
[Status::STATUS_ENABLED],
- $this->_model->getVisibleInCatalogStatuses()
+ $this->model->getVisibleInCatalogStatuses()
);
$this->assertEquals(
[Status::STATUS_ENABLED],
- $this->_model->getVisibleStatuses()
+ $this->model->getVisibleStatuses()
);
- $this->_model->setStatus(Status::STATUS_DISABLED);
- $this->assertFalse($this->_model->isVisibleInCatalog());
+ $this->model->setStatus(Status::STATUS_DISABLED);
+ $this->assertFalse($this->model->isVisibleInCatalog());
- $this->_model->setStatus(Status::STATUS_ENABLED);
- $this->assertTrue($this->_model->isVisibleInCatalog());
+ $this->model->setStatus(Status::STATUS_ENABLED);
+ $this->assertTrue($this->model->isVisibleInCatalog());
$this->assertEquals(
[
@@ -348,16 +354,16 @@ public function testVisibilityApi()
Visibility::VISIBILITY_IN_CATALOG,
Visibility::VISIBILITY_BOTH,
],
- $this->_model->getVisibleInSiteVisibilities()
+ $this->model->getVisibleInSiteVisibilities()
);
- $this->assertFalse($this->_model->isVisibleInSiteVisibility());
- $this->_model->setVisibility(Visibility::VISIBILITY_IN_SEARCH);
- $this->assertTrue($this->_model->isVisibleInSiteVisibility());
- $this->_model->setVisibility(Visibility::VISIBILITY_IN_CATALOG);
- $this->assertTrue($this->_model->isVisibleInSiteVisibility());
- $this->_model->setVisibility(Visibility::VISIBILITY_BOTH);
- $this->assertTrue($this->_model->isVisibleInSiteVisibility());
+ $this->assertFalse($this->model->isVisibleInSiteVisibility());
+ $this->model->setVisibility(Visibility::VISIBILITY_IN_SEARCH);
+ $this->assertTrue($this->model->isVisibleInSiteVisibility());
+ $this->model->setVisibility(Visibility::VISIBILITY_IN_CATALOG);
+ $this->assertTrue($this->model->isVisibleInSiteVisibility());
+ $this->model->setVisibility(Visibility::VISIBILITY_BOTH);
+ $this->assertTrue($this->model->isVisibleInSiteVisibility());
}
/**
@@ -368,9 +374,9 @@ public function testVisibilityApi()
*/
public function testIsDuplicable()
{
- $this->assertTrue($this->_model->isDuplicable());
- $this->_model->setIsDuplicable(0);
- $this->assertFalse($this->_model->isDuplicable());
+ $this->assertTrue($this->model->isDuplicable());
+ $this->model->setIsDuplicable(0);
+ $this->assertFalse($this->model->isDuplicable());
}
/**
@@ -383,13 +389,13 @@ public function testIsDuplicable()
*/
public function testIsSalable()
{
- $this->_model = $this->productRepository->get('simple');
+ $this->model = $this->productRepository->get('simple');
// fixture
- $this->assertTrue((bool) $this->_model->isSalable());
- $this->assertTrue((bool) $this->_model->isSaleable());
- $this->assertTrue((bool) $this->_model->isAvailable());
- $this->assertTrue($this->_model->isInStock());
+ $this->assertTrue((bool) $this->model->isSalable());
+ $this->assertTrue((bool) $this->model->isSaleable());
+ $this->assertTrue((bool) $this->model->isAvailable());
+ $this->assertTrue($this->model->isInStock());
}
/**
@@ -402,13 +408,13 @@ public function testIsSalable()
*/
public function testIsNotSalableWhenStatusDisabled()
{
- $this->_model = $this->productRepository->get('simple');
+ $this->model = $this->productRepository->get('simple');
- $this->_model->setStatus(0);
- $this->assertFalse((bool) $this->_model->isSalable());
- $this->assertFalse((bool) $this->_model->isSaleable());
- $this->assertFalse((bool) $this->_model->isAvailable());
- $this->assertFalse($this->_model->isInStock());
+ $this->model->setStatus(0);
+ $this->assertFalse((bool) $this->model->isSalable());
+ $this->assertFalse((bool) $this->model->isSaleable());
+ $this->assertFalse((bool) $this->model->isAvailable());
+ $this->assertFalse($this->model->isInStock());
}
/**
@@ -419,8 +425,8 @@ public function testIsNotSalableWhenStatusDisabled()
*/
public function testIsVirtual()
{
- $this->assertFalse($this->_model->isVirtual());
- $this->assertFalse($this->_model->getIsVirtual());
+ $this->assertFalse($this->model->isVirtual());
+ $this->assertFalse($this->model->getIsVirtual());
/** @var $model \Magento\Catalog\Model\Product */
$model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
@@ -438,9 +444,9 @@ public function testIsVirtual()
*/
public function testToArray()
{
- $this->assertEquals([], $this->_model->toArray());
- $this->_model->setSku('sku')->setName('name');
- $this->assertEquals(['sku' => 'sku', 'name' => 'name'], $this->_model->toArray());
+ $this->assertEquals([], $this->model->toArray());
+ $this->model->setSku('sku')->setName('name');
+ $this->assertEquals(['sku' => 'sku', 'name' => 'name'], $this->model->toArray());
}
/**
@@ -450,8 +456,8 @@ public function testToArray()
*/
public function testFromArray()
{
- $this->_model->fromArray(['sku' => 'sku', 'name' => 'name', 'stock_item' => ['key' => 'value']]);
- $this->assertEquals(['sku' => 'sku', 'name' => 'name'], $this->_model->getData());
+ $this->model->fromArray(['sku' => 'sku', 'name' => 'name', 'stock_item' => ['key' => 'value']]);
+ $this->assertEquals(['sku' => 'sku', 'name' => 'name'], $this->model->getData());
}
/**
@@ -461,9 +467,9 @@ public function testFromArray()
*/
public function testSetOrigDataBackend()
{
- $this->assertEmpty($this->_model->getOrigData());
- $this->_model->setOrigData('key', 'value');
- $this->assertEquals('value', $this->_model->getOrigData('key'));
+ $this->assertEmpty($this->model->getOrigData());
+ $this->model->setOrigData('key', 'value');
+ $this->assertEquals('value', $this->model->getOrigData('key'));
}
/**
@@ -473,24 +479,24 @@ public function testSetOrigDataBackend()
*/
public function testReset()
{
- $model = $this->_model;
+ $model = $this->model;
$this->_assertEmpty($model);
- $this->_model->setData('key', 'value');
- $this->_model->reset();
+ $this->model->setData('key', 'value');
+ $this->model->reset();
$this->_assertEmpty($model);
- $this->_model->setOrigData('key', 'value');
- $this->_model->reset();
+ $this->model->setOrigData('key', 'value');
+ $this->model->reset();
$this->_assertEmpty($model);
- $this->_model->addCustomOption('key', 'value');
- $this->_model->reset();
+ $this->model->addCustomOption('key', 'value');
+ $this->model->reset();
$this->_assertEmpty($model);
- $this->_model->canAffectOptions(true);
- $this->_model->reset();
+ $this->model->canAffectOptions(true);
+ $this->model->reset();
$this->_assertEmpty($model);
}
@@ -519,7 +525,7 @@ public function testIsProductsHasSku()
$product2 = $this->productRepository->get('simple2');
$this->assertTrue(
- $this->_model->isProductsHasSku(
+ $this->model->isProductsHasSku(
[$product1->getId(), $product2->getId()]
)
);
@@ -533,7 +539,7 @@ public function testIsProductsHasSku()
public function testProcessBuyRequest()
{
$request = new \Magento\Framework\DataObject();
- $result = $this->_model->processBuyRequest($request);
+ $result = $this->model->processBuyRequest($request);
$this->assertInstanceOf(\Magento\Framework\DataObject::class, $result);
$this->assertArrayHasKey('errors', $result->getData());
}
@@ -545,7 +551,7 @@ public function testProcessBuyRequest()
*/
public function testValidate()
{
- $this->_model->setTypeId(
+ $this->model->setTypeId(
'simple'
)->setAttributeSetId(
4
@@ -568,7 +574,7 @@ public function testValidate()
)->setCollectExceptionMessages(
true
);
- $validationResult = $this->_model->validate();
+ $validationResult = $this->model->validate();
$this->assertEquals('SKU length should be 64 characters maximum.', $validationResult['sku']);
unset($validationResult['sku']);
foreach ($validationResult as $error) {
@@ -588,7 +594,7 @@ public function testValidateUniqueInputAttributeValue()
$attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
->get(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class)
->loadByCode(\Magento\Catalog\Model\Product::ENTITY, 'unique_input_attribute');
- $this->_model->setTypeId(
+ $this->model->setTypeId(
'simple'
)->setAttributeSetId(
4
@@ -611,7 +617,7 @@ public function testValidateUniqueInputAttributeValue()
true
);
- $validationResult = $this->_model->validate();
+ $validationResult = $this->model->validate();
$this->assertCount(1, $validationResult);
$this->assertContains(
@@ -633,11 +639,11 @@ public function testValidateUniqueInputAttributeOnTheSameProduct()
$attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
->get(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class)
->loadByCode(\Magento\Catalog\Model\Product::ENTITY, 'unique_input_attribute');
- $this->_model = $this->_model->loadByAttribute(
+ $this->model = $this->model->loadByAttribute(
'sku',
'simple product with unique input attribute'
);
- $this->_model->setTypeId(
+ $this->model->setTypeId(
'simple'
)->setAttributeSetId(
4
@@ -660,7 +666,7 @@ public function testValidateUniqueInputAttributeOnTheSameProduct()
true
);
- $validationResult = $this->_model->validate();
+ $validationResult = $this->model->validate();
$this->assertTrue($validationResult);
}
@@ -672,8 +678,8 @@ public function testValidateUniqueInputAttributeOnTheSameProduct()
*/
public function testGetOptions()
{
- $this->_model = $this->productRepository->get('simple_with_custom_options');
- $options = $this->_model->getOptions();
+ $this->model = $this->productRepository->get('simple_with_custom_options');
+ $options = $this->model->getOptions();
$this->assertNotEmpty($options);
$expectedValue = [
'3-1-select' => -3000.00,