ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilSkinStyleContainer.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
27 {
28  protected ilLanguage $lng;
29 
33  protected ilSkin $skin;
34 
39 
44 
46 
47  public function __construct(
48  ilLanguage $lng,
49  ilSkin $skin,
50  ilSystemStyleMessageStack $message_stack,
51  ilSystemStyleConfig $system_styles_conf = null,
52  ilFileSystemHelper $file_system = null
53  ) {
54  $this->lng = $lng;
55  $this->skin = $skin;
56  $this->setMessageStack($message_stack);
57 
58  if (!$system_styles_conf) {
60  } else {
61  $this->setSystemStylesConf($system_styles_conf);
62  }
63 
64  if (!$file_system) {
65  $this->file_system = new ilFileSystemHelper($this->lng, $message_stack);
66  } else {
67  $this->file_system = $file_system;
68  }
69  }
70 
75  public function create(ilSystemStyleMessageStack $message_stack): void
76  {
77  if (file_exists($this->getSkinDirectory())) {
79  }
80 
81  mkdir($this->getSkinDirectory(), 0775, true);
82 
83  foreach ($this->getSkin()->getStyles() as $style) {
84  $old_style = new ilSkinStyle('', '', '-', '-', '-', '-');
85  $this->updateStyle($style->getId(), $old_style);
86  }
87  $this->writeSkinToXML();
88  }
89 
94  public function updateSkin(ilSkin $old_skin = null): void
95  {
96  if (!$old_skin) {
97  $old_skin = $this->getSkin();
98  }
99  $old_customizing_skin_directory = $this->getSystemStylesConf()->getCustomizingSkinPath() . $old_skin->getId() . '/';
100 
101  //Move if skin id has been changed
102  if ($old_skin->getId() != $this->getSkin()->getId()) {
103  $this->file_system->move($old_customizing_skin_directory, $this->getSkinDirectory());
104  }
105 
106  //Delete old template.xml and write a new one
107  $this->file_system->delete($this->getSkinDirectory() . 'template.xml');
108  $this->writeSkinToXML();
109  }
110 
114  public function updateStyle(string $style_id, ilSkinStyle $old_style): void
115  {
116  $style = $this->getSkin()->getStyle($style_id);
117 
118  if(!is_dir($this->getSkinDirectory().$style->getId())) {
119  mkdir($this->getSkinDirectory().$style->getId(), 0775, true);
120  }
121 
122  if ($style->getId()."/".$style->getImageDirectory() != $old_style->getId()."/".$old_style->getImageDirectory()
123  && !is_dir($this->getImagesStylePath($style->getId()))) {
124  if (is_dir($this->getSkinDirectory() .$old_style->getId()."/". $old_style->getImageDirectory())) {
125  $this->file_system->changeResourceDirectory(
126  $this->getSkinDirectory(),
127  $style->getId()."/".$style->getImageDirectory(),
128  $old_style->getId()."/".$old_style->getImageDirectory()
129  );
130  } else {
131  $this->file_system->createResourceDirectory(
132  $this->getSystemStylesConf()->getDefaultImagesPath(),
133  $this->getImagesStylePath($style->getId())
134  );
135  }
136  }
137 
138  if ($style->getId()."/".$style->getFontDirectory() != $old_style->getId()."/".$old_style->getFontDirectory()
139  && !is_dir($this->getFontsStylePath($style->getId()))) {
140  if (is_dir($this->getSkinDirectory() . $old_style->getId()."/". $old_style->getFontDirectory())) {
141  $this->file_system->changeResourceDirectory(
142  $this->getSkinDirectory(),
143  $style->getId()."/".$style->getFontDirectory(),
144  $old_style->getId()."/".$old_style->getFontDirectory()
145  );
146  } else {
147  $this->file_system->createResourceDirectory(
148  $this->getSystemStylesConf()->getDefaultFontsPath(),
149  $this->getFontsStylePath($style->getId())
150  );
151  }
152  }
153 
154  if ($style->getId()."/".$style->getSoundDirectory() != $old_style->getId()."/".$old_style->getSoundDirectory()
155  && !is_dir($this->getSoundsStylePath($style->getId()))) {
156  if (is_dir($this->getSkinDirectory() . $old_style->getId()."/". $old_style->getSoundDirectory())) {
157  $this->file_system->changeResourceDirectory(
158  $this->getSkinDirectory(),
159  $style->getId()."/".$style->getSoundDirectory(),
160  $old_style->getId()."/".$old_style->getSoundDirectory()
161  );
162  } else {
163  $this->file_system->createResourceDirectory(
164  $this->getSystemStylesConf()->getDefaultSoundsPath(),
165  $this->getSoundsStylePath($style->getId())
166  );
167  }
168  }
169 
170  if($style->getId() != $old_style->getId()) {
171  if (is_dir($this->getScssSettingsPath($old_style->getId()))) {
172  $this->file_system->changeResourceDirectory(
173  $this->getSkinDirectory(),
174  $style->getId().'/'.$this->getScssSettingsFolderName(),
175  $old_style->getId().'/'.$this->getScssSettingsFolderName()
176  );
177  } elseif(!is_dir($this->getScssSettingsPath($old_style->getId()))) {
178  $this->copySettingsFromDefault($style);
179  }
180 
181  if (file_exists($this->getSkinDirectory() .$old_style->getId().'/'.$old_style->getCssFile() . '.scss')) {
182  rename(
183  $this->getSkinDirectory().$old_style->getId().'/'.$old_style->getCssFile().'.scss',
184  $this->getScssFilePath($style->getId())
185  );
186  } else {
187  $this->createMainScssFile($style);
188  }
189 
190  if (file_exists($this->getSkinDirectory().$old_style->getId().'/'.$old_style->getCssFile().'.css')) {
191  rename(
192  $this->getSkinDirectory().$old_style->getId().'/'.$old_style->getCssFile().'.css',
193  $this->getCSSFilePath($style->getId())
194  );
195  } else {
196  try {
197  $this->compileScss($style->getId());
198  } catch (Exception $e) {
199  $this->getMessageStack()->addMessage(
201  $e->getMessage(),
203  )
204  );
205  copy($this->getSystemStylesConf()->getDelosPath() . '.css', $this->getCSSFilePath($style->getId()));
206  }
207  }
208  }
209 
210 
211  $this->writeSkinToXML();
212  }
213 
218  protected function createScssStructure(ilSkinStyle $style): void
219  {
220  $this->copySettingsFromDefault($style);
221  $this->createMainScssFile($style);
222  $this->copyCSSFromDefault($style);
223  $this->compileScss($style->getId());
224  }
225 
229  public function createMainScssFile(ilSkinStyle $style): void
230  {
231 
232  $replacement_start = "// ## Begin Replacement Variables";
233  $replacement_end = "// ## End Replacement Variables";
234 
235  $path = $this->getScssFilePath($style->getId());
236 
237  if(!is_file($path)) {
238  $main_scss_content = $this->getNewMainScssFileContent($replacement_start, $replacement_end);
239  } else {
240  $main_scss_content = file_get_contents($path);
241  }
242 
243  $regex_part_to_replace_start = "%$replacement_start.*?$replacement_end%s";
245  $replacement = $settings->getVariablesForDelosOverride();
246  $new_variabales_content = "$replacement_start $replacement $replacement_end";
247 
248  $main_scss_content = preg_replace(
249  $regex_part_to_replace_start,
250  $new_variabales_content,
251  $main_scss_content
252  );
253 
254  file_put_contents($path, $main_scss_content);
255 
256  $this->getMessageStack()->addMessage(
258  $this->lng->txt('main_scss_created') . ' ' . $path,
260  )
261  );
262  }
263 
264  protected function getNewMainScssFileContent(string $replacement_start, string $replacement_end): string
265  {
266  return "// # ITCSS structure
267  // Try to apply changes by only changing the variables in the settings
268  @use \"./" . $this->getScssSettingsFolderName() . "\" as globals;
269 
270  // Default Skin is loaded with the custom setting being applied.
271  @use \"" . $this->getSystemStylesConf()->getRelDelosPath() . "\" with ( \n".
272  $replacement_start . "\n" .
273  $replacement_end . "\n" .
274  ");" . "\n" .
275  "// Apply/load other styling changes here.";
276  }
277 
282  {
283  if (is_dir($this->getScssSettingsPath($style->getId()))) {
284  $this->file_system->removeResourceDirectory($this->getSkinDirectory(), $style->getId()."/".$this->getScssSettingsFolderName());
285  }
286 
287  $this->file_system->createResourceDirectory(
288  $this->getSystemStylesConf()->getDefaultSettingsPath(),
289  $this->getScssSettingsPath($style->getId())
290  );
291 
293 
294  $settings->readAndreplaceContentOfFolder([
295  "@use \"../030-tools/" => "@use \"../../../../../../templates/default/030-tools/",
296  "@use \"../050-layout/" => "@use \"../../../../../../templates/default/050-layout/"
297  ]);
298 
299  return $settings;
300  }
301 
305  public function resetImages(ilSkinStyle $style): void
306  {
307  $this->file_system->recursiveRemoveDir($this->getImagesStylePath($style->getId()));
308  $this->file_system->createResourceDirectory(
309  $this->getSystemStylesConf()->getDefaultImagesPath(),
310  $this->getImagesStylePath($style->getId())
311  );
312  }
313 
317  public function copyCSSFromDefault(ilSkinStyle $style): void
318  {
319  copy($this->getSystemStylesConf()->getDelosPath() . '.css', $this->getCSSFilePath($style->getId()));
320  }
321 
325  public function delete(): void
326  {
327  $this->file_system->recursiveRemoveDir(self::getSkinDirectory());
328  $this->getMessageStack()->addMessage(
330  $this->lng->txt('skin_deleted') . $this->getSkinDirectory(),
332  )
333  );
334  }
335 
339  public function deleteStyle(ilSkinStyle $style): void
340  {
341  if ($style->isSubstyle()) {
343  $this->getSkin()->getId(),
344  $style->getSubstyleOf(),
345  $style->getId()
346  );
347  $this->getMessageStack()->prependMessage(
349  $this->lng->txt('style_assignments_deleted') . ' ' . $style->getName(),
351  )
352  );
353  }
354 
355  $this->file_system->saveDeleteFile($this->getScssFilePath($style->getId()));
356  $this->file_system->saveDeleteFile($this->getCSSFilePath($style->getId()));
357  $this->file_system->removeResourceDirectory($this->getSkinDirectory(), $style->getId(), false);
358 
359  $this->getSkin()->removeStyle($style->getId());
360 
361  $this->file_system->removeResourceDirectory(
362  $this->getSkinDirectory(),
363  $style->getImageDirectory()
364  );
365  $this->file_system->removeResourceDirectory(
366  $this->getSkinDirectory(),
367  $style->getFontDirectory()
368  );
369  $this->file_system->removeResourceDirectory(
370  $this->getSkinDirectory(),
371  $style->getSoundDirectory()
372  );
373 
374  $this->writeSkinToXML();
375  $this->getMessageStack()->prependMessage(
377  $this->lng->txt('style_deleted') . ' ' . $style->getName(),
379  )
380  );
381  }
382 
386  public function export(): void
387  {
389  $this->createTempZip(),
390  $this->getSkin()->getId() . '.zip',
391  '',
392  true
393  );
394  }
395 
399  public function createTempZip(): string
400  {
401  $skin_directory = $this->getSkinDirectory(); // parent of skin directory
402  $output_file = dirname($skin_directory) . '/' . $this->getSkin()->getId() . '.zip';
403 
404  ilFileUtils::zip($skin_directory, $output_file, true);
405 
406  return $output_file;
407  }
408 
412  public function compileScss(string $style_id): void
413  {
414  if (!PATH_TO_SCSS) {
416  }
417 
418  $output = shell_exec(PATH_TO_SCSS . ' ' . $this->getScssFilePath($style_id));
419  if (!$output) {
420  $Scss_error = shell_exec(PATH_TO_SCSS . ' ' . $this->getScssFilePath($style_id) . ' 2>&1');
421  if (!$Scss_error) {
422  throw new ilSystemStyleException(
424  'Empty css output, unknown error.'
425  );
426  }
428  }
429  file_put_contents($this->getCSSFilePath($style_id), $output);
430  }
431 
432  public function getSkin(): ilSkin
433  {
434  return $this->skin;
435  }
436 
437  public function setSkin(ilSkin $skin): void
438  {
439  $this->skin = $skin;
440  }
441 
442  public function getSkinDirectory(): string
443  {
444  return $this->getSystemStylesConf()->getCustomizingSkinPath() . $this->getSkin()->getId() . '/';
445  }
446 
447  public function getCSSFilePath(string $style_id): string
448  {
449  return $this->getSkinDirectory() . $style_id . "/".$this->getSkin()->getStyle($style_id)->getCssFile() . '.css';
450  }
451 
452  public function getScssFilePath(string $style_id): string
453  {
454  return $this->getSkinDirectory() . $style_id . "/".$this->getSkin()->getStyle($style_id)->getCssFile() . '.scss';
455  }
456 
457  public function getScssSettingsPath(string $style_id): string
458  {
459  return $this->getSkinDirectory() . $style_id . "/".$this->getScssSettingsFolderName();
460  }
461 
462  public function getScssSettingsFolderName(): string
463  {
464  return $this->system_styles_conf->getScssSettingsFolderName();
465  }
466 
467  public function getImagesStylePath(string $style_id): string
468  {
469  return $this->getSkinDirectory().$style_id."/".$this->getSkin()->getStyle($style_id)->getImageDirectory();
470  }
471 
472  public function getSoundsStylePath(string $style_id): string
473  {
474  return $this->getSkinDirectory().$style_id."/".$this->getSkin()->getStyle($style_id)->getSoundDirectory();
475  }
476 
477  public function getFontsStylePath(string $style_id): string
478  {
479  return $this->getSkinDirectory().$style_id."/".$this->getSkin()->getStyle($style_id)->getFontDirectory();
480  }
481 
483  {
484  return $this->message_stack;
485  }
486 
487  public function setMessageStack(ilSystemStyleMessageStack $message_stack): void
488  {
489  $this->message_stack = $message_stack;
490  }
491 
492  public function addStyle(ilSkinStyle $style): void
493  {
494  $this->getSkin()->addStyle($style);
495  $old_style = new ilSkinStyle('', '', '-', '-', '-', '-');
496  $this->updateStyle($style->getId(), $old_style);
497  }
498 
499  protected function writeSkinToXML(): void
500  {
501  $this->getSkin()->writeToXMLFile($this->getSkinDirectory() . 'template.xml');
502  }
503 
505  {
507  }
508 
509  public function setSystemStylesConf(ilSystemStyleConfig $system_styles_conf): void
510  {
511  $this->system_styles_conf = $system_styles_conf;
512  }
513 }
array $settings
Setting values (LTI parameters, custom parameters and local parameters).
Definition: System.php:200
setSystemStylesConf(ilSystemStyleConfig $system_styles_conf)
getNewMainScssFileContent(string $replacement_start, string $replacement_end)
setMessageStack(ilSystemStyleMessageStack $message_stack)
createMainScssFile(ilSkinStyle $style)
Creates the main Scss file.
createScssStructure(ilSkinStyle $style)
Creates the Scss/css structure of a style.
ilSystemStyleConfig $system_styles_conf
Used to wire this component up with the correct pathes into the customizing directory.
ilSystemStyleMessageStack $message_stack
Used to stack messages to be displayed to the user (mostly reports for failed actions) ...
ilSkin $skin
Data-scope for the skin this container capsules.
File System Helper, to reduce deps.
resetImages(ilSkinStyle $style)
Copies (resets) the images from delos.
$path
Definition: ltiservices.php:32
This class is responsible for all file system related actions related actions of a skin such as copyi...
copySettingsFromDefault(ilSkinStyle $style)
Copies (resets) the settings files from delos.
static deliverFileAttached(string $path_to_file, ?string $download_file_name=null, ?string $mime_type=null, bool $delete_file=false)
static deleteSubStyleCategoryAssignments(string $a_skin_id, string $a_style_id, string $a_substyle)
Delets a sub styles category assignment.
deleteStyle(ilSkinStyle $style)
Deletes a style completely.
copyCSSFromDefault(ilSkinStyle $style)
Copies (resets) the images from delos.
createTempZip()
Creates a temp zip file.
updateStyle(string $style_id, ilSkinStyle $old_style)
Updates one single style.
ilSystemStyleConfig wraps all &#39;constants&#39; to ensure the testability of all classes using those &#39;const...
isSubstyle()
Return wheter this style is a substyle of another.
create(ilSystemStyleMessageStack $message_stack)
Creates a new skin.
static zip(string $a_dir, string $a_file, bool $compress_content=false)
export()
Exports the complete skin to an zip file.
Used to stack messages to be shown to the user.
__construct(ilLanguage $lng, ilSkin $skin, ilSystemStyleMessageStack $message_stack, ilSystemStyleConfig $system_styles_conf=null, ilFileSystemHelper $file_system=null)
getSubstyleOf()
Returns the parent style of this style if set.
updateSkin(ilSkin $old_skin=null)
Updates the skin.
ilSkin holds an manages the basic data of a skin as provide by the template of the skin...