Skip to content

Commit

Permalink
Handle DuplicateProductCommand with new shop constraint ShopCollectio…
Browse files Browse the repository at this point in the history
…n, improve copy of link rewrite
  • Loading branch information
jolelievre committed Dec 19, 2024
1 parent 54a9664 commit f9d6cf7
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 125 deletions.
138 changes: 39 additions & 99 deletions src/Adapter/Product/Update/ProductDuplicator.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
use PrestaShop\PrestaShop\Adapter\Product\Stock\Repository\StockAvailableRepository;
use PrestaShop\PrestaShop\Adapter\Product\Stock\Update\ProductStockProperties;
use PrestaShop\PrestaShop\Adapter\Product\Stock\Update\ProductStockUpdater;
use PrestaShop\PrestaShop\Adapter\Tools;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\CombinationId;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\CannotDuplicateProductException;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\CannotUpdateProductException;
Expand All @@ -54,6 +55,7 @@
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductType;
use PrestaShop\PrestaShop\Core\Domain\Shop\Exception\ShopAssociationNotFound;
use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopCollection;
use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopConstraint;
use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopId;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
Expand All @@ -73,106 +75,23 @@
*/
class ProductDuplicator extends AbstractMultiShopObjectModelRepository
{
/**
* @var ProductRepository
*/
private $productRepository;

/**
* @var HookDispatcherInterface
*/
private $hookDispatcher;

/**
* @var TranslatorInterface
*/
private $translator;

/**
* @var StringModifierInterface
*/
private $stringModifier;

/**
* @var Connection
*/
private $connection;

/**
* @var string
*/
private $dbPrefix;

/**
* @var CombinationRepository
*/
private $combinationRepository;

/**
* @var ProductSupplierRepository
*/
private $productSupplierRepository;

/**
* @var SpecificPriceRepository
*/
private $specificPriceRepository;

/**
* @var StockAvailableRepository
*/
private $stockAvailableRepository;

/**
* @var ProductStockUpdater
*/
private $productStockUpdater;

/**
* @var CombinationStockUpdater
*/
private $combinationStockUpdater;

/**
* @var ProductImageRepository
*/
private $productImageRepository;

/**
* @var ProductImagePathFactory
*/
private $productImageSystemPathFactory;

public function __construct(
ProductRepository $productRepository,
HookDispatcherInterface $hookDispatcher,
TranslatorInterface $translator,
StringModifierInterface $stringModifier,
Connection $connection,
string $dbPrefix,
CombinationRepository $combinationRepository,
ProductSupplierRepository $productSupplierRepository,
SpecificPriceRepository $specificPriceRepository,
StockAvailableRepository $stockAvailableRepository,
ProductStockUpdater $productStockUpdater,
CombinationStockUpdater $combinationStockUpdater,
ProductImageRepository $productImageRepository,
ProductImagePathFactory $productImageSystemPathFactory
protected readonly ProductRepository $productRepository,
protected readonly HookDispatcherInterface $hookDispatcher,
protected readonly TranslatorInterface $translator,
protected readonly StringModifierInterface $stringModifier,
protected readonly Connection $connection,
protected readonly string $dbPrefix,
protected readonly CombinationRepository $combinationRepository,
protected readonly ProductSupplierRepository $productSupplierRepository,
protected readonly SpecificPriceRepository $specificPriceRepository,
protected readonly StockAvailableRepository $stockAvailableRepository,
protected readonly ProductStockUpdater $productStockUpdater,
protected readonly CombinationStockUpdater $combinationStockUpdater,
protected readonly ProductImageRepository $productImageRepository,
protected readonly ProductImagePathFactory $productImageSystemPathFactory,
protected readonly Tools $tools,
) {
$this->productRepository = $productRepository;
$this->hookDispatcher = $hookDispatcher;
$this->translator = $translator;
$this->stringModifier = $stringModifier;
$this->connection = $connection;
$this->dbPrefix = $dbPrefix;
$this->combinationRepository = $combinationRepository;
$this->productSupplierRepository = $productSupplierRepository;
$this->specificPriceRepository = $specificPriceRepository;
$this->stockAvailableRepository = $stockAvailableRepository;
$this->productStockUpdater = $productStockUpdater;
$this->combinationStockUpdater = $combinationStockUpdater;
$this->productImageRepository = $productImageRepository;
$this->productImageSystemPathFactory = $productImageSystemPathFactory;
}

/**
Expand Down Expand Up @@ -241,7 +160,7 @@ private function duplicateProduct(ProductId $sourceProductId, ShopConstraint $sh

if ($shopConstraint->getShopId()) {
$targetDefaultShopId = $shopConstraint->getShopId();
} elseif ($shopConstraint->getShopGroupId()) {
} elseif ($shopConstraint->getShopGroupId() || ($shopConstraint instanceof ShopCollection && $shopConstraint->hasShopIds())) {
// If source default shop is in the group use it as new default, if not use the first shop from group
$targetDefaultShopId = null;
foreach ($shopIds as $groupShopId) {
Expand Down Expand Up @@ -270,6 +189,7 @@ private function duplicateProduct(ProductId $sourceProductId, ShopConstraint $sh
$shopProduct->date_add = date('Y-m-d H:i:s');
// Force a copy name to tell the two products apart (for each shop since name can be different on each shop)
$shopProduct->name = $this->getNewProductName($shopProduct->name);
$shopProduct->link_rewrite = $this->getNewProductLinkRewrite($shopProduct->link_rewrite);
// Force ID to update the new product
$shopProduct->id = $shopProduct->id_product = $newProductId->getValue();
// Force the desired default shop so that it doesn't switch back to the source one
Expand Down Expand Up @@ -327,6 +247,26 @@ private function getNewProductName(array $oldProductLocalizedNames): array
return $newProductLocalizedNames;
}

/**
* Provides duplicated product name
*
* @param array<int, string> $oldProductLocalizedLinkRewrites
*
* @return array<int, string>
*/
private function getNewProductLinkRewrite(array $oldProductLocalizedLinkRewrites): array
{
$newProductLocalizedLinkRewrites = [];
foreach ($oldProductLocalizedLinkRewrites as $langId => $oldName) {
$langId = (int) $langId;
$namePattern = $this->translator->trans('copy of %s', [], 'Admin.Catalog.Feature', Language::getLocaleById($langId));
$newName = sprintf($namePattern, $oldName);
$newProductLocalizedLinkRewrites[$langId] = $this->tools->linkRewrite($this->stringModifier->cutEnd($newName, ProductSettings::MAX_NAME_LENGTH));
}

return $newProductLocalizedLinkRewrites;
}

/**
* Duplicates related product entities & associations
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public function assertLocalizedPropertyForDefaultShop(string $productReference,
}

/**
* @Then product :productReference localized :fieldName for shops :shopReferences should be:
* @Then product :productReference localized :fieldName for shop(s) :shopReferences should be:
*
* localizedValues transformation handled by @see LocalizedArrayTransformContext
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
use PrestaShop\PrestaShop\Core\Domain\Product\Command\DuplicateProductCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\ProductException;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopCollection;
use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopConstraint;

class DuplicateProductFeatureContext extends AbstractProductFeatureContext
Expand Down Expand Up @@ -70,6 +71,23 @@ public function duplicateForShop(string $productReference, string $newProductRef
$this->getSharedStorage()->set($newProductReference, $newProductId->getValue());
}

/**
* @When I duplicate product :productReference to a :newProductReference for shops :shopReferences
*
* @param string $productReference
* @param string $newProductReference
* @param string $shopReferences
*/
public function duplicateForShopCollection(string $productReference, string $newProductReference, string $shopReferences): void
{
$newProductId = $this->getCommandBus()->handle(new DuplicateProductCommand(
$this->getSharedStorage()->get($productReference),
ShopCollection::shops($this->referencesToIds($shopReferences))
));

$this->getSharedStorage()->set($newProductReference, $newProductId->getValue());
}

/**
* @When I duplicate product :productReference to a :newProductReference for all shops
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
class PricesAssertionFeatureContext extends AbstractProductFeatureContext
{
/**
* @Then product :productReference should have following prices information for shops :shopReference:
* @Then product :productReference should have following prices information for shop(s) :shopReference:
*
* @param string $productReference
* @param string $shopReferences
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ Feature: Copy product from shop to shop.
And single shop context is loaded
And manufacturer studioDesign named "Studio Design" exists
And I create carrier "carrier1" with specified properties:
| name | ecoCarrier |
| name | ecoCarrier |
And I create carrier "carrier2" with specified properties:
| name | Fast carry |
| name | Fast carry |
# Prepare a few data
And I add new tax "us-tax-state-1" with following properties:
| name | US Tax (6%) |
Expand Down Expand Up @@ -206,9 +206,9 @@ Feature: Copy product from shop to shop.
| en-US | Its so smart |
| fr-FR | lel joke |
And product "productWithFieldsCopy" localized "link_rewrite" for shops shop1 should be:
| locale | value |
| en-US | smart-sunglasses |
| fr-FR | lunettes-de-soleil |
| locale | value |
| en-US | copy-of-smart-sunglasses |
| fr-FR | copie-de-lunettes-de-soleil |
And product productWithFieldsCopy should have following seo options for shops shop1:
| redirect_type | 301-product |
| redirect_target | productForRedirection |
Expand Down Expand Up @@ -281,9 +281,9 @@ Feature: Copy product from shop to shop.
| en-US | Its so smart3 |
| fr-FR | lel joke3 |
And product "productWithFieldsCopy3" localized "link_rewrite" for shops shop3 should be:
| locale | value |
| en-US | smart-sunglasses3 |
| fr-FR | lunettes-de-soleil3 |
| locale | value |
| en-US | copy-of-smart-sunglasses3 |
| fr-FR | copie-de-lunettes-de-soleil3 |
And product productWithFieldsCopy3 should have following seo options for shops shop3:
| redirect_type | 302-product |
| redirect_target | productForRedirection2 |
Expand Down Expand Up @@ -356,9 +356,9 @@ Feature: Copy product from shop to shop.
| en-US | Its so smart |
| fr-FR | lel joke |
And product "productWithFieldsOnAllShops" localized "link_rewrite" for shops "shop1,shop2" should be:
| locale | value |
| en-US | smart-sunglasses |
| fr-FR | lunettes-de-soleil |
| locale | value |
| en-US | copy-of-smart-sunglasses |
| fr-FR | copie-de-lunettes-de-soleil |
And product productWithFieldsOnAllShops should have following seo options for shops "shop1,shop2":
| redirect_type | 301-product |
| redirect_target | productForRedirection |
Expand Down Expand Up @@ -425,8 +425,8 @@ Feature: Copy product from shop to shop.
| fr-FR | lel joke3 |
And product "productWithFieldsOnAllShops" localized "link_rewrite" for shops shop3 should be:
| locale | value |
| en-US | smart-sunglasses3 |
| fr-FR | lunettes-de-soleil3 |
| en-US | copy-of-smart-sunglasses3 |
| fr-FR | copie-de-lunettes-de-soleil3 |
And product productWithFieldsOnAllShops should have following seo options for shops shop3:
| redirect_type | 302-product |
| redirect_target | productForRedirection2 |
Expand Down Expand Up @@ -500,9 +500,9 @@ Feature: Copy product from shop to shop.
| en-US | Its so smart |
| fr-FR | lel joke |
And product "productWithFieldsDefaultGroup" localized "link_rewrite" for shops "shop1,shop2" should be:
| locale | value |
| en-US | smart-sunglasses |
| fr-FR | lunettes-de-soleil |
| locale | value |
| en-US | copy-of-smart-sunglasses |
| fr-FR | copie-de-lunettes-de-soleil |
And product productWithFieldsDefaultGroup should have following seo options for shops "shop1,shop2":
| redirect_type | 301-product |
| redirect_target | productForRedirection |
Expand Down Expand Up @@ -576,9 +576,9 @@ Feature: Copy product from shop to shop.
| en-US | Its so smart3 |
| fr-FR | lel joke3 |
And product "productWithFieldsSecondGroup" localized "link_rewrite" for shops shop3 should be:
| locale | value |
| en-US | smart-sunglasses3 |
| fr-FR | lunettes-de-soleil3 |
| locale | value |
| en-US | copy-of-smart-sunglasses3 |
| fr-FR | copie-de-lunettes-de-soleil3 |
And product productWithFieldsSecondGroup should have following seo options for shops shop3:
| redirect_type | 302-product |
| redirect_target | productForRedirection2 |
Expand Down
Loading

0 comments on commit f9d6cf7

Please sign in to comment.