├── example
├── src
│ ├── Controller
│ │ ├── .gitignore
│ │ └── DefaultController.php
│ ├── Entity
│ │ ├── .gitignore
│ │ ├── Test1.php
│ │ ├── DictWords.php
│ │ ├── States.php
│ │ └── States2.php
│ ├── Repository
│ │ ├── .gitignore
│ │ └── DictWordsRepository.php
│ ├── Kernel.php
│ └── DataSeeds
│ │ ├── TestSeed.php
│ │ ├── DictWordsSeed.php
│ │ ├── CsvSeed.php
│ │ ├── USStatesSeed.php
│ │ └── USStatesSeed2.php
├── config
│ ├── packages
│ │ ├── test
│ │ │ ├── twig.yaml
│ │ │ ├── framework.yaml
│ │ │ └── web_profiler.yaml
│ │ ├── routing.yaml
│ │ ├── prod
│ │ │ ├── routing.yaml
│ │ │ └── doctrine.yaml
│ │ ├── sensio_framework_extra.yaml
│ │ ├── dev
│ │ │ ├── web_profiler.yaml
│ │ │ └── debug.yaml
│ │ ├── twig.yaml
│ │ ├── debug.yaml
│ │ ├── web_profiler.yaml
│ │ ├── framework.yaml
│ │ ├── doctrine.yaml
│ │ └── cache.yaml
│ ├── routes.yaml
│ ├── routes
│ │ ├── dev
│ │ │ ├── framework.yaml
│ │ │ └── web_profiler.yaml
│ │ ├── framework.yaml
│ │ ├── annotations.yaml
│ │ └── web_profiler.yaml
│ ├── preload.php
│ ├── bundles.php
│ ├── bootstrap.php
│ └── services.yaml
├── public
│ └── index.php
├── .gitignore
├── templates
│ ├── base.html.twig
│ └── default
│ │ └── index.html.twig
├── .env
└── composer.json
├── tests
├── bootstrap.php
├── App
│ ├── config.yml
│ └── AppKernel.php
├── fixtures
│ ├── FailSeed.php
│ ├── GlobSeedA.php
│ ├── GlobSeedB.php
│ ├── TownSeed.php
│ ├── StreetSeed.php
│ ├── CountrySeed.php
│ └── PostcodeSeed.php
└── SeedCommandTest.php
├── .gitignore
├── src
├── Command
│ ├── Seed.php
│ ├── LoadSeedsCommand.php
│ └── UnloadSeedsCommand.php
├── Core
│ ├── ManualSeedCommand.php
│ ├── SeedRegistry.php
│ └── SeedCoreCommand.php
├── Exception
│ └── InvalidSeedNameException.php
├── Model
│ └── SeedItem.php
├── Interfaces
│ └── SeedInterface.php
├── Resources
│ └── config
│ │ └── services.yml
├── EvotodiSeedBundle.php
└── DependencyInjection
│ ├── EvotodiSeedExtension.php
│ └── Compiler
│ └── SeedPass.php
├── phpunit.xml.dist
├── LICENSE
├── composer.json
├── .travis.yml
└── README.md
/example/src/Controller/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/src/Entity/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/src/Repository/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/config/packages/test/twig.yaml:
--------------------------------------------------------------------------------
1 | twig:
2 | strict_variables: true
3 |
--------------------------------------------------------------------------------
/example/config/packages/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | utf8: true
4 |
--------------------------------------------------------------------------------
/example/config/packages/prod/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | strict_requirements: null
4 |
--------------------------------------------------------------------------------
/example/config/routes.yaml:
--------------------------------------------------------------------------------
1 | #index:
2 | # path: /
3 | # controller: App\Controller\DefaultController::index
4 |
--------------------------------------------------------------------------------
/example/config/packages/sensio_framework_extra.yaml:
--------------------------------------------------------------------------------
1 | sensio_framework_extra:
2 | router:
3 | annotations: false
4 |
--------------------------------------------------------------------------------
/example/config/packages/test/framework.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: true
3 | session:
4 | storage_id: session.storage.mock_file
5 |
--------------------------------------------------------------------------------
/example/config/routes/dev/framework.yaml:
--------------------------------------------------------------------------------
1 | _errors:
2 | resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
3 | prefix: /_error
4 |
--------------------------------------------------------------------------------
/example/config/routes/framework.yaml:
--------------------------------------------------------------------------------
1 | when@dev:
2 | _errors:
3 | resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
4 | prefix: /_error
5 |
--------------------------------------------------------------------------------
/example/config/packages/test/web_profiler.yaml:
--------------------------------------------------------------------------------
1 | web_profiler:
2 | toolbar: false
3 | intercept_redirects: false
4 |
5 | framework:
6 | profiler: { collect: false }
7 |
--------------------------------------------------------------------------------
/example/config/packages/dev/web_profiler.yaml:
--------------------------------------------------------------------------------
1 | web_profiler:
2 | toolbar: true
3 | intercept_redirects: false
4 |
5 | framework:
6 | profiler: { only_exceptions: false }
7 |
--------------------------------------------------------------------------------
/example/config/routes/annotations.yaml:
--------------------------------------------------------------------------------
1 | controllers:
2 | resource: ../../src/Controller/
3 | type: annotation
4 |
5 | kernel:
6 | resource: ../../src/Kernel.php
7 | type: annotation
8 |
--------------------------------------------------------------------------------
/example/config/packages/twig.yaml:
--------------------------------------------------------------------------------
1 | twig:
2 | default_path: '%kernel.project_dir%/templates'
3 | debug: '%kernel.debug%'
4 | strict_variables: '%kernel.debug%'
5 | exception_controller: null
6 |
--------------------------------------------------------------------------------
/example/config/preload.php:
--------------------------------------------------------------------------------
1 | symfony/framework-bundle ###
2 | /.env.local
3 | /.env.local.php
4 | /.env.*.local
5 | /config/secrets/prod/prod.decrypt.private.php
6 | /public/bundles/
7 | /var/
8 | /vendor/
9 | ###< symfony/framework-bundle ###
10 |
11 | ###> symfony/web-server-bundle ###
12 | /.web-server-pid
13 | ###< symfony/web-server-bundle ###
14 |
--------------------------------------------------------------------------------
/example/templates/base.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {% block title %}Welcome!{% endblock %}
6 | {% block stylesheets %}{% endblock %}
7 |
8 |
9 | {% block body %}{% endblock %}
10 | {% block javascripts %}{% endblock %}
11 |
12 |
13 |
--------------------------------------------------------------------------------
/example/config/packages/web_profiler.yaml:
--------------------------------------------------------------------------------
1 | when@dev:
2 | web_profiler:
3 | toolbar: true
4 | intercept_redirects: false
5 |
6 | framework:
7 | profiler: { only_exceptions: false }
8 |
9 | when@test:
10 | web_profiler:
11 | toolbar: false
12 | intercept_redirects: false
13 |
14 | framework:
15 | profiler: { collect: false }
16 |
--------------------------------------------------------------------------------
/src/Core/ManualSeedCommand.php:
--------------------------------------------------------------------------------
1 | method = null;
12 |
13 | $this
14 | ->addArgument('method', InputArgument::REQUIRED, 'load/unload seed')
15 | ;
16 | $this->baseConfigure();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Command/LoadSeedsCommand.php:
--------------------------------------------------------------------------------
1 | method = 'load';
17 | parent::configure();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Command/UnloadSeedsCommand.php:
--------------------------------------------------------------------------------
1 | method = 'unload';
17 | parent::configure();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Exception/InvalidSeedNameException.php:
--------------------------------------------------------------------------------
1 | name = $name;
15 | $this->classRef = $classRef;
16 | $this->order = $order;
17 | $this->manual = $manual;
18 | }
19 |
20 | public function getClassName(): string
21 | {
22 | return get_class($this->classRef);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/fixtures/FailSeed.php:
--------------------------------------------------------------------------------
1 | ['all' => true],
5 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
6 | Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
7 | Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
8 | Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true],
9 | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
10 | Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
11 | Evotodi\SeedBundle\EvotodiSeedBundle::class => ['all' => true],
12 | ];
13 |
--------------------------------------------------------------------------------
/tests/fixtures/GlobSeedA.php:
--------------------------------------------------------------------------------
1 | writeln('Load foo:bar');
19 | return 0;
20 | }
21 |
22 | public function unload(InputInterface $input, OutputInterface $output): int
23 | {
24 | $output->writeln('Unload foo:bar');
25 | return 0;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/fixtures/GlobSeedB.php:
--------------------------------------------------------------------------------
1 | writeln('Load foo:baz');
19 | return 0;
20 | }
21 |
22 | public function unload(InputInterface $input, OutputInterface $output): int
23 | {
24 | $output->writeln('Unload foo:baz');
25 | return 0;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Interfaces/SeedInterface.php:
--------------------------------------------------------------------------------
1 | writeln('Load town');
24 | return 0;
25 | }
26 |
27 | public function unload(InputInterface $input, OutputInterface $output): int
28 | {
29 | $output->writeln('Unload town');
30 | return 0;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tests/fixtures/StreetSeed.php:
--------------------------------------------------------------------------------
1 | writeln('Load street');
24 | return 0;
25 | }
26 |
27 | public function unload(InputInterface $input, OutputInterface $output): int
28 | {
29 | $output->writeln('Unload street');
30 | return 0;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tests/fixtures/CountrySeed.php:
--------------------------------------------------------------------------------
1 | writeln('Load country');
24 | return 0;
25 | }
26 |
27 | public function unload(InputInterface $input, OutputInterface $output): int
28 | {
29 | $output->writeln('Unload country');
30 | return 0;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tests/fixtures/PostcodeSeed.php:
--------------------------------------------------------------------------------
1 | writeln('Load postcode');
24 | return 0;
25 | }
26 |
27 | public function unload(InputInterface $input, OutputInterface $output): int
28 | {
29 | $output->writeln('Unload postcode');
30 | return 0;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/example/src/Entity/Test1.php:
--------------------------------------------------------------------------------
1 | id;
28 | }
29 |
30 | public function setId( int $id): self
31 | {
32 | $this->id = $id;
33 | return $this;
34 | }
35 |
36 | public function getTest1(): string
37 | {
38 | return $this->test1;
39 | }
40 |
41 | public function setTest1(string $test1): self
42 | {
43 | $this->test1 = $test1;
44 | return $this;
45 | }
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/EvotodiSeedBundle.php:
--------------------------------------------------------------------------------
1 | extension){
16 | $this->extension = new EvotodiSeedExtension();
17 | }
18 |
19 | return $this->extension;
20 | }
21 |
22 | public function build(ContainerBuilder $container): void
23 | {
24 | $this->container = $container;
25 |
26 | parent::build($container);
27 | $container->addCompilerPass(new SeedPass());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/example/src/DataSeeds/TestSeed.php:
--------------------------------------------------------------------------------
1 | disableDoctrineLogging();
19 | $test = new Test1();
20 | $test->setTest1('asdf');
21 |
22 | $this->getManager()->persist($test);
23 | $this->getManager()->flush();
24 | return 0;
25 | }
26 |
27 | public function unload(InputInterface $input, OutputInterface $output): int
28 | {
29 | $this->getManager()->getConnection()->executeQuery('DELETE FROM test1');
30 | return 0;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/example/templates/default/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 |
3 | {% block title %}Hello DefaultController!{% endblock %}
4 |
5 | {% block body %}
6 |
10 |
11 |
12 |
Hello {{ controller_name }}! ✅
13 |
14 | This friendly message is coming from:
15 |
19 |
20 | {% endblock %}
21 |
--------------------------------------------------------------------------------
/src/DependencyInjection/EvotodiSeedExtension.php:
--------------------------------------------------------------------------------
1 | registerForAutoconfiguration(SeedInterface::class)->addTag('seed.seed');
21 |
22 | $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
23 | $loader->load('services.yml');
24 | }
25 |
26 | public function getAlias(): string
27 | {
28 | return 'evo_seed';
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/example/src/Entity/DictWords.php:
--------------------------------------------------------------------------------
1 | id;
35 | }
36 |
37 | public function setId(int $id): self
38 | {
39 | $this->id = $id;
40 | return $this;
41 | }
42 |
43 | public function getWord(): string
44 | {
45 | return $this->word;
46 | }
47 |
48 | public function setWord(string $word): self
49 | {
50 | $this->word = $word;
51 | return $this;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/example/src/Controller/DefaultController.php:
--------------------------------------------------------------------------------
1 | getParameter('kernel.logs_dir').'/dev.log', 0);
18 | // $reader->getParser()->registerPattern('test', '/\[(?P.*)\] (?P\w+).(?P\w+): (?P.*)(?P.*)(?P.*)/');
19 | // $reader->setPattern('test');
20 | // foreach ($reader as $log) {
21 | // echo sprintf("::: %s %s %s
", $log['date']->format('Y-m-d h:i:s'), $log['level'], $log['message']);
22 | // }
23 | // dd($reader);
24 | return $this->render('default/index.html.twig', [
25 | 'controller_name' => 'DefaultController',
26 | ]);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ./src
6 |
7 |
8 | ./Resources
9 | ./Tests
10 | ./vendor
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | ./tests
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/example/src/Entity/States.php:
--------------------------------------------------------------------------------
1 | abv;
35 | }
36 |
37 | public function setAbv(string $abv): self
38 | {
39 | $this->abv = $abv;
40 | return $this;
41 | }
42 |
43 | public function getName(): string
44 | {
45 | return $this->name;
46 | }
47 |
48 | public function setName(string $name): self
49 | {
50 | $this->name = $name;
51 | return $this;
52 | }
53 |
54 | public function __toString()
55 | {
56 | return $this->getAbv();
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/example/src/Entity/States2.php:
--------------------------------------------------------------------------------
1 | abv;
35 | }
36 |
37 | public function setAbv(string $abv): self
38 | {
39 | $this->abv = $abv;
40 | return $this;
41 | }
42 |
43 | public function getName(): string
44 | {
45 | return $this->name;
46 | }
47 |
48 | public function setName(string $name): self
49 | {
50 | $this->name = $name;
51 | return $this;
52 | }
53 |
54 | public function __toString()
55 | {
56 | return $this->getAbv();
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/tests/App/AppKernel.php:
--------------------------------------------------------------------------------
1 | load(__DIR__.'/config.yml');
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2020-present Justin Davis and other contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/example/src/Repository/DictWordsRepository.php:
--------------------------------------------------------------------------------
1 | getEntityManager();
25 | return $em->createQuery(
26 | "SELECT word FROM AppBundle:DictWords AS d ORDER BY RAND() LIMIT 0,3; "
27 | )->getResult();
28 | }
29 |
30 | public function findRandWordsNew($count): array
31 | {
32 | $em = $this->getEntityManager();
33 | $words = $em->getRepository(DictWords::class)->findAll();
34 | shuffle($words);
35 | return array_slice($words, 0 , $count);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "evotodi/seed-bundle",
3 | "description": "Seeder for symfony 6/7",
4 | "type": "symfony-bundle",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "evotodi",
9 | "email": "evotodi@gmail.com"
10 | },
11 | {
12 | "name": "Soyuka",
13 | "email": "soyuka@gmail.com"
14 | }
15 | ],
16 | "require": {
17 | "php": "^8",
18 | "symfony/framework-bundle": "^6.0|^7.0",
19 | "symfony/console": "^6.0|^7.0",
20 | "symfony/finder": "^6.0|^7.0",
21 | "doctrine/doctrine-bundle": "^2.0",
22 | "doctrine/orm": "^2.0|^3.0",
23 | "symfony/yaml": "^6.0|^7.0",
24 | "symfony/doctrine-bridge": "^6.0|^7.0",
25 | "webmozart/glob": "^4.5"
26 | },
27 | "require-dev": {
28 | "symfony/config": "^6.0|^7.0",
29 | "symfony/dependency-injection": "^6.0|^7.0",
30 | "symfony/phpunit-bridge": "^6.0|^7.0"
31 |
32 | },
33 | "autoload": {
34 | "psr-4": {
35 | "Evotodi\\SeedBundle\\": "src/"
36 | }
37 | },
38 | "autoload-dev": {
39 | "psr-4": {
40 | "Evotodi\\SeedBundle\\Tests\\": "tests/"
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/example/config/bootstrap.php:
--------------------------------------------------------------------------------
1 | =1.2)
9 | if (is_array($env = @include dirname(__DIR__).'/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) {
10 | foreach ($env as $k => $v) {
11 | $_ENV[$k] = $_ENV[$k] ?? (isset($_SERVER[$k]) && 0 !== strpos($k, 'HTTP_') ? $_SERVER[$k] : $v);
12 | }
13 | } elseif (!class_exists(Dotenv::class)) {
14 | throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
15 | } else {
16 | // load all the .env files
17 | (new Dotenv())->loadEnv(dirname(__DIR__).'/.env');
18 | }
19 |
20 | $_SERVER += $_ENV;
21 | $_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev';
22 | $_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV'];
23 | $_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
24 |
--------------------------------------------------------------------------------
/example/config/services.yaml:
--------------------------------------------------------------------------------
1 | # This file is the entry point to configure your own services.
2 | # Files in the packages/ subdirectory configure your dependencies.
3 |
4 | # Put parameters here that don't need to change on each machine where the app is deployed
5 | # https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
6 | parameters:
7 |
8 | services:
9 | # default configuration for services in *this* file
10 | _defaults:
11 | autowire: true # Automatically injects dependencies in your services.
12 | autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
13 |
14 | # makes classes in src/ available to be used as services
15 | # this creates a service per class whose id is the fully-qualified class name
16 | App\:
17 | resource: '../src/*'
18 | exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
19 |
20 | # controllers are imported separately to make sure services can be injected
21 | # as action arguments even if you don't extend any base controller class
22 | App\Controller\:
23 | resource: '../src/Controller'
24 | tags: ['controller.service_arguments']
25 |
26 | # add more service definitions when explicit configuration is needed
27 | # please note that last definitions always *replace* previous ones
28 |
29 | # App\DataSeeds\TestSeed:
30 | # arguments: ['@doctrine.orm.entity_manager', '@service_container']
31 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | os: linux
3 | cache:
4 | directories:
5 | - $HOME/.composer/cache/files
6 | - $HOME/symfony-bridge/.phpunit
7 |
8 | env:
9 | global:
10 | - PHPUNIT_FLAGS="-v"
11 | - SYMFONY_PHPUNIT_DIR="$HOME/symfony-bridge/.phpunit"
12 |
13 | jobs:
14 | fast_finish: true
15 | include:
16 | # Minimum supported dependencies with the latest and oldest PHP version
17 | - php: 8.0
18 | env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest"
19 |
20 | # Latest commit to master
21 | - php: 8.0
22 | env: STABILITY="dev"
23 |
24 | allow_failures:
25 | # Dev-master is allowed to fail.
26 | - env: STABILITY="dev"
27 |
28 | before_install:
29 | - if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi
30 | - if ! [ -z "$STABILITY" ]; then composer config minimum-stability ${STABILITY}; fi;
31 | - if ! [ -v "$DEPENDENCIES" ]; then composer require --no-update ${DEPENDENCIES}; fi;
32 |
33 | install:
34 | # To be removed when this issue will be resolved: https://github.com/composer/composer/issues/5355
35 | - if [[ "$COMPOSER_FLAGS" == *"--prefer-lowest"* ]]; then
36 | composer update --prefer-dist --no-interaction --prefer-stable --quiet;
37 | else
38 | composer update --prefer-dist --no-interaction --quiet;
39 | fi
40 | - ./vendor/bin/simple-phpunit install
41 |
42 | script:
43 | - composer validate --strict --no-check-lock
44 | # simple-phpunit is the PHPUnit wrapper provided by the PHPUnit Bridge component and
45 | # it helps with testing legacy code and deprecations (composer require symfony/phpunit-bridge)
46 | - ./vendor/bin/simple-phpunit $PHPUNIT_FLAGS
47 |
--------------------------------------------------------------------------------
/example/.env:
--------------------------------------------------------------------------------
1 | # In all environments, the following files are loaded if they exist,
2 | # the latter taking precedence over the former:
3 | #
4 | # * .env contains default values for the environment variables needed by the app
5 | # * .env.local uncommitted file with local overrides
6 | # * .env.$APP_ENV committed environment-specific defaults
7 | # * .env.$APP_ENV.local uncommitted environment-specific overrides
8 | #
9 | # Real environment variables win over .env files.
10 | #
11 | # DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
12 | #
13 | # Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
14 | # https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
15 |
16 | ###> symfony/framework-bundle ###
17 | APP_ENV=dev
18 | APP_SECRET=my_secret
19 | #TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
20 | #TRUSTED_HOSTS='^(localhost|example\.com)$'
21 | ###< symfony/framework-bundle ###
22 |
23 | ###> doctrine/doctrine-bundle ###
24 | # Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
25 | # For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
26 | # For a PostgreSQL database, use: "postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=11&charset=utf8"
27 | # IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
28 | #DATABASE_URL=mysql://apollo:apollo@server-mysql:3306/seedtest
29 | DATABASE_URL=sqlite:///var/test.db
30 | ###< doctrine/doctrine-bundle ###
31 |
--------------------------------------------------------------------------------
/example/src/DataSeeds/DictWordsSeed.php:
--------------------------------------------------------------------------------
1 | disableDoctrineLogging();
29 |
30 | //Access doctrine through $this->doctrine
31 | $dictWordsRepository = $this->getManager()->getRepository(DictWords::class);
32 |
33 |
34 | foreach ($this->getWords() as $word) {
35 |
36 | if($dictWordsRepository->findOneBy(array('word' => $word))) {
37 | continue;
38 | }
39 |
40 | $em = new DictWords();
41 |
42 | $em->setWord($word);
43 |
44 | //Doctrine manager is also available
45 | $this->getManager()->persist($em);
46 |
47 | $this->getManager()->flush();
48 | }
49 |
50 | $this->getManager()->clear();
51 | return 0;
52 | }
53 |
54 | public function unload(InputInterface $input, OutputInterface $output): int
55 | {
56 | $className = $this->getManager()->getClassMetadata(DictWords::class )->getName();
57 | $this->getManager()->createQuery('DELETE FROM '.$className)->execute();
58 | return 0;
59 | }
60 |
61 | public function getWords(): bool|array
62 | {
63 | $words = file(__DIR__.'/../Resources/dictWords.txt');
64 | shuffle($words);
65 | return array_slice($words, 0, 1000);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/example/src/DataSeeds/CsvSeed.php:
--------------------------------------------------------------------------------
1 | parameterBag = $parameterBag;
21 | $this->filesystem = $filesystem;
22 | }
23 |
24 | public static function seedName(): string
25 | {
26 | return 'csv';
27 | }
28 |
29 | /**
30 | * @throws Exception
31 | */
32 | public function load(InputInterface $input, OutputInterface $output): int
33 | {
34 | $csvColumns = ['id', 'name', 'data'];
35 | $csvData = [];
36 | for($i = 0; $i < 10; $i++){
37 | $csvData[] = [$i, 'MyName'.$i, random_int(0, 1000)];
38 | }
39 |
40 | $this->filesystem->mkdir($this->parameterBag->get('kernel.project_dir').'/var');
41 |
42 | $file = fopen($this->parameterBag->get('kernel.project_dir').'/var/test.csv', 'w');
43 |
44 | fputcsv($file, $csvColumns);
45 | foreach ($csvData as $datum){
46 | fputcsv($file, $datum);
47 | }
48 |
49 | fclose($file);
50 |
51 | return 0;
52 | }
53 |
54 | public function unload(InputInterface $input, OutputInterface $output): int
55 | {
56 | $this->filesystem->remove($this->parameterBag->get('kernel.project_dir').'/var/test.csv');
57 | return 0;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/example/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "project",
3 | "license": "proprietary",
4 | "require": {
5 | "php": ">=8.0",
6 | "ext-ctype": "*",
7 | "ext-iconv": "*",
8 | "evotodi/seed-bundle": "dev-master",
9 | "sensio/framework-extra-bundle": "^6.0|^7.0",
10 | "symfony/asset": "^6.0|^7.0",
11 | "symfony/console": "^6.0|^7.0",
12 | "symfony/dotenv": "^6.0|^7.0",
13 | "symfony/flex": "^1.0",
14 | "symfony/framework-bundle": "^6.0|^7.0",
15 | "symfony/property-access": "^6.0|^7.0",
16 | "symfony/yaml": "^6.0|^7.0",
17 | "doctrine/doctrine-bundle": "^2.0",
18 | "doctrine/orm": "^2.8"
19 | },
20 | "require-dev": {
21 | "symfony/debug-bundle": "^6.0|^7.0",
22 | "symfony/maker-bundle": "^1.0",
23 | "symfony/stopwatch": "^6.0|^7.0",
24 | "symfony/var-dumper": "^6.0|^7.0",
25 | "symfony/web-profiler-bundle": "^6.0|^7.0"
26 | },
27 | "config": {
28 | "preferred-install": {
29 | "*": "dist"
30 | },
31 | "sort-packages": true,
32 | "allow-plugins": {
33 | "symfony/flex": true
34 | }
35 | },
36 | "autoload": {
37 | "psr-4": {
38 | "App\\": "src/"
39 | }
40 | },
41 | "autoload-dev": {
42 | "psr-4": {
43 | }
44 | },
45 | "replace": {
46 | "paragonie/random_compat": "2.*",
47 | "symfony/polyfill-ctype": "*",
48 | "symfony/polyfill-iconv": "*",
49 | "symfony/polyfill-php71": "*",
50 | "symfony/polyfill-php70": "*",
51 | "symfony/polyfill-php56": "*"
52 | },
53 | "scripts": {
54 | "auto-scripts": {
55 | "cache:clear": "symfony-cmd",
56 | "assets:install %PUBLIC_DIR%": "symfony-cmd"
57 | },
58 | "post-install-cmd": [
59 | "@auto-scripts"
60 | ],
61 | "post-update-cmd": [
62 | "@auto-scripts"
63 | ]
64 | },
65 | "conflict": {
66 | "symfony/symfony": "*"
67 | },
68 | "extra": {
69 | "symfony": {
70 | "allow-contrib": true,
71 | "require": "^6.0|^7.0",
72 | "docker": false
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/DependencyInjection/Compiler/SeedPass.php:
--------------------------------------------------------------------------------
1 | has('seed.registry')) {
21 | return;
22 | }
23 |
24 | $definition = $container->findDefinition('seed.registry');
25 | $taggedServices = $container->findTaggedServiceIds('seed.seed');
26 |
27 | foreach ($taggedServices as $id => $tags){
28 | $seedItem = $container->findDefinition($id);
29 | if(!$seedItem->getClass() instanceof SeedCoreCommand) {
30 | $seedItem->addMethodCall('setManager', [new Reference('doctrine')]);
31 | $seedItem->addMethodCall('setRegistry', [new Reference('seed.registry')]);
32 | }
33 | try {
34 | $rc = new ReflectionClass($id);
35 | if($rc->hasMethod('seedName')){
36 | $seedName = $rc->getMethod('seedName')->invoke(null);
37 | if(in_array($seedName, ['load', 'unload', SeedCoreCommand::CORE_SEED_NAME])){
38 | throw new InvalidSeedNameException(InvalidSeedNameException::MESSAGE . $id);
39 | }
40 | $seedOrder = $rc->getMethod('getOrder')->invoke(null);
41 |
42 | $definition->addMethodCall('addSeed', [$seedName, new Reference($id), $seedOrder]);
43 | }
44 | } catch (ReflectionException) {
45 | }
46 |
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Core/SeedRegistry.php:
--------------------------------------------------------------------------------
1 | 'string', 'class' => 'object', 'order' => 'int', 'path' => 'string'])]
11 | private array $seeds = [];
12 |
13 | /** @noinspection PhpUnused */
14 | public function addSeed(string $seedName, object $seedClass, int $seedOrder): void
15 | {
16 | $this->seeds[strtolower($seedName)] = [
17 | 'name' => strtolower($seedName),
18 | 'class' => $seedClass,
19 | 'order' => $seedOrder,
20 | 'path' => "/". str_replace(':', "/", strtolower($seedName)),
21 | ];
22 | }
23 |
24 | #[ArrayShape(['name' => ['name' => 'string', 'class' => 'object', 'order' => 'int', 'path' => 'string']])]
25 | public function all(): array
26 | {
27 | return $this->seeds;
28 | }
29 |
30 | #[ArrayShape(['name' => 'string', 'class' => 'object', 'order' => 'int', 'path' => 'string'])]
31 | public function get(string $seedName): ?array
32 | {
33 | if(key_exists(strtolower($seedName), $this->seeds)){
34 | return $this->seeds[strtolower($seedName)];
35 | }
36 | return null;
37 | }
38 |
39 | public function has(string $seedName): bool
40 | {
41 | if(key_exists(strtolower($seedName), $this->seeds)){
42 | return true;
43 | }
44 | return false;
45 | }
46 |
47 | #[ArrayShape(['name' => 'string'])]
48 | public function keys(): array
49 | {
50 | return array_keys($this->seeds);
51 | }
52 |
53 | #[ArrayShape(['name' => 'string'])]
54 | public function glob(string $glob): array
55 | {
56 | $paths = array_column($this->seeds, 'path');
57 |
58 | $globPath = strtolower($glob);
59 | if(!str_starts_with($glob, '/')){
60 | $globPath = '/' . $glob;
61 | }
62 | $globPath = str_replace(':', '/', $globPath);
63 |
64 | $matches = Glob::filter($paths, $globPath);
65 |
66 | $ret = [];
67 | foreach ($matches as $val){
68 | $seed = $this->get(ltrim(str_replace('/', ":", $val), ':'));
69 | if($seed){
70 | $ret[] = $seed['name'];
71 | }
72 | }
73 | if(empty($ret)){
74 | $ret[] = strtolower($glob);
75 | }
76 | return $ret;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/example/src/DataSeeds/USStatesSeed.php:
--------------------------------------------------------------------------------
1 | disableDoctrineLogging();
34 |
35 | //Access doctrine through $this->doctrine
36 | $statesRepository = $this->getManager()->getRepository(States::class);
37 |
38 |
39 | foreach ($this->getStates() as $abv => $name) {
40 |
41 | if($statesRepository->findOneBy(array('abv' => $abv))) {
42 | continue;
43 | }
44 |
45 | $em = new States();
46 |
47 | $em->setAbv($abv);
48 | $em->setName($name);
49 |
50 | //Doctrine manager is also available
51 | $this->getManager()->persist($em);
52 |
53 | $this->getManager()->flush();
54 | }
55 |
56 | $this->getManager()->clear();
57 | return 0;
58 | }
59 |
60 | public function unload(InputInterface $input, OutputInterface $output): int
61 | {
62 | $className = $this->getManager()->getClassMetadata(States::class)->getName();
63 | $this->getManager()->createQuery('DELETE FROM '.$className)->execute();
64 | return 0;
65 | }
66 |
67 | public function getStates(): array
68 | {
69 | return array (
70 | 'AL'=>'Alabama',
71 | 'AK'=>'Alaska',
72 | 'AZ'=>'Arizona',
73 | 'AR'=>'Arkansas',
74 | 'CA'=>'California',
75 | 'CO'=>'Colorado',
76 | 'CT'=>'Connecticut',
77 | 'DE'=>'Delaware',
78 | 'DC'=>'District of Columbia',
79 | 'FL'=>'Florida',
80 | 'GA'=>'Georgia',
81 | 'HI'=>'Hawaii',
82 | 'ID'=>'Idaho',
83 | 'IL'=>'Illinois',
84 | 'IN'=>'Indiana',
85 | 'IA'=>'Iowa',
86 | 'KS'=>'Kansas',
87 | 'KY'=>'Kentucky',
88 | 'LA'=>'Louisiana',
89 | 'ME'=>'Maine',
90 | 'MD'=>'Maryland',
91 | 'MA'=>'Massachusetts',
92 | 'MI'=>'Michigan',
93 | 'MN'=>'Minnesota',
94 | 'MS'=>'Mississippi',
95 | 'MO'=>'Missouri',
96 | 'MT'=>'Montana',
97 | 'NE'=>'Nebraska',
98 | 'NV'=>'Nevada',
99 | 'NH'=>'New Hampshire',
100 | 'NJ'=>'New Jersey',
101 | 'NM'=>'New Mexico',
102 | 'NY'=>'New York',
103 | 'NC'=>'North Carolina',
104 | 'ND'=>'North Dakota',
105 | 'OH'=>'Ohio',
106 | 'OK'=>'Oklahoma',
107 | 'OR'=>'Oregon',
108 | 'PA'=>'Pennsylvania',
109 | 'RI'=>'Rhode Island',
110 | 'SC'=>'South Carolina',
111 | 'SD'=>'South Dakota',
112 | 'TN'=>'Tennessee',
113 | 'TX'=>'Texas',
114 | 'UT'=>'Utah',
115 | 'VT'=>'Vermont',
116 | 'VA'=>'Virginia',
117 | 'WA'=>'Washington',
118 | 'WV'=>'West Virginia',
119 | 'WI'=>'Wisconsin',
120 | 'WY'=>'Wyoming',
121 | );
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/example/src/DataSeeds/USStatesSeed2.php:
--------------------------------------------------------------------------------
1 | disableDoctrineLogging();
34 |
35 | //Access doctrine through $this->doctrine
36 | $statesRepository = $this->getManager()->getRepository(States::class);
37 |
38 |
39 | foreach ($this->getStates() as $abv => $name) {
40 |
41 | if($statesRepository->findOneBy(array('abv' => $abv))) {
42 | continue;
43 | }
44 |
45 | $em = new States();
46 |
47 | $em->setAbv($abv);
48 | $em->setName($name);
49 |
50 | //Doctrine manager is also available
51 | $this->getManager()->persist($em);
52 |
53 | $this->getManager()->flush();
54 | }
55 |
56 | $this->getManager()->clear();
57 | return 0;
58 | }
59 |
60 | public function unload(InputInterface $input, OutputInterface $output): int
61 | {
62 | $className = $this->getManager()->getClassMetadata(States::class)->getName();
63 | $this->getManager()->createQuery('DELETE FROM '.$className)->execute();
64 | return 0;
65 | }
66 |
67 | public function getStates(): array
68 | {
69 | return array (
70 | 'AL'=>'Alabama',
71 | 'AK'=>'Alaska',
72 | 'AZ'=>'Arizona',
73 | 'AR'=>'Arkansas',
74 | 'CA'=>'California',
75 | 'CO'=>'Colorado',
76 | 'CT'=>'Connecticut',
77 | 'DE'=>'Delaware',
78 | 'DC'=>'District of Columbia',
79 | 'FL'=>'Florida',
80 | 'GA'=>'Georgia',
81 | 'HI'=>'Hawaii',
82 | 'ID'=>'Idaho',
83 | 'IL'=>'Illinois',
84 | 'IN'=>'Indiana',
85 | 'IA'=>'Iowa',
86 | 'KS'=>'Kansas',
87 | 'KY'=>'Kentucky',
88 | 'LA'=>'Louisiana',
89 | 'ME'=>'Maine',
90 | 'MD'=>'Maryland',
91 | 'MA'=>'Massachusetts',
92 | 'MI'=>'Michigan',
93 | 'MN'=>'Minnesota',
94 | 'MS'=>'Mississippi',
95 | 'MO'=>'Missouri',
96 | 'MT'=>'Montana',
97 | 'NE'=>'Nebraska',
98 | 'NV'=>'Nevada',
99 | 'NH'=>'New Hampshire',
100 | 'NJ'=>'New Jersey',
101 | 'NM'=>'New Mexico',
102 | 'NY'=>'New York',
103 | 'NC'=>'North Carolina',
104 | 'ND'=>'North Dakota',
105 | 'OH'=>'Ohio',
106 | 'OK'=>'Oklahoma',
107 | 'OR'=>'Oregon',
108 | 'PA'=>'Pennsylvania',
109 | 'RI'=>'Rhode Island',
110 | 'SC'=>'South Carolina',
111 | 'SD'=>'South Dakota',
112 | 'TN'=>'Tennessee',
113 | 'TX'=>'Texas',
114 | 'UT'=>'Utah',
115 | 'VT'=>'Vermont',
116 | 'VA'=>'Virginia',
117 | 'WA'=>'Washington',
118 | 'WV'=>'West Virginia',
119 | 'WI'=>'Wisconsin',
120 | 'WY'=>'Wyoming',
121 | );
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | 
3 |
4 |
5 | 
6 |
7 | # Symfony/Doctrine Seed Bundle
8 | Used to load/unload seed data from a doctrine database or anything that needs seeded.
9 |
10 | Example would be to load a table with a list of states and abbreviations, or populate the users table with initial admin user(s).
11 | Unlike the [DoctrineFixturesBundle](https://github.com/doctrine/DoctrineFixturesBundle) which is mainly for development this bundle is for seeding a database before the initial push to production.
12 |
13 | ## Installation
14 | Install the package with:
15 | ```console
16 | composer require evotodi/seed-bundle
17 | ```
18 |
19 |
20 | (Optional) Load seeds as services `config/services.yaml`
21 | In Symfony default services.yaml classes in src/ are loaded as services, so creating a folder src/DataSeeds/ will load the seeds as services.
22 | ```yaml
23 | services:
24 | Evotodi\SeedBundle\DataSeeds\:
25 | resource: '../DataSeeds/*'
26 | ```
27 |
28 | ## Building a seed to populate a database
29 | The `Seed` class is a `Command` and :
30 |
31 | - Must extend `Evotodi\SeedBundle\Command\Seed`
32 | - Must return the seed name from the static `seedName` method
33 | - Seed naming must follow the colon seperated naming convention for symfony console commands.
34 |
35 |
36 | ```php
37 | disableDoctrineLogging();
82 |
83 | $users = [
84 | [
85 | 'email' => 'admin@admin.com',
86 | 'password' => 'password123',
87 | 'roles' => ['ROLE_ADMIN'],
88 | ],
89 |
90 |
91 | ];
92 |
93 | foreach ($users as $user){
94 | $userRepo = new User();
95 | $userRepo->setEmail($user['email']);
96 | $userRepo->setRoles($user['roles']);
97 | $userRepo->setPassword($this->passwordEncoder->encodePassword($userRepo, $user['password']));
98 | $this->manager->persist($userRepo);
99 | }
100 | $this->manager->flush();
101 | $this->manager->clear();
102 |
103 | /**
104 | * Must return an exit code.
105 | * A value other than 0 or Command::SUCCESS is considered a failed seed load/unload.
106 | */
107 | return 0;
108 | }
109 |
110 | /**
111 | * The unload method is called when unloading a seed
112 | */
113 | public function unload(InputInterface $input, OutputInterface $output): int
114 | {
115 | //Clear the table
116 | $this->manager->getConnection()->exec('DELETE FROM user');
117 |
118 | /**
119 | * Must return an exit code.
120 | * A value other than 0 or Command::SUCCESS is considered a failed seed load/unload.
121 | */
122 | return 0;
123 | }
124 | }
125 | ```
126 |
127 | ## Seed commands
128 | The SeedBundle gives you two default commands and one for each seed you made.
129 | With the previous example, I'd have:
130 |
131 | ```
132 | bin/console seed:load
133 | bin/console seed:unload
134 | bin/console seed:user
135 | ```
136 | *Note: If your seeds do not show up in the command list under seed: then clear the cache*
137 |
138 | ## Global seed commands
139 | The global `seed:load` and `seed:unload` allow you to run multiple seeds in one command.
140 | The rest of this section will only show `seed:load` as it works the same as `seed:unload`.
141 |
142 | * `seed:load` will load all seeds in ascending order.
143 | * `seed:load user` will load only the user seed (see the example above).
144 | * Multiple seed like `seed:load user country town` will only load those seeds.
145 | * `seed:load --skip country` will load all seed except country. Multiple skips are allowed.
146 | * `seed:load --debug` with the debug flag will print what will be loaded and in what order.
147 | * `seed:load --break` will exit the seed load if a seed fails.
148 | * `seed:load --from country` will start with the county seed and load from there skipping lesser order values and possibly skipping same order values as country.
149 | See [Global seed ordering](#global-seed-ordering) for more details.
150 |
151 | ## Global seed name matching
152 | Seed names are matched using [webmozarts/glob](https://github.com/webmozarts/glob) filtering by turning the seed names into path like strings.
153 | An example would be if you had the following seeds:
154 | - prod:users:us
155 | - prod:users:eu
156 | - prod:users:it
157 | - prod:prices
158 | - prod:products
159 | - dev:users
160 | - dev:prices
161 | - dev:products
162 |
163 | And wanted to only load the users in the 'prod' group then call `seed:load prod/users/*`
164 | Or to load the whole 'prod' group then call `seed:load prod/**/*`
165 | Or load the 'dev' prices and products along with the 'prod' users then call `seed:load dev:prices dev:products prod:users:*`
166 |
167 | *Note: colons and forward slashed are interchangeable because all colons are replaced with forward slashes for filtering.*
168 |
169 | Please see the readme of [webmozarts/glob](https://github.com/webmozarts/glob) for more information on glob patterns.
170 |
171 | ## Global seed ordering
172 | Every seed has a `getOrder` method that is used to sort them. The default value is `0`.
173 | Seeds are loaded/unloaded in ascending order.
174 |
175 | #### Caution: Seeds with the same order value are loaded semi-randomly. This is especially a concern when using the --from option.
176 | #### Example issue of ordering and --from
177 | Seeds:
178 | * seed-a order 0
179 | * seed-b order 1
180 | * seed-c order 1
181 | * seed-d order 1
182 | * seed-e order 2
183 |
184 | Calling `seed:load --from seed-c` will start loading with seed-c but since seed-b and seed-d have the same order one or both may or may not be loaded depending on what order they were loaded into the registry.
185 | It is suggested to use the `--debug` flag to verify the order of loading or sequentially order your seeds.
186 |
187 | ## Manual seed commands
188 | Calling `seed:user load` (from example above) will load only the user seed. Conversely, calling `seed:user unload` will unload it.
189 |
190 | ## Example project
191 | In the example folder is a project that can be used to experiment with the Seed bundle.
192 | It shows how to seed a database or flat file.
193 |
194 | ## Thanks
195 | Thanks to soyuka/SeedBundle
196 |
197 | ## Contributions
198 | Contributions are very welcome!
199 |
200 | Please create detailed issues and PRs.
201 |
202 | ## Licence
203 |
204 | This package is free software distributed under the terms of the [MIT license](LICENSE).
205 |
206 | ## Updates
207 | * 2024-01-16
208 | * Fix depreciations for PHP 8.4
209 | * 2022-05-10 
210 | * Breaking changes to previous versions as this is mostly a re-write of the bundle.
211 | * Seeds no longer need to have a name ending in seed
212 | * Setting the seed name is no longer supported in the configure method. Use the static method seedName to return the seed name.
213 | * The configuration file has been dropped
214 | * Php 8+ is required
215 | * Symfony 6+ is required
216 | * 2021-12-06
217 | * Updated dependencies to allow for symfony 5.3 and 5.4
218 | * 2020-06-03
219 | * Updated dependencies to allow for Symfony 4.4.* and 5.0.* and 5.1.*
220 | * 2020-04-23
221 | * Updated dependencies to allow for Symfony 4.4.* and 5.0.*
222 | * Added a required return exit code to load and unload functions
223 | * Updated tests to reflect required return code
224 |
--------------------------------------------------------------------------------
/src/Core/SeedCoreCommand.php:
--------------------------------------------------------------------------------
1 | manager = $manager;
31 | }
32 |
33 | /** @noinspection PhpUnused */
34 | public function setRegistry(SeedRegistry $registry): void
35 | {
36 | $this->registry = $registry;
37 | }
38 |
39 | public static function seedName(): string
40 | {
41 | return self::CORE_SEED_NAME;
42 | }
43 |
44 | /** @noinspection PhpUnused */
45 | public static function getOrder(): int
46 | {
47 | return 0;
48 | }
49 |
50 | private function getSeedName(): string
51 | {
52 | return preg_replace('/^seed:/', '', $this->getName());
53 | }
54 |
55 | public function getManager(?string $name = null): ObjectManager
56 | {
57 | return $this->manager->getManager($name);
58 | }
59 |
60 | protected function baseConfigure(): void
61 | {
62 | $this
63 | ->setName(sprintf('seed:%s', $this->seedName()))
64 | ->addOption('skip', '-s', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Seed(s) to skip')
65 | ->addOption('break', '-b', InputOption::VALUE_NONE, 'Stop on failed seed')
66 | ->addOption('debug', '-d', InputOption::VALUE_NONE, 'Debug seed ordering without making changes')
67 | ->addOption('from', '-f', InputOption::VALUE_REQUIRED, 'Start from seed. Unavailable for glob matching')
68 | ;
69 | }
70 |
71 | protected function configure(): void
72 | {
73 | $this
74 | ->addArgument('seeds', InputArgument::IS_ARRAY, 'seed(s)')
75 | ;
76 | $this->baseConfigure();
77 | }
78 |
79 | protected function execute(InputInterface $input, OutputInterface $output): int
80 | {
81 | $io = new SymfonyStyle($input, $output);
82 | $debug = $input->getOption('debug');
83 |
84 | $seedArgs = [];
85 | if($input->hasArgument('seeds')){
86 | /** Add seeds from args to seedLoadNames */
87 | $seedArgs = $input->getArgument('seeds');
88 | if(empty($seedArgs)){
89 | $seedArgs = $this->registry->keys();
90 | }
91 | }else{
92 | /** Else add single command seed to seedLoadNames */
93 | $seedArgs[] = $this->getSeedName();
94 | }
95 |
96 | if($input->hasArgument('method')){
97 | $this->method = $input->getArgument('method');
98 | $this->manual = true;
99 | }
100 |
101 | if (!in_array($this->method, ['load', 'unload'])) {
102 | throw new InvalidArgumentException('Method should be one of: load, unload');
103 | }
104 |
105 | /** Check if seed from is valid */
106 | $from = $input->getOption('from');
107 | if($from) {
108 | $from = strtolower($from);
109 | if (!$this->registry->has($from)) {
110 | throw new InvalidArgumentException(sprintf("Invalid from seed %s! Valid seeds are '%s'", $from, join(", '", $this->registry->keys())));
111 | }
112 | $io->text(sprintf('Starting at seed %s', get_class($this->registry->get($from)['class'])));
113 | }
114 |
115 | /** Check if seed skips is valid */
116 | $skips = $input->getOption('skip');
117 | if(!empty($skips)){
118 | foreach ($skips as $sKey => $skip){
119 | $skips[$sKey] = strtolower($skip);
120 | if (!$this->registry->has(strtolower($skip))) {
121 | throw new InvalidArgumentException(sprintf("Invalid skip seed %s! Valid seeds are '%s'", $skip, join(", '", $this->registry->keys())));
122 | }
123 | }
124 | }
125 |
126 | /** Gather all seeds to process */
127 | $seedsToProcess = [];
128 | foreach ($seedArgs as $seedArg) {
129 | foreach ($this->registry->glob($seedArg) as $seedName){
130 | $seedsToProcess[] = $seedName;
131 | }
132 | }
133 | $seedsToProcess = array_unique($seedsToProcess);
134 |
135 | /** Check if seed names are valid and create SeedItems */
136 | $seedItems = [];
137 | foreach ($seedsToProcess as $seedName) {
138 | if (!$this->registry->has($seedName)) {
139 | throw new InvalidArgumentException(sprintf("Invalid seed '%s'! Valid seeds are '%s'", $seedName, join(", '", $this->registry->keys())));
140 | }
141 | $regItem = $this->registry->get($seedName);
142 | $seedItems[] = new SeedItem($regItem['name'], $regItem['class'], $regItem['order'], $this->manual);
143 | }
144 |
145 | /** Sort the seeds in order */
146 | usort($seedItems, function ($a, $b) {
147 | return $a->order <=> $b->order;
148 | });
149 |
150 | /** Check for seeds to process */
151 | if(count($seedItems) == 0){
152 | $io->warning("No seeds found");
153 | return Command::FAILURE;
154 | }
155 |
156 | $processStartTime = microtime(true);
157 | $failedSeeds = [];
158 | $skippedSeeds = [];
159 | $startFrom = true;
160 |
161 | if($debug){
162 | $io->warning("Debugging seed order. No changes will be made.");
163 | }
164 | foreach ($seedItems as $seedItem){
165 | $retCode = 0;
166 | if($startFrom and $from){
167 | if($seedItem->name != $from){
168 | $io->text(sprintf('Skipping by from %s order %s', $seedItem->getClassName(), $seedItem->order));
169 | $skippedSeeds[] = $seedItem->getClassName();
170 | continue;
171 | }else{
172 | $startFrom = false;
173 | }
174 | }
175 |
176 | if(in_array($seedItem->name, $skips)){
177 | $io->text(sprintf('Skipping by skip %s order %s', $seedItem->getClassName(), $seedItem->order));
178 | $skippedSeeds[] = $seedItem->getClassName();
179 | continue;
180 | }
181 |
182 | $seedStartTime = microtime(true);
183 |
184 | switch ($this->method) {
185 | case 'load':
186 | if($debug){
187 | $io->text(sprintf('Debug loading %s with order %s', $seedItem->getClassName(), $seedItem->order));
188 | }else {
189 | $io->text(sprintf('Starting load %s order %s...', $seedItem->getClassName(), $seedItem->order));
190 | if ($seedItem->manual) {
191 | /** @noinspection PhpUnhandledExceptionInspection */
192 | $retCode = $this->load($input, $output);
193 | } else {
194 | $cls = $seedItem->classRef;
195 | $retCode = $cls->load($input, $output);
196 |
197 | }
198 | }
199 | break;
200 | case 'unload':
201 | if($debug){
202 | $io->text(sprintf('Debug unloading %s with order %s', $seedItem->getClassName(), $seedItem->order));
203 | }else {
204 | $io->text(sprintf('Starting unload %s order %s...', $seedItem->getClassName(), $seedItem->order));
205 | if ($seedItem->manual) {
206 | /** @noinspection PhpUnhandledExceptionInspection */
207 | $retCode = $this->unload($input, $output);
208 | } else {
209 | $cls = $seedItem->classRef;
210 | $retCode = $cls->unload($input, $output);
211 | }
212 | }
213 | break;
214 | }
215 |
216 | $seedTime = microtime(true) - $seedStartTime;
217 |
218 | if($retCode > 0){
219 | $io->text(sprintf('Failed processing seed %s return code was %s (%.2f seconds)', $seedItem->getClassName(), $retCode, $seedTime));
220 | $failedSeeds[] = $seedItem->getClassName();
221 | }else{
222 | if(!$debug) {
223 | $io->text(sprintf('Seed done %s (%.2f seconds)', $seedItem->getClassName(), $seedTime));
224 | }
225 | }
226 | if($input->getOption('break')){
227 | $io->text("Stopped on failed seed");
228 | return Command::FAILURE;
229 | }
230 | }
231 |
232 | $processTime = microtime(true) - $processStartTime;
233 | if(!$debug) {
234 | $completeMessage = sprintf('Loading seed(s) completed (%.2f seconds)', $processTime);
235 | if(empty($failedSeeds) and empty($skippedSeeds)) {
236 | $io->success($completeMessage);
237 | }else{
238 | if(!empty($failedSeeds)){
239 | $completeMessage .= sprintf("\nFailed Seeds: %s", join(', ', array_unique($failedSeeds)));
240 | }
241 | if(!empty($skippedSeeds)){
242 | $completeMessage .= sprintf("\nSkipped Seeds: %s", join(', ', array_unique($skippedSeeds)));
243 | }
244 | $io->warning($completeMessage);
245 | }
246 | }
247 |
248 | return Command::SUCCESS;
249 | }
250 |
251 | /**
252 | * @noinspection PhpUnhandledExceptionInspection
253 | * @noinspection PhpUnusedParameterInspection
254 | */
255 | public function load(InputInterface $input, OutputInterface $output): int
256 | {
257 | throw new Exception("Core seed load should not be called");
258 | }
259 |
260 | /**
261 | * @noinspection PhpUnhandledExceptionInspection
262 | * @noinspection PhpUnusedParameterInspection
263 | */
264 | public function unload(InputInterface $input, OutputInterface $output): int
265 | {
266 |
267 | throw new Exception("Core seed unload should not be called");
268 | }
269 |
270 | /**
271 | * disableDoctrineLogging
272 | * Shortcut to disable doctrine logging, useful when loading big seeds to
273 | * avoid memory leaks.
274 | * @noinspection PhpUnused
275 | */
276 | protected function disableDoctrineLogging(): void
277 | {
278 | $config = $this->manager->getConnection()->getConfiguration();
279 | if (method_exists($config,'setSQLLogger')) {
280 | $config->setSQLLogger(null);
281 | } else {
282 | $config->setMiddlewares(array_filter(
283 | $config->getMiddlewares(),
284 | fn($middleware) => !($middleware instanceof Middleware)
285 | ));
286 | }
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/tests/SeedCommandTest.php:
--------------------------------------------------------------------------------
1 | application = new Application($kernel);
23 | self::$cacheDir = self::$kernel->getCacheDir();
24 | }
25 |
26 | public static function tearDownAfterClass(): void
27 | {
28 | parent::tearDownAfterClass();
29 | /** Remove the cache dir */
30 | if(!is_null(self::$cacheDir) and self::$cacheDir != '/') {
31 | (new Filesystem())->remove(self::$cacheDir);
32 | }
33 | }
34 |
35 | /** @dataProvider seedProvider */
36 | public function testSeedsExist(string $seed)
37 | {
38 | $command = $this->application->find($seed);
39 | $this->assertEquals($seed, $command->getName());
40 | }
41 |
42 | public function seedProvider(): Generator
43 | {
44 | yield 'Country Seed' => ['seed:country'];
45 | yield 'Glob Seed A' => ['seed:foo:bar'];
46 | yield 'Glob Seed B' => ['seed:foo:baz'];
47 | yield 'Postcode Seed' => ['seed:postcode'];
48 | yield 'Street Seed' => ['seed:street'];
49 | yield 'Town Seed' => ['seed:town'];
50 | yield 'Fail Seed' => ['seed:fail'];
51 | }
52 |
53 | public function testBadSeedNotExist()
54 | {
55 | $this->expectException(CommandNotFoundException::class);
56 | $this->application->find("seed:bad");
57 | }
58 |
59 | public function testSeedCommandMethod()
60 | {
61 | $this->expectException(InvalidArgumentException::class);
62 | $this->expectExceptionMessage("Method should be one of: load, unload");
63 | $command = $this->application->find('seed:country');
64 |
65 | $commandTester = new CommandTester($command);
66 | $commandTester->execute(['command' => $command->getName(), 'method' => 'nonexistant']);
67 |
68 | $this->assertEquals(1, $commandTester->getStatusCode());
69 | }
70 |
71 | public function testNoSeeds()
72 | {
73 | $tokenServiceMock = $this->getMockBuilder(SeedRegistry::class)
74 | ->disableOriginalConstructor()
75 | ->getMock();
76 | self::getContainer()->set('seed.registry', $tokenServiceMock);
77 |
78 | $command = $this->application->find('seed:load');
79 | $commandTester = new CommandTester($command);
80 | $commandTester->execute(['command' => $command->getName()]);
81 |
82 | $this->assertMatchesRegularExpression('/No seeds found/', $commandTester->getDisplay());
83 | $this->assertEquals(1, $commandTester->getStatusCode());
84 | }
85 |
86 | public function testLoadSeeds()
87 | {
88 | $command = $this->application->find('seed:load');
89 |
90 | $commandTester = new CommandTester($command);
91 | $commandTester->execute(['command' => $command->getName()]);
92 |
93 | $output = $commandTester->getDisplay();
94 |
95 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/", $output);
96 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/", $output);
97 |
98 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\TownSeed/", $output);
99 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\TownSeed/", $output);
100 |
101 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\StreetSeed/", $output);
102 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\StreetSeed/", $output);
103 |
104 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\PostcodeSeed/", $output);
105 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\PostcodeSeed/", $output);
106 |
107 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedA/", $output);
108 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedA/", $output);
109 |
110 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedB/", $output);
111 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedB/", $output);
112 |
113 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\FailSeed/", $output);
114 | $this->assertMatchesRegularExpression("/Failed processing seed Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\FailSeed/", $output);
115 |
116 | $this->assertEquals(0, $commandTester->getStatusCode());
117 | }
118 |
119 | public function testUnloadSeeds()
120 | {
121 | $command = $this->application->find('seed:unload');
122 |
123 | $commandTester = new CommandTester($command);
124 | $commandTester->execute(['command' => $command->getName()]);
125 |
126 | $output = $commandTester->getDisplay();
127 |
128 | $this->assertMatchesRegularExpression("/Starting unload Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/", $output);
129 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/", $output);
130 |
131 | $this->assertMatchesRegularExpression("/Starting unload Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\TownSeed/", $output);
132 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\TownSeed/", $output);
133 |
134 | $this->assertMatchesRegularExpression("/Starting unload Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\StreetSeed/", $output);
135 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\StreetSeed/", $output);
136 |
137 | $this->assertMatchesRegularExpression("/Starting unload Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\PostcodeSeed/", $output);
138 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\PostcodeSeed/", $output);
139 |
140 | $this->assertMatchesRegularExpression("/Starting unload Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedA/", $output);
141 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedA/", $output);
142 |
143 | $this->assertMatchesRegularExpression("/Starting unload Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedB/", $output);
144 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedB/", $output);
145 |
146 | $this->assertMatchesRegularExpression("/Starting unload Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\FailSeed/", $output);
147 | $this->assertMatchesRegularExpression("/Failed processing seed Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\FailSeed/", $output);
148 | $this->assertEquals(0, $commandTester->getStatusCode());
149 | }
150 |
151 | public function testNamedSeeds()
152 | {
153 | $command = $this->application->find('seed:load');
154 |
155 | $commandTester = new CommandTester($command);
156 | $commandTester->execute(['command' => $command->getName(), 'seeds' => ['country']]);
157 |
158 | $output = $commandTester->getDisplay();
159 |
160 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/", $output);
161 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/", $output);
162 |
163 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\TownSeed/", $output);
164 | $this->assertDoesNotMatchRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\TownSeed/", $output);
165 |
166 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\StreetSeed/", $output);
167 | $this->assertDoesNotMatchRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\StreetSeed/", $output);
168 |
169 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\PostcodeSeed/", $output);
170 | $this->assertDoesNotMatchRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\PostcodeSeed/", $output);
171 |
172 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedA/", $output);
173 | $this->assertDoesNotMatchRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedA/", $output);
174 |
175 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedB/", $output);
176 | $this->assertDoesNotMatchRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedB/", $output);
177 |
178 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\FailSeed/", $output);
179 | $this->assertDoesNotMatchRegularExpression("/Failed processing seed Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\FailSeed/", $output);
180 |
181 | $this->assertEquals(0, $commandTester->getStatusCode());
182 | }
183 |
184 | public function testGlobSeeds()
185 | {
186 | $command = $this->application->find('seed:load');
187 |
188 | $commandTester = new CommandTester($command);
189 | $commandTester->execute(['command' => $command->getName(), 'seeds' => ['foo:*']]);
190 |
191 | $output = $commandTester->getDisplay();
192 |
193 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedA/", $output);
194 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedA/", $output);
195 |
196 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedB/", $output);
197 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedB/", $output);
198 |
199 | $this->assertEquals(0, $commandTester->getStatusCode());
200 | }
201 |
202 | public function testSkipSeeds()
203 | {
204 | $command = $this->application->find('seed:load');
205 |
206 | $commandTester = new CommandTester($command);
207 | $commandTester->execute(['command' => $command->getName(), '--skip' => ['Town', 'fail']]);
208 |
209 | $output = $commandTester->getDisplay();
210 |
211 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/", $output);
212 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/", $output);
213 |
214 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\TownSeed/", $output);
215 | $this->assertDoesNotMatchRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\TownSeed/", $output);
216 |
217 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\StreetSeed/", $output);
218 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\StreetSeed/", $output);
219 |
220 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\PostcodeSeed/", $output);
221 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\PostcodeSeed/", $output);
222 |
223 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedA/", $output);
224 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedA/", $output);
225 |
226 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedB/", $output);
227 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\GlobSeedB/", $output);
228 |
229 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\FailSeed/", $output);
230 | $this->assertDoesNotMatchRegularExpression("/Failed processing seed Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\FailSeed/", $output);
231 |
232 | $this->assertEquals(0, $commandTester->getStatusCode());
233 | }
234 |
235 | public function testBreakSeed()
236 | {
237 | $command = $this->application->find('seed:load');
238 |
239 | $commandTester = new CommandTester($command);
240 | $commandTester->execute(['command' => $command->getName(), '-b' => true]);
241 |
242 | $output = $commandTester->getDisplay();
243 |
244 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/", $output);
245 | $this->assertDoesNotMatchRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/", $output);
246 |
247 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\TownSeed/", $output);
248 | $this->assertDoesNotMatchRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\TownSeed/", $output);
249 |
250 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\StreetSeed/", $output);
251 | $this->assertDoesNotMatchRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\StreetSeed/", $output);
252 |
253 | $this->assertMatchesRegularExpression('/Failed processing seed Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\FailSeed/', $output);
254 | $this->assertEquals(1, $commandTester->getStatusCode());
255 | }
256 |
257 | public function testDebugSeed()
258 | {
259 | $command = $this->application->find('seed:load');
260 |
261 | $commandTester = new CommandTester($command);
262 | $commandTester->execute(['command' => $command->getName(), '-d' => true, 'seeds' => ['country']]);
263 |
264 | $output = $commandTester->getDisplay();
265 |
266 | $this->assertMatchesRegularExpression('/Debug loading Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/', $output);
267 | $this->assertEquals(0, $commandTester->getStatusCode());
268 | }
269 |
270 | public function testFromSeed()
271 | {
272 | $command = $this->application->find('seed:load');
273 |
274 | $commandTester = new CommandTester($command);
275 | $commandTester->execute(['command' => $command->getName(), '-f' => 'street']);
276 |
277 | $output = $commandTester->getDisplay();
278 |
279 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/", $output);
280 | $this->assertDoesNotMatchRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\CountrySeed/", $output);
281 |
282 | $this->assertDoesNotMatchRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\TownSeed/", $output);
283 | $this->assertDoesNotMatchRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\TownSeed/", $output);
284 |
285 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\StreetSeed/", $output);
286 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\StreetSeed/", $output);
287 |
288 | $this->assertMatchesRegularExpression("/Starting load Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\PostcodeSeed/", $output);
289 | $this->assertMatchesRegularExpression("/Seed done Evotodi\\\\SeedBundle\\\\Tests\\\\fixtures\\\\PostcodeSeed/", $output);
290 |
291 | $this->assertEquals(0, $commandTester->getStatusCode());
292 | }
293 |
294 | }
295 |
--------------------------------------------------------------------------------