Passed
Push — master ( f55a40...3301f5 )
by Timo
23:56
created

Util   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 464
Duplicated Lines 0 %

Test Coverage

Coverage 91.46%

Importance

Changes 0
Metric Value
wmc 52
dl 0
loc 464
ccs 150
cts 164
cp 0.9146
rs 7.9487
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A getDocumentId() 0 12 2
A isAllowedPageType() 0 11 2
B getConfigurationFromExistingTSFE() 0 43 6
A getAllowedPageTypes() 0 5 1
B isDraftRecord() 0 13 5
C getConfigurationFromPageId() 0 36 8
A getPageOverlayTableName() 0 3 2
A getAbsRefPrefixFromTSFE() 0 13 3
A getIsTYPO3VersionBelow9() 0 3 1
A getConfigurationFromInitializedTSFE() 0 7 1
A getSolrConfigurationFromPageId() 0 4 1
A getPageDocumentId() 0 11 2
A getSolrConfiguration() 0 4 1
A containsOneOfTheStrings() 0 10 3
A buildTypoScriptConfigurationFromArray() 0 4 1
A isLocalizedRecord() 0 7 1
A buildConfigurationArray() 0 10 3
A getConfigurationPageIdToUse() 0 10 2
B initializeTsfe() 0 60 7

How to fix   Complexity   

Complex Class

Complex classes like Util often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Util, and based on these observations, apply Extract Interface, too.

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\Index\Queue\RecordMonitor\Helper\RootPageResolver;
28
use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository;
29
use ApacheSolrForTypo3\Solr\Domain\Site\SiteHashService;
30
use ApacheSolrForTypo3\Solr\System\Cache\TwoLevelCache;
31
use ApacheSolrForTypo3\Solr\System\Configuration\ConfigurationManager;
32
use ApacheSolrForTypo3\Solr\System\Configuration\ConfigurationPageResolver;
33
use ApacheSolrForTypo3\Solr\System\Configuration\ExtensionConfiguration;
34
use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration;
35
use ApacheSolrForTypo3\Solr\System\DateTime\FormatService;
36
use ApacheSolrForTypo3\Solr\System\TCA\TCAService;
37
use TYPO3\CMS\Backend\Utility\BackendUtility;
38
use TYPO3\CMS\Core\TimeTracker\TimeTracker;
39
use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
40
use TYPO3\CMS\Core\Utility\GeneralUtility;
41
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
42
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
43
use TYPO3\CMS\Frontend\Page\PageRepository;
44
45
/**
46
 * Utility class for tx_solr
47
 *
48
 * @author Ingo Renner <[email protected]>
49
 */
