[Association] Add basic Association and AssociationType model. Add backend administration pages for AssociationType.

Add some translations.
This commit is contained in:
l3l0 2014-11-01 15:49:19 +01:00 committed by Łukasz Chruściel
parent 2e05391512
commit 7a127a6efd
30 changed files with 895 additions and 0 deletions

View file

@ -220,6 +220,8 @@ default:
- Sylius\Bundle\MoneyBundle\Behat\MoneyContext
- Sylius\Bundle\ProductBundle\Behat\ProductContext
- Sylius\Bundle\ResourceBundle\Behat\FixtureContext
- Sylius\Bundle\ProductBundle\Behat\ProductAssociationContext
- Sylius\Bundle\ResourceBundle\Behat\BaseContext
- Sylius\Bundle\TaxationBundle\Behat\TaxationContext
- Sylius\Bundle\TaxonomyBundle\Behat\TaxonomyContext
- Sylius\Bundle\WebBundle\Behat\WebContext

View file

@ -0,0 +1,64 @@
@products
Feature: Product association
In order connect products together in many contexts
As a store owner
I want to be able associate product with another ones
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 |
And there are following attributes:
| name | presentation | type | choices |
| T-Shirt fabric | T-Shirt | text | |
| T-Shirt fare trade | Faretrade product | checkbox | |
| Color | color | choice | red, blue |
| Size | size | number | |
And the following products exist:
| name | price | options | attributes |
| Super T-Shirt | 19.99 | T-Shirt size, T-Shirt color | T-Shirt fabric: Wool |
| Black T-Shirt | 19.99 | T-Shirt size | T-Shirt fabric: Cotton |
| Mug | 5.99 | | |
| Sticker | 10.00 | | |
And product "Super T-Shirt" is available in all variations
And there are following tax categories:
| name |
| Clothing |
| Electronics |
| Print |
And there are following taxonomies defined:
| name |
| Category |
| Special |
And taxonomy "Category" has following taxons:
| Clothing > T-Shirts |
| Clothing > Premium T-Shirts |
And taxonomy "Special" has following taxons:
| Featured |
| New |
@wip
Scenario: Create association type
Given I want to create new association type
When I create "Cross sell" association type
Then I should be able to add "Cross sell" associations to any product
@wip
Scenario Outline: Associate product with others products
Given there are following association types:
| name |
| Cross sell |
| Upsell |
| Different |
And I want to assign new association for "<Product name>" product
When I select "<Associated product name>" product as "<Association type>" association
Then I should see that "<Product name>" is connected with "<Associated product name>" by "<Association type>" association
Examples:
| Product name | Associated product name | Association type |
| Black T-Shirt | Super T-Shirt | Cross sell |
| Black T-Shirt | Mug | Different |

View file

@ -85,6 +85,7 @@ sylius_taxonomy:
model: Sylius\Component\Core\Model\Taxon
form:
default: Sylius\Bundle\CoreBundle\Form\Type\TaxonType
association_type: ~
sylius_product:
resources:

View file

@ -0,0 +1,74 @@
<?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\Behat;
use Behat\Behat\Tester\Exception\PendingException;
use Behat\Gherkin\Node\TableNode;
use Sylius\Bundle\ResourceBundle\Behat\DefaultContext;
class ProductAssociationContext extends DefaultContext
{
/**
* @When I create :arg1 association type
*/
public function iCreateAssociationType($typeName)
{
$this->fillField('Name', $typeName);
$this->pressButton('Create');
$this->assertSession()->pageTextContains('Association type has been successfully created.');
}
/**
* @Then I should be able to add :arg1 associations to any product
*/
public function iShouldBeAbleToAddAssociationsToAnyProduct($typeName)
{
$this->getSession()->visit($this->generatePageUrl('product index'));
$this->getSession()->getPage()->clickLink('edit');
$this->assertSession()->pageTextContains('Editing product');
throw new \Exception();
//$this->assertSession()->elementContains('css', '')
}
/**
* @Given there are following association types:
*/
public function thereAreFollowingAssociationTypes(TableNode $table)
{
throw new PendingException();
}
/**
* @Given I want to assign new association for :arg1 product
*/
public function iWantToAssignNewAssociationForProduct($arg1)
{
throw new PendingException();
}
/**
* @When I select :arg1 product as :arg2 association
*/
public function iSelectProductAsAssociation($arg1, $arg2)
{
throw new PendingException();
}
/**
* @Then I should see that :arg1 is connected with :arg2 by :arg3 association
*/
public function iShouldSeeThatIsConnectedWithByAssociation($arg1, $arg2, $arg3)
{
throw new PendingException();
}
}

