Passed
Push — master ( 14b490...3d7c7d )
by Timo
23:43
created

Util::initializeTsfe()   B

Complexity

Conditions 7
Paths 20

Size

Total Lines 59
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 7.0012

Importance

Changes 0
Metric Value
eloc 33
dl 0
loc 59
ccs 33
cts 34
cp 0.9706
rs 8.4586
c 0
b 0
f 0
cc 7
nc 20
nop 3
crap 7.0012

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace ApacheSolrForTypo3\Solr;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2009-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\Domain\Site\SiteRepository;
28
use ApacheSolrForTypo3\Solr\System\Cache\TwoLevelCache;
29
use ApacheSolrForTypo3\Solr\System\Configuration\ConfigurationManager;
30
use ApacheSolrForTypo3\Solr\System\Configuration\ConfigurationPageResolver;
31
use ApacheSolrForTypo3\Solr\System\Configuration\ExtensionConfiguration;
32
use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration;
33
use ApacheSolrForTypo3\Solr\System\TCA\TCAService;
34
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
35
use ApacheSolrForTypo3\Solr\System\Mvc\Frontend\Controller\OverriddenTypoScriptFrontendController;
36
use TYPO3\CMS\Backend\Utility\BackendUtility;
37
use TYPO3\CMS\Core\TimeTracker\TimeTracker;
38
use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
39
use TYPO3\CMS\Core\Utility\GeneralUtility;
40
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
41
use TYPO3\CMS\Frontend\Page\PageRepository;
42
43
/**
44
 * Utility class for tx_solr
45
 *
46
 * @author Ingo Renner <[email protected]>
47
 */
