Your IP : 127.0.0.1
<?php
declare(strict_types=1);
namespace Destoff\Custom\Rewrite\Product;
use Magento\Catalog\Model\Product\Copier as MageCopier;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Attribute\ScopeOverriddenValue;
use Magento\Catalog\Model\Product;
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;
use Magento\Catalog\Model\Product\CopyConstructorInterface;
use Magento\Framework\App\RequestInterface;
class Copier extends MageCopier
{
public function __construct(
CopyConstructorInterface $copyConstructor,
ProductFactory $productFactory,
ScopeOverriddenValue $scopeOverriddenValue,
OptionRepository $optionRepository,
MetadataPool $metadataPool,
RequestInterface $request
) {
$this->productFactory = $productFactory;
$this->copyConstructor = $copyConstructor;
$this->scopeOverriddenValue = $scopeOverriddenValue;
$this->optionRepository = $optionRepository;
$this->metadataPool = $metadataPool;
$this->request = $request;
parent::__construct($copyConstructor, $productFactory, $scopeOverriddenValue, $optionRepository, $metadataPool);
}
public function copy(Product $product): Product
{
$data = $this->request->getParams();
$productCopy = clone $product;
$product->getWebsiteIds();
$product->getCategoryIds();
$metadata = $this->metadataPool->getMetadata(ProductInterface::class);
/** @var Product $duplicate */
$duplicate = $this->productFactory->create();
$productData = $productCopy->getData();
if(isset($productData['total_sale'])) {
$productData['total_sale'] = 0;
}
$productData = $this->removeStockItem($productData);
$duplicate->setData($productData);
$duplicate->setOptions([]);
$duplicate->setIsDuplicate(true);
$duplicate->setOriginalLinkId($productCopy->getData($metadata->getLinkField()));
$duplicate->setStatus(Status::STATUS_DISABLED);
$duplicate->setCreatedAt(null);
$duplicate->setUpdatedAt(null);
$duplicate->setId(null);
$duplicate->setStoreId(Store::DEFAULT_STORE_ID);
$this->copyConstructor->build($productCopy, $duplicate);
$this->setDefaultUrl($productCopy, $duplicate);
$this->setStoresUrl($productCopy, $duplicate);
$this->optionRepository->duplicate($productCopy, $duplicate);
$duplicate->setQuantityAndStockStatus([
'qty' => $data['product']['quantity_and_stock_status']['qty'] ?? null,
'is_in_stock' => $data['product']['quantity_and_stock_status']['is_in_stock'] ?? null
]);
$duplicate->setStockData(
[
'is_qty_decimal' => $data['product']['stock_data']['is_qty_decimal'] ?? 0
]
)->save();
return $duplicate;
}
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();
}
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);
}
private function modifyUrl(string $urlKey) : string
{
return preg_match('/(.*)-(\d+)$/', $urlKey, $matches)
? $matches[1] . '-' . ($matches[2] + 1)
: $urlKey . '-1';
}
private function removeStockItem(array $productData): array
{
if (isset($productData[ProductInterface::EXTENSION_ATTRIBUTES_KEY])) {
$extensionAttributes = $productData[ProductInterface::EXTENSION_ATTRIBUTES_KEY];
if (null !== $extensionAttributes->getStockItem()) {
$extensionAttributes->setData('stock_item', null);
}
}
return $productData;
}
}