diff --git a/README.md b/README.md
index 70d6fcd6..ffb49b52 100644
--- a/README.md
+++ b/README.md
@@ -90,6 +90,36 @@ $ php bin/console doctrine:schema:update --force
or use [Doctrine Migrations](https://symfony.com/doc/master/bundles/DoctrineMigrationsBundle/index.html).
+## Fixtures
+
+ 1. Add a new yaml file to the folder `config/packages` and name it as you wish, e.g. `my_own_fixtures.yaml`.
+
+ 2. Fill this yaml with your own brand fixtures and don't forget to declare the definition of
+ your product(s) before this brand definition or use existing product(s) code.
+ ```
+ # config/packages/my_own_fixtures.yaml
+
+ sylius_fixtures:
+ suites:
+ my_own_brand_fixtures:
+ fixtures:
+ loevgaard_sylius_brand_plugin_brand:
+ options:
+ custom:
+ flux:
+ name: 'My brand'
+ slug: 'my-brand'
+ products:
+ - product_code_1
+ - product_code_2
+ - product_code_3
+ ```
+
+ 3. Load your fixtures
+
+ ```bash
+ php bin/console sylius:fixture:load my_own_brand_fixtures
+ ```
## Installation and usage for plugin development
[Find more information here](install-dev.md)
diff --git a/composer.json b/composer.json
index 52d9a37c..5b23367b 100644
--- a/composer.json
+++ b/composer.json
@@ -20,6 +20,7 @@
"friends-of-behat/symfony-extension": "^1.2.1",
"friends-of-behat/variadic-extension": "^1.1",
"lakion/mink-debug-extension": "^1.2.3",
+ "matthiasnoback/symfony-config-test": "^3.0",
"phpspec/phpspec": "^5.0",
"phpstan/phpstan-doctrine": "^0.10",
"phpstan/phpstan-shim": "^0.10",
diff --git a/phpstan.neon b/phpstan.neon
index 98566716..10967053 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -9,3 +9,4 @@ parameters:
ignoreErrors:
- '/Parameter #1 $configuration of method Symfony\Component\DependencyInjection\Extension\Extension::processConfiguration() expects Symfony\Component\Config\Definition\ConfigurationInterface, Symfony\Component\Config\Definition\ConfigurationInterface|null given./'
+ - '/Cannot call method scalarNode\(\) on Symfony\\Component\\Config\\Definition\\Builder\\NodeParentInterface\|null/'
diff --git a/src/Assigner/ProductsAssigner.php b/src/Assigner/ProductsAssigner.php
new file mode 100644
index 00000000..2920b81a
--- /dev/null
+++ b/src/Assigner/ProductsAssigner.php
@@ -0,0 +1,22 @@
+addProduct($product);
+ }
+ }
+ }
+}
diff --git a/src/Assigner/ProductsAssignerInterface.php b/src/Assigner/ProductsAssignerInterface.php
new file mode 100644
index 00000000..dc450cf0
--- /dev/null
+++ b/src/Assigner/ProductsAssignerInterface.php
@@ -0,0 +1,17 @@
+images = new ArrayCollection();
+ $this->initializeImagesCollection();
+ $this->initializeProductsCollection();
}
/**
@@ -83,62 +77,4 @@ public function setName(string $name): void
{
$this->name = $name;
}
-
- /********************************
- * ImagesAwareInterface methods *
- *******************************/
-
- /**
- * {@inheritdoc}
- */
- public function getImages(): Collection
- {
- return $this->images;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getImagesByType(string $type): Collection
- {
- return $this->images->filter(function (ImageInterface $image) use ($type) {
- return $type === $image->getType();
- });
- }
-
- /**
- * {@inheritdoc}
- */
- public function hasImages(): bool
- {
- return !$this->images->isEmpty();
- }
-
- /**
- * {@inheritdoc}
- */
- public function hasImage(ImageInterface $image): bool
- {
- return $this->images->contains($image);
- }
-
- /**
- * {@inheritdoc}
- */
- public function addImage(ImageInterface $image): void
- {
- $image->setOwner($this);
- $this->images->add($image);
- }
-
- /**
- * {@inheritdoc}
- */
- public function removeImage(ImageInterface $image): void
- {
- if ($this->hasImage($image)) {
- $image->setOwner(null);
- $this->images->removeElement($image);
- }
- }
}
diff --git a/src/Entity/BrandInterface.php b/src/Entity/BrandInterface.php
index b1761360..d5870a7a 100644
--- a/src/Entity/BrandInterface.php
+++ b/src/Entity/BrandInterface.php
@@ -6,7 +6,7 @@
use Sylius\Component\Resource\Model\ResourceInterface;
-interface BrandInterface extends ResourceInterface
+interface BrandInterface extends ResourceInterface, ProductsAwareInterface, ImagesAwareInterface
{
/**
* Returns the name of the brand
diff --git a/src/Entity/ImagesAwareInterface.php b/src/Entity/ImagesAwareInterface.php
new file mode 100644
index 00000000..7cf7e461
--- /dev/null
+++ b/src/Entity/ImagesAwareInterface.php
@@ -0,0 +1,12 @@
+images = new ArrayCollection();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getImages(): Collection
+ {
+ return $this->images;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getImagesByType(string $type): Collection
+ {
+ return $this->images->filter(function (ImageInterface $image) use ($type) {
+ return $type === $image->getType();
+ });
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasImages(): bool
+ {
+ return !$this->images->isEmpty();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasImage(ImageInterface $image): bool
+ {
+ return $this->images->contains($image);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addImage(ImageInterface $image): void
+ {
+ if (false === $this->hasImage($image)) {
+ $image->setOwner($this);
+ $this->images->add($image);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function removeImage(ImageInterface $image): void
+ {
+ if ($this->hasImage($image)) {
+ $image->setOwner(null);
+ $this->images->removeElement($image);
+ }
+ }
+}
diff --git a/src/Entity/ProductTrait.php b/src/Entity/ProductTrait.php
index 4fe9edf3..902cceed 100644
--- a/src/Entity/ProductTrait.php
+++ b/src/Entity/ProductTrait.php
@@ -10,13 +10,13 @@ trait ProductTrait
{
/**
* @var BrandInterface|null
- * @ORM\ManyToOne(targetEntity="Loevgaard\SyliusBrandPlugin\Entity\Brand")
+ * @ORM\ManyToOne(targetEntity="Loevgaard\SyliusBrandPlugin\Entity\Brand", inversedBy="products")
* @ORM\JoinColumn(name="brand_id", referencedColumnName="id")
*/
protected $brand;
/**
- * @return BrandInterface|null
+ * {@inheritdoc}
*/
public function getBrand(): ?BrandInterface
{
@@ -24,7 +24,7 @@ public function getBrand(): ?BrandInterface
}
/**
- * @param BrandInterface|null $brand
+ * {@inheritdoc}
*/
public function setBrand(?BrandInterface $brand): void
{
diff --git a/src/Entity/ProductsAwareInterface.php b/src/Entity/ProductsAwareInterface.php
new file mode 100644
index 00000000..502d1004
--- /dev/null
+++ b/src/Entity/ProductsAwareInterface.php
@@ -0,0 +1,34 @@
+products = new ArrayCollection();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getProducts(): Collection
+ {
+ return $this->products;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasProduct(BrandAwareInterface $product): bool
+ {
+ return $this->products->contains($product);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addProduct(BrandAwareInterface $product): void
+ {
+ if (false === $this->hasProduct($product)) {
+ /** @var ProductsAwareInterface $this */
+ $product->setBrand($this);
+ $this->products->add($product);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function removeProduct(BrandAwareInterface $product): void
+ {
+ if (true === $this->hasProduct($product)) {
+ $product->setBrand(null);
+ $this->products->removeElement($product);
+ }
+ }
+}
diff --git a/src/Fixture/BrandFixture.php b/src/Fixture/BrandFixture.php
new file mode 100644
index 00000000..fee0957b
--- /dev/null
+++ b/src/Fixture/BrandFixture.php
@@ -0,0 +1,33 @@
+children()
+ ->scalarNode('name')->cannotBeEmpty()->end()
+ ->scalarNode('slug')->cannotBeEmpty()->end()
+ ->arrayNode('products')
+ ->scalarPrototype()->end()
+ ->end();
+ }
+}
diff --git a/src/Fixture/Factory/BrandExampleFactory.php b/src/Fixture/Factory/BrandExampleFactory.php
new file mode 100644
index 00000000..77e48bd7
--- /dev/null
+++ b/src/Fixture/Factory/BrandExampleFactory.php
@@ -0,0 +1,82 @@
+productRepository = $productRepository;
+ $this->productAssigner = $productAssigner;
+ $this->brandFactory = $brandFactory;
+
+ $this->optionsResolver = new OptionsResolver();
+
+ $this->configureOptions($this->optionsResolver);
+ }
+
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configureOptions(OptionsResolver $resolver): void
+ {
+ $resolver
+ ->setRequired('name')
+ ->setAllowedTypes('name', 'string')
+ ->setRequired('slug')
+ ->setAllowedTypes('slug', 'string')
+ ->setDefault('products', [])
+ ->setAllowedTypes('products', 'array')
+ ->setNormalizer('products', LazyOption::findBy($this->productRepository, 'code'))
+ ;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function create(array $options = []): BrandInterface
+ {
+ $options = $this->optionsResolver->resolve($options);
+
+ /** @var BrandInterface $brand */
+ $brand = $this->brandFactory->createNew();
+ $brand->setName($options['name']);
+ $brand->setSlug($options['slug']);
+
+ $this->productAssigner->assign($brand, $options['products']);
+
+ return $brand;
+ }
+}
diff --git a/src/Resources/config/doctrine/Brand.orm.xml b/src/Resources/config/doctrine/Brand.orm.xml
index 1989b7b3..da8ae664 100644
--- a/src/Resources/config/doctrine/Brand.orm.xml
+++ b/src/Resources/config/doctrine/Brand.orm.xml
@@ -14,8 +14,9 @@
+
-
\ No newline at end of file
+
diff --git a/src/Resources/config/services.yml b/src/Resources/config/services.yml
index 20527b6f..6206a2ca 100644
--- a/src/Resources/config/services.yml
+++ b/src/Resources/config/services.yml
@@ -44,3 +44,23 @@ services:
class: Loevgaard\SyliusBrandPlugin\Menu\AdminProductFormMenuListener
tags:
- { name: kernel.event_listener, event: sylius.menu.admin.product.form, method: addItems }
+
+ loevgaard_sylius_brand.assigner.products:
+ class: Loevgaard\SyliusBrandPlugin\Assigner\ProductsAssigner
+
+ loevgaard_sylius_brand.fixture.brand:
+ public: true
+ class: Loevgaard\SyliusBrandPlugin\Fixture\BrandFixture
+ arguments:
+ - '@loevgaard_sylius_brand.manager.brand'
+ - '@loevgaard_sylius_brand.fixture.example_factory.brand'
+ tags:
+ - { name: sylius_fixtures.fixture }
+
+ loevgaard_sylius_brand.fixture.example_factory.brand:
+ public: true
+ class: Loevgaard\SyliusBrandPlugin\Fixture\Factory\BrandExampleFactory
+ arguments:
+ - '@sylius.repository.product'
+ - '@loevgaard_sylius_brand.assigner.products'
+ - '@loevgaard_sylius_brand.factory.brand'
diff --git a/tests/Fixture/BrandFixtureTest.php b/tests/Fixture/BrandFixtureTest.php
new file mode 100644
index 00000000..4aa282c9
--- /dev/null
+++ b/tests/Fixture/BrandFixtureTest.php
@@ -0,0 +1,46 @@
+assertConfigurationIsValid([[]], 'custom');
+ }
+
+ /** @test */
+ public function brand_can_be_generated_randomly(): void
+ {
+ $this->assertConfigurationIsValid([['random' => 4]], 'random');
+ $this->assertPartialConfigurationIsInvalid([['random' => -1]], 'random');
+ }
+
+ /** @test */
+ public function brand_products_is_optional(): void
+ {
+ $this->assertConfigurationIsValid([['custom' => [['products' => []]]]], 'custom.*.products');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getConfiguration(): BrandFixture
+ {
+ return new BrandFixture(
+ $this->getMockBuilder(ObjectManager::class)->getMock(),
+ $this->getMockBuilder(ExampleFactoryInterface::class)->getMock()
+ );
+ }
+}