48
class Util
49
{
50
51
    /**
52
     * Generates a document id for documents representing page records.
53
     *
54
     * @param int $uid The page's uid
55
     * @param int $typeNum The page's typeNum
56
     * @param int $language the language id, defaults to 0
57
     * @param string $accessGroups comma separated list of uids of groups that have access to that page
58
     * @param string $mountPointParameter The mount point parameter that is used to access the page.
59
     * @return string The document id for that page
60
     */
61 68
    public static function getPageDocumentId($uid, $typeNum = 0, $language = 0, $accessGroups = '0,-1', $mountPointParameter = '')
62
    {
63 68
        $additionalParameters = $typeNum . '/' . $language . '/' . $accessGroups;
64
65 68
        if ((string)$mountPointParameter !== '') {
66 2
            $additionalParameters = $mountPointParameter . '/' . $additionalParameters;
67
        }
68
69 68
        $documentId = self::getDocumentId('pages', $uid, $uid, $additionalParameters);
70
71 68
        return $documentId;
72
    }
73
74
    /**
75
     * Generates a document id in the form $siteHash/$type/$uid.
76
     *
77
     * @param string $table The records table name
78
     * @param int $rootPageId The record's site root id
79
     * @param int $uid The record's uid
80
     * @param string $additionalIdParameters Additional ID parameters
81
     * @return string A document id
82
     */
83 88
    public static function getDocumentId($table, $rootPageId, $uid, $additionalIdParameters = '')
84
    {
85 88
        $siteRepository = GeneralUtility::makeInstance(SiteRepository::class);
86 88
        $site = $siteRepository->getSiteByPageId($rootPageId);
87 88
        $siteHash = $site->getSiteHash();
88
89 88
        $documentId = $siteHash . '/' . $table . '/' . $uid;
90 88
        if (!empty($additionalIdParameters)) {
91 68
            $documentId .= '/' . $additionalIdParameters;
92
        }
93
94 88
        return $documentId;
95
    }
96
97
    /**
98
     * Shortcut to retrieve the TypoScript configuration for EXT:solr
99
     * (plugin.tx_solr) from TSFE.
100
     *
101
     * @return TypoScriptConfiguration
102
     */
103 201
    public static function getSolrConfiguration()
104
    {
105 201
        $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
106 201
        return $configurationManager->getTypoScriptConfiguration();
107
    }
108
109
    /**
110
     * Gets the Solr configuration for a specific root page id.
111
     * To be used from the backend.
112
     *
113
     * @param int $pageId Id of the (root) page to get the Solr configuration from.
114
     * @param bool $initializeTsfe Optionally initializes a full TSFE to get the configuration, defaults to FALSE
115
     * @param int $language System language uid, optional, defaults to 0
116
     * @return TypoScriptConfiguration The Solr configuration for the requested tree.
117
     */
118 157
    public static function getSolrConfigurationFromPageId($pageId, $initializeTsfe = false, $language = 0)
119
    {
120 157
        $rootPath = '';
121 157
        return self::getConfigurationFromPageId($pageId, $rootPath, $initializeTsfe, $language);
122
    }
123
124
    /**
125
     * Loads the TypoScript configuration for a given page id and language.
126
     * Language usage may be disabled to get the default TypoScript
127
     * configuration.
128
     *
129
     * @param int $pageId Id of the (root) page to get the Solr configuration from.
130
     * @param string $path The TypoScript configuration path to retrieve.
131
     * @param bool $initializeTsfe Optionally initializes a full TSFE to get the configuration, defaults to FALSE
132
     * @param int $language System language uid, optional, defaults to 0
133
     * @param bool $useTwoLevelCache Flag to enable the two level cache for the typoscript configuration array
134
     * @return TypoScriptConfiguration The Solr configuration for the requested tree.
135
     */
136 158
    public static function getConfigurationFromPageId($pageId, $path, $initializeTsfe = false, $language = 0, $useTwoLevelCache = true)
137
    {
138 158
        $pageId = self::getConfigurationPageIdToUse($pageId);
139
140 158
        static $configurationObjectCache = [];
141 158
        $cacheId = md5($pageId . '|' . $path . '|' . $language . '|' . ($initializeTsfe ? '1' : '0'));
142 158
        if (isset($configurationObjectCache[$cacheId])) {
143 71
            return $configurationObjectCache[$cacheId];
144
        }
145
146
        // If we're on UID 0, we cannot retrieve a configuration currently.
147
        // getRootline() below throws an exception (since #typo3-60 )
148
        // as UID 0 cannot have any parent rootline by design.
149 158
        if ($pageId == 0) {
150 3
            return $configurationObjectCache[$cacheId] = self::buildTypoScriptConfigurationFromArray([], $pageId, $language, $path);
151
        }
152
153 156
        if ($useTwoLevelCache) {
154
            /** @var $cache TwoLevelCache */
155 156
            $cache = GeneralUtility::makeInstance(TwoLevelCache::class, /** @scrutinizer ignore-type */ 'tx_solr_configuration');
156 156
            $configurationArray = $cache->get($cacheId);
157
        }
158
159 156
        if (!empty($configurationArray)) {
160
            // we have a cache hit and can return it.
161
            return $configurationObjectCache[$cacheId] = self::buildTypoScriptConfigurationFromArray($configurationArray, $pageId, $language, $path);
162
        }
163
164
        // we have nothing in the cache. We need to build the configurationToUse
165 156
        $configurationArray = self::buildConfigurationArray($pageId, $path, $initializeTsfe, $language);
166
167 156
        if ($useTwoLevelCache && isset($cache)) {
168 156
            $cache->set($cacheId, $configurationArray);
169
        }
170
171 156
        return $configurationObjectCache[$cacheId] = self::buildTypoScriptConfigurationFromArray($configurationArray, $pageId, $language, $path);
172
    }
173
174
    /**
175
     * This method retrieves the closest pageId where a configuration is located, when this
176
     * feature is enabled.
177
     *
178
     * @param int $pageId
179
     * @return int
180
     */
181 158
    protected static function getConfigurationPageIdToUse($pageId)
182
    {
183 158
        $extensionConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class);
184 158
        if ($extensionConfiguration->getIsUseConfigurationFromClosestTemplateEnabled()) {
185
            /** @var $configurationPageResolve ConfigurationPageResolver */
186
            $configurationPageResolver = GeneralUtility::makeInstance(ConfigurationPageResolver::class);
187
            $pageId = $configurationPageResolver->getClosestPageIdWithActiveTemplate($pageId);
188
            return $pageId;
189
        }
190 158
        return $pageId;
191
    }
192
193
    /**
194
     * Initializes a TSFE, if required and builds an configuration array, containing the solr configuration.
195
     *
196
     * @param integer $pageId
197
     * @param string $path
198
     * @param boolean $initializeTsfe
199
     * @param integer $language
200
     * @return array
201
     */
202 156
    protected static function buildConfigurationArray($pageId, $path, $initializeTsfe, $language)
203
    {
204 156
        if ($initializeTsfe) {
205 19
            self::initializeTsfe($pageId, $language);
206 19
            $configurationToUse = self::getConfigurationFromInitializedTSFE($path);
207
        } else {
208 156
            $configurationToUse = self::getConfigurationFromExistingTSFE($pageId, $path, $language);
209
        }
210
211 156
        return is_array($configurationToUse) ? $configurationToUse : [];
212
    }
