1 | <?php |
||
44 | class IndexService |
||
45 | { |
||
46 | /** |
||
47 | * @var TypoScriptConfiguration |
||
48 | */ |
||
49 | protected $configuration; |
||
50 | |||
51 | /** |
||
52 | * @var Site |
||
53 | */ |
||
54 | protected $site; |
||
55 | |||
56 | /** |
||
57 | * @var IndexQueueWorkerTask |
||
58 | */ |
||
59 | protected $contextTask; |
||
60 | |||
61 | /** |
||
62 | * @var Queue |
||
63 | */ |
||
64 | protected $indexQueue; |
||
65 | |||
66 | /** |
||
67 | * @var Dispatcher |
||
68 | */ |
||
69 | protected $signalSlotDispatcher; |
||
70 | |||
71 | /** |
||
72 | * @var \ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager |
||
73 | */ |
||
74 | protected $logger = null; |
||
75 | |||
76 | /** |
||
77 | * IndexService constructor. |
||
78 | * @param Site $site |
||
79 | * @param Queue|null $queue |
||
80 | * @param Dispatcher|null $dispatcher |
||
81 | */ |
||
82 | 7 | public function __construct(Site $site, Queue $queue = null, Dispatcher $dispatcher = null) |
|
83 | { |
||
84 | 7 | $this->logger = GeneralUtility::makeInstance(SolrLogManager::class, __CLASS__); |
|
85 | 7 | $this->site = $site; |
|
86 | 7 | $this->indexQueue = is_null($queue) ? GeneralUtility::makeInstance(Queue::class) : $queue; |
|
87 | 7 | $this->signalSlotDispatcher = is_null($dispatcher) ? GeneralUtility::makeInstance(Dispatcher::class) : $dispatcher; |
|
88 | 7 | } |
|
89 | |||
90 | /** |
||
91 | * @param \ApacheSolrForTypo3\Solr\Task\IndexQueueWorkerTask $contextTask |
||
92 | */ |
||
93 | 1 | public function setContextTask($contextTask) |
|
94 | { |
||
95 | 1 | $this->contextTask = $contextTask; |
|
96 | 1 | } |
|
97 | |||
98 | /** |
||
99 | * @return \ApacheSolrForTypo3\Solr\Task\IndexQueueWorkerTask |
||
100 | */ |
||
101 | 6 | public function getContextTask() |
|
102 | { |
||
103 | 6 | return $this->contextTask; |
|
104 | } |
||
105 | |||
106 | /** |
||
107 | * Indexes items from the Index Queue. |
||
108 | * |
||
109 | * @param int $limit |
||
110 | * @return bool |
||
111 | */ |
||
112 | 6 | public function indexItems($limit) |
|
113 | { |
||
114 | 6 | $errors = 0; |
|
115 | 6 | $indexRunId = uniqid(); |
|
116 | 6 | $configurationToUse = $this->site->getSolrConfiguration(); |
|
117 | |||
118 | // get items to index |
||
119 | 6 | $itemsToIndex = $this->indexQueue->getItemsToIndex($this->site, $limit); |
|
120 | |||
121 | 6 | $this->emitSignal('beforeIndexItems', [$itemsToIndex, $this->getContextTask(), $indexRunId]); |
|
122 | |||
123 | 6 | foreach ($itemsToIndex as $itemToIndex) { |
|
124 | try { |
||
125 | // try indexing |
||
126 | 6 | $this->emitSignal('beforeIndexItem', [$itemToIndex, $this->getContextTask(), $indexRunId]); |
|
127 | 6 | $this->indexItem($itemToIndex, $configurationToUse); |
|
128 | 6 | $this->emitSignal('afterIndexItem', [$itemToIndex, $this->getContextTask(), $indexRunId]); |
|
129 | 6 | } catch (\Exception $e) { |
|
130 | $errors++; |
||
131 | $this->indexQueue->markItemAsFailed($itemToIndex, $e->getCode() . ': ' . $e->__toString()); |
||
132 | $this->generateIndexingErrorLog($itemToIndex, $e); |
||
133 | } |
||
134 | 6 | } |
|
135 | |||
136 | 6 | $this->emitSignal('afterIndexItems', [$itemsToIndex, $this->getContextTask(), $indexRunId]); |
|
137 | |||
138 | 6 | return ($errors === 0); |
|
139 | } |
||
140 | |||
141 | /** |
||
142 | * Generates a message in the error log when an error occured. |
||
143 | * |
||
144 | * @param Item $itemToIndex |
||
145 | * @param \Exception $e |
||
146 | */ |
||
147 | protected function generateIndexingErrorLog(Item $itemToIndex, \Exception $e) |
||
148 | { |
||
149 | $message = 'Failed indexing Index Queue item ' . $itemToIndex->getIndexQueueUid(); |
||
150 | $data = ['code' => $e->getCode(), 'message' => $e->getMessage(), 'trace' => $e->getTrace(), 'item' => (array)$itemToIndex]; |
||
151 | |||
152 | $this->logger->log( |
||
153 | SolrLogManager::ERROR, |
||
154 | $message, |
||
155 | $data |
||
156 | ); |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * Builds an emits a singal for the IndexService. |
||
161 | * |
||
162 | * @param string $name |
||
163 | * @param array $arguments |
||
164 | * @return mixed |
||
165 | */ |
||
166 | 6 | protected function emitSignal($name, $arguments) |
|
170 | |||
171 | /** |
||
172 | * Indexes an item from the Index Queue. |
||
173 | * |
||
174 | * @param Item $item An index queue item to index |
||
175 | * @param TypoScriptConfiguration $configuration |
||
176 | * @return bool TRUE if the item was successfully indexed, FALSE otherwise |
||
177 | */ |
||
178 | 5 | protected function indexItem(Item $item, TypoScriptConfiguration $configuration) |
|
179 | { |
||
180 | 5 | $indexer = $this->getIndexerByItem($item->getIndexingConfigurationName(), $configuration); |
|
181 | |||
182 | // Remember original http host value |
||
183 | 5 | $originalHttpHost = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : null; |
|
184 | |||
185 | 5 | $this->initializeHttpServerEnvironment($item); |
|
186 | 5 | $itemIndexed = $indexer->index($item); |
|
187 | |||
188 | // update IQ item so that the IQ can determine what's been indexed already |
||
189 | 5 | if ($itemIndexed) { |
|
190 | 5 | $item->updateIndexedTime(); |
|
191 | 5 | } |
|
192 | |||
193 | 5 | if (!is_null($originalHttpHost)) { |
|
194 | $_SERVER['HTTP_HOST'] = $originalHttpHost; |
||
195 | } else { |
||
196 | 5 | unset($_SERVER['HTTP_HOST']); |
|
197 | } |
||
198 | |||
199 | // needed since TYPO3 7.5 |
||
200 | 5 | GeneralUtility::flushInternalRuntimeCaches(); |
|
201 | |||
202 | 5 | return $itemIndexed; |
|
203 | } |
||
204 | |||
205 | /** |
||
206 | * A factory method to get an indexer depending on an item's configuration. |
||
207 | * |
||
208 | * By default all items are indexed using the default indexer |
||
209 | * (ApacheSolrForTypo3\Solr\IndexQueue\Indexer) coming with EXT:solr. Pages by default are |
||
210 | * configured to be indexed through a dedicated indexer |
||
211 | * (ApacheSolrForTypo3\Solr\IndexQueue\PageIndexer). In all other cases a dedicated indexer |
||
212 | * can be specified through TypoScript if needed. |
||
213 | * |
||
214 | * @param string $indexingConfigurationName Indexing configuration name. |
||
215 | * @param TypoScriptConfiguration $configuration |
||
216 | * @return Indexer |
||
217 | */ |
||
218 | 5 | protected function getIndexerByItem($indexingConfigurationName, TypoScriptConfiguration $configuration) |
|
233 | |||
234 | /** |
||
235 | * Gets the indexing progress. |
||
236 | * |
||
237 | * @return float Indexing progress as a two decimal precision float. f.e. 44.87 |
||
238 | */ |
||
239 | 2 | public function getProgress() |
|
243 | |||
244 | /** |
||
245 | * Initializes the $_SERVER['HTTP_HOST'] environment variable in CLI |
||
246 | * environments dependent on the Index Queue item's root page. |
||
247 | * |
||
248 | * When the Index Queue Worker task is executed by a cron job there is no |
||
249 | * HTTP_HOST since we are in a CLI environment. RealURL needs the host |
||
250 | * information to generate a proper URL though. Using the Index Queue item's |
||
251 | * root page information we can determine the correct host although being |
||
252 | * in a CLI environment. |
||
253 | * |
||
254 | * @param Item $item Index Queue item to use to determine the host. |
||
255 | * @param |
||
256 | */ |
||
257 | 5 | protected function initializeHttpServerEnvironment(Item $item) |
|
274 | } |
||
275 |