Passed
Pull Request — master (#1300)
by
unknown
21:35
created

PageIndexer   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 320
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Test Coverage

Coverage 56.79%

Importance

Changes 0
Metric Value
wmc 28
c 0
b 0
f 0
lcom 1
cbo 13
dl 0
loc 320
ccs 96
cts 169
cp 0.5679
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A activate() 0 21 1
A getData() 0 4 1
A getAccessRootline() 0 11 2
B registerAuthorizationService() 0 27 1
B generatePageUrl() 0 28 4
C hook_indexContent() 0 69 10
A getSolrConnection() 0 12 1
A getIndexQueueItem() 0 7 1
B authorizeFrontendUser() 0 24 3
A getHighestAuthenticationServicePriority() 0 14 4
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 2 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\SolrService;
32
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
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 8
    public function activate()
81
    {
82 8
        $pageIndexingHookRegistration = PageIndexer::class;
83
84 8
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['initFEuser'][__CLASS__] = '&' . $pageIndexingHookRegistration . '->authorizeFrontendUser';
85 8
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['tslib_fe-PostProc'][__CLASS__] = '&' . $pageIndexingHookRegistration . '->disableCaching';
86 8
        $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 8
        $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
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 8
        $GLOBALS['T3_VAR']['callUserFunction_classPool'][__CLASS__] = $this;
97
        //$GLOBALS['T3_VAR']['getUserObj'][$pageIndexingHookRegistration] = $this;
98
99 8
        $this->registerAuthorizationService();
100 8
    }
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 1
    public function authorizeFrontendUser()
122
    {
123 1
        $accessRootline = $this->getAccessRootline();
124 1
        $stringAccessRootline = (string)$accessRootline;
125
126 1
        if (empty($stringAccessRootline)) {
127
            return;
128
        }
129
130 1
        if (!is_array($GLOBALS['TSFE']->fe_user->user)) {
131 1
            $GLOBALS['TSFE']->fe_user->user = [];
132
        }
133
134 1
        $groups = $accessRootline->getGroups();
135 1
        $groupList = implode(',', $groups);
136
137 1
        $GLOBALS['TSFE']->fe_user->user['username'] = AuthorizationService::SOLR_INDEXER_USERNAME;
138 1
        $GLOBALS['TSFE']->fe_user->user['usergroup'] = $groupList;
139
140 1
        $this->responseData['authorization'] = [
141 1
            'username' => $GLOBALS['TSFE']->fe_user->user['username'],
142 1
            'usergroups' => $GLOBALS['TSFE']->fe_user->user['usergroup']
143
        ];
144 1
    }
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 8
    protected function getAccessRootline()
152
    {
153 8
        $stringAccessRootline = '';
154
155 8
        if ($this->request->getParameter('accessRootline')) {
156
            $stringAccessRootline = $this->request->getParameter('accessRootline');
157
        }
158
159 8
        $accessRootline = GeneralUtility::makeInstance(Rootline::class, $stringAccessRootline);
160 8
        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 8
    protected function registerAuthorizationService()
170
    {
171 8
        $overrulingPriority = $this->getHighestAuthenticationServicePriority() + 1;
172
173 8
        ExtensionManagementUtility::addService(
174 8
            'solr', // extension key
175 8
            'auth', // service type
176 8
            AuthorizationService::class,
177
            // service key
178
            [// service meta data
179 8
                'title' => 'Solr Indexer Authorization',
180 8
                'description' => 'Authorizes the Solr Index Queue indexer to access protected pages.',
181
182 8
                'subtype' => 'getUserFE,authUserFE,getGroupsFE',
183
184
                'available' => true,
185 8
                'priority' => $overrulingPriority,
186 8
                'quality' => 100,
187
188 8
                'os' => '',
189 8
                'exec' => '',
190
191 8
                'classFile' => ExtensionManagementUtility::extPath('solr') . 'Classes/IndexQueue/FrontendHelper/AuthorizationService.php',
192
                'className' => AuthorizationService::class,
193
            ]
194
        );
195 8
    }
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 8
    protected function getHighestAuthenticationServicePriority()
204
    {
205 8
        $highestPriority = 0;
206
207 8
        if (is_array($GLOBALS['T3_SERVICES']['auth'])) {
208 1
            foreach ($GLOBALS['T3_SERVICES']['auth'] as $service) {
209 1
                if ($service['priority'] > $highestPriority) {
210 1
                    $highestPriority = $service['priority'];
211
                }
212
            }
213
        }
214
215 8
        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 8
    protected function generatePageUrl()
230
    {
231 8
        if ($this->request->getParameter('overridePageUrl')) {
232
            return $this->request->getParameter('overridePageUrl');
233
        }
234
235
            /** @var $contentObject ContentObjectRenderer */
236 8
        $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
237
238
        $typolinkConfiguration = [
239 8
            'parameter' => intval($this->page->id),
240 8
            'linkAccessRestrictedPages' => '1'
241
        ];
242
243 8
        $language = GeneralUtility::_GET('L');
244 8
        if (!empty($language)) {
245
            $typolinkConfiguration['additionalParams'] = '&L=' . $language;
246
        }
247
248 8
        $url = $contentObject->typoLink_URL($typolinkConfiguration);
249
250
        // clean up
251 8
        if ($url == '') {
252
            $url = '/';
253
        }
254
255 8
        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 8
    public function hook_indexContent(TypoScriptFrontendController $page)
265
    {
266 8
        $this->logger = GeneralUtility::makeInstance(SolrLogManager::class, __CLASS__);
267
268 8
        $this->page = $page;
269 8
        $configuration = Util::getSolrConfiguration();
270
271 8
        $logPageIndexed = $configuration->getLoggingIndexingPageIndexed();
272 8
        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 8
            $indexQueueItem = $this->getIndexQueueItem();
284 8
            if (is_null($indexQueueItem)) {
285
                throw new \UnexpectedValueException('Can not get index queue item', 1482162337);
286
            }
287
288 8
            $solrConnection = $this->getSolrConnection($indexQueueItem);
289
290
            /** @var $indexer Typo3PageIndexer */
291 8
            $indexer = GeneralUtility::makeInstance(Typo3PageIndexer::class, $page);
292 8
            $indexer->setSolrConnection($solrConnection);
293 8
            $indexer->setPageAccessRootline($this->getAccessRootline());
294 8
            $indexer->setPageUrl($this->generatePageUrl());
295 8
            $indexer->setMountPointParameter($GLOBALS['TSFE']->MP);
296 8
            $indexer->setIndexQueueItem($indexQueueItem);
297
298 8
            $this->responseData['pageIndexed'] = (int)$indexer->indexPage();
299 8
            $this->responseData['originalPageDocument'] = (array)$indexer->getPageSolrDocument();
300 8
            $this->responseData['solrConnection'] = [
301 8
                'rootPage' => $indexQueueItem->getRootPageUid(),
302 8
                'sys_language_uid' => $GLOBALS['TSFE']->sys_language_uid,
303 8
                'solr' => (string)$solrConnection
304
            ];
305
306 8
            $documentsSentToSolr = $indexer->getDocumentsSentToSolr();
307 8
            foreach ($documentsSentToSolr as $document) {
308 8
                $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 8
        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 8
    }
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 SolrService Solr server connection
340
     */
341 8
    protected function getSolrConnection(Item $indexQueueItem)
342
    {
343
        /** @var $connectionManager ConnectionManager */
344 8
        $connectionManager = GeneralUtility::makeInstance(ConnectionManager::class);
345
346 8
        $solrConnection = $connectionManager->getConnectionByRootPageId(
347 8
            $indexQueueItem->getRootPageUid(),
348 8
            $GLOBALS['TSFE']->sys_language_uid
349
        );
350
351 8
        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 8
    protected function getIndexQueueItem()
360
    {
361
        /** @var $indexQueue Queue */
362 8
        $indexQueue = GeneralUtility::makeInstance(Queue::class);
363 8
        $indexQueueItem = $indexQueue->getItem($this->request->getParameter('item'));
364 8
        return $indexQueueItem;
365
    }
366
}
367