View file

@ -0,0 +1,64 @@
<?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\Controller;
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Association type controller.
*
* @author Leszek Prabucki <leszek.prabucki@gmail.com>
*/
class AssociationTypeController extends ResourceController
{
/**
* @param Request $request
*
* @return RedirectResponse|Response
*/
public function createAction(Request $request)
{
$form = $this->getForm();
if ($form->handleRequest($request)->isValid()) {
$resource = $this->domainManager->create($form->getData());
if ($this->config->isApiRequest()) {
return $this->handleView($this->view($resource, 201));
}
if (null === $resource) {
return $this->redirectHandler->redirectToIndex();
}
return $this->redirectHandler->redirectTo($resource);
}
if ($this->config->isApiRequest()) {
return $this->handleView($this->view($form));
}
$view = $this
->view()
->setTemplate($this->config->getTemplate('create.html'))
->setData(array(
$this->config->getResourceName() => null,
'form' => $form->createView()
))
;
return $this->handleView($view);
}
}

View file

@ -131,6 +131,15 @@ class Configuration implements ConfigurationInterface
->end()
->end()
->end()
->arrayNode('association_type')
->addDefaultsIfNotSet()
->children()
->scalarNode('model')->defaultValue('Sylius\Component\Product\Model\AssociationType')->end()
->scalarNode('controller')->defaultValue('Sylius\Bundle\ProductBundle\Controller\AssociationTypeController')->end()
->scalarNode('repository')->defaultValue('Sylius\Bundle\ProductBundle\Doctrine\ORM\AssociationTypeRepository')->end()
->scalarNode('form')->defaultValue('Sylius\Bundle\ProductBundle\Form\Type\AssociationTypeType')->end()
->end()
->end()
->end()
->end()
->end()

View file

@ -0,0 +1,30 @@
<?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\Doctrine\ORM;
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
/**
* Default association type repository.
*
* @author Paweł Jędrzejewski <pawel@sylius.org>
*/
class AssociationTypeRepository extends EntityRepository
{
/**
* {@inheritdoc}
*/
protected function getAlias()
{
return 'association_type';
}
}

View file

@ -0,0 +1,60 @@
<?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;
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* Association type form type.
*
* @author Leszek Prabucki <leszek.prabucki@gmail.com>
*/
class AssociationTypeType extends AbstractResourceType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text', array(
'label' => 'sylius.form.association_type.name',
'required' => true
))
;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'sylius_association_type';
}
/**
* {@inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
parent::setDefaultOptions($resolver);
$resolver->replaceDefaults([
'empty_data' => function (FormInterface $form) {
return new $this->dataClass($form->get('name')->getData());
}
]);
}
}

View file

@ -0,0 +1,38 @@
<?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\AssociationType" table="sylius_association_type">
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="name" column="name" type="string">
<gedmo:versioned />
</field>
<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>
<field name="deletedAt" column="deleted_at" type="datetime" nullable="true" />
<gedmo:soft-deleteable field-name="deletedAt" />
<gedmo:loggable />
</mapped-superclass>
</doctrine-mapping>

View file

@ -10,3 +10,13 @@ sylius:
meta_description: Metadescripció
product_archetype:
name: Nom
form:
product:
name: Nom
description: Descripció
meta_keywords: Meta keywords
meta_description: Metadescripció
prototype:
name: Nom
association_type:
name: Nom

View file

@ -99,6 +99,14 @@ class WebContext extends BaseWebContext implements SnippetAcceptingContext
$this->getSession()->visit($this->generateUrl('sylius_homepage'));
}
/**
* @Given I want to create new association type
*/
public function iWantToCreateNewAssociationType()
{
$this->iAmOnThePage('association type creation');
}
/**
* @Given /^I am on my account homepage$/
*/

