, Heimspiel GmbH * @package Vhs * @subpackage ViewHelpers */ class IfViewHelper extends AbstractConditionViewHelper { use ConditionViewHelperTrait; const OPERATOR_IS_EQUAL = '=='; const OPERATOR_IS_NOT_EQUAL = '!='; const OPERATOR_IS_GREATER_OR_EQUAL = '>='; const OPERATOR_IS_SMALLER_OR_EQUAL = '<='; const OPERATOR_IS_SMALLER = '<'; const OPERATOR_IS_GREATER = '>'; const OPERATOR_LOGICAL_AND = 'AND'; const OPERATOR_LOGICAL_OR = 'OR'; const OPERATOR_BOOLEAN_AND = '&&'; const OPERATOR_BOOLEAN_OR = '||'; /** * @var array */ static protected $comparisonOperators = array( self::OPERATOR_IS_EQUAL => self::OPERATOR_IS_EQUAL, self::OPERATOR_IS_NOT_EQUAL => self::OPERATOR_IS_NOT_EQUAL, self::OPERATOR_IS_GREATER_OR_EQUAL => self::OPERATOR_IS_GREATER_OR_EQUAL, self::OPERATOR_IS_SMALLER_OR_EQUAL => self::OPERATOR_IS_SMALLER_OR_EQUAL, self::OPERATOR_IS_SMALLER => self::OPERATOR_IS_SMALLER, self::OPERATOR_IS_GREATER => self::OPERATOR_IS_GREATER ); /** * @var array */ static protected $logicalOperators = array( self::OPERATOR_LOGICAL_AND => self::OPERATOR_LOGICAL_AND, self::OPERATOR_LOGICAL_OR => self::OPERATOR_LOGICAL_OR, self::OPERATOR_BOOLEAN_AND => self::OPERATOR_LOGICAL_AND, self::OPERATOR_BOOLEAN_OR => self::OPERATOR_LOGICAL_OR ); /** * Lower value means less precedence * * @var array */ static protected $operatorPrecedence = array( self::OPERATOR_LOGICAL_OR => 0, self::OPERATOR_LOGICAL_AND => 1 ); /** * Initialize * * @return void * @api */ public function initializeArguments() { self::registerArgument('stack', 'array', 'The stack to be evaluated', TRUE); } /** * This method decides if the condition is TRUE or FALSE. It can be overriden in extending viewhelpers to adjust functionality. * * @param array $arguments ViewHelper arguments to evaluate the condition for this ViewHelper, allows for flexiblity in overriding this method. * @return bool */ static protected function evaluateCondition($arguments = NULL) { return TRUE === self::evaluateStack($arguments['stack']); } /** * @throws \RuntimeException * @param array $stack * @return boolean */ static protected function evaluateStack(array $stack) { $stackCount = count($stack); if (0 === $stackCount) { return FALSE; } elseif (1 === $stackCount) { return BooleanNode::convertToBoolean(reset($stack)); } elseif (3 === $stackCount) { list ($leftSide, $operator, $rightSide) = array_values($stack); if (TRUE === is_string($operator) && TRUE === isset(self::$comparisonOperators[$operator])) { $operator = self::$comparisonOperators[$operator]; return BooleanNode::evaluateComparator($operator, $leftSide, $rightSide); } } $operator = FALSE; $operatorPrecedence = PHP_INT_MAX; $operatorIndex = FALSE; foreach ($stack as $index => $element) { if (TRUE === is_string($element) && TRUE === isset(self::$logicalOperators[$element])) { $currentOperator = self::$logicalOperators[$element]; $currentOperatorPrecedence = self::$operatorPrecedence[$currentOperator]; if ($currentOperatorPrecedence <= $operatorPrecedence) { $operator = $currentOperator; $operatorPrecedence = $currentOperatorPrecedence; $operatorIndex = $index; } } } if (FALSE === $operator) { throw new \RuntimeException('The stack was not comparable and did not include any logical operators.', 1385071197); } $operatorIndex = array_search($operatorIndex, array_keys($stack)); if (0 === $operatorIndex || $operatorIndex + 1 >= $stackCount) { throw new \RuntimeException('The stack may not contain a logical operator at the first or last element.', 1385072228); } $leftSide = array_slice($stack, 0, $operatorIndex); $rightSide = array_slice($stack, $operatorIndex + 1); return self::evaluateLogicalOperator($leftSide, $operator, $rightSide); } /** * @throws \RuntimeException * @param array $leftSide * @param string $operator * @param array $rightSide * @return boolean */ static protected function evaluateLogicalOperator(array $leftSide, $operator, array $rightSide) { $leftCondition = self::evaluateStack(self::prepareSideForEvaluation($leftSide)); $rightCondition = self::evaluateStack(self::prepareSideForEvaluation($rightSide)); if (self::OPERATOR_LOGICAL_AND === $operator) { return $leftCondition && $rightCondition; } elseif (self::OPERATOR_LOGICAL_OR === $operator) { return $leftCondition || $rightCondition; } throw new \RuntimeException('The stack could not be evaluated (internal error).', 1385072357); } /** * @param array $side * @return array */ static protected function prepareSideForEvaluation(array $side) { if (1 === count($side)) { $element = reset($side); if (TRUE === is_array($element)) { return $element; } } return $side; } }