50
class Util
51
{
52
53
    /**
54
     * Generates a document id for documents representing page records.
55
     *
56
     * @param int $uid The page's uid
57
     * @param int $typeNum The page's typeNum
58
     * @param int $language the language id, defaults to 0
59
     * @param string $accessGroups comma separated list of uids of groups that have access to that page
60
     * @param string $mountPointParameter The mount point parameter that is used to access the page.
61
     * @return string The document id for that page
62
     */
63 66
    public static function getPageDocumentId($uid, $typeNum = 0, $language = 0, $accessGroups = '0,-1', $mountPointParameter = '')
64
    {
65 66
        $additionalParameters = $typeNum . '/' . $language . '/' . $accessGroups;
66
67 66
        if ((string)$mountPointParameter !== '') {
68 2
            $additionalParameters = $mountPointParameter . '/' . $additionalParameters;
69
        }
70
71 66
        $documentId = self::getDocumentId('pages', $uid, $uid, $additionalParameters);
72
73 66
        return $documentId;
74
    }
75
76
    /**
77
     * Generates a document id in the form $siteHash/$type/$uid.
78
     *
79
     * @param string $table The records table name
80
     * @param int $rootPageId The record's site root id
81
     * @param int $uid The record's uid
82
     * @param string $additionalIdParameters Additional ID parameters
83
     * @return string A document id
84
     */
85 85
    public static function getDocumentId($table, $rootPageId, $uid, $additionalIdParameters = '')
86
    {
87 85
        $siteRepository = GeneralUtility::makeInstance(SiteRepository::class);
88 85
        $site = $siteRepository->getSiteByPageId($rootPageId);
89 85
        $siteHash = $site->getSiteHash();
90
91 85
        $documentId = $siteHash . '/' . $table . '/' . $uid;
92 85
        if (!empty($additionalIdParameters)) {
93 66
            $documentId .= '/' . $additionalIdParameters;
94
        }
95
96 85
        return $documentId;
97
    }
98
99
    /**
100
     * Shortcut to retrieve the TypoScript configuration for EXT:solr
101
     * (plugin.tx_solr) from TSFE.
102
     *
103
     * @return TypoScriptConfiguration
104
     */
105 174
    public static function getSolrConfiguration()
106
    {
107 174
        $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
108 174
        return $configurationManager->getTypoScriptConfiguration();
109
    }
110
111
    /**
112
     * Gets the Solr configuration for a specific root page id.
113
     * To be used from the backend.
114
     *
115
     * @param int $pageId Id of the (root) page to get the Solr configuration from.
116
     * @param bool $initializeTsfe Optionally initializes a full TSFE to get the configuration, defaults to FALSE
117
     * @param int $language System language uid, optional, defaults to 0
118
     * @return TypoScriptConfiguration The Solr configuration for the requested tree.
119
     */
120 153
    public static function getSolrConfigurationFromPageId($pageId, $initializeTsfe = false, $language = 0)
121
    {
122 153
        $rootPath = '';
123 153
        return self::getConfigurationFromPageId($pageId, $rootPath, $initializeTsfe, $language);
124
    }
125
126
    /**
127
     * Loads the TypoScript configuration for a given page id and language.
128
     * Language usage may be disabled to get the default TypoScript
129
     * configuration.
130
     *
131
     * @param int $pageId Id of the (root) page to get the Solr configuration from.
132
     * @param string $path The TypoScript configuration path to retrieve.
133
     * @param bool $initializeTsfe Optionally initializes a full TSFE to get the configuration, defaults to FALSE
134
     * @param int $language System language uid, optional, defaults to 0
135
     * @param bool $useTwoLevelCache Flag to enable the two level cache for the typoscript configuration array
136
     * @return TypoScriptConfiguration The Solr configuration for the requested tree.
137
     */
138 154
    public static function getConfigurationFromPageId($pageId, $path, $initializeTsfe = false, $language = 0, $useTwoLevelCache = true)
139
    {
140 154
        $pageId = self::getConfigurationPageIdToUse($pageId);
141
142 154
        static $configurationObjectCache = [];
143 154
        $cacheId = md5($pageId . '|' . $path . '|' . $language . '|' . ($initializeTsfe ? '1' : '0'));
144 154
        if (isset($configurationObjectCache[$cacheId])) {
145 70
            return $configurationObjectCache[$cacheId];
146
        }
147
148
        // If we're on UID 0, we cannot retrieve a configuration currently.
149
        // getRootline() below throws an exception (since #typo3-60 )
150
        // as UID 0 cannot have any parent rootline by design.
151 154
        if ($pageId == 0) {
152 2
            return $configurationObjectCache[$cacheId] = self::buildTypoScriptConfigurationFromArray([], $pageId, $language, $path);
153
        }
154
155 153
        if ($useTwoLevelCache) {
156
            /** @var $cache TwoLevelCache */
157 153
            $cache = GeneralUtility::makeInstance(TwoLevelCache::class, /** @scrutinizer ignore-type */ 'tx_solr_configuration');
158 153
            $configurationArray = $cache->get($cacheId);
159
        }
160
161 153
        if (!empty($configurationArray)) {
162
            // we have a cache hit and can return it.
163
            return $configurationObjectCache[$cacheId] = self::buildTypoScriptConfigurationFromArray($configurationArray, $pageId, $language, $path);
164
        }
165
166
        // we have nothing in the cache. We need to build the configurationToUse
167 153
        $configurationArray = self::buildConfigurationArray($pageId, $path, $initializeTsfe, $language);
168
169 153
        if ($useTwoLevelCache && isset($cache)) {
170 153
            $cache->set($cacheId, $configurationArray);
171
        }
172
173 153
        return $configurationObjectCache[$cacheId] = self::buildTypoScriptConfigurationFromArray($configurationArray, $pageId, $language, $path);
174
    }
175
176
    /**
177
     * This method retrieves the closest pageId where a configuration is located, when this
178
     * feature is enabled.
179
     *
180
     * @param int $pageId
181
     * @return int
182
     */
183 154
    protected static function getConfigurationPageIdToUse($pageId)
184
    {
185 154
        $extensionConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class);
186 154
        if ($extensionConfiguration->getIsUseConfigurationFromClosestTemplateEnabled()) {
187
            /** @var $configurationPageResolve ConfigurationPageResolver */
188
            $configurationPageResolver = GeneralUtility::makeInstance(ConfigurationPageResolver::class);
189
            $pageId = $configurationPageResolver->getClosestPageIdWithActiveTemplate($pageId);
190
            return $pageId;
191
        }
192 154
        return $pageId;
193
    }
