Completed
Pull Request — master (#1193)
by
unknown
27:18 queued 21:31
created

PopulateCommand::initialize()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 15
c 0
b 0
f 0
ccs 0
cts 14
cp 0
rs 9.4285
cc 3
eloc 11
nc 2
nop 2
crap 12
1
<?php
2
3
namespace FOS\ElasticaBundle\Command;
4
5
use FOS\ElasticaBundle\Event\IndexPopulateEvent;
6
use FOS\ElasticaBundle\Event\TypePopulateEvent;
7
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
8
use Symfony\Component\Console\Helper\QuestionHelper;
9
use Symfony\Component\Console\Input\InputOption;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Output\OutputInterface;
12
use FOS\ElasticaBundle\Index\IndexManager;
13
use FOS\ElasticaBundle\Provider\ProviderRegistry;
14
use FOS\ElasticaBundle\Index\Resetter;
15
use Symfony\Component\Console\Helper\ProgressBar;
16
use Symfony\Component\Console\Question\Question;
17
18
/**
19
 * Populate the search index.
20
 */
21
class PopulateCommand extends ContainerAwareCommand
22
{
23
    /**
24
     * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
25
     */
26
    private $dispatcher;
27
28
    /**
29
     * @var IndexManager
30
     */
31
    private $indexManager;
32
33
    /**
34
     * @var ProgressClosureBuilder
35
     */
36
    private $progressClosureBuilder;
37
38
    /**
39
     * @var ProviderRegistry
40
     */
41
    private $providerRegistry;
42
43
    /**
44
     * @var Resetter
45
     */
46
    private $resetter;
47
48
    /**
49
     * @see Symfony\Component\Console\Command\Command::configure()
50
     */
51
    protected function configure()
52
    {
53
        $this
54
            ->setName('fos:elastica:populate')
55
            ->addOption('index', null, InputOption::VALUE_OPTIONAL, 'The index to repopulate')
56
            ->addOption('type', null, InputOption::VALUE_OPTIONAL, 'The type to repopulate')
57
            ->addOption('no-reset', null, InputOption::VALUE_NONE, 'Do not reset index before populating')
58
            ->addOption('offset', null, InputOption::VALUE_REQUIRED, 'Start indexing at offset', 0)
59
            ->addOption('sleep', null, InputOption::VALUE_REQUIRED, 'Sleep time between persisting iterations (microseconds)', 0)
60
            ->addOption('batch-size', null, InputOption::VALUE_REQUIRED, 'Index packet size (overrides provider config option)')
61
            ->addOption('ignore-errors', null, InputOption::VALUE_NONE, 'Do not stop on errors')
62
            ->addOption('no-overwrite-format', null, InputOption::VALUE_NONE, 'Prevent this command from overwriting ProgressBar\'s formats')
63
            ->setDescription('Populates search indexes from providers')
64
        ;
65
    }
66
67
    /**
68
     * {@inheritDoc}
69
     */
70
    protected function initialize(InputInterface $input, OutputInterface $output)
71
    {
72
        $this->dispatcher = $this->getContainer()->get('event_dispatcher');
73
        $this->indexManager = $this->getContainer()->get('fos_elastica.index_manager');
74
        $this->providerRegistry = $this->getContainer()->get('fos_elastica.provider_registry');
75
        $this->resetter = $this->getContainer()->get('fos_elastica.resetter');
76
        $this->progressClosureBuilder = new ProgressClosureBuilder();
77
78
        if (!$input->getOption('no-overwrite-format') && class_exists('Symfony\\Component\\Console\\Helper\\ProgressBar')) {
79
            ProgressBar::setFormatDefinition('normal', " %current%/%max% [%bar%] %percent:3s%%\n%message%");
80
            ProgressBar::setFormatDefinition('verbose', " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%\n%message%");
81
            ProgressBar::setFormatDefinition('very_verbose', " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%\n%message%");
82
            ProgressBar::setFormatDefinition('debug', " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%\n%message%");
83
        }
84
    }
85
86
    /**
87
     * {@inheritDoc}
88
     */
89
    protected function execute(InputInterface $input, OutputInterface $output)
90
    {
91
        $index = $input->getOption('index');
92
        $type = $input->getOption('type');
93
        $reset = !$input->getOption('no-reset');
94
        $options = array(
95
            'ignore_errors' => $input->getOption('ignore-errors'),
96
            'offset' => $input->getOption('offset'),
97
            'sleep' => $input->getOption('sleep')
98
        );
99
        if ($input->getOption('batch-size')) {
100
            $options['batch_size'] = (int) $input->getOption('batch-size');
101
        }
102
103
        if ($input->isInteractive() && $reset && $input->getOption('offset')) {
104
            /** @var QuestionHelper $dialog */
105
            $dialog = $this->getHelperSet()->get('question');
106
            if (!$dialog->askConfirmation($input, $output, new Question('<question>You chose to reset the index and start indexing with an offset. Do you really want to do that?</question>'))) {
0 ignored issues
show
Bug introduced by
The method askConfirmation() does not seem to exist on object<Symfony\Component...\Helper\QuestionHelper>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
107
                return;
108
            }
109
        }
110
111
        if (null === $index && null !== $type) {
112
            throw new \InvalidArgumentException('Cannot specify type option without an index.');
113
        }
114
115
        if (null !== $index) {
116
            if (null !== $type) {
117
                $this->populateIndexType($output, $index, $type, $reset, $options);
118
            } else {
119
                $this->populateIndex($output, $index, $reset, $options);
120
            }
121
        } else {
122
            $indexes = array_keys($this->indexManager->getAllIndexes());
123
124
            foreach ($indexes as $index) {
125
                $this->populateIndex($output, $index, $reset, $options);
126
            }
127
        }
128
    }
129
130
    /**
131
     * Recreates an index, populates its types, and refreshes the index.
132
     *
133
     * @param OutputInterface $output
134
     * @param string          $index
135
     * @param boolean         $reset
136
     * @param array           $options
137
     */
138
    private function populateIndex(OutputInterface $output, $index, $reset, $options)
139
    {
140
        $event = new IndexPopulateEvent($index, $reset, $options);
141
        $this->dispatcher->dispatch(IndexPopulateEvent::PRE_INDEX_POPULATE, $event);
142
143
        if ($event->isReset()) {
144
            $output->writeln(sprintf('<info>Resetting</info> <comment>%s</comment>', $index));
145
            $this->resetter->resetIndex($index, true);
146
        }
147
148
        $types = array_keys($this->providerRegistry->getIndexProviders($index));
149
        foreach ($types as $type) {
150
            $this->populateIndexType($output, $index, $type, false, $event->getOptions());
151
        }
152
153
        $this->dispatcher->dispatch(IndexPopulateEvent::POST_INDEX_POPULATE, $event);
154
155
        $this->refreshIndex($output, $index, $reset);
156
    }
157
158
    /**
159
     * Deletes/remaps an index type, populates it, and refreshes the index.
160
     *
161
     * @param OutputInterface $output
162
     * @param string          $index
163
     * @param string          $type
164
     * @param boolean         $reset
165
     * @param array           $options
166
     */
167
    private function populateIndexType(OutputInterface $output, $index, $type, $reset, $options)
168
    {
169
        $event = new TypePopulateEvent($index, $type, $reset, $options);
170
        $this->dispatcher->dispatch(TypePopulateEvent::PRE_TYPE_POPULATE, $event);
171
172
        if ($event->isReset()) {
173
            $output->writeln(sprintf('<info>Resetting</info> <comment>%s/%s</comment>', $index, $type));
174
            $this->resetter->resetIndexType($index, $type);
175
        }
176
177
        $offset = $options['offset'];
178
        $provider = $this->providerRegistry->getProvider($index, $type);
179
        $loggerClosure = $this->progressClosureBuilder->build($output, 'Populating', $index, $type, $offset);
180
        $provider->populate($loggerClosure, $event->getOptions());
181
182
        $this->dispatcher->dispatch(TypePopulateEvent::POST_TYPE_POPULATE, $event);
183
184
        $this->refreshIndex($output, $index, false);
185
    }
186
187
    /**
188
     * Refreshes an index.
189
     *
190
     * @param OutputInterface $output
191
     * @param string          $index
192
     * @param bool            $postPopulate
193
     */
194
    private function refreshIndex(OutputInterface $output, $index, $postPopulate = true)
195
    {
196
        if ($postPopulate) {
197
            $this->resetter->postPopulate($index);
198
        }
199
200
        $output->writeln(sprintf('<info>Refreshing</info> <comment>%s</comment>', $index));
201
        $this->indexManager->getIndex($index)->refresh();
202
    }
203
}
204