closedquestion-8.x-3.x-dev/src/Question/Mapping/CqMatchRange.php
src/Question/Mapping/CqMatchRange.php
<?php
namespace Drupal\closedquestion\Question\Mapping;
use Drupal\Component\Utility\Html;
/**
* Class CqMatchRange.
*
* CqMatchRange checks if one or more inlineChoice(s) contains a numeric value
* in a certain range, or if a certain given value is in a certain range.
*
* @package Drupal\closedquestion\Question\Mapping
*/
class CqMatchRange extends CqAbstractMapping {
/**
* Implements CqAbstractMapping::evaluate()
*/
public function evaluate() {
$choiceId = $this->getParam('inlinechoice');
$matchAll = $this->getParam('matchall');
$minval = $this->getParam('minval');
if ($minval !== NULL && !is_numeric($minval)) {
// Non numeric minval, probably a math expression.
$minval = $this->context->evaluateMath($minval);
}
$maxval = $this->getParam('maxval');
if ($maxval !== NULL && !is_numeric($maxval)) {
// Non numeric minval, probably a math expression.
$maxval = $this->context->evaluateMath($maxval);
}
$value = $this->getParam('value');
if ($value !== NULL && !is_numeric($value)) {
// Non numeric value, probably a math expression.
$value = $this->context->evaluateMath($value);
}
if ($choiceId === NULL && $value === NULL) {
\Drupal::messenger()->addMessage(t('Range without inlineChoice or value attribute found.'), 'warning');
}
if ($choiceId !== NULL) {
$answer = $this->context->getAnswerForChoice($choiceId);
}
else {
$answer = $value;
}
if ($answer !== NULL) {
if (is_array($answer)) {
foreach ($answer as $subChoice => $subAnswer) {
$this->topParent->lastMatchedId = $subChoice;
$subAnswer = closedquestion_fix_number($subAnswer);
$matched = TRUE;
if (!is_numeric($subAnswer)) {
$matched = FALSE;
}
if ($minval !== NULL && $subAnswer < $minval) {
$matched = FALSE;
}
if ($maxval !== NULL && $subAnswer > $maxval) {
$matched = FALSE;
}
if (!$matchAll && $matched) {
// This sub-answer matched, and we need only one to match, so this
// range matches, return TRUE.
return TRUE;
}
if ($matchAll && !$matched) {
// This sub-answer did not match, and we need all of 'em to match
// for true, so the match failed, return FALSE.
return FALSE;
}
}
// If we did not return sooner then the result of the last one is final.
return $matched;
}
else {
$this->topParent->lastMatchedId = $choiceId;
$answer = closedquestion_fix_number($answer);
if (!is_numeric($answer)) {
return FALSE;
}
if ($minval !== NULL && $answer < $minval && (string) $answer !== (string) $minval) {
// String check is for failing float comparisons.
// @TODO: find a better way of doing this.
return FALSE;
}
if ($maxval !== NULL && $answer > $maxval && (string) $answer !== (string) $maxval) {
return FALSE;
}
return TRUE;
}
}
else {
return FALSE;
}
}
/**
* Overrides CqAbstractMapping::getAllText()
*/
public function getAllText() {
$choiceId = $this->getParam('inlinechoice');
$value = $this->getParam('value');
$minval = $this->getParam('minval');
if ($minval === NULL) {
$minval = '-∞';
}
else {
$minval = Html::escape($minval);
}
$maxval = $this->getParam('maxval');
if ($maxval === NULL) {
$maxval = '∞';
}
else {
$maxval = Html::escape($maxval);
}
$retval = array();
if ($choiceId !== NULL) {
$retval['logic']['#markup'] = t('Range: choiceId=%id, minval=@minval, maxval=@maxval.', array(
'%id' => $choiceId,
'@minval' => $minval,
'@maxval' => $maxval,
));
}
elseif ($value !== NULL) {
$retval['logic']['#markup'] = t('Range: value=%id, minval=@minval, maxval=@maxval.', array(
'%id' => $value,
'@minval' => $minval,
'@maxval' => $maxval,
));
}
else {
$retval['logic']['#markup'] = t('Range: minval=@minval, maxval=@maxval.', array(
'@minval' => $minval,
'@maxval' => $maxval,
));
}
$retval += parent::getAllText();
return $retval;
}
}
