Skip to content
CompositeValidator.php 10.4 KiB
Newer Older
require_once "Expressions/ResultOfAnswerOfQuestionExpression.php";
require_once "./Customizing/global/plugins/Services/Repository/RepositoryObject/QuestionSetPool/Parser/classes/Exception/ExpressionNotSupportedByQuestion.php";
require_once "./Customizing/global/plugins/Services/Repository/RepositoryObject/QuestionSetPool/Parser/classes/Exception/QuestionNotExist.php";
require_once "./Customizing/global/plugins/Services/Repository/RepositoryObject/QuestionSetPool/Parser/classes/Exception/OperatorNotSupportedByExpression.php";
require_once "./Customizing/global/plugins/Services/Repository/RepositoryObject/QuestionSetPool/Parser/classes/Exception/UnsupportedExpression.php";
require_once "./Customizing/global/plugins/Services/Repository/RepositoryObject/QuestionSetPool/Parser/classes/Exception/UnsupportedOperation.php";
require_once "./Customizing/global/plugins/Services/Repository/RepositoryObject/QuestionSetPool/Parser/classes/Exception/AnswerIndexNotExist.php";
require_once "./Customizing/global/plugins/Services/Repository/RepositoryObject/QuestionSetPool/Parser/classes/Exception/QuestionNotReachable.php";
require_once "./Customizing/global/plugins/Services/Repository/RepositoryObject/QuestionSetPool/Parser/classes/Exception/AnswerValueNotExist.php";
require_once "./Customizing/global/plugins/Services/Repository/RepositoryObject/QuestionSetPool/Parser/classes/Exception/UnableToParseCondition.php";
require_once "./Customizing/global/plugins/Services/Repository/RepositoryObject/QuestionSetPool/Parser/classes/Exception/DuplicateElement.php";
/**
 * Class CompositeValidator
 *
 * Date: 04.12.13
 * Time: 14:19
 * @author Thomas Joußen <tjoussen@databay.de>
Michael Jansen's avatar
Michael Jansen committed
 */
