1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* WellCommerce Open-Source E-Commerce Platform |
4
|
|
|
* |
5
|
|
|
* This file is part of the WellCommerce package. |
6
|
|
|
* |
7
|
|
|
* (c) Adam Piotrowski <[email protected]> |
8
|
|
|
* |
9
|
|
|
* For the full copyright and license information, |
10
|
|
|
* please view the LICENSE file that was distributed with this source code. |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
namespace WellCommerce\Bundle\SearchBundle\Command; |
14
|
|
|
|
15
|
|
|
use Doctrine\Common\Collections\ArrayCollection; |
16
|
|
|
use Doctrine\Common\Collections\Collection; |
17
|
|
|
use Doctrine\Common\Collections\Criteria; |
18
|
|
|
use Doctrine\ORM\Tools\Pagination\Paginator; |
19
|
|
|
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; |
20
|
|
|
use Symfony\Component\Console\Helper\ProgressBar; |
21
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
22
|
|
|
use Symfony\Component\Console\Input\InputOption; |
23
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
24
|
|
|
use WellCommerce\Bundle\AppBundle\Entity\Locale; |
25
|
|
|
use WellCommerce\Bundle\CoreBundle\Doctrine\Repository\RepositoryInterface; |
26
|
|
|
use WellCommerce\Bundle\SearchBundle\Manager\SearchManagerInterface; |
27
|
|
|
use WellCommerce\Component\Search\Model\TypeInterface; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Class ReindexCommand |
31
|
|
|
* |
32
|
|
|
* @author Adam Piotrowski <[email protected]> |
33
|
|
|
*/ |
34
|
|
|
final class ReindexCommand extends ContainerAwareCommand |
35
|
|
|
{ |
36
|
|
|
/** |
37
|
|
|
* @var TypeInterface |
38
|
|
|
*/ |
39
|
|
|
private $type; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @var int |
43
|
|
|
*/ |
44
|
|
|
private $batchSize; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @var RepositoryInterface |
48
|
|
|
*/ |
49
|
|
|
private $repository; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* @var SearchManagerInterface |
53
|
|
|
*/ |
54
|
|
|
private $manager; |
55
|
|
|
|
56
|
|
|
protected function configure() |
57
|
|
|
{ |
58
|
|
|
$this->setDescription('Reindexes search types'); |
59
|
|
|
$this->setName('wellcommerce:search:reindex'); |
60
|
|
|
|
61
|
|
|
$this->addOption( |
62
|
|
|
'type', |
63
|
|
|
null, |
64
|
|
|
InputOption::VALUE_REQUIRED, |
65
|
|
|
'Index type', |
66
|
|
|
'product' |
67
|
|
|
); |
68
|
|
|
|
69
|
|
|
$this->addOption( |
70
|
|
|
'batch', |
71
|
|
|
null, |
72
|
|
|
InputOption::VALUE_REQUIRED, |
73
|
|
|
'Batch size', |
74
|
|
|
150 |
75
|
|
|
); |
76
|
|
|
|
77
|
|
|
$this->addOption( |
78
|
|
|
'repository', |
79
|
|
|
null, |
80
|
|
|
InputOption::VALUE_REQUIRED, |
81
|
|
|
'Repository service', |
82
|
|
|
'product.repository' |
83
|
|
|
); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
protected function initialize(InputInterface $input, OutputInterface $output) |
87
|
|
|
{ |
88
|
|
|
$this->manager = $this->getSearchManager(); |
89
|
|
|
$this->type = $this->manager->getType($input->getOption('type')); |
90
|
|
|
$this->batchSize = $input->getOption('batch'); |
91
|
|
|
$this->repository = $this->getRepository($input->getOption('repository')); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
95
|
|
|
{ |
96
|
|
|
$this->getContainer()->get('doctrine.helper')->disableFilter('locale'); |
97
|
|
|
|
98
|
|
|
$this->getLocales()->map(function (Locale $locale) use ($output) { |
99
|
|
|
$output->writeln(sprintf('<info>Reindexing locale:</info> %s', $locale->getCode())); |
100
|
|
|
$this->reindex($locale->getCode(), $output); |
101
|
|
|
}); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
private function reindex(string $locale, OutputInterface $output) |
105
|
|
|
{ |
106
|
|
|
$totalEntities = $this->getTotalCount(); |
107
|
|
|
$iterations = $this->getIterations($totalEntities, $this->batchSize); |
108
|
|
|
|
109
|
|
|
$output->writeln(sprintf('<comment>Total entities:</comment> %s', $totalEntities)); |
110
|
|
|
$output->writeln(sprintf('<comment>Batch size:</comment> %s', $this->batchSize)); |
111
|
|
|
$output->writeln(sprintf('<comment>Iterations:</comment> %s', count($iterations))); |
112
|
|
|
$output->writeln(sprintf('<comment>Locale:</comment> %s', $locale)); |
113
|
|
|
|
114
|
|
|
$output->writeln('<info>Flushing index</info>'); |
115
|
|
|
$this->manager->removeIndex($locale, $this->type->getName()); |
116
|
|
|
$this->manager->createIndex($locale, $this->type->getName()); |
117
|
|
|
|
118
|
|
|
$progress = new ProgressBar($output, count($iterations)); |
119
|
|
|
$progress->setFormat('verbose'); |
120
|
|
|
$progress->setRedrawFrequency($this->batchSize); |
121
|
|
|
$progress->start(); |
122
|
|
|
|
123
|
|
|
foreach ($iterations as $iteration) { |
124
|
|
|
$entities = $this->getEntities($iteration); |
125
|
|
|
$documents = new ArrayCollection(); |
126
|
|
|
foreach ($entities as $entity) { |
127
|
|
|
$document = $this->type->createDocument($entity, $locale); |
128
|
|
|
$documents->add($document); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
$this->manager->addDocuments($documents, $locale, $this->type->getName()); |
132
|
|
|
$progress->advance(); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
$progress->finish(); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
private function getEntities(int $iteration): array |
139
|
|
|
{ |
140
|
|
|
return $this->repository->findBy([], null, $this->batchSize, $iteration * $this->batchSize); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
private function getLocales(): Collection |
144
|
|
|
{ |
145
|
|
|
$criteria = new Criteria(); |
146
|
|
|
$criteria->andWhere($criteria->expr()->eq('enabled', true)); |
147
|
|
|
|
148
|
|
|
return $this->getContainer()->get('locale.repository')->matching($criteria); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
private function getRepository(string $serviceId): RepositoryInterface |
152
|
|
|
{ |
153
|
|
|
if (false === $this->getContainer()->has($serviceId)) { |
154
|
|
|
return $this->getContainer()->get($this->type->getName() . '.repository'); |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
return $this->getContainer()->get($serviceId); |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
private function getIterations(int $total, int $batchSize): array |
161
|
|
|
{ |
162
|
|
|
return range(0, ceil($total / $batchSize)); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
private function getSearchManager(): SearchManagerInterface |
166
|
|
|
{ |
167
|
|
|
return $this->getContainer()->get('search.manager'); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
private function getTotalCount(): int |
171
|
|
|
{ |
172
|
|
|
$queryBuilder = $this->repository->getQueryBuilder(); |
173
|
|
|
$query = $queryBuilder->getQuery(); |
174
|
|
|
$query->useQueryCache(true); |
175
|
|
|
$query->useResultCache(true); |
176
|
|
|
$paginator = new Paginator($query, true); |
177
|
|
|
$paginator->setUseOutputWalkers(false); |
178
|
|
|
|
179
|
|
|
return $paginator->count(); |
180
|
|
|
} |
181
|
|
|
} |
182
|
|
|
|