Create Archetype component and bundle to replace the product prototype

This commit is contained in:
Adam Elsodaney 2014-12-14 13:48:19 +00:00
parent 0f4e22f689
commit de7d000c9b
176 changed files with 2627 additions and 933 deletions

View file

@ -0,0 +1,52 @@
<?php
namespace Sylius\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20141214134644 extends AbstractMigration
{
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_prototype_attribute DROP FOREIGN KEY FK_E0C4700125998077');
$this->addSql('ALTER TABLE sylius_product_prototype_option DROP FOREIGN KEY FK_1AD7AAC525998077');
$this->addSql('CREATE TABLE sylius_product_archetype (id INT AUTO_INCREMENT NOT NULL, parent_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME DEFAULT NULL, INDEX IDX_A4001B52727ACA70 (parent_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
$this->addSql('CREATE TABLE sylius_product_archetype_option (product_archetype_id INT NOT NULL, option_id INT NOT NULL, INDEX IDX_BCE763A7FE884EAC (product_archetype_id), INDEX IDX_BCE763A7A7C41D6F (option_id), PRIMARY KEY(product_archetype_id, option_id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
$this->addSql('CREATE TABLE sylius_product_archetype_attribute (archetype_id INT NOT NULL, attribute_id INT NOT NULL, INDEX IDX_97763342732C6CC7 (archetype_id), INDEX IDX_97763342B6E62EFA (attribute_id), PRIMARY KEY(archetype_id, attribute_id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
$this->addSql('ALTER TABLE sylius_product_archetype ADD CONSTRAINT FK_A4001B52727ACA70 FOREIGN KEY (parent_id) REFERENCES sylius_product_archetype (id)');
$this->addSql('ALTER TABLE sylius_product_archetype_option ADD CONSTRAINT FK_BCE763A7FE884EAC FOREIGN KEY (product_archetype_id) REFERENCES sylius_product_archetype (id)');
$this->addSql('ALTER TABLE sylius_product_archetype_option ADD CONSTRAINT FK_BCE763A7A7C41D6F FOREIGN KEY (option_id) REFERENCES sylius_product_option (id)');
$this->addSql('ALTER TABLE sylius_product_archetype_attribute ADD CONSTRAINT FK_97763342732C6CC7 FOREIGN KEY (archetype_id) REFERENCES sylius_product_archetype (id)');
$this->addSql('ALTER TABLE sylius_product_archetype_attribute ADD CONSTRAINT FK_97763342B6E62EFA FOREIGN KEY (attribute_id) REFERENCES sylius_product_attribute (id)');
$this->addSql('DROP TABLE sylius_product_prototype');
$this->addSql('DROP TABLE sylius_product_prototype_attribute');
$this->addSql('DROP TABLE sylius_product_prototype_option');
}
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('ALTER TABLE sylius_product_archetype DROP FOREIGN KEY FK_A4001B52727ACA70');
$this->addSql('ALTER TABLE sylius_product_archetype_option DROP FOREIGN KEY FK_BCE763A7FE884EAC');
$this->addSql('ALTER TABLE sylius_product_archetype_attribute DROP FOREIGN KEY FK_97763342732C6CC7');
$this->addSql('CREATE TABLE sylius_product_prototype (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
$this->addSql('CREATE TABLE sylius_product_prototype_attribute (prototype_id INT NOT NULL, attribute_id INT NOT NULL, INDEX IDX_E0C4700125998077 (prototype_id), INDEX IDX_E0C47001B6E62EFA (attribute_id), PRIMARY KEY(prototype_id, attribute_id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
$this->addSql('CREATE TABLE sylius_product_prototype_option (prototype_id INT NOT NULL, option_id INT NOT NULL, INDEX IDX_1AD7AAC525998077 (prototype_id), INDEX IDX_1AD7AAC5A7C41D6F (option_id), PRIMARY KEY(prototype_id, option_id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
$this->addSql('ALTER TABLE sylius_product_prototype_attribute ADD CONSTRAINT FK_E0C47001B6E62EFA FOREIGN KEY (attribute_id) REFERENCES sylius_product_attribute (id)');
$this->addSql('ALTER TABLE sylius_product_prototype_attribute ADD CONSTRAINT FK_E0C4700125998077 FOREIGN KEY (prototype_id) REFERENCES sylius_product_prototype (id)');
$this->addSql('ALTER TABLE sylius_product_prototype_option ADD CONSTRAINT FK_1AD7AAC5A7C41D6F FOREIGN KEY (option_id) REFERENCES sylius_product_option (id)');
$this->addSql('ALTER TABLE sylius_product_prototype_option ADD CONSTRAINT FK_1AD7AAC525998077 FOREIGN KEY (prototype_id) REFERENCES sylius_product_prototype (id)');
$this->addSql('DROP TABLE sylius_product_archetype');
$this->addSql('DROP TABLE sylius_product_archetype_option');
$this->addSql('DROP TABLE sylius_product_archetype_attribute');
}
}

View file

@ -78,6 +78,8 @@
"sylius/addressing": "self.version",
"sylius/addressing-bundle": "self.version",
"sylius/api-bundle": "self.version",
"sylius/archetype": "self.version",
"sylius/archetype-bundle": "self.version",
"sylius/attribute": "self.version",
"sylius/attribute-bundle": "self.version",
"sylius/cart": "self.version",

21
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "0d6fa706b0b05fac0c7ee97b3bbb4391",
"hash": "f876b21c165d173aaa21b048ff16e92f",
"packages": [
{
"name": "ajbdev/authorizenet-php-api",
@ -147,6 +147,17 @@
"MIT"
],
"authors": [
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com",
"homepage": "http://www.jwage.com/",
"role": "Creator"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com",
"homepage": "http://www.instaclick.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
@ -2633,7 +2644,7 @@
"email": "stof@notk.org"
},
{
"name": "Knplabs",
"name": "KnpLabs",
"homepage": "http://knplabs.com"
},
{
@ -2684,7 +2695,7 @@
"email": "stof@notk.org"
},
{
"name": "Knplabs",
"name": "KnpLabs",
"homepage": "http://knplabs.com"
},
{
@ -5339,12 +5350,12 @@
"version": "v1.16.2",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"url": "https://github.com/fabpot/Twig.git",
"reference": "42f758d9fe2146d1f0470604fc05ee43580873fc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/42f758d9fe2146d1f0470604fc05ee43580873fc",
"url": "https://api.github.com/repos/fabpot/Twig/zipball/42f758d9fe2146d1f0470604fc05ee43580873fc",
"reference": "42f758d9fe2146d1f0470604fc05ee43580873fc",
"shasum": ""
},

View file

@ -0,0 +1,121 @@
@products
Feature: Product archetypes
In order to create similar products faster
As a store owner
I want to be able to create archetypes
Background:
Given there is default currency configured
And I am logged in as administrator
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 |
And there are following attributes:
| name | presentation |
| T-Shirt collection | Collection |
| T-Shirt fabric | T-Shirt fabric |
| Bag material | Material |
| Beverage calories | Calories |
| Coffee caffeine | Caffeine |
And there is archetype "T-Shirt" with following configuration:
| options | T-Shirt color, T-Shirt size |
| attributes | T-Shirt collection, T-Shirt fabric |
And there is archetype "Beverage" with following configuration:
| options | Beverage size, Beverage milk |
| attributes | Beverage calories |
Scenario: Seeing index of all archetypes
Given I am on the dashboard page
When I follow "Product archetypes"
Then I should be on the product archetype index page
And I should see 2 archetypes in the list
Scenario: Seeing empty index of archetypes
Given there are no product archetypes
When I am on the product archetype index page
Then I should see "There are no archetypes defined"
Scenario: Accessing the archetype creation form
Given I am on the dashboard page
When I follow "Product archetypes"
And I follow "Create archetype"
Then I should be on the product archetype creation page
Scenario: Submitting form without specifying the name
Given I am on the product archetype creation page
When I press "Create"
Then I should still be on the product archetype creation page
And I should see "Please enter archetype name."
Scenario: Creating Bag archetype with color as option
and material as attribute
Given I am on the product archetype creation page
When I fill in "Name" with "Bag"
And I select "Bag color" from "Options"
And I select "Bag material" from "Attributes"
And I press "Create"
Then I should be on the product archetype index page
And I should see "Archetype has been successfully created."
Scenario: Creating simple T-Shirt archetype with color and size
as options but without attributes
Given I am on the product archetype creation page
When I fill in "Name" with "Simple T-Shirt"
And I select "T-Shirt color" from "Options"
And I additionally select "T-Shirt size" from "Options"
And I press "Create"
Then I should be on the product archetype index page
And I should see "Archetype has been successfully created."
Scenario: Accessing the product building form from the list
Given I am on the product archetype index page
When I click "Build" near "T-Shirt"
Then I should be building product archetype "T-Shirt"
Scenario: Creating a product by building archetype
Given I am building product archetype "T-Shirt"
When I fill in the following:
| Name | Manchester United tee |
| Description | Interesting description |
| Price | 59.99 |
| T-Shirt fabric | Cotton 100% |
| T-Shirt collection | Champions League '11 |
And I press "Create"
Then I should be on the page of product "Manchester United tee"
And I should see "Product has been successfully created."
And "T-Shirt size" should appear on the page
Scenario: Accessing the editing form from the list
Given I am on the product archetype index page
When I click "edit" near "T-Shirt"
Then I should be editing product archetype "T-Shirt"
Scenario: Updating the archetype
Given I am editing product archetype "T-Shirt"
When I fill in "Name" with "Turbo T-Shirt"
And I press "Save changes"
Then I should be on the product archetype index page
And I should see "Archetype has been successfully updated."
Scenario: Inheriting the properties from parent archetype to a child archetype
Given I am on the product archetype creation page
When I fill in "Name" with "Coffee"
And I select "Beverage" from "Parent"
And I select "Coffee variety" from "Options"
And I select "Coffee caffeine" from "Attributes"
And I press "Create"
Then I should be on the product archetype index page
And I should see "Archetype has been successfully created."
@javascript
Scenario: Deleted archetype disappears from the list
Given I am on the product archetype index page
When I click "delete" near "T-Shirt"
And I click "delete" from the confirmation modal
Then I should be on the product archetype index page
And I should see "There are no archetypes defined"

View file

@ -1,103 +0,0 @@
@products
Feature: Product prototypes
In order to create similar products faster
As a store owner
I want to be able to create prototypes
Background:
Given there is default currency configured
And I am logged in as administrator
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 |
And there are following attributes:
| name | presentation |
| T-Shirt collection | Collection |
| T-Shirt fabric | T-Shirt fabric |
| Bag material | Material |
And there is prototype "T-Shirt" with following configuration:
| options | T-Shirt color, T-Shirt size |
| attributes | T-Shirt collection, T-Shirt fabric |
Scenario: Seeing index of all prototypes
Given I am on the dashboard page
When I follow "Product prototypes"
Then I should be on the product prototype index page
And I should see 1 prototype in the list
Scenario: Seeing empty index of prototypes
Given there are no product prototypes
When I am on the product prototype index page
Then I should see "There are no prototypes defined"
Scenario: Accessing the prototype creation form
Given I am on the dashboard page
When I follow "Product prototypes"
And I follow "Create prototype"
Then I should be on the product prototype creation page
Scenario: Submitting form without specifying the name
Given I am on the product prototype creation page
When I press "Create"
Then I should still be on the product prototype creation page
And I should see "Please enter prototype name."
Scenario: Creating Bag prototype with color as option
and material as attribute
Given I am on the product prototype creation page
When I fill in "Name" with "Bag"
And I select "Bag color" from "Options"
And I select "Bag material" from "Attributes"
And I press "Create"
Then I should be on the product prototype index page
And I should see "Prototype has been successfully created."
Scenario: Creating simple T-Shirt prototype with color and size
as options but without attributes
Given I am on the product prototype creation page
When I fill in "Name" with "Simple T-Shirt"
And I select "T-Shirt color" from "Options"
And I additionally select "T-Shirt size" from "Options"
And I press "Create"
Then I should be on the product prototype index page
And I should see "Prototype has been successfully created."
Scenario: Accessing the product building form from the list
Given I am on the product prototype index page
When I click "Build" near "T-Shirt"
Then I should be building product prototype "T-Shirt"
Scenario: Creating a product by building prototype
Given I am building product prototype "T-Shirt"
When I fill in the following:
| Name | Manchester United tee |
| Description | Interesting description |
| Price | 59.99 |
| T-Shirt fabric | Cotton 100% |
| T-Shirt collection | Champions League '11 |
And I press "Create"
Then I should be on the page of product "Manchester United tee"
And I should see "Product has been successfully created."
And "T-Shirt size" should appear on the page
Scenario: Accessing the editing form from the list
Given I am on the product prototype index page
When I click "edit" near "T-Shirt"
Then I should be editing product prototype "T-Shirt"
Scenario: Updating the prototype
Given I am editing product prototype "T-Shirt"
When I fill in "Name" with "Turbo T-Shirt"
And I press "Save changes"
Then I should be on the product prototype index page
And I should see "Prototype has been successfully updated."
@javascript
Scenario: Deleted prototype disappears from the list
Given I am on the product prototype index page
When I click "delete" near "T-Shirt"
And I click "delete" from the confirmation modal
Then I should be on the product prototype index page
And I should see "There are no prototypes defined"

View file

@ -1,5 +1,6 @@
suites:
Addressing : { namespace: Sylius, spec_path: src/Sylius/Component/Addressing }
Archetype : { namespace: Sylius, spec_path: src/Sylius/Component/Archetype }
Attribute : { namespace: Sylius, spec_path: src/Sylius/Component/Attribute }
Cart : { namespace: Sylius, spec_path: src/Sylius/Component/Cart }
Core : { namespace: Sylius, spec_path: src/Sylius/Component/Core }
@ -26,6 +27,7 @@ suites:
Variation : { namespace: Sylius, spec_path: src/Sylius/Component/Variation }
AddressingBundle : { namespace: Sylius, spec_path: src/Sylius/Bundle/AddressingBundle }
ArchetypeBundle : { namespace: Sylius, spec_path: src/Sylius/Bundle/ArchetypeBundle }
AttributeBundle : { namespace: Sylius, spec_path: src/Sylius/Bundle/AttributeBundle }
CartBundle : { namespace: Sylius, spec_path: src/Sylius/Bundle/CartBundle }
CoreBundle : { namespace: Sylius, spec_path: src/Sylius/Bundle/CoreBundle }

View file

@ -17,9 +17,9 @@ sylius_api_product_attribute:
resource: @SyliusApiBundle/Resources/config/routing/product_attribute.yml
prefix: /product-attributes
sylius_api_product_prototype:
resource: @SyliusApiBundle/Resources/config/routing/product_prototype.yml
prefix: /product-prototypes
sylius_api_product_archetype:
resource: @SyliusApiBundle/Resources/config/routing/product_archetype.yml
prefix: /product-archetypes
sylius_api_taxonomy:
resource: @SyliusApiBundle/Resources/config/routing/taxonomy.yml

View file

@ -0,0 +1,36 @@
# This file is part of the Sylius package.
# (c) Paweł Jędrzejewski
sylius_api_product_archetype_index:
path: /
methods: [GET]
defaults:
_controller: sylius.controller.product_archetype:indexAction
_sylius:
sortable: true
sorting:
name: desc
sylius_api_product_archetype_create:
path: /
methods: [POST]
defaults:
_controller: sylius.controller.product_archetype:createAction
sylius_api_product_archetype_update:
path: /{id}
methods: [PUT, PATCH]
defaults:
_controller: sylius.controller.product_archetype:updateAction
sylius_api_product_archetype_delete:
path: /{id}
methods: [DELETE]
defaults:
_controller: sylius.controller.product_archetype:deleteAction
sylius_api_product_archetype_show:
path: /{id}
methods: [GET]
defaults:
_controller: sylius.controller.product_archetype:showAction

View file

@ -1,36 +0,0 @@
# This file is part of the Sylius package.
# (c) Paweł Jędrzejewski
sylius_api_product_prototype_index:
path: /
methods: [GET]
defaults:
_controller: sylius.controller.product_prototype:indexAction
_sylius:
sortable: true
sorting:
name: desc
sylius_api_product_prototype_create:
path: /
methods: [POST]
defaults:
_controller: sylius.controller.product_prototype:createAction
sylius_api_product_prototype_update:
path: /{id}
methods: [PUT, PATCH]
defaults:
_controller: sylius.controller.product_prototype:updateAction
sylius_api_product_prototype_delete:
path: /{id}
methods: [DELETE]
defaults:
_controller: sylius.controller.product_prototype:deleteAction
sylius_api_product_prototype_show:
path: /{id}
methods: [GET]
defaults:
_controller: sylius.controller.product_prototype:showAction

View file

@ -0,0 +1,5 @@
vendor/
bin/
composer.phar
composer.lock

View file

@ -0,0 +1,6 @@
CHANGELOG
=========
### v0.13.0
* Initial dev release.

View file

@ -0,0 +1,105 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ArchetypeBundle\DependencyInjection;
use Sylius\Bundle\ResourceBundle\SyliusResourceBundle;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* This class contains the configuration information for the bundle.
*
* This information is solely responsible for how the different configuration
* sections are normalized, and merged.
*
* @author Adam Elsodaney <adam.elso@gmail.com>
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('sylius_archetype');
$rootNode
->addDefaultsIfNotSet()
->children()
->scalarNode('driver')->defaultValue(SyliusResourceBundle::DRIVER_DOCTRINE_ORM)->end()
->end()
;
$this->addClassesSection($rootNode);
$this->addValidationGroupsSection($rootNode);
return $treeBuilder;
}
/**
* Adds `validation_groups` section.
*
* @param ArrayNodeDefinition $node
*/
private function addValidationGroupsSection(ArrayNodeDefinition $node)
{
$node
->children()
->arrayNode('validation_groups')
->useAttributeAsKey('name')
->prototype('array')
->children()
->arrayNode('archetype')
->prototype('scalar')->end()
->defaultValue(array('sylius'))
->end()
->end()
->end()
->end()
->end()
;
}
/**
* Adds `classes` section.
*
* @param ArrayNodeDefinition $node
*/
private function addClassesSection(ArrayNodeDefinition $node)
{
$node
->children()
->arrayNode('classes')
->useAttributeAsKey('name')
->prototype('array')
->children()
->scalarNode('subject')->isRequired()->end()
->scalarNode('attribute')->isRequired()->defaultValue('Sylius\Component\Attribute\Model\Attribute')->end()
->scalarNode('option')->isRequired()->defaultValue('Sylius\Component\Variation\Model\Option')->end()
->arrayNode('archetype')
->addDefaultsIfNotSet()
->children()
->scalarNode('model')->defaultValue('Sylius\Component\Archetype\Model\Archetype')->end()
->scalarNode('controller')->defaultValue('Sylius\Bundle\ResourceBundle\Controller\ResourceController')->end()
->scalarNode('repository')->cannotBeEmpty()->end()
->scalarNode('form')->defaultValue('Sylius\Bundle\ArchetypeBundle\Form\Type\ArchetypeType')->end()
->end()
->end()
->end()
->end()
->end()
->end()
;
}
}

View file

@ -0,0 +1,119 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ArchetypeBundle\DependencyInjection;
use Sylius\Bundle\ResourceBundle\DependencyInjection\AbstractResourceExtension;
use Sylius\Bundle\ResourceBundle\SyliusResourceBundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
/**
* Archetype extension.
*
* @author Adam Elsodaney <adam.elso@gmail.com>
*/
class SyliusArchetypeExtension extends AbstractResourceExtension
{
/**
* {@inheritdoc}
*/
public function load(array $config, ContainerBuilder $container)
{
$this->configure(
$config,
new Configuration(),
$container,
self::CONFIGURE_LOADER | self::CONFIGURE_DATABASE | self::CONFIGURE_PARAMETERS | self::CONFIGURE_VALIDATORS
);
}
/**
* {@inheritdoc}
*/
public function process(array $config, ContainerBuilder $container)
{
$subjects = array();
$convertedConfig = array();
foreach ($config['classes'] as $subject => $parameters) {
$subjects[$subject] = $parameters;
unset($parameters['subject'], $parameters['attribute'], $parameters['option']);
foreach ($parameters as $resource => $classes) {
$convertedConfig[$subject.'_'.$resource] = $classes;
}
$this->createSubjectServices($container, $config['driver'], $subject, $convertedConfig);
if (!isset($config['validation_groups'][$subject]['archetype'])) {
$config['validation_groups'][$subject]['archetype'] = array('sylius');
}
}
$container->setParameter('sylius.archetype.subjects', $subjects);
$config['classes'] = $convertedConfig;
$config['validation_groups'] = $this->buildValidationConfig($config);
return $config;
}
/**
* Create services for every subject.
*
* @param ContainerBuilder $container
* @param string $driver
* @param string $subject
* @param array $config
*/
private function createSubjectServices(ContainerBuilder $container, $driver, $subject, array $config)
{
$archetypeAlias = $subject.'_archetype';
$archetypeClasses = $config[$archetypeAlias];
$archetypeFormType = new Definition($archetypeClasses['form']);
$archetypeFormType
->setArguments(array($archetypeClasses['model'], '%sylius.validation_group.'.$archetypeAlias.'%', $subject))
->addTag('form.type', array('alias' => 'sylius_'.$archetypeAlias))
;
$container->setDefinition('sylius.form.type.'.$archetypeAlias, $archetypeFormType);
$choiceTypeClasses = array(
SyliusResourceBundle::DRIVER_DOCTRINE_ORM => 'Sylius\Bundle\ArchetypeBundle\Form\Type\ArchetypeEntityChoiceType'
);
$archetypeChoiceFormType = new Definition($choiceTypeClasses[$driver]);
$archetypeChoiceFormType
->setArguments(array($subject, $archetypeClasses['model']))
->addTag('form.type', array('alias' => 'sylius_'.$archetypeAlias.'_choice'))
;
$container->setDefinition('sylius.form.type.'.$archetypeAlias.'_choice', $archetypeChoiceFormType);
}
/**
* @param array $config
* @return array
*/
private function buildValidationConfig(array $config)
{
$validationConfig = array();
foreach ($config['validation_groups'] as $subject => $parameters) {
foreach ($parameters as $resource => $validationGroups) {
$validationConfig[$subject . '_' . $resource] = $validationGroups;
}
}
return $validationConfig;
}
}

View file

@ -0,0 +1,157 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ArchetypeBundle\EventListener;
use Doctrine\Common\EventSubscriber;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
/**
* Doctrine listener used to manipulate mappings.
*
* @author Adam Elsodaney <adam.elso@gmail.com>
*/
class LoadMetadataSubscriber implements EventSubscriber
{
/**
* @var array
*/
protected $subjects;
/**
* Constructor
*
* @param array $subjects
*/
public function __construct(array $subjects)
{
$this->subjects = $subjects;
}
/**
* @return array
*/
public function getSubscribedEvents()
{
return array(
'loadClassMetadata',
);
}
/**
* @param LoadClassMetadataEventArgs $eventArgs
*/
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$metadata = $eventArgs->getClassMetadata();
foreach ($this->subjects as $subject => $class) {
if ($class['archetype']['model'] !== $metadata->getName()) {
continue;
}
$this->mapVariations($metadata, $class, $subject);
$this->mapAttributes($metadata, $class, $subject);
$this->mapParent($metadata, $class);
}
}
/**
* @param ClassMetadataInfo|ClassMetadata $metadata
* @param array $class
* @param string $subject
*/
private function mapAttributes(ClassMetadataInfo $metadata, array $class, $subject)
{
$attributeMapping = array(
'fieldName' => 'attributes',
'type' => ClassMetadataInfo::MANY_TO_MANY,
'targetEntity' => $class['attribute'],
'joinTable' => array(
'name' => sprintf('sylius_%s_archetype_attribute', $subject),
'joinColumns' => array(array(
'name' => 'archetype_id',
'referencedColumnName' => 'id',
'nullable' => false,
'unique' => false,
// 'onDelete' => 'CASCADE', ?
)),
'inverseJoinColumns' => array(array(
'name' => 'attribute_id',
'referencedColumnName' => 'id',
'nullable' => false,
'unique' => false,
// 'onDelete' => 'CASCADE', ?
))
),
);
$metadata->mapManyToMany($attributeMapping);
}
/**
* @param ClassMetadataInfo|ClassMetadata $metadata
* @param array $class
* @param string $subject
*/
private function mapVariations(ClassMetadataInfo $metadata, array $class, $subject)
{
$optionMapping = array(
'fieldName' => 'options',
'type' => ClassMetadataInfo::MANY_TO_MANY,
'targetEntity' => $class['option'],
'joinTable' => array(
'name' => sprintf('sylius_%s_archetype_option', $subject),
'joinColumns' => array(array(
'name' => sprintf('%s_archetype_id', $subject),
'referencedColumnName' => 'id',
'nullable' => false,
'unique' => false,
// 'onDelete' => 'CASCADE', ?
)),
'inverseJoinColumns' => array(array(
'name' => 'option_id',
'referencedColumnName' => 'id',
'nullable' => false,
'unique' => false,
// 'onDelete' => 'CASCADE', ?
))
),
);
$metadata->mapManyToMany($optionMapping);
}
/**
* @param ClassMetadataInfo|ClassMetadata $metadata
* @param array $class
*/
private function mapParent(ClassMetadataInfo $metadata, array $class)
{
$parentMapping = array(
'fieldName' => 'parent',
'type' => ClassMetadataInfo::MANY_TO_ONE,
'targetEntity' => $class['archetype']['model'],
'inversedBy' => 'children',
'joinColumn' => array(
'name' => 'parent_id',
'referencedColumnName' => 'id',
'nullable' => true,
'onDelete' => 'CASCADE'
),
);
$metadata->mapManyToOne($parentMapping);
}
}

View file

@ -0,0 +1,69 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ArchetypeBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* Archetype choice form type.
*
* @author Adam Elsodaney <adam.elso@gmail.com>
*/
abstract class ArchetypeChoiceType extends AbstractType
{
/**
* Name of the archetype subject.
*
* @var string
*/
protected $subjectName;
/**
* Archetype class name.
*
* @var string
*/
protected $className;
/**
* Constructor.
*
* @param string $subjectName
* @param string $className
*/
public function __construct($subjectName, $className)
{
$this->subjectName = $subjectName;
$this->className = $className;
}
/**
* {@inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver
->setDefaults(array(
'class' => $this->className
))
;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return sprintf('sylius_%s_archetype_choice', $this->subjectName);
}
}

View file

@ -0,0 +1,28 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ArchetypeBundle\Form\Type;
/**
* Archetype choice form type.
*
* @author Adam Elsodaney <adam.elso@gmail.com>
*/
class ArchetypeEntityChoiceType extends ArchetypeChoiceType
{
/**
* {@inheritdoc}
*/
public function getParent()
{
return 'entity';
}
}

View file

@ -0,0 +1,58 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ArchetypeBundle\Form\Type;
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
use Symfony\Component\Form\FormBuilderInterface;
/**
* Product archetype form type.
*
* @author Adam Elsodaney <adam.elso@gmail.com>
*/
class ArchetypeType extends AbstractResourceType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text', array(
'label' => 'sylius.form.archetype.name'
))
->add('parent', 'sylius_archetype_choice', array(
'required' => false,
'label' => 'sylius.form.archetype.parent',
'property' => 'name'
))
->add('attributes', 'sylius_archetype_attribute_choice', array(
'required' => false,
'multiple' => true,
'label' => 'sylius.form.archetype.attributes'
))
->add('options', 'sylius_archetype_option_choice', array(
'required' => false,
'multiple' => true,
'label' => 'sylius.form.archetype.options'
))
;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'sylius_archetype';
}
}

