SeedCommand::configure()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 39
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 29
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 39
ccs 0
cts 35
cp 0
crap 2
rs 9.456
1
<?php
2
/**
3
 * This file is part of graze/sprout.
4
 *
5
 * Copyright © 2018 Nature Delivered Ltd. <https://www.graze.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license https://github.com/graze/sprout/blob/master/LICENSE.md
11
 * @link    https://github.com/graze/sprout
12
 */
13
14
namespace Graze\Sprout\Command;
15
16
use Exception;
17
use Graze\ParallelProcess\Pool;
18
use Graze\ParallelProcess\Table;
19
use Graze\Sprout\Config\Config;
20
use Graze\Sprout\Parser\FileTablePopulator;
21
use Graze\Sprout\Parser\ParsedSchema;
22
use Graze\Sprout\Parser\SchemaParser;
23
use Graze\Sprout\Seed\Seeder;
24
use Graze\Sprout\Seed\TableSeederFactory;
25
use League\Flysystem\Adapter\Local;
26
use Symfony\Component\Console\Command\Command;
27
use Symfony\Component\Console\Input\ArrayInput;
28
use Symfony\Component\Console\Input\InputArgument;
29
use Symfony\Component\Console\Input\InputInterface;
30
use Symfony\Component\Console\Input\InputOption;
31
use Symfony\Component\Console\Output\OutputInterface;
32
33
class SeedCommand extends Command
34
{
35
    const OPTION_CONFIG          = 'config';
36
    const OPTION_NO_CHOP         = 'no-chop';
37
    const OPTION_CHOP_ALL        = 'chop-all';
38
    const OPTION_GROUP           = 'group';
39
    const ARGUMENT_SCHEMA_TABLES = 'schemaTables';
40
41
    protected function configure()
42
    {
43
        $this->setName('seed');
44
        $this->setDescription('Seed all the data for a given group, schema or table');
45
46
        $this->addOption(
47
            static::OPTION_CONFIG,
48
            'c',
49
            InputOption::VALUE_OPTIONAL,
50
            'The configuration file to use',
51
            Config::DEFAULT_CONFIG_PATH
52
        );
53
54
        $this->addOption(
55
            static::OPTION_NO_CHOP,
56
            '',
57
            InputOption::VALUE_NONE,
58
            'Do not chop (truncate) tables before seeding them'
59
        );
60
        $this->addOption(
61
            static::OPTION_CHOP_ALL,
62
            '',
63
            InputOption::VALUE_NONE,
64
            'Truncate all of the tables in the database. '
65
            . 'Any tables in the excludes list in the configuration will be ignored.'
66
            . 'If the `--no-chop` option is set, this will have no effect.'
67
        );
68
69
        $this->addOption(
70
            static::OPTION_GROUP,
71
            'g',
72
            InputOption::VALUE_OPTIONAL,
73
            'group to seed'
74
        );
75
76
        $this->addArgument(
77
            static::ARGUMENT_SCHEMA_TABLES,
78
            InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
79
            'Collection of schema and tables to use, examples: schema1 schema2 | schema1:* schema2:table1,table2'
80
        );
81
    }
82
83
    /**
84
     * @param \Symfony\Component\Console\Input\InputInterface   $input
85
     * @param \Symfony\Component\Console\Output\OutputInterface $output
86
     *
87
     * @return int|null
88
     * @throws Exception
89
     */
90
    protected function execute(InputInterface $input, OutputInterface $output)
91
    {
92
        $schemas = $input->getArgument(static::ARGUMENT_SCHEMA_TABLES);
93
        $config = (new Config())->parse($input->getOption('config'));
94
        $group = $input->getOption('group') ?: $config->get(Config::CONFIG_DEFAULT_GROUP);
95
96
        if (!$input->getOption(static::OPTION_NO_CHOP)) {
97
            $chopCommand = new ChopCommand();
98
            $exitCode = $chopCommand->run(
99
                new ArrayInput([
100
                    static::ARGUMENT_SCHEMA_TABLES => $schemas,
101
                    '--' . static::OPTION_CONFIG   => $input->getOption(static::OPTION_CONFIG),
102
                    '--' . static::OPTION_GROUP    => $group,
103
                    '--' . ChopCommand::OPTION_ALL => $input->getOption(static::OPTION_CHOP_ALL),
104
                ]),
105
                $output
106
            );
107
            if ($exitCode !== 0) {
108
                throw new \RuntimeException('failed to chop down the tables');
109
            }
110
        }
111
112
        $fileSystem = new Local('/');
113
        $tablePopulator = new FileTablePopulator($fileSystem);
114
        $schemaParser = new SchemaParser($tablePopulator, $config, $group);
115
        $parsedSchemas = $schemaParser->extractSchemas($schemas);
116
117
        $numTables = array_sum(array_map(
118
            function (ParsedSchema $schema) {
119
                return count($schema->getTables());
120
            },
121
            $parsedSchemas
122
        ));
123
124
        $useGlobal = $numTables <= 10;
125
126
        $globalPool = new Pool();
127
        $globalPool->setMaxSimultaneous($config->get(Config::CONFIG_DEFAULT_SIMULTANEOUS_PROCESSES));
128
129
        foreach ($parsedSchemas as $schema) {
130
            $output->writeln(sprintf(
131
                'Seeding <info>%d</info> tables in <info>%s</info> schema in group <info>%s</info> from <info>%s</info>',
132
                count($schema->getTables()),
133
                $schema->getSchemaName(),
134
                $group,
135
                $schema->getPath()
136
            ));
137
138
            if ($useGlobal) {
139
                $pool = $globalPool;
140
            } else {
141
                $pool = new Pool(
142
                    [],
143
                    $config->get(Config::CONFIG_DEFAULT_SIMULTANEOUS_PROCESSES),
144
                    false,
145
                    ['seed', 'schema' => $schema->getSchemaName()]
146
                );
147
                $globalPool->add($pool);
148
            }
149
150
            $seeder = new Seeder($schema->getSchemaConfig(), $output, new TableSeederFactory($pool, $fileSystem));
151
            $seeder->seed($schema->getPath(), $schema->getTables());
152
        }
153
154
        $processTable = new Table($output, $globalPool);
155
        $processTable->setShowSummary(true);
156
157
        if (!$processTable->run(0.1)) {
158
            return 1;
159
        }
160
161
        return 0;
162
    }
163
}
164