Passed
Push — master ( f74695...a5d0a9 )
by Timo
24:59
created

Util::getPageAndRootlineOfTSFE()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.5

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 3
cts 6
cp 0.5
rs 9.9
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2.5
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 66
    public static function getPageDocumentId($uid, $typeNum = 0, $language = 0, $accessGroups = '0,-1', $mountPointParameter = '')
62
    {
63 66
        $additionalParameters = $typeNum . '/' . $language . '/' . $accessGroups;
64
65 66
        if ((string)$mountPointParameter !== '') {
66 2
            $additionalParameters = $mountPointParameter . '/' . $additionalParameters;
67
        }
68
69 66
        $documentId = self::getDocumentId('pages', $uid, $uid, $additionalParameters);
70
71 66
        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 85
    public static function getDocumentId($table, $rootPageId, $uid, $additionalIdParameters = '')
84
    {
85 85
        $siteRepository = GeneralUtility::makeInstance(SiteRepository::class);
86 85
        $site = $siteRepository->getSiteByPageId($rootPageId);
87 85
        $siteHash = $site->getSiteHash();
88
89 85
        $documentId = $siteHash . '/' . $table . '/' . $uid;
90 85
        if (!empty($additionalIdParameters)) {
91 66
            $documentId .= '/' . $additionalIdParameters;
92
        }
93
94 85
        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 174
    public static function getSolrConfiguration()
104
    {
105 174
        $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
106 174
        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 153
    public static function getSolrConfigurationFromPageId($pageId, $initializeTsfe = false, $language = 0)
119
    {
120 153
        $rootPath = '';
121 153
        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 154
    public static function getConfigurationFromPageId($pageId, $path, $initializeTsfe = false, $language = 0, $useTwoLevelCache = true)
137
    {
138 154
        $pageId = self::getConfigurationPageIdToUse($pageId);
139
140 154
        static $configurationObjectCache = [];
141 154
        $cacheId = md5($pageId . '|' . $path . '|' . $language . '|' . ($initializeTsfe ? '1' : '0'));
142 154
        if (isset($configurationObjectCache[$cacheId])) {
143 70
            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 154
        if ($pageId == 0) {
150 2
            return $configurationObjectCache[$cacheId] = self::buildTypoScriptConfigurationFromArray([], $pageId, $language, $path);
151
        }
152
153 153
        if ($useTwoLevelCache) {
154
            /** @var $cache TwoLevelCache */
155 153
            $cache = GeneralUtility::makeInstance(TwoLevelCache::class, /** @scrutinizer ignore-type */ 'tx_solr_configuration');
156 153
            $configurationArray = $cache->get($cacheId);
157
        }
158
159 153
        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 153
        $configurationArray = self::buildConfigurationArray($pageId, $path, $initializeTsfe, $language);
166
167 153
        if ($useTwoLevelCache && isset($cache)) {
168 153
            $cache->set($cacheId, $configurationArray);
169
        }
170
171 153
        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 154
    protected static function getConfigurationPageIdToUse($pageId)
182
    {
183 154
        $extensionConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class);
184 154
        if ($extensionConfiguration->getIsUseConfigurationFromClosestTemplateEnabled()) {
185
            /** @var $configurationPageResolve ConfigurationPageResolver */
186
            $configurationPageResolver = GeneralUtility::makeInstance(ConfigurationPageResolver::class);
187
            $pageId = $configurationPageResolver->getClosestPageIdWithActiveTemplate($pageId);
188
            return $pageId;
189
        }
190 154
        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 153
    protected static function buildConfigurationArray($pageId, $path, $initializeTsfe, $language)
203
    {
204 153
        if ($initializeTsfe) {
205 18
            self::initializeTsfe($pageId, $language);
206 18
            $configurationToUse = self::getConfigurationFromInitializedTSFE($path);
207
        } else {
208 153
            $configurationToUse = self::getConfigurationFromExistingTSFE($pageId, $path, $language);
209
        }
210
211 153
        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 154
    protected static function buildTypoScriptConfigurationFromArray(array $configurationToUse, $pageId, $languageId, $typoScriptPath)
224
    {
225 154
        $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
226 154
        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 18
    private static function getConfigurationFromInitializedTSFE($path)
237
    {
238
        /** @var $tmpl ExtendedTemplateService */
239 18
        $tmpl = GeneralUtility::makeInstance(ExtendedTemplateService::class);
240 18
        $configuration = $tmpl->ext_getSetup($GLOBALS['TSFE']->tmpl->setup, $path);
241 18
        $configurationToUse = $configuration[0];
242 18
        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 153
    private static function getConfigurationFromExistingTSFE($pageId, $path, $language)
254
    {
255 153
        if (is_int($language)) {
256 153
            GeneralUtility::_GETset($language, 'L');
257
        }
258
259
            /** @var $pageSelect PageRepository */
260 153
        $pageSelect = GeneralUtility::makeInstance(PageRepository::class);
261 153
        $rootLine = $pageSelect->getRootLine($pageId);
262
263 153
        $initializedTsfe = false;
264 153
        $initializedPageSelect = false;
265 153
        if (empty($GLOBALS['TSFE']->sys_page)) {
266 83
            if (empty($GLOBALS['TSFE'])) {
267 83
                $GLOBALS['TSFE'] = new \stdClass();
268 83
                $GLOBALS['TSFE']->tmpl = new \stdClass();
269 83
                $GLOBALS['TSFE']->tmpl->rootLine = $rootLine;
270 83
                $GLOBALS['TSFE']->sys_page = $pageSelect;
271 83
                $GLOBALS['TSFE']->id = $pageId;
272 83
                $GLOBALS['TSFE']->tx_solr_initTsfe = 1;
273 83
                $initializedTsfe = true;
274
            }
275
276 83
            $GLOBALS['TSFE']->sys_page = $pageSelect;
277 83
            $initializedPageSelect = true;
278
        }
279
            /** @var $tmpl ExtendedTemplateService */
280 153
        $tmpl = GeneralUtility::makeInstance(ExtendedTemplateService::class);
281 153
        $tmpl->tt_track = false; // Do not log time-performance information
282 153
        $tmpl->init();
283 153
        $tmpl->runThroughTemplates($rootLine); // This generates the constants/config + hierarchy info for the template.
284 153
        $tmpl->generateConfig();
285
286 153
        $getConfigurationFromInitializedTSFEAndWriteToCache = $tmpl->ext_getSetup($tmpl->setup, $path);
287 153
        $configurationToUse = $getConfigurationFromInitializedTSFEAndWriteToCache[0];
288
289 153
        if ($initializedPageSelect) {
290 83
            $GLOBALS['TSFE']->sys_page = null;
291
        }
292 153
        if ($initializedTsfe) {
293 83
            unset($GLOBALS['TSFE']);
294
        }
295 153
        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 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
324 23
            $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 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
            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 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 23
            $GLOBALS['TSFE']->settingLanguage();
350 23
            if (!$useCache) {
351
                $GLOBALS['TSFE']->settingLocale();
352
            }
353
354 23
            $GLOBALS['TSFE']->newCObj();
355 23
            $GLOBALS['TSFE']->absRefPrefix = self::getAbsRefPrefixFromTSFE($GLOBALS['TSFE']);
356 23
            $GLOBALS['TSFE']->calculateLinkVars();
357
358 23
            if ($useCache) {
359 23
                $tsfeCache[$cacheId] = $GLOBALS['TSFE'];
360
            }
361
        }
362
363 23
        if ($useCache) {
364 23
            $GLOBALS['TSFE'] = $tsfeCache[$cacheId];
365 23
            $GLOBALS['TSFE']->settingLocale();
366
        }
367 23
    }
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 23
    private static function getPageAndRootlineOfTSFE($pageId)
375
    {
376
        //@todo This can be dropped when TYPO3 8 compatibility is dropped
377 23
        if (Util::getIsTYPO3VersionBelow9()) {
378 23
            $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 23
    }
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 39
    public static function isDraftRecord($table, $uid)
396
    {
397 39
        $isWorkspaceRecord = false;
398
399 39
        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 39
        return $isWorkspaceRecord;
408
    }
409
410
    /**
411
     * Checks whether a record is a localization overlay.
412
     *
413
     * @param string $tableName The record's table name
414
     * @param array $record The record to check
415
     * @deprecated Since 8.1.0 will be removed in 9.0.0. Use TCAService::isLocalizedRecord instead.
416
     * @return bool TRUE if the record is a language overlay, FALSE otherwise
417
     */
418
    public static function isLocalizedRecord($tableName, array $record)
419
    {
420
        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);
421
422
        /** @var $tcaService TCAService */
423
        $tcaService = GeneralUtility::makeInstance(TCAService::class);
424
        return $tcaService->isLocalizedRecord($tableName, $record);
425
    }
426
427
    /**
428
     * Check if the page type of a page record is allowed
429
     *
430
     * @param array $pageRecord The pages database row
431
     * @param string $configurationName The name of the configuration to use.
432
     *
433
     * @return bool TRUE if the page type is allowed, otherwise FALSE
434
     */
435 30
    public static function isAllowedPageType(array $pageRecord, $configurationName = 'pages')
436
    {
437 30
        $isAllowedPageType = false;
438 30
        $configurationName = $configurationName ?? 'pages';
439 30
        $allowedPageTypes = self::getAllowedPageTypes($pageRecord['uid'], $configurationName);
440
441 30
        if (in_array($pageRecord['doktype'], $allowedPageTypes)) {
442 29
            $isAllowedPageType = true;
443
        }
444
445 30
        return $isAllowedPageType;
446
    }
447
448
    /**
449
     * Get allowed page types
450
     *
451
     * @param int $pageId Page ID
452
     * @param string $configurationName The name of the configuration to use.
453
     *
454
     * @return array Allowed page types to compare to a doktype of a page record
455
     */
456 30
    public static function getAllowedPageTypes($pageId, $configurationName = 'pages')
457
    {
458 30
        $rootPath = '';
459 30
        $configuration = self::getConfigurationFromPageId($pageId, $rootPath);
460 30
        return $configuration->getIndexQueueAllowedPageTypesArrayByConfigurationName($configurationName);
461
    }
462
463
    /**
464
     * Resolves the configured absRefPrefix to a valid value and resolved if absRefPrefix
465
     * is set to "auto".
466
     *
467
     * @param TypoScriptFrontendController $TSFE
468
     * @return string
469
     */
470 23
    public static function getAbsRefPrefixFromTSFE(TypoScriptFrontendController $TSFE)
471
    {
472 23
        $absRefPrefix = '';
473 23
        if (empty($TSFE->config['config']['absRefPrefix'])) {
474 20
            return $absRefPrefix;
475
        }
476
477 3
        $absRefPrefix = trim($TSFE->config['config']['absRefPrefix']);
478 3
        if ($absRefPrefix === 'auto') {
479 1
            $absRefPrefix = GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
480
        }
481
482 3
        return $absRefPrefix;
483
    }
484
485
    /**
486
     * @todo This method is just added for pages_language_overlay compatibility checks and will be removed when TYPO8 support is dropped
487
     * @return boolean
488
     */
489 242
    public static function getIsTYPO3VersionBelow9()
490
    {
491 242
        return (bool)version_compare(TYPO3_branch, '9.0', '<');
492
    }
493
494
    /**
495
     * @todo This method is just added for pages_language_overlay compatibility checks and will be removed when TYPO8 support is dropped
496
     * @return string
497
     */
498
    public static function getPageOverlayTableName()
499
    {
500
        return self::getIsTYPO3VersionBelow9() ? 'pages_language_overlay' : 'pages';
501
    }
502
503
    /**
504
     * This function can be used to check if one of the strings in needles is
505
     * contained in the haystack.
506
     *
507
     *
508
     * Example:
509
     *
510
     * haystack: the brown fox
511
     * needles: ['hello', 'world']
512
     * result: false
513
     *
514
     * haystack: the brown fox
515
     * needles: ['is', 'fox']
516
     * result: true
517
     *
518
     * @param string $haystack
519
     * @param array $needles
520
     * @return bool
521
     */
522 52
    public static function containsOneOfTheStrings($haystack, array $needles)
523
    {
524 52
        foreach ($needles as $needle) {
525 52
            $position = strpos($haystack, $needle);
526 52
            if ($position !== false) {
527 52
                return true;
528
            }
529
        }
530
531 49
        return false;
532
    }
533
}
534