194
195
    /**
196
     * Initializes a TSFE, if required and builds an configuration array, containing the solr configuration.
197
     *
198
     * @param integer $pageId
199
     * @param string $path
200
     * @param boolean $initializeTsfe
201
     * @param integer $language
202
     * @return array
203
     */
204 153
    protected static function buildConfigurationArray($pageId, $path, $initializeTsfe, $language)
205
    {
206 153
        if ($initializeTsfe) {
207 18
            self::initializeTsfe($pageId, $language);
208 18
            $configurationToUse = self::getConfigurationFromInitializedTSFE($path);
209
        } else {
210 153
            $configurationToUse = self::getConfigurationFromExistingTSFE($pageId, $path, $language);
211
        }
212
213 153
        return is_array($configurationToUse) ? $configurationToUse : [];
214
    }
215
216
    /**
217
     * Builds the configuration object from a config array and returns it.
218
     *
219
     * @param array $configurationToUse
220
     * @param int $pageId
221
     * @param int $languageId
222
     * @param string $typoScriptPath
223
     * @return TypoScriptConfiguration
224
     */
225 154
    protected static function buildTypoScriptConfigurationFromArray(array $configurationToUse, $pageId, $languageId, $typoScriptPath)
226
    {
227 154
        $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
228 154
        return $configurationManager->getTypoScriptConfiguration($configurationToUse, $pageId, $languageId, $typoScriptPath);
229
    }
230
231
    /**
232
     * This function is used to retrieve the configuration from a previous initialized TSFE
233
     * (see: getConfigurationFromPageId)
234
     *
235
     * @param string $path
236
     * @return mixed
237
     */
238 18
    private static function getConfigurationFromInitializedTSFE($path)
239
    {
240
        /** @var $tmpl ExtendedTemplateService */
241 18
        $tmpl = GeneralUtility::makeInstance(ExtendedTemplateService::class);
242 18
        $configuration = $tmpl->ext_getSetup($GLOBALS['TSFE']->tmpl->setup, $path);
243 18
        $configurationToUse = $configuration[0];
244 18
        return $configurationToUse;
245
    }
246
247
    /**
248
     * This function is used to retrieve the configuration from an existing TSFE instance
249
     * @param $pageId
250
     * @param $path
251
     * @param $language
252
     * @return mixed
253
     */
254 153
    private static function getConfigurationFromExistingTSFE($pageId, $path, $language)
255
    {
256 153
        if (is_int($language)) {
257 153
            GeneralUtility::_GETset($language, 'L');
258
        }
259
260
            /** @var $pageSelect PageRepository */
261 153
        $pageSelect = GeneralUtility::makeInstance(PageRepository::class);
262 153
        $rootLine = $pageSelect->getRootLine($pageId);
263
264 153
        $initializedTsfe = false;
265 153
        $initializedPageSelect = false;
266 153
        if (empty($GLOBALS['TSFE']->sys_page)) {
267 83
            if (empty($GLOBALS['TSFE'])) {
268 83
                $GLOBALS['TSFE'] = new \stdClass();
269 83
                $GLOBALS['TSFE']->tmpl = new \stdClass();
270 83
                $GLOBALS['TSFE']->tmpl->rootLine = $rootLine;
271 83
                $GLOBALS['TSFE']->sys_page = $pageSelect;
272 83
                $GLOBALS['TSFE']->id = $pageId;
273 83
                $GLOBALS['TSFE']->tx_solr_initTsfe = 1;
274 83
                $initializedTsfe = true;
275
            }
276
277 83
            $GLOBALS['TSFE']->sys_page = $pageSelect;
278 83
            $initializedPageSelect = true;
279
        }
280
            /** @var $tmpl ExtendedTemplateService */
281 153
        $tmpl = GeneralUtility::makeInstance(ExtendedTemplateService::class);
282 153
        $tmpl->tt_track = false; // Do not log time-performance information
283 153
        $tmpl->init();
284 153
        $tmpl->runThroughTemplates($rootLine); // This generates the constants/config + hierarchy info for the template.
285 153
        $tmpl->generateConfig();
286
287 153
        $getConfigurationFromInitializedTSFEAndWriteToCache = $tmpl->ext_getSetup($tmpl->setup, $path);
288 153
        $configurationToUse = $getConfigurationFromInitializedTSFEAndWriteToCache[0];
289
290 153
        if ($initializedPageSelect) {
291 83
            $GLOBALS['TSFE']->sys_page = null;
292
        }
293 153
        if ($initializedTsfe) {
294 83
            unset($GLOBALS['TSFE']);
295
        }
296 153
        return $configurationToUse;
297
    }
