Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 155 |
|
0.00% |
0 / 17 |
CRAP | |
0.00% |
0 / 1 |
taoItems_actions_Items | |
0.00% |
0 / 155 |
|
0.00% |
0 / 17 |
2070 | |
0.00% |
0 / 1 |
getEventManager | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
defaultData | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
12 | |||
getClassService | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
cloneInstance | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
moveInstance | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
moveAll | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getOntologyData | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
editItem | |
0.00% |
0 / 67 |
|
0.00% |
0 / 1 |
156 | |||
editItemClass | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
42 | |||
deleteItem | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
deleteClass | |
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 | |||
translateInstance | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
authoring | |
0.00% |
0 / 38 |
|
0.00% |
0 / 1 |
110 | |||
getDependsOnPropertyValidator | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getResourceWatcher | |
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) 2002-2008 (original work) Public Research Centre Henri Tudor & University of Luxembourg |
19 | * (under the project TAO & TAO2); |
20 | * 2008-2010 (update and modification) Deutsche Institut für Internationale Pädagogische Forschung |
21 | * (under the project TAO-TRANSFER); |
22 | * 2009-2012 (update and modification) Public Research Centre Henri Tudor |
23 | * (under the project TAO-SUSTAIN & TAO-DEV); |
24 | * 2012-2018 (update and modification) Open Assessment Technologies SA (under the project TAO-PRODUCT); |
25 | */ |
26 | |
27 | declare(strict_types=1); |
28 | |
29 | use oat\oatbox\event\EventManager; |
30 | use oat\generis\model\OntologyRdfs; |
31 | use oat\tao\model\lock\LockManager; |
32 | use oat\tao\model\TaoOntology; |
33 | use oat\taoItems\model\Form\Modifier\FormModifierProxy; |
34 | use oat\taoItems\model\ItemModelStatus; |
35 | use oat\tao\model\accessControl\Context; |
36 | use oat\generis\model\OntologyAwareTrait; |
37 | use oat\tao\model\resources\ResourceWatcher; |
38 | use oat\oatbox\validator\ValidatorInterface; |
39 | use oat\taoItems\model\event\ItemUpdatedEvent; |
40 | use oat\tao\model\controller\SignedFormInstance; |
41 | use oat\taoItems\model\event\ItemRdfUpdatedEvent; |
42 | use oat\taoItems\model\Translation\Form\Modifier\TranslationFormModifierProxy; |
43 | use tao_helpers_form_FormContainer as FormContainer; |
44 | use oat\tao\model\Lists\Business\Validation\DependsOnPropertyValidator; |
45 | |
46 | /** |
47 | * Items Controller provide actions performed from url resolution |
48 | * |
49 | * @author Bertrand Chevrier, <taosupport@tudor.lu> |
50 | * @package taoItems |
51 | * @license GPLv2 http://www.opensource.org/licenses/gpl-2.0.php |
52 | */ |
53 | // phpcs:ignore |
54 | class taoItems_actions_Items extends tao_actions_SaSModule |
55 | { |
56 | use OntologyAwareTrait; |
57 | |
58 | /** |
59 | * @return EventManager |
60 | */ |
61 | protected function getEventManager() |
62 | { |
63 | return $this->getServiceLocator()->get(EventManager::SERVICE_ID); |
64 | } |
65 | |
66 | /** |
67 | * overwrite the parent defaultData, adding the item label to be sent to the view |
68 | */ |
69 | protected function defaultData() |
70 | { |
71 | parent::defaultData(); |
72 | if ($this->hasRequestParameter('uri')) { |
73 | $uri = $this->getRequestParameter('uri'); |
74 | $classUri = $this->getRequestParameter('classUri'); |
75 | if (!empty($uri)) { |
76 | $item = $this->getResource(tao_helpers_Uri::decode($uri)); |
77 | $this->setData('label', $item->getLabel()); |
78 | |
79 | $this->setData( |
80 | 'authoringUrl', |
81 | _url( |
82 | 'authoring', |
83 | 'Items', |
84 | 'taoItems', |
85 | ['uri' => $uri, 'classUri' => $classUri] |
86 | ) |
87 | ); |
88 | |
89 | $this->setData('previewUrl', $this->getClassService()->getPreviewUrl($item)); |
90 | } |
91 | } |
92 | } |
93 | |
94 | /** |
95 | * (non-PHPdoc) |
96 | * @see tao_actions_RdfController::getClassService() |
97 | * @return taoItems_models_classes_ItemsService |
98 | */ |
99 | protected function getClassService() |
100 | { |
101 | if (is_null($this->service)) { |
102 | $this->service = taoItems_models_classes_ItemsService::singleton(); |
103 | } |
104 | return $this->service; |
105 | } |
106 | |
107 | /** |
108 | * overwrite the parent cloneInstance to add the requiresRight only in Items |
109 | * @see tao_actions_TaoModule::cloneInstance() |
110 | * @requiresRight uri READ |
111 | * @requiresRight classUri WRITE |
112 | */ |
113 | public function cloneInstance() |
114 | { |
115 | return parent::cloneInstance(); |
116 | } |
117 | |
118 | /** |
119 | * overwrite the parent moveInstance to add the requiresRight only in Items |
120 | * @see tao_actions_TaoModule::moveInstance() |
121 | * @requiresRight uri WRITE |
122 | * @requiresRight destinationClassUri WRITE |
123 | */ |
124 | public function moveInstance() |
125 | { |
126 | return parent::moveInstance(); |
127 | } |
128 | |
129 | /** |
130 | * overwrite the parent moveAllInstances to add the requiresRight only in Items |
131 | * @see tao_actions_TaoModule::moveAll() |
132 | * @requiresRight ids WRITE |
133 | */ |
134 | public function moveAll() |
135 | { |
136 | return parent::moveAll(); |
137 | } |
138 | |
139 | /** |
140 | * overwrite the parent getOntologyData to add the requiresRight only in Items |
141 | * @see tao_actions_TaoModule::getOntologyData() |
142 | * @requiresRight classUri READ |
143 | */ |
144 | public function getOntologyData() |
145 | { |
146 | return parent::getOntologyData(); |
147 | } |
148 | |
149 | /** |
150 | * Edit an item instance |
151 | * |
152 | * @requiresRight id READ |
153 | */ |
154 | public function editItem(): void |
155 | { |
156 | $this->defaultData(); |
157 | |
158 | $itemClass = $this->getCurrentClass(); |
159 | $item = $this->getCurrentInstance(); |
160 | |
161 | if (!$this->isLocked($item, 'item_locked.tpl')) { |
162 | $lock = LockManager::getImplementation()->getLockData($item); |
163 | |
164 | if ($lock !== null && $lock->getOwnerId() == $this->getSession()->getUser()->getIdentifier()) { |
165 | $this->setData('lockDate', $lock->getCreationTime()); |
166 | $this->setData('id', $item->getUri()); |
167 | } |
168 | |
169 | $itemUri = $item->getUri(); |
170 | $context = new Context( |
171 | [ |
172 | Context::PARAM_CONTROLLER => self::class, |
173 | Context::PARAM_ACTION => __FUNCTION__, |
174 | ] |
175 | ); |
176 | |
177 | $hasWriteAccess = $this->hasWriteAccess($itemUri) && $this->hasWriteAccessByContext($context); |
178 | |
179 | $formContainer = new SignedFormInstance( |
180 | $itemClass, |
181 | $item, |
182 | [ |
183 | FormContainer::CSRF_PROTECTION_OPTION => true, |
184 | FormContainer::IS_DISABLED => !$hasWriteAccess, |
185 | FormContainer::ATTRIBUTE_VALIDATORS => [ |
186 | 'data-depends-on-property' => [ |
187 | $this->getDependsOnPropertyValidator(), |
188 | ], |
189 | ], |
190 | FormContainer::FORM_MODIFIERS => [ |
191 | FormModifierProxy::class, |
192 | TranslationFormModifierProxy::class, |
193 | ], |
194 | ] |
195 | ); |
196 | $myForm = $formContainer->getForm(); |
197 | |
198 | $myForm->setOptions([ |
199 | 'resourceType' => TaoOntology::ITEM_CLASS_URI |
200 | ]); |
201 | |
202 | if ($hasWriteAccess) { |
203 | if ($myForm->isSubmited() && $myForm->isValid()) { |
204 | $this->validateInstanceRoot($itemUri); |
205 | |
206 | $properties = $myForm->getValues(); |
207 | |
208 | if (array_key_exists('warning', $properties)) { |
209 | $this->logWarning('Warning property is still in use', ['backend']); |
210 | unset($properties['warning']); |
211 | } |
212 | |
213 | // Bind item properties and set default content: |
214 | $binder = new tao_models_classes_dataBinding_GenerisFormDataBinder($item); |
215 | $item = $binder->bind($properties); |
216 | |
217 | $this->getEventManager()->trigger(new ItemUpdatedEvent($item->getUri(), $properties)); |
218 | $this->getEventManager()->trigger(new ItemRdfUpdatedEvent($item->getUri(), $properties)); |
219 | |
220 | // If item label has been changed, do not use getLabel() to prevent cached value from lazy loading |
221 | $label = $item->getOnePropertyValue(new core_kernel_classes_Property(OntologyRdfs::RDFS_LABEL)); |
222 | $this->setData('selectNode', tao_helpers_Uri::encode($item->getUri())); |
223 | $this->setData('label', ($label !== null) ? $label->literal : ''); |
224 | $this->setData('message', __('Item saved')); |
225 | $this->setData('reload', true); |
226 | } |
227 | } else { |
228 | $myForm->setActions([]); |
229 | } |
230 | |
231 | $currentModel = $this->getClassService()->getItemModel($item); |
232 | $hasPreview = false; |
233 | $hasModel = false; |
234 | |
235 | if (!empty($currentModel)) { |
236 | $hasModel = true; |
237 | $isDeprecated = $this->getClassService()->hasModelStatus($item, [ItemModelStatus::INSTANCE_DEPRECATED]); |
238 | $hasPreview = !$isDeprecated && $this->getClassService()->hasItemContent($item); |
239 | } |
240 | |
241 | $this->setData('isPreviewEnabled', $hasPreview); |
242 | $this->setData('updatedAt', $this->getResourceWatcher()->getUpdatedAt($item)); |
243 | $this->setData('isAuthoringEnabled', $hasModel); |
244 | |
245 | $this->setData('formTitle', __('Edit Item')); |
246 | $this->setData('myForm', $myForm->render()); |
247 | |
248 | $this->setView('Items/editItem.tpl'); |
249 | } |
250 | } |
251 | |
252 | /** |
253 | * Edit a class |
254 | * @requiresRight id READ |
255 | */ |
256 | public function editItemClass() |
257 | { |
258 | $this->defaultData(); |
259 | |
260 | $clazz = $this->getClass($this->getRequestParameter('id')); |
261 | |
262 | if ($this->hasRequestParameter('property_mode')) { |
263 | $this->setSessionAttribute('property_mode', $this->getRequestParameter('property_mode')); |
264 | } |
265 | |
266 | $myForm = $this->getClassForm($clazz, $this->getClassService()->getRootClass()); |
267 | |
268 | if ($this->hasWriteAccess($clazz->getUri())) { |
269 | if ($myForm->isSubmited()) { |
270 | if ($myForm->isValid()) { |
271 | if ($clazz instanceof core_kernel_classes_Resource) { |
272 | $this->setData("selectNode", tao_helpers_Uri::encode($clazz->getUri())); |
273 | } |
274 | $this->setData('message', __('Class schema saved')); |
275 | $this->setData('reload', false); |
276 | } |
277 | } |
278 | } else { |
279 | $myForm->setActions([]); |
280 | } |
281 | $this->setData('formTitle', __('Manage item class schema')); |
282 | $this->setData('myForm', $myForm->render()); |
283 | $this->setView('form.tpl', 'tao'); |
284 | } |
285 | |
286 | /** |
287 | * delete an item |
288 | * called via ajax |
289 | * @requiresRight id WRITE |
290 | * @return void |
291 | * @throws Exception |
292 | */ |
293 | public function deleteItem() |
294 | { |
295 | return parent::deleteResource(); |
296 | } |
297 | |
298 | /** |
299 | * delete a class |
300 | * @requiresRight id WRITE |
301 | * @throws Exception |
302 | */ |
303 | public function deleteClass() |
304 | { |
305 | return parent::deleteClass(); |
306 | } |
307 | |
308 | /** |
309 | * Delete all given resources |
310 | * |
311 | * @requiresRight ids WRITE |
312 | * |
313 | * @throws Exception |
314 | */ |
315 | public function deleteAll() |
316 | { |
317 | return parent::deleteAll(); |
318 | } |
319 | |
320 | /** |
321 | * Move class to another location |
322 | * @requiresRight classUri WRITE |
323 | */ |
324 | public function moveClass() |
325 | { |
326 | return parent::moveResource(); |
327 | } |
328 | |
329 | /** |
330 | * @see TaoModule::translateInstance |
331 | * @requiresRight uri WRITE |
332 | * @return void |
333 | */ |
334 | public function translateInstance() |
335 | { |
336 | $this->defaultData(); |
337 | parent::translateInstance(); |
338 | $this->setView('form.tpl', 'tao'); |
339 | } |
340 | |
341 | /** |
342 | * Item Authoring tool loader action |
343 | * @requiresRight id WRITE |
344 | */ |
345 | public function authoring() |
346 | { |
347 | $this->defaultData(); |
348 | |
349 | $item = $this->getResource($this->getRequestParameter('id')); |
350 | |
351 | if (!$this->isLocked($item, 'item_locked.tpl')) { |
352 | $this->setData('error', false); |
353 | try { |
354 | $itemModel = $this->getClassService()->getItemModel($item); |
355 | if ($itemModel !== null) { |
356 | $itemModelImpl = $this->getClassService()->getItemModelImplementation($itemModel); |
357 | $authoringUrl = $itemModelImpl->getAuthoringUrl($item); |
358 | if (!empty($authoringUrl)) { |
359 | LockManager::getImplementation() |
360 | ->setLock($item, $this->getSession()->getUser()->getIdentifier()); |
361 | |
362 | // Add support for the translation and the side-by-side authoring tool |
363 | if ($this->getRequestParameter('translation') !== null) { |
364 | $authoringUrl = sprintf( |
365 | '%s&translation=%s', |
366 | $authoringUrl, |
367 | $this->getRequestParameter('translation') |
368 | ); |
369 | } |
370 | if ($this->getRequestParameter('originResourceUri') !== null) { |
371 | $authoringUrl = sprintf( |
372 | '%s&originResourceUri=%s', |
373 | $authoringUrl, |
374 | $this->getRequestParameter('originResourceUri') |
375 | ); |
376 | } |
377 | |
378 | return $this->forwardUrl($authoringUrl); |
379 | } |
380 | } |
381 | throw new common_exception_NoImplementation(); |
382 | } catch (Exception $e) { |
383 | if ($e instanceof InterruptedActionException) { |
384 | throw $e; |
385 | } |
386 | $this->setData('error', true); |
387 | //build clear error or warning message: |
388 | if (!empty($itemModel) && $itemModel instanceof core_kernel_classes_Resource) { |
389 | $errorMsg = __( |
390 | 'No item authoring tool available for the selected type of item: %s' |
391 | . $itemModel->getLabel() |
392 | ); |
393 | } else { |
394 | $errorMsg = __('No item type selected for the current item.') |
395 | . " {$item->getLabel()} " |
396 | . __('Please select first the item type!'); |
397 | } |
398 | $this->setData('errorMsg', $errorMsg); |
399 | } |
400 | } |
401 | } |
402 | |
403 | private function getDependsOnPropertyValidator(): ValidatorInterface |
404 | { |
405 | return $this->getPsrContainer()->get(DependsOnPropertyValidator::class); |
406 | } |
407 | |
408 | private function getResourceWatcher(): ResourceWatcher |
409 | { |
410 | return $this->getPsrContainer()->get(ResourceWatcher::SERVICE_ID); |
411 | } |
412 | } |