[TASK] Remove dependency between SiteLanguage and Site
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Configuration / TypoScript / ConditionMatching / ConditionMatcher.php
1 <?php
2
3 namespace TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching;
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 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher;
20 use TYPO3\CMS\Core\Context\Context;
21 use TYPO3\CMS\Core\Context\UserAspect;
22 use TYPO3\CMS\Core\Site\Entity\Site;
23 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25
26 /**
27 * Matching TypoScript conditions for frontend disposal.
28 *
29 * Used with the TypoScript parser. Matches browserinfo
30 * and IP numbers for use with templates.
31 */
32 class ConditionMatcher extends AbstractConditionMatcher
33 {
34 /**
35 * @var Context
36 */
37 protected $context;
38
39 /**
40 * @param Context $context optional context to fetch data from
41 */
42 public function __construct(Context $context = null)
43 {
44 $this->context = $context ?? GeneralUtility::makeInstance(Context::class);
45 }
46
47 /**
48 * Evaluates a TypoScript condition given as input,
49 * eg. "[browser=net][...(other conditions)...]"
50 *
51 * @param string $string The condition to match against its criteria.
52 * @return bool Whether the condition matched
53 * @see \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::parse()
54 * @throws \TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException
55 */
56 protected function evaluateCondition($string)
57 {
58 list($key, $value) = GeneralUtility::trimExplode('=', $string, false, 2);
59 $result = $this->evaluateConditionCommon($key, $value);
60
61 if (is_bool($result)) {
62 return $result;
63 }
64 switch ($key) {
65 case 'usergroup':
66 $groupList = $this->getGroupList();
67 // '0,-1' is the default usergroups when not logged in!
68 if ($groupList !== '0,-1') {
69 $values = GeneralUtility::trimExplode(',', $value, true);
70 foreach ($values as $test) {
71 if ($test === '*' || GeneralUtility::inList($groupList, $test)) {
72 return true;
73 }
74 }
75 }
76 break;
77 case 'treeLevel':
78 $values = GeneralUtility::trimExplode(',', $value, true);
79 $treeLevel = count($this->rootline) - 1;
80 foreach ($values as $test) {
81 if ($test == $treeLevel) {
82 return true;
83 }
84 }
85 break;
86 case 'PIDupinRootline':
87 case 'PIDinRootline':
88 $values = GeneralUtility::trimExplode(',', $value, true);
89 if ($key === 'PIDinRootline' || !in_array($this->pageId, $values)) {
90 foreach ($values as $test) {
91 foreach ($this->rootline as $rlDat) {
92 if ($rlDat['uid'] == $test) {
93 return true;
94 }
95 }
96 }
97 }
98 break;
99 case 'site':
100 $site = $this->getCurrentSite();
101 if ($site instanceof Site) {
102 $values = GeneralUtility::trimExplode(',', $value, true);
103 foreach ($values as $test) {
104 $point = strcspn($test, '=');
105 $testValue = substr($test, $point + 1);
106 $testValue = trim($testValue);
107 $theVarName = trim(substr($test, 0, $point));
108 $methodName = 'get' . ucfirst($theVarName);
109 if (method_exists($site, $methodName)) {
110 $sitePropertyValue = call_user_func([$site, $methodName]);
111 // loose check on purpose in order to check for integer values
112 if ($testValue == $sitePropertyValue) {
113 return true;
114 }
115 }
116 }
117 }
118 break;
119 case 'siteLanguage':
120 $siteLanguage = $this->getCurrentSiteLanguage();
121 if ($siteLanguage instanceof SiteLanguage) {
122 $values = GeneralUtility::trimExplode(',', $value, true);
123 foreach ($values as $test) {
124 $point = strcspn($test, '=');
125 $testValue = substr($test, $point + 1);
126 $testValue = trim($testValue);
127 $theVarName = trim(substr($test, 0, $point));
128 $methodName = 'get' . ucfirst($theVarName);
129 if (method_exists($siteLanguage, $methodName)) {
130 $languagePropertyValue = call_user_func([$siteLanguage, $methodName]);
131 // loose check on purpose in order to check for integer values
132 if ($testValue == $languagePropertyValue) {
133 return true;
134 }
135 }
136 }
137 }
138 break;
139 default:
140 $conditionResult = $this->evaluateCustomDefinedCondition($string);
141 if ($conditionResult !== null) {
142 return $conditionResult;
143 }
144 }
145
146 return false;
147 }
148
149 /**
150 * Returns GP / ENV / TSFE / session vars
151 *
152 * @example GP:L
153 * @example TSFE:fe_user|sesData|foo|bar
154 * @example TSFE:id
155 * @example ENV:HTTP_HOST
156 *
157 * @param string $var Identifier
158 * @return mixed|null The value of the variable pointed to or NULL if variable did not exist
159 */
160 protected function getVariable($var)
161 {
162 $vars = explode(':', $var, 2);
163 $val = $this->getVariableCommon($vars);
164 if ($val === null) {
165 $splitAgain = explode('|', $vars[1], 2);
166 $k = trim($splitAgain[0]);
167 if ($k) {
168 switch ((string)trim($vars[0])) {
169 case 'TSFE':
170 if (strpos($vars[1], 'fe_user|sesData|') === 0) {
171 trigger_error(
172 'Condition on TSFE|fe_user|sesData is deprecated and will be removed in TYPO3 CMS 10',
173 E_USER_DEPRECATED
174 );
175 $val = $this->getSessionVariable(substr($vars[1], 16));
176 } else {
177 $val = $this->getGlobal('TSFE|' . $vars[1]);
178 }
179 break;
180 case 'session':
181 $val = $this->getSessionVariable($vars[1]);
182 break;
183 default:
184 }
185 }
186 }
187 return $val;
188 }
189
190 /**
191 * Return variable from current frontend user session
192 *
193 * @param string $var Session key
194 * @return mixed|null The value of the variable pointed to or NULL if variable did not exist
195 */
196 protected function getSessionVariable(string $var)
197 {
198 $retVal = null;
199 $keyParts = explode('|', $var);
200 $sessionKey = array_shift($keyParts);
201 $tsfe = $this->getTypoScriptFrontendController();
202 if ($tsfe && is_object($tsfe->fe_user)) {
203 $retVal = $tsfe->fe_user->getSessionData($sessionKey);
204 foreach ($keyParts as $keyPart) {
205 if (is_object($retVal)) {
206 $retVal = $retVal->{$keyPart};
207 } elseif (is_array($retVal)) {
208 $retVal = $retVal[$keyPart];
209 } else {
210 break;
211 }
212 }
213 }
214 return $retVal;
215 }
216
217 /**
218 * Get the usergroup list of the current user.
219 *
220 * @return string The usergroup list of the current user
221 */
222 protected function getGroupList(): string
223 {
224 /** @var UserAspect $userAspect */
225 $userAspect = $this->context->getAspect('frontend.user');
226 return implode(',', $userAspect->getGroupIds());
227 }
228
229 /**
230 * Determines the current page Id.
231 *
232 * @return int The current page Id
233 */
234 protected function determinePageId()
235 {
236 return (int)($this->getTypoScriptFrontendController()->id ?? 0);
237 }
238
239 /**
240 * Gets the properties for the current page.
241 *
242 * @return array The properties for the current page.
243 */
244 protected function getPage()
245 {
246 return $this->getTypoScriptFrontendController()->page;
247 }
248
249 /**
250 * Determines the rootline for the current page.
251 *
252 * @return array The rootline for the current page.
253 */
254 protected function determineRootline()
255 {
256 return (array)$this->getTypoScriptFrontendController()->tmpl->rootLine;
257 }
258
259 /**
260 * Get the id of the current user.
261 *
262 * @return int The id of the current user
263 */
264 protected function getUserId(): int
265 {
266 $userAspect = $this->context->getAspect('frontend.user');
267 return $userAspect->get('id');
268 }
269
270 /**
271 * Determines if a user is logged in.
272 *
273 * @return bool Determines if a user is logged in
274 */
275 protected function isUserLoggedIn(): bool
276 {
277 /** @var UserAspect $userAspect */
278 $userAspect = $this->context->getAspect('frontend.user');
279 return $userAspect->isLoggedIn();
280 }
281
282 /**
283 * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
284 */
285 protected function getTypoScriptFrontendController()
286 {
287 return $GLOBALS['TSFE'];
288 }
289
290 /**
291 * Returns the currently configured "site language" if a site is configured (= resolved) in the current request.
292 *
293 * @internal
294 */
295 protected function getCurrentSiteLanguage(): ?SiteLanguage
296 {
297 if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface
298 && $GLOBALS['TYPO3_REQUEST']->getAttribute('language') instanceof SiteLanguage) {
299 return $GLOBALS['TYPO3_REQUEST']->getAttribute('language');
300 }
301 return null;
302 }
303
304 /**
305 * Returns the currently configured site if a site is configured (= resolved) in the current request.
306 *
307 * @internal
308 */
309 protected function getCurrentSite(): ?Site
310 {
311 if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface
312 && $GLOBALS['TYPO3_REQUEST']->getAttribute('site') instanceof Site) {
313 return $GLOBALS['TYPO3_REQUEST']->getAttribute('site');
314 }
315 return null;
316 }
317 }