Failed Conditions
Push — task/3376-TYPO3_12_compatibili... ( 6ec289...1d802a )
by Rafael
40:27
created

PageIndexer::__invoke()   C

Complexity

Conditions 11
Paths 168

Size

Total Lines 70
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 45
c 0
b 0
f 0
dl 0
loc 70
rs 6.75
cc 11
nc 168
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper;
17
18
use ApacheSolrForTypo3\Solr\Access\Rootline;
19
use ApacheSolrForTypo3\Solr\ConnectionManager;
20
use ApacheSolrForTypo3\Solr\IndexQueue\Item;
21
use ApacheSolrForTypo3\Solr\IndexQueue\Queue;
22
use ApacheSolrForTypo3\Solr\NoSolrConnectionFoundException;
23
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
24
use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection;
25
use ApacheSolrForTypo3\Solr\Typo3PageIndexer;
26
use ApacheSolrForTypo3\Solr\Util;
27
use Doctrine\DBAL\Driver\Exception as DBALDriverException;
28
use Doctrine\DBAL\Exception as DBALException;
29
use Throwable;
30
use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException;
31
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
32
use TYPO3\CMS\Core\Utility\GeneralUtility;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Core\Utility\GeneralUtility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
34
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
35
use TYPO3\CMS\Frontend\Event\AfterCacheableContentIsGeneratedEvent;
36
use UnexpectedValueException;
37
38
/**
39
 * Index Queue Page Indexer frontend helper to ask the frontend page indexer to
40
 * index the page.
41
 *
42
 * @author Ingo Renner <[email protected]>
43
 */
