Completed
Pull Request — master (#861)
by
unknown
23:09
created

Site::getPageIdsFromCurrentDepthAndCallRecursive()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 23
ccs 8
cts 8
cp 1
rs 8.7972
cc 4
eloc 12
nc 6
nop 3
crap 4
1
<?php
2
namespace ApacheSolrForTypo3\Solr;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2011-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 2 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 TYPO3\CMS\Backend\Utility\BackendUtility;
28
use TYPO3\CMS\Core\Registry;
29
use TYPO3\CMS\Core\Utility\GeneralUtility;
30
use TYPO3\CMS\Frontend\Page\PageRepository;
31
32
/**
33
 * A site is a branch in a TYPO3 installation. Each site's root page is marked
34
 * by the "Use as Root Page" flag.
35
 *
36
 * @author Ingo Renner <[email protected]>
37
 */
38
class Site
39
{
40
    /**
41
     * Cache for ApacheSolrForTypo3\Solr\Site objects
42
     *
43
     * @var array
44
     */
45
    protected static $sitesCache = [];
46
47
    /**
48
     * Small cache for the list of pages in a site, so that the results of this
49
     * rather expensive operation can be used by all initializers without having
50
     * each initializer do it again.
51
     *
52
     * TODO Move to caching framework once TYPO3 4.6 is the minimum required
53
     * version.
54
     *
55
     * @var array
56
     */
57
    protected static $sitePagesCache = [];
58
59
    /**
60
     * Root page record.
61
     *
62
     * @var array
63
     */
64
    protected $rootPage = [];
65
66
    /**
67
     * The site's sys_language_mode
68
     *
69
     * @var string
70
     */
71
    protected $sysLanguageMode = null;
72
73
    /**
74
     * Constructor.
75
     *
76
     * @param int $rootPageId Site root page ID (uid). The page must be marked as site root ("Use as Root Page" flag).
77
     */
78 63
    public function __construct($rootPageId)
79
    {
80 63
        $page = BackendUtility::getRecord('pages', $rootPageId);
81
82 63
        if (!$page['is_siteroot']) {
83
            throw new \InvalidArgumentException(
84
                'The page for the given page ID \'' . $rootPageId
85
                . '\' is not marked as root page and can therefore not be used as site root page.',
86
                1309272922
87
            );
88
        }
89
90 63
        $this->rootPage = $page;
91 63
    }
92
93
    /**
94
     * Gets the Site for a specific page Id.
95
     *
96
     * @param int $pageId The page Id to get a Site object for.
97
     * @return Site Site for the given page Id.
98
     */
99 50
    public static function getSiteByPageId($pageId)
100
    {
101 50
        $rootPageId = Util::getRootPageId($pageId);
102
103 50
        if (!isset(self::$sitesCache[$rootPageId])) {
104 50
            self::$sitesCache[$rootPageId] = GeneralUtility::makeInstance(__CLASS__,
105
                $rootPageId);
106
        }
107
108 50
        return self::$sitesCache[$rootPageId];
109
    }
110
111
    /**
112
     * Creates a dropdown selector of available TYPO3 sites with Solr
113
     * configured.
114
     *
115
     * @param string $selectorName Name to be used in the select's name attribute
116
     * @param Site $selectedSite Optional, currently selected site
117
     * @return string Site selector HTML code
118
     * @todo Extract into own class like indexing configuration selector
119
     */
120
    public static function getAvailableSitesSelector(
121
        $selectorName,
122
        Site $selectedSite = null
123
    ) {
124
        $sites = self::getAvailableSites();
125
        $selector = '<select name="' . $selectorName . '" class="form-control">';
126
127
        foreach ($sites as $site) {
128
            $selectedAttribute = '';
129
            if ($selectedSite !== null && $site->getRootPageId() == $selectedSite->getRootPageId()) {
130
                $selectedAttribute = ' selected="selected"';
131
            }
132
133
            $selector .= '<option value="' . $site->getRootPageId() . '"' . $selectedAttribute . '>'
134
                . $site->getLabel()
135
                . '</option>';
136
        }
137
138
        $selector .= '</select>';
139
140
        return $selector;
141
    }
142
143
    /**
144
     * Gets all available TYPO3 sites with Solr configured.
145
     *
146
     * @param bool $stopOnInvalidSite
147
     *
148
     * @return Site[] An array of available sites
149
     */
150 17
    public static function getAvailableSites($stopOnInvalidSite = false)
151
    {
152 17
        static $sitesCached;
153 17
        $sites = [];
154
155
        // Check if $sites has been cached
156 17
        if (isset($sitesCached)) {
157 1
            return $sitesCached;
158
        }
159
160 17
        $servers = self::getSolrServersFromRegistry();
161
162 17
        foreach ($servers as $server) {
163 17
            if (isset($sites[$server['rootPageUid']])) {
164
                //get each site only once
165
                continue;
166
            }
167
168
            try {
169 17
                $sites[$server['rootPageUid']] = GeneralUtility::makeInstance(__CLASS__, $server['rootPageUid']);
170
            } catch (\InvalidArgumentException $e) {
171
                if ($stopOnInvalidSite) {
172 17
                    throw $e;
173
                }
174
            }
175
        }
176
177 17
        $sitesCached = $sites;
178
179 17
        return $sitesCached;
180
    }
181
182
    /**
183
     * Returns the first available Site.
184
     *
185
     * @param bool $stopOnInvalidSite
186
     *
187
     * @return Site
188
     */
189 16
    public static function getFirstAvailableSite($stopOnInvalidSite = false)
190
    {
191 16
        $sites = self::getAvailableSites($stopOnInvalidSite);
192 16
        return array_shift($sites);
193
    }
194
195
    /**
196
     * Clears the $sitePagesCache
197
     *
198
     */
199
    public static function clearSitePagesCache()
200
    {
201
        self::$sitePagesCache = [];
202
    }
203
204
    /**
205
     * Gets the site's root page ID (uid).
206
     *
207
     * @return int The site's root page ID.
208
     */
209 22
    public function getRootPageId()
210
    {
211 22
        return $this->rootPage['uid'];
212
    }
213
214
    /**
215
     * Gets the site's label. The label is build from the the site title and root
216
     * page ID (uid).
217
     *
218
     * @return string The site's label.
219
     */
220 9
    public function getLabel()
221
    {
222 9
        $rootlineTitles = [];
223 9
        $rootLine = BackendUtility::BEgetRootLine($this->rootPage['uid']);
224
        // Remove last
225 9
        array_pop($rootLine);
226 9
        $rootLine = array_reverse($rootLine);
227 9
        foreach ($rootLine as $rootLineItem) {
228 9
            $rootlineTitles[] = $rootLineItem['title'];
229
        }
230 9
        return implode(' - ', $rootlineTitles) . ', Root Page ID: ' . $this->rootPage['uid'];
231
    }
232
233
    /**
234
     * Retrieves the configured solr servers from the registry.
235
     *
236
     * @return array
237
     */
238 17
    protected static function getSolrServersFromRegistry()
239
    {
240
        /** @var $registry Registry */
241 17
        $registry = GeneralUtility::makeInstance(Registry::class);
242 17
        $servers = (array) $registry->get('tx_solr', 'servers', []);
243 17
        return $servers;
244
    }
245
246
    /**
247
     * Gets the site's Solr TypoScript configuration (plugin.tx_solr.*)
248
     *
249
     * @return  \ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration The Solr TypoScript configuration
250
     */
251 12
    public function getSolrConfiguration()
252
    {
253 12
        return Util::getSolrConfigurationFromPageId($this->rootPage['uid']);
254
    }
255
256
    /**
257
     * Gets the system languages (IDs) for which Solr connections have been
258
     * configured.
259
     *
260
     * @return array Array of system language IDs for which connections have been configured on this site.
261
     */
262
    public function getLanguages()
263
    {
264
        $siteLanguages = [];
265
266
        $servers = self::getSolrServersFromRegistry();
267
268
        foreach ($servers as $connectionKey => $solrConnection) {
269
            list($siteRootPageId, $systemLanguageId) = explode('|',
270
                $connectionKey);
271
272
            if ($siteRootPageId == $this->rootPage['uid']) {
273
                $siteLanguages[] = $systemLanguageId;
274
            }
275
        }
276
277
        return $siteLanguages;
278
    }
279
280
    /**
281
     * Gets the site's default language as configured in
282
     * config.sys_language_uid. If sys_language_uid is not set, 0 is assumed to
283
     * be the default.
284
     *
285
     * @return int The site's default language.
286
     */
287 1
    public function getDefaultLanguage()
288
    {
289 1
        $siteDefaultLanguage = 0;
290
291 1
        $configuration = Util::getConfigurationFromPageId(
292 1
            $this->rootPage['uid'],
293 1
            'config',
294 1
            false,
295 1
            false
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
296
        );
297
298 1
        $siteDefaultLanguage = $configuration->getValueByPathOrDefaultValue('sys_language_uid', $siteDefaultLanguage);
299
        // default language is set through default L GET parameter -> overruling config.sys_language_uid
300 1
        $siteDefaultLanguage = $configuration->getValueByPathOrDefaultValue('defaultGetVars.L', $siteDefaultLanguage);
301
302 1
        return $siteDefaultLanguage;
303
    }
304
305
    /**
306
     * Generates a list of page IDs in this site. Attention, this includes
307
     * all page types! Deleted pages are not included.
308
     *
309
     * @param int|string $rootPageId Page ID from where to start collection sub pages
310
     * @param int $maxDepth Maximum depth to descend into the site tree
311
     * @return array Array of pages (IDs) in this site
312
     */
313 8
    public function getPages($rootPageId = 'SITE_ROOT', $maxDepth = 999)
314
    {
315
        // when we have a cached value, we can return it.
316 8
        if (!empty(self::$sitePagesCache[$rootPageId])) {
317 7
            return self::$sitePagesCache[$rootPageId];
318
        }
319
320 8
        $pageIds = [];
321 8
        $maxDepth = intval($maxDepth);
322
323 8
        $recursionRootPageId = intval($rootPageId);
324 8
        if ($rootPageId == 'SITE_ROOT') {
325 8
            $recursionRootPageId = $this->rootPage['uid'];
326 8
            $pageIds[] = (int) $this->rootPage['uid'];
327
        }
328
329 8
        if ($maxDepth <= 0) {
330
            // exiting the recursion loop, may write to cache now
331
            self::$sitePagesCache[$rootPageId] = $pageIds;
332
            return $pageIds;
333
        }
334
335
        // get the page ids of the current level and if needed call getPages recursive
336 8
        $pageIds = $this->getPageIdsFromCurrentDepthAndCallRecursive($maxDepth, $recursionRootPageId, $pageIds);
337
338
        // exiting the recursion loop, may write to cache now
339 8
        self::$sitePagesCache[$rootPageId] = $pageIds;
340 8
        return $pageIds;
341
    }
342
343
    /**
344
     * This method retrieves the pages ids from the current tree level an calls getPages recursive,
345
     * when the maxDepth has not been reached.
346
     *
347
     * @param int $maxDepth
348
     * @param int $recursionRootPageId
349
     * @param array $pageIds
350
     * @return array
351
     */
352 8
    protected function getPageIdsFromCurrentDepthAndCallRecursive($maxDepth, $recursionRootPageId, $pageIds)
353
    {
354 8
        static $initialPagesAdditionalWhereClause;
355
356 8
        // Only fetch $initialPagesAdditionalWhereClause on first call
357 6
        if (empty($initialPagesAdditionalWhereClause)) {
358
            // Fetch configuration in order to be able to read initialPagesAdditionalWhereClause
359 6
            $configuration = Util::getSolrConfigurationFromPageId($this->rootPage['uid']);
360 6
            $initialPagesAdditionalWhereClause = $configuration->getInitialPagesAdditionalWhereClause();
361
        }
362
363 8
        $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'pid = ' . $recursionRootPageId . ' ' . BackendUtility::deleteClause('pages') . $initialPagesAdditionalWhereClause);
364 8
365
        while ($page = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
366
            $pageIds[] = (int) $page['uid'];
367
368
            if ($maxDepth > 1) {
369
                $pageIds = array_merge($pageIds, $this->getPages($page['uid'], $maxDepth - 1));
370
            }
371
        }
372
        $GLOBALS['TYPO3_DB']->sql_free_result($result);
373
        return $pageIds;
374
    }
375
376 46
    /**
377
     * Generates the site's unique Site Hash.
378 46
     *
379
     * The Site Hash is build from the site's main domain, the system encryption
380
     * key, and the extension "tx_solr". These components are concatenated and
381
     * sha1-hashed.
382
     *
383
     * @return string Site Hash.
384
     */
385
    public function getSiteHash()
386
    {
387 48
        return Util::getSiteHashForDomain($this->getDomain());
388
    }
389 48
390 48
    /**
391
     * Gets the site's main domain. More specifically the first domain record in
392 48
     * the site tree.
393
     *
394
     * @return string The site's main domain.
395
     */
396
    public function getDomain()
397
    {
398
        $pageSelect = GeneralUtility::makeInstance(PageRepository::class);
399
        $rootLine = $pageSelect->getRootLine($this->rootPage['uid']);
400 1
401
        return BackendUtility::firstDomainRecord($rootLine);
402 1
    }
403
404
    /**
405
     * Gets the site's root page.
406
     *
407
     * @return array The site's root page.
408
     */
409
    public function getRootPage()
410
    {
411
        return $this->rootPage;
412
    }
413
414
    /**
415
     * Gets the site's root page's title.
416
     *
417
     * @return string The site's root page's title
418
     */
419
    public function getTitle()
420 11
    {
421
        return $this->rootPage['title'];
422 11
    }
423 11
424 11
    /**
425
     * Gets the site's config.sys_language_mode setting
426
     *
427 11
     * @return string The site's config.sys_language_mode
428
     */
429
    public function getSysLanguageMode()
430
    {
431
        if (is_null($this->sysLanguageMode)) {
432
            Util::initializeTsfe($this->getRootPageId());
433
            $this->sysLanguageMode = $GLOBALS['TSFE']->sys_language_mode;
434
        }
435
436
        return $this->sysLanguageMode;
437
    }
438
}
439