mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
[Variation] Introduce code to OptionValue and Option
This commit is contained in:
parent
c438924272
commit
ccfb7cb7bd
32 changed files with 339 additions and 78 deletions
40
app/migrations/Version20151221121710.php
Normal file
40
app/migrations/Version20151221121710.php
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Sylius\Migrations;
|
||||
|
||||
use Doctrine\DBAL\Migrations\AbstractMigration;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
class Version20151221121710 extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function up(Schema $schema)
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||
|
||||
$this->addSql('ALTER TABLE sylius_product_option ADD code VARCHAR(255) NOT NULL');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_E4C0EBEF77153098 ON sylius_product_option (code)');
|
||||
$this->addSql('ALTER TABLE sylius_product_option_value ADD code VARCHAR(255) NOT NULL');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_F7FF7D4B77153098 ON sylius_product_option_value (code)');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function down(Schema $schema)
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||
|
||||
$this->addSql('DROP INDEX UNIQ_E4C0EBEF77153098 ON sylius_product_option');
|
||||
$this->addSql('ALTER TABLE sylius_product_option DROP code');
|
||||
$this->addSql('DROP INDEX UNIQ_F7FF7D4B77153098 ON sylius_product_option_value');
|
||||
$this->addSql('ALTER TABLE sylius_product_option_value DROP code');
|
||||
}
|
||||
}
|
||||
|
|
@ -7,9 +7,9 @@ Feature: Inventory tracking
|
|||
Background:
|
||||
Given store has default configuration
|
||||
And there are following options:
|
||||
| name | presentation | values |
|
||||
| T-Shirt color | Color | Red, Blue, Green |
|
||||
| T-Shirt size | Size | S, M, L |
|
||||
| code | name | presentation | values |
|
||||
| O1 |T-Shirt color | Color | Red[OV1], Blue[OV2], Green[OV3] |
|
||||
| O2 |T-Shirt size | Size | S[OV4], M[OV5], L[OV6] |
|
||||
And the following products exist:
|
||||
| name | price | options |
|
||||
| Super T-Shirt | 19.99 | T-Shirt size, T-Shirt color |
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ Feature: Product archetypes
|
|||
Background:
|
||||
Given store has default configuration
|
||||
And there are following options:
|
||||
| name | presentation | values |
|
||||
| T-Shirt color | Color | Red, Blue, Green |
|
||||
| T-Shirt size | Size | S, M, L |
|
||||
| Bag color | Color | Black, Light balsamic |
|
||||
| Beverage size | Size | Tall, Grande, Venti |
|
||||
| Beverage milk | Milk | None, Whole, Skinny, Soya |
|
||||
| Coffee variety | Variety | Colombian, Ethiopian |
|
||||
| code | name | presentation | values |
|
||||
| O1 |T-Shirt color | Color | Red[OV1], Blue[OV2], Green[OV3] |
|
||||
| O2 |T-Shirt size | Size | S[OV4], M[OV5], L[OV6] |
|
||||
| O3 | Bag color | Color | Black[OV7], Light balsamic[OV8] |
|
||||
| O4 | Beverage size | Size | Tall[OV9], Grande[OV10], Venti[OV11] |
|
||||
| O5 | Beverage milk | Milk | None[OV12], Whole[OV13], Skinny[OV14], Soya[OV15] |
|
||||
| O6 | Coffee variety | Variety | Colombian[OV16], Ethiopian[OV17] |
|
||||
And there are following attributes:
|
||||
| name | presentation | type |
|
||||
| T-Shirt collection | Collection | text |
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ Feature: Product options
|
|||
Background:
|
||||
Given store has default configuration
|
||||
And there are following options:
|
||||
| name | presentation | values |
|
||||
| T-Shirt color | Color | Red, Blue, Green |
|
||||
| T-Shirt size | Size | S, M, L |
|
||||
| code | name | presentation | values |
|
||||
| O1 |T-Shirt color | Color | Red[OV1], Blue[OV2], Green[OV3] |
|
||||
| O2 |T-Shirt size | Size | S[OV4], M[OV5], L[OV6] |
|
||||
And I am logged in as administrator
|
||||
|
||||
Scenario: Seeing index of all options
|
||||
|
|
@ -40,7 +40,8 @@ Feature: Product options
|
|||
|
||||
Scenario: Trying to create option without at least 2 values
|
||||
Given I am on the product option creation page
|
||||
When I fill in "Internal name" with "Bag color"
|
||||
When I fill in "Code" with "PO3"
|
||||
And I fill in "Internal name" with "Bag color"
|
||||
And I fill in "Presentation" with "Color"
|
||||
And I press "Create"
|
||||
Then I should still be on the product option creation page
|
||||
|
|
@ -49,13 +50,14 @@ Feature: Product options
|
|||
@javascript
|
||||
Scenario: Creating option with 4 possible values
|
||||
Given I am on the product option creation page
|
||||
When I fill in "Internal name" with "Bag color"
|
||||
When I fill in "Code" with "PO3"
|
||||
And I fill in "Internal name" with "Bag color"
|
||||
And I fill in "Presentation" with "Color"
|
||||
And I add following option values:
|
||||
| Black |
|
||||
| White |
|
||||
| Brown |
|
||||
| Purple |
|
||||
| OV7 | Black |
|
||||
| OV8 | White |
|
||||
| OV9 | Brown |
|
||||
| OV10 | Purple |
|
||||
And I press "Create"
|
||||
Then I should be on the product option index page
|
||||
And I should see "Option has been successfully created."
|
||||
|
|
@ -63,12 +65,13 @@ Feature: Product options
|
|||
@javascript
|
||||
Scenario: Values are listed after creating the option
|
||||
Given I am on the product option creation page
|
||||
When I fill in "Internal name" with "Mug type"
|
||||
When I fill in "Code" with "PO3"
|
||||
And I fill in "Internal name" with "Mug type"
|
||||
And I fill in "Presentation" with "Type"
|
||||
And I add following option values:
|
||||
| Normal mug |
|
||||
| Large mug |
|
||||
| MONSTER mug |
|
||||
| OV7 | Normal mug |
|
||||
| OV8 | Large mug |
|
||||
| OV9 | MONSTER mug |
|
||||
And I press "Create"
|
||||
Then I should be on the product option index page
|
||||
And I should see option with value containing "Normal mug" in that list
|
||||
|
|
@ -77,15 +80,15 @@ Feature: Product options
|
|||
Scenario: Adding values to existing option
|
||||
Given I am editing product option "T-Shirt size"
|
||||
And I add following option values:
|
||||
| XL |
|
||||
| XXL |
|
||||
| OV7 | XL |
|
||||
| OV8 | XXL |
|
||||
And I press "Save changes"
|
||||
Then I should be on the product option index page
|
||||
And "Option has been successfully updated." should appear on the page
|
||||
And I should see option with value containing "XXL" in the list
|
||||
|
||||
Scenario: Created options appear in the list
|
||||
Given I created option "Hat size" with values "S, M, L"
|
||||
Given I created option "Hat size" with values "S[VO3], M[VO4], L[V05]" and option code "PO3"
|
||||
When I go to the product option index page
|
||||
Then I should see 3 options in the list
|
||||
And I should see option with name "Hat size" in that list
|
||||
|
|
@ -105,3 +108,57 @@ Feature: Product options
|
|||
And I click "delete" from the confirmation modal
|
||||
Then I should be on the product option index page
|
||||
And I should not see option with name "T-Shirt color" in that list
|
||||
|
||||
Scenario: Cannot edit product option code
|
||||
When I am editing product option "T-Shirt color"
|
||||
Then the code field should be disabled
|
||||
|
||||
@javascript
|
||||
Scenario: Try add product option without code
|
||||
Given I am on the product option creation page
|
||||
When I fill in "Internal name" with "Bag color"
|
||||
And I fill in "Presentation" with "Color"
|
||||
And I add following option values:
|
||||
| OV7 | Black |
|
||||
| OV8 | White |
|
||||
And I press "Create"
|
||||
Then I should still be on the product option creation page
|
||||
And I should see "Please enter option code."
|
||||
|
||||
@javascript
|
||||
Scenario: Try add product option with existing code
|
||||
Given I am on the product option creation page
|
||||
When I fill in "Code" with "O1"
|
||||
And I fill in "Internal name" with "Bag color"
|
||||
And I fill in "Presentation" with "Color"
|
||||
And I add following option values:
|
||||
| OV7 | Black |
|
||||
| OV8 | White |
|
||||
And I press "Create"
|
||||
Then I should still be on the product option creation page
|
||||
And I should see "The option with given code already exists."
|
||||
|
||||
@javascript
|
||||
Scenario: Try add product option values without code
|
||||
Given I am on the product option creation page
|
||||
When I fill in "Code" with "O3"
|
||||
And I fill in "Internal name" with "Bag color"
|
||||
And I fill in "Presentation" with "Color"
|
||||
And I add option value "Black"
|
||||
And I add option value "White"
|
||||
And I press "Create"
|
||||
Then I should still be on the product option creation page
|
||||
And I should see "Please enter option value code."
|
||||
|
||||
@javascript
|
||||
Scenario: Try add product option value with existing code
|
||||
Given I am on the product option creation page
|
||||
When I fill in "Code" with "O3"
|
||||
And I fill in "Internal name" with "Bag color"
|
||||
And I fill in "Presentation" with "Color"
|
||||
And I add following option values:
|
||||
| OV1 | Black |
|
||||
| OV8 | White |
|
||||
And I press "Create"
|
||||
Then I should still be on the product option creation page
|
||||
And I should see "The option value with given code already exists."
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ Feature: Product variants
|
|||
Background:
|
||||
Given store has default configuration
|
||||
And there are following options:
|
||||
| name | presentation | values |
|
||||
| T-Shirt color | Color | Red, Blue, Green |
|
||||
| T-Shirt size | Size | S, M, L |
|
||||
| code | name | presentation | values |
|
||||
| O1 |T-Shirt color | Color | Red[OV1], Blue[OV2], Green[OV3] |
|
||||
| O2 |T-Shirt size | Size | S[OV4], M[OV5], L[OV6] |
|
||||
And the following products exist:
|
||||
| name | price | options |
|
||||
| Super T-Shirt | 19.99 | T-Shirt size, T-Shirt color |
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ Feature: Products
|
|||
Background:
|
||||
Given store has default configuration
|
||||
And there are following options:
|
||||
| name | presentation | values |
|
||||
| T-Shirt color | Color | Red, Blue, Green |
|
||||
| T-Shirt size | Size | S, M, L |
|
||||
| code | name | presentation | values |
|
||||
| O1 |T-Shirt color | Color | Red[OV1], Blue[OV2], Green[OV3] |
|
||||
| O2 |T-Shirt size | Size | S[OV4], M[OV5], L[OV6] |
|
||||
And there are following attributes:
|
||||
| name | type | configuration |
|
||||
| T-Shirt fabric | text | min:2,max:255 |
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ Feature: Cart
|
|||
| Clothing[TX1] > T-Shirts[TX2] |
|
||||
| Clothing[TX1] > PHP T-Shirts[TX3] |
|
||||
And there are following options:
|
||||
| name | presentation | values |
|
||||
| T-Shirt color | Color | Red, Blue, Green |
|
||||
| T-Shirt size | Size | S, M, L |
|
||||
| code | name | presentation | values |
|
||||
| O1 |T-Shirt color | Color | Red[OV1], Blue[OV2], Green[OV3] |
|
||||
| O2 |T-Shirt size | Size | S[OV4], M[OV5], L[OV6] |
|
||||
And the following products exist:
|
||||
| name | price | options | taxons | variants selection |
|
||||
| Super T-Shirt | 20.00 | T-Shirt size, T-Shirt color | T-Shirts | match |
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ Feature: Checkout starting
|
|||
| Clothing[TX1] > T-Shirts[TX2] |
|
||||
| Clothing[TX1] > PHP T-Shirts[TX3] |
|
||||
And there are following options:
|
||||
| name | presentation | values |
|
||||
| T-Shirt color | Color | Red, Blue, Green |
|
||||
| code | name | presentation | values |
|
||||
| O1 |T-Shirt color | Color | Red[OV1], Blue[OV2], Green[OV3] |
|
||||
And the following products exist:
|
||||
| name | price | options | taxons | variants selection |
|
||||
| Super T-Shirt | 20.00 | T-Shirt color | T-Shirts | match |
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ Feature: Browse products, categories, attributes and options in preferred langua
|
|||
| Clothing[TX1] > T-Shirts[TX2] |
|
||||
| Clothing[TX1] > PHP T-Shirts[TX3] |
|
||||
And there are following options:
|
||||
| name | presentation | values |
|
||||
| T-Shirt color | Color | Red, Blue, Green |
|
||||
| T-Shirt size | Size | S, M, L |
|
||||
| code | name | presentation | values |
|
||||
| O1 |T-Shirt color | Color | Red[OV1], Blue[OV2], Green[OV3] |
|
||||
| O2 |T-Shirt size | Size | S[OV4], M[OV5], L[OV6] |
|
||||
And there are following attributes:
|
||||
| name | presentation | type | choices |
|
||||
| T-Shirt fabric | Fabric | text | |
|
||||
|
|
|
|||
|
|
@ -31,32 +31,55 @@ class LoadProductOptionData extends DataFixture
|
|||
{
|
||||
// T-Shirt size option.
|
||||
$option = $this->createOption(
|
||||
'O1',
|
||||
'T-Shirt size',
|
||||
array($this->defaultLocale => 'Size', 'es_ES' => 'Talla'),
|
||||
array('S', 'M', 'L', 'XL', 'XXL')
|
||||
array(
|
||||
'OV1' => 'S',
|
||||
'OV2' => 'M',
|
||||
'OV3' => 'L',
|
||||
'OV4' => 'XL',
|
||||
'OV5' => 'XXL',
|
||||
)
|
||||
);
|
||||
$manager->persist($option);
|
||||
|
||||
// T-Shirt color option.
|
||||
$option = $this->createOption(
|
||||
'O2',
|
||||
'T-Shirt color',
|
||||
array($this->defaultLocale => 'Color'),
|
||||
array('Red', 'Blue', 'Green')
|
||||
array(
|
||||
'OV6' => 'Red',
|
||||
'OV7' => 'Blue',
|
||||
'OV8' => 'Green',
|
||||
)
|
||||
);
|
||||
$manager->persist($option);
|
||||
|
||||
// Sticker size option.
|
||||
$option = $this->createOption(
|
||||
'O3',
|
||||
'Sticker size',
|
||||
array($this->defaultLocale => 'Size', 'es_ES' => 'Talla'),
|
||||
array('3"', '5"', '7"'));
|
||||
array(
|
||||
'OV9' => '3"',
|
||||
'OV10' => '5"',
|
||||
'OV11' => '7"',
|
||||
)
|
||||
);
|
||||
$manager->persist($option);
|
||||
|
||||
// Mug type option.
|
||||
$option = $this->createOption(
|
||||
'O4',
|
||||
'Mug type',
|
||||
array($this->defaultLocale => 'Type', 'es_ES' => 'Tipo'),
|
||||
array('Medium mug', 'Double mug', 'MONSTER mug')
|
||||
array(
|
||||
'OV12' => 'Medium mug',
|
||||
'OV13' => 'Double mug',
|
||||
'OV14' => 'MONSTER mug',
|
||||
)
|
||||
);
|
||||
$manager->persist($option);
|
||||
|
||||
|
|
@ -72,19 +95,19 @@ class LoadProductOptionData extends DataFixture
|
|||
}
|
||||
|
||||
/**
|
||||
* Create an option.
|
||||
*
|
||||
* @param string $optionCode
|
||||
* @param string $name
|
||||
* @param array $presentationTranslation
|
||||
* @param array $values
|
||||
* @param array $presentationTranslation
|
||||
* @param array $valuesData
|
||||
*
|
||||
* @return OptionInterface
|
||||
*/
|
||||
protected function createOption($name, array $presentationTranslation, array $values)
|
||||
protected function createOption($optionCode, $name, array $presentationTranslation, array $valuesData)
|
||||
{
|
||||
/* @var $option OptionInterface */
|
||||
$option = $this->getProductOptionFactory()->createNew();
|
||||
$option->setName($name);
|
||||
$option->setCode($optionCode);
|
||||
|
||||
foreach ($presentationTranslation as $locale => $presentation) {
|
||||
$option->setCurrentLocale($locale);
|
||||
|
|
@ -92,12 +115,13 @@ class LoadProductOptionData extends DataFixture
|
|||
}
|
||||
$option->setCurrentLocale($this->defaultLocale);
|
||||
|
||||
foreach ($values as $text) {
|
||||
foreach ($valuesData as $code => $value) {
|
||||
/* @var $value OptionValueInterface */
|
||||
$value = $this->getProductOptionValueFactory()->createNew();
|
||||
$value->setValue($text);
|
||||
$optionValue = $this->getProductOptionValueFactory()->createNew();
|
||||
$optionValue->setValue($value);
|
||||
$optionValue->setCode($code);
|
||||
|
||||
$option->addValue($value);
|
||||
$option->addValue($optionValue);
|
||||
}
|
||||
|
||||
$this->setReference('Sylius.Option.'.$name, $option);
|
||||
|
|
|
|||
|
|
@ -145,26 +145,30 @@ class ProductContext extends DefaultContext
|
|||
public function thereAreOptions(TableNode $table)
|
||||
{
|
||||
foreach ($table->getHash() as $data) {
|
||||
$this->thereIsOption($data['name'], $data['values'], $data['presentation'], false);
|
||||
$this->thereIsOption($data['name'], $data['values'], $data['code'], $data['presentation'], false);
|
||||
}
|
||||
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^I created option "([^""]*)" with values "([^""]*)"$/
|
||||
* @Given /^I created option "([^""]*)" with values "([^""]*)" and option code "([^""]*)"$/
|
||||
*/
|
||||
public function thereIsOption($name, $values, $presentation = null, $flush = true)
|
||||
public function thereIsOption($name, $values, $optionCode, $presentation = null, $flush = true)
|
||||
{
|
||||
$optionValueFactory = $this->getFactory('product_option_value');
|
||||
|
||||
$option = $this->getFactory('product_option')->createNew();
|
||||
$option->setCode($optionCode);
|
||||
$option->setName($name);
|
||||
$option->setPresentation($presentation ?: $name);
|
||||
|
||||
foreach (explode(',', $values) as $value) {
|
||||
foreach(explode(',', $values) as $valueData) {
|
||||
|
||||
$valueData = preg_split("[\\[|\\]]", $valueData, -1, PREG_SPLIT_NO_EMPTY);
|
||||
$optionValue = $optionValueFactory->createNew();
|
||||
$optionValue->setValue(trim($value));
|
||||
$optionValue->setValue(trim($valueData[0]));
|
||||
$optionValue->setCode(trim($valueData[1]));
|
||||
|
||||
$option->addValue($optionValue);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,15 +51,15 @@ class AddCodeFormSubscriber implements EventSubscriberInterface
|
|||
public function preSetData(FormEvent $event)
|
||||
{
|
||||
$resource = $event->getData();
|
||||
$disabled = false;
|
||||
|
||||
if (!$resource instanceof CodeAwareInterface) {
|
||||
if ($resource instanceof CodeAwareInterface) {
|
||||
$disabled = (null !== $resource->getCode());
|
||||
} else if (null !== $resource) {
|
||||
throw new UnexpectedTypeException($resource, CodeAwareInterface::class);
|
||||
}
|
||||
|
||||
$form = $event->getForm();
|
||||
$disabled = (null !== $resource->getCode());
|
||||
|
||||
|
||||
$form->add('code', $this->type, array('label' => 'sylius.ui.code', 'disabled' => $disabled));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,10 +45,10 @@ class AddCodeFormSubscriberSpec extends ObjectBehavior
|
|||
$event->getData()->willReturn($resource);
|
||||
$event->getForm()->willReturn($form);
|
||||
|
||||
$resource->getCode()->shouldBeCalled()->willReturn('Code12');
|
||||
$resource->getCode()->willReturn(null);
|
||||
|
||||
$form
|
||||
->add('code', Argument::type('string'), Argument::containing(true))
|
||||
->add('code', Argument::type('string'), Argument::withEntry('disabled', false))
|
||||
->shouldBeCalled()
|
||||
;
|
||||
|
||||
|
|
@ -63,10 +63,10 @@ class AddCodeFormSubscriberSpec extends ObjectBehavior
|
|||
$event->getData()->willReturn($resource);
|
||||
$event->getForm()->willReturn($form);
|
||||
|
||||
$resource->getCode()->shouldBeCalled()->willReturn(null);
|
||||
$resource->getCode()->willReturn('Code12');
|
||||
|
||||
$form
|
||||
->add('code', Argument::type('string'), Argument::containing(false))
|
||||
->add('code', Argument::type('string'), Argument::withEntry('disabled', true))
|
||||
->shouldBeCalled()
|
||||
;
|
||||
|
||||
|
|
@ -79,6 +79,19 @@ class AddCodeFormSubscriberSpec extends ObjectBehavior
|
|||
$this->shouldThrow('\UnexpectedTypeException');
|
||||
}
|
||||
|
||||
function it_sets_code_as_enabled_when_resource_is_null(FormEvent $event, FormInterface $form)
|
||||
{
|
||||
$event->getForm()->willReturn($form);
|
||||
$event->getData()->willReturn(null);
|
||||
|
||||
$form
|
||||
->add('code', 'text', Argument::withEntry('disabled', false))
|
||||
->shouldBeCalled()
|
||||
;
|
||||
|
||||
$this->preSetData($event);
|
||||
}
|
||||
|
||||
function it_adds_code_with_specified_type(FormEvent $event, FormInterface $form, CodeAwareInterface $resource)
|
||||
{
|
||||
$this->beConstructedWith('currency');
|
||||
|
|
@ -86,10 +99,10 @@ class AddCodeFormSubscriberSpec extends ObjectBehavior
|
|||
$event->getData()->willReturn($resource);
|
||||
$event->getForm()->willReturn($form);
|
||||
|
||||
$resource->getCode()->shouldBeCalled()->willReturn('Code12');
|
||||
$resource->getCode()->willReturn('Code12');
|
||||
|
||||
$form
|
||||
->add('code', 'currency', Argument::containing(true))
|
||||
->add('code', 'currency', Argument::withEntry('disabled', true))
|
||||
->shouldBeCalled()
|
||||
;
|
||||
|
||||
|
|
@ -101,10 +114,10 @@ class AddCodeFormSubscriberSpec extends ObjectBehavior
|
|||
$event->getData()->willReturn($resource);
|
||||
$event->getForm()->willReturn($form);
|
||||
|
||||
$resource->getCode()->shouldBeCalled()->willReturn('Code12');
|
||||
$resource->getCode()->willReturn('Code12');
|
||||
|
||||
$form
|
||||
->add('code', 'text', Argument::containing(true))
|
||||
->add('code', 'text', Argument::withEntry('disabled', true))
|
||||
->shouldBeCalled()
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
namespace Sylius\Bundle\VariationBundle\Form\Type;
|
||||
|
||||
use Sylius\Bundle\ResourceBundle\Form\EventSubscriber\AddCodeFormSubscriber;
|
||||
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
|
|
@ -58,6 +59,7 @@ class OptionType extends AbstractResourceType
|
|||
'label' => false,
|
||||
'button_add_label' => 'sylius.form.option_value.add_value',
|
||||
))
|
||||
->addEventSubscriber(new AddCodeFormSubscriber())
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
namespace Sylius\Bundle\VariationBundle\Form\Type;
|
||||
|
||||
use Sylius\Bundle\ResourceBundle\Form\EventSubscriber\AddCodeFormSubscriber;
|
||||
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
|
|
@ -45,6 +46,7 @@ class OptionValueType extends AbstractResourceType
|
|||
->add('value', 'text', array(
|
||||
'label' => 'sylius.form.option_value.value',
|
||||
))
|
||||
->addEventSubscriber(new AddCodeFormSubscriber())
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
<generator strategy="AUTO" />
|
||||
</id>
|
||||
|
||||
<field name="code" column="code" type="string" unique="true" />
|
||||
<field name="name" column="name" type="string" />
|
||||
|
||||
<field name="createdAt" column="created_at" type="datetime">
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
<generator strategy="AUTO" />
|
||||
</id>
|
||||
|
||||
<field name="code" column="code" type="string" unique="true" />
|
||||
<field name="value" column="value" type="string" />
|
||||
</mapped-superclass>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@ Sylius\Component\Variation\Model\Option:
|
|||
exclusion_policy: ALL
|
||||
xml_root_name: option
|
||||
properties:
|
||||
code:
|
||||
exopse: true
|
||||
type: string
|
||||
name:
|
||||
expose: true
|
||||
type: string
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@ Sylius\Component\Variation\Model\OptionValue:
|
|||
exclusion_policy: ALL
|
||||
xml_root_name: option-value
|
||||
properties:
|
||||
code:
|
||||
expose: true
|
||||
type: string
|
||||
value:
|
||||
expose: true
|
||||
type: string
|
||||
|
|
|
|||
|
|
@ -23,6 +23,17 @@
|
|||
</class>
|
||||
|
||||
<class name="Sylius\Component\Variation\Model\Option">
|
||||
<constraint name="Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity">
|
||||
<option name="fields">code</option>
|
||||
<option name="message">sylius.option.code.unique</option>
|
||||
<option name="groups">sylius</option>
|
||||
</constraint>
|
||||
<property name="code">
|
||||
<constraint name="NotBlank">
|
||||
<option name="message">sylius.option.code.not_blank</option>
|
||||
<option name="groups">sylius</option>
|
||||
</constraint>
|
||||
</property>
|
||||
<property name="name">
|
||||
<constraint name="NotBlank">
|
||||
<option name="message">sylius.option.name.not_blank</option>
|
||||
|
|
@ -66,6 +77,17 @@
|
|||
</class>
|
||||
|
||||
<class name="Sylius\Component\Variation\Model\OptionValue">
|
||||
<constraint name="Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity">
|
||||
<option name="fields">code</option>
|
||||
<option name="message">sylius.option_value.code.unique</option>
|
||||
<option name="groups">sylius</option>
|
||||
</constraint>
|
||||
<property name="code">
|
||||
<constraint name="NotBlank">
|
||||
<option name="message">sylius.option_value.code.not_blank</option>
|
||||
<option name="groups">sylius</option>
|
||||
</constraint>
|
||||
</property>
|
||||
<property name="value">
|
||||
<constraint name="NotBlank">
|
||||
<option name="message">sylius.option_value.value.not_blank</option>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
sylius:
|
||||
option:
|
||||
code:
|
||||
not_blank: Please enter option code.
|
||||
unique: The option with given code already exists.
|
||||
name:
|
||||
not_blank: Please enter option name.
|
||||
min_length: Option name must be at least 1 character long.|Option name must be at least {{ limit }} characters long.
|
||||
|
|
@ -11,6 +14,9 @@ sylius:
|
|||
values:
|
||||
min_count: Please add at least {{ limit }} option value.|Please add at least {{ limit }} option values.
|
||||
option_value:
|
||||
code:
|
||||
not_blank: Please enter option value code.
|
||||
unique: The option value with given code already exists.
|
||||
value:
|
||||
not_blank: Please enter option value.
|
||||
variant:
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ namespace spec\Sylius\Bundle\VariationBundle\Form\Type;
|
|||
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Prophecy\Argument;
|
||||
use Sylius\Bundle\ResourceBundle\Form\EventSubscriber\AddCodeFormSubscriber;
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
use Symfony\Component\Form\FormTypeInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
|
@ -42,16 +43,25 @@ class OptionTypeSpec extends ObjectBehavior
|
|||
{
|
||||
$builder
|
||||
->add('name', 'text', Argument::any())
|
||||
->shouldBeCalled()
|
||||
->willReturn($builder)
|
||||
;
|
||||
|
||||
$builder
|
||||
->add('translations', 'a2lix_translationsForms', Argument::any())
|
||||
->shouldBeCalled()
|
||||
->willReturn($builder)
|
||||
;
|
||||
|
||||
$builder
|
||||
->add('values', 'collection', Argument::any())
|
||||
->shouldBeCalled()
|
||||
->willReturn($builder)
|
||||
;
|
||||
|
||||
$builder
|
||||
->addEventSubscriber(Argument::type(AddCodeFormSubscriber::class))
|
||||
->shouldBeCalled()
|
||||
->willReturn($builder)
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ namespace spec\Sylius\Bundle\VariationBundle\Form\Type;
|
|||
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Prophecy\Argument;
|
||||
use Sylius\Bundle\ResourceBundle\Form\EventSubscriber\AddCodeFormSubscriber;
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
use Symfony\Component\Form\FormTypeInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
|
@ -41,6 +42,13 @@ class OptionValueTypeSpec extends ObjectBehavior
|
|||
{
|
||||
$builder
|
||||
->add('value', 'text', Argument::any())
|
||||
->shouldBeCalled()
|
||||
->willReturn($builder)
|
||||
;
|
||||
|
||||
$builder
|
||||
->addEventSubscriber(Argument::type(AddCodeFormSubscriber::class))
|
||||
->shouldBeCalled()
|
||||
->willReturn($builder)
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -514,12 +514,22 @@ class WebContext extends BaseWebContext implements SnippetAcceptingContext
|
|||
*/
|
||||
public function iAddFollowingOptionValues(TableNode $table)
|
||||
{
|
||||
foreach ($table->getRows() as $i => $value) {
|
||||
foreach ($table->getRows() as $value) {
|
||||
$newItem = $this->addNewItemToFormCollection($this->getSession()->getPage(), 'option_values');
|
||||
$newItem->fillField('Value', $value[0]);
|
||||
$newItem->fillField('Value', $value[1]);
|
||||
$newItem->fillField('Code', $value[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^I add option value "([^""]*)"$/
|
||||
*/
|
||||
public function iAddOptionValue($optionValue)
|
||||
{
|
||||
$newItem = $this->addNewItemToFormCollection($this->getSession()->getPage(), 'option_values');
|
||||
$newItem->fillField('Value', $optionValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^I add choice "([^""]*)"$/
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-md-8 row-split">
|
||||
{{ form_row(form.code) }}
|
||||
{{ form_row(form.name) }}
|
||||
{{ form_row(form.translations) }}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th>{{ sylius_resource_sort('id', '#id') }}</th>
|
||||
<th>{{ sylius_resource_sort('code', 'sylius.ui.code'|trans) }}</th>
|
||||
<th>{{ sylius_resource_sort('name', 'sylius.product_option.name'|trans) }}</th>
|
||||
{#TODO allow sort by translation field#}
|
||||
{#<th>{{ sylius_resource_sort('presentation', 'sylius.product_option.presentation'|trans) }}</th>#}
|
||||
|
|
@ -21,6 +22,7 @@
|
|||
{% for option in options %}
|
||||
<tr id="{{ option.id }}">
|
||||
<td>{{ option.id }}</td>
|
||||
<td>{{ option.code }}</td>
|
||||
<td>{{ option.name }}</td>
|
||||
<td>{{ option.presentation }}</td>
|
||||
<td>
|
||||
|
|
|
|||
|
|
@ -26,6 +26,11 @@ class Option extends AbstractTranslatable implements OptionInterface
|
|||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $code;
|
||||
|
||||
/**
|
||||
* Internal name.
|
||||
*
|
||||
|
|
@ -78,6 +83,22 @@ class Option extends AbstractTranslatable implements OptionInterface
|
|||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCode()
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setCode($code)
|
||||
{
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
namespace Sylius\Component\Variation\Model;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Sylius\Component\Resource\Model\CodeAwareInterface;
|
||||
use Sylius\Component\Resource\Model\TimestampableInterface;
|
||||
|
||||
/**
|
||||
|
|
@ -20,7 +21,7 @@ use Sylius\Component\Resource\Model\TimestampableInterface;
|
|||
*
|
||||
* @author Paweł Jędrzejewski <pawel@sylius.org>
|
||||
*/
|
||||
interface OptionInterface extends TimestampableInterface, OptionTranslationInterface
|
||||
interface OptionInterface extends CodeAwareInterface, TimestampableInterface, OptionTranslationInterface
|
||||
{
|
||||
/**
|
||||
* Get internal name.
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ class OptionValue implements OptionValueInterface
|
|||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $code;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
|
@ -47,6 +52,22 @@ class OptionValue implements OptionValueInterface
|
|||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCode()
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setCode($code)
|
||||
{
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -11,23 +11,20 @@
|
|||
|
||||
namespace Sylius\Component\Variation\Model;
|
||||
|
||||
use Sylius\Component\Resource\Model\CodeAwareInterface;
|
||||
use Sylius\Component\Resource\Model\ResourceInterface;
|
||||
|
||||
/**
|
||||
* @author Paweł Jędrzejewski <pawel@sylius.org>
|
||||
*/
|
||||
interface OptionValueInterface extends ResourceInterface
|
||||
interface OptionValueInterface extends ResourceInterface, CodeAwareInterface
|
||||
{
|
||||
/**
|
||||
* Get option.
|
||||
*
|
||||
* @return OptionInterface
|
||||
*/
|
||||
public function getOption();
|
||||
|
||||
/**
|
||||
* Set option.
|
||||
*
|
||||
* @param OptionInterface $option
|
||||
*/
|
||||
public function setOption(OptionInterface $option = null);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,12 @@ class OptionSpec extends ObjectBehavior
|
|||
$this->getId()->shouldReturn(null);
|
||||
}
|
||||
|
||||
function it_has_mutable_code()
|
||||
{
|
||||
$this->setCode('O1');
|
||||
$this->getCode()->shouldReturn('O1');
|
||||
}
|
||||
|
||||
function it_should_not_have_name_by_default()
|
||||
{
|
||||
$this->getName()->shouldReturn(null);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@ class OptionValueSpec extends ObjectBehavior
|
|||
$this->getId()->shouldReturn(null);
|
||||
}
|
||||
|
||||
function it_has_mutable_code()
|
||||
{
|
||||
$this->setCode('OV1');
|
||||
$this->getCode()->shouldReturn('OV1');
|
||||
}
|
||||
|
||||
function it_should_not_belong_to_an_option_by_default()
|
||||
{
|
||||
$this->getOption()->shouldReturn(null);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue