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 | } |