closedquestion-8.x-3.x-dev/src/Question/CqRange.php
src/Question/CqRange.php
<?php
namespace Drupal\closedquestion\Question;
use Drupal\closedquestion\Question\Mapping\CqFeedback;
/**
* Class CqRange.
*
* CqRange checks if the answer of a Value question is in a certain range.
* Used by CqQuestionValue.
*
* @package Drupal\closedquestion\Question
*/
class CqRange {
/**
* The minimum value for this range to match, inclusive.
*
* @var int
*/
private $minValue;
/**
* The maximum value for this range to match, inclusive.
*
* @var int
*/
private $maxValue;
/**
* If this range matches, does that mean the answer is correct?
*
* @var int
*/
private $correct = 0;
/**
* Feedback items contained in this mapping.
*
* @var \Drupal\closedquestion\Question\Mapping\CqFeedback[]
*/
private $feedback = array();
/**
* XML helper.
*
* @var \Drupal\closedquestion\Utility\XmlLib
*/
protected $xmlLib;
/**
* Constructor for the Range object.
*
* @param \DOMElement $node
* The XML node to use for initalisation.
* @param \Drupal\closedquestion\Question\CqQuestionInterface $context
* The question or other object that the mapping can query for
* things like the current answer, draggables, hotspots and the parsing of
* html.
*/
public function __construct(\DOMElement $node, CqQuestionInterface $context) {
/* @var \Drupal\closedquestion\Utility\XmlLib xmlLib */
$this->xmlLib = \Drupal::service('closedquestion.utility.xml_lib');
$nodeList = $node->getElementsByTagName('minval');
$item = $nodeList->item(0);
if ($item != NULL) {
$this->minValue = trim($this->xmlLib->getTextContent($item, $context, FALSE));
}
$nodeList = $node->getElementsByTagName('maxval');
$item = $nodeList->item(0);
if ($item != NULL) {
$this->maxValue = trim($this->xmlLib->getTextContent($item, $context, FALSE));
}
foreach ($node->getElementsByTagName('feedback') as $fb) {
$this->feedback[] = CqFeedback::newCqFeedback($fb, $context);
}
$attribs = $node->attributes;
$item = $attribs->getNamedItem('correct');
if ($item !== NULL) {
$this->correct = (int) $item->value;
}
}
/**
* Getter for the correct property.
*
* @return int
* 1 if correct.
*/
public function getCorrect() {
return $this->correct;
}
/**
* Is the given answer in range?
*
* @param int $answer
* The answer to check.
*
* @return bool
* TRUE if answer is in range.
*/
public function inRange($answer) {
if ($answer !== NULL) {
$answer = closedquestion_fix_number($answer);
if ($this->minValue !== NULL && $answer < $this->minValue) {
return FALSE;
}
if ($this->maxValue !== NULL && $answer > $this->maxValue) {
return FALSE;
}
return TRUE;
}
else {
return FALSE;
}
}
/**
* Is the given answer correct?
*
* That is: in range when correct is true, and not in range when correct
* is not true.
*
* @param int $answer
* The answer to check.
*
* @return bool
* The result of the check.
*/
public function correctlyAnswered($answer) {
return (!($this->inRange($answer) xor $this->correct));
}
/**
* Get the feedback items associated with this range, for $tries tries.
*
* @param int $tries
* The number of incorrect attempts the student made for this question.
*
* @return \Drupal\closedquestion\Question\Mapping\CqFeedback[]
* Feedback items.
*/
public function getFeedback($tries) {
$retVal = array();
foreach ($this->feedback as $fb) {
if ($fb->inRange($tries)) {
$retVal[] = $fb;
}
}
return $retVal;
}
/**
* Returns a html representation of this mapping, and it's children.
*
* @return array
* Render array.
*/
public function getAllText() {
$retval = array(
'correct' => $this->correct,
'minval' => $this->minValue,
'maxval' => $this->maxValue,
);
if (count($this->feedback) > 0) {
$retval['feedback'] = array(
'#theme' => 'closedquestion_feedback_list',
'#extended' => TRUE,
);
foreach ($this->feedback as $fbitem) {
$retval['feedback']['items'][] = $fbitem->getAllText();
}
}
$retval['#theme'] = 'closedquestion_range';
return $retval;
}
}