213
214
    /**
215
     * Builds the configuration object from a config array and returns it.
216
     *
217
     * @param array $configurationToUse
218
     * @param int $pageId
219
     * @param int $languageId
220
     * @param string $typoScriptPath
221
     * @return TypoScriptConfiguration
222
     */
223 158
    protected static function buildTypoScriptConfigurationFromArray(array $configurationToUse, $pageId, $languageId, $typoScriptPath)
224
    {
225 158
        $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
226 158
        return $configurationManager->getTypoScriptConfiguration($configurationToUse, $pageId, $languageId, $typoScriptPath);
227
    }
228
229
    /**
230
     * This function is used to retrieve the configuration from a previous initialized TSFE
231
     * (see: getConfigurationFromPageId)
232
     *
233
     * @param string $path
234
     * @return mixed
235
     */
236 19
    private static function getConfigurationFromInitializedTSFE($path)
237
    {
238
        /** @var $tmpl ExtendedTemplateService */
239 19
        $tmpl = GeneralUtility::makeInstance(ExtendedTemplateService::class);
240 19
        $configuration = $tmpl->ext_getSetup($GLOBALS['TSFE']->tmpl->setup, $path);
241 19
        $configurationToUse = $configuration[0];
242 19
        return $configurationToUse;
243
    }
244
245
    /**
246
     * This function is used to retrieve the configuration from an existing TSFE instance
247
     *
248
     * @param $pageId
249
     * @param $path
250
     * @param $language
251
     * @return mixed
252
     */
253 156
    private static function getConfigurationFromExistingTSFE($pageId, $path, $language)
254
    {
255 156
        if (is_int($language)) {
256 156
            GeneralUtility::_GETset($language, 'L');
257
        }
258
259
            /** @var $pageSelect PageRepository */
260 156
        $pageSelect = GeneralUtility::makeInstance(PageRepository::class);
261 156
        $rootLine = $pageSelect->getRootLine($pageId);
262
263 156
        $initializedTsfe = false;
264 156
        $initializedPageSelect = false;
265 156
        if (empty($GLOBALS['TSFE']->sys_page)) {
266 84
            if (empty($GLOBALS['TSFE'])) {
267 84
                $GLOBALS['TSFE'] = new \stdClass();
268 84
                $GLOBALS['TSFE']->tmpl = new \stdClass();
269 84
                $GLOBALS['TSFE']->tmpl->rootLine = $rootLine;
270 84
                $GLOBALS['TSFE']->sys_page = $pageSelect;
271 84
                $GLOBALS['TSFE']->id = $pageId;
272 84
                $GLOBALS['TSFE']->tx_solr_initTsfe = 1;
273 84
                $initializedTsfe = true;
274
            }
275
276 84
            $GLOBALS['TSFE']->sys_page = $pageSelect;
277 84
            $initializedPageSelect = true;
278
        }
279
            /** @var $tmpl ExtendedTemplateService */
280 156
        $tmpl = GeneralUtility::makeInstance(ExtendedTemplateService::class);
281 156
        $tmpl->tt_track = false; // Do not log time-performance information
282 156
        $tmpl->init();
283 156
        $tmpl->runThroughTemplates($rootLine); // This generates the constants/config + hierarchy info for the template.
284 156
        $tmpl->generateConfig();
285
286 156
        $getConfigurationFromInitializedTSFEAndWriteToCache = $tmpl->ext_getSetup($tmpl->setup, $path);
287 156
        $configurationToUse = $getConfigurationFromInitializedTSFEAndWriteToCache[0];
288
289 156
        if ($initializedPageSelect) {
290 84
            $GLOBALS['TSFE']->sys_page = null;
291
        }
292 156
        if ($initializedTsfe) {
293 84
            unset($GLOBALS['TSFE']);
294
        }
295 156
        return $configurationToUse;
296
    }
297
298
    /**
299
     * Initializes the TSFE for a given page ID and language.
300
     *
301
     * @param int $pageId The page id to initialize the TSFE for
302
     * @param int $language System language uid, optional, defaults to 0
303
     * @param bool $useCache Use cache to reuse TSFE
304
     * @todo When we drop TYPO3 8 support we should use a middleware stack to initialize a TSFE for our needs
305
     * @return void
306
     */
307 24
    public static function initializeTsfe($pageId, $language = 0, $useCache = true)
