TYPO3 CMS  TYPO3_6-2
BooleanNode.php
Go to the documentation of this file.
1 <?php
3 
4 /* *
5  * This script is backported from the TYPO3 Flow package "TYPO3.Fluid". *
6  * *
7  * It is free software; you can redistribute it and/or modify it under *
8  * the terms of the GNU Lesser General Public License, either version 3 *
9  * of the License, or (at your option) any later version. *
10  * *
11  * The TYPO3 project - inspiring people to share! *
12  * */
13 
18 
28  static protected $comparators = array('==', '!=', '%', '>=', '>', '<=', '<');
29 
37  ^ # Start with first input symbol
38  (?: # start repeat
39  COMPARATORS # We allow all comparators
40  |\s* # Arbitary spaces
41  |-? # Numbers, possibly with the "minus" symbol in front.
42  [0-9]+ # some digits
43  (?: # and optionally a dot, followed by some more digits
44  \\.
45  [0-9]+
46  )?
47  |\'[^\'\\\\]* # single quoted string literals with possibly escaped single quotes
48  (?:
49  \\\\. # escaped character
50  [^\'\\\\]* # unrolled loop following Jeffrey E.F. Friedl
51  )*\'
52  |"[^"\\\\]* # double quoted string literals with possibly escaped double quotes
53  (?:
54  \\\\. # escaped character
55  [^"\\\\]* # unrolled loop following Jeffrey E.F. Friedl
56  )*"
57  )*
58  $/x';
59 
65  protected $leftSide;
66 
72  protected $rightSide;
73 
81  protected $comparator;
82 
89  protected $syntaxTreeNode;
90 
98  public function __construct(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\AbstractNode $syntaxTreeNode) {
99  $childNodes = $syntaxTreeNode->getChildNodes();
100  if (count($childNodes) > 3) {
101  throw new \TYPO3\CMS\Fluid\Core\Parser\Exception('A boolean expression has more than three parts.', 1244201848);
102  } elseif (count($childNodes) === 0) {
103  // In this case, we do not have child nodes; i.e. the current SyntaxTreeNode
104  // is a text node with a literal comparison like "1 == 1"
105  $childNodes = array($syntaxTreeNode);
106  }
107 
108  $this->leftSide = new \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\RootNode();
109  $this->rightSide = new \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\RootNode();
110  $this->comparator = NULL;
111  foreach ($childNodes as $childNode) {
112  if ($childNode instanceof \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\TextNode && !preg_match(str_replace('COMPARATORS', implode('|', self::$comparators), self::$booleanExpressionTextNodeCheckerRegularExpression), $childNode->getText())) {
113  // $childNode is text node, and no comparator found.
114  $this->comparator = NULL;
115  // skip loop and fall back to classical to boolean conversion.
116  break;
117  }
118 
119  if ($this->comparator !== NULL) {
120  // comparator already set, we are evaluating the right side of the comparator
121  $this->rightSide->addChildNode($childNode);
122  } elseif ($childNode instanceof \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\TextNode
123  && ($this->comparator = $this->getComparatorFromString($childNode->getText()))) {
124  // comparator in current string segment
125  $explodedString = explode($this->comparator, $childNode->getText());
126  if (isset($explodedString[0]) && trim($explodedString[0]) !== '') {
127  $value = trim($explodedString[0]);
128  if (is_numeric($value)) {
129  $this->leftSide->addChildNode(new \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\NumericNode($value));
130  } else {
131  $this->leftSide->addChildNode(new \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\TextNode(preg_replace('/(^[\'"]|[\'"]$)/', '', $value)));
132  }
133  }
134  if (isset($explodedString[1]) && trim($explodedString[1]) !== '') {
135  $value = trim($explodedString[1]);
136  if (is_numeric($value)) {
137  $this->rightSide->addChildNode(new \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\NumericNode($value));
138  } else {
139  $this->rightSide->addChildNode(new \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\TextNode(preg_replace('/(^[\'"]|[\'"]$)/', '', $value)));
140  }
141  }
142  } else {
143  // comparator not found yet, on the left side of the comparator
144  $this->leftSide->addChildNode($childNode);
145  }
146  }
147 
148  if ($this->comparator === NULL) {
149  // No Comparator found, we need to evaluate the given syntax tree node manually
150  $this->syntaxTreeNode = $syntaxTreeNode;
151  }
152  }
153 
158  public function getComparator() {
159  return $this->comparator;
160  }
161 
166  public function getSyntaxTreeNode() {
167  return $this->syntaxTreeNode;
168  }
169 
174  public function getLeftSide() {
175  return $this->leftSide;
176  }
177 
182  public function getRightSide() {
183  return $this->rightSide;
184  }
185 
190  public function evaluate(\TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface $renderingContext) {
191  if ($this->comparator !== NULL) {
192  return self::evaluateComparator($this->comparator, $this->leftSide->evaluate($renderingContext), $this->rightSide->evaluate($renderingContext));
193  } else {
194  $value = $this->syntaxTreeNode->evaluate($renderingContext);
195  return self::convertToBoolean($value);
196  }
197  }
198 
219  static public function evaluateComparator($comparator, $evaluatedLeftSide, $evaluatedRightSide) {
220  switch ($comparator) {
221  case '==':
222  if (is_object($evaluatedLeftSide) || is_object($evaluatedRightSide)) {
223  return ($evaluatedLeftSide === $evaluatedRightSide);
224  } else {
225  return ($evaluatedLeftSide == $evaluatedRightSide);
226  }
227  case '!=':
228  if (is_object($evaluatedLeftSide) || is_object($evaluatedRightSide)) {
229  return ($evaluatedLeftSide !== $evaluatedRightSide);
230  } else {
231  return ($evaluatedLeftSide != $evaluatedRightSide);
232  }
233  case '%':
234  if (!self::isComparable($evaluatedLeftSide, $evaluatedRightSide)) {
235  return FALSE;
236  }
237  return (boolean) ((int)$evaluatedLeftSide % (int)$evaluatedRightSide);
238  case '>':
239  if (!self::isComparable($evaluatedLeftSide, $evaluatedRightSide)) {
240  return FALSE;
241  }
242  return $evaluatedLeftSide > $evaluatedRightSide;
243  case '>=':
244  if (!self::isComparable($evaluatedLeftSide, $evaluatedRightSide)) {
245  return FALSE;
246  }
247  return $evaluatedLeftSide >= $evaluatedRightSide;
248  case '<':
249  if (!self::isComparable($evaluatedLeftSide, $evaluatedRightSide)) {
250  return FALSE;
251  }
252  return $evaluatedLeftSide < $evaluatedRightSide;
253  case '<=':
254  if (!self::isComparable($evaluatedLeftSide, $evaluatedRightSide)) {
255  return FALSE;
256  }
257  return $evaluatedLeftSide <= $evaluatedRightSide;
258  default:
259  throw new \TYPO3\CMS\Fluid\Core\Parser\Exception('Comparator "' . $comparator . '" is not implemented.', 1244234398);
260  }
261  }
262 
273  static protected function isComparable($evaluatedLeftSide, $evaluatedRightSide) {
274  if ((is_null($evaluatedLeftSide) || is_string($evaluatedLeftSide))
275  && is_string($evaluatedRightSide)) {
276  return TRUE;
277  }
278  if (is_bool($evaluatedLeftSide) || is_null($evaluatedLeftSide)) {
279  return TRUE;
280  }
281  if (is_object($evaluatedLeftSide) && is_object($evaluatedRightSide)) {
282  return TRUE;
283  }
284  if ((is_string($evaluatedLeftSide) || is_resource($evaluatedLeftSide) || is_numeric($evaluatedLeftSide))
285  && (is_string($evaluatedRightSide) || is_resource($evaluatedRightSide) || is_numeric($evaluatedRightSide))) {
286  return TRUE;
287  }
288  if (is_array($evaluatedLeftSide) && is_array($evaluatedRightSide)) {
289  return TRUE;
290  }
291  return FALSE;
292  }
293 
300  protected function getComparatorFromString($string) {
301  foreach (self::$comparators as $comparator) {
302  if (strpos($string, $comparator) !== FALSE) {
303  return $comparator;
304  }
305  }
306  return NULL;
307  }
308 
317  static public function convertToBoolean($value) {
318  if (is_bool($value)) {
319  return $value;
320  }
321 
322  if (is_integer($value) || is_float($value)) {
323  return !empty($value);
324  }
325 
326  if (is_numeric($value)) {
327  return ($value != 0);
328  }
329 
330  if (is_string($value)) {
331  return (!empty($value) && strtolower($value) !== 'false');
332  }
333  if (is_array($value) || (is_object($value) && $value instanceof \Countable)) {
334  return (bool) count($value);
335  }
336  if (is_object($value)) {
337  return TRUE;
338  }
339 
340  return FALSE;
341  }
342 }
evaluate(\TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface $renderingContext)
static evaluateComparator($comparator, $evaluatedLeftSide, $evaluatedRightSide)
__construct(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\AbstractNode $syntaxTreeNode)
Definition: BooleanNode.php:98
static isComparable($evaluatedLeftSide, $evaluatedRightSide)