View file

@ -154,6 +154,16 @@ class BackendMenuBuilder extends MenuBuilder
if (!$child->hasChildren()) {
$menu->removeChild('assortment');
}
$child->addChild('prototypes', array(
'route' => 'sylius_backend_product_prototype_index',
'labelAttributes' => array('icon' => 'glyphicon glyphicon-compressed'),
))->setLabel($this->translate(sprintf('sylius.backend.menu.%s.prototypes', $section)));
$child->addChild('association types', array(
'route' => 'sylius_backend_association_type_index',
'labelAttributes' => array('icon' => 'glyphicon glyphicon-th-list'),
))->setLabel($this->translate(sprintf('sylius.backend.menu.%s.association_type', $section)));
}
/**

View file

@ -0,0 +1,40 @@
# This file is part of the Sylius package.
# (c) Paweł Jędrzejewski
sylius_backend_association_type_index:
path: /
methods: [GET]
defaults:
_controller: sylius.controller.association_type:indexAction
_sylius:
template: SyliusWebBundle:Backend/AssociationType:index.html.twig
sortable: true
sorting:
name: desc
sylius_backend_association_type_create:
path: /new
methods: [GET, POST]
defaults:
_controller: sylius.controller.association_type:createAction
_sylius:
template: SyliusWebBundle:Backend/AssociationType:create.html.twig
redirect: sylius_backend_association_type_index
sylius_backend_association_type_update:
path: /{id}/edit
methods: [GET, PUT]
defaults:
_controller: sylius.controller.association_type:updateAction
_sylius:
template: SyliusWebBundle:Backend/AssociationType:update.html.twig
redirect: sylius_backend_association_type_index
sylius_backend_association_type_delete:
path: /{id}
methods: [DELETE]
defaults:
_controller: sylius.controller.association_type:deleteAction
_sylius:
template: SyliusWebBundle:Backend/Misc:delete.html.twig
redirect: sylius_backend_association_type_index

View file

@ -24,6 +24,10 @@ sylius_backend_product:
resource: @SyliusWebBundle/Resources/config/routing/backend/product.yml
prefix: /products
sylius_backend_association_type:
resource: @SyliusWebBundle/Resources/config/routing/backend/association_type.yml
prefix: /association-types
sylius_backend_inventory:
resource: @SyliusWebBundle/Resources/config/routing/backend/inventory.yml
prefix: /inventory

View file

@ -58,6 +58,7 @@ sylius:
archetypes: Product archetypes
assortment: Assortment
attributes: Configure attributes
association_type: Association Types
blocks: Blocks
channels: Channels
configuration: Configuration

View file

@ -47,6 +47,13 @@ sylius:
tracking_number: Tracking number
title: My account
add_to_cart: Add to cart
association_type:
index_header: Association Types
update_header: Edit Association Type
create_header: Create Association Type
name: Name
create: Create
update: Update
address:
city: City
company: Company
@ -225,6 +232,8 @@ sylius:
index: Permissions
product:
index: Products
association_type:
index: Association Types
promotion:
index: Promotions
promotion_coupon:

View file

@ -0,0 +1,7 @@
{% form_theme form 'SyliusWebBundle::forms.html.twig' %}
<fieldset>
{{ form_row(form.name, {'attr': {'class': 'input-lg'}}) }}
</fieldset>
{{ form_widget(form._token) }}

View file

@ -0,0 +1,24 @@
{% extends 'SyliusWebBundle:Backend:layout.html.twig' %}
{% from 'SyliusResourceBundle:Macros:actions.html.twig' import create %}
{% block topbar %}
<ol class="breadcrumb">
<li>{{ 'sylius.breadcrumb.assortment'|trans }}</li>
<li><a href="{{ path('sylius_backend_association_type_index') }}">{{ 'sylius.breadcrumb.association_type.index'|trans }}</a></li>
<li>{{ 'sylius.breadcrumb.new'|trans }}</li>
</ol>
{% endblock %}
{% block content %}
<div class="page-header">
<h1><i class="glyphicon glyphicon-plus-sign"></i> {{ 'sylius.association_type.create_header'|trans|raw }}</h1>
</div>
{{ form_errors(form) }}
<form action="{{ path('sylius_backend_association_type_create') }}" method="post" class="form-horizontal" novalidate>
{% include 'SyliusWebBundle:Backend/AssociationType:_form.html.twig' %}
{{ create() }}
</form>
{% endblock %}

View file

@ -0,0 +1,26 @@
{% extends 'SyliusWebBundle:Backend:layout.html.twig' %}
{% import 'SyliusResourceBundle:Macros:buttons.html.twig' as buttons %}
{% from 'SyliusWebBundle:Backend/Macros:misc.html.twig' import pagination %}
{% from 'SyliusWebBundle:Backend/AssociationType:macros.html.twig' import list %}
{% block topbar %}
<ol class="breadcrumb">
<li>{{ 'sylius.breadcrumb.assortment'|trans }}</li>
<li>{{ 'sylius.breadcrumb.association_type.index'|trans }}</li>
</ol>
{% endblock %}
{% block content %}
<div class="page-header">
<div class="actions-menu">
{{ buttons.create(path('sylius_backend_association_type_create'), 'sylius.association_type.create'|trans) }}
</div>
<h1><i class="glyphicon glyphicon-list-alt"></i> {{ 'sylius.association_type.index_header'|trans|raw }}</h1>
</div>
{{ pagination(association_types) }}
{{ list(association_types) }}
{{ pagination(association_types) }}
{% endblock %}

View file

@ -0,0 +1,32 @@
{% macro list(association_types) %}
{% import 'SyliusResourceBundle:Macros:buttons.html.twig' as buttons %}
{% import 'SyliusWebBundle:Backend/Macros:alerts.html.twig' as alerts %}
{% if association_types|length > 0 %}
<table class="table">
<thead>
<tr>
<th>{{ sylius_resource_sort('id', '#id') }}</th>
<th>{{ sylius_resource_sort('name', 'sylius.association_type.name'|trans) }}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for type in association_types %}
<tr id="{{ type.id }}">
<td>{{ type.id }}</td>
<td>{{ type.name }}</td>
<td class="center-text">
{{ buttons.edit(path('sylius_backend_association_type_update', {'id': type.id})) }}
{{ buttons.delete(path('sylius_backend_association_type_delete', {'id': type.id})) }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
{{ alerts.info('sylius.product_attribute.no_results'|trans) }}
{% endif %}
{% endmacro %}

View file

@ -0,0 +1,27 @@
{% extends 'SyliusWebBundle:Backend:layout.html.twig' %}
{% from 'SyliusResourceBundle:Macros:actions.html.twig' import update %}
{% block topbar %}
<ol class="breadcrumb">
<li>{{ 'sylius.breadcrumb.assortment'|trans }}</li>
<li><a href="{{ path('sylius_backend_association_type_index') }}">{{ 'sylius.breadcrumb.association_type.index'|trans }}</a></li>
<li>{{ association_type.name }}</li>
<li>{{ 'sylius.breadcrumb.edit'|trans }}</li>
</ol>
{% endblock %}
{% block content %}
<div class="page-header">
<h1><i class="glyphicon glyphicon-pencil"></i> {{ 'sylius.association_type.update_header'|trans|raw }}</h1>
</div>
{{ form_errors(form) }}
<form action="{{ path('sylius_backend_association_type_update', {'id': association_type.id}) }}" method="post" class="form-horizontal" novalidate>
<input type="hidden" name="_method" value="PUT">
{% include 'SyliusWebBundle:Backend/AssociationType:_form.html.twig' %}
{{ update() }}
</form>
{% endblock %}

View file

@ -0,0 +1,22 @@
{% form_theme form 'SyliusWebBundle::forms.html.twig' %}
<div class="tab-pane" id="associations">
<div id="sylius-assortment-product-attributes" class="collection-container" data-prototype="{{ ('<div id="sylius_product_attributes___name__">' ~ form_row(form.attributes.vars.prototype.attribute, {'attr': {'class': 'attribute-chooser'}}))|e }}{{ (form_row(form.attributes.vars.prototype.value) ~ '</div>')|e }}">
{% for attributeForm in form.attributes %}
<div class="sylius-assortment-product-attributes-attribute row">
<div class="col-md-10">
{{ form_widget(attributeForm) }}
</div>
<div class="col-md-2">
<a href="#" class="btn btn-danger" data-collection-button="delete" data-collection="sylius-assortment-product-attributes" data-collection-item="attribute"><i class="glyphicon glyphicon-trash"></i>&nbsp;{{ 'sylius.product.remove_attribute'|trans }}</a>
</div>
</div>
{% endfor %}
{% for key, prototype in form.attributes.vars.prototype.vars.prototypes %}
<div id="attribute-prototype_{{ key }}" class="attribute-prototypes" data-prototype="{{ form_widget(prototype)|e }}"></div>
{% endfor %}
</div>
<a href="#" class="btn btn-success btn-block" data-collection-button="add" data-prototype="sylius-assortment-product-attributes" data-collection="sylius-assortment-product-attributes">
{{ 'sylius.product.add_attribute'|trans }}
</a>
</div>

View file

@ -0,0 +1,42 @@
<?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\Component\Product\Model;
/**
* Abstract association class
*
* @author Leszek Prabucki <leszek.prabucki@gmail.com>
*/
abstract class Association
{
/**
* @var mixed $id
*/
private $id;
/**
* @var AssociationType
*/
private $type;
public function __construct(AssociationType $type)
{
$this->type = $type;
}
public function getId()
{
return $this->id;
}
abstract function getAssociatedObject();
}

