ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilCertificateTemplateImportAction.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
30
35{
40 private readonly \ILIAS\Data\Factory $df;
42
43 public function __construct(
44 private readonly int $objectId,
45 private readonly string $certificatePath,
46 private readonly ilCertificatePlaceholderDescription $placeholderDescriptionObject,
47 private readonly ilLogger $logger,
48 private readonly Filesystem $filesystem,
49 private readonly IRSS $irss,
53 ?ilDBInterface $database = null,
54 ?\ILIAS\Data\Factory $df = null,
56 ) {
57 global $DIC;
58 if ($database === null) {
59 $database = $DIC->database();
60 }
61
62 if ($templateRepository === null) {
64 }
65 $this->templateRepository = $templateRepository;
66
67 if ($objectHelper === null) {
69 }
70 $this->objectHelper = $objectHelper;
71
72 if ($utilHelper === null) {
74 }
75 $this->utilHelper = $utilHelper;
76 $this->stakeholder = new ilCertificateTemplateStakeholder();
77 $this->df = $df ?? new \ILIAS\Data\Factory();
78 $this->svg_blacklist_processor = $svg_blacklist_processor ?? new SVGBlacklistPreProcessor();
79 }
80
88 public function import(
89 string $path_to_zip_file,
90 string $filename,
91 string $root_directory = CLIENT_WEB_DIR,
92 string $ilias_version = ILIAS_VERSION_NUMERIC,
93 string $installation_id = IL_INST_ID
94 ): bool {
95 $import_path = $this->createArchiveDirectory($installation_id);
96
97 $clean_up_import_dir = function () use (&$import_path) {
98 try {
99 if ($this->filesystem->hasDir($import_path)) {
100 $this->filesystem->deleteDir($import_path);
101 }
102 } catch (Throwable $e) {
103 $this->logger->error(sprintf("Can't clean up import directory: %s", $e->getMessage()));
104 $this->logger->error($e->getTraceAsString());
105 }
106 };
107
108 $result = $this->df->ok(true);
109
110 try {
111 return $result
112 ->then(
113 function () use ($path_to_zip_file, $filename, $root_directory, $import_path): \ILIAS\Data\Result {
114 $result = $this->utilHelper->moveUploadedFile(
115 $path_to_zip_file,
116 $filename,
117 $root_directory . $import_path . $filename
118 );
119 if ($result) {
120 return $this->df->ok($result);
121 }
122
123 return $this->df->error(
124 sprintf(
125 'Could not move uploaded file %s to %s',
126 $path_to_zip_file,
127 $root_directory . $import_path . $filename
128 )
129 );
130 }
131 )
132 ->then(function () use ($root_directory, $import_path, $filename): \ILIAS\Data\Result {
133 $destination_dir = $root_directory . $import_path;
134 $unzip = $this->utilHelper->unzip(
135 $root_directory . $import_path . $filename,
136 $destination_dir,
137 true
138 );
139
140 $unzipped = $unzip->extract();
141
142 // Cleanup memory, otherwise there will be issues with NFS-based file systems after `listContents` has been called
143 unset($unzip);
144
145 if ($unzipped) {
146 return $this->df->ok($unzipped);
147 }
148
149 return $this->df->error(
150 sprintf(
151 'Could not unzip file %s to %s',
152 $root_directory . $import_path . $filename,
153 $destination_dir
154 )
155 );
156 })
157 ->then(function () use ($import_path, $filename): \ILIAS\Data\Result {
158 if ($this->filesystem->has($import_path . $filename)) {
159 $this->filesystem->delete($import_path . $filename);
160 }
161
162 $num_xml_files = 0;
163 $contents = $this->filesystem->listContents($import_path);
164 foreach ($contents as $file) {
165 if (!$file->isFile()) {
166 continue;
167 }
168
169 if (str_contains($file->getPath(), '.xml')) {
170 $num_xml_files++;
171 }
172
173 if (str_contains($file->getPath(), '.svg')) {
174 $stream = $this->filesystem->readStream($file->getPath());
175 $file_metadata = $stream->getMetadata();
176 $absolute_file_path = $file_metadata['uri'];
177
178 $metadata = new Metadata(
179 pathinfo($absolute_file_path)['basename'],
180 filesize($absolute_file_path),
181 mime_content_type($absolute_file_path)
182 );
183
184 $processing_result = $this->svg_blacklist_processor->process($stream, $metadata);
185 if ($processing_result->getCode() !== ProcessingStatus::OK) {
186 return $this->df->error(
187 sprintf('SVG file check failed. Reason: %s', $processing_result->getMessage())
188 );
189 }
190 }
191 }
192
193 if ($num_xml_files === 0) {
194 return $this->df->error(
195 sprintf('No XML files found in import directory: %s', $import_path)
196 );
197 }
198
199 return $this->df->ok($contents);
200 })
204 ->then(function (array $contents) use ($ilias_version) {
205 $certificate = $this->templateRepository->fetchCurrentlyUsedCertificate($this->objectId);
206
207 $current_version = $certificate->getVersion();
208 $upcoming_verion = $current_version + 1;
209 $xsl = $certificate->getCertificateContent();
210
211 foreach ($contents as $file) {
212 if (!$file->isFile()) {
213 continue;
214 }
215
216 if (str_contains($file->getPath(), '.xml')) {
217 $xsl = $this->filesystem->read($file->getPath());
218 $xsl = preg_replace(
219 "/url\‍([']{0,1}(.*?)[']{0,1}\‍)/",
220 'url([BACKGROUND_IMAGE])',
221 $xsl
222 );
223 } elseif (str_contains($file->getPath(), '.jpg')) {
224 $background_rid = $this->irss->manage()->stream(
225 $this->filesystem->readStream($file->getPath()),
226 $this->stakeholder
227 );
228 } elseif (str_contains($file->getPath(), '.svg')) {
229 $tile_image_rid = $this->irss->manage()->stream(
230 $this->filesystem->readStream($file->getPath()),
231 $this->stakeholder
232 );
233 }
234 }
235
236 $serialized_template_values = json_encode(
237 $this->placeholderDescriptionObject->getPlaceholderDescriptions(),
238 JSON_THROW_ON_ERROR
239 );
240
241 $upcoming_version_hash = hash(
242 'sha256',
243 implode('', [
244 $xsl,
245 isset($background_rid) ? $this->irss->manage()->getResource(
246 $background_rid
247 )->getStorageID() : '',
248 $serialized_template_values,
249 isset($tile_image_rid) ? $this->irss->manage()->getResource(
250 $tile_image_rid
251 )->getStorageID() : ''
252 ])
253 );
254
255 $template = new ilCertificateTemplate(
256 $this->objectId,
257 $this->objectHelper->lookupType($this->objectId),
258 $xsl,
259 $upcoming_version_hash,
260 $serialized_template_values,
261 $upcoming_verion,
262 $ilias_version,
263 time(),
264 false,
265 '',
266 '',
267 isset($background_rid) ? $background_rid->serialize() : '',
268 isset($tile_image_rid) ? $tile_image_rid->serialize() : ''
269 );
270
271 $this->templateRepository->save($template);
272
273 return null;
274 })
275 ->isOK();
276 } catch (Throwable $e) {
277 $this->logger->error(sprintf('Error during certificate import: %s', $e->getMessage()));
278 $this->logger->error($e->getTraceAsString());
279
280 return false;
281 } finally {
282 $clean_up_import_dir();
283 }
284 }
285
291 private function createArchiveDirectory(string $installationID): string
292 {
293 $type = $this->objectHelper->lookupType($this->objectId);
294 $certificateId = $this->objectId;
295
296 $dir = $this->certificatePath . time() . '__' . $installationID . '__' . $type . '__' . $certificateId . '__certificate/';
297 if ($this->filesystem->hasDir($dir)) {
298 $this->filesystem->deleteDir($dir);
299 }
300 $this->filesystem->createDir($dir);
301
302 return $dir;
303 }
304}
$filename
Definition: buildRTE.php:78
Indicates that a file is missing or not found.
Indicates general problems with the input or output operations.
Definition: IOException.php:28
__construct(private readonly int $objectId, private readonly string $certificatePath, private readonly ilCertificatePlaceholderDescription $placeholderDescriptionObject, private readonly ilLogger $logger, private readonly Filesystem $filesystem, private readonly IRSS $irss, ?ilCertificateTemplateRepository $templateRepository=null, ?ilCertificateObjectHelper $objectHelper=null, ?ilCertificateUtilHelper $utilHelper=null, ?ilDBInterface $database=null, ?\ILIAS\Data\Factory $df=null, ?SVGBlacklistPreProcessor $svg_blacklist_processor=null)
readonly ilCertificateTemplateStakeholder $stakeholder
readonly ilCertificateTemplateRepository $templateRepository
readonly SVGBlacklistPreProcessor $svg_blacklist_processor
createArchiveDirectory(string $installationID)
Creates a directory for a zip archive containing multiple certificates.
Just a wrapper class to create Unit Test for other classes.
Component logger with individual log levels by component id.
const CLIENT_WEB_DIR
Definition: constants.php:47
const IL_INST_ID
Definition: constants.php:40
const ILIAS_VERSION_NUMERIC
The filesystem interface provides the public interface for the Filesystem service API consumer.
Definition: Filesystem.php:37
Interface ilDBInterface.
has(string $class_name)
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26