Completed
Push — master ( b6b629...72d15a )
by Timo
10s
created

PageIndexer::getIndexQueueItem()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1.037

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 4
cts 6
cp 0.6667
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 0
crap 1.037
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 = array();
69
70
    /**
71
     * Activates a frontend helper by registering for hooks and other
72
     * resources required by the frontend helper to work.
73
     */
74 3
    public function activate()
75
    {
76 3
        $pageIndexingHookRegistration = 'ApacheSolrForTypo3\\Solr\\IndexQueue\\FrontendHelper\\PageIndexer';
77
78 3
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['initFEuser'][__CLASS__] = '&' . $pageIndexingHookRegistration . '->authorizeFrontendUser';
79 3
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['tslib_fe-PostProc'][__CLASS__] = '&' . $pageIndexingHookRegistration . '->disableCaching';
80 3
        $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 3
        $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument']['ApacheSolrForTypo3\\Solr\\IndexQueue\\FrontendHelper\\PageFieldMappingIndexer'] = 'ApacheSolrForTypo3\\Solr\\IndexQueue\\FrontendHelper\\PageFieldMappingIndexer';
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 3
        $GLOBALS['T3_VAR']['callUserFunction_classPool'][__CLASS__] = $this;
91
        //$GLOBALS['T3_VAR']['getUserObj'][$pageIndexingHookRegistration] = $this;
92
93 3
        $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 3
    }
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 = array();
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 3
    protected function getAccessRootline()
150
    {
151 3
        $stringAccessRootline = '';
152
153 3
        if ($this->request->getParameter('accessRootline')) {
154
            $stringAccessRootline = $this->request->getParameter('accessRootline');
155
        }
156
157 3
        $accessRootline = GeneralUtility::makeInstance(Rootline::class, $stringAccessRootline);
158 3
        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 3
    protected function registerAuthorizationService()
168
    {
169 3
        $overrulingPriority = $this->getHighestAuthenticationServicePriority() + 1;
170
171 3
        ExtensionManagementUtility::addService(
172 3
            'solr', // extension key
173 3
            'auth', // service type
174 3
            'ApacheSolrForTypo3\\Solr\\IndexQueue\\FrontendHelper\\AuthorizationService',
175
            // service key
176
            array( // service meta data
177 3
                'title' => 'Solr Indexer Authorization',
178 3
                'description' => 'Authorizes the Solr Index Queue indexer to access protected pages.',
179
180 3
                'subtype' => 'getUserFE,authUserFE,getGroupsFE',
181
182
                'available' => true,
183 3
                'priority' => $overrulingPriority,
184 3
                'quality' => 100,
185
186 3
                'os' => '',
187 3
                'exec' => '',
188
189 3
                'classFile' => $GLOBALS['PATH_solr'] . 'Classes/IndexQueue/FrontendHelper/AuthorizationService.php',
190 3
                'className' => 'ApacheSolrForTypo3\\Solr\\IndexQueue\\FrontendHelper\\AuthorizationService',
191
            )
192
        );
193 3
    }
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 3
    protected function getHighestAuthenticationServicePriority()
202
    {
203 3
        $highestPriority = 0;
204
205 3
        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 3
        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 3
    protected function generatePageUrl()
228
    {
229 3
        if ($this->request->getParameter('overridePageUrl')) {
230
            return $this->request->getParameter('overridePageUrl');
231
        }
232
233
            /** @var $contentObject ContentObjectRenderer */
234 3
        $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
235
236
        $typolinkConfiguration = array(
237 3
            'parameter' => intval($this->page->id),
238 3
            'linkAccessRestrictedPages' => '1'
239
        );
240
241 3
        $language = GeneralUtility::_GET('L');
242 3
        if (!empty($language)) {
243
            $typolinkConfiguration['additionalParams'] = '&L=' . $language;
244
        }
245
246 3
        $url = $contentObject->typoLink_URL($typolinkConfiguration);
247
248
        // clean up
249 3
        if ($url == '') {
250
            $url = '/';
251
        }
252
253 3
        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 3
    public function hook_indexContent(TypoScriptFrontendController $page)
263
    {
264 3
        $this->page = $page;
265 3
        $configuration = Util::getSolrConfiguration();
266
267 3
        $logPageIndexed = $configuration->getLoggingIndexingPageIndexed();
268 3
        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 3
            $indexQueueItem = $this->getIndexQueueItem();
278 3
            if (is_null($indexQueueItem)) {
279
                throw new \UnexpectedValueException('Can not get index queue item', 1482162337);
280
            }
281
282 3
            $solrConnection = $this->getSolrConnection($indexQueueItem);
283
284
            /** @var $indexer Typo3PageIndexer */
285 3
            $indexer = GeneralUtility::makeInstance(Typo3PageIndexer::class, $page);
286 3
            $indexer->setSolrConnection($solrConnection);
287 3
            $indexer->setPageAccessRootline($this->getAccessRootline());
288 3
            $indexer->setPageUrl($this->generatePageUrl());
289 3
            $indexer->setMountPointParameter($GLOBALS['TSFE']->MP);
290 3
            $indexer->setIndexQueueItem($indexQueueItem);
291
292 3
            $this->responseData['pageIndexed'] = (int)$indexer->indexPage();
293 3
            $this->responseData['originalPageDocument'] = (array)$indexer->getPageSolrDocument();
294 3
            $this->responseData['solrConnection'] = array(
295 3
                'rootPage' => $indexQueueItem->getRootPageUid(),
296 3
                'sys_language_uid' => $GLOBALS['TSFE']->sys_language_uid,
297 3
                'solr' => (string)$solrConnection
298
            );
299
300 3
            $documentsSentToSolr = $indexer->getDocumentsSentToSolr();
301 3
            foreach ($documentsSentToSolr as $document) {
302 3
                $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 3
        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 3
    }
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 3
    protected function getSolrConnection(Item $indexQueueItem)
329
    {
330
        /** @var $connectionManager ConnectionManager */
331 3
        $connectionManager = GeneralUtility::makeInstance(ConnectionManager::class);
332
333 3
        $solrConnection = $connectionManager->getConnectionByRootPageId(
334 3
            $indexQueueItem->getRootPageUid(),
335 3
            $GLOBALS['TSFE']->sys_language_uid
336
        );
337
338 3
        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 3
    protected function getIndexQueueItem()
347
    {
348
        /** @var $indexQueue Queue */
349 3
        $indexQueue = GeneralUtility::makeInstance(Queue::class);
350 3
        $indexQueueItem = $indexQueue->getItem($this->request->getParameter('item'));
351 3
        return $indexQueueItem;
352
    }
353
}
354