View file

@ -0,0 +1,78 @@
<?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\Component\Product\Model;
/**
* AssociationType model.
*
* @author Leszek Prabucki <leszek.prabucki@gmail.com>
*/
class AssociationType
{
/**
* @var mixed
*/
protected $id;
/**
* @var string
*/
protected $name;
/**
* @var \DateTime
*/
protected $createdAt;
/**
* @var \DateTime
*/
protected $updatedAt;
/**
* @var null|\DateTime
*/
protected $deletedAt;
/**
* @param string $name
*/
public function __construct($name)
{
$this->setName($name);
$this->createdAt = new \DateTime();
$this->updatedAt = new \DateTime();
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
public function setName($name)
{
if (null === $name || !trim(str_replace(["\n", "\t"], '', $name))) {
throw new \InvalidArgumentException('Association type name cannot be empty.');
}
$this->name = $name;
return $this;
}
public function getId()
{
return $this->id;
}
}

View file

@ -55,6 +55,13 @@ class Product extends AbstractTranslatable implements ProductInterface
*/
protected $attributes;
/**
* Product options.
*
* @var Collection|Association[]
*/
protected $associations;
/**
* @var Collection|BaseVariantInterface[]
*/
@ -71,6 +78,7 @@ class Product extends AbstractTranslatable implements ProductInterface
$this->availableOn = new \DateTime();
$this->attributes = new ArrayCollection();
$this->associations = new ArrayCollection();
$this->variants = new ArrayCollection();
$this->options = new ArrayCollection();
$this->createdAt = new \DateTime();
@ -458,4 +466,23 @@ class Product extends AbstractTranslatable implements ProductInterface
$this->deletedAt = $deletedAt;
}
/**
* @param Association $association
* @return
*/
public function addAssociation(Association $association)
{
$this->associations[] = $association;
return $this;
}
/**
* @return Association[]
*/
public function getAssociations()
{
return $this->associations->toArray();
}
}

