Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 161 |
|
0.00% |
0 / 16 |
CRAP | |
0.00% |
0 / 1 |
DeliveryMgmt | |
0.00% |
0 / 161 |
|
0.00% |
0 / 16 |
1482 | |
0.00% |
0 / 1 |
getEventManager | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getClassService | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
editDelivery | |
0.00% |
0 / 51 |
|
0.00% |
0 / 1 |
72 | |||
excludeTesttaker | |
0.00% |
0 / 20 |
|
0.00% |
0 / 1 |
20 | |||
saveExcluded | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
20 | |||
wizard | |
0.00% |
0 / 28 |
|
0.00% |
0 / 1 |
42 | |||
getAvailableTests | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
20 | |||
moveResource | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
moveAll | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getTreeOptionsFromRequest | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
isUserRestricted | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
getExtraValidationRules | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getValidatorFactory | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDeliveryFormFactory | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getRoleBasedContextRestrictAccess | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getFeatureFlagChecker | |
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) 2014-2024 (original work) Open Assessment Technologies SA; |
19 | * |
20 | * |
21 | */ |
22 | |
23 | namespace oat\taoDeliveryRdf\controller; |
24 | |
25 | use oat\generis\model\kernel\persistence\smoothsql\search\ComplexSearchService; |
26 | use oat\generis\model\OntologyRdfs; |
27 | use oat\oatbox\event\EventManager; |
28 | use oat\tao\helpers\Template; |
29 | use oat\tao\model\accessControl\RoleBasedContextRestrictAccess; |
30 | use oat\tao\model\featureFlag\FeatureFlagCheckerInterface; |
31 | use oat\tao\model\featureFlag\FeatureFlagChecker; |
32 | use oat\tao\model\resources\ResourceWatcher; |
33 | use oat\tao\model\TaoOntology; |
34 | use oat\tao\model\taskQueue\TaskLogActionTrait; |
35 | use oat\taoDacSimple\model\PermissionProvider; |
36 | use oat\taoDelivery\model\AssignmentService; |
37 | use oat\taoDelivery\model\execution\ServiceProxy; |
38 | use oat\taoDeliveryRdf\model\Delivery\Presentation\Web\Form\DeliveryFormFactory; |
39 | use oat\taoDeliveryRdf\model\DeliveryContainerService; |
40 | use oat\taoDeliveryRdf\model\DeliveryFactory; |
41 | use oat\taoDeliveryRdf\model\event\DeliveryUpdatedEvent; |
42 | use oat\taoDeliveryRdf\model\GroupAssignment; |
43 | use oat\taoDeliveryRdf\model\tasks\CompileDelivery; |
44 | use oat\taoDeliveryRdf\model\validation\DeliveryValidatorFactory; |
45 | use oat\taoDeliveryRdf\view\form\WizardForm; |
46 | use oat\taoDeliveryRdf\model\NoTestsException; |
47 | use oat\taoDeliveryRdf\model\DeliveryAssemblyService; |
48 | use oat\taoDelivery\model\execution\Monitoring; |
49 | use tao_helpers_form_FormContainer as FormContainer; |
50 | |
51 | /** |
52 | * Controller to managed assembled deliveries |
53 | * |
54 | * @author CRP Henri Tudor - TAO Team - {@link http://www.tao.lu} |
55 | * @package taoDelivery |
56 | */ |
57 | class DeliveryMgmt extends \tao_actions_SaSModule |
58 | { |
59 | use TaskLogActionTrait; |
60 | |
61 | private const FEATURE_FLAG_GROUPS_DISABLED = 'FEATURE_FLAG_GROUPS_DISABLED'; |
62 | private const FEATURE_FLAG_TEST_TAKERS_DISABLED = 'FEATURE_FLAG_TEST_TAKERS_DISABLED'; |
63 | |
64 | /** |
65 | * @return EventManager |
66 | */ |
67 | protected function getEventManager() |
68 | { |
69 | return $this->getServiceLocator()->get(EventManager::SERVICE_ID); |
70 | } |
71 | |
72 | /** |
73 | * (non-PHPdoc) |
74 | * @see \tao_actions_SaSModule::getClassService() |
75 | */ |
76 | protected function getClassService() |
77 | { |
78 | if (!$this->service) { |
79 | $this->service = DeliveryAssemblyService::singleton(); |
80 | } |
81 | return $this->service; |
82 | } |
83 | |
84 | /** |
85 | * Edit a delivery instance |
86 | * |
87 | * @access public |
88 | * @author CRP Henri Tudor - TAO Team - {@link http://www.tao.lu} |
89 | * @return void |
90 | * @throws \common_exception_NoImplementation |
91 | * @throws \common_exception_Error |
92 | * @throws \oat\tao\model\security\SecurityException |
93 | */ |
94 | public function editDelivery() |
95 | { |
96 | $this->defaultData(); |
97 | |
98 | $delivery = $this->getCurrentInstance(); |
99 | |
100 | $formContainer = $this->getDeliveryFormFactory()->create( |
101 | $delivery, |
102 | [FormContainer::CSRF_PROTECTION_OPTION => true] |
103 | ); |
104 | $myForm = $formContainer->getForm(); |
105 | $deliveryUri = $delivery->getUri(); |
106 | |
107 | if ($myForm->isSubmited() && $myForm->isValid()) { |
108 | $this->validateInstanceRoot($deliveryUri); |
109 | $propertyValues = $myForm->getValues(); |
110 | |
111 | // then save the property values as usual |
112 | $binder = new \tao_models_classes_dataBinding_GenerisFormDataBinder($delivery); |
113 | $delivery = $binder->bind($propertyValues); |
114 | |
115 | $this->getEventManager()->trigger(new DeliveryUpdatedEvent($deliveryUri, $propertyValues)); |
116 | |
117 | $this->setData('selectNode', \tao_helpers_Uri::encode($deliveryUri)); |
118 | $this->setData('message', __('Delivery saved')); |
119 | $this->setData('reload', true); |
120 | } |
121 | |
122 | $this->setData('label', $delivery->getLabel()); |
123 | |
124 | // history |
125 | $this->setData('date', $this->getClassService()->getCompilationDate($delivery)); |
126 | $serviceProxy = $this->getServiceLocator()->get(ServiceProxy::SERVICE_ID); |
127 | if ($serviceProxy instanceof Monitoring) { |
128 | $execs = $serviceProxy->getExecutionsByDelivery($delivery); |
129 | $this->setData('exec', count($execs)); |
130 | } |
131 | |
132 | $assignmentService = $this->getServiceLocator()->get(AssignmentService::SERVICE_ID); |
133 | if (!$this->isUserRestricted() && get_class($assignmentService) == GroupAssignment::class) { |
134 | // define the groups related to the current delivery |
135 | $property = $this->getProperty(GroupAssignment::PROPERTY_GROUP_DELIVERY); |
136 | $tree = \tao_helpers_form_GenerisTreeForm::buildReverseTree($delivery, $property); |
137 | $tree->setTitle(__('Assigned to')); |
138 | $tree->setTemplate(Template::getTemplate('widgets/assignGroup.tpl')); |
139 | $this->setData('groupTree', $tree->render()); |
140 | } |
141 | |
142 | $solarDesignEnabled = $this->getFeatureFlagChecker()->isEnabled( |
143 | FeatureFlagCheckerInterface::FEATURE_FLAG_SOLAR_DESIGN_ENABLED |
144 | ); |
145 | |
146 | $this->setData( |
147 | 'ttdisabled', |
148 | $this->isUserRestricted() || $solarDesignEnabled |
149 | ); |
150 | |
151 | // testtaker brick |
152 | $this->setData('assemblyUri', $deliveryUri); |
153 | |
154 | // define the subjects excluded from the current delivery |
155 | $property = $this->getProperty(DeliveryContainerService::PROPERTY_EXCLUDED_SUBJECTS); |
156 | $excluded = $delivery->getPropertyValues($property); |
157 | $this->setData('ttexcluded', count($excluded)); |
158 | |
159 | $users = $assignmentService->getAssignedUsers($deliveryUri); |
160 | $assigned = array_diff(array_unique($users), $excluded); |
161 | $this->setData('ttassigned', count($assigned)); |
162 | |
163 | $updatedAt = $this->getServiceLocator()->get(ResourceWatcher::SERVICE_ID)->getUpdatedAt($delivery); |
164 | $this->setData('updatedAt', $updatedAt); |
165 | $this->setData('formTitle', __('Properties')); |
166 | $this->setData('myForm', $myForm->render()); |
167 | |
168 | if ($this->getServiceLocator()->get(\common_ext_ExtensionsManager::SERVICE_ID)->isEnabled('taoCampaign')) { |
169 | $this->setData('campaign', taoCampaign_helpers_Campaign::renderCampaignTree($delivery)); |
170 | } |
171 | $this->setView('DeliveryMgmt/editDelivery.tpl'); |
172 | } |
173 | |
174 | public function excludeTesttaker() |
175 | { |
176 | $this->defaultData(); |
177 | |
178 | $assembly = $this->getCurrentInstance(); |
179 | $this->setData('assemblyUri', $assembly->getUri()); |
180 | |
181 | // define the subjects excluded from the current delivery |
182 | $property = $this->getProperty(DeliveryContainerService::PROPERTY_EXCLUDED_SUBJECTS); |
183 | $excluded = []; |
184 | foreach ($assembly->getPropertyValues($property) as $uri) { |
185 | $user = $this->getResource($uri); |
186 | $excluded[$uri] = $user->getLabel(); |
187 | } |
188 | |
189 | $assigned = []; |
190 | $assignedUsers = $this |
191 | ->getServiceLocator() |
192 | ->get(AssignmentService::SERVICE_ID) |
193 | ->getAssignedUsers($assembly->getUri()); |
194 | |
195 | foreach ($assignedUsers as $userId) { |
196 | if (!array_key_exists($userId, $excluded)) { |
197 | $user = $this->getResource($userId); |
198 | $assigned[$userId] = $user->getLabel(); |
199 | } |
200 | } |
201 | |
202 | $this->setData('assigned', $assigned); |
203 | $this->setData('excluded', $excluded); |
204 | |
205 | |
206 | $this->setView('DeliveryMgmt/excludeTesttaker.tpl'); |
207 | } |
208 | |
209 | public function saveExcluded() |
210 | { |
211 | if (!$this->isXmlHttpRequest()) { |
212 | throw new \common_exception_IsAjaxAction(__FUNCTION__); |
213 | } |
214 | if (!$this->hasRequestParameter('excluded')) { |
215 | throw new \common_exception_MissingParameter('excluded'); |
216 | } |
217 | |
218 | $jsonArray = json_decode($_POST['excluded']); |
219 | if (!is_array($jsonArray)) { |
220 | throw new \common_Exception('parameter "excluded" should be a json encoded array'); |
221 | } |
222 | |
223 | $assembly = $this->getCurrentInstance(); |
224 | $success = $assembly->editPropertyValues( |
225 | $this->getProperty(DeliveryContainerService::PROPERTY_EXCLUDED_SUBJECTS), |
226 | $jsonArray |
227 | ); |
228 | |
229 | $this->getEventManager()->trigger( |
230 | new DeliveryUpdatedEvent( |
231 | $assembly->getUri(), |
232 | [ |
233 | DeliveryContainerService::PROPERTY_EXCLUDED_SUBJECTS => $jsonArray, |
234 | ] |
235 | ) |
236 | ); |
237 | |
238 | $this->returnJson([ |
239 | 'saved' => $success |
240 | ]); |
241 | } |
242 | |
243 | public function wizard() |
244 | { |
245 | $this->defaultData(); |
246 | |
247 | try { |
248 | $formContainer = new WizardForm(['class' => $this->getCurrentClass()]); |
249 | $myForm = $formContainer->getForm(); |
250 | |
251 | if ($myForm->isValid() && $myForm->isSubmited()) { |
252 | try { |
253 | $test = $this->getResource($myForm->getValue('test')); |
254 | $deliveryClass = $this->getClass($myForm->getValue('classUri')); |
255 | /** @var DeliveryFactory $deliveryFactoryResources */ |
256 | $deliveryFactoryResources = $this->getServiceLocator()->get(DeliveryFactory::SERVICE_ID); |
257 | $initialProperties = $deliveryFactoryResources->getInitialPropertiesFromArray($myForm->getValues()); |
258 | return $this->returnTaskJson( |
259 | CompileDelivery::createTask( |
260 | $test, |
261 | $deliveryClass, |
262 | $initialProperties |
263 | ) |
264 | ); |
265 | } catch (\Exception $e) { |
266 | return $this->returnJson([ |
267 | 'success' => false, |
268 | 'errorMsg' => $e instanceof \common_exception_UserReadableException |
269 | ? $e->getUserMessage() |
270 | : $e->getMessage(), |
271 | 'errorCode' => $e->getCode(), |
272 | ]); |
273 | } |
274 | } else { |
275 | $this->setData('myForm', $myForm->render()); |
276 | $this->setData('formTitle', __('Create a new delivery')); |
277 | $this->setView('form.tpl', 'tao'); |
278 | } |
279 | } catch (NoTestsException $e) { |
280 | $this->setView('DeliveryMgmt/wizard_error.tpl'); |
281 | } |
282 | } |
283 | |
284 | /** |
285 | * Prepare formatted for select2 component filtered list of available for compilation tests |
286 | * @throws \common_Exception |
287 | * @throws \oat\oatbox\service\ServiceNotFoundException |
288 | */ |
289 | public function getAvailableTests() |
290 | { |
291 | $q = $this->getRequestParameter('q'); |
292 | $tests = []; |
293 | |
294 | $testService = \taoTests_models_classes_TestsService::singleton(); |
295 | /** @var ComplexSearchService $search */ |
296 | $search = $this->getServiceLocator()->get(ComplexSearchService::SERVICE_ID); |
297 | |
298 | $queryBuilder = $search->query(); |
299 | $query = $search->searchType($queryBuilder, TaoOntology::CLASS_URI_TEST, true) |
300 | ->add(OntologyRdfs::RDFS_LABEL) |
301 | ->contains($q); |
302 | |
303 | $queryBuilder->setCriteria($query); |
304 | |
305 | $result = $search->getGateway()->search($queryBuilder); |
306 | |
307 | foreach ($result as $test) { |
308 | try { |
309 | $testItems = $testService->getTestItems($test); |
310 | //Filter tests which has no items |
311 | if (!empty($testItems)) { |
312 | $testUri = $test->getUri(); |
313 | $tests[] = ['id' => $testUri, 'uri' => $testUri, 'text' => $test->getLabel()]; |
314 | } |
315 | } catch (\Exception $e) { |
316 | $this->logWarning('Unable to load items for test ' . $testUri); |
317 | } |
318 | } |
319 | $this->returnJson(['total' => count($tests), 'items' => $tests]); |
320 | } |
321 | |
322 | /** |
323 | * overwrite the parent moveAllInstances to add the requiresRight only in Items |
324 | * @see tao_actions_TaoModule::moveResource() |
325 | * @requiresRight classUri WRITE |
326 | */ |
327 | public function moveResource() |
328 | { |
329 | return parent::moveResource(); |
330 | } |
331 | /** |
332 | * overwrite the parent moveAllInstances to add the requiresRight only in Items |
333 | * @see tao_actions_TaoModule::moveAll() |
334 | * @requiresRight ids WRITE |
335 | */ |
336 | public function moveAll() |
337 | { |
338 | return parent::moveAll(); |
339 | } |
340 | |
341 | /** |
342 | * @param array $options |
343 | * @throws \common_exception_IsAjaxAction |
344 | */ |
345 | protected function getTreeOptionsFromRequest($options = []) |
346 | { |
347 | $config = $this->getServiceLocator()->get('taoDeliveryRdf/DeliveryMgmt')->getConfig(); |
348 | $options['order'] = key($config['OntologyTreeOrder']); |
349 | $options['orderdir'] = $config['OntologyTreeOrder'][$options['order']]; |
350 | return parent::getTreeOptionsFromRequest($options); |
351 | } |
352 | |
353 | private function isUserRestricted() |
354 | { |
355 | return $this->getRoleBasedContextRestrictAccess() |
356 | ->isRestricted( |
357 | $this->getUserRoles(), |
358 | 'ltiAuthoringLaunchRestrictRoles' |
359 | ); |
360 | } |
361 | |
362 | protected function getExtraValidationRules(): array |
363 | { |
364 | return $this->getValidatorFactory()->createMultiple(); |
365 | } |
366 | |
367 | private function getValidatorFactory(): DeliveryValidatorFactory |
368 | { |
369 | return $this->getPsrContainer()->get(DeliveryValidatorFactory::class); |
370 | } |
371 | |
372 | private function getDeliveryFormFactory(): DeliveryFormFactory |
373 | { |
374 | return $this->getPsrContainer()->get(DeliveryFormFactory::class); |
375 | } |
376 | private function getRoleBasedContextRestrictAccess(): RoleBasedContextRestrictAccess |
377 | { |
378 | return $this->getPsrContainer()->get(RoleBasedContextRestrictAccess::class); |
379 | } |
380 | |
381 | private function getFeatureFlagChecker(): FeatureFlagCheckerInterface |
382 | { |
383 | return $this->getServiceLocator()->get(FeatureFlagChecker::class); |
384 | } |
385 | } |