[FEATURE] Custom TypoScript-conditions also in backend
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Configuration / TypoScript / ConditionMatching / AbstractConditionMatcher.php
1 <?php
2 namespace TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Utility\GeneralUtility;
18
19 /**
20 * Matching TypoScript conditions
21 *
22 * Used with the TypoScript parser.
23 * Matches browserinfo, IPnumbers for use with templates
24 *
25 * @author Oliver Hader <oliver@typo3.org>
26 */
27 abstract class AbstractConditionMatcher {
28
29 /**
30 * Id of the current page.
31 *
32 * @var int
33 */
34 protected $pageId;
35
36 /**
37 * The rootline for the current page.
38 *
39 * @var array
40 */
41 protected $rootline;
42
43 /**
44 * Whether to simulate the behaviour and match all conditions
45 * (used in TypoScript object browser).
46 *
47 * @var bool
48 */
49 protected $simulateMatchResult = FALSE;
50
51 /**
52 * Whether to simulat the behaviour and match specific conditions
53 * (used in TypoScript object browser).
54 *
55 * @var array
56 */
57 protected $simulateMatchConditions = array();
58
59 /**
60 * Sets the id of the page to evaluate conditions for.
61 *
62 * @param int $pageId Id of the page (must be positive)
63 * @return void
64 */
65 public function setPageId($pageId) {
66 if (is_integer($pageId) && $pageId > 0) {
67 $this->pageId = $pageId;
68 }
69 }
70
71 /**
72 * Gets the id of the page to evaluate conditions for.
73 *
74 * @return int Id of the page
75 */
76 public function getPageId() {
77 return $this->pageId;
78 }
79
80 /**
81 * Sets the rootline.
82 *
83 * @param array $rootline The rootline to be used for matching (must have elements)
84 * @return void
85 */
86 public function setRootline(array $rootline) {
87 if (count($rootline)) {
88 $this->rootline = $rootline;
89 }
90 }
91
92 /**
93 * Gets the rootline.
94 *
95 * @return array The rootline to be used for matching
96 */
97 public function getRootline() {
98 return $this->rootline;
99 }
100
101 /**
102 * Sets whether to simulate the behaviour and match all conditions.
103 *
104 * @param bool $simulateMatchResult Whether to simulate positive matches
105 * @return void
106 */
107 public function setSimulateMatchResult($simulateMatchResult) {
108 if (is_bool($simulateMatchResult)) {
109 $this->simulateMatchResult = $simulateMatchResult;
110 }
111 }
112
113 /**
114 * Sets whether to simulate the behaviour and match specific conditions.
115 *
116 * @param array $simulateMatchConditions Conditions to simulate a match for
117 * @return void
118 */
119 public function setSimulateMatchConditions(array $simulateMatchConditions) {
120 $this->simulateMatchConditions = $simulateMatchConditions;
121 }
122
123 /**
124 * Normalizes an expression and removes the first and last square bracket.
125 * + OR normalization: "...]OR[...", "...]||[...", "...][..." --> "...]||[..."
126 * + AND normalization: "...]AND[...", "...]&&[..." --> "...]&&[..."
127 *
128 * @param string $expression The expression to be normalized (e.g. "[A] && [B] OR [C]")
129 * @return string The normalized expression (e.g. "[A]&&[B]||[C]")
130 */
131 protected function normalizeExpression($expression) {
132 $normalizedExpression = preg_replace(array(
133 '/\\]\\s*(OR|\\|\\|)?\\s*\\[/i',
134 '/\\]\\s*(AND|&&)\\s*\\[/i'
135 ), array(
136 ']||[',
137 ']&&['
138 ), trim($expression));
139 return $normalizedExpression;
140 }
141
142 /**
143 * Matches a TypoScript condition expression.
144 *
145 * @param string $expression The expression to match
146 * @return bool Whether the expression matched
147 */
148 public function match($expression) {
149 // Return directly if result should be simulated:
150 if ($this->simulateMatchResult) {
151 return $this->simulateMatchResult;
152 }
153 // Return directly if matching for specific condition is simulated only:
154 if (count($this->simulateMatchConditions)) {
155 return in_array($expression, $this->simulateMatchConditions);
156 }
157 // Sets the current pageId if not defined yet:
158 if (!isset($this->pageId)) {
159 $this->pageId = $this->determinePageId();
160 }
161 // Sets the rootline if not defined yet:
162 if (!isset($this->rootline)) {
163 $this->rootline = $this->determineRootline();
164 }
165 $result = FALSE;
166 $normalizedExpression = $this->normalizeExpression($expression);
167 // First and last character must be square brackets (e.g. "[A]&&[B]":
168 if ($normalizedExpression[0] === '[' && substr($normalizedExpression, -1) === ']') {
169 $innerExpression = substr($normalizedExpression, 1, -1);
170 $orParts = explode(']||[', $innerExpression);
171 foreach ($orParts as $orPart) {
172 $andParts = explode(']&&[', $orPart);
173 foreach ($andParts as $andPart) {
174 $result = $this->evaluateCondition($andPart);
175 // If condition in AND context fails, the whole block is FALSE:
176 if ($result === FALSE) {
177 break;
178 }
179 }
180 // If condition in OR context succeeds, the whole expression is TRUE:
181 if ($result === TRUE) {
182 break;
183 }
184 }
185 }
186 return $result;
187 }
188
189 /**
190 * Evaluates a TypoScript condition given as input, eg. "[applicationContext = Production][...(other condition)...]"
191 *
192 * @param string $key The condition to match against its criterias.
193 * @param string $value
194 * @return NULL|boolean Result of the evaluation; NULL if condition could not be evaluated
195 */
196 protected function evaluateConditionCommon($key, $value) {
197 if (GeneralUtility::inList('browser,device,version,system,useragent', strtolower($key))) {
198 GeneralUtility::deprecationLog(
199 'Usage of client related conditions (browser, device, version, system, useragent) is deprecated since 7.0.'
200 );
201 $browserInfo = $this->getBrowserInfo(GeneralUtility::getIndpEnv('HTTP_USER_AGENT'));
202 }
203 $keyParts = GeneralUtility::trimExplode('|', $key);
204 switch ($keyParts[0]) {
205 case 'applicationContext':
206 $values = GeneralUtility::trimExplode(',', $value, TRUE);
207 $currentApplicationContext = GeneralUtility::getApplicationContext();
208 foreach ($values as $applicationContext) {
209 if ($this->searchStringWildcard($currentApplicationContext, $applicationContext)) {
210 return TRUE;
211 }
212 }
213 return FALSE;
214 break;
215 case 'browser':
216 $values = GeneralUtility::trimExplode(',', $value, TRUE);
217 // take all identified browsers into account, eg chrome deliver
218 // webkit=>532.5, chrome=>4.1, safari=>532.5
219 // so comparing string will be
220 // "webkit532.5 chrome4.1 safari532.5"
221 $all = '';
222 foreach ($browserInfo['all'] as $key => $value) {
223 $all .= $key . $value . ' ';
224 }
225 foreach ($values as $test) {
226 if (stripos($all, $test) !== FALSE) {
227 return TRUE;
228 }
229 }
230 return FALSE;
231 break;
232 case 'version':
233 $values = GeneralUtility::trimExplode(',', $value, TRUE);
234 foreach ($values as $test) {
235 if (strcspn($test, '=<>') == 0) {
236 switch ($test[0]) {
237 case '=':
238 if (doubleval(substr($test, 1)) == $browserInfo['version']) {
239 return TRUE;
240 }
241 break;
242 case '<':
243 if (doubleval(substr($test, 1)) > $browserInfo['version']) {
244 return TRUE;
245 }
246 break;
247 case '>':
248 if (doubleval(substr($test, 1)) < $browserInfo['version']) {
249 return TRUE;
250 }
251 break;
252 }
253 } elseif (strpos(' ' . $browserInfo['version'], $test) == 1) {
254 return TRUE;
255 }
256 }
257 return FALSE;
258 break;
259 case 'system':
260 $values = GeneralUtility::trimExplode(',', $value, TRUE);
261 // Take all identified systems into account, e.g. mac for iOS, Linux
262 // for android and Windows NT for Windows XP
263 $allSystems = ' ' . implode(' ', $browserInfo['all_systems']);
264 foreach ($values as $test) {
265 if (stripos($allSystems, $test) !== FALSE) {
266 return TRUE;
267 }
268 }
269 return FALSE;
270 break;
271 case 'device':
272 if (!isset($this->deviceInfo)) {
273 $this->deviceInfo = $this->getDeviceType(GeneralUtility::getIndpEnv('HTTP_USER_AGENT'));
274 }
275 $values = GeneralUtility::trimExplode(',', $value, TRUE);
276 foreach ($values as $test) {
277 if ($this->deviceInfo == $test) {
278 return TRUE;
279 }
280 }
281 return FALSE;
282 break;
283 case 'useragent':
284 $test = trim($value);
285 if ($test !== '') {
286 return $this->searchStringWildcard((string)$browserInfo['useragent'], $test);
287 } else {
288 return FALSE;
289 }
290 break;
291 case 'language':
292 if (GeneralUtility::getIndpEnv('HTTP_ACCEPT_LANGUAGE') === $value) {
293 return TRUE;
294 }
295 $values = GeneralUtility::trimExplode(',', $value, TRUE);
296 foreach ($values as $test) {
297 if (preg_match('/^\\*.+\\*$/', $test)) {
298 $allLanguages = preg_split('/[,;]/', GeneralUtility::getIndpEnv('HTTP_ACCEPT_LANGUAGE'));
299 if (in_array(substr($test, 1, -1), $allLanguages)) {
300 return TRUE;
301 }
302 } elseif (GeneralUtility::getIndpEnv('HTTP_ACCEPT_LANGUAGE') == $test) {
303 return TRUE;
304 }
305 }
306 return FALSE;
307 break;
308 case 'IP':
309 if ($value === 'devIP') {
310 $value = trim($GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']);
311 }
312
313 return (bool)GeneralUtility::cmpIP(GeneralUtility::getIndpEnv('REMOTE_ADDR'), $value);
314 break;
315 case 'hostname':
316 return (bool)GeneralUtility::cmpFQDN(GeneralUtility::getIndpEnv('REMOTE_ADDR'), $value);
317 break;
318 case 'hour':
319 case 'minute':
320 case 'month':
321 case 'year':
322 case 'dayofweek':
323 case 'dayofmonth':
324 case 'dayofyear':
325 // In order to simulate time properly in templates.
326 $theEvalTime = $GLOBALS['SIM_EXEC_TIME'];
327 switch ($key) {
328 case 'hour':
329 $theTestValue = date('H', $theEvalTime);
330 break;
331 case 'minute':
332 $theTestValue = date('i', $theEvalTime);
333 break;
334 case 'month':
335 $theTestValue = date('m', $theEvalTime);
336 break;
337 case 'year':
338 $theTestValue = date('Y', $theEvalTime);
339 break;
340 case 'dayofweek':
341 $theTestValue = date('w', $theEvalTime);
342 break;
343 case 'dayofmonth':
344 $theTestValue = date('d', $theEvalTime);
345 break;
346 case 'dayofyear':
347 $theTestValue = date('z', $theEvalTime);
348 break;
349 }
350 $theTestValue = (int)$theTestValue;
351 // comp
352 $values = GeneralUtility::trimExplode(',', $value, TRUE);
353 foreach ($values as $test) {
354 if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($test)) {
355 $test = '=' . $test;
356 }
357 if ($this->compareNumber($test, $theTestValue)) {
358 return TRUE;
359 }
360 }
361 return FALSE;
362 break;
363 case 'compatVersion':
364 return GeneralUtility::compat_version($value);
365 break;
366 case 'loginUser':
367 if ($this->isUserLoggedIn()) {
368 $values = GeneralUtility::trimExplode(',', $value, TRUE);
369 foreach ($values as $test) {
370 if ($test == '*' || (string)$this->getUserId() === (string)$test) {
371 return TRUE;
372 }
373 }
374 } elseif ($value === '') {
375 return TRUE;
376 }
377 return FALSE;
378 break;
379 case 'page':
380 if ($keyParts[1]) {
381 $page = $this->getPage();
382 $property = $keyParts[1];
383 if (!empty($page) && isset($page[$property]) && (string)$page[$property] === (string)$value) {
384 return TRUE;
385 }
386 }
387 return FALSE;
388 break;
389 case 'globalVar':
390 $values = GeneralUtility::trimExplode(',', $value, TRUE);
391 foreach ($values as $test) {
392 $point = strcspn($test, '!=<>');
393 $theVarName = substr($test, 0, $point);
394 $nv = $this->getVariable(trim($theVarName));
395 $testValue = substr($test, $point);
396 if ($this->compareNumber($testValue, $nv)) {
397 return TRUE;
398 }
399 }
400 return FALSE;
401 break;
402 case 'globalString':
403 $values = GeneralUtility::trimExplode(',', $value, TRUE);
404 foreach ($values as $test) {
405 $point = strcspn($test, '=');
406 $theVarName = substr($test, 0, $point);
407 $nv = (string)$this->getVariable(trim($theVarName));
408 $testValue = substr($test, $point + 1);
409 if ($this->searchStringWildcard($nv, trim($testValue))) {
410 return TRUE;
411 }
412 }
413 return FALSE;
414 break;
415 case 'userFunc':
416 $matches = array();
417 preg_match_all('/^\s*([^\(\s]+)\s*(?:\((.*)\))?\s*$/', $value, $matches);
418 $funcName = $matches[1][0];
419 $funcValues = $matches[2][0] ? $this->parseUserFuncArguments($matches[2][0]) : array();
420 if (is_callable($funcName) && call_user_func_array($funcName, $funcValues)) {
421 return TRUE;
422 }
423 return FALSE;
424 break;
425 }
426 return NULL;
427 }
428
429 /**
430 * Evaluates a TypoScript condition given as input with a custom class name,
431 * e.g. "[MyCompany\MyPackage\ConditionMatcher\MyOwnConditionMatcher = myvalue]"
432 *
433 * @param string $condition The condition to match
434 * @return NULL|boolean Result of the evaluation; NULL if condition could not be evaluated
435 * @throws \TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException
436 */
437 protected function evaluateCustomDefinedCondition($condition) {
438 $conditionResult = NULL;
439
440 list($conditionClassName, $conditionParameters) = GeneralUtility::trimExplode(' ', $condition, FALSE, 2);
441
442 // Check if the condition class name is a valid class
443 // This is necessary to not stop here for the conditions ELSE and GLOBAL
444 if (class_exists($conditionClassName)) {
445 // Use like this: [MyCompany\MyPackage\ConditionMatcher\MyOwnConditionMatcher = myvalue]
446 /** @var \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition $conditionObject */
447 $conditionObject = GeneralUtility::makeInstance($conditionClassName);
448 if (($conditionObject instanceof \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition) === FALSE) {
449 throw new \TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException(
450 '"' . $conditionClassName . '" is not a valid TypoScript Condition object.',
451 1410286153
452 );
453 }
454
455 $conditionParameters = $this->parseUserFuncArguments($conditionParameters);
456 $conditionObject->setConditionMatcherInstance($this);
457 $conditionResult = $conditionObject->matchCondition($conditionParameters);
458 }
459
460 return $conditionResult;
461 }
462
463 /**
464 * Parses arguments to the userFunc.
465 *
466 * @param string $arguments
467 * @return array
468 */
469 protected function parseUserFuncArguments($arguments) {
470 $result = array();
471 $arguments = trim($arguments);
472 while ($arguments) {
473 if ($arguments[0] === ',') {
474 $result[] = '';
475 $arguments = substr($arguments, 1);
476 } else {
477 $pos = strcspn($arguments, ',\'"');
478 if ($pos == 0) {
479 // We hit a quote of some kind
480 $quote = $arguments[0];
481 $segment = preg_replace('/^(.*?[^\\\])' . $quote . '.*$/', '\1', substr($arguments, 1));
482 $segment = str_replace('\\' . $quote, $quote, $segment);
483 $result[] = $segment;
484 $offset = strpos($arguments, ',', strlen($segment) + 2);
485 if ($offset === FALSE) {
486 $offset = strlen($arguments);
487 }
488 $arguments = substr($arguments, $offset);
489 } else {
490 $result[] = trim(substr($arguments, 0, $pos));
491 $arguments = substr($arguments, $pos + 1);
492 }
493 }
494 $arguments = trim($arguments);
495 };
496 return $result;
497 }
498
499 /**
500 * Get variable common
501 *
502 * @param array $vars
503 * @return mixed Whatever value. If none, then NULL.
504 */
505 protected function getVariableCommon(array $vars) {
506 $value = NULL;
507 if (count($vars) == 1) {
508 $value = $this->getGlobal($vars[0]);
509 } else {
510 $splitAgain = explode('|', $vars[1], 2);
511 $k = trim($splitAgain[0]);
512 if ($k) {
513 switch ((string)trim($vars[0])) {
514 case 'GP':
515 $value = GeneralUtility::_GP($k);
516 break;
517 case 'ENV':
518 $value = getenv($k);
519 break;
520 case 'IENV':
521 $value = GeneralUtility::getIndpEnv($k);
522 break;
523 case 'LIT':
524 return trim($vars[1]);
525 break;
526 default:
527 return NULL;
528 }
529 // If array:
530 if (count($splitAgain) > 1) {
531 if (is_array($value) && trim($splitAgain[1])) {
532 $value = $this->getGlobal($splitAgain[1], $value);
533 } else {
534 $value = '';
535 }
536 }
537 }
538 }
539 return $value;
540 }
541
542 /**
543 * Evaluates a $leftValue based on an operator: "<", ">", "<=", ">=", "!=" or "="
544 *
545 * @param string $test The value to compare with on the form [operator][number]. Eg. "< 123
546 * @param float $leftValue The value on the left side
547 * @return bool If $value is "50" and $test is "< 123" then it will return TRUE.
548 */
549 protected function compareNumber($test, $leftValue) {
550 if (preg_match('/^(!?=+|<=?|>=?)\\s*([^\\s]*)\\s*$/', $test, $matches)) {
551 $operator = $matches[1];
552 $rightValue = $matches[2];
553 switch ($operator) {
554 case '>=':
555 return $leftValue >= doubleval($rightValue);
556 break;
557 case '<=':
558 return $leftValue <= doubleval($rightValue);
559 break;
560 case '!=':
561 // multiple values may be split with '|'
562 // see if none matches ("not in list")
563 $found = FALSE;
564 $rightValueParts = GeneralUtility::trimExplode('|', $rightValue);
565 foreach ($rightValueParts as $rightValueSingle) {
566 if ($leftValue == doubleval($rightValueSingle)) {
567 $found = TRUE;
568 break;
569 }
570 }
571 return $found === FALSE;
572 break;
573 case '<':
574 return $leftValue < doubleval($rightValue);
575 break;
576 case '>':
577 return $leftValue > doubleval($rightValue);
578 break;
579 default:
580 // nothing valid found except '=', use '='
581 // multiple values may be split with '|'
582 // see if one matches ("in list")
583 $found = FALSE;
584 $rightValueParts = GeneralUtility::trimExplode('|', $rightValue);
585 foreach ($rightValueParts as $rightValueSingle) {
586 if ($leftValue == $rightValueSingle) {
587 $found = TRUE;
588 break;
589 }
590 }
591 return $found;
592 }
593 }
594 return FALSE;
595 }
596
597 /**
598 * Matching two strings against each other, supporting a "*" wildcard or (if wrapped in "/") PCRE regular expressions
599 *
600 * @param string $haystack The string in which to find $needle.
601 * @param string $needle The string to find in $haystack
602 * @return bool Returns TRUE if $needle matches or is found in (according to wildcards) in $haystack. Eg. if $haystack is "Netscape 6.5" and $needle is "Net*" or "Net*ape" then it returns TRUE.
603 */
604 protected function searchStringWildcard($haystack, $needle) {
605 $result = FALSE;
606 if ($haystack === $needle) {
607 $result = TRUE;
608 } elseif ($needle) {
609 if (preg_match('/^\\/.+\\/$/', $needle)) {
610 // Regular expression, only "//" is allowed as delimiter
611 $regex = $needle;
612 } else {
613 $needle = str_replace(array('*', '?'), array('###MANY###', '###ONE###'), $needle);
614 $regex = '/^' . preg_quote($needle, '/') . '$/';
615 // Replace the marker with .* to match anything (wildcard)
616 $regex = str_replace(array('###MANY###', '###ONE###'), array('.*', '.'), $regex);
617 }
618 $result = (bool)preg_match($regex, $haystack);
619 }
620 return $result;
621 }
622
623 /**
624 * Generates an array with abstracted browser information
625 *
626 * @param string $userAgent The useragent string, \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('HTTP_USER_AGENT')
627 * @return array Contains keys "browser", "version", "system
628 */
629 protected function getBrowserInfo($userAgent) {
630 return \TYPO3\CMS\Core\Utility\ClientUtility::getBrowserInfo($userAgent);
631 }
632
633 /**
634 * Gets a code for a browsing device based on the input useragent string.
635 *
636 * @param string $userAgent The useragent string, \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('HTTP_USER_AGENT')
637 * @return string Code for the specific device type
638 * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8
639 */
640 protected function getDeviceType($userAgent) {
641 return \TYPO3\CMS\Core\Utility\ClientUtility::getDeviceType($userAgent);
642 }
643
644 /**
645 * Return global variable where the input string $var defines array keys separated by "|"
646 * Example: $var = "HTTP_SERVER_VARS | something" will return the value $GLOBALS['HTTP_SERVER_VARS']['something'] value
647 *
648 * @param string $var Global var key, eg. "HTTP_GET_VAR" or "HTTP_GET_VARS|id" to get the GET parameter "id" back.
649 * @param array $source Alternative array than $GLOBAL to get variables from.
650 * @return mixed Whatever value. If none, then blank string.
651 */
652 protected function getGlobal($var, $source = NULL) {
653 $vars = explode('|', $var);
654 $c = count($vars);
655 $k = trim($vars[0]);
656 $theVar = isset($source) ? $source[$k] : $GLOBALS[$k];
657 for ($a = 1; $a < $c; $a++) {
658 if (!isset($theVar)) {
659 break;
660 }
661 $key = trim($vars[$a]);
662 if (is_object($theVar)) {
663 $theVar = $theVar->{$key};
664 } elseif (is_array($theVar)) {
665 $theVar = $theVar[$key];
666 } else {
667 return '';
668 }
669 }
670 if (!is_array($theVar) && !is_object($theVar)) {
671 return $theVar;
672 } else {
673 return '';
674 }
675 }
676
677 /**
678 * Evaluates a TypoScript condition given as input, eg. "[browser=net][...(other conditions)...]"
679 *
680 * @param string $string The condition to match against its criterias.
681 * @return bool Whether the condition matched
682 * @see \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::parse()
683 */
684 abstract protected function evaluateCondition($string);
685
686 /**
687 * Gets the value of a variable.
688 *
689 * Examples of names:
690 * + TSFE:id
691 * + GP:firstLevel|secondLevel
692 * + _GET|firstLevel|secondLevel
693 * + LIT:someLiteralValue
694 *
695 * @param string $name The name of the variable to fetch the value from
696 * @return mixed The value of the given variable (string) or NULL if variable did not exist
697 */
698 abstract protected function getVariable($name);
699
700 /**
701 * Gets the usergroup list of the current user.
702 *
703 * @return string The usergroup list of the current user
704 */
705 abstract protected function getGroupList();
706
707 /**
708 * Determines the current page Id.
709 *
710 * @return int The current page Id
711 */
712 abstract protected function determinePageId();
713
714 /**
715 * Gets the properties for the current page.
716 *
717 * @return array The properties for the current page.
718 */
719 abstract protected function getPage();
720
721 /**
722 * Determines the rootline for the current page.
723 *
724 * @return array The rootline for the current page.
725 */
726 abstract protected function determineRootline();
727
728 /**
729 * Gets the id of the current user.
730 *
731 * @return int The id of the current user
732 */
733 abstract protected function getUserId();
734
735 /**
736 * Determines if a user is logged in.
737 *
738 * @return bool Determines if a user is logged in
739 */
740 abstract protected function isUserLoggedIn();
741
742 /**
743 * Sets a log message.
744 *
745 * @param string $message The log message to set/write
746 * @return void
747 */
748 abstract protected function log($message);
749
750 }