Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 63
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
PatchService
0.00% covered (danger)
0.00%
0 / 63
0.00% covered (danger)
0.00%
0 / 10
210
0.00% covered (danger)
0.00%
0 / 1
 patch
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 1
6
 getMediaService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 validateResource
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 validateXml
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getMediaParser
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFileSourceUnserializer
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFileSystem
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getFileSystemService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFlySystemManagement
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 findLanguageResource
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
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) 2020-2021 (original work) Open Assessment Technologies SA;
19 */
20
21declare(strict_types=1);
22
23namespace oat\taoMediaManager\model\sharedStimulus\service;
24
25use core_kernel_classes_Literal;
26use core_kernel_classes_Resource as Resource;
27use core_kernel_persistence_Exception;
28use InvalidArgumentException;
29use LogicException;
30use oat\generis\model\fileReference\FileReferenceSerializer;
31use oat\generis\model\OntologyAwareTrait;
32use oat\oatbox\filesystem\File;
33use oat\oatbox\filesystem\FileSystem;
34use oat\oatbox\filesystem\FilesystemInterface;
35use oat\oatbox\filesystem\FileSystemService;
36use oat\oatbox\service\ConfigurableService;
37use oat\tao\model\media\TaoMediaException;
38use oat\tao\model\media\TaoMediaResolver;
39use oat\taoMediaManager\model\fileManagement\FileSourceUnserializer;
40use oat\taoMediaManager\model\fileManagement\FlySystemManagement;
41use oat\taoMediaManager\model\MediaService;
42use oat\taoMediaManager\model\sharedStimulus\parser\SharedStimulusMediaExtractor;
43use oat\taoMediaManager\model\sharedStimulus\PatchCommand;
44use oat\taoMediaManager\model\sharedStimulus\SharedStimulus;
45use oat\taoMediaManager\model\SharedStimulusImporter;
46use oat\taoMediaManager\model\TaoMediaOntology;
47use qtism\data\storage\xml\XmlStorageException;
48use tao_helpers_I18n;
49use tao_models_classes_FileNotFoundException as FileNotFoundException;
50
51class PatchService extends ConfigurableService
52{
53    use OntologyAwareTrait;
54
55    /**
56     * @var TaoMediaResolver
57     */
58    private $mediaResolver;
59
60    /**
61     * @throws core_kernel_persistence_Exception
62     */
63    public function patch(PatchCommand $command): SharedStimulus
64    {
65        /** @var File $file */
66        $file = $this->getServiceLocator()->get(FileReferenceSerializer::SERVICE_ID)->unserialize(
67            $command->getFileReference()
68        );
69
70        $id = $command->getId();
71        $userId = $command->getUserId();
72
73        $resource = $this->getResource($id);
74
75        $this->validateResource($resource);
76        $this->validateXml($file);
77
78        /* @var core_kernel_classes_Literal */
79        $link = $resource->getUniquePropertyValue(
80            $this->getProperty(
81                TaoMediaOntology::PROPERTY_LINK
82            )
83        );
84        $sharedStimulusStoredSourceFile = $this->getFileSourceUnserializer()->unserialize((string)$link);
85
86        $this->getFileSystem()->writeStream($sharedStimulusStoredSourceFile, $file->readStream());
87
88        $content = $file->read();
89        $resource->editPropertyValues(
90            $this->getProperty(TaoMediaOntology::PROPERTY_MD5),
91            md5($content)
92        );
93
94        $this->getMediaService()->dispatchMediaSavedEvent(
95            'Imported new file',
96            $resource,
97            $sharedStimulusStoredSourceFile,
98            $file->getMimeType(),
99            $userId,
100            $content
101        );
102
103        $file->delete();
104
105        $languageResource = $resource->getOnePropertyValue(
106            $this->getProperty(TaoMediaOntology::PROPERTY_LANGUAGE)
107        );
108
109        if ($languageResource instanceof core_kernel_classes_Literal) {
110            $languageResource = $this->findLanguageResource($languageResource);
111        }
112
113        return new SharedStimulus(
114            $id,
115            $resource->getLabel(),
116            $languageResource->getUri()
117        );
118    }
119
120    private function getMediaService(): MediaService
121    {
122        return MediaService::singleton();
123    }
124
125    /**
126     * @param Resource $resource
127     */
128    private function validateResource(Resource $resource): void
129    {
130        if (!$resource->isInstanceOf($this->getClass(TaoMediaOntology::CLASS_URI_MEDIA_ROOT))) {
131            $this->logAlert(
132                sprintf(
133                    'Incorrect resource provided, %s should be subtype of  %s',
134                    $resource->getUri(),
135                    TaoMediaOntology::CLASS_URI_MEDIA_ROOT
136                )
137            );
138            throw new InvalidArgumentException('Invalid resource provided');
139        }
140    }
141
142    /**
143     * @throws TaoMediaException|FileNotFoundException
144     */
145    private function validateXml(File $file): void
146    {
147        try {
148            SharedStimulusImporter::isValidSharedStimulus($file);
149        } catch (XmlStorageException $e) {
150            $this->logAlert(sprintf('Incorrect shared stimulus xml, %s', $e->getMessage()));
151            throw new InvalidArgumentException('Invalid XML provided');
152        }
153    }
154
155    public function getMediaParser(): SharedStimulusMediaExtractor
156    {
157        return $this->getServiceLocator()->get(SharedStimulusMediaExtractor::class);
158    }
159
160    private function getFileSourceUnserializer(): FileSourceUnserializer
161    {
162        return $this->getServiceLocator()->get(FileSourceUnserializer::class);
163    }
164
165    private function getFileSystem(): FilesystemInterface
166    {
167        return $this->getFileSystemService()
168            ->getFileSystem($this->getFlySystemManagement()->getOption(FlySystemManagement::OPTION_FS));
169    }
170
171    private function getFileSystemService(): FileSystemService
172    {
173        return $this->getServiceLocator()->get(FileSystemService::SERVICE_ID);
174    }
175
176    private function getFlySystemManagement(): FlySystemManagement
177    {
178        return $this->getServiceLocator()->get(FlySystemManagement::SERVICE_ID);
179    }
180
181    private function findLanguageResource(core_kernel_classes_Literal $resourceLanguage): Resource
182    {
183        $resourceLanguage = tao_helpers_I18n::getLangResourceByCode((string)$resourceLanguage);
184        if (!$resourceLanguage instanceof Resource) {
185            throw new LogicException(sprintf("Fail to find the resource of %s", (string)$resourceLanguage));
186        }
187        return $resourceLanguage;
188    }
189}