Passed
Push — master ( 8b92f8...a05608 )
by Bartosz
33s
created

AsyncReindexRunner::formatIndexersToBeReindex()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * File: AsyncReindexRunner.php
7
 *
8
 * @author Bartosz Kubicki [email protected]>
9
 * @author Paweł Papke <[email protected]>
10
 * @copyright Copyright (C) 2018 Lizard Media (http://lizardmedia.pl)
11
 */
12
13
namespace LizardMedia\AdminIndexer\Model\ReindexRunner;
14
15
use LizardMedia\AdminIndexer\Api\Adapter\ReactPHP\ChildProcess\ProcessFactoryInterface;
16
use LizardMedia\AdminIndexer\Api\Adapter\ReactPHP\EventLoop\LoopFactoryInterface;
17
use LizardMedia\AdminIndexer\Api\ReindexRunnerInterface;
18
use LizardMedia\AdminIndexer\Api\ReindexRunner\MessageBagInterface;
19
use LizardMedia\AdminIndexer\Exception\ReindexFailureAggregateException;
20
use Magento\Framework\Filesystem\DirectoryList;
21
use Magento\Framework\Indexer\IndexerRegistry;
22
use React\EventLoop\LoopInterface;
23
use React\ChildProcess\Process;
24
25
/**
26
 * Class AsyncReindexRunner
27
 * @package LizardMedia\AdminIndexer\Model\ReindexRunner
28
 */
29
class AsyncReindexRunner implements ReindexRunnerInterface
30
{
31
    /**
32
     * @var string
33
     */
34
    private const INDEXER_REINDEX_COMMAND = 'bin/magento indexer:reindex';
35
36
    /**
37
     * @var ProcessFactoryInterface
38
     */
39
    private $childProcessFactory;
40
41
    /**
42
     * @var LoopFactoryInterface
43
     */
44
    private $loopFactory;
45
46
    /**
47
     * @var MessageBagInterface
48
     */
49
    private $messageBag;
50
51
    /**
52
     * @var DirectoryList
53
     */
54
    private $directoryList;
55
56
    /**
57
     * @var IndexerRegistry
58
     */
59
    private $indexerRegistry;
60
61
    /**
62
     * AsyncReindexRunner constructor.
63
     * @param ProcessFactoryInterface $childProcessFactory
64
     * @param LoopFactoryInterface $loopFactory
65
     * @param MessageBagInterface $messageBag
66
     * @param DirectoryList $directoryList
67
     * @param IndexerRegistry $indexerRegistry
68
     */
69
    public function __construct(
70
        ProcessFactoryInterface $childProcessFactory,
71
        LoopFactoryInterface $loopFactory,
72
        MessageBagInterface $messageBag,
73
        DirectoryList $directoryList,
74
        IndexerRegistry $indexerRegistry
75
    ) {
76
        $this->childProcessFactory = $childProcessFactory;
77
        $this->loopFactory = $loopFactory;
78
        $this->messageBag = $messageBag;
79
        $this->directoryList = $directoryList;
80
        $this->indexerRegistry = $indexerRegistry;
81
    }
82
83
    /**
84
     * {@inheritDoc}
85
     */
86
    public function run(string ...$indexerIds): void
87
    {
88
        $this->informAboutIndexing($indexerIds);
89
        $indexerIds = $this->formatIndexersToBeReindex(...$indexerIds);
90
        $loop = $this->instantiateLoop();
91
92
        try {
93
            $command = $this->buildCommand($indexerIds);
94
            $process = $this->instantiateNewProcess($command);
95
            $process->start($loop);
96
            $loop->run();
97
        } catch (\Exception $exception) {
98
            $this->handleException($exception);
99
        }
100
    }
101
102
    /**
103
     * @param string[] ...$indexerIds
104
     * @return string
105
     */
106
    private function formatIndexersToBeReindex(string ...$indexerIds): string
107
    {
108
        return implode(' ', $indexerIds);
109
    }
110
111
    /**
112
     * @param array $indexerIds
113
     * @return void
114
     */
115
    private function informAboutIndexing(array $indexerIds): void
116
    {
117
        foreach ($indexerIds as $indexerId) {
118
            $this->messageBag->addMessage(__('Indexing of indexer %1 has been executed', $indexerId)->render());
119
        }
120
    }
121
122
    /**
123
     * @return LoopInterface
124
     */
125
    private function instantiateLoop(): LoopInterface
126
    {
127
        return $this->loopFactory->create();
128
    }
129
130
    /**
131
     * @param string $indexerIds
132
     * @return string
133
     */
134
    private function buildCommand(string $indexerIds): string
135
    {
136
        return sprintf(
137
            'php %s/%s %s > /dev/null 2>&1 &',
138
            $this->getRootDir(),
139
            self::INDEXER_REINDEX_COMMAND,
140
            $indexerIds
141
        );
142
    }
143
144
    /**
145
     * @return string
146
     */
147
    private function getRootDir(): string
148
    {
149
        return $this->directoryList->getRoot();
150
    }
151
152
    /**
153
     * @param string $command
154
     * @return Process
155
     */
156
    private function instantiateNewProcess(string $command): Process
157
    {
158
        return $this->childProcessFactory->create($command);
159
    }
160
161
162
    /**
163
     * @param \Exception $exception
164
     * @return void
165
     * @throws ReindexFailureAggregateException
166
     */
167
    private function handleException(\Exception $exception): void
168
    {
169
        throw new ReindexFailureAggregateException(
170
            __($exception->getMessage()),
171
            $exception,
172
            $exception->getCode()
173
        );
174
    }
175
}
176