Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 64
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
TriplesManagerService
0.00% covered (danger)
0.00%
0 / 64
0.00% covered (danger)
0.00%
0 / 9
756
0.00% covered (danger)
0.00%
0 / 1
 getFileRefSerializer
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 deleteTripleDependencies
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
20
 deleteTriplesFor
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 cloneTriples
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 cloneFile
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
30
 getPropertyStorageMap
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 isFileReference
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
42
 serializeAsset
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFileSourceSerializer
0.00% covered (danger)
0.00%
0 / 1
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) 2020 (original work) Open Assessment Technologies SA;
19 */
20
21namespace oat\taoRevision\model;
22
23use common_Exception;
24use common_Logger;
25use oat\generis\model\fileReference\FileReferenceSerializer;
26use oat\generis\model\GenerisRdf;
27use oat\generis\model\OntologyAwareTrait;
28use oat\generis\model\OntologyRdfs;
29use oat\oatbox\filesystem\Directory;
30use oat\oatbox\filesystem\File;
31use oat\oatbox\filesystem\FileSystemService;
32use oat\oatbox\service\ConfigurableService;
33use core_kernel_classes_ContainerCollection as TriplesCollection;
34use core_kernel_classes_Resource as Resource;
35use core_kernel_classes_Triple as Triple;
36use core_kernel_persistence_smoothsql_SmoothModel as Model;
37use oat\taoMediaManager\model\fileManagement\FileSourceSerializer;
38use oat\taoMediaManager\model\MediaService;
39
40/**
41 * Class TriplesManagerService
42 * @package oat\taoRevision\model
43 */
44class TriplesManagerService extends ConfigurableService
45{
46    use OntologyAwareTrait;
47
48    public const SERVICE_ID = 'taoRevision/triples';
49
50    /**
51     * @return FileReferenceSerializer
52     */
53    protected function getFileRefSerializer()
54    {
55        return $this->getServiceLocator()->get(FileReferenceSerializer::SERVICE_ID);
56    }
57
58    /**
59     * @param Triple $triple
60     */
61    public function deleteTripleDependencies(Triple $triple)
62    {
63        if (!$this->isFileReference($triple)) {
64            return;
65        }
66
67        $referencer = $this->getFileRefSerializer();
68        $this->serializeAsset($triple);
69        $source = $referencer->unserialize($triple->object);
70
71        if ($source instanceof Directory) {
72            $source->deleteSelf();
73        } elseif ($source instanceof File) {
74            $source->delete();
75        }
76
77        $referencer->cleanUp($triple->object);
78    }
79
80    /**
81     * @param Resource   $resource
82     * @param Model|null $model
83     */
84    public function deleteTriplesFor(Resource $resource, Model $model = null)
85    {
86        $triples = $model
87            ? $model->getRdfsInterface()->getResourceImplementation()->getRdfTriples($resource)
88            : $resource->getRdfTriples();
89
90        foreach ($triples as $triple) {
91            $this->deleteTripleDependencies($triple);
92        }
93
94        $resource->delete();
95    }
96
97    /**
98     * @param TriplesCollection $triples
99     * @param array             $propertyFilesystemMap
100     *
101     * @return array
102     * @throws common_Exception
103     */
104    public function cloneTriples(TriplesCollection $triples, array $propertyFilesystemMap = [])
105    {
106        $clones = [];
107        foreach ($triples as $original) {
108            $triple = clone $original;
109            if ($this->isFileReference($triple)) {
110                $targetFileSystem = $propertyFilesystemMap[$triple->predicate] ?? null;
111                $this->serializeAsset($triple);
112                $triple->object = $this->cloneFile($triple->object, $targetFileSystem);
113            }
114            $clones[] = $triple;
115        }
116
117        return $clones;
118    }
119
120    /**
121     * @param      $fileUri
122     * @param null $targetFileSystemId
123     *
124     * @return string
125     * @throws \common_Exception
126     * @throws \tao_models_classes_FileNotFoundException
127     */
128    protected function cloneFile($fileUri, $targetFileSystemId = null)
129    {
130        $referencer = $this->getFileRefSerializer();
131        $flySystemService = $this->getServiceLocator()->get(FileSystemService::SERVICE_ID);
132
133        $source = $referencer->unserialize($fileUri);
134        $targetFileSystemId = !$targetFileSystemId ? $source->getFileSystemId() : $targetFileSystemId;
135        $destinationPath = $flySystemService->getDirectory($targetFileSystemId)->getDirectory(uniqid('', true));
136
137        if ($source instanceof Directory) {
138            common_Logger::i('clone directory ' . $fileUri);
139            foreach ($source->getFlyIterator(Directory::ITERATOR_FILE | Directory::ITERATOR_RECURSIVE) as $file) {
140                $destinationPath->getFile($source->getRelPath($file))->write($file->readStream());
141            }
142            $destination = $destinationPath;
143        } elseif ($source instanceof File) {
144            common_Logger::i('clone file ' . $fileUri);
145            $destination = $destinationPath->getFile($source->getBasename());
146            $destination->write($source->readStream());
147        }
148
149        return $referencer->serialize($destination);
150    }
151
152    /**
153     * @param TriplesCollection $triples
154     *
155     * @return array
156     */
157    public function getPropertyStorageMap(TriplesCollection $triples)
158    {
159        $map = [];
160
161        foreach ($triples as $triple) {
162            if ($this->isFileReference($triple)) {
163                $this->serializeAsset($triple);
164                $source = $this->getFileRefSerializer()->unserialize($triple->object);
165                $map[$triple->predicate] = $source->getFileSystemId();
166            }
167        }
168
169        return $map;
170    }
171
172    /**
173     * @param Triple $triple
174     *
175     * @return bool
176     */
177    protected function isFileReference(Triple $triple)
178    {
179        $property = $this->getProperty($triple->predicate);
180        $range = $property->getRange();
181
182        $uri = $property->getUri();
183
184        if ($uri == MediaService::PROPERTY_LINK) {
185            return true;
186        }
187
188        if ($range === null) {
189            return false;
190        }
191
192        switch ($range->getUri()) {
193            case GenerisRdf::CLASS_GENERIS_FILE:
194                return true;
195            case OntologyRdfs::RDFS_RESOURCE:
196                $object = $this->getResource($triple->object);
197                return $object->hasType($this->getClass(GenerisRdf::CLASS_GENERIS_FILE));
198            default:
199                return false;
200        }
201    }
202
203    private function serializeAsset(Triple $triple): void
204    {
205        $this->getFileSourceSerializer()->serialize($triple);
206    }
207
208    private function getFileSourceSerializer(): FileSourceSerializer
209    {
210        return $this->getServiceLocator()->get(FileSourceSerializer::class);
211    }
212}