Skip to content

Commit

Permalink
Merge pull request #7134 from GSadee/translatable-product-association…
Browse files Browse the repository at this point in the history
…-type-name

[ProductAssociationType] Translatable product association type's name
  • Loading branch information
pjedrzejewski committed Dec 20, 2016
2 parents da54dc8 + c0d4957 commit 694dc67
Show file tree
Hide file tree
Showing 39 changed files with 622 additions and 76 deletions.
1 change: 1 addition & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ After:
### Product / ProductBundle

* `ProductVariant::$name` property (and corresponding getter and setter) was removed to make it translatable. Therefore, `ProductVariantTranslation` was introduced with one `$name` property. All product variants names are migrated to new concept with migration `Version2016121415313`. Look at [this PR](https://github.com/Sylius/Sylius/pull/7091) if you have any problems with upgrade.
* `ProductAssociationType::$name` property (and corresponding getter and setter) was removed to make it translatable. Therefore, `ProductAssociationTypeTranslation` was introduced with one `$name` property. All product association types names are migrated to new concept with migration `Version20161219160441`. Look at [this PR](https://github.com/Sylius/Sylius/pull/7134) if you have any problems with upgrade.

### Promotion / PromotionBundle

Expand Down
56 changes: 56 additions & 0 deletions app/migrations/Version20161219160441.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace Sylius\Migrations;

use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* @author Grzegorz Sadowski <grzegorz.sadowski@lakion.com>
*/
class Version20161219160441 extends AbstractMigration implements ContainerAwareInterface
{
/**
* @var ContainerInterface
*/
private $container;

/**
* {@inheritdoc}
*/
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}

/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');

$defaultLocale = $this->container->getParameter('locale');

$this->addSql('CREATE TABLE sylius_product_association_type_translation (id INT AUTO_INCREMENT NOT NULL, translatable_id INT NOT NULL, name VARCHAR(255) DEFAULT NULL, locale VARCHAR(255) NOT NULL, INDEX IDX_4F618E52C2AC5D3 (translatable_id), UNIQUE INDEX sylius_product_association_type_translation_uniq_trans (translatable_id, locale), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
$this->addSql('ALTER TABLE sylius_product_association_type_translation ADD CONSTRAINT FK_4F618E52C2AC5D3 FOREIGN KEY (translatable_id) REFERENCES sylius_product_association_type (id) ON DELETE CASCADE');
$this->addSql('INSERT INTO sylius_product_association_type_translation (translatable_id, name, locale) SELECT id, name, "'.$defaultLocale.'" from sylius_product_association_type WHERE sylius_product_association_type.name IS NOT null');
$this->addSql('ALTER TABLE sylius_product_association_type DROP name');
}

/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');

$defaultLocale = $this->container->getParameter('locale');

$this->addSql('ALTER TABLE sylius_product_association_type ADD name VARCHAR(255) NOT NULL COLLATE utf8_unicode_ci');
$this->addSql('UPDATE sylius_product_association_type SET name = (SELECT name FROM sylius_product_association_type_translation WHERE sylius_product_association_type_translation.translatable_id = sylius_product_association_type.id AND sylius_product_association_type_translation.locale = "'.$defaultLocale.'")');
$this->addSql('DROP TABLE sylius_product_association_type_translation');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ Feature: Adding a new product association type
I want to add a new product association type to the store

Background:
Given I am logged in as an administrator
Given the store is available in "English (United States)"
And I am logged in as an administrator

@ui
Scenario: Adding a new product association type
When I want to create a new product association type
And I specify its code as "cross_sell"
And I specify its name as "Cross sell"
And I name it "Cross sell" in "English (United States)"
And I add it
Then I should be notified that it has been successfully created
And the product association type "Cross sell" should appear in the store
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ Feature: Editing a product association type
I want to be able to edit the product association type

Background:
Given the store has a product association type "Cross sell"
Given the store is available in "English (United States)"
And the store has a product association type "Cross sell"
And I am logged in as an administrator

@ui
Scenario: Changing a name of an existing product association type
When I want to modify the "Cross sell" product association type
And I rename it to "Up sell"
And I rename it to "Up sell" in "English (United States)"
And I save my changes
Then I should be notified that it has been successfully edited
And this product association type name should be "Up sell"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ Feature: Product association type unique code validation
I want to be prevented from adding two product association types with the same code

Background:
Given the store has a product association type "Cross sell" with a code "cross_sell"
Given the store is available in "English (United States)"
And the store has a product association type "Cross sell" with a code "cross_sell"
And I am logged in as an administrator

@ui
Scenario: Trying to add a new product association type with a taken code
When I want to create a new product association type
And I specify its code as "cross_sell"
And I specify its name as "Cross sell"
And I name it "Cross sell" in "English (United States)"
And I try to add it
Then I should be notified that product association type with this code already exists
And there should still be only one product association type with a code "cross_sell"
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ Feature: Product association type validation
I want to be prevented from adding it without specifying required fields

Background:
Given the store has a product association type "Cross sell"
Given the store is available in "English (United States)"
And the store has a product association type "Cross sell"
And I am logged in as an administrator

@ui
Scenario: Trying to add a new product association type without specifying its code
When I want to create a new product association type
And I specify its name as "Up sell"
And I name it "Up sell" in "English (United States)"
But I do not specify its code
And I try to add it
Then I should be notified that code is required
Expand All @@ -29,7 +30,7 @@ Feature: Product association type validation
@ui
Scenario: Trying to remove name from an existing product association type
When I want to modify the "Cross sell" product association type
And I remove its name
And I remove its name from "English (United States)" translation
And I try to save my changes
Then I should be notified that name is required
And this product association type should still be named "Cross sell"
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,23 @@ Feature: Viewing product's associations

Background:
Given the store operates on a single channel in "United States"
And that channel allows to shop using "English (United States)" and "Polish (Poland)" locales
And the store has a product "LG G3"
And the store has "LG headphones" and "LG earphones" products
And the store has also "LG G4" and "LG G5" products
And the store has a product association type "Accessories"
And the store has also a product association type "Alternatives"
And the store has "LG headphones", "LG earphones", "LG G4" and "LG G5" products
And the store has a product association type named "Accessories" in "English (United States)" locale and "Akcesoria" in "Polish (Poland)" locale
And the store has also a product association type named "Alternatives" in "English (United States)" locale and "Alternatywy" in "Polish (Poland)" locale
And the product "LG G3" has an association "Accessories" with products "LG headphones" and "LG earphones"
And the product "LG G3" has also an association "Alternatives" with products "LG G4" and "LG G5"

@ui
Scenario: Viewing a detailed page with product's associations
Scenario: Viewing a detailed page with product's associations in default locale
When I view product "LG G3"
Then I should see the product association "Accessories" with products "LG headphones" and "LG earphones"
And I should also see the product association "Alternatives" with products "LG G4" and "LG G5"

@ui
Scenario: Viewing a detailed page with product's associations after locale change
When I switch to the "Polish (Poland)" locale
And I view product "LG G3"
Then I should see the product association "Akcesoria" with products "LG headphones" and "LG earphones"
And I should also see the product association "Alternatywy" with products "LG G4" and "LG G5"
65 changes: 61 additions & 4 deletions src/Sylius/Behat/Context/Setup/ProductAssociationContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@
namespace Sylius\Behat\Context\Setup;

use Behat\Behat\Context\Context;
use Doctrine\Common\Persistence\ObjectManager;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Product\Model\ProductAssociationInterface;
use Sylius\Component\Product\Model\ProductAssociationTypeInterface;
use Sylius\Component\Product\Model\ProductAssociationTypeTranslationInterface;
use Sylius\Component\Product\Repository\ProductAssociationTypeRepositoryInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Resource\Model\TranslationInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;

/**
Expand All @@ -34,13 +38,18 @@ final class ProductAssociationContext implements Context
*/
private $productAssociationTypeFactory;

/**
* @var FactoryInterface
*/
private $productAssociationTypeTranslationFactory;

/**
* @var FactoryInterface
*/
private $productAssociationFactory;

/**
* @var RepositoryInterface
* @var ProductAssociationTypeRepositoryInterface
*/
private $productAssociationTypeRepository;

Expand All @@ -49,25 +58,36 @@ final class ProductAssociationContext implements Context
*/
private $productAssociationRepository;

/**
* @var ObjectManager
*/
private $objectManager;

/**
* @param SharedStorageInterface $sharedStorage
* @param FactoryInterface $productAssociationTypeFactory
* @param FactoryInterface $productAssociationTypeTranslationFactory
* @param FactoryInterface $productAssociationFactory
* @param RepositoryInterface $productAssociationTypeRepository
* @param ProductAssociationTypeRepositoryInterface $productAssociationTypeRepository
* @param RepositoryInterface $productAssociationRepository
* @param ObjectManager $objectManager
*/
public function __construct(
SharedStorageInterface $sharedStorage,
FactoryInterface $productAssociationTypeFactory,
FactoryInterface $productAssociationTypeTranslationFactory,
FactoryInterface $productAssociationFactory,
RepositoryInterface $productAssociationTypeRepository,
RepositoryInterface $productAssociationRepository
ProductAssociationTypeRepositoryInterface $productAssociationTypeRepository,
RepositoryInterface $productAssociationRepository,
ObjectManager $objectManager
) {
$this->sharedStorage = $sharedStorage;
$this->productAssociationTypeFactory = $productAssociationTypeFactory;
$this->productAssociationTypeTranslationFactory = $productAssociationTypeTranslationFactory;
$this->productAssociationFactory = $productAssociationFactory;
$this->productAssociationTypeRepository = $productAssociationTypeRepository;
$this->productAssociationRepository = $productAssociationRepository;
$this->objectManager = $objectManager;
}

/**
Expand All @@ -79,6 +99,21 @@ public function theStoreHasAProductAssociationType($name, $code = null)
$this->createProductAssociationType($name, $code);
}

/**
* @Given /^the store has(?:| also) a product association type named "([^"]+)" in ("[^"]+" locale) and "([^"]+)" in ("[^"]+" locale)$/
*/
public function itHasVariantNamedInAndIn($firstName, $firstLocale, $secondName, $secondLocale)
{
$productAssociationType = $this->createProductAssociationType($firstName);

$names = [$firstName => $firstLocale, $secondName => $secondLocale];
foreach ($names as $name => $locale) {
$this->addProductAssociationTypeTranslation($productAssociationType, $name, $locale);
}

$this->objectManager->flush();
}

/**
* @Given the store has :firstName and :secondName product association types
*/
Expand Down Expand Up @@ -114,6 +149,8 @@ public function theProductHasAnAssociationWithProducts(
/**
* @param string $name
* @param string|null $code
*
* @return ProductAssociationTypeInterface
*/
private function createProductAssociationType($name, $code = null)
{
Expand All @@ -128,6 +165,8 @@ private function createProductAssociationType($name, $code = null)

$this->productAssociationTypeRepository->add($productAssociationType);
$this->sharedStorage->set('product_association_type', $productAssociationType);

return $productAssociationType;
}

/**
Expand All @@ -153,6 +192,24 @@ private function createProductAssociation(
$this->productAssociationRepository->add($productAssociation);
}

/**
* @param ProductAssociationTypeInterface $productAssociationType
* @param string $name
* @param string $locale
*/
private function addProductAssociationTypeTranslation(
ProductAssociationTypeInterface $productAssociationType,
$name,
$locale
) {
/** @var ProductAssociationTypeTranslationInterface|TranslationInterface $translation */
$translation = $this->productAssociationTypeTranslationFactory->createNew();
$translation->setLocale($locale);
$translation->setName($name);

$productAssociationType->addTranslation($translation);
}

/**
* @param string $name
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace Sylius\Behat\Context\Transform;

use Behat\Behat\Context\Context;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Sylius\Component\Product\Repository\ProductAssociationTypeRepositoryInterface;
use Webmozart\Assert\Assert;

/**
Expand All @@ -21,14 +21,14 @@
final class ProductAssociationTypeContext implements Context
{
/**
* @var RepositoryInterface
* @var ProductAssociationTypeRepositoryInterface
*/
private $productAssociationTypeRepository;

/**
* @param RepositoryInterface $productAssociationTypeRepository
* @param ProductAssociationTypeRepositoryInterface $productAssociationTypeRepository
*/
public function __construct(RepositoryInterface $productAssociationTypeRepository)
public function __construct(ProductAssociationTypeRepositoryInterface $productAssociationTypeRepository)
{
$this->productAssociationTypeRepository = $productAssociationTypeRepository;
}
Expand All @@ -39,15 +39,21 @@ public function __construct(RepositoryInterface $productAssociationTypeRepositor
*/
public function getProductAssociationTypeByName($productAssociationTypeName)
{
$productAssociationType = $this->productAssociationTypeRepository->findOneBy([
'name' => $productAssociationTypeName,
]);
$productAssociationTypes = $this->productAssociationTypeRepository->findByName(
$productAssociationTypeName,
'en_US'
);

Assert::notNull(
$productAssociationType,
sprintf('Cannot find product association type with name %s', $productAssociationTypeName)
Assert::eq(
1,
count($productAssociationTypes),
sprintf(
'%d product association types has been found with name "%s".',
count($productAssociationTypes),
$productAssociationTypeName
)
);

return $productAssociationType;
return $productAssociationTypes[0];
}
}

0 comments on commit 694dc67

Please sign in to comment.