Passed
Push — master ( 16f071...683c38 )
by Timo
22:25
created

PageIndexer   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 318
Duplicated Lines 0 %

Test Coverage

Coverage 80.17%

Importance

Changes 0
Metric Value
wmc 28
dl 0
loc 318
ccs 97
cts 121
cp 0.8017
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getHighestAuthenticationServicePriority() 0 13 4
B generatePageUrl() 0 27 4
A getData() 0 3 1
A activate() 0 20 1
C hook_indexContent() 0 66 10
A getAccessRootline() 0 10 2
A getIndexQueueItem() 0 6 1
A authorizeFrontendUser() 0 22 3
B registerAuthorizationService() 0 24 1
A getSolrConnection() 0 11 1
1
<?php
2
namespace ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2011-2015 Ingo Renner <[email protected]>
8
 *  All rights reserved
9
 *
10
 *  This script is part of the TYPO3 project. The TYPO3 project is
11
 *  free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 3 of the License, or
14
 *  (at your option) any later version.
15
 *
16
 *  The GNU General Public License can be found at
17
 *  http://www.gnu.org/copyleft/gpl.html.
18
 *
19
 *  This script is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
23
 *
24
 *  This copyright notice MUST APPEAR in all copies of the script!
25
 ***************************************************************/
26
27
use ApacheSolrForTypo3\Solr\Access\Rootline;
28
use ApacheSolrForTypo3\Solr\ConnectionManager;
29
use ApacheSolrForTypo3\Solr\IndexQueue\Item;
30
use ApacheSolrForTypo3\Solr\IndexQueue\Queue;
31
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
32
use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection;
33
use ApacheSolrForTypo3\Solr\Typo3PageIndexer;
34
use ApacheSolrForTypo3\Solr\Util;
35
use TYPO3\CMS\Core\SingletonInterface;
36
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
37
use TYPO3\CMS\Core\Utility\GeneralUtility;
38
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
39
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
40
41
/**
42
 * Index Queue Page Indexer frontend helper to ask the frontend page indexer to
43
 * index the page.
44
 *
45
 * @author Ingo Renner <[email protected]>
46
 */