View file

@ -0,0 +1,74 @@
SyliusArchetypeBundle [![Build status...](https://secure.travis-ci.org/Sylius/SyliusArchetypeBundle.png?branch=master)](http://travis-ci.org/Sylius/SyliusArchetypeBundle)
=====================
Archetypes system for entities in Symfony2 applications.
Sylius
------
**Sylius** - Modern ecommerce for Symfony2. Visit [Sylius.org](http://sylius.org).
[phpspec](http://phpspec.net) examples
--------------------------------------
```bash
$ composer install
$ bin/phpspec run -fpretty
```
Documentation
-------------
Documentation is available on [**docs.sylius.org**](http://docs.sylius.org/en/latest/bundles/SyliusArchetypeBundle/index.html).
Contributing
------------
All informations about contributing to Sylius can be found on [this page](http://docs.sylius.org/en/latest/contributing/index.html).
Mailing lists
-------------
### Users
Questions? Feel free to ask on [users mailing list](http://groups.google.com/group/sylius).
### Developers
To contribute and develop this bundle, use the [developers mailing list](http://groups.google.com/group/sylius-dev).
Sylius twitter account
----------------------
If you want to keep up with updates, [follow the official Sylius account on twitter](http://twitter.com/Sylius).
Bug tracking
------------
This bundle uses [GitHub issues](https://github.com/Sylius/Sylius/issues).
If you have found bug, please create an issue.
Versioning
----------
Releases will be numbered with the format `major.minor.patch`.
And constructed with the following guidelines.
* Breaking backwards compatibility bumps the major.
* New additions without breaking backwards compatibility bumps the minor.
* Bug fixes and misc changes bump the patch.
For more information on SemVer, please visit [semver.org website](http://semver.org/).
This versioning method is same for all **Sylius** bundles and applications.
MIT License
-----------
License can be found [here](https://github.com/Sylius/SyliusArchetypeBundle/blob/master/Resources/meta/LICENSE).
Authors
-------
The bundle was originally created by [Adam Elsodaney](http://archfizz.com).
See the list of [contributors](https://github.com/Sylius/SyliusArchetypeBundle/contributors).

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
This file is part of the Sylius package.
(c) Paweł Jędrzejewski
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
-->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<mapped-superclass name="Sylius\Component\Archetype\Model\Archetype" table="sylius_archetype">
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="name" column="name" type="string" />
<field name="createdAt" column="created_at" type="datetime">
<gedmo:timestampable on="create" />
</field>
<field name="updatedAt" column="updated_at" type="datetime" nullable="true">
<gedmo:timestampable on="update" />
</field>
</mapped-superclass>
</doctrine-mapping>

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This file is part of the Sylius package.
(c) Paweł Jędrzejewski
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
-->
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="sylius.event_subscriber.archetype.load_metadata.class">Sylius\Bundle\ArchetypeBundle\EventListener\LoadMetadataSubscriber</parameter>
</parameters>
<services>
<service id="sylius.event_subscriber.archetype.load_metadata" class="%sylius.event_subscriber.archetype.load_metadata.class%">
<tag name="doctrine.event_subscriber" />
<argument>%sylius.archetype.subjects%</argument>
</service>
</services>
</container>

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This file is part of the Sylius package.
(c) Paweł Jędrzejewski
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
-->
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping
http://symfony.com/schema/dic/services/constraint-mapping-1.0.xsd">
<class name="Sylius\Component\Archetype\Model\Archetype">
<property name="name">
<constraint name="NotBlank">
<option name="message">sylius.archetype.name.not_blank</option>
<option name="groups">sylius</option>
</constraint>
<constraint name="Length">
<option name="min">2</option>
<option name="minMessage">sylius.archetype.name.min_length</option>
<option name="max">255</option>
<option name="maxMessage">sylius.archetype.name.max_length</option>
<option name="groups">sylius</option>
</constraint>
</property>
</class>
</constraint-mapping>

View file

@ -0,0 +1,19 @@
Copyright (c) 2011-2014 Paweł Jędrzejewski
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,7 @@
sylius:
form:
archetype:
name: Name
parent: Parent
attributes: Attributes
options: Options

View file

@ -0,0 +1,39 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ArchetypeBundle;
use Sylius\Bundle\ResourceBundle\AbstractResourceBundle;
use Sylius\Bundle\ResourceBundle\SyliusResourceBundle;
/**
* @author Adam Elsodaney <adam.elso@gmail.com>
*/
class SyliusArchetypeBundle extends AbstractResourceBundle
{
/**
* {@inheritdoc}
*/
public static function getSupportedDrivers()
{
return array(
SyliusResourceBundle::DRIVER_DOCTRINE_ORM
);
}
/**
* {@inheritdoc}
*/
protected function getModelNamespace()
{
return 'Sylius\Component\Archetype\Model';
}
}

View file

@ -0,0 +1,52 @@
{
"name": "sylius/archetype-bundle",
"type": "symfony-bundle",
"description": "Archetypes of models for your Symfony2 applications.",
"keywords": ["shop", "ecommerce", "products", "product", "assortment", "prototypes", "archetypes"],
"homepage": "http://sylius.org",
"license": "MIT",
"authors": [
{
"name": "Paweł Jędrzejewski",
"homepage": "http://pjedrzejewski.com"
},
{
"name": "Sylius project",
"homepage": "http://sylius.org"
},
{
"name": "Community contributions",
"homepage": "http://github.com/Sylius/Sylius/contributors"
}
],
"require": {
"php": ">=5.3.3",
"symfony/framework-bundle": "~2.3",
"stof/doctrine-extensions-bundle": "1.1.*",
"sylius/resource-bundle": "0.13.*@dev",
"sylius/archetype": "0.13.*@dev",
"sylius/attribute-bundle": "0.13.*@dev",
"sylius/variation-bundle": "0.13.*@dev"
},
"require-dev": {
"phpspec/phpspec": "~2.0",
"symfony/form": "~2.3",
"symfony/validator": "~2.3"
},
"config": {
"bin-dir": "bin"
},
"autoload": {
"psr-4": { "Sylius\\Bundle\\ArchetypeBundle\\": "" }
},
"autoload-dev": {
"psr-4": { "Sylius\\Bundle\\ArchetypeBundle\\spec\\": "spec/" }
},
"extra": {
"branch-alias": {
"dev-master": "0.13-dev"
}
},
"minimum-stability": "dev"
}

View file

@ -0,0 +1,131 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace spec\Sylius\Bundle\ArchetypeBundle\EventListener;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
/**
* @author Adam Elsodaney <adam.elso@gmail.com>
*/
class LoadMetadataSubscriberSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith(array(
'product' => array(
'subject' => 'Some\App\Product\Entity\Product',
'attribute' => 'Some\App\Product\Entity\Attribute',
'option' => 'Some\App\Product\Entity\Option',
'archetype' => array(
'model' => 'Some\App\Product\Entity\Archetype',
),
),
));
}
function it_is_initializable()
{
$this->shouldHaveType('Sylius\Bundle\ArchetypeBundle\EventListener\LoadMetadataSubscriber');
}
function it_is_a_Doctrine_event_subscriber()
{
$this->shouldImplement('Doctrine\Common\EventSubscriber');
}
function it_subscribes_to_loadClassMetadata_events_dispatched_by_Doctrine()
{
$this->getSubscribedEvents()->shouldReturn(array('loadClassMetadata'));
}
function it_does_not_add_mapping_if_the_class_is_not_configured_to_be_an_archetype(LoadClassMetadataEventArgs $eventArgs, ClassMetadataInfo $metadata)
{
$eventArgs->getClassMetadata()->willReturn($metadata);
$metadata->getName()->willReturn('KeepMoving\ThisClass\DoesNot\Concern\You');
$metadata->mapManyToMany(Argument::any())->shouldNotBeCalled();
$metadata->mapOneToMany(Argument::any())->shouldNotBeCalled();
$metadata->mapManyToOne(Argument::any())->shouldNotBeCalled();
$this->loadClassMetadata($eventArgs);
}
function it_maps_attributes_and_options_to_archetypes(LoadClassMetadataEventArgs $eventArgs, ClassMetadataInfo $metadata)
{
$eventArgs->getClassMetadata()->willReturn($metadata);
$metadata->getName()->willReturn('Some\App\Product\Entity\Archetype');
$attributeMapping = array(
'fieldName' => 'attributes',
'type' => ClassMetadataInfo::MANY_TO_MANY,
'targetEntity' => 'Some\App\Product\Entity\Attribute',
'joinTable' => array(
'name' => 'sylius_product_archetype_attribute',
'joinColumns' => array(array(
'name' => 'archetype_id', // or `product_archetype_id` ?
'referencedColumnName' => 'id',
'nullable' => false,
'unique' => false,
)),
'inverseJoinColumns' => array(array(
'name' => 'attribute_id', // or `product_attribute_id` ?
'referencedColumnName' => 'id',
'nullable' => false,
'unique' => false,
))
),
);
$optionMapping = array(
'fieldName' => 'options',
'type' => ClassMetadataInfo::MANY_TO_MANY,
'targetEntity' => 'Some\App\Product\Entity\Option',
'joinTable' => array(
'name' => 'sylius_product_archetype_option',
'joinColumns' => array(array(
'name' => 'product_archetype_id',
'referencedColumnName' => 'id',
'nullable' => false,
'unique' => false,
)),
'inverseJoinColumns' => array(array(
'name' => 'option_id',
'referencedColumnName' => 'id',
'nullable' => false,
'unique' => false,
))
),
);
$parentMapping = array(
'fieldName' => 'parent',
'type' => ClassMetadataInfo::MANY_TO_ONE,
'targetEntity' => 'Some\App\Product\Entity\Archetype',
'inversedBy' => 'children',
'joinColumn' => array(
'name' => 'parent_id',
'referencedColumnName' => 'id',
'nullable' => true,
'onDelete' => 'CASCADE'
),
);
$metadata->mapManyToMany($attributeMapping)->shouldBeCalled();
$metadata->mapManyToMany($optionMapping)->shouldBeCalled();
$metadata->mapManyToOne($parentMapping)->shouldBeCalled();
$this->loadClassMetadata($eventArgs);
}
}

View file

@ -0,0 +1,79 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace spec\Sylius\Bundle\ArchetypeBundle\Form\Type;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* @author Adam Elsodaney <adam.elso@gmail.com>
*/
class ArchetypeTypeSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('Archetype', array('sylius'));
}
function it_is_initializable()
{
$this->shouldHaveType('Sylius\Bundle\ArchetypeBundle\Form\Type\ArchetypeType');
}
function it_is_a_form_type()
{
$this->shouldImplement('Symfony\Component\Form\FormTypeInterface');
}
function it_builds_form_with_proper_fields(FormBuilder $builder)
{
$builder
->add('name', 'text', Argument::any())
->willReturn($builder)
;
$builder
->add('parent', 'sylius_archetype_choice', Argument::any())
->willReturn($builder)
;
$builder
->add('attributes', 'sylius_archetype_attribute_choice', Argument::any())
->willReturn($builder)
;
$builder
->add('options', 'sylius_archetype_option_choice', Argument::any())
->willReturn($builder)
;
$this->buildForm($builder, array());
}
function it_defines_assigned_data_class(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'Archetype',
'validation_groups' => array('sylius')
))->shouldBeCalled();
$this->setDefaultOptions($resolver);
}
function it_has_valid_name()
{
$this->getName()->shouldReturn('sylius_archetype');
}
}

View file

@ -40,8 +40,8 @@ class SyliusAttributeExtension extends AbstractResourceExtension
*/
public function process(array $config, ContainerBuilder $container)
{
$convertedConfig = array();
$subjects = array();
$convertedConfig = array();
foreach ($config['classes'] as $subject => $parameters) {
$subjects[$subject] = $parameters;

View file

@ -12,7 +12,9 @@
namespace Sylius\Bundle\AttributeBundle\EventListener;
use Doctrine\Common\EventSubscriber;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
/**
* Doctrine listener used to manipulate mappings.
@ -70,7 +72,7 @@ class LoadMetadataSubscriber implements EventSubscriber
))
);
$metadata->mapManyToOne($subjectMapping);
$this->mapManyToOne($metadata, $subjectMapping);
$attributeMapping = array(
'fieldName' => 'attribute',
@ -83,7 +85,16 @@ class LoadMetadataSubscriber implements EventSubscriber
))
);
$metadata->mapManyToOne($attributeMapping);
$this->mapManyToOne($metadata, $attributeMapping);
}
}
/**
* @param ClassMetadataInfo|ClassMetadata $metadata
* @param array $subjectMapping
*/
private function mapManyToOne(ClassMetadataInfo $metadata, array $subjectMapping)
{
$metadata->mapManyToOne($subjectMapping);
}
}

View file

@ -12,5 +12,5 @@ sylius:
property:
name: Interner Name
presentation: Präsentation
prototype:
archetype:
properties: Eigenschaften

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Nombre interno
presentation: Presentación
prototype:
archetype:
name: Nombre
properties: Propiedades

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Nom interne
presentation: Présentation
prototype:
archetype:
name: Nom
properties: Propriétés

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Interne naam
presentation: Weergave
prototype:
archetype:
name: Naam
properties: Eigenschappen

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Nazwa w systemie
presentation: Nazwa publiczna
prototype:
archetype:
name: Nazwa
properties: Właściwości

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Внутреннее название
presentation: Публичное название
prototype:
archetype:
name: Название
properties: Свойства

View file

@ -9,6 +9,6 @@ sylius:
properties: Vlastnosti
meta_keywords: Meta kľúčové slová
meta_description: Meta popis
prototype:
archetype:
name: Názov
properties: Vlastnosti

View file

@ -5,5 +5,5 @@ sylius:
label:
product:
name: Ime
prototype:
archetype:
name: Ime

View file

@ -46,7 +46,7 @@ sylius:
not_blank: Bitte wählen Sie eine Einstellung.
value:
not_blank: Bitte geben Sie einen Wert für diese Einstellung an.
prototype:
archetype:
name:
not_blank: Bitte geben Sie einen Namen für dieses Muster an.
min_length: 'Der Name des Musters muss mindestens 1 Zeichen lang sein.|Der Name des Musters muss mindestens {{ limit }} Zeichen lang sein.'

View file

@ -46,7 +46,7 @@ sylius:
not_blank: Por favor seleccione una propiedad.
value:
not_blank: Por favor introduzca un valor para la propiedad.
prototype:
archetype:
name:
not_blank: Por favor introduzca el nombre del prototipo.
min_length: 'El nombre del prototipo debe tener al menos 1 carácter.|El nombre del prototipo debe tener al menos {{ limit }} caracteres.'

View file

@ -46,7 +46,7 @@ sylius:
not_blank: Veuillez choisir une propriété.
value:
not_blank: Veuillez saisir la propriété du produit.
prototype:
archetype:
name:
not_blank: Veuillez saisir le nom du prototype.
min_length: 'Le nom du prototype de la propriété ne doit pas dépasser 1 caractère.|Le nom du prototype ne doit pas dépasser les {{ limit }} caractères.'

View file

@ -46,7 +46,7 @@ sylius:
not_blank: Selecteer een eigenschap.
value:
not_blank: Voer een eigenschap waarde in.
prototype:
archetype:
name:
not_blank: Voer een prototype naam in.
min_length: 'Prototype naam moet minstens 1 teken lang zijn.|Prototype naam moet minstens {{ limit }} tekens lang zijn.'

View file

@ -46,7 +46,7 @@ sylius:
not_blank: Пожалуйста выберите свойство.
value:
not_blank: Пожалуйста выберите значение свойства.
prototype:
archetype:
name:
not_blank: Пожалуйста введите название прототипа.
min_length: 'Название прототипа должно быть не менее 1 символа.|Название прототипа должно быть не менее {{ limit }} символов.'

View file

@ -43,6 +43,7 @@ abstract class Kernel extends BaseKernel
new \Sylius\Bundle\SettingsBundle\SyliusSettingsBundle(),
new \Sylius\Bundle\CartBundle\SyliusCartBundle(),
new \Sylius\Bundle\ProductBundle\SyliusProductBundle(),
new \Sylius\Bundle\ArchetypeBundle\SyliusArchetypeBundle(),
new \Sylius\Bundle\VariationBundle\SyliusVariationBundle(),
new \Sylius\Bundle\AttributeBundle\SyliusAttributeBundle(),
new \Sylius\Bundle\TaxationBundle\SyliusTaxationBundle(),

View file

@ -75,6 +75,18 @@ sylius_product:
repository: Sylius\Bundle\CoreBundle\Doctrine\ORM\ProductRepository
form: Sylius\Bundle\CoreBundle\Form\Type\ProductType
sylius_archetype:
classes:
product:
subject: Sylius\Component\Core\Model\Product
attribute: Sylius\Component\Product\Model\Attribute
option: Sylius\Component\Product\Model\Option
archetype:
model: Sylius\Component\Product\Model\Archetype
controller: Sylius\Bundle\ProductBundle\Controller\ArchetypeController
repository: Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository
form: Sylius\Bundle\ProductBundle\Form\Type\ArchetypeType
sylius_attribute: ~
sylius_variation:

View file

@ -13,31 +13,31 @@ namespace Sylius\Bundle\FixturesBundle\DataFixtures\ORM;
use Doctrine\Common\Persistence\ObjectManager;
use Sylius\Bundle\FixturesBundle\DataFixtures\DataFixture;
use Sylius\Component\Product\Model\PrototypeInterface;
use Sylius\Component\Product\Model\ArchetypeInterface;
/**
* Sample product prototypes.
* Sample product archetype.
*
* @author Paweł Jędrzejewski <pawel@sylius.org>
*/
class LoadProductPrototypeData extends DataFixture
class LoadProductArchetypeData extends DataFixture
{
/**
* {@inheritdoc}
*/
public function load(ObjectManager $manager)
{
$prototype = $this->createPrototype('T-Shirt', array('T-Shirt size', 'T-Shirt color'), array('T-Shirt brand', 'T-Shirt collection', 'T-Shirt material'));
$manager->persist($prototype);
$archetype = $this->createArchetype('T-Shirt', array('T-Shirt size', 'T-Shirt color'), array('T-Shirt brand', 'T-Shirt collection', 'T-Shirt material'));
$manager->persist($archetype);
$prototype = $this->createPrototype('Sticker', array('Sticker size'), array('Sticker resolution', 'Sticker paper'));
$manager->persist($prototype);
$archetype = $this->createArchetype('Sticker', array('Sticker size'), array('Sticker resolution', 'Sticker paper'));
$manager->persist($archetype);
$prototype = $this->createPrototype('Mug', array('Mug type'), array('Mug material'));
$manager->persist($prototype);
$archetype = $this->createArchetype('Mug', array('Mug type'), array('Mug material'));
$manager->persist($archetype);
$prototype = $this->createPrototype('Book', array(), array('Book author', 'Book ISBN', 'Book pages'));
$manager->persist($prototype);
$archetype = $this->createArchetype('Book', array(), array('Book author', 'Book ISBN', 'Book pages'));
$manager->persist($archetype);
$manager->flush();
}
@ -51,29 +51,29 @@ class LoadProductPrototypeData extends DataFixture
}
/**
* Create prototype.
* Create archetype.
*
* @param string $name
* @param array $options
* @param array $properties
*
* @return PrototypeInterface
* @return ArchetypeInterface
*/
protected function createPrototype($name, array $options, array $properties)
protected function createArchetype($name, array $options, array $properties)
{
/* @var $prototype PrototypeInterface */
$prototype = $this->getProductPrototypeRepository()->createNew();
$prototype->setName($name);
/* @var $archetype ArchetypeInterface */
$archetype = $this->getProductArchetypeRepository()->createNew();
$archetype->setName($name);
foreach ($options as $option) {
$prototype->addOption($this->getReference('Sylius.Option.'.$option));
$archetype->addOption($this->getReference('Sylius.Option.'.$option));
}
foreach ($properties as $attribute) {
$prototype->addAttribute($this->getReference('Sylius.Attribute.'.$attribute));
$archetype->addAttribute($this->getReference('Sylius.Attribute.'.$attribute));
}
$this->setReference('Sylius.Prototype.'.$name, $prototype);
$this->setReference('Sylius.Archetype.'.$name, $archetype);
return $prototype;
return $archetype;
}
}

View file

@ -77,6 +77,7 @@ class LoadProductAttributeData extends DataFixture
{
/* @var $attribute AttributeInterface */
$attribute = $this->getProductAttributeRepository()->createNew();
$attribute->setName($name);
$attribute->setPresentation($presentation);

View file

@ -81,27 +81,27 @@ class ProductContext extends DefaultContext
}
/**
* @Given /^there is prototype "([^""]*)" with following configuration:$/
* @Given /^there is archetype "([^""]*)" with following configuration:$/
*/
public function thereIsPrototypeWithFollowingConfiguration($name, TableNode $table)
public function thereIsArchetypeWithFollowingConfiguration($name, TableNode $table)
{
$manager = $this->getEntityManager();
$repository = $this->getRepository('product_prototype');
$repository = $this->getRepository('product_archetype');
$prototype = $repository->createNew();
$prototype->setName($name);
$archetype = $repository->createNew();
$archetype->setName($name);
$data = $table->getRowsHash();
foreach (explode(',', $data['options']) as $optionName) {
$prototype->addOption($this->findOneByName('product_option', trim($optionName)));
$archetype->addOption($this->findOneByName('product_option', trim($optionName)));
}
foreach (explode(',', $data['attributes']) as $attributeName) {
$prototype->addAttribute($this->findOneByName('product_attribute', trim($attributeName)));
$archetype->addAttribute($this->findOneByName('product_attribute', trim($attributeName)));
}
$manager->persist($prototype);
$manager->persist($archetype);
$manager->flush();
}

View file

@ -12,21 +12,19 @@
namespace Sylius\Bundle\ProductBundle\Controller;
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
use Sylius\Component\Product\Builder\PrototypeBuilderInterface;
use Sylius\Component\Archetype\Builder\ArchetypeBuilderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Prototype controller.
* Archetype controller.
*
* @author Paweł Jędrzejewski <pjedrzejewski@sylius.pl>
*/
class PrototypeController extends ResourceController
class ArchetypeController extends ResourceController
{
/**
* Build a product from the given prototype.
* Everything else works exactly like in product
* creation action.
* Build the object from the given archetype.
*
* @param Request $request
* @param mixed $id
@ -35,14 +33,14 @@ class PrototypeController extends ResourceController
*/
public function buildAction(Request $request, $id)
{
$prototype = $this->findOr404($request, array('id' => $id));
$archetype = $this->findOr404($request, array('id' => $id));
$productController = $this->getProductController();
$product = $productController->createNew();
$this
->getBuilder()
->build($prototype, $product)
->build($archetype, $product)
;
$form = $productController->getForm($product);
@ -58,7 +56,7 @@ class PrototypeController extends ResourceController
}
return $productController->render($this->config->getTemplate('build.html'), array(
'product_prototype' => $prototype,
'product_archetype' => $archetype,
'product' => $product,
'form' => $form->createView()
));
@ -67,7 +65,7 @@ class PrototypeController extends ResourceController
/**
* Get product controller.
*
* @return Controller
* @return ResourceController
*/
protected function getProductController()
{
@ -75,12 +73,12 @@ class PrototypeController extends ResourceController
}
/**
* Get prototype builder.
* Get archetype builder.
*
* @return PrototypeBuilderInterface
* @return ArchetypeBuilderInterface
*/
protected function getBuilder()
{
return $this->get('sylius.builder.product_prototype');
return $this->get('sylius.builder.product_archetype');
}
}

View file

@ -62,10 +62,6 @@ class Configuration implements ConfigurationInterface
->prototype('scalar')->end()
->defaultValue(array('sylius'))
->end()
->arrayNode('product_prototype')
->prototype('scalar')->end()
->defaultValue(array('sylius'))
->end()
->end()
->end()
->end()
@ -93,15 +89,6 @@ class Configuration implements ConfigurationInterface
->scalarNode('form')->defaultValue('Sylius\Bundle\ProductBundle\Form\Type\ProductType')->end()
->end()
->end()
->arrayNode('product_prototype')
->addDefaultsIfNotSet()
->children()
->scalarNode('model')->defaultValue('Sylius\Component\Product\Model\Prototype')->end()
->scalarNode('controller')->defaultValue('Sylius\Bundle\ProductBundle\Controller\PrototypeController')->end()
->scalarNode('repository')->cannotBeEmpty()->end()
->scalarNode('form')->defaultValue('Sylius\Bundle\ProductBundle\Form\Type\PrototypeType')->end()
->end()
->end()
->end()
->end()
->end()

View file

@ -0,0 +1,29 @@
<?php
namespace Sylius\Bundle\ProductBundle\Form\Type;
use Sylius\Bundle\ArchetypeBundle\Form\Type\ArchetypeChoiceType as BaseArchetypeChoiceType;
/**
* Archetype choice form type.
*
* @author Adam Elsodaney <adam.elso@gmail.com>
*/
class ArchetypeChoiceType extends BaseArchetypeChoiceType
{
/**
* @param string $className
*/
public function __construct($className)
{
parent::__construct('product', $className);
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'sylius_product_archetype_choice';
}
}

View file

@ -0,0 +1,26 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ProductBundle\Form\Type;
/**
* @author Adam Elsodaney <adam.elso@gmail.com>
*/
class ArchetypeEntityChoiceType extends ArchetypeChoiceType
{
/**
* {@inheritdoc}
*/
public function getParent()
{
return 'entity';
}
}

View file

@ -11,15 +11,15 @@
namespace Sylius\Bundle\ProductBundle\Form\Type;
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
use Sylius\Bundle\ArchetypeBundle\Form\Type\ArchetypeType as BaseArchetypeType;
use Symfony\Component\Form\FormBuilderInterface;
/**
* Product prototype form type.
* Product archetype form type.
*
* @author Paweł Jędrzejewski <pawel@sylius.org>
*/
class PrototypeType extends AbstractResourceType
class ArchetypeType extends BaseArchetypeType
{
/**
* {@inheritdoc}
@ -28,17 +28,22 @@ class PrototypeType extends AbstractResourceType
{
$builder
->add('name', 'text', array(
'label' => 'sylius.form.product_prototype.name'
'label' => 'sylius.form.product_archetype.name'
))
->add('parent', 'sylius_product_archetype_choice', array(
'required' => false,
'label' => 'sylius.form.product_archetype.parent',
'property' => 'name'
))
->add('attributes', 'sylius_product_attribute_choice', array(
'required' => false,
'multiple' => true,
'label' => 'sylius.form.product_prototype.attributes'
'label' => 'sylius.form.product_archetype.attributes'
))
->add('options', 'sylius_product_option_choice', array(
'required' => false,
'multiple' => true,
'label' => 'sylius.form.product_prototype.options'
'label' => 'sylius.form.product_archetype.options'
))
;
}
@ -48,6 +53,6 @@ class PrototypeType extends AbstractResourceType
*/
public function getName()
{
return 'sylius_product_prototype';
return 'sylius_product_archetype';
}
}

View file

@ -2,7 +2,7 @@ SyliusProductBundle [![Build status...](https://secure.travis-ci.org/Sylius/Syli
===================
Products system for [**Symfony2**](http://symfony.com) applications.
It supports simple product catalogs, as well as stores with requirement for fully customizable variants, options, properties and handy prototypes.
It supports simple product catalogs, as well as stores with requirement for fully customizable variants, options, properties and handy archetypes.
Its initial version was inspired by [Spree product and variants system](http://guides.spreecommerce.com/products_and_variants.html).

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
This file is part of the Sylius package.
(c) Paweł Jędrzejewski
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
-->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping">
<mapped-superclass name="Sylius\Component\Product\Model\Archetype" table="sylius_product_archetype">
</mapped-superclass>
</doctrine-mapping>

View file

@ -11,8 +11,7 @@
-->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping">
<mapped-superclass name="Sylius\Component\Product\Model\Attribute" table="sylius_product_attribute">
</mapped-superclass>

View file

@ -11,8 +11,7 @@
-->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping">
<mapped-superclass name="Sylius\Component\Product\Model\Option" table="sylius_product_option">
</mapped-superclass>

View file

@ -11,10 +11,7 @@
-->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping">
<mapped-superclass name="Sylius\Component\Product\Model\OptionValue" table="sylius_product_option_value">
</mapped-superclass>

View file

@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
This file is part of the Sylius package.
(c) Paweł Jędrzejewski
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
-->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mapping">
<mapped-superclass name="Sylius\Component\Product\Model\Prototype" table="sylius_product_prototype">
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="name" column="name" type="string" />
<many-to-many field="attributes" target-entity="Sylius\Component\Product\Model\AttributeInterface">
<join-table name="sylius_product_prototype_attribute">
<join-columns>
<join-column name="prototype_id" referenced-column-name="id" nullable="false" unique="false" />
</join-columns>
<inverse-join-columns>
<join-column name="attribute_id" referenced-column-name="id" nullable="false" unique="false" />
</inverse-join-columns>
</join-table>
</many-to-many>
<many-to-many field="options" target-entity="Sylius\Component\Product\Model\OptionInterface">
<join-table name="sylius_product_prototype_option">
<join-columns>
<join-column name="prototype_id" referenced-column-name="id" nullable="false" unique="false" />
</join-columns>
<inverse-join-columns>
<join-column name="option_id" referenced-column-name="id" nullable="false" unique="false" />
</inverse-join-columns>
</join-table>
</many-to-many>
<field name="createdAt" column="created_at" type="datetime">
<gedmo:timestampable on="create" />
</field>
<field name="updatedAt" column="updated_at" type="datetime" nullable="true">
<gedmo:timestampable on="update" />
</field>
</mapped-superclass>
</doctrine-mapping>

View file

@ -14,8 +14,7 @@
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
>
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<mapped-superclass name="Sylius\Component\Product\Model\Variant" table="sylius_product_variant">
<field name="availableOn" column="available_on" type="datetime" />

View file

@ -18,7 +18,7 @@
<parameters>
<parameter key="sylius.builder.product.class">Sylius\Component\Product\Builder\ProductBuilder</parameter>
<parameter key="sylius.builder.product_prototype.class">Sylius\Component\Product\Builder\PrototypeBuilder</parameter>
<parameter key="sylius.builder.product_archetype.class">Sylius\Component\Product\Builder\ArchetypeBuilder</parameter>
<parameter key="sylius.generator.product_variant.class">Sylius\Bundle\ProductBundle\Generator\VariantGenerator</parameter>
@ -31,10 +31,10 @@
<argument>%sylius.validation_group.product%</argument>
<tag name="form.type" alias="sylius_product" />
</service>
<service id="sylius.form.type.product_prototype" class="%sylius.form.type.product_prototype.class%">
<argument>%sylius.model.product_prototype.class%</argument>
<argument>%sylius.validation_group.product_prototype%</argument>
<tag name="form.type" alias="sylius_product_prototype" />
<service id="sylius.form.type.product_archetype" class="%sylius.form.type.product_archetype.class%">
<argument>%sylius.model.product_archetype.class%</argument>
<argument>%sylius.validation_group.product_archetype%</argument>
<tag name="form.type" alias="sylius_product_archetype" />
</service>
<service id="sylius.builder.product" class="%sylius.builder.product.class%">
@ -43,9 +43,9 @@
<argument type="service" id="sylius.repository.product_attribute" />
<argument type="service" id="sylius.repository.product_attribute_value" />
</service>
<service id="sylius.builder.product_prototype" class="%sylius.builder.product_prototype.class%">
<service id="sylius.builder.product_archetype" class="%sylius.builder.product_archetype.class%">
<argument type="service" id="sylius.repository.product_attribute_value" />
</service>
</service>
<service id="sylius.generator.product_variant" class="%sylius.generator.product_variant.class%">
<argument type="service" id="sylius.repository.product_variant" />
@ -57,6 +57,7 @@
<argument type="service" id="sylius.repository.product" />
<tag name="validator.constraint_validator" alias="sylius.validator.product.unique" />
</service>
</services>
</container>

View file

@ -53,20 +53,4 @@
</property>
</class>
<class name="Sylius\Component\Product\Model\Prototype">
<property name="name">
<constraint name="NotBlank">
<option name="message">sylius.prototype.name.not_blank</option>
<option name="groups">sylius</option>
</constraint>
<constraint name="Length">
<option name="min">2</option>
<option name="minMessage">sylius.prototype.name.min_length</option>
<option name="max">255</option>
<option name="maxMessage">sylius.prototype.name.max_length</option>
<option name="groups">sylius</option>
</constraint>
</property>
</class>
</constraint-mapping>

View file

@ -8,5 +8,5 @@ sylius:
description: Descripció
meta_keywords: Meta keywords
meta_description: Metadescripció
prototype:
archetype:
name: Nom

View file

@ -10,6 +10,6 @@ sylius:
available_on: Dostupný od
meta_keywords: Meta klíčová slova
meta_description: Meta popis
prototype:
archetype:
name: Jméno
properties: Vlastnosti

View file

@ -13,6 +13,6 @@ sylius:
property:
name: System navn
presentation: Præsentation
prototype:
archetype:
name: Navn
properties: Egenskaber

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Interner Name
presentation: Präsentation
prototype:
archetype:
name: Name
properties: Eigenschaften

View file

@ -12,6 +12,6 @@ sylius:
meta_description: Μετα-περιγραφή
property:
presentation: Παρουσίαση
prototype:
archetype:
name: Ονομασία
properties: Ιδιότητες

View file

@ -1,15 +1,16 @@
sylius:
form:
product:
name: Name
description: Description
attributes: Attributes
options: Options
meta_keywords: Meta keywords
meta_description: Meta description
name: Name
description: Description
attributes: Attributes
options: Options
meta_keywords: Meta keywords
meta_description: Meta description
product_variant:
available_on: Available on
product_prototype:
name: Name
attributes: Attributes
options: Options
available_on: Available on
product_archetype:
name: Name
parent: Parent
attributes: Attributes
options: Options

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Nombre interno
presentation: Presentación
prototype:
archetype:
name: Nombre
properties: Propiedades

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Nom interne
presentation: Présentation
prototype:
archetype:
name: Nom
properties: Propriétés

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Interni naziv
presentation: Prezentacija
prototype:
archetype:
name: Naziv
properties: Svojstva

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Belső név
presentation: Bemutató
prototype:
archetype:
name: Név
properties: Tulajdonságok

View file

@ -7,5 +7,5 @@ sylius:
name: Nama
meta_keywords: Meta Kata Kunci
meta_description: Meta Deskripsi
prototype:
archetype:
name: Nama

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Nome interno
presentation: Presentazione
prototype:
archetype:
name: Nome
properties: Proprietà

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Interne naam
presentation: Weergave
prototype:
archetype:
name: Naam
properties: Eigenschappen

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Internt navn
presentation: Presentasjon
prototype:
archetype:
name: Navn
properties: Egenskaper

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Nazwa w systemie
presentation: Nazwa publiczna
prototype:
archetype:
name: Nazwa
properties: Właściwości

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Nome interno
presentation: Apresentação
prototype:
archetype:
name: Nome
properties: Propriedades

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Denumire internă
presentation: Prezentare
prototype:
archetype:
name: Nume
properties: Proprietăți

View file

@ -13,6 +13,6 @@ sylius:
property:
name: Внутреннее название
presentation: Публичное название
prototype:
archetype:
name: Название
properties: Свойства

View file

@ -10,6 +10,6 @@ sylius:
available_on: Dostupný od
meta_keywords: Meta kľúčové slová
meta_description: Meta popis
prototype:
archetype:
name: Názov
properties: Vlastnosti

View file

@ -5,5 +5,5 @@ sylius:
label:
product:
name: Ime
prototype:
archetype:
name: Ime

View file

@ -13,6 +13,6 @@ sylius:
property:
name: ชื่อภายใน
presentation: สื่อถึง
prototype:
archetype:
name: ชื่อ
properties: คุณสมบัติ

View file

@ -7,6 +7,6 @@ sylius:
name: Ad
description: ıklama
properties: Özellikler
prototype:
archetype:
name: Ad
properties: Özellikler

View file

@ -46,8 +46,8 @@ sylius:
not_blank: Vælg venligst egenskab.
value:
not_blank: Venligst angiv produktets egenskabsværdi.
prototype:
archetype:
name:
not_blank: Angiv navnet på prototypen.
min_length: 'Navnet på prototypen skal være mindst ét tegn langt. |Navnet på prototypen skal være mindst {{ limit }} tegn langt.'
max_length: 'Navnet på prototypen må ikke være længere end 1 tegn. |Navnet på prototypen må ikke være længere end {{ limit }} tegn.'
not_blank: Angiv navnet på archetypen.
min_length: 'Navnet på archetypen skal være mindst ét tegn langt. |Navnet på archetypen skal være mindst {{ limit }} tegn langt.'
max_length: 'Navnet på archetypen må ikke være længere end 1 tegn. |Navnet på archetypen må ikke være længere end {{ limit }} tegn.'

View file

@ -46,7 +46,7 @@ sylius:
not_blank: Bitte wählen Sie eine Einstellung.
value:
not_blank: Bitte geben Sie einen Wert für diese Einstellung an.
prototype:
archetype:
name:
not_blank: Bitte geben Sie einen Namen für dieses Muster an.
min_length: 'Der Name des Musters muss mindestens 1 Zeichen lang sein.|Der Name des Musters muss mindestens {{ limit }} Zeichen lang sein.'

View file

@ -14,8 +14,8 @@ sylius:
sku:
not_blank: Please enter variant SKU.
unique: Variant SKU must be unique.
prototype:
archetype:
name:
not_blank: Please enter prototype name.
min_length: Prototype name must be at least 1 character long.|Prototype name must be at least {{ limit }} characters long.
max_length: Prototype name must not be longer than 1 character.|Prototype name must not be longer than {{ limit }} characters.
not_blank: Please enter archetype name.
min_length: Archetype name must be at least 1 character long.|Archetype name must be at least {{ limit }} characters long.
max_length: Archetype name must not be longer than 1 character.|Archetype name must not be longer than {{ limit }} characters.

View file

@ -46,7 +46,7 @@ sylius:
not_blank: Por favor seleccione una propiedad.
value:
not_blank: Por favor introduzca un valor para la propiedad.
prototype:
archetype:
name:
not_blank: Por favor introduzca el nombre del prototipo.
min_length: 'El nombre del prototipo debe tener al menos 1 carácter.|El nombre del prototipo debe tener al menos {{ limit }} caracteres.'

View file

@ -46,8 +46,8 @@ sylius:
not_blank: Veuillez choisir une propriété.
value:
not_blank: Veuillez saisir la propriété du produit.
prototype:
archetype:
name:
not_blank: Veuillez saisir le nom du prototype.
min_length: 'Le nom du prototype de la propriété ne doit pas dépasser 1 caractère.|Le nom du prototype ne doit pas dépasser les {{ limit }} caractères.'
max_length: 'Le nom du prototype ne doit pas dépasser 1 caractère.|Le nom du prototype ne doit pas dépasser les {{ limit }} caractères.'
not_blank: Veuillez saisir le nom du archetype.
min_length: 'Le nom du archetype de la propriété ne doit pas dépasser 1 caractère.|Le nom du archetype ne doit pas dépasser les {{ limit }} caractères.'
max_length: 'Le nom du archetype ne doit pas dépasser 1 caractère.|Le nom du archetype ne doit pas dépasser les {{ limit }} caractères.'

View file

@ -46,7 +46,7 @@ sylius:
not_blank: Odaberite opciju artikla.
value:
not_blank: Unesite vrijednost opcije artikla.
prototype:
archetype:
name:
not_blank: Unesite naziv prototipa.
min_length: 'Naziv prototipa mora imati najmanje jedan znak.|Naziv prototipa mora imati najmanje {{ limit }} znakova.'

View file

@ -46,7 +46,7 @@ sylius:
not_blank: Kérjük, válassza ki a tulajdonságot.
value:
not_blank: Kérjük, írja be a termék tulajdonság értékét.
prototype:
archetype:
name:
not_blank: Kérjük, írja be a prototípus nevét.
min_length: 'A prototípus neve legalább 1 karakter hosszú kell legyen. |A prototípus neve legalább {{ limit }} karakter hosszú kell legyen.'

View file

@ -35,6 +35,6 @@ sylius:
not_blank: Si prega di selezionare una proprietà.
value:
not_blank: Inserisci il valore di proprietà del prodotto.
prototype:
archetype:
name:
not_blank: Si prega di inserire il nome del prototipo.

View file

@ -46,8 +46,8 @@ sylius:
not_blank: Selecteer een eigenschap.
value:
not_blank: Voer een eigenschap waarde in.
prototype:
archetype:
name:
not_blank: Voer een prototype naam in.
min_length: 'Prototype naam moet minstens 1 teken lang zijn.|Prototype naam moet minstens {{ limit }} tekens lang zijn.'
max_length: 'Prototype naam mag niet langer zijn dan 1 teken.|Prototype naam mag niet langer zijn dan {{ limit }} tekens.'
not_blank: Voer een archetype naam in.
min_length: 'Archetype naam moet minstens 1 teken lang zijn.|Archetype naam moet minstens {{ limit }} tekens lang zijn.'
max_length: 'Archetype naam mag niet langer zijn dan 1 teken.|Archetype naam mag niet langer zijn dan {{ limit }} tekens.'

View file

@ -46,8 +46,8 @@ sylius:
not_blank: Velg egenskap.
value:
not_blank: Angi egenskapsverdien for produktet.
prototype:
archetype:
name:
not_blank: Skriv inn prototype navn.
min_length: 'Navnet på prototypen må være minst ett tegn. |Navnet på prototypen må være minst {{ limit }} tegn.'
max_length: 'Navnet på prototypen må ikke være lengre enn ett tegn. |Navnet på prototypen må ikke være lengre enn {{ limit }} tegn.'
not_blank: Skriv inn archetype navn.
min_length: 'Navnet på archetypen må være minst ett tegn. |Navnet på archetypen må være minst {{ limit }} tegn.'
max_length: 'Navnet på archetypen må ikke være lengre enn ett tegn. |Navnet på archetypen må ikke være lengre enn {{ limit }} tegn.'

View file

@ -46,7 +46,7 @@ sylius:
not_blank: Wybierz właściwość.
value:
not_blank: Podaj właściwość produktu.
prototype:
archetype:
name:
not_blank: Podaj nazwę prototypu.
min_length: 'Nazwa prototypu musi mieć co najmniej 1 znak.|Nazwa prototypu musi mieć co najmniej {{ limit }} znaków.'

View file

@ -46,7 +46,7 @@ sylius:
not_blank: Por favor, selecione a propriedade.
value:
not_blank: Por favor digite o valor da propriedade de produto.
prototype:
archetype:
name:
not_blank: Por favor, digite o nome do protótipo.
min_length: 'Nome do produto deve ter pelo menos 1 caracter. |Nome do produto deve ter pelo menos {{limit}} caracteres.'

View file

@ -46,7 +46,7 @@ sylius:
not_blank: Пожалуйста выберите свойство.
value:
not_blank: Пожалуйста выберите значение свойства.
prototype:
archetype:
name:
not_blank: Пожалуйста введите название прототипа.
min_length: 'Название прототипа должно быть не менее 1 символа.|Название прототипа должно быть не менее {{ limit }} символов.'

View file

@ -59,7 +59,7 @@ class SyliusProductBundle extends AbstractResourceBundle
'Sylius\Component\Product\Model\VariantInterface' => 'sylius.model.product_variant.class',
'Sylius\Component\Product\Model\OptionInterface' => 'sylius.model.product_option.class',
'Sylius\Component\Product\Model\OptionValueInterface' => 'sylius.model.product_option_value.class',
'Sylius\Component\Product\Model\PrototypeInterface' => 'sylius.model.product_prototype.class',
'Sylius\Component\Product\Model\ArchetypeInterface' => 'sylius.model.product_archetype.class',
);
}

View file

@ -0,0 +1,82 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace spec\Sylius\Bundle\ProductBundle\Form\Type;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Component\Form\FormBuilder;
/**
* @author Adam Elsodaney <adam.elso@gmail.com>
*/
class ArchetypeEntityChoiceTypeSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('Sylius\Component\Product\Model\Product');
}
function it_is_initializable()
{
$this->shouldHaveType('Sylius\Bundle\ProductBundle\Form\Type\ArchetypeEntityChoiceType');
}
function it_is_a_Sylius_product_archetype_form_choice_type()
{
$this->shouldHaveType('Sylius\Bundle\ProductBundle\Form\Type\ArchetypeChoiceType');
}
function it_is_a_Sylius_archetype_form_choice_type()
{
$this->shouldHaveType('Sylius\Bundle\ArchetypeBundle\Form\Type\ArchetypeChoiceType');
}
function it_is_a_form_type()
{
$this->shouldImplement('Symfony\Component\Form\FormTypeInterface');
}
function it_has_a_name()
{
$this->getName()->shouldBe('sylius_product_archetype_choice');
}
function it_has_a_parent_type()
{
$this->getParent()->shouldReturn('entity');
}
function it_builds_form_with_proper_fields(FormBuilder $builder)
{
$builder
->add('name', 'text', Argument::any())
->willReturn($builder)
;
$builder
->add('parent', 'sylius_product_archetype_parent_choice', Argument::any())
->willReturn($builder)
;
$builder
->add('attributes', 'sylius_product_attribute_choice', Argument::any())
->willReturn($builder)
;
$builder
->add('options', 'sylius_product_option_choice', Argument::any())
->willReturn($builder)
;
$this->buildForm($builder, array());
}
}

View file

@ -19,16 +19,16 @@ use Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* @author Paweł Jędrzejewski <pawel@sylius.org>
*/
class PrototypeTypeSpec extends ObjectBehavior
class ArchetypeTypeSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('Prototype', array('sylius'));
$this->beConstructedWith('Archetype', array('sylius'));
}
function it_is_initializable()
{
$this->shouldHaveType('Sylius\Bundle\ProductBundle\Form\Type\PrototypeType');
$this->shouldHaveType('Sylius\Bundle\ProductBundle\Form\Type\ArchetypeType');
}
function it_is_a_form_type()
@ -43,6 +43,11 @@ class PrototypeTypeSpec extends ObjectBehavior
->willReturn($builder)
;
$builder
->add('parent', 'sylius_product_archetype_choice', Argument::any())
->willReturn($builder)
;
$builder
->add('attributes', 'sylius_product_attribute_choice', Argument::any())
->willReturn($builder)
@ -60,7 +65,7 @@ class PrototypeTypeSpec extends ObjectBehavior
{
$resolver->setDefaults(
array(
'data_class' => 'Prototype',
'data_class' => 'Archetype',
'validation_groups' => array('sylius')
))->shouldBeCalled();
@ -69,6 +74,6 @@ class PrototypeTypeSpec extends ObjectBehavior
function it_has_valid_name()
{
$this->getName()->shouldReturn('sylius_product_prototype');
$this->getName()->shouldReturn('sylius_product_archetype');
}
}

View file

@ -62,6 +62,9 @@ class LoadMetadataSubscriber implements EventSubscriber
$this->mapManyToOne($metadata);
}
/**
* @param ClassMetadata $metadata
*/
private function mapOneToMany(ClassMetadata $metadata)
{
foreach ($this->variables as $class) {
@ -69,15 +72,20 @@ class LoadMetadataSubscriber implements EventSubscriber
continue;
}
$metadata->mapOneToMany(array(
'fieldName' => 'values',
$mapping = array(
'fieldName' => 'values',
'targetEntity' => $class['option_value']['model'],
'mappedBy' => 'option',
'cascade' => array('all')
));
'mappedBy' => 'option',
'cascade' => array('all')
);
$metadata->mapOneToMany($mapping);
}
}
/**
* @param ClassMetadata $metadata
*/
private function mapManyToOne(ClassMetadata $metadata)
{
foreach ($this->variables as $class) {
@ -85,20 +93,25 @@ class LoadMetadataSubscriber implements EventSubscriber
continue;
}
$metadata->mapManyToOne(array(
'fieldName' => 'option',
$mapping = array(
'fieldName' => 'option',
'targetEntity' => $class['option']['model'],
'inversedBy' => 'values',
'joinColumns' => array(array(
'name' => 'option_id',
'inversedBy' => 'values',
'joinColumns' => array(array(
'name' => 'option_id',
'referencedColumnName' => 'id',
'nullable' => false,
'onDelete' => 'CASCADE'
'nullable' => false,
'onDelete' => 'CASCADE'
))
));
);
$metadata->mapManyToOne($mapping);
}
}
/**
* @param ClassMetadata $metadata
*/
private function mapManyToMany(ClassMetadata $metadata)
{
foreach ($this->variables as $variable => $class) {

Some files were not shown because too many files have changed in this diff Show more