Configurable fixtures for Symfony applications.
Documentation is available in the docs folder.
Please use [email protected]
email to report security issues.
The bundle was originally created by Kamil Kokot. See the list of contributors.
Configurable fixtures for Symfony applications.
License: MIT License
Configurable fixtures for Symfony applications.
Documentation is available in the docs folder.
Please use [email protected]
email to report security issues.
The bundle was originally created by Kamil Kokot. See the list of contributors.
Sylius version affected: 1.10.4
sylius/fixtures-bundle: v1.7.0
Steps to reproduce
installing mongodb
composer require doctrine/mongodb-odm-bundle (with 1 recipe)
run
php bin/console cache:clear
Description
from
php bin/console cache:clear
[WARNING] Some commands could not be registered:
In MongoDBPurgerListener.php line 26:
Argument 1 passed to Sylius\Bundle\FixturesBundle\Listener\MongoDBPurgerListener::__construct() must be an instance of Doctrine\Common\Persistence\ManagerRegistry, instance of Doctrine\Bundle\MongoDBBundle\ManagerRegistry given, call
ed in D:\laragon\www<project>\var\cache\dev\Container8g1zyaR\getListenerRegistryInterfaceService.php on line 34
Problem
The problem is that the type hints in the code refer to a class that doesn't exist
https://github.com/Sylius/SyliusFixturesBundle/blob/master/src/Listener/MongoDBPurgerListener.php#L17
The Doctrine\Common\Persistence\ManagerRegistry class exists in doctrine/common 2.8
https://github.com/doctrine/common/blob/2.8/lib/Doctrine/Common/Persistence/ManagerRegistry.php
but it was removed in 2.9
https://github.com/doctrine/common/blob/2.9/lib/Doctrine/Common/Persistence/ManagerRegistry.php
Possible Solution
In vendor/sylius/fixtures-bundle/src/Listener/MongoDBPurgerListener.php
(https://github.com/Sylius/SyliusFixturesBundle/blob/master/src/Listener/MongoDBPurgerListener.php)
update
use Doctrine\Common\Persistence\ManagerRegistry;
to
use Doctrine\Persistence\ManagerRegistry;
This problem was found also in other libraries. e.g. api-platform/core#3683
Symfony: 4.3.2
Sylius: 1.5.2
PHP: 7.3.7
Consider this fixture
<?php
declare(strict_types=1);
namespace HBX\Fixture;
use Sylius\Bundle\CoreBundle\Fixture\AbstractResourceFixture;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
class ProductFixture extends AbstractResourceFixture
{
public function getName(): string
{
return 'product';
}
protected function configureResourceNode(ArrayNodeDefinition $resourceNode): void
{
$resourceNode
->arrayNode('product_options')->scalarPrototype()->end()->end()
;
}
}
In ProductExampleFactory
<?php
namespace App\Fixture\Factory;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ProductExampleFactory extends SyliusProductExampleFactory
{
protected function configureOptions(OptionsResolver $resolver): void
{
parent::configureOptions($resolver);
$resolver
// ...
// Never run
->setDefault('product_options', function (Options $options): array {
$productOptions = $this->productOptionRepository->findAll();
return [$productOptions[rand(0, count($productOptions) - 1)]];
})
// Actually even you set the default value direct, the resolved value is still an empty array only
// ->setDefault('product_options', ['Wow'])
;
}
}
I am not sure it is a SyliusFixtureBundle's bug or Symfony 4.3.3's bug
sylius:fixtures:load
currently has a hardcoded default suite name of default
. It would be nice if the default suite used in the absense of an explicit suite
argument could be configured via yaml.
The issue to track and coordinate efforts.
Sylius version affected: 1.7.4
Description
Following these steps here: https://docs.sylius.com/en/latest/customization/fixtures.html, adding countries to channels using fixtures does not work
Steps to reproduce
# config/services.yaml
sylius.fixture.example_factory.channel:
class: App\Fixture\Factory\ChannelExampleFactory
arguments:
- "@sylius.factory.channel"
- "@sylius.repository.locale"
- "@sylius.repository.currency"
- "@sylius.repository.zone"
- "@sylius.repository.country"
public: true
sylius.fixture.channel:
class: App\Fixture\ChannelFixture
arguments:
- "@sylius.manager.channel"
- "@sylius.fixture.example_factory.channel"
tags:
- { name: sylius_fixtures.fixture }
# config/packages/sylius_fixtures.yaml
sylius_fixtures:
suites:
myt:
listeners:
orm_purger: ~
logger: ~
fixtures:
locale:
options:
locales:
- 'de_DE'
currency:
options:
currencies:
- 'EUR'
geographical:
options:
countries:
- 'DE'
channel:
options:
custom:
de_store:
name: "DE Store"
code: "DE"
locales:
- "de_DE"
currencies:
- "EUR"
enabled: true
hostname: "localhost"
countries:
- "DE"
//src/Fixture/Factory/ChannelExampleFactory.php
<?php
namespace App\Fixture\Factory;
use Sylius\Bundle\CoreBundle\Fixture\Factory\ChannelExampleFactory as BaseChannelExampleFactory;
use Sylius\Bundle\CoreBundle\Fixture\OptionsResolver\LazyOption;
use Sylius\Component\Channel\Factory\ChannelFactoryInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ChannelExampleFactory extends BaseChannelExampleFactory
{
/** @var RepositoryInterface */
public $countryRepository;
public function __construct(
ChannelFactoryInterface $channelFactory,
RepositoryInterface $localeRepository,
RepositoryInterface $currencyRepository,
RepositoryInterface $zoneRepository,
RepositoryInterface $countryRepository
)
{
$this->countryRepository = $countryRepository;
parent::__construct($channelFactory, $localeRepository, $currencyRepository, $zoneRepository);
}
public function create(array $options = []): ChannelInterface
{
$channel = parent::create($options);
foreach ($options['countries'] as $country) {
$channel->addCountry($country);
}
return $channel;
}
protected function configureOptions(OptionsResolver $resolver): void
{
parent::configureOptions($resolver);
$resolver
->setDefault('countries', LazyOption::randomOne($this->countryRepository))
->setAllowedTypes('countries', 'array')
->setNormalizer('countries', LazyOption::findOneBy($this->countryRepository, 'code'));
}
}
//src/Fixture/ChannelFixture.php
<?php
namespace App\Fixture;
use Sylius\Bundle\CoreBundle\Fixture\ChannelFixture as BaseChannelFixture;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
final class ChannelFixture extends BaseChannelFixture
{
protected function configureResourceNode(ArrayNodeDefinition $resourceNode): void
{
parent::configureResourceNode($resourceNode);
$resourceNode
->children()
->arrayNode('countries')->scalarPrototype()->end()->end();
}
}
running then
php bin/console sylius:install -s myt
throws this error:
Argument 1 passed to Sylius\Component\Core\Model\Channel::addCountry() must implement interface Sylius\Component\Addressing\Model\CountryInterface, string given, called in /home/lucian/www/sylius/myt
/src/Fixture/Factory/ChannelExampleFactory.php on line 36
Looks like both methods at https://github.com/Sylius/SyliusFixturesBundle/blob/master/src/Listener/AbstractListener.php#L24 shouldn't be there
TLDR Context
When implementing plugins for Sylius, I usually add fixtures - that way app developer can "in one click" try plugin (without eating time to add some data manually).
Sometime plugins extending core resources (Product, Order, etc) and I believe we should have safe way to extend or even decorate *ExampleFactory
for core resources.
Safe means that solution should work even if 2 or more plugins will be installed that make changes to same *ExampleFactory
. This can be done with decorators I believe.
But methods at *ExampleFactory
and *Factory
protected which make that impossible to create safe solutions.
Describe the proposed solution
protected function configureResourceNode(ArrayNodeDefinition $resourceNode): void;
with
public function configureResourceNode(ArrayNodeDefinition $resourceNode): void;
at AbstractResourceFixture
and related core resources fixtures.
ConfigurableExampleFactoryInterface
(or DecorableExampleFactoryInterface
, not sure about name) - optionalinterface ConfigurableExampleFactoryInterface extends ExampleFactoryInterface
{
public function configureOptions(OptionsResolver $resolver): void;
}
AbstractExampleFactory
with:abstract class AbstractExampleFactory implements ConfigurableExampleFactoryInterface
{
abstract public function configureOptions(OptionsResolver $resolver): void;
}
Additional context
As far as currently we have some BC breaking changes in this area ("Make FixturesBundle standalone") - I believe this is good time to do proposed change too.
I will make PR - just let me know please to what branch I should base it to.
Hi sylius guys !
I was wondering why is there nothing on Sylius\Bundle\CoreBundle\Fixture\AbstractResourceFixture
in the docs. Is it because we shouldn't use it in prior of AbstractFixture
?
If not, should I write some lines on it here when I'll have some spare time?
Sylius version affected: 1.8+, but seems that the current one has an issue.
Description
It seems that it's Impossible to switch off certain ( or all ) fixtures using false as in the doc:
https://github.com/Sylius/SyliusFixturesBundle/blob/master/docs/architecture.md#disabling-listeners--fixtures-in-consecutive-configurations
This is especially hard when we want to define fixtures with smaller subset. For example, I want to have only 3 currencies in my shop. I could disable default one and redeclare it with lower subset under different key.
Steps to reproduce
sylius_fixtures:
suites:
default:
fixtures:
currency: false
And run bin/console sylius:fixtures:load --no-interaction
Command outputs Running suite "currency"
and the data is loaded from the default fixture configuration.
As the fixtures are not doing checks first, overwriting certain fixtures will end up with duplicate entries.
According to the documentation that should disable the currency fixture, but unfortunately, it has no effect.
I think this feature is documented but it's actually not supported, or maybe supported only in subset.
Possible Solution
I am not really sure if that's feature you want to support, but if not the doc should be changed.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.