47
class PageIndexer extends AbstractFrontendHelper implements SingletonInterface
48
{
49
50
    /**
51
     * This frontend helper's executed action.
52
     *
53
     * @var string
54
     */
55
    protected $action = 'indexPage';
56
57
    /**
58
     * the page currently being indexed.
59
     *
60
     * @var TypoScriptFrontendController
61
     */
62
    protected $page;
63
64
    /**
65
     * Response data
66
     *
67
     * @var array
68
     */
69
    protected $responseData = [];
70
71
    /**
72
     * @var \TYPO3\CMS\Core\Log\Logger
73
     */
74
    protected $logger = null;
75
76
    /**
77
     * Activates a frontend helper by registering for hooks and other
78
     * resources required by the frontend helper to work.
79
     */
80 20
    public function activate()
81
    {
82 20
        $pageIndexingHookRegistration = PageIndexer::class;
83
84 20
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['initFEuser'][__CLASS__] = $pageIndexingHookRegistration . '->authorizeFrontendUser';
85 20
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['tslib_fe-PostProc'][__CLASS__] = $pageIndexingHookRegistration . '->disableCaching';
86 20
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['pageIndexing'][__CLASS__] = $pageIndexingHookRegistration;
87
88
        // indexes fields defined in plugin.tx_solr.index.queue.pages.fields
89 20
        $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument']['ApacheSolrForTypo3\\Solr\\IndexQueue\\FrontendHelper\\PageFieldMappingIndexer'] = PageFieldMappingIndexer::class;
90
91
        // making sure this instance is reused when called by the hooks registered before
92
        // \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction() and \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj() use
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
93
        // these storages while the object was instantiated by
94
        // ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\Manager before.
95
        // \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance() also uses a dedicated cache
96 20
        $GLOBALS['T3_VAR']['callUserFunction_classPool'][__CLASS__] = $this;
97
        //$GLOBALS['T3_VAR']['getUserObj'][$pageIndexingHookRegistration] = $this;
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
98
99 20
        $this->registerAuthorizationService();
100 20
    }
101
102
    /**
103
     * Returns the status of whether a page was indexed.
104
     *
105
     * @return array Page indexed status.
106
     */
107
    public function getData()
108
    {
109
        return $this->responseData;
110
    }
111
112
    #
113
    # Indexer authorisation for access restricted pages / content
114
    #
115
116
    /**
117
     * Fakes a logged in user to retrieve access restricted content.
118
     *
119
     * @return void
120
     */
121 4
    public function authorizeFrontendUser()
122
    {
123 4
        $accessRootline = $this->getAccessRootline();
124 4
        $stringAccessRootline = (string)$accessRootline;
125
126 4
        if (empty($stringAccessRootline)) {
127
            return;
128
        }
129
130 4
        if (!is_array($GLOBALS['TSFE']->fe_user->user)) {
131 4
            $GLOBALS['TSFE']->fe_user->user = [];
132
        }
133
134 4
        $groups = $accessRootline->getGroups();
135 4
        $groupList = implode(',', $groups);
136
137 4
        $GLOBALS['TSFE']->fe_user->user['username'] = AuthorizationService::SOLR_INDEXER_USERNAME;
138 4
        $GLOBALS['TSFE']->fe_user->user['usergroup'] = $groupList;
139
140 4
        $this->responseData['authorization'] = [
141 4
            'username' => $GLOBALS['TSFE']->fe_user->user['username'],
142 4
            'usergroups' => $GLOBALS['TSFE']->fe_user->user['usergroup']
143
        ];
144 4
    }
145
146
    /**
147
     * Gets the access rootline as defined by the request.
148
     *
149
     * @return Rootline The access rootline to use for indexing.
150
     */
151 20
    protected function getAccessRootline()
152
    {
153 20
        $stringAccessRootline = '';
154
155 20
        if ($this->request->getParameter('accessRootline')) {
156
            $stringAccessRootline = $this->request->getParameter('accessRootline');
157
        }
158
159 20
        $accessRootline = GeneralUtility::makeInstance(Rootline::class, /** @scrutinizer ignore-type */ $stringAccessRootline);
160 20
        return $accessRootline;
161
    }
162
163
    /**
164
     * Registers an authentication service to authorize / grant the indexer to
165
     * access protected pages.
166
     *
167
     * @return void
168
     */
169 20
    protected function registerAuthorizationService()
170
    {
171 20
        $overrulingPriority = $this->getHighestAuthenticationServicePriority() + 1;
172
173 20
        ExtensionManagementUtility::addService(
174 20
            'solr', // extension key
175 20
            'auth', // service type
176 20
            AuthorizationService::class,
177
            // service key
178
            [// service meta data
179 20
                'title' => 'Solr Indexer Authorization',
180 20
                'description' => 'Authorizes the Solr Index Queue indexer to access protected pages.',
181
182 20
                'subtype' => 'getUserFE,authUserFE,getGroupsFE',
183
184
                'available' => true,
185 20
                'priority' => $overrulingPriority,
186 20
                'quality' => 100,
187
188 20
                'os' => '',
189 20
                'exec' => '',
190
191 20
                'classFile' => ExtensionManagementUtility::extPath('solr') . 'Classes/IndexQueue/FrontendHelper/AuthorizationService.php',
192
                'className' => AuthorizationService::class,
193
            ]
194
        );
195 20
    }
196
197
    /**
198
     * Determines the highest priority of all registered authentication
199
     * services.
200
     *
201
     * @return int Highest priority of all registered authentication service
202
     */
203 20
    protected function getHighestAuthenticationServicePriority()
204
    {
205 20
        $highestPriority = 0;
206
207 20
        if (is_array($GLOBALS['T3_SERVICES']['auth'])) {
208 4
            foreach ($GLOBALS['T3_SERVICES']['auth'] as $service) {
209 4
                if ($service['priority'] > $highestPriority) {
210 4
                    $highestPriority = $service['priority'];
211
                }
212
            }
213
        }
214
215 20
        return $highestPriority;
216
    }
217
218
    #
219
    # Indexing
220
    #
221
222
    /**
223
     * Generates the current page's URL.
224
     *
225
     * Uses the provided GET parameters, page id and language id.
226
     *
227
     * @return string URL of the current page.
228
     */
229 20
    protected function generatePageUrl()
230
    {
231 20
        if ($this->request->getParameter('overridePageUrl')) {
232
            return $this->request->getParameter('overridePageUrl');
233
        }
234
235
            /** @var $contentObject ContentObjectRenderer */
236 20
        $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
237
238
        $typolinkConfiguration = [
239 20
            'parameter' => intval($this->page->id),
240 20
            'linkAccessRestrictedPages' => '1'
241
        ];
242
243 20
        $language = GeneralUtility::_GET('L');
244 20
        if (!empty($language)) {
245 2
            $typolinkConfiguration['additionalParams'] = '&L=' . $language;
246
        }
247
248 20
        $url = $contentObject->typoLink_URL($typolinkConfiguration);
249
250
        // clean up
251 20
        if ($url == '') {
252
            $url = '/';
253
        }
254
255 20
        return $url;
256
    }
257
258
    /**
259
     * Handles the indexing of the page content during post processing of a
260
     * generated page.
261
     *
262
     * @param TypoScriptFrontendController $page TypoScript frontend
263
     */
264 20
    public function hook_indexContent(TypoScriptFrontendController $page)
265
    {
266 20
        $this->logger = GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__);
267
268 20
        $this->page = $page;
269 20
        $configuration = Util::getSolrConfiguration();
270
271 20
        $logPageIndexed = $configuration->getLoggingIndexingPageIndexed();
272 20
        if (!$this->page->config['config']['index_enable']) {
273
            if ($logPageIndexed) {
274
                $this->logger->log(
275
                    SolrLogManager::ERROR,
276
                    'Indexing is disabled. Set config.index_enable = 1 .'
277
                );
278
            }
279
            return;
280
        }
281
282
        try {
283 20
            $indexQueueItem = $this->getIndexQueueItem();
284 20
            if (is_null($indexQueueItem)) {
285
                throw new \UnexpectedValueException('Can not get index queue item', 1482162337);
286
            }
287
288 20
            $solrConnection = $this->getSolrConnection($indexQueueItem);
289
290
            /** @var $indexer Typo3PageIndexer */
291 20
            $indexer = GeneralUtility::makeInstance(Typo3PageIndexer::class, /** @scrutinizer ignore-type */ $page);
292 20
            $indexer->setSolrConnection($solrConnection);
293 20
            $indexer->setPageAccessRootline($this->getAccessRootline());
294 20
            $indexer->setPageUrl($this->generatePageUrl());
295 20
            $indexer->setMountPointParameter($GLOBALS['TSFE']->MP);
296 20
            $indexer->setIndexQueueItem($indexQueueItem);
297
298 20
            $this->responseData['pageIndexed'] = (int)$indexer->indexPage();
299 20
            $this->responseData['originalPageDocument'] = (array)$indexer->getPageSolrDocument();
300 20
            $this->responseData['solrConnection'] = [
301 20
                'rootPage' => $indexQueueItem->getRootPageUid(),
302 20
                'sys_language_uid' => $GLOBALS['TSFE']->sys_language_uid,
303 20
                'solr' => (string)$solrConnection
304
            ];
305
306 20
            $documentsSentToSolr = $indexer->getDocumentsSentToSolr();
307 20
            foreach ($documentsSentToSolr as $document) {
308 20
                $this->responseData['documentsSentToSolr'][] = (array)$document;
309
            }
310
        } catch (\Exception $e) {
311
            if ($configuration->getLoggingExceptions()) {
312
                $this->logger->log(
313
                    SolrLogManager::ERROR,
314
                    'Exception while trying to index page ' . $page->id,
315
                    [
316
                        $e->__toString()
317
                    ]
318
                );
319
            }
320
        }
321
322 20
        if ($logPageIndexed) {
323
            $success = $this->responseData['pageIndexed'] ? 'Success' : 'Failed';
324
            $severity = $this->responseData['pageIndexed'] ? SolrLogManager::NOTICE : SolrLogManager::ERROR;
325
326
            $this->logger->log(
327
                $severity,
328
                'Page indexed: ' . $success,
329
                $this->responseData
330
            );
331
        }
332 20
    }
