Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 101
0.00% covered (danger)
0.00%
0 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
MatchInteraction
0.00% covered (danger)
0.00%
0 / 101
0.00% covered (danger)
0.00%
0 / 12
1560
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getIdentifiedElements
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getUsedAttributes
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 getChoiceBySerial
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 isValidMatchSetNumber
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
30
 getChoices
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 addChoice
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
30
 createChoice
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 removeChoice
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
20
 getComposingElements
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
72
 toArray
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
2
 getTemplateQtiVariables
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3/*
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2013 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
19 *
20 *
21 */
22
23namespace oat\taoQtiItem\model\qti\interaction;
24
25use oat\taoQtiItem\model\qti\Element;
26use oat\taoQtiItem\model\qti\interaction\MatchInteraction;
27use oat\taoQtiItem\model\qti\interaction\BlockInteraction;
28use oat\taoQtiItem\model\qti\Item;
29use oat\taoQtiItem\model\qti\IdentifierCollection;
30use oat\taoQtiItem\model\qti\choice\Choice;
31use common_Logger;
32
33/**
34 * QTI Match Interaction
35 *
36 * @access public
37 * @author Sam, <sam@taotesting.com>
38 * @package taoQTI
39 * @see http://www.imsglobal.org/question/qtiv2p1/imsqti_infov2p1.html#element10291
40
41 */
42class MatchInteraction extends BlockInteraction
43{
44    /**
45     * the QTI tag name as defined in QTI standard
46     *
47     * @access protected
48     * @var string
49     */
50    protected static $qtiTagName = 'matchInteraction';
51    protected static $choiceClass = 'oat\\taoQtiItem\\model\\qti\\choice\\SimpleAssociableChoice';
52    protected static $baseType = 'directedPair';
53
54    public function __construct($attributes = [], Item $relatedItem = null, $serial = '')
55    {
56        parent::__construct($attributes, $relatedItem, $serial);
57
58        //init the two matchSets: a double array
59        $this->choices = [[], []];
60    }
61
62    public function getIdentifiedElements()
63    {
64
65        $returnValue = new IdentifierCollection();
66        $returnValue->addMultiple($this->getChoices(0));
67        $returnValue->addMultiple($this->getChoices(1));
68
69        return $returnValue;
70    }
71
72    protected function getUsedAttributes()
73    {
74        return array_merge(
75            parent::getUsedAttributes(),
76            [
77            'oat\\taoQtiItem\\model\\qti\\attribute\\Shuffle',
78            'oat\\taoQtiItem\\model\\qti\\attribute\\MaxAssociations',
79            'oat\\taoQtiItem\\model\\qti\\attribute\\MinAssociations'
80                ]
81        );
82    }
83
84    public function getChoiceBySerial($serial)
85    {
86
87        $returnValue = null;
88
89        for ($i = 0; $i < 2; $i++) {
90            $matchSet = $this->getChoices($i);
91            if (isset($matchSet[$serial])) {
92                $returnValue = $matchSet[$serial];
93                break;
94            }
95        }
96
97        return $returnValue;
98    }
99
100    private function isValidMatchSetNumber($setNumber)
101    {
102
103        $returnValue = false;
104
105        if (is_int($setNumber)) {
106            if ($setNumber === 0 || $setNumber === 1) {
107                $returnValue = true;
108            }
109        }
110        if (!$returnValue) {
111            common_Logger::w($setNumber);
112            throw new InvalidArgumentException(
113                'For match interactions, the match set number must be either "(int) 0" or "(int) 1"'
114            );
115        }
116
117        return $returnValue;
118    }
119
120    public function getChoices($setNumber = null)
121    {
122
123        $returnValue = [];
124
125        if ($this->isValidMatchSetNumber($setNumber)) {
126            $returnValue = $this->choices[$setNumber];
127        } else {
128            $returnValue = $this->choices;
129        }
130
131        return $returnValue;
132    }
133
134    public function addChoice(Choice $choice, $setNumber = null)
135    {
136
137        $returnValue = false;
138
139        if ($this->isValidMatchSetNumber($setNumber)) {
140            if (!empty(static::$choiceClass) && get_class($choice) == static::$choiceClass) {
141                $this->choices[$setNumber][$choice->getSerial()] = $choice;
142                $relatedItem = $this->getRelatedItem();
143                if (!is_null($relatedItem)) {
144                    $choice->setRelatedItem($relatedItem);
145                }
146                $returnValue = true;
147            } else {
148                throw new InvalidArgumentException('Wrong type of choice in argument: ' . static::$choiceClass);
149            }
150        }
151
152        return $returnValue;
153    }
154
155    /**
156     *
157     * @return oat\taoQtiItem\model\qti\choice\Choice
158     */
159    public function createChoice($choiceAttributes = [], $choiceValue = null, $setNumber = null)
160    {
161
162        $returnValue = null;
163
164        if ($this->isValidMatchSetNumber($setNumber)) {
165            if (
166                !empty(static::$choiceClass)
167                && is_subclass_of(static::$choiceClass, 'oat\\taoQtiItem\\model\\qti\\choice\\Choice')
168            ) {
169                $returnValue = new static::$choiceClass($choiceAttributes, $choiceValue);
170                $this->addChoice($returnValue, $setNumber);
171            }
172        }
173
174        return $returnValue;
175    }
176
177    public function removeChoice(Choice $choice, $setNumber = null)
178    {
179        if (!is_null($setNumber) && isset($this->choices[$setNumber])) {
180            unset($this->choices[$setNumber][$choice->getSerial()]);
181        } else {
182            for ($i = 0; $i < 2; $i++) {
183                $this->removeChoice($choice, $i);
184            }
185        }
186    }
187
188    public function getComposingElements($className = '')
189    {
190        if ($className === '') {
191            $className = 'oat\taoQtiItem\model\qti\Element';
192        }
193        $returnValue = parent::getComposingElements($className);
194        //for matchInteraction choices is not an array of Element but an array of array of Element
195        foreach ($this->getChoices(0) as $choice) {
196            if ($choice instanceof Element) {
197                if ($choice instanceof $className) {
198                    $returnValue[$choice->getSerial()] = $choice;
199                }
200                $returnValue = array_merge($returnValue, $choice->getComposingElements($className));
201            }
202        }
203
204        foreach ($this->getChoices(1) as $choice) {
205            if ($choice instanceof Element) {
206                if ($choice instanceof $className) {
207                    $returnValue[$choice->getSerial()] = $choice;
208                }
209                $returnValue = array_merge($returnValue, $choice->getComposingElements($className));
210            }
211        }
212
213        return $returnValue;
214    }
215
216    public function toArray($filterVariableContent = false, &$filtered = [])
217    {
218
219        //need to reimplent it because there are two match choice sets
220        $data = [
221            'serial' => $this->getSerial(),
222            'qtiClass' => $this->getQtiTag(),
223            'attributes' => $this->getAttributeValues(),
224            'prompt' => $this->getPrompt()->toArray($filterVariableContent, $filtered),
225            'choices' => [
226                $this->getArraySerializedElementCollection($this->getChoices(0), $filterVariableContent, $filtered),
227                $this->getArraySerializedElementCollection($this->getChoices(1), $filterVariableContent, $filtered)
228            ]
229        ];
230
231        return $data;
232    }
233
234    protected function getTemplateQtiVariables()
235    {
236
237        //need to reimplent it because there are two match choice sets
238        $variables = [
239            'tag' => static::$qtiTagName,
240            'attributes' => $this->getAttributeValues(),
241            'prompt' => $this->prompt->toQTI()
242        ];
243        unset($variables['attributes']['identifier']);
244
245        if (trim($this->getPrompt()->getBody()) !== '') {
246            //prompt is optional:
247            $variables['prompt'] = $this->prompt->toQTI();
248        }
249
250        $choices = '';
251        for ($i = 0; $i < 2; $i++) {
252            $choices .= '<simpleMatchSet>';
253            foreach ($this->getChoices($i) as $choice) {
254                $choices .= $choice->toQTI();
255            }
256            $choices .= '</simpleMatchSet>';
257        }
258
259        $variables['choices'] = $choices;
260
261        return $variables;
262    }
263}