308
    {
309 24
        static $tsfeCache = [];
310
311
        // resetting, a TSFE instance with data from a different page Id could be set already
312 24
        unset($GLOBALS['TSFE']);
313
314 24
        $cacheId = $pageId . '|' . $language;
315
316 24
        if (!is_object($GLOBALS['TT'])) {
317 24
            $GLOBALS['TT'] = GeneralUtility::makeInstance(TimeTracker::class, false);
318
        }
319
320 24
        if (!isset($tsfeCache[$cacheId]) || !$useCache) {
321 24
            GeneralUtility::_GETset($language, 'L');
322
323
324 24
            $GLOBALS['TSFE'] = GeneralUtility::makeInstance(OverriddenTypoScriptFrontendController::class, $GLOBALS['TYPO3_CONF_VARS'], $pageId, 0);
325
326
            // for certain situations we need to trick TSFE into granting us
327
            // access to the page in any case to make getPageAndRootline() work
328
            // see http://forge.typo3.org/issues/42122
329 24
            $pageRecord = BackendUtility::getRecord('pages', $pageId, 'fe_group');
330 24
            $groupListBackup = $GLOBALS['TSFE']->gr_list;
331 24
            $GLOBALS['TSFE']->gr_list = $pageRecord['fe_group'];
332
333 24
            $GLOBALS['TSFE']->sys_page = GeneralUtility::makeInstance(PageRepository::class);
334 24
            self::getPageAndRootlineOfTSFE($pageId);
0 ignored issues
show
Deprecated Code introduced by
The function ApacheSolrForTypo3\Solr\...PageAndRootlineOfTSFE() has been deprecated: This is only implemented to provide compatibility for TYPO3 8 and 9 when we drop TYPO3 8 support this should changed to use a middleware stack ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

334
            /** @scrutinizer ignore-deprecated */ self::getPageAndRootlineOfTSFE($pageId);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
335
336
            // restore gr_list
337 24
            $GLOBALS['TSFE']->gr_list = $groupListBackup;
338
339 24
            $GLOBALS['TSFE']->initTemplate();
340 24
            $GLOBALS['TSFE']->forceTemplateParsing = true;
341 24
            $GLOBALS['TSFE']->initFEuser();
342 24
            $GLOBALS['TSFE']->initUserGroups();
343
            //  $GLOBALS['TSFE']->getCompressedTCarray(); // seems to cause conflicts sometimes
0 ignored issues
show
Unused Code Comprehensibility introduced by
73% 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...
344
345 24
            $GLOBALS['TSFE']->no_cache = true;
346 24
            $GLOBALS['TSFE']->tmpl->start($GLOBALS['TSFE']->rootLine);
347 24
            $GLOBALS['TSFE']->no_cache = false;
348 24
            $GLOBALS['TSFE']->getConfigArray();
349 24
            $GLOBALS['TSFE']->settingLanguage();
350 24
            if (!$useCache) {
351
                $GLOBALS['TSFE']->settingLocale();
352
            }
353
354 24
            $GLOBALS['TSFE']->newCObj();
355 24
            $GLOBALS['TSFE']->absRefPrefix = self::getAbsRefPrefixFromTSFE($GLOBALS['TSFE']);
356 24
            $GLOBALS['TSFE']->calculateLinkVars();
357
358 24
            if ($useCache) {
359 24
                $tsfeCache[$cacheId] = $GLOBALS['TSFE'];
360
            }
361
        }
362
363 24
        if ($useCache) {
364 24
            $GLOBALS['TSFE'] = $tsfeCache[$cacheId];
365 24
            $GLOBALS['TSFE']->settingLocale();
366
        }
367 24
    }
368
369
    /**
370
     * @deprecated This is only implemented to provide compatibility for TYPO3 8 and 9 when we drop TYPO3 8 support this
371
     * should changed to use a middleware stack
372
     * @param integer $pageId
373
     */
374 24
    private static function getPageAndRootlineOfTSFE($pageId)
375
    {
376
        //@todo This can be dropped when TYPO3 8 compatibility is dropped
377 24
        if (Util::getIsTYPO3VersionBelow9()) {
378 24
            $GLOBALS['TSFE']->getPageAndRootline();
379
        } else {
380
            //@todo When we drop the support of TYPO3 8 we should use the frontend middleware stack instead of initializing this on our own
381
            /** @var $siteRepository SiteRepository */
382
            $siteRepository = GeneralUtility::makeInstance(SiteRepository::class);
383
            $site = $siteRepository->getSiteByPageId($pageId);
384
            $GLOBALS['TSFE']->getPageAndRootlineWithDomain($site->getRootPageId());
385
        }
386 24
    }
