예제 #1
0
 /**
  * Process the Repeat operator.
  *
  * Note: NULL values are simply ignored. If all sub-expressions are NULL, NULL is
  * returned.
  *
  * @return \qtism\runtime\common\OrderedContainer An ordered container filled sequentially by evaluating each sub-expressions, repeated a 'numberRepeats' of times. NULL is returned if all sub-expressions are NULL or numberRepeats < 1.
  * @throws \qtism\runtime\expressions\operators\OperatorProcessingException
  */
 public function process()
 {
     $operands = $this->getOperands();
     // get the value of numberRepeats
     $expression = $this->getExpression();
     $numberRepeats = $expression->getNumberRepeats();
     if (gettype($numberRepeats) === 'string') {
         // Variable reference found.
         $state = $this->getState();
         $varName = Utils::sanitizeVariableRef($numberRepeats);
         $varValue = $state[$varName];
         if (is_null($varValue) === true) {
             $msg = "The variable with name '{$varName}' could not be resolved.";
             throw new OperatorProcessingException($msg, $this);
         } elseif ($varValue instanceof Integer) {
             $msg = "The variable with name '{$varName}' is not an integer value.";
             throw new OperatorProcessingException($msg, $this);
         }
         $numberRepeats = $varValue->getValue();
     }
     if ($numberRepeats < 1) {
         return null;
     }
     $result = null;
     for ($i = 0; $i < $numberRepeats; $i++) {
         $refType = null;
         foreach ($operands as $operand) {
             // If null, ignore
             if (is_null($operand) || $operand instanceof Container && $operand->isNull()) {
                 continue;
             }
             // Check cardinality.
             if ($operand->getCardinality() !== Cardinality::SINGLE && $operand->getCardinality() !== Cardinality::ORDERED) {
                 $msg = "The Repeat operator only accepts operands with a single or ordered cardinality.";
                 throw new OperatorProcessingException($msg, $this, OperatorProcessingException::WRONG_CARDINALITY);
             }
             // Check baseType.
             $currentType = RuntimeUtils::inferBaseType($operand);
             if ($refType !== null && $currentType !== $refType) {
                 $msg = "The Repeat operator only accepts operands with the same baseType.";
                 throw new OperatorProcessingException($msg, $this, OperatorProcessingException::WRONG_BASETYPE);
             } elseif (is_null($result)) {
                 $refType = $currentType;
                 $result = new OrderedContainer($refType);
             }
             // Okay we are good...
             $operandCardinality = RuntimeUtils::inferCardinality($operand);
             if ($operandCardinality !== Cardinality::ORDERED) {
                 $operand = new OrderedContainer($currentType, array($operand));
             }
             foreach ($operand as $o) {
                 $result[] = $o instanceof QtiDatatype ? clone $o : $o;
             }
         }
     }
     if (isset($result) && $result->isNull() !== true) {
         return $result;
     } else {
         return null;
     }
 }