1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the FOSElasticaBundle package. |
5
|
|
|
* |
6
|
|
|
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace FOS\ElasticaBundle\Command; |
13
|
|
|
|
14
|
|
|
use FOS\ElasticaBundle\Event\IndexPopulateEvent; |
15
|
|
|
use FOS\ElasticaBundle\Event\TypePopulateEvent; |
16
|
|
|
use FOS\ElasticaBundle\Index\IndexManager; |
17
|
|
|
use FOS\ElasticaBundle\Index\Resetter; |
18
|
|
|
use FOS\ElasticaBundle\Persister\PagerPersisterInterface; |
19
|
|
|
use FOS\ElasticaBundle\Provider\PagerProviderRegistry; |
20
|
|
|
use FOS\ElasticaBundle\Provider\ProviderRegistry; |
21
|
|
|
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; |
22
|
|
|
use Symfony\Component\Console\Helper\ProgressBar; |
23
|
|
|
use Symfony\Component\Console\Helper\QuestionHelper; |
24
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
25
|
|
|
use Symfony\Component\Console\Input\InputOption; |
26
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
27
|
|
|
use Symfony\Component\Console\Question\Question; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Populate the search index. |
31
|
|
|
*/ |
32
|
|
|
class PopulateCommand extends ContainerAwareCommand |
33
|
|
|
{ |
34
|
|
|
/** |
35
|
|
|
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface |
36
|
|
|
*/ |
37
|
|
|
private $dispatcher; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @var IndexManager |
41
|
|
|
*/ |
42
|
|
|
private $indexManager; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @var ProgressClosureBuilder |
46
|
|
|
*/ |
47
|
|
|
private $progressClosureBuilder; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* @var ProviderRegistry |
51
|
|
|
*/ |
52
|
|
|
private $providerRegistry; |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* @var PagerProviderRegistry |
56
|
|
|
*/ |
57
|
|
|
private $pagerProviderRegistry; |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @var PagerPersisterInterface |
61
|
|
|
*/ |
62
|
|
|
private $pagerPersister; |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* @var Resetter |
66
|
|
|
*/ |
67
|
|
|
private $resetter; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* {@inheritdoc} |
71
|
|
|
*/ |
72
|
|
|
protected function configure() |
73
|
|
|
{ |
74
|
|
|
$this |
75
|
|
|
->setName('fos:elastica:populate') |
76
|
|
|
->addOption('index', null, InputOption::VALUE_OPTIONAL, 'The index to repopulate') |
77
|
|
|
->addOption('type', null, InputOption::VALUE_OPTIONAL, 'The type to repopulate') |
78
|
|
|
->addOption('no-reset', null, InputOption::VALUE_NONE, 'Do not reset index before populating') |
79
|
|
|
->addOption('no-delete', null, InputOption::VALUE_NONE, 'Do not delete index after populate') |
80
|
|
|
->addOption('offset', null, InputOption::VALUE_REQUIRED, 'Start indexing at offset', 0) |
81
|
|
|
->addOption('sleep', null, InputOption::VALUE_REQUIRED, 'Sleep time between persisting iterations (microseconds)', 0) |
82
|
|
|
->addOption('batch-size', null, InputOption::VALUE_REQUIRED, 'Index packet size (overrides provider config option)') |
83
|
|
|
->addOption('ignore-errors', null, InputOption::VALUE_NONE, 'Do not stop on errors') |
84
|
|
|
->addOption('no-overwrite-format', null, InputOption::VALUE_NONE, 'Prevent this command from overwriting ProgressBar\'s formats') |
85
|
|
|
->setDescription('Populates search indexes from providers') |
86
|
|
|
; |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* {@inheritdoc} |
91
|
|
|
*/ |
92
|
|
|
protected function initialize(InputInterface $input, OutputInterface $output) |
93
|
|
|
{ |
94
|
|
|
$this->dispatcher = $this->getContainer()->get('event_dispatcher'); |
95
|
|
|
$this->indexManager = $this->getContainer()->get('fos_elastica.index_manager'); |
96
|
|
|
$this->providerRegistry = $this->getContainer()->get('fos_elastica.provider_registry'); |
97
|
|
|
$this->pagerProviderRegistry = $this->getContainer()->get('fos_elastica.pager_provider_registry'); |
98
|
|
|
$this->pagerPersister = $this->getContainer()->get('fos_elastica.pager_persister'); |
99
|
|
|
$this->resetter = $this->getContainer()->get('fos_elastica.resetter'); |
100
|
|
|
$this->progressClosureBuilder = new ProgressClosureBuilder(); |
101
|
|
|
|
102
|
|
|
if (!$input->getOption('no-overwrite-format') && class_exists('Symfony\\Component\\Console\\Helper\\ProgressBar')) { |
103
|
|
|
ProgressBar::setFormatDefinition('normal', " %current%/%max% [%bar%] %percent:3s%%\n%message%"); |
104
|
|
|
ProgressBar::setFormatDefinition('verbose', " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%\n%message%"); |
105
|
|
|
ProgressBar::setFormatDefinition('very_verbose', " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%\n%message%"); |
106
|
|
|
ProgressBar::setFormatDefinition('debug', " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%\n%message%"); |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* {@inheritdoc} |
112
|
|
|
*/ |
113
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
114
|
|
|
{ |
115
|
|
|
$index = $input->getOption('index'); |
116
|
|
|
$type = $input->getOption('type'); |
117
|
|
|
$reset = !$input->getOption('no-reset'); |
118
|
|
|
$delete = !$input->getOption('no-delete'); |
119
|
|
|
|
120
|
|
|
$options = [ |
121
|
|
|
'delete' => $delete, |
122
|
|
|
'reset' => $reset, |
123
|
|
|
'ignore_errors' => $input->getOption('ignore-errors'), |
124
|
|
|
'offset' => $input->getOption('offset'), |
125
|
|
|
'sleep' => $input->getOption('sleep'), |
126
|
|
|
]; |
127
|
|
|
|
128
|
|
|
if ($input->getOption('batch-size')) { |
129
|
|
|
$options['batch_size'] = (int) $input->getOption('batch-size'); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
if ($input->isInteractive() && $reset && $input->getOption('offset')) { |
133
|
|
|
/** @var QuestionHelper $dialog */ |
134
|
|
|
$dialog = $this->getHelperSet()->get('question'); |
135
|
|
|
if (!$dialog->ask($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>'))) { |
136
|
|
|
return; |
137
|
|
|
} |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
if (null === $index && null !== $type) { |
141
|
|
|
throw new \InvalidArgumentException('Cannot specify type option without an index.'); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
if (null !== $index) { |
145
|
|
|
if (null !== $type) { |
146
|
|
|
$this->populateIndexType($output, $index, $type, $reset, $options); |
147
|
|
|
} else { |
148
|
|
|
$this->populateIndex($output, $index, $reset, $options); |
149
|
|
|
} |
150
|
|
|
} else { |
151
|
|
|
$indexes = array_keys($this->indexManager->getAllIndexes()); |
152
|
|
|
|
153
|
|
|
foreach ($indexes as $index) { |
154
|
|
|
$this->populateIndex($output, $index, $reset, $options); |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* Recreates an index, populates its types, and refreshes the index. |
161
|
|
|
* |
162
|
|
|
* @param OutputInterface $output |
163
|
|
|
* @param string $index |
164
|
|
|
* @param bool $reset |
165
|
|
|
* @param array $options |
166
|
|
|
*/ |
167
|
|
|
private function populateIndex(OutputInterface $output, $index, $reset, $options) |
168
|
|
|
{ |
169
|
|
|
$event = new IndexPopulateEvent($index, $reset, $options); |
170
|
|
|
$this->dispatcher->dispatch(IndexPopulateEvent::PRE_INDEX_POPULATE, $event); |
171
|
|
|
|
172
|
|
|
if ($event->isReset()) { |
173
|
|
|
$output->writeln(sprintf('<info>Resetting</info> <comment>%s</comment>', $index)); |
174
|
|
|
$this->resetter->resetIndex($index, true); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
$types = array_keys($this->providerRegistry->getIndexProviders($index)); |
178
|
|
|
foreach ($types as $type) { |
179
|
|
|
$this->populateIndexType($output, $index, $type, false, $event->getOptions()); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
$this->dispatcher->dispatch(IndexPopulateEvent::POST_INDEX_POPULATE, $event); |
183
|
|
|
|
184
|
|
|
$this->refreshIndex($output, $index, $reset); |
|
|
|
|
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* Deletes/remaps an index type, populates it, and refreshes the index. |
189
|
|
|
* |
190
|
|
|
* @param OutputInterface $output |
191
|
|
|
* @param string $index |
192
|
|
|
* @param string $type |
193
|
|
|
* @param bool $reset |
194
|
|
|
* @param array $options |
195
|
|
|
*/ |
196
|
|
|
private function populateIndexType(OutputInterface $output, $index, $type, $reset, $options) |
197
|
|
|
{ |
198
|
|
|
$event = new TypePopulateEvent($index, $type, $reset, $options); |
199
|
|
|
$this->dispatcher->dispatch(TypePopulateEvent::PRE_TYPE_POPULATE, $event); |
200
|
|
|
|
201
|
|
|
if ($event->isReset()) { |
202
|
|
|
$output->writeln(sprintf('<info>Resetting</info> <comment>%s/%s</comment>', $index, $type)); |
203
|
|
|
$this->resetter->resetIndexType($index, $type); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
$offset = $options['offset']; |
207
|
|
|
$loggerClosure = $this->progressClosureBuilder->build($output, 'Populating', $index, $type, $offset); |
208
|
|
|
|
209
|
|
|
if ($this->getContainer()->getParameter('fos_elastica.use_v5_api') || getenv('FOS_ELASTICA_USE_V5_API')) { |
210
|
|
|
$provider = $this->pagerProviderRegistry->getProvider($index, $type); |
211
|
|
|
|
212
|
|
|
$pager = $provider->provide($options); |
213
|
|
|
|
214
|
|
|
$options['indexName'] = $index; |
215
|
|
|
$options['typeName'] = $type; |
216
|
|
|
$options['batch_size'] = 100; |
217
|
|
|
$options['skip_indexable_check'] = false; |
218
|
|
|
|
219
|
|
|
$this->pagerPersister->insert($pager, $options); |
220
|
|
|
} else { |
221
|
|
|
$provider = $this->providerRegistry->getProvider($index, $type); |
222
|
|
|
$provider->populate($loggerClosure, $options); |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
$this->dispatcher->dispatch(TypePopulateEvent::POST_TYPE_POPULATE, $event); |
226
|
|
|
|
227
|
|
|
$this->refreshIndex($output, $index); |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
/** |
231
|
|
|
* Refreshes an index. |
232
|
|
|
* |
233
|
|
|
* @param OutputInterface $output |
234
|
|
|
* @param string $index |
235
|
|
|
*/ |
236
|
|
|
private function refreshIndex(OutputInterface $output, $index) |
237
|
|
|
{ |
238
|
|
|
$output->writeln(sprintf('<info>Refreshing</info> <comment>%s</comment>', $index)); |
239
|
|
|
$this->indexManager->getIndex($index)->refresh(); |
240
|
|
|
} |
241
|
|
|
} |
242
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.