Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
97.73% |
43 / 44 |
|
80.00% |
4 / 5 |
CRAP | |
0.00% |
0 / 1 |
OfflineQtiRunnerService | |
97.73% |
43 / 44 |
|
80.00% |
4 / 5 |
12 | |
0.00% |
0 / 1 |
getItems | |
94.12% |
16 / 17 |
|
0.00% |
0 / 1 |
4.00 | |||
getItemData | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
3 | |||
getItemIdentifiersFromTestMap | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
getSubIdentifiersRecursively | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
3 | |||
getRunnerService | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
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) 2019 (original work) Open Assessment Technologies SA ; |
19 | */ |
20 | |
21 | /** |
22 | * @author Péter Halász <peter@taotesting.com> |
23 | */ |
24 | |
25 | namespace oat\taoQtiTest\models\runner; |
26 | |
27 | use oat\oatbox\service\ConfigurableService; |
28 | use oat\taoQtiTest\models\runner\map\RunnerMap; |
29 | |
30 | /** |
31 | * Service class for the offline version of Qti Test Runner |
32 | */ |
33 | class OfflineQtiRunnerService extends ConfigurableService |
34 | { |
35 | public const SERVICE_ID = 'taoQtiTest/OfflineQtiRunnerService'; |
36 | |
37 | /** |
38 | * Returns an array of items, containing also confident data, like branching and response processing rules |
39 | * |
40 | * @param RunnerServiceContext $serviceContext |
41 | * @return array |
42 | * @throws \common_Exception |
43 | * @throws \common_exception_Error |
44 | * @throws \common_exception_InconsistentData |
45 | * @throws \common_exception_InvalidArgumentType |
46 | */ |
47 | public function getItems(RunnerServiceContext $serviceContext) |
48 | { |
49 | $this->getRunnerService()->assertQtiRunnerServiceContext($serviceContext); |
50 | |
51 | $runnerService = $this->getRunnerService(); |
52 | $testMap = $runnerService->getTestMap($serviceContext); |
53 | $items = []; |
54 | |
55 | foreach ($this->getItemIdentifiersFromTestMap($testMap) as $itemIdentifier) { |
56 | $itemRef = $runnerService->getItemHref($serviceContext, $itemIdentifier); |
57 | |
58 | $itemState = $runnerService->getItemState($serviceContext, $itemIdentifier); |
59 | |
60 | if (is_array($itemState) && (0 === count($itemState))) { |
61 | $itemState = null; |
62 | } |
63 | |
64 | /** @var QtiRunnerServiceContext $serviceContext */ |
65 | $items[$itemIdentifier] = [ |
66 | 'baseUrl' => $runnerService->getItemPublicUrl($serviceContext, $itemRef), |
67 | 'itemData' => $this->getItemData($serviceContext, $itemRef), |
68 | 'itemState' => $itemState, |
69 | 'itemIdentifier' => $itemIdentifier, |
70 | 'portableElements' => $runnerService->getItemPortableElements($serviceContext, $itemRef), |
71 | ]; |
72 | } |
73 | |
74 | return $items; |
75 | } |
76 | |
77 | /** |
78 | * Returns the itemData, extending with the variable elements |
79 | * |
80 | * @param RunnerServiceContext $context |
81 | * @param string $itemRef |
82 | * @return array |
83 | * @throws \common_exception_InvalidArgumentType |
84 | * @throws \common_Exception |
85 | */ |
86 | private function getItemData(RunnerServiceContext $context, $itemRef) |
87 | { |
88 | $this->getRunnerService()->assertQtiRunnerServiceContext($context); |
89 | |
90 | $itemData = $this->getRunnerService()->getItemData($context, $itemRef); |
91 | $itemDataVariable = $this->getRunnerService()->getItemVariableElementsData($context, $itemRef); |
92 | $responses = $itemData['data']['responses']; |
93 | |
94 | foreach (array_keys($responses) as $responseId) { |
95 | if (array_key_exists($responseId, $itemDataVariable)) { |
96 | $itemData['data']['responses'][$responseId] = array_merge(...[ |
97 | $responses[$responseId], |
98 | $itemDataVariable[$responseId], |
99 | ]); |
100 | } |
101 | } |
102 | |
103 | return $itemData; |
104 | } |
105 | |
106 | /** |
107 | * Returns the item identifiers |
108 | * |
109 | * @param array $testMap |
110 | * @return array |
111 | */ |
112 | private function getItemIdentifiersFromTestMap($testMap) |
113 | { |
114 | return $this->getSubIdentifiersRecursively($testMap, [ |
115 | RunnerMap::MAP_ATTRIBUTE_PARTS, |
116 | RunnerMap::MAP_ATTRIBUTE_SECTIONS, |
117 | RunnerMap::MAP_ATTRIBUTE_ITEMS, |
118 | ]); |
119 | } |
120 | |
121 | /** |
122 | * Calls itself recursively to return identifiers from nested arrays |
123 | * |
124 | * @param $array |
125 | * @param $identifiers |
126 | * @return array |
127 | */ |
128 | private function getSubIdentifiersRecursively($array, $identifiers) |
129 | { |
130 | $identifier = array_shift($identifiers); |
131 | if (count($identifiers) > 0) { |
132 | $result = []; |
133 | |
134 | foreach ($array[$identifier] as $key => $value) { |
135 | $result[] = $this->getSubIdentifiersRecursively( |
136 | $array[$identifier][$key], |
137 | $identifiers |
138 | ); |
139 | } |
140 | |
141 | return array_merge(...$result); |
142 | } |
143 | |
144 | return array_keys($array[$identifier]); |
145 | } |
146 | |
147 | /** |
148 | * @return ConfigurableService|QtiRunnerService |
149 | */ |
150 | private function getRunnerService() |
151 | { |
152 | return $this->getServiceLocator()->get(QtiRunnerService::SERVICE_ID); |
153 | } |
154 | } |