Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
21.82% |
24 / 110 |
|
27.27% |
3 / 11 |
CRAP | |
0.00% |
0 / 1 |
MonitoringListener | |
21.82% |
24 / 110 |
|
27.27% |
3 / 11 |
375.37 | |
0.00% |
0 / 1 |
executionCreated | |
70.00% |
7 / 10 |
|
0.00% |
0 / 1 |
2.11 | |||
executionStateChanged | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
fillMonitoringOnExecutionStateChanged | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
30 | |||
testStateChanged | |
0.00% |
0 / 24 |
|
0.00% |
0 / 1 |
20 | |||
qtiTestStatusChanged | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
6 | |||
deliveryLabelChanged | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
12 | |||
deliveryAuthorized | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
catchTestReactivatedEvent | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
updateTestTakerInformation | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
updateDeliveryInformation | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
1 | |||
getMonitoringRepository | |
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) 2021 (original work) Open Assessment Technologies SA; |
19 | * |
20 | */ |
21 | |
22 | declare(strict_types=1); |
23 | |
24 | namespace oat\taoProctoring\model\listener; |
25 | |
26 | use common_exception_Error; |
27 | use common_exception_NotFound; |
28 | use common_session_SessionManager; |
29 | use Exception; |
30 | use oat\generis\model\GenerisRdf; |
31 | use oat\generis\model\OntologyRdfs; |
32 | use oat\oatbox\service\ConfigurableService; |
33 | use oat\oatbox\user\User; |
34 | use oat\tao\model\taskQueue\QueueDispatcherInterface; |
35 | use oat\taoDelivery\model\execution\DeliveryExecutionInterface; |
36 | use oat\taoDelivery\model\execution\DeliveryExecutionService; |
37 | use oat\taoDelivery\models\classes\execution\event\DeliveryExecutionCreated; |
38 | use oat\taoDelivery\models\classes\execution\event\DeliveryExecutionReactivated; |
39 | use oat\taoDelivery\models\classes\execution\event\DeliveryExecutionState; |
40 | use oat\tao\model\event\MetadataModified; |
41 | use oat\taoDeliveryRdf\model\DeliveryAssemblyService; |
42 | use oat\taoDeliveryRdf\model\guest\GuestTestUser; |
43 | use oat\taoProctoring\model\monitorCache\DeliveryMonitoringService; |
44 | use oat\taoProctoring\model\monitorCache\implementation\DeliveryMonitoringData; |
45 | use oat\taoProctoring\model\repository\MonitoringRepository; |
46 | use oat\taoProctoring\model\Tasks\DeliveryUpdaterTask; |
47 | use oat\taoQtiTest\models\event\QtiTestChangeEvent; |
48 | use oat\taoProctoring\model\execution\DeliveryExecution; |
49 | use oat\taoTests\models\event\TestChangedEvent; |
50 | use oat\taoQtiTest\models\event\QtiTestStateChangeEvent; |
51 | use oat\taoProctoring\model\authorization\AuthorizationGranted; |
52 | use tao_helpers_Date; |
53 | |
54 | class MonitoringListener extends ConfigurableService implements MonitoringListenerInterface |
55 | { |
56 | /** |
57 | * @throws common_exception_NotFound |
58 | */ |
59 | public function executionCreated(DeliveryExecutionCreated $event): void |
60 | { |
61 | $deliveryExecution = $event->getDeliveryExecution(); |
62 | |
63 | $data = $this->getMonitoringRepository()->createMonitoringData($deliveryExecution, []); |
64 | |
65 | $data = $this->updateDeliveryInformation($data, $deliveryExecution); |
66 | $data = $this->updateTestTakerInformation($data, $event->getUser()); |
67 | |
68 | $data->updateData([DeliveryMonitoringService::CONNECTIVITY]); |
69 | $success = $this->getMonitoringRepository()->save($data); |
70 | if (!$success) { |
71 | $this->logWarning( |
72 | 'monitor cache for delivery ' . $deliveryExecution->getIdentifier() . ' could not be created' |
73 | ); |
74 | } |
75 | } |
76 | |
77 | /** |
78 | * @throws common_exception_Error|common_exception_NotFound|Exception |
79 | */ |
80 | public function executionStateChanged(DeliveryExecutionState $event): void |
81 | { |
82 | $data = $this->getMonitoringRepository()->createMonitoringData($event->getDeliveryExecution()); |
83 | |
84 | $this->fillMonitoringOnExecutionStateChanged($event, $data); |
85 | |
86 | $success = $this->getMonitoringRepository()->partialSave($data); |
87 | if (!$success) { |
88 | $this->logWarning( |
89 | 'monitor cache for delivery ' . $event->getDeliveryExecution()->getIdentifier() |
90 | . ' could not be created' |
91 | ); |
92 | } |
93 | } |
94 | |
95 | /** |
96 | * @throws common_exception_Error|common_exception_NotFound |
97 | */ |
98 | protected function fillMonitoringOnExecutionStateChanged( |
99 | DeliveryExecutionState $event, |
100 | DeliveryMonitoringData $data |
101 | ): void { |
102 | $data->update(DeliveryMonitoringService::STATUS, $event->getState()); |
103 | $data->updateData([DeliveryMonitoringService::CONNECTIVITY]); |
104 | $user = common_session_SessionManager::getSession()->getUser(); |
105 | |
106 | if ( |
107 | in_array($event->getState(), [DeliveryExecution::STATE_AWAITING, DeliveryExecution::STATE_PAUSED]) |
108 | && $user instanceof GuestTestUser |
109 | ) { |
110 | $data->getDeliveryExecution()->setState(DeliveryExecution::STATE_AUTHORIZED); |
111 | } |
112 | |
113 | if ($event->getState() == DeliveryExecution::STATE_TERMINATED) { |
114 | $data->update( |
115 | DeliveryMonitoringService::END_TIME, |
116 | tao_helpers_Date::getTimeStamp(time(), true) |
117 | ); |
118 | } |
119 | if ($event->getState() == DeliveryExecution::STATE_FINISHED) { |
120 | $data->update( |
121 | DeliveryMonitoringService::END_TIME, |
122 | tao_helpers_Date::getTimeStamp($event->getDeliveryExecution()->getFinishTime(), true) |
123 | ); |
124 | } |
125 | } |
126 | |
127 | /** |
128 | * Something changed in the state of the test execution (for example: the current item in the test) |
129 | * |
130 | * @throws common_exception_NotFound|common_exception_Error |
131 | */ |
132 | public function testStateChanged(TestChangedEvent $event): void |
133 | { |
134 | $deliveryExecution = $this->getServiceLocator()->get(DeliveryExecutionService::SERVICE_ID) |
135 | ->getDeliveryExecution($event->getServiceCallId()); |
136 | |
137 | $data = $this->getMonitoringRepository()->createMonitoringData($deliveryExecution); |
138 | |
139 | $data->update(DeliveryMonitoringService::CURRENT_ASSESSMENT_ITEM, $event->getNewStateDescription()); |
140 | if ($event instanceof QtiTestChangeEvent) { |
141 | $data->setTestSession($event->getSession()); |
142 | $data->updateData([ |
143 | DeliveryMonitoringService::REMAINING_TIME, |
144 | DeliveryMonitoringService::EXTRA_TIME, |
145 | DeliveryMonitoringService::CONNECTIVITY |
146 | ]); |
147 | } |
148 | |
149 | $dataKeys = [ |
150 | DeliveryMonitoringService::STATUS, |
151 | ]; |
152 | $session = $event->getSession(); |
153 | $userId = common_session_SessionManager::getSession()->getUser()->getIdentifier(); |
154 | if ($deliveryExecution->getUserIdentifier() === $userId) { |
155 | $dataKeys[] = DeliveryMonitoringService::DIFF_TIMESTAMP; |
156 | $dataKeys[] = DeliveryMonitoringService::LAST_TEST_TAKER_ACTIVITY; |
157 | } |
158 | $data->setTestSession($session); |
159 | $data->updateData($dataKeys); |
160 | |
161 | $success = $this->getMonitoringRepository()->partialSave($data); |
162 | if (!$success) { |
163 | $this->logWarning('monitor cache for teststate could not be updated'); |
164 | } |
165 | } |
166 | |
167 | /** |
168 | * The status of the test execution has change (for example: from running to paused) |
169 | * |
170 | * @throws common_exception_NotFound |
171 | */ |
172 | public function qtiTestStatusChanged(QtiTestStateChangeEvent $event): void |
173 | { |
174 | /** @var DeliveryExecutionService $deliveryExecutionService */ |
175 | $deliveryExecutionService = $this->getServiceLocator()->get(DeliveryExecutionService::SERVICE_ID); |
176 | $deliveryExecution = $deliveryExecutionService->getDeliveryExecution($event->getServiceCallId()); |
177 | |
178 | $data = $this->getMonitoringRepository()->createMonitoringData($deliveryExecution); |
179 | |
180 | $data->setTestSession($event->getSession()); |
181 | $data->update(DeliveryMonitoringService::CURRENT_ASSESSMENT_ITEM, $event->getNewStateDescription()); |
182 | $data->updateData([ |
183 | DeliveryMonitoringService::CONNECTIVITY, |
184 | DeliveryMonitoringService::REMAINING_TIME |
185 | ]); |
186 | $success = $this->getMonitoringRepository()->partialSave($data); |
187 | if (!$success) { |
188 | $this->logWarning('monitor cache for teststate could not be updated'); |
189 | } |
190 | } |
191 | |
192 | /** |
193 | * Update the label of the delivery across the entry cache |
194 | * |
195 | * @param MetadataModified $event |
196 | */ |
197 | public function deliveryLabelChanged(MetadataModified $event): void |
198 | { |
199 | $resource = $event->getResource(); |
200 | if ($event->getMetadataUri() === OntologyRdfs::RDFS_LABEL) { |
201 | $assemblyClass = DeliveryAssemblyService::singleton()->getRootClass(); |
202 | if ($resource->isInstanceOf($assemblyClass)) { |
203 | /** @var $queueService QueueDispatcherInterface */ |
204 | $queueService = $this->getServiceLocator()->get(QueueDispatcherInterface::SERVICE_ID); |
205 | $queueService->createTask( |
206 | new DeliveryUpdaterTask(), |
207 | [$resource->getUri(), $event->getMetadataValue()], |
208 | 'Update delivery label' |
209 | ); |
210 | } |
211 | } |
212 | } |
213 | |
214 | /** |
215 | * Set the proctor who authorized this delivery execution |
216 | * |
217 | * @throws common_exception_NotFound |
218 | */ |
219 | public function deliveryAuthorized(AuthorizationGranted $event): void |
220 | { |
221 | $deliveryExecution = $event->getDeliveryExecution(); |
222 | $data = $this->getMonitoringRepository()->createMonitoringData($deliveryExecution); |
223 | |
224 | $data->update(DeliveryMonitoringService::AUTHORIZED_BY, $event->getAuthorizer()->getIdentifier()); |
225 | if (!$this->getMonitoringRepository()->partialSave($data)) { |
226 | $this->logWarning('monitor cache for authorization could not be updated'); |
227 | } |
228 | } |
229 | |
230 | /** |
231 | * @throws common_exception_NotFound |
232 | */ |
233 | public function catchTestReactivatedEvent(DeliveryExecutionReactivated $event): void |
234 | { |
235 | $deliveryExecution = $event->getDeliveryExecution(); |
236 | |
237 | $data = $this->getMonitoringRepository()->createMonitoringData($deliveryExecution); |
238 | |
239 | $data->update(DeliveryMonitoringService::REACTIVATE_AUTHORIZED_BY, $event->getUser()->getIdentifier()); |
240 | |
241 | $success = $this->getMonitoringRepository()->partialSave($data); |
242 | if (!$success) { |
243 | $this->logWarning( |
244 | 'monitor cache for delivery ' . $deliveryExecution->getIdentifier() . ' could not be created' |
245 | ); |
246 | } |
247 | } |
248 | |
249 | private function updateTestTakerInformation(DeliveryMonitoringData $data, User $user): DeliveryMonitoringData |
250 | { |
251 | $firstNames = $user->getPropertyValues(GenerisRdf::PROPERTY_USER_FIRSTNAME); |
252 | if (!empty($firstNames)) { |
253 | $data->update(DeliveryMonitoringService::TEST_TAKER_FIRST_NAME, reset($firstNames)); |
254 | } |
255 | $lastNames = $user->getPropertyValues(GenerisRdf::PROPERTY_USER_LASTNAME); |
256 | if (!empty($lastNames)) { |
257 | $data->update(DeliveryMonitoringService::TEST_TAKER_LAST_NAME, reset($lastNames)); |
258 | } |
259 | |
260 | return $data; |
261 | } |
262 | |
263 | private function updateDeliveryInformation( |
264 | DeliveryMonitoringData $data, |
265 | DeliveryExecutionInterface $deliveryExecution |
266 | ): DeliveryMonitoringData { |
267 | $data->update(DeliveryMonitoringService::STATUS, $deliveryExecution->getState()->getUri()); |
268 | $data->update(DeliveryMonitoringService::TEST_TAKER, $deliveryExecution->getUserIdentifier()); |
269 | $data->update(DeliveryMonitoringService::DELIVERY_ID, $deliveryExecution->getDelivery()->getUri()); |
270 | $data->update(DeliveryMonitoringService::DELIVERY_NAME, $deliveryExecution->getDelivery()->getLabel()); |
271 | $data->update( |
272 | DeliveryMonitoringService::START_TIME, |
273 | tao_helpers_Date::getTimeStamp($deliveryExecution->getStartTime(), true) |
274 | ); |
275 | |
276 | return $data; |
277 | } |
278 | |
279 | private function getMonitoringRepository(): MonitoringRepository |
280 | { |
281 | return $this->getServiceLocator()->get(DeliveryMonitoringService::SERVICE_ID); |
282 | } |
283 | } |