333
334
    /**
335
     * Gets the solr connection to use for indexing the page based on the
336
     * Index Queue item's properties.
337
     *
338
     * @param Item $indexQueueItem
339
     * @return SolrConnection Solr server connection
340
     */
341 20
    protected function getSolrConnection(Item $indexQueueItem)
342
    {
343
        /** @var $connectionManager ConnectionManager */
344 20
        $connectionManager = GeneralUtility::makeInstance(ConnectionManager::class);
345
346 20
        $solrConnection = $connectionManager->getConnectionByRootPageId(
347 20
            $indexQueueItem->getRootPageUid(),
348 20
            $GLOBALS['TSFE']->sys_language_uid
349
        );
350
351 20
        return $solrConnection;
352
    }
353
354
    /**
355
     * This method retrieves the item from the index queue, that is indexed in this request.
356
     *
357
     * @return \ApacheSolrForTypo3\Solr\IndexQueue\Item
358
     */
359 20
    protected function getIndexQueueItem()
360
    {
361
        /** @var $indexQueue Queue */
362 20
        $indexQueue = GeneralUtility::makeInstance(Queue::class);
363 20
        $indexQueueItem = $indexQueue->getItem($this->request->getParameter('item'));
364 20
        return $indexQueueItem;
365
    }
366
}
367