Completed
Push — master ( 5acc36...ed24b6 )
by Timo
13:20
created

PageIndexer   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 308
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Test Coverage

Coverage 49.06%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 28
c 1
b 0
f 0
lcom 1
cbo 13
dl 0
loc 308
ccs 78
cts 159
cp 0.4906
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
B activate() 0 25 1
A getData() 0 4 1
B authorizeFrontendUser() 0 24 3
A getAccessRootline() 0 11 2
A getHighestAuthenticationServicePriority() 0 14 4
B generatePageUrl() 0 28 4
C hook_indexContent() 0 58 10
A getSolrConnection() 0 12 1
A getIndexQueueItem() 0 7 1
B registerAuthorizationService() 0 27 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 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\Typo3PageIndexer;
33
use ApacheSolrForTypo3\Solr\Util;
34
use TYPO3\CMS\Core\SingletonInterface;
35
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
36
use TYPO3\CMS\Core\Utility\GeneralUtility;
37
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
38
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
39
40
/**
41
 * Index Queue Page Indexer frontend helper to ask the frontend page indexer to
42
 * index the page.
43
 *
44
 * @author Ingo Renner <[email protected]>
45
 */
46
class PageIndexer extends AbstractFrontendHelper implements SingletonInterface
47
{
48
49
    /**
50
     * This frontend helper's executed action.
51
     *
52
     * @var string
53
     */
54
    protected $action = 'indexPage';
55
56
    /**
57
     * the page currently being indexed.
58
     *
59
     * @var TypoScriptFrontendController
60
     */
61
    protected $page;
62
63
    /**
64
     * Response data
65
     *
66
     * @var array
67
     */
68
    protected $responseData = [];
69
70
    /**
71
     * Activates a frontend helper by registering for hooks and other
72
     * resources required by the frontend helper to work.
73
     */
74 5
    public function activate()
75
    {
76 5
        $pageIndexingHookRegistration = PageIndexer::class;
77
78 5
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['initFEuser'][__CLASS__] = '&' . $pageIndexingHookRegistration . '->authorizeFrontendUser';
79 5
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['tslib_fe-PostProc'][__CLASS__] = '&' . $pageIndexingHookRegistration . '->disableCaching';
80 5
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['pageIndexing'][__CLASS__] = $pageIndexingHookRegistration;
81
82
        // indexes fields defined in plugin.tx_solr.index.queue.pages.fields
83 5
        $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument']['ApacheSolrForTypo3\\Solr\\IndexQueue\\FrontendHelper\\PageFieldMappingIndexer'] = PageFieldMappingIndexer::class;
84
85
        // making sure this instance is reused when called by the hooks registered before
86
        // \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction() and \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj() use
87
        // these storages while the object was instantiated by
88
        // ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper\Manager before.
89
        // \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance() also uses a dedicated cache
90 5
        $GLOBALS['T3_VAR']['callUserFunction_classPool'][__CLASS__] = $this;
91
        //$GLOBALS['T3_VAR']['getUserObj'][$pageIndexingHookRegistration] = $this;
92
93 5
        $this->registerAuthorizationService();
94
# Since TypoScript is not available at this point we cannot bind it to some TS configuration option whether to log or not
95
#		\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('Registered Solr Page Indexer authorization service', 'solr', 1, array(
96
#			'auth services' => $GLOBALS['T3_SERVICES']['auth']
97
#		));
98 5
    }
99
100
    /**
101
     * Returns the status of whether a page was indexed.
102
     *
103
     * @return array Page indexed status.
104
     */
105
    public function getData()
106
    {
107
        return $this->responseData;
108
    }
109
110
    #
111
    # Indexer authorisation for access restricted pages / content
112
    #
113
114
    /**
115
     * Fakes a logged in user to retrieve access restricted content.
116
     *
117
     * @return void
118
     */
119
    public function authorizeFrontendUser()
120
    {
121
        $accessRootline = $this->getAccessRootline();
122
        $stringAccessRootline = (string)$accessRootline;
123
124
        if (empty($stringAccessRootline)) {
125
            return;
126
        }
127
128
        if (!is_array($GLOBALS['TSFE']->fe_user->user)) {
129
            $GLOBALS['TSFE']->fe_user->user = [];
130
        }
131
132
        $groups = $accessRootline->getGroups();
133
        $groupList = implode(',', $groups);
134
135
        $GLOBALS['TSFE']->fe_user->user['username'] = AuthorizationService::SOLR_INDEXER_USERNAME;
136
        $GLOBALS['TSFE']->fe_user->user['usergroup'] = $groupList;
137
138
        $this->responseData['authorization'] = array(
139
            'username' => $GLOBALS['TSFE']->fe_user->user['username'],
140
            'usergroups' => $GLOBALS['TSFE']->fe_user->user['usergroup']
141
        );
142
    }
143
144
    /**
145
     * Gets the access rootline as defined by the request.
146
     *
147
     * @return Rootline The access rootline to use for indexing.
148
     */
149 5
    protected function getAccessRootline()
150
    {
151 5
        $stringAccessRootline = '';
152
153 5
        if ($this->request->getParameter('accessRootline')) {
154
            $stringAccessRootline = $this->request->getParameter('accessRootline');
155
        }
156
157 5
        $accessRootline = GeneralUtility::makeInstance(Rootline::class, $stringAccessRootline);
158 5
        return $accessRootline;
159
    }
160
161
    /**
162
     * Registers an authentication service to authorize / grant the indexer to
163
     * access protected pages.
164
     *
165
     * @return void
166
     */
167 5
    protected function registerAuthorizationService()
168
    {
169 5
        $overrulingPriority = $this->getHighestAuthenticationServicePriority() + 1;
170
171 5
        ExtensionManagementUtility::addService(
172 5
            'solr', // extension key
173 5
            'auth', // service type
174 5
            AuthorizationService::class,
175
            // service key
176
            array( // service meta data
177 5
                'title' => 'Solr Indexer Authorization',
178 5
                'description' => 'Authorizes the Solr Index Queue indexer to access protected pages.',
179
180 5
                'subtype' => 'getUserFE,authUserFE,getGroupsFE',
181
182
                'available' => true,
183 5
                'priority' => $overrulingPriority,
184 5
                'quality' => 100,
185
186 5
                'os' => '',
187 5
                'exec' => '',
188
189 5
                'classFile' => $GLOBALS['PATH_solr'] . 'Classes/IndexQueue/FrontendHelper/AuthorizationService.php',
190
                'className' => AuthorizationService::class,
191
            )
192
        );
193 5
    }
194
195
    /**
196
     * Determines the highest priority of all registered authentication
197
     * services.
198
     *
199
     * @return int Highest priority of all registered authentication service
200
     */
201 5
    protected function getHighestAuthenticationServicePriority()
202
    {
203 5
        $highestPriority = 0;
204
205 5
        if (is_array($GLOBALS['T3_SERVICES']['auth'])) {
206
            foreach ($GLOBALS['T3_SERVICES']['auth'] as $service) {
207
                if ($service['priority'] > $highestPriority) {
208
                    $highestPriority = $service['priority'];
209
                }
210
            }
211
        }
212
213 5
        return $highestPriority;
214
    }
215
216
    #
217
    # Indexing
218
    #
219
220
    /**
221
     * Generates the current page's URL.
222
     *
223
     * Uses the provided GET parameters, page id and language id.
224
     *
225
     * @return string URL of the current page.
226
     */
227 5
    protected function generatePageUrl()
228
    {
229 5
        if ($this->request->getParameter('overridePageUrl')) {
230
            return $this->request->getParameter('overridePageUrl');
231
        }
232
233
            /** @var $contentObject ContentObjectRenderer */
234 5
        $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
235
236
        $typolinkConfiguration = array(
237 5
            'parameter' => intval($this->page->id),
238 5
            'linkAccessRestrictedPages' => '1'
239
        );
240
241 5
        $language = GeneralUtility::_GET('L');
242 5
        if (!empty($language)) {
243
            $typolinkConfiguration['additionalParams'] = '&L=' . $language;
244
        }
245
246 5
        $url = $contentObject->typoLink_URL($typolinkConfiguration);
247
248
        // clean up
249 5
        if ($url == '') {
250
            $url = '/';
251
        }
252
253 5
        return $url;
254
    }
255
256
    /**
257
     * Handles the indexing of the page content during post processing of a
258
     * generated page.
259
     *
260
     * @param TypoScriptFrontendController $page TypoScript frontend
261
     */
262 5
    public function hook_indexContent(TypoScriptFrontendController $page)
263
    {
264 5
        $this->page = $page;
265 5
        $configuration = Util::getSolrConfiguration();
266
267 5
        $logPageIndexed = $configuration->getLoggingIndexingPageIndexed();
268 5
        if (!$this->page->config['config']['index_enable']) {
269
            if ($logPageIndexed) {
270
                GeneralUtility::devLog('Indexing is disabled. Set config.index_enable = 1 .',
271
                    'solr', 3);
272
            }
273
            return;
274
        }
275
276
        try {
277 5
            $indexQueueItem = $this->getIndexQueueItem();
278 5
            if (is_null($indexQueueItem)) {
279
                throw new \UnexpectedValueException('Can not get index queue item', 1482162337);
280
            }
281
282 5
            $solrConnection = $this->getSolrConnection($indexQueueItem);
283
284
            /** @var $indexer Typo3PageIndexer */
285 5
            $indexer = GeneralUtility::makeInstance(Typo3PageIndexer::class, $page);
286 5
            $indexer->setSolrConnection($solrConnection);
287 5
            $indexer->setPageAccessRootline($this->getAccessRootline());
288 5
            $indexer->setPageUrl($this->generatePageUrl());
289 5
            $indexer->setMountPointParameter($GLOBALS['TSFE']->MP);
290 5
            $indexer->setIndexQueueItem($indexQueueItem);
291
292 5
            $this->responseData['pageIndexed'] = (int)$indexer->indexPage();
293 5
            $this->responseData['originalPageDocument'] = (array)$indexer->getPageSolrDocument();
294 5
            $this->responseData['solrConnection'] = array(
295 5
                'rootPage' => $indexQueueItem->getRootPageUid(),
296 5
                'sys_language_uid' => $GLOBALS['TSFE']->sys_language_uid,
297 5
                'solr' => (string)$solrConnection
298
            );
299
300 5
            $documentsSentToSolr = $indexer->getDocumentsSentToSolr();
301 5
            foreach ($documentsSentToSolr as $document) {
302 5
                $this->responseData['documentsSentToSolr'][] = (array)$document;
303
            }
304
        } catch (\Exception $e) {
305
            if ($configuration->getLoggingExceptions()) {
306
                GeneralUtility::devLog('Exception while trying to index page ' . $page->id,
307
                    'solr', 3, array(
308
                        $e->__toString()
309
                    ));
310
            }
311
        }
312
313 5
        if ($logPageIndexed) {
314
            $success = $this->responseData['pageIndexed'] ? 'Success' : 'Failed';
315
            $severity = $this->responseData['pageIndexed'] ? -1 : 3;
316
317
            GeneralUtility::devLog('Page indexed: ' . $success, 'solr', $severity, $this->responseData);
318
        }
319 5
    }
320
321
    /**
322
     * Gets the solr connection to use for indexing the page based on the
323
     * Index Queue item's properties.
324
     *
325
     * @param Item $indexQueueItem
326
     * @return SolrService Solr server connection
327
     */
328 5
    protected function getSolrConnection(Item $indexQueueItem)
329
    {
330
        /** @var $connectionManager ConnectionManager */
331 5
        $connectionManager = GeneralUtility::makeInstance(ConnectionManager::class);
332
333 5
        $solrConnection = $connectionManager->getConnectionByRootPageId(
334 5
            $indexQueueItem->getRootPageUid(),
335 5
            $GLOBALS['TSFE']->sys_language_uid
336
        );
337
338 5
        return $solrConnection;
339
    }
340
341
    /**
342
     * This method retrieves the item from the index queue, that is indexed in this request.
343
     *
344
     * @return \ApacheSolrForTypo3\Solr\IndexQueue\Item
345
     */
346 5
    protected function getIndexQueueItem()
347
    {
348
        /** @var $indexQueue Queue */
349 5
        $indexQueue = GeneralUtility::makeInstance(Queue::class);
350 5
        $indexQueueItem = $indexQueue->getItem($this->request->getParameter('item'));
351 5
        return $indexQueueItem;
352
    }
353
}
354