387
388
    /**
389
     * Check if record ($table, $uid) is a workspace record
390
     *
391
     * @param string $table The table the record belongs to
392
     * @param int $uid The record's uid
393
     * @return bool TRUE if the record is in a draft workspace, FALSE if it's a LIVE record
394
     */
395 40
    public static function isDraftRecord($table, $uid)
396
    {
397 40
        $isWorkspaceRecord = false;
398
399 40
        if ((ExtensionManagementUtility::isLoaded('workspaces')) && (BackendUtility::isTableWorkspaceEnabled($table))) {
400
            $record = BackendUtility::getRecord($table, $uid, 'pid, t3ver_state');
401
402
            if ($record['pid'] == '-1' || $record['t3ver_state'] > 0) {
403
                $isWorkspaceRecord = true;
404
            }
405
        }
406
407 40
        return $isWorkspaceRecord;
408
    }
409
410
    /**
411
     * Check if the page type of a page record is allowed
412
     *
413
     * @param array $pageRecord The pages database row
414
     * @param string $configurationName The name of the configuration to use.
415
     *
416
     * @return bool TRUE if the page type is allowed, otherwise FALSE
417
     */
418 30
    public static function isAllowedPageType(array $pageRecord, $configurationName = 'pages')
419
    {
420 30
        $isAllowedPageType = false;
421 30
        $configurationName = $configurationName ?? 'pages';
422 30
        $allowedPageTypes = self::getAllowedPageTypes($pageRecord['uid'], $configurationName);
423
424 30
        if (in_array($pageRecord['doktype'], $allowedPageTypes)) {
425 29
            $isAllowedPageType = true;
426
        }
427
428 30
        return $isAllowedPageType;
429
    }
430
431
    /**
432
     * Get allowed page types
433
     *
434
     * @param int $pageId Page ID
435
     * @param string $configurationName The name of the configuration to use.
436
     *
437
     * @return array Allowed page types to compare to a doktype of a page record
438
     */
439 30
    public static function getAllowedPageTypes($pageId, $configurationName = 'pages')
440
    {
441 30
        $rootPath = '';
442 30
        $configuration = self::getConfigurationFromPageId($pageId, $rootPath);
443 30
        return $configuration->getIndexQueueAllowedPageTypesArrayByConfigurationName($configurationName);
444
    }
445
446
    /**
447
     * Resolves the configured absRefPrefix to a valid value and resolved if absRefPrefix
448
     * is set to "auto".
449
     *
450
     * @param TypoScriptFrontendController $TSFE
451
     * @return string
452
     */
453 24
    public static function getAbsRefPrefixFromTSFE(TypoScriptFrontendController $TSFE)
454
    {
455 24
        $absRefPrefix = '';
456 24
        if (empty($TSFE->config['config']['absRefPrefix'])) {
457 21
            return $absRefPrefix;
458
        }
459
460 3
        $absRefPrefix = trim($TSFE->config['config']['absRefPrefix']);
461 3
        if ($absRefPrefix === 'auto') {
462 1
            $absRefPrefix = GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
463
        }
464
465 3
        return $absRefPrefix;
466
    }
467
468
    /**
469
     * @todo This method is just added for pages_language_overlay compatibility checks and will be removed when TYPO8 support is dropped
470
     * @return boolean
471
     */
472 247
    public static function getIsTYPO3VersionBelow9()
473
    {
474 247
        return (bool)version_compare(TYPO3_branch, '9.0', '<');
475
    }
476
477
    /**
478
     * @todo This method is just added for pages_language_overlay compatibility checks and will be removed when TYPO8 support is dropped
479
     * @return string
480
     */
481
    public static function getPageOverlayTableName()
482
    {
483
        return self::getIsTYPO3VersionBelow9() ? 'pages_language_overlay' : 'pages';
484
    }
485
486
    /**
487
     * This function can be used to check if one of the strings in needles is
488
     * contained in the haystack.
489
     *
490
     *
491
     * Example:
492
     *
493
     * haystack: the brown fox
494
     * needles: ['hello', 'world']
495
     * result: false
496
     *
497
     * haystack: the brown fox
498
     * needles: ['is', 'fox']
499
     * result: true
500
     *
501
     * @param string $haystack
502
     * @param array $needles
503
     * @return bool
504
     */
505 54
    public static function containsOneOfTheStrings($haystack, array $needles)
506
    {
507 54
        foreach ($needles as $needle) {
508 54
            $position = strpos($haystack, $needle);
509 54
            if ($position !== false) {
510 54
                return true;
511
            }
512
        }
513
514 51
        return false;
515
    }
516
}
517