View file

@ -0,0 +1,43 @@
<?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\Component\Product\Model;
/**
* ProductAssociation model.
*
* @author Leszek Prabucki <leszek.prabucki@gmail.com>
*/
class ProductAssociation extends Association
{
/**
* @var ProductInterface
*/
private $product;
/**
* @param ProductInterface $product
* @param AssociationType $type
*/
public function __construct(ProductInterface $product, AssociationType $type)
{
parent::__construct($type);
$this->product = $product;
}
/**
* @return ProductInterface
*/
final public function getAssociatedObject()
{
return $this->product;
}
}

View file

@ -53,4 +53,46 @@ interface ProductInterface extends
* @param null|\DateTime $availableUntil
*/
public function setAvailableUntil(\DateTime $availableUntil = null);
/**
* Get meta keywords.
*
* @return string
*/
public function getMetaKeywords();
/**
* Set meta keywords for the product.
*
* @param string $metaKeywords
*/
public function setMetaKeywords($metaKeywords);
/**
* Get meta description.
*
* @return string
*/
public function getMetaDescription();
/**
* Set meta description for the product.
*
* @param string $metaDescription
*/
public function setMetaDescription($metaDescription);
/**
* Add association to product
*
* @param Association $association
*/
public function addAssociation(Association $association);
/**
* Get associations
*
* @param Association[] $association
*/
public function getAssociations();
}

