Passed
Push — release-11.2.x ( e68ea3...8442ea )
by Rafael
12:54
created

getHighestAuthenticationServicePriority()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4.7691

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 13
ccs 7
cts 11
cp 0.6364
rs 10
c 0
b 0
f 0
cc 4
nc 2
nop 0
crap 4.7691
1
<?php
2
3
namespace ApacheSolrForTypo3\Solr\IndexQueue\FrontendHelper;
4
5
/***************************************************************
6
 *  Copyright notice
7
 *
8
 *  (c) 2011-2015 Ingo Renner <[email protected]>
9
 *  All rights reserved
10
 *
11
 *  This script is part of the TYPO3 project. The TYPO3 project is
12
 *  free software; you can redistribute it and/or modify
13
 *  it under the terms of the GNU General Public License as published by
14
 *  the Free Software Foundation; either version 3 of the License, or
15
 *  (at your option) any later version.
16
 *
17
 *  The GNU General Public License can be found at
18
 *  http://www.gnu.org/copyleft/gpl.html.
19
 *
20
 *  This script is distributed in the hope that it will be useful,
21
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 *  GNU General Public License for more details.
24
 *
25
 *  This copyright notice MUST APPEAR in all copies of the script!
26
 ***************************************************************/
27
28
use ApacheSolrForTypo3\Solr\Access\Rootline;
29
use ApacheSolrForTypo3\Solr\ConnectionManager;
30
use ApacheSolrForTypo3\Solr\IndexQueue\Item;
31
use ApacheSolrForTypo3\Solr\IndexQueue\Queue;
32
use ApacheSolrForTypo3\Solr\NoSolrConnectionFoundException;
33
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
34
use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection;
35
use ApacheSolrForTypo3\Solr\Typo3PageIndexer;
36
use ApacheSolrForTypo3\Solr\Util;
37
use Exception;
38
use TYPO3\CMS\Core\Log\Logger;
39
use TYPO3\CMS\Core\SingletonInterface;
40
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
41
use TYPO3\CMS\Core\Utility\GeneralUtility;
42
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
43
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
44
use UnexpectedValueException;
45
46
/**
47
 * Index Queue Page Indexer frontend helper to ask the frontend page indexer to
48
 * index the page.
49
 *
50
 * @author Ingo Renner <[email protected]>
51
 */
