Passed
Push — release-11.5.x ( 1520e1...01d568 )
by Rafael
43:11
created

SiteUtility::getSolrConnectionConfiguration()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 37
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 28
dl 0
loc 37
ccs 13
cts 13
cp 1
rs 9.472
c 0
b 0
f 0
cc 4
nc 2
nop 2
crap 4
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace ApacheSolrForTypo3\Solr\System\Util;
17
18
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
19
use TYPO3\CMS\Core\Site\Entity\Site;
20
use TYPO3\CMS\Core\Site\SiteFinder;
21
use TYPO3\CMS\Core\Utility\GeneralUtility;
22
23
/**
24
 * This class contains related functions for the new site management that was introduced with TYPO3 9.
25
 */
26
class SiteUtility
27
{
28
    /**
29
     * @var array
30
     */
31
    public static array $languages = [];
32
33
    /**
34
     * Determines if the site where the page belongs to is managed with the TYPO3 site management.
35
     *
36
     * @param int $pageId
37
     * @return bool
38
     */
39 29
    public static function getIsSiteManagedSite(int $pageId): bool
40
    {
41 29
        $siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
42
        try {
43
            /* @var SiteFinder $siteFinder */
44 29
            return $siteFinder->getSiteByPageId($pageId) instanceof Site;
45
        } catch (SiteNotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
46
        }
47
        return false;
48
    }
49
50
    /**
51
     * This method is used to retrieve the connection configuration from the TYPO3 site configuration.
52
     *
53
     * Note: Language context properties have precedence over global settings.
54
     *
55
     * The configuration is done in the globals configuration of a site, and be extended in the language specific configuration
56
     * of a site.
57
     *
58
     * Typically, everything except the core name is configured on the global level and the core name differs for each language.
59
     *
60
     * In addition, every property can be defined for the ```read``` and ```write``` scope.
61
     *
62
     * The convention for property keys is "solr_{propertyName}_{scope}". With the configuration "solr_host_read" you define the host
63
     * for the solr read connection.
64
     *
65
     * @param Site $typo3Site
66
     * @param string $property
67
     * @param int $languageId
68
     * @param string $scope
69
     * @param mixed $defaultValue
70
     * @return mixed
71
     */
72 225
    public static function getConnectionProperty(
73
        Site $typo3Site,
74
        string $property,
75
        int $languageId,
76
        string $scope,
77
        $defaultValue = null
78
    ) {
79 225
        $value = self::getConnectionPropertyOrFallback($typo3Site, $property, $languageId, $scope);
80 225
        if ($value === null) {
81 207
            return $defaultValue;
82
        }
83 224
        return $value;
84
    }
85
86
    /**
87
     * Builds the Solr connection configuration
88
     *
89
     * @param Site $typo3Site
90
     * @param int $languageUid
91
     * @return array|null
92
     */
93
    public static function getSolrConnectionConfiguration(Site $typo3Site, int $languageUid): ?array
94
    {
95
        $solrEnabled = self::getConnectionProperty($typo3Site, 'enabled', $languageUid, 'read', true);
96 225
        $solrReadCore = self::getConnectionProperty($typo3Site, 'core', $languageUid, 'read');
97
        $solrWriteCore = self::getConnectionProperty($typo3Site, 'core', $languageUid, 'write');
98
        if (!$solrEnabled || empty($solrReadCore) || empty($solrWriteCore)) {
99
            return null;
100
        }
101
102 225
        $rootPageUid = $typo3Site->getRootPageId();
103 208
        return [
104
            'connectionKey' => $rootPageUid . '|' . $languageUid,
105
            'rootPageUid' => $rootPageUid,
106
            'read' => [
107 225
                'scheme' => self::getConnectionProperty($typo3Site, 'scheme', $languageUid, 'read', 'http'),
108
                'host' => self::getConnectionProperty($typo3Site, 'host', $languageUid, 'read', 'localhost'),
109
                'port' => (int)self::getConnectionProperty($typo3Site, 'port', $languageUid, 'read', 8983),
110 225
                // @todo: transform core to path
111
                'path' =>
112
                self::getConnectionProperty($typo3Site, 'path', $languageUid, 'read', '/solr/') .
113 225
                $solrReadCore . '/' ,
114 225
                'username' => self::getConnectionProperty($typo3Site, 'username', $languageUid, 'read', ''),
115 218
                'password' => self::getConnectionProperty($typo3Site, 'password', $languageUid, 'read', ''),
116
            ],
117 225
            'write' => [
118 225
                'scheme' => self::getConnectionProperty($typo3Site, 'scheme', $languageUid, 'write', 'http'),
119 208
                'host' => self::getConnectionProperty($typo3Site, 'host', $languageUid, 'write', 'localhost'),
120
                'port' => (int)self::getConnectionProperty($typo3Site, 'port', $languageUid, 'write', 8983),
121
                // @todo: transform core to path
122
                'path' =>
123 223
                self::getConnectionProperty($typo3Site, 'path', $languageUid, 'write', '/solr/') .
124 223
                $solrWriteCore . '/' ,
125
                'username' => self::getConnectionProperty($typo3Site, 'username', $languageUid, 'write', ''),
126
                'password' => self::getConnectionProperty($typo3Site, 'password', $languageUid, 'write', ''),
127
            ],
128
129
            'language' => $languageUid,
130
        ];
131
    }
132
133
    /**
134
     * Builds the Solr connection configuration for all languages of given TYPO3 site
135 213
     *
136
     * @param Site $typo3Site
137 213
     * @return array
138 213
     */
139 7
    public static function getAllSolrConnectionConfigurations(Site $typo3Site): array
140
    {
141 213
        $connections = [];
142 213
        foreach ($typo3Site->getLanguages() as $language) {
143
            $connection = self::getSolrConnectionConfiguration($typo3Site, $language->getLanguageId());
144
            if ($connection !== null) {
145
                $connections[$language->getLanguageId()] = $connection;
146 213
            }
147 213
        }
148 213
149 212
        return $connections;
150
    }
151 1
152
    /**
153
     * Resolves site configuration properties.
154
     * Language context properties have precedence over global settings.
155
     *
156
     * @param Site $typo3Site
157
     * @param string $property
158
     * @param int $languageId
159
     * @param string $scope
160 225
     * @return string|bool|null
161
     */
162 225
    protected static function getConnectionPropertyOrFallback(
163 225
        Site $typo3Site,
164 223
        string $property,
165
        int $languageId,
166
        string $scope
167 224
    ) {
168
        if ($scope === 'write' && !self::writeConnectionIsEnabled($typo3Site, $languageId)) {
169
            $scope = 'read';
170
        }
171
172
        // convention key solr_$property_$scope
173
        $keyToCheck = 'solr_' . $property . '_' . $scope;
174
175
        // convention fallback key solr_$property_read
176
        $fallbackKey = 'solr_' . $property . '_read';
177
178
        // try to find language specific setting if found return it
179
        $rootPageUid = $typo3Site->getRootPageId();
180 225
        if (isset(self::$languages[$rootPageUid][$languageId]) === false) {
181
            self::$languages[$rootPageUid][$languageId] = $typo3Site->getLanguageById($languageId)->toArray();
182 225
        }
183 1
        $value = self::getValueOrFallback(self::$languages[$rootPageUid][$languageId], $keyToCheck, $fallbackKey);
184
        if ($value !== null) {
185 225
            return $value;
186 1
        }
187
188
        // if not found check global configuration
189 225
        $siteBaseConfiguration = $typo3Site->getConfiguration();
190
        return self::getValueOrFallback($siteBaseConfiguration, $keyToCheck, $fallbackKey);
191
    }
192
193
    /**
194
     * Checks whether write connection is enabled.
195
     * Language context properties have precedence over global settings.
196
     *
197
     * @param Site $typo3Site
198
     * @param int $languageId
199
     * @return bool
200
     */
201
    protected static function writeConnectionIsEnabled(Site $typo3Site, int $languageId): bool
202
    {
203
        $rootPageUid = $typo3Site->getRootPageId();
204
        if (isset(self::$languages[$rootPageUid][$languageId]) === false) {
205
            self::$languages[$rootPageUid][$languageId] = $typo3Site->getLanguageById($languageId)->toArray();
206
        }
207
        $value = self::getValueOrFallback(self::$languages[$rootPageUid][$languageId], 'solr_use_write_connection', 'solr_use_write_connection');
208
        if ($value !== null) {
209
            return $value;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $value could return the type string which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
210
        }
211
212
        $siteBaseConfiguration = $typo3Site->getConfiguration();
213
        $value = self::getValueOrFallback($siteBaseConfiguration, 'solr_use_write_connection', 'solr_use_write_connection');
214
        if ($value !== null) {
215
            return $value;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $value could return the type string which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
216
        }
217
        return false;
218
    }
219
220
    /**
221
     * @param array $data
222
     * @param string $keyToCheck
223
     * @param string $fallbackKey
224
     * @return string|bool|null
225
     */
226
    protected static function getValueOrFallback(array $data, string $keyToCheck, string $fallbackKey)
227
    {
228
        $value = $data[$keyToCheck] ?? null;
229
        if ($value === '0' || $value === 0 || !empty($value)) {
230
            return self::evaluateConfigurationData($value);
231
        }
232
233
        return self::evaluateConfigurationData($data[$fallbackKey] ?? null);
234
    }
235
236
    /**
237
     * Evaluate configuration data
238
     *
239
     * Setting boolean values via environment variables
240
     * results in strings like 'false' that may be misinterpreted
241
     * thus we check for boolean values in strings.
242
     *
243
     * @param string|bool|null $value
244
     * @return string|bool|null
245
     */
246
    protected static function evaluateConfigurationData($value)
247
    {
248
        if ($value === 'true') {
249
            return true;
250
        }
251
        if ($value === 'false') {
252
            return false;
253
        }
254
255
        return $value;
256
    }
257
}
258