219 lines
8.9 KiB
PHP
219 lines
8.9 KiB
PHP
<?php
|
|
/**
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; under version 2
|
|
* of the License (non-upgradable).
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Copyright (c) 2013-2014 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
|
|
*
|
|
*/
|
|
|
|
use qtism\data\IAssessmentItem;
|
|
use qtism\common\datatypes\QtiPoint;
|
|
use qtism\common\datatypes\QtiString;
|
|
use qtism\common\datatypes\QtiIdentifier;
|
|
use qtism\common\datatypes\QtiFloat;
|
|
use qtism\common\datatypes\QtiInteger;
|
|
use qtism\common\datatypes\QtiBoolean;
|
|
use qtism\runtime\common\MultipleContainer;
|
|
use qtism\runtime\common\OrderedContainer;
|
|
use qtism\common\enums\Cardinality;
|
|
use qtism\common\datatypes\QtiPair;
|
|
use qtism\common\datatypes\QtiDirectedPair;
|
|
use qtism\common\enums\BaseType;
|
|
use qtism\runtime\common\ResponseVariable;
|
|
use qtism\runtime\common\OutcomeVariable;
|
|
use qtism\runtime\common\Variable;
|
|
|
|
/**
|
|
* The VariableFiller provides a way to fill a QtiSm Runtime Variable with
|
|
* a value coming from the client side. These values are always transmitted as
|
|
* plain strings. However, we need a way to transform these string values as
|
|
* QtiSm compliant variable values. This is the goal of this class.
|
|
*
|
|
* @author Jérôme Bogaerts <jerome@taotesting.com>
|
|
*
|
|
*/
|
|
class taoQtiCommon_helpers_LegacyVariableFiller extends taoQtiCommon_helpers_AbstractVariableFiller {
|
|
|
|
/**
|
|
* Create a new LegacyVariableFiller object.
|
|
*
|
|
* @param IAssessmentItem $itemRef The item the variables you want to fill belong to.
|
|
*/
|
|
public function __construct(IAssessmentItem $itemRef) {
|
|
parent::__construct($itemRef);
|
|
}
|
|
|
|
/**
|
|
* Fille the variable $variableName with a correctly transformed
|
|
* $clientSideValue.
|
|
*
|
|
* @param string $variableName The variable identifier you want to fill.
|
|
* @param string $clientSideValue The value received from the client-side.
|
|
* @return Variable A Variable object filled with a correctly transformed $clientSideValue.
|
|
* @throws OutOfBoundsException If no variable with $variableName is described in the item.
|
|
* @throws OutOfRangeException If the $clientSideValue does not fit the target variable's baseType.
|
|
*/
|
|
public function fill($variableName, $clientSideValue) {
|
|
$variable = null;
|
|
|
|
$outcomeDeclarations = $this->getItemRef()->getOutcomeDeclarations();
|
|
$responseDeclarations = $this->getItemRef()->getResponseDeclarations();
|
|
|
|
if (isset($responseDeclarations[$variableName]) === true) {
|
|
$variable = ResponseVariable::createFromDataModel($responseDeclarations[$variableName]);
|
|
}
|
|
else if (isset($outcomeDeclarations[$variableName]) === true) {
|
|
$variable = OutcomeVariable::createFromDataModel($outcomeDeclarations[$variableName]);
|
|
}
|
|
|
|
if (empty($variable) === true) {
|
|
$itemId = $this->getItemRef()->getIdentifier();
|
|
$msg = "No variable declaration '${variableName}' found in '${itemId}'.";
|
|
throw new OutOfBoundsException($msg);
|
|
}
|
|
|
|
common_Logger::d("Filling variable '" . $variable->getIdentifier() . "'.");
|
|
|
|
if (is_array($clientSideValue) === false) {
|
|
$clientSideValue = array($clientSideValue);
|
|
}
|
|
|
|
try {
|
|
$finalValues = array();
|
|
foreach ($clientSideValue as $val) {
|
|
$finalValues[] = self::transform($variable->getBaseType(), $val);
|
|
}
|
|
|
|
if ($variable->getCardinality() === Cardinality::SINGLE) {
|
|
$variable->setValue($finalValues[0]);
|
|
}
|
|
else if ($variable->getCardinality() === Cardinality::MULTIPLE) {
|
|
$variable->setValue(new MultipleContainer($variable->getBaseType(), $finalValues));
|
|
}
|
|
else {
|
|
// Cardinality is ORDERED.
|
|
$variable->setValue(new OrderedContainer($variable->getBaseType(), $finalValues));
|
|
}
|
|
|
|
return $variable;
|
|
}
|
|
catch (InvalidArgumentException $e) {
|
|
if (is_array($clientSideValue)) {
|
|
$clientSideValue = implode(',', $clientSideValue);
|
|
}
|
|
|
|
$msg = "An error occured while filling variable '${variableName}' with client-side value '${clientSideValue}':" . $e->getMessage();
|
|
throw new InvalidArgumentException($msg, 0, $e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Transform $value in a $baseType datatype.
|
|
*
|
|
* @param integer $baseType
|
|
* @param mixed $value
|
|
* @return mixed
|
|
* @throws InvalidArgumentException If $baseType is unknown.
|
|
* @throws OutOfRangeException If $value cannot be transformed into $baseType datatype.
|
|
*/
|
|
protected static function transform($baseType, $value) {
|
|
|
|
switch ($baseType) {
|
|
case BaseType::BOOLEAN:
|
|
if ($value === '') {
|
|
return null;
|
|
}
|
|
else {
|
|
return ($value === 'true') ? true : false;
|
|
}
|
|
break;
|
|
|
|
case BaseType::DIRECTED_PAIR:
|
|
if (is_array($value) === false) {
|
|
$msg = "Cannot transform a value into a QTI directedPair, it is not an array, '" . gettype($value) . "' given";
|
|
throw new OutOfRangeException($msg);
|
|
}
|
|
else if (empty($value[0])) {
|
|
$msg = "Cannot transform a value into a QTI directedPair, the first identifier was not given.";
|
|
throw new OutOfRangeException($msg);
|
|
}
|
|
else if (empty($value[1])) {
|
|
$msg = "Cannot transform a value into a QTI directedPair, the second identifier was not given.";
|
|
throw new OutOfRangeException($msg);
|
|
}
|
|
else {
|
|
return new QtiDirectedPair($value[0], $value[1]);
|
|
}
|
|
break;
|
|
|
|
case BaseType::PAIR:
|
|
if (is_array($value) === false) {
|
|
$msg = "Cannot transform a value into a QTI pair, it is not an array, '" . gettype($value) . "' given";
|
|
throw new OutOfRangeException($msg);
|
|
}
|
|
else if (empty($value[0])) {
|
|
$msg = "Cannot transform a value into a QTI pair, the first identifier was not given.";
|
|
throw new OutOfRangeException($msg);
|
|
}
|
|
else if (empty($value[1])) {
|
|
$msg = "Cannot transform a value into a QTI pair, the second identifier was not given.";
|
|
throw new OutOfRangeException($msg);
|
|
}
|
|
else {
|
|
return new QtiPair($value[0], $value[1]);
|
|
}
|
|
break;
|
|
|
|
case BaseType::STRING:
|
|
return new QtiString($value);
|
|
break;
|
|
case BaseType::IDENTIFIER:
|
|
return ($value !== '') ? new QtiIdentifier($value) : null;
|
|
break;
|
|
|
|
case BaseType::INTEGER:
|
|
return ($value !== '') ? new QtiInteger(intval($value)) : null;
|
|
break;
|
|
|
|
case BaseType::FLOAT:
|
|
return ($value !== '') ? new QtiFloat(floatval($value)) : null;
|
|
break;
|
|
|
|
case BaseType::POINT:
|
|
if (is_array($value) === false) {
|
|
$msg = "Cannot transform a value into a QTI point, it is not an array, '" . gettype($value) . "' given";
|
|
throw new OutOfRangeException($msg);
|
|
}
|
|
else if (empty($value[0])) {
|
|
$msg = "Cannot transform a value into a QTI point, X was not given.";
|
|
throw new OutOfRangeException($msg);
|
|
}
|
|
else if (empty($value[1])) {
|
|
$msg = "Cannot transform a value into a QTI point, Y was not given.";
|
|
throw new OutOfRangeException($msg);
|
|
}
|
|
else {
|
|
return new QtiPoint(intval($value[0]), intval($value[1]));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
$msg = "Not supported baseType constant '${baseType}'.";
|
|
throw new InvalidArgumentException($msg);
|
|
break;
|
|
}
|
|
}
|
|
}
|