class CompositeValidator
{

Michael Jansen's avatar
Michael Jansen committed
    /**
     * @var ilParserQuestionProvider
     *
     * @todo Needs to be abstract or interface
     */
    protected $object_loader;
Michael Jansen's avatar
Michael Jansen committed
    /**
     * @var ilQuestionSetPoolNode
     */
    protected $node;
Michael Jansen's avatar
Michael Jansen committed
    /**
     * @var array
     */
    protected $data;
Michael Jansen's avatar
Michael Jansen committed
    /**
     * @param ilParserQuestionProvider $object_loader
     * @oaram ilQuestionSetPoolNode $node
     * @param array $data
     */
    public function __construct($object_loader, $node, $data)
    {
        $this->object_loader = $object_loader;
        $this->node = $node;
        $this->data = $data;
    }
Michael Jansen's avatar
Michael Jansen committed
    public function validate(AbstractComposite $composite)
    {
        if (is_array($composite->nodes) && count($composite->nodes) > 0) {
            $this->validate($composite->nodes[0]);
            $this->validate($composite->nodes[1]);
            $this->validateSubTree($composite);
        }
Michael Jansen's avatar
Michael Jansen committed
        return;
    }
Michael Jansen's avatar
Michael Jansen committed
    private function validateSubTree(AbstractComposite $composite)
    {
        if ($composite->nodes[0] instanceof QuestionExpressionInterface &&
            $composite->nodes[1] instanceof SolutionExpressionInterface
        ) {
            $question_expression = $composite->nodes[0];
            $answer_expression = $composite->nodes[1];
            $question_index = $composite->nodes[0]->getQuestionIndex();
            $answer_index = null;
            $question = $this->object_loader->getQuestion($question_index);
Michael Jansen's avatar
Michael Jansen committed
            $this->checkQuestionExists($question, $question_index);
            $this->checkQuestionIsReachable($question, $question_index);
Michael Jansen's avatar
Michael Jansen committed
            if ($this->isResultOfAnswerExpression($question_expression)) {
                $answer_index = $question_expression->getAnswerIndex() - 1;
                $this->checkIfAnswerIndexOfQuestionExists($question, $question_index, $answer_index);
            }
            if ($answer_expression instanceof NumberOfResultExpression && !($question instanceof assClozeTest)) {
                $this->checkIfAnswerIndexOfQuestionExists($question, $question_index, $answer_expression->getNumericValue() - 1);
            }
Michael Jansen's avatar
Michael Jansen committed
            $this->checkAnswerExpressionExist($question->getExpressionTypes(), $answer_expression, $question_index);
            $this->checkOperatorExistForExpression($question->getOperators($answer_expression::$identifier), $answer_expression, $composite::$pattern);
Michael Jansen's avatar
Michael Jansen committed
            if ($answer_expression instanceof OrderingResultExpression &&
                ($question instanceof assOrderingHorizontal || $question instanceof assOrderingQuestion)
            ) {
                foreach ($answer_expression->getOrdering() as $order) {
                    $count = 0;
                    foreach ($answer_expression->getOrdering() as $element) {
                        if ($element == $order) {
                            $count++;
                        }
                    }
                    if ($count > 1) {
                        throw new DuplicateElement($order);
                    }
Michael Jansen's avatar
Michael Jansen committed
                    $this->checkIfAnswerIndexOfQuestionExists($question, $question_index, $order - 1);
                }
            }
            if ($question instanceof assClozeTest) {
                $this->validateClozeTest($answer_index, $question, $answer_expression, $question_index);
            } elseif (
                $answer_expression instanceof PercentageResultExpression &&
                $this->isResultOfAnswerExpression($question_expression) &&
                !($question instanceof assFormulaQuestion)
            ) {
                throw new ExpressionNotSupportedByQuestion($answer_expression->getValue(), $question_index . "[" . ($answer_index + 1) . "]");
            }
        } elseif (
            ($composite->nodes[0] instanceof AbstractOperation &&
            $composite->nodes[1] instanceof ExpressionInterface) ||
            ($composite->nodes[0] instanceof ExpressionInterface &&
            $composite->nodes[1] instanceof AbstractOperation) ||
            ($composite->nodes[0] instanceof SolutionExpressionInterface)
        ) {
            throw new UnableToParseCondition("");
        }
    }
Michael Jansen's avatar
Michael Jansen committed
    /**
     * @param int                            $answer_index
     * @param assQuestion|iQuestionCondition $question
     * @param ExpressionInterface            $answer_expression
     * @param int                            $question_index
     *
     * @throws AnswerValueNotExist
     */
    private function validateClozeTest($answer_index, $question, $answer_expression, $question_index)
    {
        if ($answer_index !== null) {
            $options = $question->getAvailableAnswerOptions($answer_index);
            $found = false;
            switch ($options->getType()) {
                case 0: // text
                    if (
                        $answer_expression instanceof StringResultExpression
                    ) {
                        $found = true;
                    }
Michael Jansen's avatar
Michael Jansen committed
                    break;
                case 1: // select
Michael Jansen's avatar
Michael Jansen committed
                    if ($answer_expression instanceof StringResultExpression) {
                        foreach ($options->getItems(new ilArrayElementShuffler()) as $item) {
                            if ($item->getAnswertext() == $answer_expression->getText()) {
                                $found = true;
                            }
                        }
                    } elseif ($answer_expression instanceof NumberOfResultExpression) {
                        foreach ($options->getItems(new ilArrayElementShuffler()) as $item) {
                            if ($item->getOrder() == $answer_expression->getNumericValue() - 1) {
                                $found = true;
                            }
                        }
                    }
                break;
                case 2: // numeric
                    if ($answer_expression instanceof NumericResultExpression) {
                        $found = true;
                    }
                break;
            }
Michael Jansen's avatar
Michael Jansen committed
            if ($answer_expression instanceof EmptyAnswerExpression) {
                $found = true;
            }
            if (!$found && !($answer_expression instanceof PercentageResultExpression)) {
                throw new AnswerValueNotExist($question_index, $answer_expression->getValue(), $answer_index + 1);
            }
        }
    }
Michael Jansen's avatar
Michael Jansen committed
    /**
     * @param iQuestionCondition $question
     * @param int $question_index
     * @param int $answer_index
     *
     * @throws AnswerIndexNotExist
     */
    private function checkIfAnswerIndexOfQuestionExists($question, $question_index, $answer_index)
    {
        $answer_options = $question->getAvailableAnswerOptions($answer_index);
        if ($answer_options == null) {
            throw new AnswerIndexNotExist($question_index, $answer_index + 1);
        }
    }
Michael Jansen's avatar
Michael Jansen committed
    /**
     * @param assQuestion|null $question
     * @param int $index
     *
     * @throws QuestionNotExist
     */
    private function checkQuestionExists($question, $index)
    {
        if ($question == null) {
            throw new QuestionNotExist($index);
        }
    }
Michael Jansen's avatar
Michael Jansen committed
    /**
     * @param ExpressionInterface $expression
     *
     * @return bool
     */
    private function isResultOfAnswerExpression($expression)
    {
        return $expression instanceof ResultOfAnswerOfQuestionExpression;
    }
Michael Jansen's avatar
Michael Jansen committed
    /**
     * @param array $expressions
     * @param ExpressionInterface $answer_expression
     * @param int $question_index
     *
     * @throws ExpressionNotSupportedByQuestion
     */
    private function checkAnswerExpressionExist($expressions, $answer_expression, $question_index)
    {
        if (!in_array($answer_expression::$identifier, $expressions)) {
            throw new ExpressionNotSupportedByQuestion($answer_expression->getValue(), $question_index);
        }
    }
Michael Jansen's avatar
Michael Jansen committed
    /**
     * @param array $operators
     * @param ExpressionInterface $answer_expression
     * @param string $pattern
     *
     * @throws OperatorNotSupportedByExpression
     */
    private function checkOperatorExistForExpression($operators, $answer_expression, $pattern)
    {
        if (!in_array($pattern, $operators)) {
            throw new OperatorNotSupportedByExpression($answer_expression->getValue(), $pattern);
        }
    }
Michael Jansen's avatar
Michael Jansen committed
    /**
     * @param $question
     * @param $index
     *
     * @throws QuestionNotReachable
     */
    private function checkQuestionIsReachable($question, $index)
    {
        $reachable = false;
        foreach ($this->data as $node) {
            if ($node["node_index"] > $this->node->getIndex()) {
                break;
            }
Michael Jansen's avatar
Michael Jansen committed
            if ($node["question_fi"] == $question->getId()) {
                $reachable = true;
                break;
            }
        }
Michael Jansen's avatar
Michael Jansen committed
        if (!$reachable) {
            throw new QuestionNotReachable($index);
        }
    }