Passed
Pull Request — release-11.5.x (#3371)
by Markus
50:39 queued 27:09
created

TypoScript::buildConfigurationArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 7
c 3
b 0
f 0
dl 0
loc 12
ccs 7
cts 7
cp 1
rs 10
cc 2
nc 2
nop 3
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17
18
namespace ApacheSolrForTypo3\Solr\FrontendEnvironment;
19
20
use ApacheSolrForTypo3\Solr\System\Cache\TwoLevelCache;
21
use ApacheSolrForTypo3\Solr\System\Configuration\ConfigurationManager;
22
use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration;
23
use Doctrine\DBAL\Driver\Exception as DBALDriverException;
24
use TYPO3\CMS\Core\Error\Http\InternalServerErrorException;
25
use TYPO3\CMS\Core\Error\Http\ServiceUnavailableException;
26
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
27
use TYPO3\CMS\Core\SingletonInterface;
28
use TYPO3\CMS\Core\Utility\GeneralUtility;
29
30
/**
31
 * Class TypoScript
32
 */
33
class TypoScript implements SingletonInterface
34
{
35
    /**
36
     * Holds the TypoScript values for given page-id language and TypoScript path.
37
     *
38
     * @var array
39
     */
40
    private array $configurationObjectCache = [];
41
42
    /**
43
     * Loads the TypoScript configuration for a given page-id and language.
44
     * Language usage may be disabled to get the default TypoScript
45
     * configuration.
46
     *
47
     * @param int $pageId The page id of the (root) page to get the Solr configuration from.
48
     * @param string $path The TypoScript configuration path to retrieve.
49
     * @param int $language System language uid, optional, defaults to 0
50
     * @param int|null $rootPageId
51
     *
52
     * @return TypoScriptConfiguration The Solr configuration for the requested tree.
53
     *
54
     * @throws DBALDriverException
55
     */
56 211
    public function getConfigurationFromPageId(
57
        int $pageId,
58
        string $path,
59
        int $language = 0,
60
        ?int $rootPageId = null
61
    ): TypoScriptConfiguration {
62 211
        $cacheId = md5($pageId . '|' . $path . '|' . $language);
63 211
        if (isset($this->configurationObjectCache[$cacheId])) {
64 95
            return $this->configurationObjectCache[$cacheId];
65
        }
66
67
        // If we're on UID 0, we cannot retrieve a configuration.
68
        // TSFE can not be initialized for UID = 0
69
        // getRootline() below throws an exception (since #typo3-60 )
70
        // as UID 0 cannot have any parent rootline by design.
71 211
        if ($pageId === 0 && $rootPageId === null) {
72
            return $this->configurationObjectCache[$cacheId] = $this->buildTypoScriptConfigurationFromArray([], $pageId, $language, $path);
73
        }
74
75
        /* @var TwoLevelCache $cache */
76 211
        $cache = GeneralUtility::makeInstance(TwoLevelCache::class, /** @scrutinizer ignore-type */ 'tx_solr_configuration');
77 211
        $configurationArray = $cache->get($cacheId);
78
79 211
        if (!empty($configurationArray)) {
80
            // we have a cache hit and can return it.
81
            return $this->configurationObjectCache[$cacheId] = $this->buildTypoScriptConfigurationFromArray($configurationArray, $pageId, $language, $path);
82
        }
83
84
        // we have nothing in the cache. We need to build the configurationToUse
85 211
        $configurationArray = $this->buildConfigurationArray($pageId, $path, $language);
86
87 211
        $cache->set($cacheId, $configurationArray);
88
89 211
        return $this->configurationObjectCache[$cacheId] = $this->buildTypoScriptConfigurationFromArray($configurationArray, $pageId, $language, $path);
90
    }
91
92
    /**
93
     * Builds a configuration array, containing the solr configuration.
94
     *
95
     * @param int $pageId
96
     * @param string $path
97
     * @param int $language
98
     *
99
     * @return array
100
     *
101
     * @throws DBALDriverException
102
     */
103 210
    protected function buildConfigurationArray(int $pageId, string $path, int $language): array
104
    {
105
        /* @var Tsfe $tsfeManager */
106 210
        $tsfeManager = GeneralUtility::makeInstance(Tsfe::class);
107
        try {
108 210
            $tsfe = $tsfeManager->getTsfeByPageIdAndLanguageId($pageId, $language);
109 6
        } catch (InternalServerErrorException | ServiceUnavailableException | SiteNotFoundException | Exception\Exception $e) {
110
            // @todo logging!
111 6
            return [];
112
        }
113 210
        $getConfigurationFromInitializedTSFEAndWriteToCache = $this->ext_getSetup($tsfe->tmpl->setup ?? [], $path);
114 210
        return $getConfigurationFromInitializedTSFEAndWriteToCache[0] ?? [];
115
    }
116
117
    /**
118
     * Adapted from TYPO3 core
119
     * @see sysext:core/Classes/TypoScript/ExtendedTemplateService until TYPO3 v11
120
     * @param array $theSetup
121
     * @param string $theKey
122
     * @return array
123
     */
124 210
    public function ext_getSetup(array $theSetup, string $theKey): array
125
    {
126
        // 'a.b.c' --> ['a', 'b.c']
127 210
        $parts = explode('.', $theKey, 2);
128 210
        if ((string)$parts[0] !== '' && is_array($theSetup[$parts[0] . '.'])) {
129
            if (trim($parts[1] ?? '') !== '') {
130
                // Current path segment is a sub array, check it recursively by applying the rest of the key
131
                return $this->ext_getSetup($theSetup[$parts[0] . '.'], trim($parts[1] ?? ''));
132
            }
133
            // No further path to evaluate, return current setup and the value for the current path segment - if any
134
            return [$theSetup[$parts[0] . '.'], $theSetup[$parts[0]] ?? ''];
135
        }
136 210
        if (trim($theKey) !== '') {
137
            return [[], $theSetup[$theKey]];
138
        }
139 210
        return [$theSetup, ''];
140
    }
141
142
    /**
143
     * Builds the configuration object from a config array and returns it.
144
     *
145
     * @param array $configurationToUse
146
     * @param int $pageId
147
     * @param int $languageId
148
     * @param string $typoScriptPath
149
     * @return TypoScriptConfiguration
150
     */
151 210
    protected function buildTypoScriptConfigurationFromArray(array $configurationToUse, int $pageId, int $languageId, string $typoScriptPath): TypoScriptConfiguration
152
    {
153 210
        $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
154 210
        return $configurationManager->getTypoScriptConfiguration($configurationToUse, $pageId, $languageId, $typoScriptPath);
155
    }
156
}
157