/**
  * Process the PatternMatch.
  *
  * @return boolean|null A single boolean with a value of true if the sub-expression matches the pattern and false if it does not. If the sub-expression is NULL, the the operator results in NULL.
  * @throws \qtism\runtime\expressions\operators\OperatorProcessingException
  */
 public function process()
 {
     $operands = $this->getOperands();
     if ($operands->containsNull() === true) {
         return null;
     }
     if ($operands->exclusivelySingle() === false) {
         $msg = "The PatternMatch operator only accepts operands with a single cardinality.";
         throw new OperatorProcessingException($msg, $this, OperatorProcessingException::WRONG_CARDINALITY);
     }
     if ($operands->exclusivelyString() === false) {
         $msg = "The PatternMatch operator only accepts operands with a string baseType.";
         throw new OperatorProcessingException($msg, $this, OperatorProcessingException::WRONG_BASETYPE);
     }
     // XML schema always implicitly anchors the entire regular expression
     // because there is no carret (^) nor dollar ($) signs.
     // see http://www.regular-expressions.info/xml.html
     $rawPattern = $this->getExpression()->getPattern();
     $pattern = OperatorUtils::escapeSymbols($rawPattern, array('$', '^'));
     $pattern = OperatorUtils::pregAddDelimiter('^' . $pattern . '$');
     // XSD regexp always case-sensitive (nothing to do), dot matches white-spaces (use PCRE_DOTALL).
     $pattern .= 's';
     $result = @preg_match($pattern, $operands[0]->getValue());
     if ($result === 1) {
         return new Boolean(true);
     } elseif ($result === 0) {
         return new Boolean(false);
     } else {
         $error = preg_last_error();
         $errorType = 'PCRE Engine compilation error';
         switch ($error) {
             case PREG_INTERNAL_ERROR:
                 $errorType = "PCRE Engine internal error";
                 break;
             case PREG_BACKTRACK_LIMIT_ERROR:
                 $errorType = "PCRE Engine backtrack limit exceeded";
                 break;
             case PREG_RECURSION_LIMIT_ERROR:
                 $errorType = "PCRE Engine recursion limit exceeded";
                 break;
             case PREG_BAD_UTF8_ERROR:
                 $errorType = "PCRE Engine malformed UTF-8";
                 break;
             case PREG_BAD_UTF8_OFFSET_ERROR:
                 $errorType = "PCRE Engine UTF-8 offset error";
                 break;
         }
         $msg = "An internal error occured while processing the regular expression '{$rawPattern}': {$errorType}.";
         throw new OperatorProcessingException($msg, $this, OperatorProcessingException::RUNTIME_ERROR);
     }
 }
Example #2
0
 /**
  * @dataProvider pregAddDelimiterProvider
  *
  * @param string $string
  * @param string $expected
  */
 public function testPregAddDelimiter($string, $expected)
 {
     $this->assertSame($expected, OperatorsUtils::pregAddDelimiter($string));
 }