Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 136 |
|
0.00% |
0 / 16 |
CRAP | |
0.00% |
0 / 1 |
taoTests_actions_Tests | |
0.00% |
0 / 136 |
|
0.00% |
0 / 16 |
1190 | |
0.00% |
0 / 1 |
getEventManager | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getClassService | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
preview | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
editTest | |
0.00% |
0 / 68 |
|
0.00% |
0 / 1 |
110 | |||
delete | |
0.00% |
0 / 30 |
|
0.00% |
0 / 1 |
42 | |||
authoring | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
30 | |||
moveInstance | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
moveAll | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
cloneInstance | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
deleteAll | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
moveClass | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDependsOnPropertyValidator | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getClassDeleter | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getResourceDeleter | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getTranslationSyncService | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | // phpcs:disable Generic.Files.LineLength |
4 | /* |
5 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public License |
7 | * as published by the Free Software Foundation; under version 2 |
8 | * of the License (non-upgradable). |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * |
19 | * Copyright (c) 2002-2008 (original work) Public Research Centre Henri Tudor & University of Luxembourg (under the project TAO & TAO2); |
20 | * 2008-2010 (update and modification) Deutsche Institut für Internationale Pädagogische Forschung (under the project TAO-TRANSFER); |
21 | * 2009-2012 (update and modification) Public Research Centre Henri Tudor (under the project TAO-SUSTAIN & TAO-DEV); |
22 | * |
23 | */ |
24 | // phpcs:enable |
25 | |
26 | use oat\oatbox\event\EventManager; |
27 | use oat\tao\model\lock\LockManager; |
28 | use oat\oatbox\validator\ValidatorInterface; |
29 | use oat\tao\model\accessControl\Context; |
30 | use oat\tao\model\resources\ResourceWatcher; |
31 | use oat\tao\model\TaoOntology; |
32 | use oat\taoTests\models\event\TestUpdatedEvent; |
33 | use oat\tao\model\controller\SignedFormInstance; |
34 | use oat\tao\model\resources\Service\ClassDeleter; |
35 | use oat\tao\model\routing\AnnotationReader\security; |
36 | use oat\taoTests\models\Form\Modifier\FormModifierProxy; |
37 | use oat\taoTests\models\Translation\Form\Modifier\TranslationFormModifierProxy; |
38 | use tao_helpers_form_FormContainer as FormContainer; |
39 | use oat\generis\model\resource\Service\ResourceDeleter; |
40 | use oat\tao\model\resources\Contract\ClassDeleterInterface; |
41 | use oat\generis\model\resource\Contract\ResourceDeleterInterface; |
42 | use oat\generis\model\resource\exception\ResourceDeletionException; |
43 | use oat\tao\model\resources\Exception\PartialClassDeletionException; |
44 | use oat\tao\model\Lists\Business\Validation\DependsOnPropertyValidator; |
45 | use oat\tao\model\Translation\Service\TranslationSyncService; |
46 | |
47 | /** |
48 | * Tests Controller provide actions performed from url resolution |
49 | * |
50 | * @author Bertrand Chevrier, <taosupport@tudor.lu> |
51 | * @package taoTests |
52 | |
53 | * @license GPLv2 http://www.opensource.org/licenses/gpl-2.0.php |
54 | * |
55 | */ |
56 | // phpcs:ignore |
57 | class taoTests_actions_Tests extends tao_actions_SaSModule |
58 | { |
59 | /** |
60 | * @return EventManager |
61 | */ |
62 | protected function getEventManager() |
63 | { |
64 | return $this->getServiceLocator()->get(EventManager::SERVICE_ID); |
65 | } |
66 | |
67 | protected function getClassService() |
68 | { |
69 | return taoTests_models_classes_TestsService::singleton(); |
70 | } |
71 | |
72 | /** |
73 | * constructor: initialize the service and the default data |
74 | * @security("hide") |
75 | */ |
76 | public function __construct() |
77 | { |
78 | parent::__construct(); |
79 | |
80 | //the service is initialized by default |
81 | $this->service = taoTests_models_classes_TestsService::singleton(); |
82 | $this->defaultData(); |
83 | } |
84 | |
85 | /* |
86 | * controller actions |
87 | */ |
88 | |
89 | /** |
90 | * @requiresRight id READ |
91 | */ |
92 | public function preview(): void |
93 | { |
94 | $this->index(); |
95 | } |
96 | |
97 | /** |
98 | * edit a test instance |
99 | * @requiresRight id READ |
100 | */ |
101 | public function editTest() |
102 | { |
103 | $test = new core_kernel_classes_Resource($this->getRequestParameter('id')); |
104 | |
105 | $this->setData('isPreviewEnabled', $this->service->hasItems($test)); |
106 | |
107 | if (!$this->isLocked($test)) { |
108 | // my lock |
109 | $lock = LockManager::getImplementation()->getLockData($test); |
110 | $sessionIdentifier = common_session_SessionManager::getSession()->getUser()->getIdentifier(); |
111 | |
112 | if (!is_null($lock) && $lock->getOwnerId() === $sessionIdentifier) { |
113 | $this->setData('lockDate', $lock->getCreationTime()); |
114 | $this->setData('id', $lock->getResource()->getUri()); |
115 | } |
116 | |
117 | $context = new Context( |
118 | [ |
119 | Context::PARAM_CONTROLLER => self::class, |
120 | Context::PARAM_ACTION => __FUNCTION__, |
121 | ] |
122 | ); |
123 | $hasWriteAccess = $this->hasWriteAccess($test->getUri()) && $this->hasWriteAccessByContext($context); |
124 | |
125 | $clazz = $this->getCurrentClass(); |
126 | $formContainer = new SignedFormInstance( |
127 | $clazz, |
128 | $test, |
129 | [ |
130 | FormContainer::IS_DISABLED => !$hasWriteAccess, |
131 | FormContainer::CSRF_PROTECTION_OPTION => true, |
132 | FormContainer::ATTRIBUTE_VALIDATORS => [ |
133 | 'data-depends-on-property' => [ |
134 | $this->getDependsOnPropertyValidator(), |
135 | ], |
136 | ], |
137 | FormContainer::FORM_MODIFIERS => [ |
138 | FormModifierProxy::class, |
139 | TranslationFormModifierProxy::class, |
140 | ], |
141 | ] |
142 | ); |
143 | $myForm = $formContainer->getForm(); |
144 | |
145 | $myForm->setOptions([ |
146 | 'resourceType' => TaoOntology::CLASS_URI_TEST |
147 | ]); |
148 | |
149 | if ($hasWriteAccess) { |
150 | if ($myForm->isSubmited() && $myForm->isValid()) { |
151 | $this->validateInstanceRoot($test->getUri()); |
152 | |
153 | $propertyValues = $myForm->getValues(); |
154 | |
155 | // don't hande the testmodel via bindProperties |
156 | if ( |
157 | array_key_exists( |
158 | taoTests_models_classes_TestsService::PROPERTY_TEST_TESTMODEL, |
159 | $propertyValues |
160 | ) |
161 | ) { |
162 | $modelUri = $propertyValues[taoTests_models_classes_TestsService::PROPERTY_TEST_TESTMODEL]; |
163 | unset($propertyValues[taoTests_models_classes_TestsService::PROPERTY_TEST_TESTMODEL]); |
164 | if (!empty($modelUri)) { |
165 | $testModel = new core_kernel_classes_Resource($modelUri); |
166 | $this->service->setTestModel($test, $testModel); |
167 | } |
168 | } else { |
169 | common_Logger::w('No testmodel on test form', 'taoTests'); |
170 | } |
171 | |
172 | //then save the property values as usual |
173 | $binder = new tao_models_classes_dataBinding_GenerisFormDataBinder($test); |
174 | $test = $binder->bind($propertyValues); |
175 | $this->getEventManager()->trigger(new TestUpdatedEvent($test->getUri(), $propertyValues)); |
176 | |
177 | $this->setData('selectNode', tao_helpers_Uri::encode($test->getUri())); |
178 | $this->setData('message', __('Test saved')); |
179 | $this->setData('reload', true); |
180 | } |
181 | } else { |
182 | $myForm->setActions([]); |
183 | } |
184 | |
185 | $myForm->removeElement(tao_helpers_Uri::encode( |
186 | taoTests_models_classes_TestsService::PROPERTY_TEST_CONTENT |
187 | )); |
188 | $updatedAt = $this->getServiceLocator()->get(ResourceWatcher::SERVICE_ID)->getUpdatedAt($test); |
189 | $this->setData('updatedAt', $updatedAt); |
190 | $this->setData('uri', tao_helpers_Uri::encode($test->getUri())); |
191 | $this->setData('classUri', tao_helpers_Uri::encode($clazz->getUri())); |
192 | $this->setData('formTitle', __('Test properties')); |
193 | $this->setData('myForm', $myForm->render()); |
194 | $this->setView('Tests/editTest.tpl'); |
195 | } |
196 | } |
197 | |
198 | /** |
199 | * delete a test or a test class. called via ajax |
200 | * |
201 | * @throws Exception |
202 | * @throws common_exception_BadRequest |
203 | * @requiresRight id WRITE |
204 | */ |
205 | public function delete() |
206 | { |
207 | try { |
208 | $this->validateCsrf(); |
209 | } catch (common_exception_Unauthorized $e) { |
210 | $this->response = $this->getPsrResponse()->withStatus(403, __('Unable to process your request')); |
211 | return; |
212 | } |
213 | if (!tao_helpers_Request::isAjax()) { |
214 | throw new common_exception_BadRequest('wrong request mode'); |
215 | } |
216 | |
217 | $uri = $this->getRequestParameter('id'); |
218 | |
219 | $this->validateInstanceRoot($uri); |
220 | |
221 | $instance = $this->getCurrentInstance('id'); |
222 | |
223 | $lockManager = LockManager::getImplementation(); |
224 | $userId = common_session_SessionManager::getSession()->getUser()->getIdentifier(); |
225 | |
226 | if ($lockManager->isLocked($instance)) { |
227 | $lockManager->releaseLock($instance, $userId); |
228 | } |
229 | |
230 | $label = $instance->getLabel(); |
231 | /** |
232 | * @var ResourceDeleterInterface|ClassDeleterInterface $deleter |
233 | * @var core_kernel_classes_Resource|core_kernel_classes_Class $instanceToDelete |
234 | */ |
235 | [$deleter, $instanceToDelete] = $instance->isClass() |
236 | ? [$this->getClassDeleter(), $this->getClass($instance)] |
237 | : [$this->getResourceDeleter(), $instance]; |
238 | |
239 | try { |
240 | $deleter->delete($instanceToDelete); |
241 | $success = true; |
242 | $deleted = true; |
243 | $message = __('%s has been deleted', $label); |
244 | } catch (PartialClassDeletionException | ResourceDeletionException $exception) { |
245 | $success = $exception instanceof PartialClassDeletionException; |
246 | $deleted = false; |
247 | $message = $exception->getUserMessage(); |
248 | } |
249 | |
250 | $this->returnJson([ |
251 | 'success' => $success, |
252 | 'message' => $message, |
253 | 'deleted' => $deleted, |
254 | ]); |
255 | } |
256 | |
257 | /** |
258 | * Redirect the test's authoring |
259 | * @requiresRight id WRITE |
260 | */ |
261 | public function authoring() |
262 | { |
263 | $test = new core_kernel_classes_Resource($this->getRequestParameter('id')); |
264 | if (!$this->isLocked($test)) { |
265 | $testModel = $this->service->getTestModel($test); |
266 | $testModelImpl = $this->service->getTestModelImplementation($testModel); |
267 | $authoringUrl = $testModelImpl->getAuthoringUrl($test); |
268 | if (!empty($authoringUrl)) { |
269 | $userId = common_session_SessionManager::getSession()->getUser()->getIdentifier(); |
270 | LockManager::getImplementation()->setLock($test, $userId); |
271 | |
272 | // Add support for the translation and the side-by-side authoring tool |
273 | if ($this->getRequestParameter('translation') !== null) { |
274 | $authoringUrl = sprintf( |
275 | '%s&translation=%s', |
276 | $authoringUrl, |
277 | $this->getRequestParameter('translation') |
278 | ); |
279 | } |
280 | if ($this->getRequestParameter('originResourceUri') !== null) { |
281 | $this->getTranslationSyncService()->syncById($this->getRequestParameter('originResourceUri')); |
282 | $authoringUrl = sprintf( |
283 | '%s&originResourceUri=%s', |
284 | $authoringUrl, |
285 | $this->getRequestParameter('originResourceUri') |
286 | ); |
287 | } |
288 | |
289 | return $this->forwardUrl($authoringUrl); |
290 | } |
291 | throw new common_exception_NoImplementation(); |
292 | } |
293 | } |
294 | |
295 | /** |
296 | * overwrite the parent moveInstance to add the requiresRight only in Tests |
297 | * @see tao_actions_TaoModule::moveInstance() |
298 | * @requiresRight uri WRITE |
299 | * @requiresRight destinationClassUri WRITE |
300 | */ |
301 | public function moveInstance() |
302 | { |
303 | parent::moveInstance(); |
304 | } |
305 | |
306 | /** |
307 | * overwrite the parent moveAllInstances to add the requiresRight only in Items |
308 | * @see tao_actions_TaoModule::moveAll() |
309 | * @requiresRight ids WRITE |
310 | */ |
311 | public function moveAll() |
312 | { |
313 | return parent::moveAll(); |
314 | } |
315 | |
316 | /** |
317 | * overwrite the parent cloneInstance to add the requiresRight only in Tests |
318 | * @see tao_actions_TaoModule::cloneInstance() |
319 | * @requiresRight uri READ |
320 | * @requiresRight classUri WRITE |
321 | */ |
322 | public function cloneInstance() |
323 | { |
324 | return parent::cloneInstance(); |
325 | } |
326 | |
327 | /** |
328 | * Delete all given resources |
329 | * |
330 | * @requiresRight ids WRITE |
331 | * |
332 | * @throws Exception |
333 | */ |
334 | public function deleteAll() |
335 | { |
336 | return parent::deleteAll(); |
337 | } |
338 | |
339 | /** |
340 | * Move class to another location |
341 | * @requiresRight classUri WRITE |
342 | */ |
343 | public function moveClass() |
344 | { |
345 | return parent::moveResource(); |
346 | } |
347 | |
348 | private function getDependsOnPropertyValidator(): ValidatorInterface |
349 | { |
350 | return $this->getPsrContainer()->get(DependsOnPropertyValidator::class); |
351 | } |
352 | |
353 | private function getClassDeleter(): ClassDeleterInterface |
354 | { |
355 | return $this->getPsrContainer()->get(ClassDeleter::class); |
356 | } |
357 | |
358 | private function getResourceDeleter(): ResourceDeleterInterface |
359 | { |
360 | return $this->getPsrContainer()->get(ResourceDeleter::class); |
361 | } |
362 | |
363 | private function getTranslationSyncService(): TranslationSyncService |
364 | { |
365 | return $this->getPsrContainer()->get(TranslationSyncService::class); |
366 | } |
367 | } |