ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.ilSystemStyleSkinContainer.php
Go to the documentation of this file.
1<?php
2include_once("Services/Style/System/classes/Utilities/class.ilSkinStyleXML.php");
3include_once("Services/Style/System/classes/class.ilStyleDefinition.php");
4include_once("Services/Style/System/classes/Exceptions/class.ilSystemStyleException.php");
5include_once("Services/Style/System/classes/Utilities/class.ilSystemStyleMessageStack.php");
6include_once("Services/Style/System/classes/Utilities/class.ilSystemStyleMessage.php");
7include_once("Services/Style/System/classes/Less/class.ilSystemStyleLessFile.php");
8include_once("Services/Style/System/classes/Utilities/class.ilSystemStyleConfig.php");
9
20{
21
25 protected $lng;
26
32 protected $skin;
33
39 protected static $message_stack = null;
40
47
56 {
57 global $DIC;
58
59 $this->lng = $DIC->language();
60
61 $this->skin = $skin;
62
63 if (!$message_stack) {
65 } else {
67 }
68
71 } else {
73 }
74 }
75
86 {
87 if (!$skin_id) {
89 }
90
93 }
94
95 if ($skin_id != "default") {
96 return new self(ilSkinXML::parseFromXML($system_styles_conf->getCustomizingSkinPath() . $skin_id . "/template.xml"), $message_stack, $system_styles_conf);
97 } else {
98 return new self(ilSkinXML::parseFromXML($system_styles_conf->getDefaultTemplatePath()), $message_stack, $system_styles_conf);
99 }
100 }
101
109 {
110 if (file_exists($this->getSkinDirectory())) {
112 }
113
114
115 mkdir($this->getSkinDirectory(), 0777, true);
116
117 foreach ($this->getSkin()->getStyles() as $style) {
118 $this->createResourceDirectory($this->getSystemStylesConf()->getDefaultImagesPath(), $style->getImageDirectory());
119 $this->createResourceDirectory($this->getSystemStylesConf()->getDefaultSoundsPath(), $style->getSoundDirectory());
120 $this->createResourceDirectory($this->getSystemStylesConf()->getDefaultFontsPath(), $style->getFontDirectory());
121 try {
122 $this->createLessStructure($style);
123 } catch (Exception $e) {
124 $message_stack->addMessage(new ilSystemStyleMessage($this->lng->txt("less_compile_failed") . " " . $e->getMessage(), ilSystemStyleMessage::TYPE_ERROR));
125 }
126 }
127 $this->writeSkinToXML();
128 }
129
136 public function updateSkin(ilSkinXML $old_skin)
137 {
138 $old_customizing_skin_directory = $this->getSystemStylesConf()->getCustomizingSkinPath() . $old_skin->getId() . "/";
139
140 //Move if skin id has been changed
141 if ($old_skin->getId() != $this->getSkin()->getId()) {
142 $this->move($old_customizing_skin_directory, $this->getSkinDirectory());
143 }
144
145 //Delete old template.xml and write a new one
146 unlink($this->getSkinDirectory() . "template.xml");
147 $this->writeSkinToXML();
148 }
149
156 public function updateStyle($style_id, ilSkinStyleXML $old_style)
157 {
158 $style = $this->getSkin()->getStyle($style_id);
159
160 if ($style->getImageDirectory() != $old_style->getImageDirectory()) {
161 if (file_exists($this->getSkinDirectory() . $old_style->getImageDirectory())) {
162 $this->changeResourceDirectory($style->getImageDirectory(), $old_style->getImageDirectory());
163 } else {
164 $this->createResourceDirectory($this->getSystemStylesConf()->getDefaultImagesPath(), $style->getImageDirectory());
165 }
166 }
167
168 if ($style->getFontDirectory() != $old_style->getFontDirectory()) {
169 if (file_exists($this->getSkinDirectory() . $old_style->getFontDirectory())) {
170 $this->changeResourceDirectory($style->getFontDirectory(), $old_style->getFontDirectory());
171 } else {
172 $this->createResourceDirectory($this->getSystemStylesConf()->getDefaultFontsPath(), $style->getFontDirectory());
173 }
174 }
175
176 if ($style->getSoundDirectory() != $old_style->getSoundDirectory()) {
177 if (file_exists($this->getSkinDirectory() . $old_style->getSoundDirectory())) {
178 $this->changeResourceDirectory($style->getSoundDirectory(), $old_style->getSoundDirectory());
179 } else {
180 $this->createResourceDirectory($this->getSystemStylesConf()->getDefaultSoundsPath(), $style->getSoundDirectory());
181 }
182 }
183
184
185
186 if (file_exists($this->getSkinDirectory() . $old_style->getCssFile() . ".less")) {
187 rename($this->getSkinDirectory() . $old_style->getCssFile() . ".less", $this->getLessFilePath($style->getId()));
188 } else {
189 $this->createMainLessFile($style);
190 }
191
192 if (file_exists($this->getSkinDirectory() . $old_style->getCssFile() . "-variables.less")) {
193 rename($this->getSkinDirectory() . $old_style->getCssFile() . "-variables.less", $this->getLessVariablesFilePath($style->getId()));
194 } else {
195 $this->copyVariablesFromDefault($style);
196 }
197
198 $this->changeVariablesImport($this->getLessFilePath($style->getId()), $old_style->getCssFile() . "-variables.less", $this->getLessVariablesName($style->getId()));
199
200 if (file_exists($this->getSkinDirectory() . $old_style->getCssFile() . ".css")) {
201 rename($this->getSkinDirectory() . $old_style->getCssFile() . ".css", $this->getCSSFilePath($style->getId()));
202 } else {
203 try {
204 $this->compileLess($style->getId());
205 } catch (Exception $e) {
206 $this->getMessageStack()->addMessage(
208 $e->getMessage(),
210 )
211 );
212 copy($this->getSystemStylesConf()->getDelosPath() . ".css", $this->getCSSFilePath($style->getId()));
213 }
214 }
215
216 $this->writeSkinToXML();
217 }
218
225 protected function resourcesStyleReferences($resource)
226 {
227 $references_ids = array();
228 foreach ($this->getSkin()->getStyles() as $style) {
229 if ($style->referencesResource($resource)) {
230 $references_ids[] = $style->getId();
231 }
232 }
233 return $references_ids;
234 }
235
243 protected function createResourceDirectory($source, $target)
244 {
245 $path = $this->getSkinDirectory() . $target;
246
247 mkdir($path, 0777, true);
248
249 if ($source != "") {
250 self::xCopy($source, $path);
251 $this->getMessageStack()->addMessage(
253 $this->lng->txt("dir_created") . $path,
255 )
256 );
257 }
258 }
259
267 protected function changeResourceDirectory($new_dir, $old_dir)
268 {
269 $absolut_new_dir = $this->getSkinDirectory() . $new_dir;
270 $absolut_old_dir = $this->getSkinDirectory() . $old_dir;
271
272 if (file_exists($absolut_new_dir)) {
273 $this->getMessageStack()->addMessage(
275 $this->lng->txt("dir_changed_to") . " " . $absolut_new_dir,
277 )
278 );
279 $this->getMessageStack()->addMessage(
281 $this->lng->txt("dir_preserved_backup") . " " . $absolut_old_dir,
283 )
284 );
285 } else {
286 mkdir($absolut_new_dir, 0777, true);
287 self::xCopy($absolut_old_dir, $absolut_new_dir);
288 $this->getMessageStack()->addMessage(
290 $this->lng->txt("dir_copied_from") . " " . $absolut_old_dir . " " . $this->lng->txt("to") . " " . $absolut_new_dir,
292 )
293 );
294 if (count($this->resourcesStyleReferences($old_dir)) == 0) {
295 self::recursiveRemoveDir(self::getSkinDirectory() . $old_dir);
296 $this->getMessageStack()->addMessage(
298 $this->lng->txt("dir_deleted") . " " . $absolut_old_dir,
300 )
301 );
302 } else {
303 $this->getMessageStack()->addMessage(
305 $this->lng->txt("dir_preserved_linked") . " " . $absolut_old_dir,
307 )
308 );
309 }
310 }
311 }
312
318 protected function removeResourceDirectory($dir)
319 {
320 $absolut_dir = $this->getSkinDirectory() . $dir;
321
322 if (file_exists($absolut_dir)) {
323 if (count($this->resourcesStyleReferences($dir)) == 0) {
325 $this->getMessageStack()->addMessage(
327 $this->lng->txt("dir_deleted") . " " . $dir,
329 )
330 );
331 } else {
332 $this->getMessageStack()->addMessage(
334 $this->lng->txt("dir_preserved_linked") . " " . $dir,
336 )
337 );
338 }
339 }
340 }
341
348 protected function createLessStructure(ilSkinStyleXML $style)
349 {
350 $this->createMainLessFile($style);
351 $this->copyVariablesFromDefault($style);
352 $this->copyCSSFromDefault($style);
353 $this->compileLess($style->getId());
354 }
355
361 public function createMainLessFile(ilSkinStyleXML $style)
362 {
363 $path = $this->getLessFilePath($style->getId());
364 file_put_contents($path, $this->getLessMainFileDefautContent($style));
365 $this->getMessageStack()->addMessage(
367 $this->lng->txt("main_less_created") . " " . $path,
369 )
370 );
371 }
372
380 {
381 $less_file = new ilSystemStyleLessFile($this->getSystemStylesConf()->getDefaultVariablesPath());
382 $less_file->setLessVariablesFile($this->getLessVariablesFilePath($style->getId()));
383 $less_file->write();
384 return $less_file;
385 }
386
392 public function resetImages(ilSkinStyleXML $style)
393 {
395 $this->createResourceDirectory($this->getSystemStylesConf()->getDefaultImagesPath(), $style->getImageDirectory());
396 }
397
403 public function copyCSSFromDefault(ilSkinStyleXML $style)
404 {
405 copy($this->getSystemStylesConf()->getDelosPath() . ".css", $this->getCSSFilePath($style->getId()));
406 }
407
415 public static function xCopy($src, $dest)
416 {
417 foreach (scandir($src) as $file) {
418 $src_file = rtrim($src, '/') . '/' . $file;
419 $dest_file = rtrim($dest, '/') . '/' . $file;
420 if (!is_readable($src_file)) {
422 }
423 if (substr($file, 0, 1) != ".") {
424 if (is_dir($src_file)) {
425 if (!file_exists($dest_file)) {
426 try {
427 mkdir($dest_file);
428 } catch (Exception $e) {
429 throw new ilSystemStyleException(ilSystemStyleException::FOLDER_CREATION_FAILED, "Copy " . $src_file . " to " . $dest_file . " Error: " . $e);
430 }
431 }
432 self::xCopy($src_file, $dest_file);
433 } else {
434 try {
435 copy($src_file, $dest_file);
436 } catch (Exception $e) {
437 throw new ilSystemStyleException(ilSystemStyleException::FILE_CREATION_FAILED, "Copy " . $src_file . " to " . $dest_file . " Error: " . $e);
438 }
439 }
440 }
441 }
442 }
443
449 public static function recursiveRemoveDir($dir)
450 {
451 if (is_dir($dir)) {
452 $objects = scandir($dir);
453 foreach ($objects as $object) {
454 if ($object != "." && $object != "..") {
455 if (is_dir($dir . "/" . $object)) {
456 self::recursiveRemoveDir($dir . "/" . $object);
457 } else {
458 unlink($dir . "/" . $object);
459 }
460 }
461 }
462 rmdir($dir);
463 }
464 }
465
466
474 {
475 $content = "@import \"" . $this->getSystemStylesConf()->getRelDelosPath() . "\";\n";
476 $content .= "// Import Custom Less Files here\n";
477
478 $content .= "@import \"" . $this->getLessVariablesName($style->getId()) . "\";\n";
479 return $content;
480 }
481
488 public function move($from, $to)
489 {
490 rename($from, $to);
491 }
492
493
497 public function delete()
498 {
499 self::recursiveRemoveDir(self::getSkinDirectory());
500 $this->getMessageStack()->addMessage(
502 $this->lng->txt("skin_deleted") . $this->getSkinDirectory(),
504 )
505 );
506 }
507
513 protected function deleteFile($path)
514 {
515 if (file_exists($path)) {
516 unlink($path);
517 $this->getMessageStack()->addMessage(
519 $this->lng->txt("file_deleted") . " " . $path,
521 )
522 );
523 }
524 }
525
531 public function deleteStyle(ilSkinStyleXML $style)
532 {
533 if ($style->isSubstyle()) {
535 $this->getMessageStack()->prependMessage(
537 $this->lng->txt("style_assignments_deleted") . " " . $style->getName(),
539 )
540 );
541 }
542
543 $this->deleteFile($this->getLessFilePath($style->getId()));
544 $this->deleteFile($this->getCSSFilePath($style->getId()));
545 $this->deleteFile($this->getLessVariablesFilePath($style->getId()));
546
547 $this->getSkin()->removeStyle($style->getId());
548
552
553 $this->writeSkinToXML();
554 $this->getMessageStack()->prependMessage(
556 $this->lng->txt("style_deleted") . " " . $style->getName(),
558 )
559 );
560 }
561
568 public function copy()
569 {
570 $new_skin_id_addon = "";
571
572 while (ilStyleDefinition::skinExists($this->getSkin()->getId() . $new_skin_id_addon, $this->getSystemStylesConf())) {
573 $new_skin_id_addon .= "Copy";
574 }
575
576 $new_skin_path = rtrim($this->getSkinDirectory(), "/") . $new_skin_id_addon;
577
578 mkdir($new_skin_path, 0777, true);
579 $this->xCopy($this->getSkinDirectory(), $new_skin_path);
580 $this->getMessageStack()->addMessage(new ilSystemStyleMessage($this->lng->txt("directory_created") . " " . $new_skin_path, ilSystemStyleMessage::TYPE_SUCCESS));
581 return self::generateFromId($this->getSkin()->getId() . $new_skin_id_addon, null, $this->getSystemStylesConf());
582 }
583
587 public function export()
588 {
589 ilFileDelivery::deliverFileAttached($this->createTempZip(), $this->getSkin()->getId() . ".zip", '', true);
590 }
591
597 public function createTempZip()
598 {
599 $rel_tmp_zip = "../" . $this->getSkin()->getId() . ".zip";
600 ilUtil::zip($this->getSkinDirectory(), $rel_tmp_zip, true);
601 return rtrim($this->getSkinDirectory(), "/") . ".zip";
602 }
603
615 public static function import($import_zip_path, $name, ilSystemStyleMessageStack $message_stack = null, $system_styles_conf = null, $uploaded = true)
616 {
617 if (!$system_styles_conf) {
619 }
620
621 $skin_id = preg_replace('/[^A-Za-z0-9\-_]/', '', rtrim($name, ".zip"));
622
624 $skin_id .= "Copy";
625 }
626
627 $skin_path = $system_styles_conf->getCustomizingSkinPath() . $skin_id;
628 mkdir($skin_path, 0777, true);
629
630 $temp_zip_path = $skin_path . "/" . $name;
631 if ($uploaded) {
632 move_uploaded_file($import_zip_path, $temp_zip_path);
633 } else {
634 rename($import_zip_path, $temp_zip_path);
635 }
636 ilUtil::unzip($temp_zip_path);
637 unlink($temp_zip_path);
638
640 }
641
647 protected function changeVariablesImport($main_path, $old_style_import, $new_style_import)
648 {
649 $main_less_content = file_get_contents($main_path);
650 $main_less_content = str_replace(
651 "@import \"" . $old_style_import,
652 "@import \"" . $new_style_import,
653 $main_less_content
654 );
655 file_put_contents($main_path, $main_less_content);
656 }
657
662 public function compileLess($style_id)
663 {
664 if (!PATH_TO_LESSC) {
666 }
667
668 $output = shell_exec(PATH_TO_LESSC . " " . $this->getLessFilePath($style_id));
669 if (!$output) {
670 $less_error = shell_exec(PATH_TO_LESSC . " " . $this->getLessFilePath($style_id) . " 2>&1");
671 if (!$less_error) {
672 throw new ilSystemStyleException(ilSystemStyleException::LESS_COMPILE_FAILED, "Empty css output, unknown error.");
673 }
675 }
676 file_put_contents($this->getCSSFilePath($style_id), $output);
677 }
681 public function getSkin()
682 {
683 return $this->skin;
684 }
685
689 public function setSkin($skin)
690 {
691 $this->skin = $skin;
692 }
693
697 public function getSkinDirectory()
698 {
699 return $this->getSystemStylesConf()->getCustomizingSkinPath() . $this->getSkin()->getId() . "/";
700 }
701
702
707 public function getCSSFilePath($style_id)
708 {
709 return $this->getSkinDirectory() . $this->getSkin()->getStyle($style_id)->getCssFile() . ".css";
710 }
711
716 public function getLessFilePath($style_id)
717 {
718 return $this->getSkinDirectory() . $this->getSkin()->getStyle($style_id)->getCssFile() . ".less";
719 }
720
725 public function getLessVariablesFilePath($style_id)
726 {
727 return $this->getSkinDirectory() . $this->getLessVariablesName($style_id);
728 }
729
734 public function getLessVariablesName($style_id)
735 {
736 return $this->getSkin()->getStyle($style_id)->getCssFile() . "-variables.less";
737 }
738
743 public function getImagesSkinPath($style_id)
744 {
745 return $this->getSkinDirectory() . $this->getSkin()->getStyle($style_id)->getImageDirectory();
746 }
747
751 public static function getMessageStack()
752 {
754 }
755
759 public static function setMessageStack($message_stack)
760 {
761 self::$message_stack = $message_stack;
762 }
763
767 public function addStyle(ilSkinStyleXML $style)
768 {
769 $this->getSkin()->addStyle($style);
770 $old_style = new ilSkinStyleXML("", "");
771 $this->updateStyle($style->getId(), $old_style);
772 }
773
774 protected function writeSkinToXML()
775 {
776 $this->getSkin()->writeToXMLFile($this->getSkinDirectory() . "template.xml");
777 }
778
782 public function getSystemStylesConf()
783 {
785 }
786
791 {
792 $this->system_styles_conf = $system_styles_conf;
793 }
794}
An exception for terminatinating execution or to throw for unit testing.
static deliverFileAttached($path_to_file, $download_file_name='', $mime_type='', $delete_file=false)
void
getSubstyleOf()
Returns the parent style of this style if set.
isSubstyle()
Return wheter this style is a substyle of another.
ilSkinXml holds an manages the basic data of a skin as provide by the template of the skin.
static skinExists($skin_id, ilSystemStyleConfig $system_style_config=null)
Check whether a skin exists.
ilSystemStyleConfig wraps all 'constants' to ensure the testability of all classes using those 'const...
Class for advanced editing exception handling in ILIAS.
Used to stack messages to be shown to the user.
static deleteSubStyleCategoryAssignments($a_skin_id, $a_style_id, $a_substyle)
Delets a sub styles category assignment.
This class is responsible for all file system related actions related actions of a skin such as copyi...
static recursiveRemoveDir($dir)
Recursive delete of a folder.
getLessMainFileDefautContent(ilSkinStyleXML $style)
Returns the main less default content if a new style is created.
deleteFile($path)
Deletes a given file in the container.
changeResourceDirectory($new_dir, $old_dir)
Alters the name/path of a resource directory.
createResourceDirectory($source, $target)
Creates a resource directory (sound, images or fonts) by copying from the source (mostly delos)
copyCSSFromDefault(ilSkinStyleXML $style)
Copies (resets) the images from delos.
updateSkin(ilSkinXML $old_skin)
Updates the skin.
removeResourceDirectory($dir)
Deletes a resource directory.
static generateFromId($skin_id, ilSystemStyleMessageStack $message_stack=null, ilSystemStyleConfig $system_styles_conf=null)
Generate the container class by parsing the corresponding XML.
static xCopy($src, $dest)
Recursive copy of a folder.
changeVariablesImport($main_path, $old_style_import, $new_style_import)
copyVariablesFromDefault(ilSkinStyleXML $style)
Copies (resets) the variables file from delos.
resourcesStyleReferences($resource)
Checks if a given resource (folder) is still referenced by a style of the containers skin.
export()
Exports the complete skin to an zip file.
deleteStyle(ilSkinStyleXML $style)
Deletes a style completely.
move($from, $to)
Used to move a complete directory of a skin.
__construct(ilSkinXML $skin, ilSystemStyleMessageStack $message_stack=null, ilSystemStyleConfig $system_styles_conf=null)
ilSystemStyleSkinContainer constructor.
updateStyle($style_id, ilSkinStyleXML $old_style)
Updates one single style.
resetImages(ilSkinStyleXML $style)
Copies (resets) the images from delos.
createMainLessFile(ilSkinStyleXML $style)
Creates the main less file.
create(ilSystemStyleMessageStack $message_stack)
Creates a new skin.
createLessStructure(ilSkinStyleXML $style)
Creates the less/css structure of a style.
static zip($a_dir, $a_file, $compress_content=false)
zips given directory/file into given zip.file
static unzip($a_file, $overwrite=false, $a_flat=false)
unzip file
if($format !==null) $name
Definition: metadata.php:230
$source
Definition: metadata.php:76
$DIC
Definition: xapitoken.php:46