44
class PageIndexer extends AbstractFrontendHelper
45
{
46
    /**
47
     * This frontend helper's executed action.
48
     *
49
     * @var string
50
     */
51
    protected string $action = 'indexPage';
52
53
    /**
54
     * the page currently being indexed.
55
     *
56
     * @var TypoScriptFrontendController
57
     */
58
    protected TypoScriptFrontendController $page;
59
60
    /**
61
     * Response data
62
     *
63
     * @var array
64
     */
65
    protected array $responseData = [];
66
67
    /**
68
     * Activates a frontend helper by registering for hooks and other
69
     * resources required by the frontend helper to work.
70
     *
71
     * @noinspection PhpUnused
72
     */
73
    public function activate(): void
74
    {
75
        $this->isActivated = true;
76
77
        // indexes fields defined in plugin.tx_solr.index.queue.pages.fields
78
        $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument'][PageFieldMappingIndexer::class] = PageFieldMappingIndexer::class;
79
80
        $this->registerAuthorizationService();
81
    }
82
83
    /**
84
     * Returns the status of whether a page was indexed.
85
     *
86
     * @return array Page indexed status.
87
     * @noinspection PhpUnused
88
     */
89
    public function getData(): array
90
    {
91
        return $this->responseData;
92
    }
93
94
    /**
95
     * Gets the access rootline as defined by the request.
96
     *
97
     * @return Rootline The access rootline to use for indexing.
98
     */
99
    protected function getAccessRootline(): Rootline
100
    {
101
        $stringAccessRootline = '';
102
103
        if ($this->request->getParameter('accessRootline')) {
0 ignored issues
show
Bug introduced by
The method getParameter() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

103
        if ($this->request->/** @scrutinizer ignore-call */ getParameter('accessRootline')) {

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...
104
            $stringAccessRootline = $this->request->getParameter('accessRootline');
105
        }
106
107
        return GeneralUtility::makeInstance(Rootline::class, /** @scrutinizer ignore-type */ $stringAccessRootline);
108
    }
109
110
    /**
111
     * Registers an authentication service to authorize / grant the indexer to
112
     * access protected pages.
113
     */
114
    protected function registerAuthorizationService()
115
    {
116
        $overrulingPriority = $this->getHighestAuthenticationServicePriority() + 1;
117
118
        ExtensionManagementUtility::addService(
119
            'solr', // extension key
120
            'auth', // service type
121
            AuthorizationService::class,
122
            // service key
123
            [// service meta data
124
                'title' => 'Solr Indexer Authorization',
125
                'description' => 'Authorizes the Solr Index Queue indexer to access protected pages.',
126
127
                'subtype' => 'getUserFE,authUserFE,getGroupsFE',
128
129
                'available' => true,
130
                'priority' => $overrulingPriority,
131
                'quality' => 100,
132
133
                'os' => '',
134
                'exec' => '',
135
136
                'classFile' => ExtensionManagementUtility::extPath('solr') . 'Classes/IndexQueue/FrontendHelper/AuthorizationService.php',
137
                'className' => AuthorizationService::class,
138
            ]
139
        );
140
    }
141
142
    /**
143
     * Determines the highest priority of all registered authentication
144
     * services.
145
     *
146
     * @return int Highest priority of all registered authentication service
147
     */
148
    protected function getHighestAuthenticationServicePriority(): int
149
    {
150
        $highestPriority = 0;
151
152
        if (is_array($GLOBALS['T3_SERVICES']['auth'] ?? null)) {
153
            foreach ($GLOBALS['T3_SERVICES']['auth'] as $service) {
154
                if ($service['priority'] > $highestPriority) {
155
                    $highestPriority = $service['priority'];
156
                }
157
            }
158
        }
159
160
        return $highestPriority;
161
    }
162
163
    //
164
    // Indexing
165
    //
166
167
    /**
168
     * Generates the current page's URL.
169
     *
170
     * Uses the provided GET parameters, page id and language id.
171
     *
172
     * @return string URL of the current page.
173
     */
174
    protected function generatePageUrl(): string
175
    {
176
        if ($this->request->getParameter('overridePageUrl')) {
177
            return $this->request->getParameter('overridePageUrl');
178
        }
179
180
        /** @var $contentObject ContentObjectRenderer */
181
        $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
182
183
        $typolinkConfiguration = [
184
            'parameter' => $this->page->id,
185
            'linkAccessRestrictedPages' => '1',
186
        ];
187
188
        $language = GeneralUtility::_GET('L');
189
        if (!empty($language)) {
190
            $typolinkConfiguration['additionalParams'] = '&L=' . $language;
191
        }
192
193
        $url = $contentObject->typoLink_URL($typolinkConfiguration);
194
195
        // clean up
196
        if ($url == '') {
197
            $url = '/';
198
        }
199
200
        return $url;
201
    }
202
203
    /**
204
     * Handles the indexing of the page content during AfterCacheableContentIsGeneratedEvent of a generated page.
205
     *
206
     * @param AfterCacheableContentIsGeneratedEvent $event
207
     */
208
    public function __invoke(AfterCacheableContentIsGeneratedEvent $event): void
209
    {
210
        if (!$this->isActivated) {
211
            return;
212
        }
213
214
        $this->logger = GeneralUtility::makeInstance(SolrLogManager::class, self::class);
215
216
        $this->page = $event->getController();
217
        $configuration = Util::getSolrConfiguration();
218
219
        $logPageIndexed = $configuration->getLoggingIndexingPageIndexed();
220
        if (!$this->page->config['config']['index_enable'] ?? false) {
221
            if ($logPageIndexed) {
222
                $this->logger->log(
0 ignored issues
show
Bug introduced by
The method log() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

222
                $this->logger->/** @scrutinizer ignore-call */ 
223
                               log(

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...
223
                    SolrLogManager::ERROR,
224
                    'Indexing is disabled. Set config.index_enable = 1 .'
225
                );
226
            }
227
            return;
228
        }
229
230
        try {
231
            $indexQueueItem = $this->getIndexQueueItem();
232
            if (is_null($indexQueueItem)) {
233
                throw new UnexpectedValueException('Can not get index queue item', 1482162337);
234
            }
235
236
            $solrConnection = $this->getSolrConnection($indexQueueItem);
237
238
            /** @var $indexer Typo3PageIndexer */
239
            $indexer = GeneralUtility::makeInstance(Typo3PageIndexer::class, /** @scrutinizer ignore-type */ $this->page);
240
            $indexer->setSolrConnection($solrConnection);
241
            $indexer->setPageAccessRootline($this->getAccessRootline());
242
            $indexer->setPageUrl($this->generatePageUrl());
243
            $indexer->setMountPointParameter($GLOBALS['TSFE']->MP);
244
            $indexer->setIndexQueueItem($indexQueueItem);
245
246
            $this->responseData['pageIndexed'] = (int)$indexer->indexPage();
247
            $this->responseData['originalPageDocument'] = (array)$indexer->getPageSolrDocument();
248
            $this->responseData['solrConnection'] = [
249
                'rootPage' => $indexQueueItem->getRootPageUid(),
250
                'sys_language_uid' => Util::getLanguageUid(),
251
                'solr' => (string)$solrConnection->getNode('write'),
252
            ];
253
254
            $documentsSentToSolr = $indexer->getDocumentsSentToSolr();
255
            foreach ($documentsSentToSolr as $document) {
256
                $this->responseData['documentsSentToSolr'][] = (array)$document;
257
            }
258
        } catch (Throwable $e) {
259
            if ($configuration->getLoggingExceptions()) {
260
                $this->logger->log(
261
                    SolrLogManager::ERROR,
262
                    'Exception while trying to index page ' . $this->page->id,
263
                    [
264
                        $e->__toString(),
265
                    ]
266
                );
267
            }
268
        }
269
270
        if ($logPageIndexed) {
271
            $success = $this->responseData['pageIndexed'] ? 'Success' : 'Failed';
272
            $severity = $this->responseData['pageIndexed'] ? SolrLogManager::NOTICE : SolrLogManager::ERROR;
273
274
            $this->logger->log(
275
                $severity,
276
                'Page indexed: ' . $success,
277
                $this->responseData
278
            );
279
        }
280
    }
281
282
    /**
283
     * Gets the solr connection to use for indexing the page based on the
284
     * Index Queue item's properties.
285
     *
286
     * @param Item $indexQueueItem
287
     * @return SolrConnection Solr server connection
288
     * @throws AspectNotFoundException
289
     * @throws NoSolrConnectionFoundException
290
     * @throws DBALDriverException
291
     */
292
    protected function getSolrConnection(Item $indexQueueItem): SolrConnection
293
    {
294
        /** @var $connectionManager ConnectionManager */
295
        $connectionManager = GeneralUtility::makeInstance(ConnectionManager::class);
296
297
        return $connectionManager->getConnectionByRootPageId(
298
            $indexQueueItem->getRootPageUid(),
0 ignored issues
show
Bug introduced by
It seems like $indexQueueItem->getRootPageUid() can also be of type null; however, parameter $pageId of ApacheSolrForTypo3\Solr\...onnectionByRootPageId() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

298
            /** @scrutinizer ignore-type */ $indexQueueItem->getRootPageUid(),
Loading history...
299
            Util::getLanguageUid()
300
        );
301
    }
302
303
    /**
304
     * This method retrieves the item from the index queue, that is indexed in this request.
305
     *
306
     * @return Item|null
307
     * @throws DBALDriverException
308
     * @throws DBALException
309
     */
310
    protected function getIndexQueueItem(): ?Item
311
    {
312
        /** @var $indexQueue Queue */
313
        $indexQueue = GeneralUtility::makeInstance(Queue::class);
314
        return $indexQueue->getItem($this->request->getParameter('item'));
315
    }
316
}
317