Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 104
0.00% covered (danger)
0.00%
0 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
DeliveryDeleteService
0.00% covered (danger)
0.00%
0 / 104
0.00% covered (danger)
0.00%
0 / 15
1332
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 execute
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
30
 getDeliveryExecutions
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
20
 getReport
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 deleteDelivery
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
30
 getResultStorage
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getServiceProxy
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getQtiTestService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getItemService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTestService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDeliveryDeleteService
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 buildDeliveryExecutionDeleteRequest
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 deleteLinkedResources
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
20
 deleteDeliveryExecutions
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
20
 hasDeliveryExecutions
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
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) 2018 (original work) Open Assessment Technologies SA;
19 *
20 */
21
22namespace oat\taoDeliveryRdf\model\Delete;
23
24use common_report_Report;
25use common_ext_ExtensionsManager as ExtensionsManager;
26use core_kernel_classes_Resource;
27use core_kernel_classes_Resource as KernelResource;
28use oat\oatbox\service\ConfigurableService;
29use oat\taoDelivery\model\execution\DeliveryExecution;
30use oat\taoDelivery\model\execution\Monitoring;
31use oat\taoDelivery\model\execution\ServiceProxy;
32use oat\taoDelivery\model\execution\Delete\DeliveryExecutionDeleteRequest;
33use oat\taoDelivery\model\execution\Delete\DeliveryExecutionDeleteService;
34use oat\taoDeliveryRdf\model\DeliveryAssemblyService;
35use oat\taoQtiTest\models\TestSessionService;
36use oat\taoResultServer\models\classes\ResultManagement;
37use oat\taoResultServer\models\classes\ResultServerService;
38use taoItems_models_classes_ItemsService as ItemService;
39use taoQtiTest_models_classes_QtiTestService as QtiTestService;
40use taoTests_models_classes_TestsService as TestService;
41
42class DeliveryDeleteService extends ConfigurableService
43{
44    public const SERVICE_ID = 'taoDeliveryRdf/DeliveryDelete';
45
46    public const OPTION_DELETE_DELIVERY_DATA_SERVICES = 'deleteDeliveryDataServices';
47
48    public const OPTION_LIMIT_DELIVERY_EXECUTIONS = 'executionsLimit';
49
50    /** @var common_report_Report  */
51    protected $report;
52
53    /** @var DeliveryDeleteRequest */
54    private $request;
55
56    /**
57     * DeliveryDeleteService constructor.
58     * @param array $options
59     * @throws \Exception
60     */
61    public function __construct(array $options)
62    {
63        parent::__construct($options);
64
65        if (!$this->hasOption(static::OPTION_DELETE_DELIVERY_DATA_SERVICES)) {
66            throw new \common_exception_Error(
67                'Invalid Option provided: ' . static::OPTION_DELETE_DELIVERY_DATA_SERVICES
68            );
69        }
70    }
71
72    /**
73     * @param DeliveryDeleteRequest $request
74     * @param boolean $byChunk
75     * @return bool
76     * @throws \Exception
77     */
78    public function execute(DeliveryDeleteRequest $request, $byChunk = false)
79    {
80        $this->request = $request;
81
82        $delivery = $this->request->getDeliveryResource();
83
84        $this->report = common_report_Report::createInfo('Deleting Delivery: ' . $delivery->getUri());
85        $executions   = $this->getDeliveryExecutions($delivery);
86
87        $executionsLimit = $this->hasOption(self::OPTION_LIMIT_DELIVERY_EXECUTIONS)
88            ? $this->getOption(self::OPTION_LIMIT_DELIVERY_EXECUTIONS)
89            : count($executions);
90        if ($byChunk && $executions && count($executions) > $executionsLimit) {
91            $executionsForDeleting = array_slice($executions, 0, $executionsLimit);
92            $this->deleteDeliveryExecutions($executionsForDeleting);
93        } else {
94            $this->deleteDeliveryExecutions($executions);
95            $this->deleteLinkedResources();
96            return $this->deleteDelivery();
97        }
98        return true;
99    }
100
101    /**
102     * @param core_kernel_classes_Resource $deliveryResource
103     *
104     * @return array|DeliveryExecution[]
105     * @throws \common_exception_Error
106     * @throws \common_exception_NoImplementation
107     * @throws \oat\oatbox\service\exception\InvalidServiceManagerException
108     */
109    protected function getDeliveryExecutions(core_kernel_classes_Resource $deliveryResource)
110    {
111        $serviceProxy = $this->getServiceProxy();
112        /** @var ExtensionsManager $extensionsManager */
113        $extensionsManager = $this->getServiceManager()->get(ExtensionsManager::SERVICE_ID);
114        if ($serviceProxy instanceof Monitoring) {
115            $executions = $serviceProxy->getExecutionsByDelivery($deliveryResource);
116        } elseif ($extensionsManager->isEnabled('taoResultServer')) {
117            $resultStorage = $this->getResultStorage($deliveryResource->getUri());
118            $results       = $resultStorage->getResultByDelivery([$deliveryResource->getUri()]);
119
120            $executions = [];
121            foreach ($results as $result) {
122                $executions[] = $serviceProxy->getDeliveryExecution($result['deliveryResultIdentifier']);
123            }
124        } else {
125            throw new \common_exception_Error('Cannot retrieve delivery executions by delivery');
126        }
127
128        return $executions;
129    }
130
131    /**
132     * @return common_report_Report
133     */
134    public function getReport()
135    {
136        return $this->report;
137    }
138
139    /**
140     * @return bool
141     * @throws \Exception
142     */
143    protected function deleteDelivery()
144    {
145        if (!$this->request->isDeliveryRemovalRequested()) {
146            return true;
147        }
148
149        $services = $this->getDeliveryDeleteService();
150
151        foreach ($services as $service) {
152            try {
153                $deleted = $service->deleteDeliveryData($this->request);
154                if ($deleted) {
155                    $this->report->add(common_report_Report::createSuccess(
156                        'Delete delivery Service: ' . get_class($service) . ' data has been deleted.'
157                    ));
158                } else {
159                    $this->report->add(common_report_Report::createInfo(
160                        'Delete delivery Service: ' . get_class($service) . ' data has nothing to delete.'
161                    ));
162                }
163            } catch (\Exception $exception) {
164                $this->report->add(common_report_Report::createInfo(
165                    $exception->getMessage()
166                ));
167            }
168        }
169
170        return true;
171    }
172
173    /**
174     * @param $deliveryId
175     * @return ResultManagement
176     * @throws \common_exception_Error
177     */
178    protected function getResultStorage()
179    {
180        /** @var ResultServerService $resultService */
181        $resultService = $this->getServiceLocator()->get(ResultServerService::SERVICE_ID);
182        return $resultService->getResultStorage();
183    }
184
185    /**
186     * @return array|ServiceProxy|object
187     */
188    protected function getServiceProxy()
189    {
190        return $this->getServiceLocator()->get(ServiceProxy::SERVICE_ID);
191    }
192
193    protected function getQtiTestService(): QtiTestService
194    {
195        return $this->getServiceLocator()->get(QtiTestService::class);
196    }
197
198    protected function getItemService(): ItemService
199    {
200        return $this->getServiceLocator()->get(ItemService::class);
201    }
202
203    protected function getTestService(): TestService
204    {
205        return $this->getServiceLocator()->get(TestService::class);
206    }
207
208    /**
209     * @return DeliveryDelete[]
210     * @throws \common_exception_Error
211     */
212    private function getDeliveryDeleteService()
213    {
214        $services = [];
215        $servicesStrings = $this->getOption(static::OPTION_DELETE_DELIVERY_DATA_SERVICES);
216
217        foreach ($servicesStrings as $serviceString) {
218            $deleteService = $this->getServiceLocator()->get($serviceString);
219            if (!$deleteService instanceof DeliveryDelete) {
220                throw new \common_exception_Error('Invalid Delete Service provided: ' . $serviceString);
221            }
222
223            $services[] = $deleteService;
224        }
225
226        return $services;
227    }
228
229    /**
230     * @param $deliveryResource
231     * @param $execution
232     * @return DeliveryExecutionDeleteRequest
233     * @throws \Exception
234     */
235    private function buildDeliveryExecutionDeleteRequest($deliveryResource, $execution)
236    {
237        /** @var TestSessionService $testSessionService */
238        $testSessionService = $this->getServiceLocator()->get(TestSessionService::SERVICE_ID);
239        try {
240            $session = $testSessionService->getTestSession($execution, false);
241        } catch (\Exception $exception) {
242            $session = null;
243        }
244
245        return new DeliveryExecutionDeleteRequest(
246            $deliveryResource,
247            $execution,
248            $session
249        );
250    }
251
252    private function deleteLinkedResources(): void
253    {
254        if (!$this->request->isRecursive()) {
255            return;
256        }
257
258        $delivery = $this->request->getDeliveryResource();
259
260        if (!$delivery->exists()) {
261            return;
262        }
263
264        $test = $delivery->getUniquePropertyValue(
265            $delivery->getProperty(DeliveryAssemblyService::PROPERTY_ORIGIN)
266        );
267
268        $itemService = $this->getItemService();
269
270        foreach ($this->getQtiTestService()->getItems($test) as $item) {
271            $itemService->deleteResource($item);
272        }
273
274        $this->getTestService()->deleteResource($test);
275    }
276
277    /**
278     * @param DeliveryExecution[] $executions
279     * @throws \common_exception_Error
280     */
281    private function deleteDeliveryExecutions(array $executions): void
282    {
283        if (!$this->request->isExecutionsRemovalRequested()) {
284            return;
285        }
286
287        $delivery = $this->request->getDeliveryResource();
288
289        /** @var DeliveryExecutionDeleteService $deliveryExecutionDeleteService */
290        $deliveryExecutionDeleteService = $this->getServiceLocator()->get(DeliveryExecutionDeleteService::SERVICE_ID);
291
292        foreach ($executions as $execution) {
293            try {
294                $requestDeleteExecution = $this->buildDeliveryExecutionDeleteRequest(
295                    $delivery,
296                    $execution
297                );
298
299                $deliveryExecutionDeleteService->execute($requestDeleteExecution);
300                $this->report->add($deliveryExecutionDeleteService->getReport());
301            } catch (\Exception $exception) {
302                $this->report->add(
303                    common_report_Report::createFailure(
304                        'Failing deleting execution: ' . $execution->getIdentifier()
305                    )
306                );
307                $this->report->add(common_report_Report::createFailure($exception->getMessage()));
308            }
309        }
310    }
311
312    /**
313     * @param core_kernel_classes_Resource $delivery
314     * @return bool
315     * @throws \common_exception_Error
316     */
317    public function hasDeliveryExecutions(KernelResource $delivery)
318    {
319        $executions = $this->getDeliveryExecutions($delivery);
320        return !empty($executions);
321    }
322}