ILIAS  release_8 Revision v8.25-1-g13de6a5eca6
class.ilCertificateTemplateImportAction.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
28
33{
34 private int $objectId;
35 private string $certificatePath;
43 private string $installationID;
46
47 public function __construct(
48 int $objectId,
49 string $certificatePath,
52 Filesystem $filesystem,
57 ?ilDBInterface $database = null,
60 ) {
61 $this->objectId = $objectId;
62 $this->certificatePath = $certificatePath;
63
64 $this->logger = $logger;
65 if (null === $database) {
66 global $DIC;
67 $database = $DIC->database();
68 }
69
70 $this->web_fs = $filesystem;
71 $this->tmp_fs = $tmp_fs;
72
73 $this->placeholderDescriptionObject = $placeholderDescriptionObject;
74
75 if (null === $templateRepository) {
77 }
78 $this->templateRepository = $templateRepository;
79
80 if (null === $objectHelper) {
82 }
83 $this->objectHelper = $objectHelper;
84
85 if (null === $utilHelper) {
87 }
88 $this->utilHelper = $utilHelper;
89
90 if (null === $fileService) {
93 $filesystem
94 );
95 }
96 $this->fileService = $fileService;
97 if (null === $svg_blacklist_processor) {
99 }
100 $this->svg_blacklist_processor = $svg_blacklist_processor;
101 }
102
116 public function import(
117 string $zipFile,
118 string $filename,
119 string $web_directory = CLIENT_WEB_DIR,
120 string $storage_directory = CLIENT_DATA_DIR,
121 string $iliasVerision = ILIAS_VERSION_NUMERIC,
123 ): bool {
124 $rel_tmp_import_path = $this->createTemporaryArchiveDirectory($installationID);
125 $abs_tmp_directory = rtrim($storage_directory, '/') . '/temp/';
126 $rel_import_path = $this->createArchiveDirectory($installationID);
127
128 $clean_up_import_dir = function () use (&$rel_tmp_import_path, &$rel_import_path): void {
129 try {
130 if ($this->tmp_fs->hasDir($rel_tmp_import_path)) {
131 $this->tmp_fs->deleteDir($rel_tmp_import_path);
132 }
133 } catch (Throwable $e) {
134 $this->logger->error(sprintf("Can't clean up temporary import directory: %s", $e->getMessage()));
135 $this->logger->error($e->getTraceAsString());
136 }
137
138 try {
139 if ($this->web_fs->hasDir($rel_import_path)) {
140 $this->web_fs->deleteDir($rel_import_path);
141 }
142 } catch (Throwable $e) {
143 $this->logger->error(sprintf("Can't clean up import directory: %s", $e->getMessage()));
144 $this->logger->error($e->getTraceAsString());
145 }
146 };
147
148 try {
149 $abs_zip_path = $abs_tmp_directory . $rel_tmp_import_path . $filename;
150 $result = $this->utilHelper->moveUploadedFile(
151 $zipFile,
152 $filename,
153 $abs_zip_path
154 );
155
156 if (!$result) {
157 return false;
158 }
159
160 $this->utilHelper->unzip(
161 $abs_tmp_directory . $rel_tmp_import_path . $filename,
162 true
163 );
164
165 $abs_unzip_destination_dir = $abs_tmp_directory . $rel_tmp_import_path;
166 $sub_directory = str_replace('.zip', '', strtolower($filename)) . '/';
167 $abs_sub_directory_path = $abs_tmp_directory . $rel_tmp_import_path . $sub_directory;
168 if (is_dir($abs_sub_directory_path)) {
169 $abs_target_directory = $abs_sub_directory_path;
170 }
171
172 $this->utilHelper->renameExecutables($abs_sub_directory_path);
173
174 if ($this->tmp_fs->has($rel_tmp_import_path . $filename)) {
175 $this->tmp_fs->delete($rel_tmp_import_path . $filename);
176 }
177
178 $tmp_contents = $this->tmp_fs->listContents($rel_tmp_import_path, true);
179 foreach ($tmp_contents as $file) {
180 if (!$file->isFile()) {
181 continue;
182 }
183
184 if (!$this->web_fs->has($rel_import_path . basename($file->getPath()))) {
185 $this->web_fs->writeStream(
186 $rel_import_path . basename($file->getPath()),
187 $this->tmp_fs->readStream($file->getPath())
188 );
189 }
190 }
191
192 $num_background_images = 0;
193 $num_tile_images = 0;
194 $num_xml_files = 0;
195 $contents = $this->web_fs->listContents($rel_import_path);
196 foreach ($contents as $file) {
197 if (!$file->isFile()) {
198 continue;
199 }
200
201 if (strpos($file->getPath(), '.xml') !== false) {
202 ++$num_xml_files;
203 }
204
205 if (strpos($file->getPath(), '.svg') !== false) {
206 $stream = $this->web_fs->readStream($file->getPath());
207 $file_metadata = $stream->getMetadata();
208 $absolute_file_path = $file_metadata['uri'];
209
210 $metadata = new Metadata(
211 pathinfo($absolute_file_path)['basename'],
212 filesize($absolute_file_path),
213 mime_content_type($absolute_file_path)
214 );
215
216 ++$num_tile_images;
217
218 $processing_result = $this->svg_blacklist_processor->process($stream, $metadata);
219 if ($processing_result->getCode() !== ProcessingStatus::OK) {
220 return false;
221 }
222 }
223
224 if (str_contains($file->getPath(), '.jpg')) {
225 ++$num_background_images;
226 }
227 }
228
229 if (0 === $num_xml_files) {
230 $this->logger->error('No XML file found in the imported zip file');
231 return false;
232 }
233 if ($num_background_images > 1) {
234 $this->logger->error('More than one background image found in the imported zip file');
235 return false;
236 }
237 if ($num_tile_images > 1) {
238 $this->logger->error('More than one tile image found in the imported zip file');
239 return false;
240 }
241
242 $certificate = $this->templateRepository->fetchCurrentlyUsedCertificate($this->objectId);
243
244 $currentVersion = $certificate->getVersion();
245 $newVersion = $currentVersion + 1;
246 $backgroundImagePath = $certificate->getBackgroundImagePath();
247 $cardThumbnailImagePath = $certificate->getThumbnailImagePath();
248
249 $xsl = $certificate->getCertificateContent();
250
251 foreach ($contents as $file) {
252 if (!$file->isFile()) {
253 continue;
254 }
255
256 if (strpos($file->getPath(), '.xml') !== false) {
257 $xsl = $this->web_fs->read($file->getPath());
258 // as long as we cannot make RPC calls in a given directory, we have
259 // to add the complete path to every url
260 $xsl = preg_replace_callback(
261 "/url\‍([']{0,1}(.*?)[']{0,1}\‍)/",
262 function (array $matches) use ($web_directory): string {
263 $basePath = rtrim(
264 dirname($this->fileService->getBackgroundImageDirectory($web_directory)),
265 '/'
266 );
267 $fileName = basename($matches[1]);
268
269 if ('[BACKGROUND_IMAGE]' === $fileName) {
270 $basePath = '';
271 } elseif ($basePath !== '') {
272 $basePath .= '/';
273 }
274
275 return 'url(' . $basePath . $fileName . ')';
276 },
277 $xsl
278 );
279 } elseif (strpos($file->getPath(), '.jpg') !== false) {
280 $newBackgroundImageName = 'background_' . $newVersion . '.jpg';
281 $newPath = $this->certificatePath . $newBackgroundImageName;
282 $this->web_fs->copy($file->getPath(), $newPath);
283
284 $backgroundImagePath = $this->certificatePath . $newBackgroundImageName;
285 // upload of the background image, create a thumbnail
286
287 $backgroundImageThumbPath = $this->getBackgroundImageThumbnailPath();
288
289 $thumbnailImagePath = $web_directory . $backgroundImageThumbPath;
290
291 $originalImagePath = $web_directory . $newPath;
292 $this->utilHelper->convertImage(
293 $originalImagePath,
294 $thumbnailImagePath,
295 'JPEG',
296 "100"
297 );
298 } elseif (strpos($file->getPath(), '.svg') !== false) {
299 $newCardThumbnailName = 'thumbnail_' . $newVersion . '.svg';
300 $newPath = $this->certificatePath . $newCardThumbnailName;
301
302 $this->web_fs->copy($file->getPath(), $newPath);
303
304 $cardThumbnailImagePath = $this->certificatePath . $newCardThumbnailName;
305 }
306 }
307
308 $jsonEncodedTemplateValues = json_encode(
309 $this->placeholderDescriptionObject->getPlaceholderDescriptions(),
310 JSON_THROW_ON_ERROR
311 );
312
313 $newHashValue = hash(
314 'sha256',
315 implode('', [
316 $xsl,
317 $backgroundImagePath,
318 $jsonEncodedTemplateValues,
319 $cardThumbnailImagePath
320 ])
321 );
322
323 $template = new ilCertificateTemplate(
324 $this->objectId,
325 $this->objectHelper->lookupType($this->objectId),
326 $xsl,
327 $newHashValue,
328 $jsonEncodedTemplateValues,
329 $newVersion,
330 $iliasVerision,
331 time(),
332 true,
333 $backgroundImagePath,
334 $cardThumbnailImagePath
335 );
336
337 $this->templateRepository->save($template);
338
339 return true;
340 } catch (Throwable $e) {
341 $this->logger->error(sprintf('Error during certificate import: %s', $e->getMessage()));
342 $this->logger->error($e->getTraceAsString());
343
344 return false;
345 } finally {
346 $clean_up_import_dir();
347 }
348 }
349
353 private function createArchiveDirectory(string $installationId): string
354 {
355 $dir = $this->buildArchivePath($installationId);
356
357 if ($this->web_fs->hasDir($dir)) {
358 $this->web_fs->deleteDir($dir);
359 }
360 $this->web_fs->createDir($dir);
361
362 return $dir;
363 }
364
368 private function createTemporaryArchiveDirectory(string $installationId): string
369 {
370 $dir = $this->buildArchivePath($installationId);
371
372 if ($this->tmp_fs->hasDir($dir)) {
373 $this->tmp_fs->deleteDir($dir);
374 }
375 $this->tmp_fs->createDir($dir);
376
377 return $dir;
378 }
379
380 private function buildArchivePath(string $installationId): string
381 {
382 $seperator = '__';
383 $type = $this->objectHelper->lookupType($this->objectId);
384
385 return implode($seperator, [
386 $this->certificatePath . time(),
387 $installationId,
388 $type,
389 $this->objectId,
390 'certificate/'
391 ]);
392 }
393
394 private function getBackgroundImageThumbnailPath(): string
395 {
396 return $this->certificatePath . 'background.jpg.thumb.jpg';
397 }
398}
$filename
Definition: buildRTE.php:78
ilCertificateBackgroundImageFileService $fileService
ilCertificatePlaceholderDescription $placeholderDescriptionObject
__construct(int $objectId, string $certificatePath, ilCertificatePlaceholderDescription $placeholderDescriptionObject, ilLogger $logger, Filesystem $filesystem, Filesystem $tmp_fs, ?ilCertificateTemplateRepository $templateRepository=null, ?ilCertificateObjectHelper $objectHelper=null, ?ilCertificateUtilHelper $utilHelper=null, ?ilDBInterface $database=null, ?ilCertificateBackgroundImageFileService $fileService=null, ?SVGBlacklistPreProcessor $svg_blacklist_processor=null)
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 CLIENT_DATA_DIR
Definition: constants.php:46
const IL_INST_ID
Definition: constants.php:40
global $DIC
Definition: feed.php:28
const ILIAS_VERSION_NUMERIC
Interface Filesystem.
Definition: Filesystem.php:40
Interface ilDBInterface.
Class FlySystemFileAccessTest \Provider\FlySystem @runTestsInSeparateProcesses @preserveGlobalState d...
$type