Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 85 |
|
0.00% |
0 / 14 |
CRAP | |
0.00% |
0 / 1 |
CrudResultsService | |
0.00% |
0 / 85 |
|
0.00% |
0 / 14 |
1056 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getRootClass | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
get | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
format | |
0.00% |
0 / 29 |
|
0.00% |
0 / 1 |
132 | |||
getAll | |
0.00% |
0 / 31 |
|
0.00% |
0 / 1 |
72 | |||
delete | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
deleteAll | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
update | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
isInScope | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getClassService | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getFormResource | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 | |||
splitByAttempt | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getItemVariableSplitter | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getNormalizer | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
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) 2017-2020 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT); |
19 | * |
20 | */ |
21 | |
22 | namespace oat\taoResultServer\models\classes; |
23 | |
24 | use core_kernel_classes_Class; |
25 | use oat\taoDeliveryRdf\model\DeliveryAssemblyService; |
26 | use oat\taoResultServer\models\Formatter\ItemResponseCollectionNormalizer; |
27 | use oat\taoResultServer\models\Formatter\ItemResponseVariableSplitter; |
28 | use tao_models_classes_CrudService; |
29 | use taoResultServer_models_classes_ReadableResultStorage; |
30 | use taoResultServer_models_classes_ResponseVariable; |
31 | |
32 | /** |
33 | * Crud services implements basic CRUD services, originally intended for REST controllers/ HTTP exception handlers |
34 | * Consequently the signatures and behaviors is closer to REST and throwing HTTP like exceptions |
35 | */ |
36 | class CrudResultsService extends tao_models_classes_CrudService |
37 | { |
38 | public const GROUP_BY_DELIVERY = 0; |
39 | public const GROUP_BY_TEST = 1; |
40 | public const GROUP_BY_ITEM = 2; |
41 | |
42 | /** @var core_kernel_classes_Class */ |
43 | protected $resultClass; |
44 | |
45 | public function __construct() |
46 | { |
47 | parent::__construct(); |
48 | $this->resultClass = new core_kernel_classes_Class(ResultService::DELIVERY_RESULT_CLASS_URI); |
49 | } |
50 | |
51 | public function getRootClass() |
52 | { |
53 | return $this->resultClass; |
54 | } |
55 | |
56 | public function get($uri, $groupBy = self::GROUP_BY_DELIVERY) |
57 | { |
58 | $resultService = $this->getServiceLocator()->get(ResultServerService::SERVICE_ID); |
59 | $implementation = $resultService->getResultStorage(); |
60 | return $this->format($implementation, $uri); |
61 | } |
62 | |
63 | public function format( |
64 | taoResultServer_models_classes_ReadableResultStorage $resultStorage, |
65 | $resultIdentifier, |
66 | int $groupBy = self::GROUP_BY_DELIVERY, |
67 | bool $fetchOnlyLastAttemptResult = false, |
68 | bool $splitByAttempt = false |
69 | ): array { |
70 | $groupedData = []; |
71 | if ($groupBy === self::GROUP_BY_DELIVERY || $groupBy === self::GROUP_BY_ITEM) { |
72 | $calls = $resultStorage->getRelatedItemCallIds($resultIdentifier); |
73 | } else { |
74 | $calls = $resultStorage->getRelatedTestCallIds($resultIdentifier); |
75 | $fetchOnlyLastAttemptResult = false; |
76 | } |
77 | |
78 | foreach ($calls as $callId) { |
79 | $results = $resultStorage->getVariables($callId); |
80 | $results = $this->getNormalizer()->normalize($results); |
81 | $lastData = []; |
82 | foreach ($results as $result) { |
83 | $result = array_pop($result); |
84 | if (isset($result->variable)) { |
85 | $resource = $this->getFormResource($result->variable); |
86 | if (!$fetchOnlyLastAttemptResult) { |
87 | $lastData[] = $resource; |
88 | } else { |
89 | $currentResTime = preg_replace('/0(\.\d*)\s(\d*)/', '$2$1', $resource['epoch']); |
90 | $previousResTime = preg_replace( |
91 | '/0(\.\d*)\s(\d*)/', |
92 | '$2$1', |
93 | $lastData[$resource['identifier']]['epoch'] ?? '0.0 0' |
94 | ); |
95 | if ($currentResTime > $previousResTime) { |
96 | $lastData[$resource['identifier']] = $resource; |
97 | } |
98 | } |
99 | } |
100 | } |
101 | $groupKey = $groupBy === self::GROUP_BY_DELIVERY ? $resultIdentifier : $callId; |
102 | $groupedData[$groupKey][] = $splitByAttempt ? $this->splitByAttempt($lastData) : $lastData; |
103 | } |
104 | foreach ($groupedData as $groupKey => $items) { |
105 | $returnData[$groupKey] = array_merge(...$items); |
106 | } |
107 | return $returnData ?? []; |
108 | } |
109 | |
110 | public function getAll() |
111 | { |
112 | $resources = []; |
113 | $deliveryService = DeliveryAssemblyService::singleton(); |
114 | foreach ($deliveryService->getAllAssemblies() as $assembly) { |
115 | // delivery uri |
116 | $delivery = $assembly->getUri(); |
117 | |
118 | $resultService = $this->getServiceLocator()->get(ResultServerService::SERVICE_ID); |
119 | $implementation = $resultService->getResultStorage(); |
120 | |
121 | // get delivery executions |
122 | |
123 | //get all info |
124 | foreach ($implementation->getResultByDelivery([$delivery]) as $result) { |
125 | $result = array_merge($result, [RDFS_LABEL => $assembly->getLabel()]); |
126 | $properties = []; |
127 | foreach ($result as $key => $value) { |
128 | $property = []; |
129 | $type = 'resource'; |
130 | switch ($key) { |
131 | case 'deliveryResultIdentifier': |
132 | $property['predicateUri'] = "http://www.tao.lu/Ontologies/TAOResult.rdf#Identifier"; |
133 | break; |
134 | case 'testTakerIdentifier': |
135 | $property['predicateUri'] = "http://www.tao.lu/Ontologies/TAOResult.rdf#resultOfSubject"; |
136 | break; |
137 | case 'deliveryIdentifier': |
138 | $property['predicateUri'] = "http://www.tao.lu/Ontologies/TAOResult.rdf#resultOfDelivery"; |
139 | break; |
140 | default: |
141 | $property['predicateUri'] = $key; |
142 | $type = 'literal'; |
143 | break; |
144 | } |
145 | $property['values'] = ['valueType' => $type, 'value' => $value]; |
146 | |
147 | $properties[] = $property; |
148 | } |
149 | $resources[] = [ |
150 | 'uri' => $result['deliveryResultIdentifier'], |
151 | 'properties' => $properties |
152 | ]; |
153 | } |
154 | } |
155 | return $resources; |
156 | } |
157 | |
158 | |
159 | public function delete($resource) |
160 | { |
161 | throw new \common_exception_NoImplementation(); |
162 | } |
163 | |
164 | public function deleteAll() |
165 | { |
166 | throw new \common_exception_NoImplementation(); |
167 | } |
168 | |
169 | |
170 | public function update($uri = null, $propertiesValues = []) |
171 | { |
172 | throw new \common_exception_NoImplementation(); |
173 | } |
174 | |
175 | public function isInScope($uri) |
176 | { |
177 | return true; |
178 | } |
179 | |
180 | /** |
181 | * |
182 | * @author Patrick Plichart, patrick@taotesting.com |
183 | * return tao_models_classes_ClassService |
184 | */ |
185 | protected function getClassService() |
186 | { |
187 | // TODO: Implement getClassService() method. |
188 | } |
189 | |
190 | private function getFormResource($variable): array |
191 | { |
192 | $resource['value'] = $variable->getValue(); |
193 | $resource['identifier'] = $variable->getIdentifier(); |
194 | if ($variable instanceof taoResultServer_models_classes_ResponseVariable) { |
195 | $resource['type'] = $this->getClass(QtiResultsService::CLASS_RESPONSE_VARIABLE); |
196 | } else { |
197 | $resource['type'] = $this->getClass(QtiResultsService::CLASS_OUTCOME_VARIABLE); |
198 | } |
199 | $resource['epoch'] = $variable->getEpoch(); |
200 | $resource['cardinality'] = $variable->getCardinality(); |
201 | $resource['basetype'] = $variable->getBaseType(); |
202 | return $resource; |
203 | } |
204 | |
205 | private function splitByAttempt(array $itemVariables): array |
206 | { |
207 | return $this->getItemVariableSplitter()->splitByAttempt($itemVariables); |
208 | } |
209 | |
210 | private function getItemVariableSplitter(): ItemResponseVariableSplitter |
211 | { |
212 | return $this->getServiceLocator()->get(ItemResponseVariableSplitter::class); |
213 | } |
214 | |
215 | private function getNormalizer(): ItemResponseCollectionNormalizer |
216 | { |
217 | return $this->getServiceLocator()->get(ItemResponseCollectionNormalizer::class); |
218 | } |
219 | } |