/** * 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); } }
/** * @dataProvider pregAddDelimiterProvider * * @param string $string * @param string $expected */ public function testPregAddDelimiter($string, $expected) { $this->assertSame($expected, OperatorsUtils::pregAddDelimiter($string)); }