52
class PageIndexer extends AbstractFrontendHelper implements SingletonInterface
53
{
54
55
    /**
56
     * This frontend helper's executed action.
57
     *
58
     * @var string
59
     */
60
    protected $action = 'indexPage';
61
62
    /**
63
     * the page currently being indexed.
64
     *
65
     * @var TypoScriptFrontendController
66
     */
67
    protected $page;
68
69
    /**
70
     * Response data
71
     *
72
     * @var array
73
     */
74
    protected $responseData = [];
75
76
    /**
77
     * @var Logger
78
     */
79
    protected $logger = null;
80
81
    /**
82
     * Activates a frontend helper by registering for hooks and other
83
     * resources required by the frontend helper to work.
84
     *
85
     * @noinspection PhpUnused
86
     */
87 10
    public function activate()
88
    {
89 10
        $pageIndexingHookRegistration = PageIndexer::class;
90
91 10
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['pageIndexing'][__CLASS__] = $pageIndexingHookRegistration;
92
93
        // indexes fields defined in plugin.tx_solr.index.queue.pages.fields
94 10
        $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['Indexer']['indexPageSubstitutePageDocument'][PageFieldMappingIndexer::class] = PageFieldMappingIndexer::class;
95
96 10
        $this->registerAuthorizationService();
97 10
    }
98
99
    /**
100
     * Returns the status of whether a page was indexed.
101
     *
102
     * @return array Page indexed status.
103
     * @noinspection PhpUnused
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
     * @noinspection PhpUnused
119
     */
120
    public function authorizeFrontendUser()
121
    {
122
        $accessRootline = $this->getAccessRootline();
123
        $stringAccessRootline = (string)$accessRootline;
124
125
        if (empty($stringAccessRootline)) {
126
            return;
127
        }
128
129
        if (!is_array($GLOBALS['TSFE']->fe_user->user)) {
130
            $GLOBALS['TSFE']->fe_user->user = [];
131
        }
132
133
        $groups = $accessRootline->getGroups();
134
        $groupList = implode(',', $groups);
135
136
        $GLOBALS['TSFE']->fe_user->user['username'] = AuthorizationService::SOLR_INDEXER_USERNAME;
137
        $GLOBALS['TSFE']->fe_user->user['usergroup'] = $groupList;
138
139
        $this->responseData['authorization'] = [
140
            'username' => $GLOBALS['TSFE']->fe_user->user['username'],
141
            'usergroups' => $GLOBALS['TSFE']->fe_user->user['usergroup']
142
        ];
143
    }
144
145
    /**
146
     * Gets the access rootline as defined by the request.
147
     *
148
     * @return Rootline The access rootline to use for indexing.
149
     */
150 10
    protected function getAccessRootline()
151
    {
152 10
        $stringAccessRootline = '';
153
154 10
        if ($this->request->getParameter('accessRootline')) {
155
            $stringAccessRootline = $this->request->getParameter('accessRootline');
156
        }
157
158
        /** @noinspection PhpIncompatibleReturnTypeInspection */
159 10
        return GeneralUtility::makeInstance(Rootline::class, /** @scrutinizer ignore-type */ $stringAccessRootline);
160
    }
161
162
    /**
163
     * Registers an authentication service to authorize / grant the indexer to
164
     * access protected pages.
165
     *
166
     * @return void
167
     */
168 10
    protected function registerAuthorizationService()
169
    {
170 10
        $overrulingPriority = $this->getHighestAuthenticationServicePriority() + 1;
171
172 10
        ExtensionManagementUtility::addService(
173
            'solr', // extension key
174
            'auth', // service type
175
            AuthorizationService::class,
176
            // service key
177
            [// service meta data
178 10
                'title' => 'Solr Indexer Authorization',
179 10
                'description' => 'Authorizes the Solr Index Queue indexer to access protected pages.',
180
181 10
                'subtype' => 'getUserFE,authUserFE,getGroupsFE',
182
183
                'available' => true,
184 10
                'priority' => $overrulingPriority,
185 10
                'quality' => 100,
186
187 10
                'os' => '',
188 10
                'exec' => '',
189
190 10
                'classFile' => ExtensionManagementUtility::extPath('solr') . 'Classes/IndexQueue/FrontendHelper/AuthorizationService.php',
191
                'className' => AuthorizationService::class,
192
            ]
193
        );
194 10
    }
195
196
    /**
197
     * Determines the highest priority of all registered authentication
198
     * services.
199
     *
200
     * @return int Highest priority of all registered authentication service
201
     */
202 10
    protected function getHighestAuthenticationServicePriority()
203
    {
204 10
        $highestPriority = 0;
205
206 10
        if (is_array($GLOBALS['T3_SERVICES']['auth'])) {
207 10
            foreach ($GLOBALS['T3_SERVICES']['auth'] as $service) {
208 10
                if ($service['priority'] > $highestPriority) {
209 10
                    $highestPriority = $service['priority'];
210
                }
211
            }
212
        }
213
214 10
        return $highestPriority;
215
    }
216
217
    #
218
    # Indexing
219
    #
220
221
    /**
222
     * Generates the current page's URL.
223
     *
224
     * Uses the provided GET parameters, page id and language id.
225
     *
226
     * @return string URL of the current page.
227
     */
228 10
    protected function generatePageUrl()
229
    {
230 10
        if ($this->request->getParameter('overridePageUrl')) {
231
            return $this->request->getParameter('overridePageUrl');
232
        }
233
234
            /** @var $contentObject ContentObjectRenderer */
235 10
        $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
236
237
        $typolinkConfiguration = [
238 10
            'parameter' => intval($this->page->id),
239 10
            'linkAccessRestrictedPages' => '1'
240
        ];
241
242 10
        $language = GeneralUtility::_GET('L');
243 10
        if (!empty($language)) {
244
            $typolinkConfiguration['additionalParams'] = '&L=' . $language;
245
        }
246
247 10
        $url = $contentObject->typoLink_URL($typolinkConfiguration);
248
249
        // clean up
250 10
        if ($url == '') {
251
            $url = '/';
252
        }
253
254 10
        return $url;
255
    }
256
257
    /**
258
     * Handles the indexing of the page content during post processing of a
259
     * generated page.
260
     *
261
     * @param TypoScriptFrontendController $page TypoScript frontend
262
     * @noinspection PhpUnused
263
     */
264 10
    public function hook_indexContent(TypoScriptFrontendController $page)
265
    {
266 10
        $this->logger = GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__);
267
268 10
        $this->page = $page;
269 10
        $configuration = Util::getSolrConfiguration();
270
271 10
        $logPageIndexed = $configuration->getLoggingIndexingPageIndexed();
272 10
        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 10
            $indexQueueItem = $this->getIndexQueueItem();
284 10
            if (is_null($indexQueueItem)) {
285
                throw new UnexpectedValueException('Can not get index queue item', 1482162337);
286
            }
287
288 10
            $solrConnection = $this->getSolrConnection($indexQueueItem);
289
290
            /** @var $indexer Typo3PageIndexer */
291 10
            $indexer = GeneralUtility::makeInstance(Typo3PageIndexer::class, /** @scrutinizer ignore-type */ $page);
292 10
            $indexer->setSolrConnection($solrConnection);
293 10
            $indexer->setPageAccessRootline($this->getAccessRootline());
294 10
            $indexer->setPageUrl($this->generatePageUrl());
295 10
            $indexer->setMountPointParameter($GLOBALS['TSFE']->MP);
296 10
            $indexer->setIndexQueueItem($indexQueueItem);
297
298 10
            $this->responseData['pageIndexed'] = (int)$indexer->indexPage();
299 10
            $this->responseData['originalPageDocument'] = (array)$indexer->getPageSolrDocument();
300 10
            $this->responseData['solrConnection'] = [
301 10
                'rootPage' => $indexQueueItem->getRootPageUid(),
302 10
                'sys_language_uid' => Util::getLanguageUid(),
303 10
                'solr' => (string)$solrConnection->getNode('write')
304
            ];
305
306 10
            $documentsSentToSolr = $indexer->getDocumentsSentToSolr();
307 10
            foreach ($documentsSentToSolr as $document) {
308 10
                $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 10
        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 10
    }
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
     * @throws NoSolrConnectionFoundException
341
     */
342 10
    protected function getSolrConnection(Item $indexQueueItem)
343
    {
344
        /** @var $connectionManager ConnectionManager */
345 10
        $connectionManager = GeneralUtility::makeInstance(ConnectionManager::class);
346
347 10
        return $connectionManager->getConnectionByRootPageId(
348 10
            $indexQueueItem->getRootPageUid(),
349 10
            Util::getLanguageUid()
350
        );
351
    }
352
353
    /**
354
     * This method retrieves the item from the index queue, that is indexed in this request.
355
     *
356
     * @return Item
357
     */
358 10
    protected function getIndexQueueItem()
359
    {
360
        /** @var $indexQueue Queue */
361 10
        $indexQueue = GeneralUtility::makeInstance(Queue::class);
362 10
        return $indexQueue->getItem($this->request->getParameter('item'));
363
    }
364
}
365