Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 122
0.00% covered (danger)
0.00%
0 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
taoTests_actions_Tests
0.00% covered (danger)
0.00%
0 / 122
0.00% covered (danger)
0.00%
0 / 15
992
0.00% covered (danger)
0.00%
0 / 1
 getEventManager
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getClassService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 editTest
0.00% covered (danger)
0.00%
0 / 55
0.00% covered (danger)
0.00%
0 / 1
72
 delete
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
42
 authoring
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
30
 moveInstance
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 moveAll
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 cloneInstance
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 deleteAll
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 moveClass
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDependsOnPropertyValidator
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getClassDeleter
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getResourceDeleter
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTranslationSyncService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
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
26use oat\oatbox\event\EventManager;
27use oat\tao\model\lock\LockManager;
28use oat\oatbox\validator\ValidatorInterface;
29use oat\tao\model\resources\ResourceWatcher;
30use oat\tao\model\TaoOntology;
31use oat\taoTests\models\event\TestUpdatedEvent;
32use oat\tao\model\controller\SignedFormInstance;
33use oat\tao\model\resources\Service\ClassDeleter;
34use oat\tao\model\routing\AnnotationReader\security;
35use oat\taoTests\models\Form\Modifier\FormModifierProxy;
36use oat\taoTests\models\Translation\Form\Modifier\TranslationFormModifierProxy;
37use tao_helpers_form_FormContainer as FormContainer;
38use oat\generis\model\resource\Service\ResourceDeleter;
39use oat\tao\model\resources\Contract\ClassDeleterInterface;
40use oat\generis\model\resource\Contract\ResourceDeleterInterface;
41use oat\generis\model\resource\exception\ResourceDeletionException;
42use oat\tao\model\resources\Exception\PartialClassDeletionException;
43use oat\tao\model\Lists\Business\Validation\DependsOnPropertyValidator;
44use oat\tao\model\Translation\Service\TranslationSyncService;
45
46/**
47 * Tests Controller provide actions performed from url resolution
48 *
49 * @author Bertrand Chevrier, <taosupport@tudor.lu>
50 * @package taoTests
51
52 * @license GPLv2  http://www.opensource.org/licenses/gpl-2.0.php
53 *
54 */
55// phpcs:ignore
56class taoTests_actions_Tests extends tao_actions_SaSModule
57{
58    /**
59     * @return EventManager
60     */
61    protected function getEventManager()
62    {
63        return $this->getServiceLocator()->get(EventManager::SERVICE_ID);
64    }
65
66    protected function getClassService()
67    {
68        return taoTests_models_classes_TestsService::singleton();
69    }
70
71    /**
72     * constructor: initialize the service and the default data
73     * @security("hide")
74     */
75    public function __construct()
76    {
77        parent::__construct();
78
79        //the service is initialized by default
80        $this->service = taoTests_models_classes_TestsService::singleton();
81        $this->defaultData();
82    }
83
84    /*
85    * controller actions
86    */
87
88
89    /**
90     * edit a test instance
91     * @requiresRight id READ
92     */
93    public function editTest()
94    {
95        $test = new core_kernel_classes_Resource($this->getRequestParameter('id'));
96
97        $this->setData('isPreviewEnabled', $this->service->hasItems($test));
98
99        if (!$this->isLocked($test)) {
100            // my lock
101            $lock = LockManager::getImplementation()->getLockData($test);
102            $sessionIdentifier = common_session_SessionManager::getSession()->getUser()->getIdentifier();
103
104            if (!is_null($lock) && $lock->getOwnerId() === $sessionIdentifier) {
105                $this->setData('lockDate', $lock->getCreationTime());
106                $this->setData('id', $lock->getResource()->getUri());
107            }
108
109            $clazz = $this->getCurrentClass();
110            $formContainer = new SignedFormInstance(
111                $clazz,
112                $test,
113                [
114                    FormContainer::CSRF_PROTECTION_OPTION => true,
115                    FormContainer::ATTRIBUTE_VALIDATORS => [
116                        'data-depends-on-property' => [
117                            $this->getDependsOnPropertyValidator(),
118                        ],
119                    ],
120                    FormContainer::FORM_MODIFIERS => [
121                        FormModifierProxy::class,
122                        TranslationFormModifierProxy::class,
123                    ],
124                ]
125            );
126            $myForm = $formContainer->getForm();
127
128            $myForm->setOptions([
129                'resourceType' => TaoOntology::CLASS_URI_TEST
130            ]);
131
132            if ($myForm->isSubmited() && $myForm->isValid()) {
133                $this->validateInstanceRoot($test->getUri());
134
135                $propertyValues = $myForm->getValues();
136
137                // don't hande the testmodel via bindProperties
138                if (array_key_exists(taoTests_models_classes_TestsService::PROPERTY_TEST_TESTMODEL, $propertyValues)) {
139                    $modelUri = $propertyValues[taoTests_models_classes_TestsService::PROPERTY_TEST_TESTMODEL];
140                    unset($propertyValues[taoTests_models_classes_TestsService::PROPERTY_TEST_TESTMODEL]);
141                    if (!empty($modelUri)) {
142                        $testModel = new core_kernel_classes_Resource($modelUri);
143                        $this->service->setTestModel($test, $testModel);
144                    }
145                } else {
146                    common_Logger::w('No testmodel on test form', 'taoTests');
147                }
148
149                //then save the property values as usual
150                $binder = new tao_models_classes_dataBinding_GenerisFormDataBinder($test);
151                $test = $binder->bind($propertyValues);
152                $this->getEventManager()->trigger(new TestUpdatedEvent($test->getUri(), $propertyValues));
153
154                $this->setData('selectNode', tao_helpers_Uri::encode($test->getUri()));
155                $this->setData('message', __('Test saved'));
156                $this->setData('reload', true);
157            }
158
159            $myForm->removeElement(tao_helpers_Uri::encode(
160                taoTests_models_classes_TestsService::PROPERTY_TEST_CONTENT
161            ));
162            $updatedAt = $this->getServiceLocator()->get(ResourceWatcher::SERVICE_ID)->getUpdatedAt($test);
163            $this->setData('updatedAt', $updatedAt);
164            $this->setData('uri', tao_helpers_Uri::encode($test->getUri()));
165            $this->setData('classUri', tao_helpers_Uri::encode($clazz->getUri()));
166            $this->setData('formTitle', __('Test properties'));
167            $this->setData('myForm', $myForm->render());
168            $this->setView('Tests/editTest.tpl');
169        }
170    }
171
172    /**
173     * delete a test or a test class. called via ajax
174     *
175     * @throws Exception
176     * @throws common_exception_BadRequest
177     * @requiresRight id WRITE
178     */
179    public function delete()
180    {
181        try {
182            $this->validateCsrf();
183        } catch (common_exception_Unauthorized $e) {
184            $this->response = $this->getPsrResponse()->withStatus(403, __('Unable to process your request'));
185            return;
186        }
187        if (!tao_helpers_Request::isAjax()) {
188            throw new common_exception_BadRequest('wrong request mode');
189        }
190
191        $uri = $this->getRequestParameter('id');
192
193        $this->validateInstanceRoot($uri);
194
195        $instance = $this->getCurrentInstance('id');
196
197        $lockManager = LockManager::getImplementation();
198        $userId = common_session_SessionManager::getSession()->getUser()->getIdentifier();
199
200        if ($lockManager->isLocked($instance)) {
201            $lockManager->releaseLock($instance, $userId);
202        }
203
204        $label = $instance->getLabel();
205        /**
206         * @var ResourceDeleterInterface|ClassDeleterInterface $deleter
207         * @var core_kernel_classes_Resource|core_kernel_classes_Class $instanceToDelete
208         */
209        [$deleter, $instanceToDelete] = $instance->isClass()
210            ? [$this->getClassDeleter(), $this->getClass($instance)]
211            : [$this->getResourceDeleter(), $instance];
212
213        try {
214            $deleter->delete($instanceToDelete);
215            $success = true;
216            $deleted = true;
217            $message = __('%s has been deleted', $label);
218        } catch (PartialClassDeletionException | ResourceDeletionException $exception) {
219            $success = $exception instanceof PartialClassDeletionException;
220            $deleted = false;
221            $message = $exception->getUserMessage();
222        }
223
224        $this->returnJson([
225            'success' => $success,
226            'message' => $message,
227            'deleted' => $deleted,
228        ]);
229    }
230
231    /**
232     * Redirect the test's authoring
233     * @requiresRight id WRITE
234     */
235    public function authoring()
236    {
237        $test = new core_kernel_classes_Resource($this->getRequestParameter('id'));
238        if (!$this->isLocked($test)) {
239            $testModel = $this->service->getTestModel($test);
240            $testModelImpl = $this->service->getTestModelImplementation($testModel);
241            $authoringUrl = $testModelImpl->getAuthoringUrl($test);
242            if (!empty($authoringUrl)) {
243                $userId = common_session_SessionManager::getSession()->getUser()->getIdentifier();
244                LockManager::getImplementation()->setLock($test, $userId);
245
246                // Add support for the translation and the side-by-side authoring tool
247                if ($this->getRequestParameter('translation') !== null) {
248                    $authoringUrl = sprintf(
249                        '%s&translation=%s',
250                        $authoringUrl,
251                        $this->getRequestParameter('translation')
252                    );
253                }
254                if ($this->getRequestParameter('originResourceUri') !== null) {
255                    $this->getTranslationSyncService()->syncById($this->getRequestParameter('originResourceUri'));
256                    $authoringUrl = sprintf(
257                        '%s&originResourceUri=%s',
258                        $authoringUrl,
259                        $this->getRequestParameter('originResourceUri')
260                    );
261                }
262
263                return $this->forwardUrl($authoringUrl);
264            }
265            throw new common_exception_NoImplementation();
266        }
267    }
268
269    /**
270     * overwrite the parent moveInstance to add the requiresRight only in Tests
271     * @see tao_actions_TaoModule::moveInstance()
272     * @requiresRight uri WRITE
273     * @requiresRight destinationClassUri WRITE
274     */
275    public function moveInstance()
276    {
277        parent::moveInstance();
278    }
279
280    /**
281     * overwrite the parent moveAllInstances to add the requiresRight only in Items
282     * @see tao_actions_TaoModule::moveAll()
283     * @requiresRight ids WRITE
284     */
285    public function moveAll()
286    {
287        return parent::moveAll();
288    }
289
290    /**
291     * overwrite the parent cloneInstance to add the requiresRight only in Tests
292     * @see tao_actions_TaoModule::cloneInstance()
293     * @requiresRight uri READ
294     * @requiresRight classUri WRITE
295     */
296    public function cloneInstance()
297    {
298        return parent::cloneInstance();
299    }
300
301    /**
302     * Delete all given resources
303     *
304     * @requiresRight ids WRITE
305     *
306     * @throws Exception
307     */
308    public function deleteAll()
309    {
310        return parent::deleteAll();
311    }
312
313    /**
314     * Move class to another location
315     * @requiresRight classUri WRITE
316     */
317    public function moveClass()
318    {
319        return parent::moveResource();
320    }
321
322    private function getDependsOnPropertyValidator(): ValidatorInterface
323    {
324        return $this->getPsrContainer()->get(DependsOnPropertyValidator::class);
325    }
326
327    private function getClassDeleter(): ClassDeleterInterface
328    {
329        return $this->getPsrContainer()->get(ClassDeleter::class);
330    }
331
332    private function getResourceDeleter(): ResourceDeleterInterface
333    {
334        return $this->getPsrContainer()->get(ResourceDeleter::class);
335    }
336
337    private function getTranslationSyncService(): TranslationSyncService
338    {
339        return $this->getPsrContainer()->get(TranslationSyncService::class);
340    }
341}