298
299
    /**
300
     * Initializes the TSFE for a given page ID and language.
301
     *
302
     * @param int $pageId The page id to initialize the TSFE for
303
     * @param int $language System language uid, optional, defaults to 0
304
     * @param bool $useCache Use cache to reuse TSFE
305
     * @return void
306
     */
307 23
    public static function initializeTsfe($pageId, $language = 0, $useCache = true)
308
    {
309 23
        static $tsfeCache = [];
310
311
        // resetting, a TSFE instance with data from a different page Id could be set already
312 23
        unset($GLOBALS['TSFE']);
313
314 23
        $cacheId = $pageId . '|' . $language;
315
316 23
        if (!is_object($GLOBALS['TT'])) {
317 23
            $GLOBALS['TT'] = GeneralUtility::makeInstance(TimeTracker::class, false);
318
        }
319
320 23
        if (!isset($tsfeCache[$cacheId]) || !$useCache) {
321 23
            GeneralUtility::_GETset($language, 'L');
322
323 23
            $GLOBALS['TSFE'] = GeneralUtility::makeInstance(TypoScriptFrontendController::class,
324 23
                $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 23
            $pageRecord = BackendUtility::getRecord('pages', $pageId, 'fe_group');
330 23
            $groupListBackup = $GLOBALS['TSFE']->gr_list;
331 23
            $GLOBALS['TSFE']->gr_list = $pageRecord['fe_group'];
332
333 23
            $GLOBALS['TSFE']->sys_page = GeneralUtility::makeInstance(PageRepository::class);
334 23
            $GLOBALS['TSFE']->getPageAndRootline();
335
336
            // restore gr_list
337 23
            $GLOBALS['TSFE']->gr_list = $groupListBackup;
338
339 23
            $GLOBALS['TSFE']->initTemplate();
340 23
            $GLOBALS['TSFE']->forceTemplateParsing = true;
341 23
            $GLOBALS['TSFE']->initFEuser();
342 23
            $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 23
            $GLOBALS['TSFE']->no_cache = true;
346 23
            $GLOBALS['TSFE']->tmpl->start($GLOBALS['TSFE']->rootLine);
347 23
            $GLOBALS['TSFE']->no_cache = false;
348 23
            $GLOBALS['TSFE']->getConfigArray();
349
350 23
            $GLOBALS['TSFE']->settingLanguage();
351 23
            if (!$useCache) {
352
                $GLOBALS['TSFE']->settingLocale();
353
            }
354
355 23
            $GLOBALS['TSFE']->newCObj();
356 23
            $GLOBALS['TSFE']->absRefPrefix = self::getAbsRefPrefixFromTSFE($GLOBALS['TSFE']);
357 23
            $GLOBALS['TSFE']->calculateLinkVars();
358
359 23
            if ($useCache) {
360 23
                $tsfeCache[$cacheId] = $GLOBALS['TSFE'];
361
            }
362
        }
363
364 23
        if ($useCache) {
365 23
            $GLOBALS['TSFE'] = $tsfeCache[$cacheId];
366 23
            $GLOBALS['TSFE']->settingLocale();
367
        }
368 23
    }
369
370
    /**
371
     * Check if record ($table, $uid) is a workspace record
372
     *
373
     * @param string $table The table the record belongs to
374
     * @param int $uid The record's uid
375
     * @return bool TRUE if the record is in a draft workspace, FALSE if it's a LIVE record
376
     */
377 39
    public static function isDraftRecord($table, $uid)
378
    {
379 39
        $isWorkspaceRecord = false;
380
381 39
        if ((ExtensionManagementUtility::isLoaded('workspaces')) && (BackendUtility::isTableWorkspaceEnabled($table))) {
382
            $record = BackendUtility::getRecord($table, $uid, 'pid, t3ver_state');
383
384
            if ($record['pid'] == '-1' || $record['t3ver_state'] > 0) {
385
                $isWorkspaceRecord = true;
386
            }
387
        }
388
389 39
        return $isWorkspaceRecord;
390
    }
391
392
    /**
393
     * Checks whether a record is a localization overlay.
394
     *
395
     * @param string $tableName The record's table name
396
     * @param array $record The record to check
397
     * @deprecated Since 8.1.0 will be removed in 9.0.0. Use TCAService::isLocalizedRecord instead.
398
     * @return bool TRUE if the record is a language overlay, FALSE otherwise
399
     */
400
    public static function isLocalizedRecord($tableName, array $record)
401
    {
402
        trigger_error('Call deprecated method Util::isLocalizedRecord, use TCAService::isLocalizedRecord instead, deprecated since 8.1.0 will be removed in 9.0.0', E_USER_DEPRECATED);
403
404
        /** @var $tcaService TCAService */
405
        $tcaService = GeneralUtility::makeInstance(TCAService::class);
406
        return $tcaService->isLocalizedRecord($tableName, $record);
407
    }
408
409
    /**
410
     * Check if the page type of a page record is allowed
411
     *
412
     * @param array $pageRecord The pages database row
413
     * @param string $configurationName The name of the configuration to use.
414
     *
415
     * @return bool TRUE if the page type is allowed, otherwise FALSE
416
     */
417 30
    public static function isAllowedPageType(array $pageRecord, $configurationName = 'pages')
418
    {
419 30
        $isAllowedPageType = false;
420 30
        $configurationName = $configurationName ?? 'pages';
421 30
        $allowedPageTypes = self::getAllowedPageTypes($pageRecord['uid'], $configurationName);
422
423 30
        if (in_array($pageRecord['doktype'], $allowedPageTypes)) {
424 29
            $isAllowedPageType = true;
425
        }
426
427 30
        return $isAllowedPageType;
428
    }
429
430
    /**
431
     * Get allowed page types
432
     *
433
     * @param int $pageId Page ID
434
     * @param string $configurationName The name of the configuration to use.
435
     *
436
     * @return array Allowed page types to compare to a doktype of a page record
437
     */
438 30
    public static function getAllowedPageTypes($pageId, $configurationName = 'pages')
439
    {
440 30
        $rootPath = '';
441 30
        $configuration = self::getConfigurationFromPageId($pageId, $rootPath);
442 30
        return $configuration->getIndexQueueAllowedPageTypesArrayByConfigurationName($configurationName);
443
    }
444
445
    /**
446
     * Resolves the configured absRefPrefix to a valid value and resolved if absRefPrefix
447
     * is set to "auto".
448
     *
449
     * @param TypoScriptFrontendController $TSFE
450
     * @return string
451
     */
452 23
    public static function getAbsRefPrefixFromTSFE(TypoScriptFrontendController $TSFE)
453
    {
454 23
        $absRefPrefix = '';
455 23
        if (empty($TSFE->config['config']['absRefPrefix'])) {
456 20
            return $absRefPrefix;
457
        }
458
459 3
        $absRefPrefix = trim($TSFE->config['config']['absRefPrefix']);
460 3
        if ($absRefPrefix === 'auto') {
461 1
            $absRefPrefix = GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
462
        }
463
464 3
        return $absRefPrefix;
465
    }
466
467
    /**
468
     * @todo This method is just added for pages_language_overlay compatibility checks and will be removed when TYPO8 support is dropped
469
     * @return boolean
470
     */
471 241
    public static function getIsTYPO3VersionBelow9()
472
    {
473 241
        return (bool)version_compare(TYPO3_branch, '9.0', '<');
474
    }
475
476
    /**
477
     * @todo This method is just added for pages_language_overlay compatibility checks and will be removed when TYPO8 support is dropped
478
     * @return string
479
     */
480
    public static function getPageOverlayTableName()
481
    {
482
        return self::getIsTYPO3VersionBelow9() ? 'pages_language_overlay' : 'pages';
483
    }
484
485
    /**
486
     * This function can be used to check if one of the strings in needles is
487
     * contained in the haystack.
488
     *
489
     *
490
     * Example:
491
     *
492
     * haystack: the brown fox
493
     * needles: ['hello', 'world']
494
     * result: false
495
     *
496
     * haystack: the brown fox
497
     * needles: ['is', 'fox']
498
     * result: true
499
     *
500
     * @param string $haystack
501
     * @param array $needles
502
     * @return bool
503
     */
504 52
    public static function containsOneOfTheStrings($haystack, array $needles)
505
    {
506 52
        foreach ($needles as $needle) {
507 52
            $position = strpos($haystack, $needle);
508 52
            if ($position !== false) {
509 52
                return true;
510
            }
511
        }
512
513 49
        return false;
514
    }
515
}
516