View file

@ -15,6 +15,7 @@ use Doctrine\Common\Collections\Collection;
use PhpSpec\ObjectBehavior;
use Sylius\Component\Resource\Model\ToggleableInterface;
use Sylius\Component\Product\Model\ArchetypeInterface;
use Sylius\Component\Product\Model\Association;
use Sylius\Component\Product\Model\AttributeValueInterface;
use Sylius\Component\Product\Model\OptionInterface;
use Sylius\Component\Product\Model\ProductInterface;
@ -308,4 +309,17 @@ class ProductSpec extends ObjectBehavior
$this->enable();
$this->shouldBeEnabled();
}
function it_allows_to_add_assoication(Association $association1, Association $association2)
{
$this
->addAssociation($association1)
->addAssociation($association2)
;
$this->getAssociations()->shouldReturn([
$association1,
$association2
]);
}
}

View file

@ -0,0 +1,52 @@
<?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\Component\Product\Model;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class AssociationTypeSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('Cross sell');
}
function it_has_name()
{
$this->getName()->shouldBe('Cross sell');
}
function it_needs_to_have_mutable_name_sadly()
{
$this->setName('Changed name')->shouldBe($this);
$this->getName()->shouldBe('Changed name');
}
function it_cannot_be_created_with_empty_name()
{
$this->shouldThrow('\InvalidArgumentException')->during('__construct', ['']);
$this->shouldThrow('\InvalidArgumentException')->during('__construct', [' ']);
$this->shouldThrow('\InvalidArgumentException')->during('__construct', ["\n"]);
$this->shouldThrow('\InvalidArgumentException')->during('__construct', ["\t"]);
$this->shouldThrow('\InvalidArgumentException')->during('__construct', [null]);
}
function it_does_not_allow_to_change_name_to_empty_one()
{
$this->shouldThrow('\InvalidArgumentException')->during('setName', ['']);
$this->shouldThrow('\InvalidArgumentException')->during('setName', [' ']);
$this->shouldThrow('\InvalidArgumentException')->during('setName', ["\n"]);
$this->shouldThrow('\InvalidArgumentException')->during('setName', ["\t"]);
$this->shouldThrow('\InvalidArgumentException')->during('setName', [null]);
}
}

View file

@ -0,0 +1,35 @@
<?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\Component\Product\Model;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Sylius\Component\Product\Model\AssociationType;
use Sylius\Component\Product\Model\ProductInterface;
class ProductAssociationSpec extends ObjectBehavior
{
function let(ProductInterface $product, AssociationType $associationType)
{
$this->beConstructedWith($product, $associationType);
}
function it_is_association()
{
$this->shouldHaveType('Sylius\Component\Product\Model\Association');
}
function it_allows_to_get_associated_product(ProductInterface $product)
{
$this->getAssociatedObject()->shouldBe($product);
}
}