ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilObjStyleSheet.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
29{
31 protected \ILIAS\Style\Content\InternalRepoService $repo;
32 protected bool $is_3_10_skin = false;
33 protected string $export_sub_dir = "";
34 protected array $chars_by_type = [];
35 protected array $end_styles = [];
36 protected array $chars = [];
37 protected bool $up_to_date = false;
38 public array $style = [];
39 protected array $hidden_chars = [];
40 protected array $style_class = [];
41
42 protected int $scope = 0;
43
44 public static array $num_unit = array("px", "em", "rem", "ex", "%", "pt", "pc", "in", "mm", "cm");
45 public static array $num_unit_no_perc = array("px", "em", "rem", "ex", "pt", "pc", "in", "mm", "cm");
46
47 // css parameters and their attribute values, input type and group
48 public static array $parameter = array(
49 "font-size" => array(
50 "values" => array("xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "smaller", "larger"),
51 "input" => "fontsize",
52 "group" => "text"),
53 "font-family" => array(
54 "values" => array(),
55 "input" => "text",
56 "group" => "text"),
57 "font-style" => array(
58 "values" => array("italic", "oblique", "normal"),
59 "input" => "select",
60 "group" => "text"),
61 "font-weight" => array(
62 "values" => array("bold", "normal", "bolder", "lighter"),
63 "input" => "select",
64 "group" => "text"),
65 "font-variant" => array(
66 "values" => array("small-caps", "normal"),
67 "input" => "select",
68 "group" => "text"),
69 "word-spacing" => array(
70 "values" => array(),
71 "input" => "numeric_no_perc",
72 "group" => "text"),
73 "letter-spacing" => array(
74 "values" => array(),
75 "input" => "numeric_no_perc",
76 "group" => "text"),
77 "text-decoration" => array(
78 "values" => array("underline", "overline", "line-through", "blink", "none"),
79 "input" => "select",
80 "group" => "text"),
81 "text-transform" => array(
82 "values" => array("capitalize", "uppercase", "lowercase", "none"),
83 "input" => "select",
84 "group" => "text"),
85 "color" => array(
86 "values" => array(),
87 "input" => "color",
88 "group" => "text"),
89 "text-indent" => array(
90 "values" => array(),
91 "input" => "numeric",
92 "group" => "text"),
93 "line-height" => array(
94 "values" => array(),
95 "input" => "numeric",
96 "group" => "text"),
97 "vertical-align" => array(
98 "values" => array("top", "middle", "bottom", "baseline", "sub", "super",
99 "text-top", "text-bottom"),
100 "input" => "select",
101 "group" => "text"),
102 "text-align" => array(
103 "values" => array("left", "center", "right", "justify"),
104 "input" => "select",
105 "group" => "text"),
106 "white-space" => array(
107 "values" => array("normal", "pre", "nowrap"),
108 "input" => "select",
109 "group" => "text"),
110 "margin" => array(
111 "values" => array(),
112 "input" => "trbl_numeric",
113 "subpar" => array("margin", "margin-top", "margin-right",
114 "margin-bottom", "margin-left"),
115 "group" => "margin_and_padding"),
116 "padding" => array(
117 "values" => array(),
118 "input" => "trbl_numeric",
119 "subpar" => array("padding", "padding-top", "padding-right",
120 "padding-bottom", "padding-left"),
121 "group" => "margin_and_padding"),
122 "border-width" => array(
123 "values" => array("thin", "medium", "thick"),
124 "input" => "border_width",
125 "subpar" => array("border-width", "border-top-width", "border-right-width",
126 "border-bottom-width", "border-left-width"),
127 "group" => "border"),
128 "border-color" => array(
129 "values" => array(),
130 "input" => "trbl_color",
131 "subpar" => array("border-color", "border-top-color", "border-right-color",
132 "border-bottom-color", "border-left-color"),
133 "group" => "border"),
134 "border-style" => array(
135 "values" => array("none", "hidden", "dotted", "dashed", "solid", "double",
136 "groove", "ridge", "inset", "outset"),
137 "input" => "border_style",
138 "subpar" => array("border-style", "border-top-style", "border-right-style",
139 "border-bottom-style", "border-left-style"),
140 "group" => "border"),
141
142 "background-color" => array(
143 "values" => array(),
144 "input" => "color",
145 "group" => "background"),
146 "background-image" => array(
147 "values" => array(),
148 "input" => "background_image",
149 "group" => "background"),
150 "background-repeat" => array(
151 "values" => array("repeat", "repeat-x", "repeat-y", "no-repeat"),
152 "input" => "select",
153 "group" => "background"),
154 "background-attachment" => array(
155 "values" => array("fixed", "scroll"),
156 "input" => "select",
157 "group" => "background"),
158 "background-position" => array(
159 "values" => array("horizontal" => array("left", "center", "right"),
160 "vertical" => array("top", "center", "bottom")),
161 "input" => "background_position",
162 "group" => "background"),
163
164 "position" => array(
165 "values" => array("absolute", "fixed", "relative", "static"),
166 "input" => "select",
167 "group" => "positioning"),
168 "top" => array(
169 "values" => array(),
170 "input" => "numeric",
171 "group" => "positioning"),
172 "bottom" => array(
173 "values" => array(),
174 "input" => "numeric",
175 "group" => "positioning"),
176 "left" => array(
177 "values" => array(),
178 "input" => "numeric",
179 "group" => "positioning"),
180 "right" => array(
181 "values" => array(),
182 "input" => "numeric",
183 "group" => "positioning"),
184 "width" => array(
185 "values" => array(),
186 "input" => "numeric",
187 "group" => "positioning"),
188 "height" => array(
189 "values" => array(),
190 "input" => "numeric",
191 "group" => "positioning"),
192 "min-height" => array(
193 "values" => array(),
194 "input" => "numeric",
195 "group" => "positioning"),
196 "float" => array(
197 "values" => array("left", "right", "none"),
198 "input" => "select",
199 "group" => "positioning"),
200 "overflow" => array(
201 "values" => array("visible", "hidden", "scroll", "auto"),
202 "input" => "select",
203 "group" => "positioning"),
204 "opacity" => array(
205 "values" => array(),
206 "input" => "percentage",
207 "group" => "special"),
208 "transform" => array(
209 "values" => array("rotate(90deg)", "rotate(180deg)", "rotate(270deg)"),
210 "input" => "select",
211 "group" => "special"),
212 "transform-origin" => array(
213 "values" => array( "horizontal" => array("left", "center", "right"),
214 "vertical" => array("top", "center", "bottom")),
215 "input" => "background_position",
216 "group" => "special"),
217 "cursor" => array(
218 "values" => array("auto", "default", "crosshair", "pointer", "move",
219 "n-resize", "ne-resize", "e-resize", "se-resize", "s-resize", "sw-resize",
220 "w-resize", "nw-resize", "text", "wait", "help"),
221 "input" => "select",
222 "group" => "special"),
223 "clear" => array(
224 "values" => array("both","left","right","none"),
225 "input" => "select",
226 "group" => "special"),
227
228 "list-style-type.ol" => array(
229 "values" => array("decimal","lower-roman","upper-roman",
230 "lower-alpha", "upper-alpha", "lower-greek", "hebrew",
231 "decimal-leading-zero", "cjk-ideographic", "hiragana",
232 "katakana", "hiragana-iroha", "katakana-iroha", "none"),
233 "input" => "select",
234 "group" => "ol"),
235 "list-style-type.ul" => array(
236 "values" => array("disc","circle","square",
237 "none"),
238 "input" => "select",
239 "group" => "ul"),
240 "list-style-image.ul" => array(
241 "values" => array(),
242 "input" => "background_image",
243 "group" => "ul"),
244 "list-style-position.ol" => array(
245 "values" => array("inside","outside"),
246 "input" => "select",
247 "group" => "ol"),
248 "list-style-position.ul" => array(
249 "values" => array("inside","outside"),
250 "input" => "select",
251 "group" => "ul"
252 ),
253 "border-collapse" => array(
254 "values" => array("collapse","separate"),
255 "input" => "select",
256 "group" => "table"
257 ),
258 "caption-side" => array(
259 "values" => array("top","bottom","left","right"),
260 "input" => "select",
261 "group" => "table"
262 )
263 );
264
265 // filter groups of properties that should only be
266 // displayed with matching tag (group -> tags)
267 public static array $filtered_groups =
268 array("ol" => array("ol"), "ul" => array("ul"),
269 "table" => array("table"), "positioning" => array("h1", "h2", "h3", "div", "img", "table", "a", "figure", "li", "p"));
270
271 // style types and their super type
272 public static array $style_super_types = array(
273 "text_block" => array("text_block", "heading1", "heading2", "heading3", "code_block"),
274 "text_inline" => array("text_inline", "sub", "sup", "code_inline", "strong", "em"),
275 "section" => array("section"),
276 "link" => array("link"),
277 "table" => array("table", "table_cell", "table_caption"),
278 "list" => array("list_o", "list_u", "list_item"),
279 "flist" => array("flist_cont", "flist_head", "flist", "flist_li", "flist_a"),
280 "media" => array("media_cont", "media_caption", "iim", "marker"),
281 "tabs" => array("va_cntr", "va_icntr", "va_ihead", "va_iheada", "va_ihcap", "va_icont",
282 "ha_cntr", "ha_icntr", "ha_ihead", "ha_iheada", "ha_ihcap", "ha_icont", "ca_cntr", "ca_icntr", "ca_ihead", "ca_icont"),
283 "question" => array("question", "qtitle", "qanswer", "qinput", "qlinput", "qsubmit", "qfeedr", "qfeedw",
284 "qimg", "qordul", "qordli", "qimgd", "qetitem", "qetcorr", "qover"),
285 "page" => array("page_cont", "page_title", "page_fn")
286 );
287
288 // these types are expandable, i.e. the user can define new style classes
289 public static array $expandable_types = array(
290 "text_block",
291 "text_inline", "section", "media_cont", "media_caption", "table", "table_cell", "flist_li", "table_caption",
292 "list_o", "list_u", "list_item",
293 "va_cntr", "va_icntr", "va_ihead", "va_iheada", "va_ihcap", "va_icont",
294 "ha_cntr", "ha_icntr", "ha_ihead", "ha_iheada", "ha_ihcap", "ha_icont",
295 "ca_cntr", "ca_icntr", "ca_ihead", "ca_icont"
296 );
297
298 // these types can be hidden in the content editor
299 public static array $hideable_types = array(
300 "table", "table_cell"
301 );
302
303 // tag that are used by style types
304 public static array $assigned_tags = array(
305 "text_block" => "p",
306 "heading1" => "h1",
307 "heading2" => "h2",
308 "heading3" => "h3",
309 "code_block" => "pre",
310 "em" => "em",
311 "text_inline" => "span",
312 "code_inline" => "code",
313 "sup" => "sup",
314 "sub" => "sub",
315 "strong" => "strong",
316 "section" => "div",
317 "link" => "a",
318 "table" => "table",
319 "table_cell" => "td",
320 "table_caption" => "caption",
321 "media_cont" => "figure",
322 "media_caption" => "div",
323 "iim" => "div",
324 "marker" => "a",
325 "list_o" => "ol",
326 "list_u" => "ul",
327 "list_item" => "li",
328 "flist_cont" => "div",
329 "flist_head" => "div",
330 "flist" => "ul",
331 "flist_li" => "li",
332 "flist_a" => "a",
333 "question" => "div",
334 "qtitle" => "div",
335 "qanswer" => "div",
336 "qimg" => "img",
337 "qimgd" => "a",
338 "qordul" => "ul",
339 "qordli" => "li",
340 "qetitem" => "a",
341 "qetcorr" => "span",
342 "qinput" => "input",
343 "qlinput" => "textarea",
344 "qsubmit" => "input",
345 "qfeedr" => "div",
346 "qfeedw" => "div",
347 "qover" => "div",
348 "page_cont" => "div",
349 "page_fn" => "div",
350 "page" => "div",
351 "page_title" => "h1",
352 "va_cntr" => "div",
353 "va_icntr" => "div",
354 "va_icont" => "div",
355 "va_ihead" => "div",
356 "va_iheada" => "div",
357 "va_ihcap" => "div",
358 "ha_cntr" => "div",
359 "ha_icntr" => "div",
360 "ha_icont" => "div",
361 "ha_iheada" => "div",
362 "ha_ihcap" => "div",
363 "ha_ihead" => "div",
364 "ca_cntr" => "div",
365 "ca_icntr" => "div",
366 "ca_ihead" => "div",
367 "ca_icont" => "div"
368 );
369
370 // pseudo classes
371 public static array $pseudo_classes =
372 [
373 "a" => ["hover"],
374 "div" => ["hover", "before"],
375 "img" => ["hover"],
376 "li" => ["before"]
377 ];
378
379 // core styles these styles MUST exists -> see also basic_style/style.xml
380 public static array $core_styles = array(
381 array("type" => "text_block", "class" => "Standard"),
382 array("type" => "text_block", "class" => "List"),
383 array("type" => "text_block", "class" => "TableContent"),
384 array("type" => "code_block", "class" => "Code"),
385 array("type" => "heading1", "class" => "Headline1"),
386 array("type" => "heading2", "class" => "Headline2"),
387 array("type" => "heading3", "class" => "Headline3"),
388 array("type" => "text_inline", "class" => "Comment"),
389 array("type" => "em", "class" => "Emph"),
390 array("type" => "text_inline", "class" => "Quotation"),
391 array("type" => "strong", "class" => "Strong"),
392 array("type" => "text_inline", "class" => "Accent"),
393 array("type" => "text_inline", "class" => "Important"),
394 array("type" => "code_inline", "class" => "CodeInline"),
395 array("type" => "sup", "class" => "Sup"),
396 array("type" => "sub", "class" => "Sub"),
397 array("type" => "link", "class" => "IntLink"),
398 array("type" => "link", "class" => "ExtLink"),
399 array("type" => "link", "class" => "FootnoteLink"),
400 array("type" => "link", "class" => "FileLink"),
401 array("type" => "link", "class" => "GlossaryLink"),
402 array("type" => "media_cont", "class" => "MediaContainer"),
403 array("type" => "media_cont", "class" => "MediaContainerMax50"),
404 array("type" => "media_cont", "class" => "MediaContainerFull100"),
405 array("type" => "table", "class" => "StandardTable"),
406 array("type" => "media_caption", "class" => "MediaCaption"),
407 array("type" => "iim", "class" => "ContentPopup"),
408 array("type" => "marker", "class" => "Marker"),
409 array("type" => "page_cont", "class" => "PageContainer"),
410 array("type" => "page", "class" => "Page"),
411 array("type" => "page_fn", "class" => "Footnote"),
412 array("type" => "page_title", "class" => "PageTitle"),
413 array("type" => "list_o", "class" => "NumberedList"),
414 array("type" => "list_u", "class" => "BulletedList"),
415 array("type" => "list_item", "class" => "StandardListItem"),
416 array("type" => "question", "class" => "Standard"),
417 array("type" => "question", "class" => "SingleChoice"),
418 array("type" => "question", "class" => "MultipleChoice"),
419 array("type" => "question", "class" => "TextQuestion"),
420 array("type" => "question", "class" => "OrderingQuestion"),
421 array("type" => "question", "class" => "MatchingQuestion"),
422 array("type" => "question", "class" => "ImagemapQuestion"),
423 array("type" => "question", "class" => "ErrorText"),
424 array("type" => "question", "class" => "TextSubset"),
425 array("type" => "question", "class" => "ClozeTest"),
426 array("type" => "qtitle", "class" => "Title"),
427 array("type" => "qanswer", "class" => "Answer"),
428 array("type" => "qimg", "class" => "QuestionImage"),
429 array("type" => "qimgd", "class" => "ImageDetailsLink"),
430 array("type" => "qordul", "class" => "OrderList"),
431 array("type" => "qordli", "class" => "OrderListItem"),
432 array("type" => "qordul", "class" => "OrderListHorizontal"),
433 array("type" => "qordli", "class" => "OrderListItemHorizontal"),
434 array("type" => "qetitem", "class" => "ErrorTextItem"),
435 array("type" => "qetitem", "class" => "ErrorTextSelected"),
436 array("type" => "qetcorr", "class" => "ErrorTextCorrected"),
437 array("type" => "qinput", "class" => "TextInput"),
438 array("type" => "qlinput", "class" => "LongTextInput"),
439 array("type" => "qsubmit", "class" => "Submit"),
440 array("type" => "qfeedr", "class" => "FeedbackRight"),
441 array("type" => "qfeedw", "class" => "FeedbackWrong"),
442 array("type" => "qover", "class" => "Correct"),
443 array("type" => "qover", "class" => "Inorrect"),
444 array("type" => "qover", "class" => "StatusMessage"),
445 array("type" => "qover", "class" => "WrongAnswersMessage"),
446 array("type" => "flist_cont", "class" => "FileListContainer"),
447 array("type" => "flist_head", "class" => "FileListHeading"),
448 array("type" => "flist", "class" => "FileList"),
449 array("type" => "flist_li", "class" => "FileListItem"),
450 array("type" => "flist_a", "class" => "FileListItemLink")
451 );
452
453 public static array $templates = array(
454 "table" => array(
455 "table" => "table",
456 "caption" => "table_caption",
457 "row_head" => "table_cell",
458 "row_foot" => "table_cell",
459 "col_head" => "table_cell",
460 "col_foot" => "table_cell",
461 "odd_row" => "table_cell",
462 "even_row" => "table_cell",
463 "odd_col" => "table_cell",
464 "even_col" => "table_cell"),
465 "vaccordion" => array(
466 "va_cntr" => "va_cntr",
467 "va_icntr" => "va_icntr",
468 "va_ihead" => "va_ihead",
469 "va_iheada" => "va_iheada",
470 "va_ihcap" => "va_ihcap",
471 "va_icont" => "va_icont"
472 ),
473 "haccordion" => array(
474 "ha_cntr" => "ha_cntr",
475 "ha_icntr" => "ha_icntr",
476 "ha_ihead" => "ha_ihead",
477 "ha_iheada" => "ha_iheada",
478 "ha_ihcap" => "ha_ihcap",
479 "ha_icont" => "ha_icont"
480 ),
481 "carousel" => array(
482 "ca_cntr" => "ca_cntr",
483 "ca_icntr" => "ca_icntr",
484 "ca_ihead" => "ca_ihead",
485 "ca_icont" => "ca_icont"
486 )
487 );
488
489 // basic style xml file, image directory and dom
490 protected static string $basic_style_file = "../vendor/ilias/Style/basic_style/style.xml";
491 protected static string $basic_style_zip = "../vendor/ilias/Style/basic_style/style.zip";
492 protected static string $basic_style_image_dir = "./components/ILIAS/COPage/basic_style/images";
493 protected static ?DOMDocument $basic_style_dom = null;
494
495 public function __construct(
496 int $a_id = 0,
497 bool $a_call_by_reference = false
498 ) {
499 global $DIC;
500
501 $this->db = $DIC->database();
502 $this->lng = $DIC->language();
503 $this->type = "sty";
504 $this->style = array();
505 $this->ilias = $DIC["ilias"];
506 $this->domain = $DIC->contentStyle()->internal()->domain();
507
508 if ($a_call_by_reference) {
509 $this->ilias->raiseError("Can't instantiate style object via reference id.", $this->ilias->error_obj->FATAL);
510 }
511 parent::__construct($a_id, false);
512 $this->repo = $DIC->contentStyle()->internal()->repo();
513 }
514
515 public static function getBasicZipPath(): string
516 {
518 }
519
523 public function setUpToDate(bool $a_up_to_date = true): void
524 {
525 $this->up_to_date = $a_up_to_date;
526 }
527
528 public function getUpToDate(): bool
529 {
530 return $this->up_to_date;
531 }
532
533 public function setScope(int $a_scope): void
534 {
535 $this->scope = $a_scope;
536 }
537
538 public function getScope(): int
539 {
540 return $this->scope;
541 }
542
543 public static function _writeUpToDate(
544 int $a_id,
545 bool $a_up_to_date
546 ): void {
547 global $DIC;
548
549 $ilDB = $DIC->database();
550
551 $q = "UPDATE style_data SET uptodate = " .
552 $ilDB->quote((int) $a_up_to_date, "integer") .
553 " WHERE id = " . $ilDB->quote($a_id, "integer");
554 $ilDB->manipulate($q);
555 }
556
557 public static function writeOwner($obj_id, $style_id)
558 {
559 global $DIC;
560 $ilDB = $DIC->database();
561
562 $q = "UPDATE style_data SET owner_obj = " .
563 $ilDB->quote((int) $obj_id, "integer") .
564 " WHERE id = " . $ilDB->quote($style_id, "integer");
565 $ilDB->manipulate($q);
566 }
567
568 public static function _lookupUpToDate(int $a_id): bool
569 {
570 global $DIC;
571
572 $ilDB = $DIC->database();
573
574 $q = "SELECT uptodate FROM style_data " .
575 " WHERE id = " . $ilDB->quote($a_id, "integer");
576 $res = $ilDB->query($q);
577 $sty = $ilDB->fetchAssoc($res);
578
579 return (bool) $sty["uptodate"];
580 }
581
585 public static function _writeStandard(
586 int $a_id,
587 bool $a_std
588 ): void {
589 global $DIC;
590
591 $ilDB = $DIC->database();
592
593 $q = "UPDATE style_data SET standard = " .
594 $ilDB->quote((int) $a_std, "integer") .
595 " WHERE id = " . $ilDB->quote($a_id, "integer");
596 $ilDB->manipulate($q);
597 }
598
599 public static function _writeScope(int $a_id, int $a_scope): void
600 {
601 global $DIC;
602
603 $ilDB = $DIC->database();
604
605 $q = "UPDATE style_data SET category = " .
606 $ilDB->quote($a_scope, "integer") .
607 " WHERE id = " . $ilDB->quote($a_id, "integer");
608 $ilDB->manipulate($q);
609 }
610
614 public static function _lookupStandard(int $a_id): bool
615 {
616 global $DIC;
617
618 $ilDB = $DIC->database();
619
620 $q = "SELECT * FROM style_data " .
621 " WHERE id = " . $ilDB->quote($a_id, "integer");
622 $res = $ilDB->query($q);
623 $sty = $ilDB->fetchAssoc($res);
624
625 return (bool) ($sty["standard"] ?? false);
626 }
627
628 public static function _writeActive(int $a_id, bool $a_active): void
629 {
630 global $DIC;
631
632 $ilDB = $DIC->database();
633
634 $q = "UPDATE style_data SET active = " .
635 $ilDB->quote((int) $a_active, "integer") .
636 " WHERE id = " . $ilDB->quote($a_id, "integer");
637 $ilDB->manipulate($q);
638 }
639
643 public static function _lookupActive(int $a_id): bool
644 {
645 global $DIC;
646
647 $ilDB = $DIC->database();
648
649 $q = "SELECT * FROM style_data " .
650 " WHERE id = " . $ilDB->quote($a_id, "integer");
651 $res = $ilDB->query($q);
652 $sty = $ilDB->fetchAssoc($res);
653
654 return (bool) $sty["active"];
655 }
656
661 public static function _getStandardStyles(
662 bool $a_exclude_default_style = false,
663 bool $a_include_deactivated = false,
664 int $a_scope = 0
665 ): array {
666 global $DIC;
667
668 $ilDB = $DIC->database();
669 $ilSetting = $DIC->settings();
670 $tree = $DIC->repositoryTree();
671
672 $default_style = $ilSetting->get("default_content_style_id");
673
674 $and_str = "";
675 if (!$a_include_deactivated) {
676 $and_str = " AND active = 1";
677 }
678
679 $q = "SELECT * FROM style_data " .
680 " WHERE standard = 1" . $and_str;
681 $res = $ilDB->query($q);
682 $styles = array();
683 while ($sty = $ilDB->fetchAssoc($res)) {
684 if (!$a_exclude_default_style || $default_style != $sty["id"]) {
685 // check scope
686 if ($a_scope > 0 && $sty["category"] > 0) {
687 if ($tree->isInTree((int) $sty["category"]) &&
688 $tree->isInTree($a_scope)) {
689 $path = $tree->getPathId($a_scope);
690 if (!in_array((int) $sty["category"], $path)) {
691 continue;
692 }
693 }
694 }
695 $styles[(int) $sty["id"]] = ilObject::_lookupTitle((int) $sty["id"]);
696 }
697 }
698
699 return $styles;
700 }
701
702
708 public static function _getClonableContentStyles(): array
709 {
710 global $DIC;
711
712 $ilAccess = $DIC->access();
713 $ilDB = $DIC->database();
714
715 $clonable_styles = array();
716
717 $q = "SELECT * FROM style_data";
718 $style_set = $ilDB->query($q);
719 while ($style_rec = $ilDB->fetchAssoc($style_set)) {
720 $clonable = false;
721 if ($style_rec["standard"] == 1) {
722 if ($style_rec["active"] == 1) {
723 $clonable = true;
724 }
725 } else {
726 $obj_ids = ilObjContentObject::_lookupContObjIdByStyleId((int) $style_rec["id"]);
727 if (count($obj_ids) == 0) {
728 $obj_ids = self::lookupObjectForStyle((int) $style_rec["id"]);
729 }
730 foreach ($obj_ids as $id) {
731 $ref = ilObject::_getAllReferences((int) $id);
732 foreach ($ref as $ref_id) {
733 if ($ilAccess->checkAccess("write", "", $ref_id)) {
734 $clonable = true;
735 }
736 }
737 }
738 }
739 if ($clonable) {
740 $clonable_styles[(int) $style_rec["id"]] =
741 ilObject::_lookupTitle((int) $style_rec["id"]);
742 }
743 }
744
745 asort($clonable_styles);
746
747 return $clonable_styles;
748 }
749
750 public static function _getBasicStyleDom(): DOMDocument
751 {
752 if (!is_object(self::$basic_style_dom)) {
753 self::$basic_style_dom = new DOMDocument();
754 self::$basic_style_dom->load(self::$basic_style_file);
755 }
756
757 return self::$basic_style_dom;
758 }
759
760 public static function getBasicImageDir(): string
761 {
762 return self::$basic_style_image_dir;
763 }
764
765
769 public function create(
770 int $a_from_style = 0,
771 bool $a_import_mode = false
772 ): int {
773 global $DIC;
774
775 $ilDB = $this->db;
776
777 $id = parent::create();
778
779 $service = $DIC->contentStyle()
780 ->internal();
781 $access_manager = $service->domain()->access(
782 0,
783 $DIC->user()->getId()
784 );
785 $access_manager->enableWrite(true);
786 $color_manager = $service->domain()->color($this->getId(), $access_manager);
787
788 if ($a_from_style == 0) {
789 if (!$a_import_mode) {
790 throw new Exception("Can't create style without a from style in non-import mode.");
791 } else {
792 // add style_data record
793 $q = "INSERT INTO style_data (id, uptodate, category) VALUES " .
794 "(" . $ilDB->quote($this->getId(), "integer") . ", 0," .
795 $ilDB->quote($this->getScope(), "integer") . ")";
796 $ilDB->manipulate($q);
797 }
798 } else {
799 // get style parameter records
800 $def = array();
801 $q = "SELECT * FROM style_parameter WHERE style_id = " .
802 $ilDB->quote($a_from_style, "integer");
803 $par_set = $ilDB->query($q);
804 while ($par_rec = $ilDB->fetchAssoc($par_set)) {
805 $def[] = array("tag" => $par_rec["tag"], "class" => $par_rec["class"],
806 "parameter" => $par_rec["parameter"], "value" => $par_rec["value"],
807 "type" => $par_rec["type"], "mq_id" => $par_rec["mq_id"], "custom" => $par_rec["custom"]);
808 }
809
810 $char_repo = $this->repo->characteristic();
811 $char_repo->cloneAllFromStyle($a_from_style, $this->getId());
812
813
814 // copy media queries
815 $from_style = new ilObjStyleSheet($a_from_style);
816 $mqs = $from_style->getMediaQueries();
817 $mq_mapping = array();
818 foreach ($mqs as $mq) {
819 $nid = $this->addMediaQuery($mq["mquery"]);
820 $mq_mapping[$mq["id"]] = $nid;
821 }
822
823 // default style settings
824 foreach ($def as $sty) {
825 $id = $ilDB->nextId("style_parameter");
826 $q = "INSERT INTO style_parameter (id, style_id, tag, class, parameter, value, type, mq_id, custom) VALUES " .
827 "(" .
828 $ilDB->quote($id, "integer") . "," .
829 $ilDB->quote($this->getId(), "integer") . "," .
830 $ilDB->quote($sty["tag"], "text") . "," .
831 $ilDB->quote($sty["class"], "text") . "," .
832 $ilDB->quote($sty["parameter"], "text") . "," .
833 $ilDB->quote($sty["value"], "text") . "," .
834 $ilDB->quote($sty["type"], "text") . "," .
835 $ilDB->quote((int) ($mq_mapping[$sty["mq_id"]] ?? 0), "integer") . "," .
836 $ilDB->quote($sty["custom"], "integer") .
837 ")";
838 $ilDB->manipulate($q);
839 }
840
841 // add style_data record
842 $q = "INSERT INTO style_data (id, uptodate, category) VALUES " .
843 "(" . $ilDB->quote($this->getId(), "integer") . ", 0," .
844 $ilDB->quote($this->getScope(), "integer") . ")";
845 $ilDB->manipulate($q);
846
847 // copy images
848 $this->domain->style($this->getId())->cloneResourceContainer($from_style->getId());
849 // copy colors
850 $colors = $from_style->getColors();
851 foreach ($colors as $c) {
852 $color_manager->addColor($c["name"], $c["code"]);
853 }
854
855 // copy templates
857 foreach ($tcts as $tct => $v) {
858 $templates = $from_style->getTemplates($tct);
859 foreach ($templates as $t) {
860 $this->addTemplate($tct, $t["name"], $t["classes"]);
861 }
862 }
863 }
864
865 $this->read();
866 if (!$a_import_mode) {
867 $this->writeCSSFile();
868 }
869
870 return $id;
871 }
872
876 public function characteristicExists(
877 string $a_char,
878 string $a_style_type
879 ): bool {
880 $ilDB = $this->db;
881
882 $set = $ilDB->queryF(
883 "SELECT style_id FROM style_char WHERE style_id = %s AND characteristic = %s AND type = %s",
884 array("integer", "text", "text"),
885 array($this->getId(), $a_char, $a_style_type)
886 );
887 if ($ilDB->fetchAssoc($set)) {
888 return true;
889 }
890 return false;
891 }
892
893 public function addCharacteristic(
894 string $a_type,
895 string $a_char,
896 bool $a_hidden = false,
897 int $order_nr = 0,
898 bool $outdated = false
899 ): void {
900 $ilDB = $this->db;
901
902 // delete characteristic record
903 $ilDB->insert("style_char", [
904 "style_id" => ["integer", $this->getId()],
905 "type" => ["text", $a_type],
906 "characteristic" => ["text", $a_char],
907 "hide" => ["integer", (int) $a_hidden],
908 "outdated" => ["integer", (int) $outdated],
909 "order_nr" => ["integer", $order_nr]
910 ]);
911
912 $this->setUpToDate(false);
913 $this->_writeUpToDate($this->getId(), false);
914 }
915
919 public function getCharacteristics(
920 string $a_type = "",
921 bool $a_no_hidden = false,
922 bool $a_include_core = true
923 ): array {
924 $chars = array();
925
926 if ($a_type == "") {
927 $chars = $this->chars;
928 }
929 if (isset($this->chars_by_type[$a_type])) {
930 foreach ($this->chars_by_type[$a_type] as $c) {
931 if ($a_include_core || !self::isCoreStyle($a_type, $c)) {
932 $chars[] = $c;
933 }
934 }
935 }
936
937 if ($a_no_hidden) {
938 foreach ($chars as $k => $char) {
939 if ($a_type == "" && $this->hidden_chars[$char["type"] . ":" . $char["class"]]) {
940 unset($chars[$k]);
941 } elseif ($this->hidden_chars[$a_type . ":" . $char] ?? false) {
942 unset($chars[$k]);
943 }
944 }
945 }
946
947 return $chars;
948 }
949
950 public function setCharacteristics(array $a_chars): void
951 {
952 $this->chars = $a_chars;
953 }
954
958 public function saveHideStatus(
959 string $a_type,
960 string $a_char,
961 bool $a_hide
962 ): void {
963 $ilDB = $this->db;
964
965 $ilDB->manipulate(
966 "UPDATE style_char SET " .
967 " hide = " . $ilDB->quote((int) $a_hide, "integer") .
968 " WHERE style_id = " . $ilDB->quote($this->getId(), "integer") . " AND " .
969 " type = " . $ilDB->quote($a_type, "text") . " AND " .
970 " characteristic = " . $ilDB->quote($a_char, "text")
971 );
972 }
973
977 public function getHideStatus(
978 string $a_type,
979 string $a_char
980 ): bool {
981 $ilDB = $this->db;
982
983 $set = $ilDB->query(
984 "SELECT hide FROM style_char " .
985 " WHERE style_id = " . $ilDB->quote($this->getId(), "integer") . " AND " .
986 " type = " . $ilDB->quote($a_type, "text") . " AND " .
987 " characteristic = " . $ilDB->quote($a_char, "text")
988 );
989 $rec = $ilDB->fetchAssoc($set);
990
991 return (bool) ($rec["hide"] ?? false);
992 }
993
997 public function ilClone(): int
998 {
1000
1001 $lng->loadLanguageModule("style");
1002
1003 $new_obj = new ilObjStyleSheet();
1004 $new_obj->setTitle($this->getTitle() . " (" . $lng->txt("sty_acopy") . ")");
1005 $new_obj->setType($this->getType());
1006 $new_obj->setDescription($this->getDescription());
1007 $new_obj->create($this->getId());
1008
1009 $new_obj->writeStyleSetting(
1010 "disable_auto_margins",
1011 $this->lookupStyleSetting("disable_auto_margins")
1012 );
1013
1014 return $new_obj->getId();
1015 }
1016
1020 public function copyImagesToDir(string $a_target): void
1021 {
1022 ilFileUtils::rCopy($this->getImagesDirectory(), $a_target);
1023 }
1024
1034 public function addParameter(
1035 string $a_tag,
1036 string $a_par,
1037 string $a_type,
1038 int $a_mq_id = 0,
1039 bool $a_custom = false
1040 ): void {
1041 $ilDB = $this->db;
1042
1043 $avail_params = $this->getAvailableParameters();
1044 $tag = explode(".", $a_tag);
1045 $value = $avail_params[$a_par][0];
1046 $id = $ilDB->nextId("style_parameter");
1047 $q = "INSERT INTO style_parameter (id,style_id, type, tag, class, parameter, value, mq_id, custom) VALUES " .
1048 "(" .
1049 $ilDB->quote($id, "integer") . "," .
1050 $ilDB->quote($this->getId(), "integer") . "," .
1051 $ilDB->quote($a_type, "text") . "," .
1052 $ilDB->quote($tag[0], "text") . "," .
1053 $ilDB->quote($tag[1], "text") . "," .
1054 $ilDB->quote($a_par, "text") . "," .
1055 $ilDB->quote($value, "text") . "," .
1056 $ilDB->quote($a_mq_id, "integer") . "," .
1057 $ilDB->quote($a_custom, "integer") .
1058 ")";
1059 $ilDB->manipulate($q);
1060 $this->read();
1061 $this->writeCSSFile();
1062 }
1063
1068 public function createImagesDirectory(): void
1069 {
1071 }
1072
1077 public static function _createImagesDirectory(
1078 int $a_style_id
1079 ): void {
1080 global $DIC;
1081
1082 $ilErr = $DIC["ilErr"];
1083
1084 $sty_data_dir = ilFileUtils::getWebspaceDir() . "/sty";
1085 if (!is_dir($sty_data_dir)) {
1086 ilFileUtils::makeDir($sty_data_dir);
1087 }
1088 if (!is_writable($sty_data_dir)) {
1089 $ilErr->raiseError("Style data directory (" . $sty_data_dir
1090 . ") not writeable.", $ilErr->FATAL);
1091 }
1092
1093 $style_dir = $sty_data_dir . "/sty_" . $a_style_id;
1094 if (!is_dir($style_dir)) {
1095 ilFileUtils::makeDir($style_dir);
1096 }
1097 if (!is_dir($style_dir)) {
1098 $ilErr->raiseError("Creation of style directory failed (" .
1099 $style_dir . ").", $ilErr->FATAL);
1100 }
1101
1102 // create images subdirectory
1103 $im_dir = $style_dir . "/images";
1104 if (!is_dir($im_dir)) {
1105 ilFileUtils::makeDir($im_dir);
1106 }
1107 if (!is_dir($im_dir)) {
1108 $ilErr->raiseError("Creation of Import Directory failed (" .
1109 $im_dir . ").", $ilErr->FATAL);
1110 }
1111
1112 // create thumbnails directory
1113 $thumb_dir = $style_dir . "/images/thumbnails";
1114 ilFileUtils::makeDir($thumb_dir);
1115 if (!is_dir($thumb_dir)) {
1116 $ilErr->raiseError("Creation of Import Directory failed (" .
1117 $thumb_dir . ").", $ilErr->FATAL);
1118 }
1119 }
1120
1121 public function getImagesDirectory(): string
1122 {
1124 }
1125
1126 public static function _getImagesDirectory(int $a_style_id): string
1127 {
1128 return ilFileUtils::getWebspaceDir() . "/sty/sty_" . $a_style_id .
1129 "/images";
1130 }
1131
1132 public function getThumbnailsDirectory(): string
1133 {
1134 return $this->getImagesDirectory() .
1135 "/thumbnails";
1136 }
1137
1141 public function deleteParameter(int $a_id): void
1142 {
1143 $ilDB = $this->db;
1144
1145 $q = "DELETE FROM style_parameter WHERE id = " .
1146 $ilDB->quote($a_id, "integer");
1147 $ilDB->query($q);
1148 }
1149
1150
1158 public function deleteCustomStylePars(
1159 string $a_tag,
1160 string $a_class,
1161 string $a_type,
1162 int $a_mq_id = 0
1163 ): void {
1164 $ilDB = $this->db;
1165
1166 $q = "DELETE FROM style_parameter WHERE " .
1167 " style_id = " . $ilDB->quote($this->getId(), "integer") . " AND " .
1168 " tag = " . $ilDB->quote($a_tag, "text") . " AND " .
1169 " class = " . $ilDB->quote($a_class, "text") . " AND " .
1170 " mq_id = " . $ilDB->quote($a_mq_id, "integer") . " AND " .
1171 " custom = " . $ilDB->quote(1, "integer") . " AND " .
1172 " " . $ilDB->equals("type", $a_type, "text", true);
1173
1174 $ilDB->manipulate($q);
1175 }
1176
1180 public function deleteStyleParOfChar(
1181 string $a_type,
1182 string $a_class
1183 ): void {
1184 $ilDB = $this->db;
1185
1186 $q = "DELETE FROM style_parameter WHERE " .
1187 " style_id = " . $ilDB->quote($this->getId(), "integer") . " AND " .
1188 " class = " . $ilDB->quote($a_class, "text") . " AND " .
1189 " " . $ilDB->equals("type", $a_type, "text", true);
1190
1191 $ilDB->manipulate($q);
1192 }
1193
1194
1195 public function delete(): bool
1196 {
1197 $ilDB = $this->db;
1198
1199 // delete object
1200 parent::delete();
1201
1202 // check whether this style is global default
1203 $def_style = $this->ilias->getSetting("default_content_style_id");
1204 if ($def_style == $this->getId()) {
1205 $this->ilias->deleteSetting("default_content_style_id");
1206 }
1207
1208 // check whether this style is global fixed
1209 $fixed_style = $this->ilias->getSetting("fixed_content_style_id");
1210 if ($fixed_style == $this->getId()) {
1211 $this->ilias->deleteSetting("fixed_content_style_id");
1212 }
1213
1214 // delete style parameter
1215 $q = "DELETE FROM style_parameter WHERE style_id = " .
1216 $ilDB->quote($this->getId(), "integer");
1217 $ilDB->manipulate($q);
1218
1219 // delete style file
1220 $css_file_name = ilFileUtils::getWebspaceDir() . "/css/style_" . $this->getId() . ".css";
1221 if (is_file($css_file_name)) {
1222 unlink($css_file_name);
1223 }
1224
1225 // delete media queries
1226 $ilDB->manipulate(
1227 "DELETE FROM sty_media_query WHERE " .
1228 " style_id = " . $ilDB->quote($this->getId(), "integer")
1229 );
1230
1231 // delete entries in learning modules
1233
1234 // delete style data record
1235 $q = "DELETE FROM style_data WHERE id = " .
1236 $ilDB->quote($this->getId(), "integer");
1237 $ilDB->manipulate($q);
1238
1239 return true;
1240 }
1241
1242
1246 public function read(): void
1247 {
1248 $ilDB = $this->db;
1249
1250 parent::read();
1251
1252 $q = "SELECT * FROM style_parameter WHERE style_id = " .
1253 $ilDB->quote($this->getId(), "integer") . " ORDER BY tag, class, type, mq_id ";
1254 $style_set = $ilDB->query($q);
1255 $ctag = "";
1256 $cclass = "";
1257 $ctype = "";
1258 $cmq_id = 0;
1259 $this->style = array();
1260 // workaround for bug #17586, see also http://stackoverflow.com/questions/3066356/multiple-css-classes-properties-overlapping-based-on-the-order-defined
1261 // e.g. ha_iheada must be written after ha_ihead, since they are acting on the same dom node
1262 // styles that must be added at the end
1263 $this->end_styles = array();
1264 $tag = null;
1265 while ($style_rec = $ilDB->fetchAssoc($style_set)) {
1266 if ($style_rec["tag"] != $ctag || $style_rec["class"] != $cclass
1267 || $style_rec["type"] != $ctype || $style_rec["mq_id"] != $cmq_id) {
1268 // add current tag array to style array
1269 if (is_array($tag)) {
1270 if (in_array($ctype, array("ha_iheada", "va_iheada"))) {
1271 $this->end_styles[] = $tag;
1272 } else {
1273 $this->style[] = $tag;
1274 }
1275 }
1276 $tag = array();
1277 }
1278 $ctag = $style_rec["tag"];
1279 $cclass = $style_rec["class"];
1280 $ctype = $style_rec["type"];
1281 $cmq_id = $style_rec["mq_id"];
1282 $tag[] = $style_rec;
1283 // added $cmq_id
1284 $this->style_class[$ctype][$cclass][$cmq_id][$style_rec["parameter"]] = $style_rec["value"];
1285 }
1286 if (is_array($tag)) {
1287 $this->style[] = $tag;
1288 }
1289 foreach ($this->end_styles as $s) {
1290 $this->style[] = $s;
1291 }
1292 //var_dump($this->style_class);
1293 $q = "SELECT * FROM style_data WHERE id = " .
1294 $ilDB->quote($this->getId(), "integer");
1295 $res = $ilDB->query($q);
1296 $sty = $ilDB->fetchAssoc($res);
1297 $this->setUpToDate((bool) $sty["uptodate"]);
1298 $this->setScope((int) $sty["category"]);
1299
1300 // get style characteristics records
1301 $this->chars = array();
1302 $this->chars_by_type = array();
1303 $q = "SELECT * FROM style_char WHERE style_id = " .
1304 $ilDB->quote($this->getId(), "integer") .
1305 " ORDER BY type ASC, characteristic ASC";
1306 $par_set = $ilDB->query($q);
1307 while ($par_rec = $ilDB->fetchAssoc($par_set)) {
1308 $this->chars[] = array("type" => $par_rec["type"], "class" => $par_rec["characteristic"], "hide" => $par_rec["hide"]);
1309 $this->chars_by_type[$par_rec["type"]][] = $par_rec["characteristic"];
1310 if ($par_rec["hide"]) {
1311 $this->hidden_chars[$par_rec["type"] . ":" . $par_rec["characteristic"]] = true;
1312 }
1313 }
1314 // var_dump($this->style); exit;
1315 }
1316
1320 public function writeCSSFile(
1321 string $a_target_file = "",
1322 string $a_image_dir = ""
1323 ): void {
1324
1325 if (true) {
1326 $style_manager = $this->domain->style($this->getId());
1327 $style_manager->writeCss();
1328
1329 $this->setUpToDate();
1330 $this->_writeUpToDate($this->getId(), true);
1331
1332 return;
1333 }
1334
1335 $style = $this->getStyle();
1336
1337 if (!is_dir(ilFileUtils::getWebspaceDir() . "/css")) {
1339 }
1340
1341 if ($a_target_file == "") {
1342 $css_file_name = ilFileUtils::getWebspaceDir() . "/css/style_" . $this->getId() . ".css";
1343 } else {
1344 $css_file_name = $a_target_file;
1345 }
1346 $css_file = fopen($css_file_name, 'wb');
1347
1348 $page_background = "";
1349
1350 $mqs = array(array("mquery" => "", "id" => 0));
1351 foreach ($this->getMediaQueries() as $mq) {
1352 $mqs[] = $mq;
1353 }
1354
1355 // iterate all media queries
1356 foreach ($mqs as $mq) {
1357 if ($mq["id"] > 0) {
1358 fwrite($css_file, "@media " . $mq["mquery"] . " {\n");
1359 }
1360 reset($style);
1361 foreach ($style as $tag) {
1362 if ($tag[0]["mq_id"] != $mq["id"]) {
1363 continue;
1364 }
1365 if (is_int(strpos($tag[0]["class"], "before")) && !is_int(strpos($tag[0]["class"], "::before"))) {
1366 $tag[0]["class"] = str_replace(":before", "::before", $tag[0]["class"]);
1367 }
1368 fwrite($css_file, $tag[0]["tag"] . ".ilc_" . $tag[0]["type"] . "_" . $tag[0]["class"] . "\n");
1369 // echo "<br>";
1370 // var_dump($tag[0]["type"]);
1371 if ($tag[0]["tag"] == "td") {
1372 fwrite($css_file, ",th" . ".ilc_" . $tag[0]["type"] . "_" . $tag[0]["class"] . "\n");
1373 }
1374 if (in_array($tag[0]["tag"], array("h1", "h2", "h3"))) {
1375 fwrite($css_file, ",div.ilc_text_block_" . $tag[0]["class"] . "\n");
1376 fwrite($css_file, ",html.il-no-tiny-bg body#tinymce.ilc_text_block_" . $tag[0]["class"] . " > p \n");
1377 }
1378 if ($tag[0]["type"] == "section") { // sections can use a tags, if links are used
1379 fwrite($css_file, ",div a.ilc_" . $tag[0]["type"] . "_" . $tag[0]["class"] . "\n");
1380 }
1381 if ($tag[0]["type"] == "strong") {
1382 fwrite($css_file, ",span.ilc_text_inline_" . $tag[0]["class"] . "\n");
1383 }
1384 if ($tag[0]["type"] == "em") {
1385 fwrite($css_file, ",span.ilc_text_inline_" . $tag[0]["class"] . "\n");
1386 }
1387 if ($tag[0]["type"] == "text_block") {
1388 fwrite($css_file, ",html.il-no-tiny-bg body#tinymce.ilc_text_block_" . $tag[0]["class"] . " > p, #copg-editor-slate-content p.ilc_text_block_" . $tag[0]["class"] . "\n");
1389 }
1390 if ($tag[0]["class"] == "VAccordCntr") {
1391 fwrite($css_file, ",div.ilc_va_cntr_AccordCntr\n");
1392 }
1393 if ($tag[0]["class"] == "VAccordICntr") {
1394 fwrite($css_file, ",div.ilc_va_icntr_AccordICntr\n");
1395 }
1396 if ($tag[0]["class"] == "VAccordICont") {
1397 fwrite($css_file, ",div.ilc_va_icont_AccordICont\n");
1398 }
1399 if ($tag[0]["class"] == "VAccordIHead") {
1400 fwrite($css_file, ",div.ilc_va_ihead_AccordIHead\n");
1401 }
1402 if ($tag[0]["class"] == "VAccordIHead:hover") {
1403 fwrite($css_file, ",div.ilc_va_ihead_AccordIHead:hover\n");
1404 }
1405 if ($tag[0]["class"] == "VAccordIHeadActive") {
1406 fwrite($css_file, ",div.ilc_va_iheada_AccordIHeadActive\n");
1407 }
1408 if ($tag[0]["class"] == "VAccordIHeadActive:hover") {
1409 fwrite($css_file, ",div.ilc_va_iheada_AccordIHeadActive:hover\n");
1410 }
1411 fwrite($css_file, "{\n");
1412
1413 // collect table border attributes
1414 $t_border = array();
1415
1416 foreach ($tag as $par) {
1417 $cur_par = $par["parameter"] ?? '';
1418 $cur_val = $par["value"] ?? '';
1419
1420 // replace named colors
1421 if (is_int(strpos($cur_par, "color")) && substr(trim($cur_val), 0, 1) == "!") {
1422 $cur_val = $this->getColorCodeForName(substr($cur_val, 1));
1423 }
1424
1425 if ($tag[0]["type"] == "table" && is_int(strpos($par["parameter"], "border"))) {
1426 $t_border[$cur_par] = $cur_val;
1427 }
1428
1429 if (in_array($cur_par, array("background-image", "list-style-image"))) {
1430 if (is_int(strpos($cur_val, "/"))) { // external
1431 $cur_val = "url(" . $cur_val . ")";
1432 } else { // internal
1433 if ($a_image_dir == "") {
1434 $cur_val = "url(../sty/sty_" . $this->getId() . "/images/" . $cur_val . ")";
1435 } else {
1436 $cur_val = "url(" . $a_image_dir . "/" . $cur_val . ")";
1437 }
1438 }
1439 }
1440
1441 if ($cur_par == "opacity") {
1442 $cur_val = ((int) $cur_val) / 100;
1443 }
1444
1445 fwrite($css_file, "\t" . $cur_par . ": " . $cur_val . ";\n");
1446
1447 // IE6 fix for minimum height
1448 /*
1449 if ($cur_par == "min-height") {
1450 fwrite($css_file, "\t" . "height" . ": " . "auto !important" . ";\n");
1451 fwrite($css_file, "\t" . "height" . ": " . $cur_val . ";\n");
1452 }*/
1453
1454 // opacity fix
1455 if ($cur_par == "opacity") {
1456 fwrite($css_file, "\t" . '-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=' . ($cur_val * 100) . ')"' . ";\n");
1457 fwrite($css_file, "\t" . 'filter: alpha(opacity=' . ($cur_val * 100) . ')' . ";\n");
1458 fwrite($css_file, "\t" . '-moz-opacity: ' . $cur_val . ";\n");
1459 }
1460
1461 // transform fix
1462 if ($cur_par == "transform") {
1463 fwrite($css_file, "\t" . '-webkit-transform: ' . $cur_val . ";\n");
1464 fwrite($css_file, "\t" . '-moz-transform: ' . $cur_val . ";\n");
1465 fwrite($css_file, "\t" . '-ms-transform: ' . $cur_val . ";\n");
1466 }
1467
1468 // transform-origin fix
1469 if ($cur_par == "transform-origin") {
1470 fwrite($css_file, "\t" . '-webkit-transform-origin: ' . $cur_val . ";\n");
1471 fwrite($css_file, "\t" . '-moz-transform-origin: ' . $cur_val . ";\n");
1472 fwrite($css_file, "\t" . '-ms-transform-origin: ' . $cur_val . ";\n");
1473 }
1474
1475 // save page background
1476 if ($tag[0]["tag"] == "div" && $tag[0]["class"] == "Page"
1477 && $cur_par == "background-color") {
1478 $page_background = $cur_val;
1479 }
1480 }
1481 fwrite($css_file, "}\n");
1482 fwrite($css_file, "\n");
1483
1484 // use table border attributes for th td as well
1485 /* if ($tag[0]["type"] == "table")
1486 {
1487 if (count($t_border) > 0)
1488 {
1489 fwrite ($css_file, $tag[0]["tag"].".ilc_".$tag[0]["type"]."_".$tag[0]["class"]." th,".
1490 $tag[0]["tag"].".ilc_".$tag[0]["type"]."_".$tag[0]["class"]." td\n");
1491 fwrite ($css_file, "{\n");
1492 foreach ($t_border as $p => $v)
1493 {
1494 // fwrite ($css_file, "\t".$p.": ".$v.";\n");
1495 }
1496 fwrite ($css_file, "}\n");
1497 fwrite ($css_file, "\n");
1498 }
1499 }*/
1500 }
1501
1502 if ($page_background != "") {
1503 fwrite($css_file, "td.ilc_Page\n");
1504 fwrite($css_file, "{\n");
1505 fwrite($css_file, "\t" . "background-color: " . $page_background . ";\n");
1506 fwrite($css_file, "}\n");
1507 }
1508 if ($mq["id"] > 0) {
1509 fwrite($css_file, "}\n");
1510 }
1511 }
1512 fclose($css_file);
1513 // exit;
1514 $this->setUpToDate();
1515 $this->_writeUpToDate($this->getId(), true);
1516 }
1517
1524 public static function getEffectiveContentStyleId(
1525 int $a_style_id
1526 ): int {
1527 global $DIC;
1528
1529 $ilSetting = $DIC->settings();
1530
1531 // check global fixed content style
1532 $fixed_style = $ilSetting->get("fixed_content_style_id");
1533 if ($fixed_style > 0) {
1534 $a_style_id = (int) $fixed_style;
1535 }
1536
1537 // check global default style
1538 if ($a_style_id <= 0) {
1539 $a_style_id = (int) $ilSetting->get("default_content_style_id");
1540 }
1541
1542 if ($a_style_id > 0 && ilObject::_lookupType($a_style_id) === "sty") {
1543 return $a_style_id;
1544 }
1545
1546 return 0;
1547 }
1548
1549 public function getParametersOfClass(
1550 string $a_type,
1551 string $a_class,
1552 int $a_mq_id = 0
1553 ): array {
1554 if (is_array($this->style_class[$a_type][$a_class][$a_mq_id])) {
1555 return $this->style_class[$a_type][$a_class][$a_mq_id];
1556 }
1557 return array();
1558 }
1559
1560 public static function getExportContentStylePath(): string
1561 {
1562 return "content_style/style.css";
1563 }
1564
1569 public static function getContentStylePath(
1570 int $a_style_id,
1571 bool $add_random = true,
1572 bool $add_token = true
1573 ): string {
1574 global $DIC;
1575 $ilSetting = $DIC->settings();
1576
1577 $random = new \Random\Randomizer();
1578 $rand = $random->getInt(1, 999999);
1579
1580 // check global fixed content style
1581 $fixed_style = $ilSetting->get("fixed_content_style_id");
1582 if ($fixed_style > 0) {
1583 $a_style_id = (int) $fixed_style;
1584 }
1585
1586 // check global default style
1587 if ($a_style_id <= 0) {
1588 $a_style_id = (int) $ilSetting->get("default_content_style_id");
1589 }
1590
1591 if ($a_style_id > 0 && ilObject::_exists($a_style_id)) {
1592 // check whether file is up to date
1593 if (!ilObjStyleSheet::_lookupUpToDate($a_style_id)) {
1594 $style = new ilObjStyleSheet($a_style_id);
1595 $style->writeCSSFile();
1596 }
1597
1598 $style_manager = $DIC->contentStyle()->internal()->domain()->style($a_style_id);
1599 $path = $style_manager->getPath();
1600 return $path;
1601 } else { // todo: work this out
1602 return "./components/ILIAS/COPage/css/content.css";
1603 }
1604 }
1605
1606 public static function getContentPrintStyle(): string
1607 {
1608 return "./components/ILIAS/COPage/css/print_content.css";
1609 }
1610
1611 public static function getSyntaxStylePath(): string
1612 {
1613 return "./components/ILIAS/COPage/css/syntaxhighlight.css";
1614 }
1615
1616 public static function getBaseContentStylePath(): string
1617 {
1618 return "./components/ILIAS/COPage/css/content_base.css";
1619 }
1620
1621 public function update(): bool
1622 {
1623 $ilDB = $this->db;
1624
1625 parent::update();
1626 $this->read(); // this could be done better
1627 $this->writeCSSFile();
1628
1629 $q = "UPDATE style_data " .
1630 "SET category = " . $ilDB->quote($this->getScope(), "integer") .
1631 " WHERE id = " . $ilDB->quote($this->getId(), "integer");
1632 $ilDB->manipulate($q);
1633
1634 return true;
1635 }
1636
1640 public function updateStyleParameter(
1641 int $a_id,
1642 string $a_value
1643 ): void {
1644 $ilDB = $this->db;
1645
1646 $q = "UPDATE style_parameter SET VALUE = " .
1647 $ilDB->quote($a_value, "text") . " WHERE id = " .
1648 $ilDB->quote($a_id, "integer");
1649 $style_set = $ilDB->manipulate($q);
1650 }
1651
1652 public function getStyle(): array
1653 {
1654 return $this->style;
1655 }
1656
1657 public function setStyle(array $a_style): void
1658 {
1659 $this->style = $a_style;
1660 }
1661
1662 public function handleXmlString(string $a_str): string
1663 {
1664 return str_replace("&", "&amp;", $a_str);
1665 }
1666
1671 public function getXML(): string
1672 {
1673 $xml = "<StyleSheet>\n";
1674
1675 // title and description
1676 $xml .= "<Title>" . $this->handleXmlString($this->getTitle()) . "</Title>";
1677 $xml .= "<Description>" . $this->handleXmlString($this->getDescription()) . "</Description>\n";
1678
1679 // style classes
1680 foreach ($this->chars as $char) {
1681 $xml .= "<Style Tag=\"" . ilObjStyleSheet::_determineTag($char["type"]) .
1682 "\" Type=\"" . $char["type"] . "\" Class=\"" . $char["class"] . "\">\n";
1683 foreach ($this->style as $style) {
1684 if ($style[0]["type"] == $char["type"] && $style[0]["class"] == $char["class"]) {
1685 foreach ($style as $tag) {
1686 $xml .= "<StyleParameter Name=\"" . $tag["parameter"] . "\" Value=\"" . $tag["value"] . "\" Custom=\"" . $tag["custom"] . "\" />\n";
1687 }
1688 }
1689 }
1690 $xml .= "</Style>\n";
1691 }
1692
1693 // colors
1694 foreach ($this->getColors() as $color) {
1695 $xml .= "<StyleColor Name=\"" . $color["name"] . "\" Code=\"" . $color["code"] . "\"/>\n";
1696 }
1697
1698 // templates
1700 foreach ($tcts as $tct => $v) {
1701 $ts = $this->getTemplates($tct);
1702
1703 foreach ($ts as $t) {
1704 $xml .= "<StyleTemplate Type=\"" . $tct . "\" Name=\"" . $t["name"] . "\">\n";
1705 foreach ($t["classes"] as $ct => $c) {
1706 if ($c != "") {
1707 $xml .= "<StyleTemplateClass ClassType=\"" . $ct . "\" Class=\"" . $c . "\"/>\n";
1708 }
1709 }
1710 $xml .= "</StyleTemplate>\n";
1711 }
1712 }
1713
1714
1715 $xml .= "</StyleSheet>";
1716 //echo "<pre>".htmlentities($xml)."</pre>"; exit;
1717 return $xml;
1718 }
1719
1720 public function createExportDirectory(): string
1721 {
1722 $sty_data_dir = ilFileUtils::getDataDir() . "/sty";
1723 ilFileUtils::makeDir($sty_data_dir);
1724 if (!is_writable($sty_data_dir)) {
1725 $this->ilias->raiseError("Style data directory (" . $sty_data_dir
1726 . ") not writeable.", $this->ilias->error_obj->FATAL);
1727 }
1728
1729 $style_dir = $sty_data_dir . "/sty_" . $this->getId();
1730 ilFileUtils::makeDir($style_dir);
1731 if (!is_dir($style_dir)) {
1732 $this->ilias->raiseError("Creation of style directory failed (" .
1733 $style_dir . ").", $this->ilias->error_obj->FATAL);
1734 }
1735
1736 // create export subdirectory
1737 $ex_dir = $style_dir . "/export";
1738 ilFileUtils::makeDir($ex_dir);
1739 if (!is_dir($ex_dir)) {
1740 $this->ilias->raiseError("Creation of Import Directory failed (" .
1741 $ex_dir . ").", $this->ilias->error_obj->FATAL);
1742 }
1743
1744 return $ex_dir;
1745 }
1746
1747 public function cleanExportDirectory(): void
1748 {
1749 $sty_data_dir = ilFileUtils::getDataDir() . "/sty";
1750 $style_dir = $sty_data_dir . "/sty_" . $this->getId();
1751 // create export subdirectory
1752 $ex_dir = $style_dir . "/export";
1753
1754 if (is_dir($ex_dir)) {
1755 ilFileUtils::delDir($ex_dir, true);
1756 }
1757 }
1758
1760 {
1761 $ex_dir = $this->createExportDirectory();
1762 $ex_sub_dir = $ex_dir . "/" . $this->getExportSubDir();
1763 ilFileUtils::makeDir($ex_sub_dir);
1764 if (!is_writable($ex_sub_dir)) {
1765 $this->ilias->raiseError("Style data directory (" . $ex_sub_dir
1766 . ") not writeable.", $this->ilias->error_obj->FATAL);
1767 }
1768 $ex_sub_images_dir = $ex_sub_dir . "/images";
1769 ilFileUtils::makeDir($ex_sub_images_dir);
1770 if (!is_writable($ex_sub_images_dir)) {
1771 $this->ilias->raiseError("Style data directory (" . $ex_sub_images_dir
1772 . ") not writeable.", $this->ilias->error_obj->FATAL);
1773 }
1774 }
1775
1779 public function setExportSubDir(string $a_dir): void
1780 {
1781 $this->export_sub_dir = $a_dir;
1782 }
1783
1787 public function getExportSubDir(): string
1788 {
1789 if ($this->export_sub_dir == "") {
1790 return "sty_" . $this->getId();
1791 } else {
1792 return $this->export_sub_dir;
1793 }
1794 }
1795
1802 public function export(): string
1803 {
1804 $this->cleanExportDirectory();
1805 $ex_dir = $this->createExportDirectory();
1806 $this->createExportSubDirectory();
1807 $this->exportXML($ex_dir . "/" . $this->getExportSubDir());
1808 //echo "-".$this->getImagesDirectory()."-".$ex_dir."/".$this->getExportSubDir()."/images"."-";
1810 $this->getImagesDirectory(),
1811 $ex_dir . "/" . $this->getExportSubDir() . "/images"
1812 );
1813 if (is_file($ex_dir . "/" . $this->getExportSubDir() . ".zip")) {
1814 unlink($ex_dir . "/" . $this->getExportSubDir() . ".zip");
1815 }
1817 $ex_dir . "/" . $this->getExportSubDir(),
1818 $ex_dir . "/" . $this->getExportSubDir() . ".zip"
1819 );
1820
1821 return $ex_dir . "/" . $this->getExportSubDir() . ".zip";
1822 }
1823
1827 public function exportXML(string $a_dir): void
1828 {
1829 $file = $a_dir . "/style.xml";
1830
1831 // open file
1832 if (!($fp = fopen($file, 'wb'))) {
1833 die("<strong>Error</strong>: Could not open \"" . $file . "\" for writing" .
1834 " in <strong>" . __FILE__ . "</strong> on line <strong>" . __LINE__ . "</strong><br />");
1835 }
1836
1837 // set file permissions
1838 chmod($file, 0770);
1839
1840 // write xml data into the file
1841 fwrite($fp, $this->getXML());
1842
1843 // close file
1844 fclose($fp);
1845 }
1846
1847 public function createImportDirectory(): string
1848 {
1849 $sty_data_dir = ilFileUtils::getDataDir() . "/sty";
1850 ilFileUtils::makeDir($sty_data_dir);
1851 if (!is_writable($sty_data_dir)) {
1852 $this->ilias->raiseError("Style data directory (" . $sty_data_dir
1853 . ") not writeable.", $this->ilias->error_obj->FATAL);
1854 }
1855
1856 $style_dir = $sty_data_dir . "/sty_" . $this->getId();
1857 ilFileUtils::makeDir($style_dir);
1858 if (!is_dir($style_dir)) {
1859 $this->ilias->raiseError("Creation of style directory failed (" .
1860 $style_dir . ").", $this->ilias->error_obj->FATAL);
1861 }
1862
1863 // create import subdirectory
1864 $im_dir = $style_dir . "/import";
1865 ilFileUtils::makeDir($im_dir);
1866 if (!is_dir($im_dir)) {
1867 $this->ilias->raiseError("Creation of Import Directory failed (" .
1868 $im_dir . ").", $this->ilias->error_obj->FATAL);
1869 }
1870
1871 return $im_dir;
1872 }
1873
1881 public function import($a_file): void
1882 {
1883 parent::create();
1884 $subdir = "";
1885 $im_dir = $this->createImportDirectory();
1886
1887 // handle uploaded files
1888 if (is_array($a_file)) {
1890 $a_file["tmp_name"],
1891 $a_file["name"],
1892 $im_dir . "/" . $a_file["name"]
1893 );
1894 $file_name = $a_file["name"];
1895 } else { // handle not directly uploaded files
1896 $pi = pathinfo($a_file);
1897 $file_name = $pi["basename"];
1898 copy($a_file, $im_dir . "/" . $file_name);
1899 }
1900 $file = pathinfo($file_name);
1901
1902 // unzip file
1903 if (strtolower($file["extension"]) == "zip") {
1904 $this->domain->resources()->zip()->unzipFile($im_dir . "/" . $file_name);
1905 $subdir = basename($file["basename"], "." . $file["extension"]);
1906 if (!is_dir($im_dir . "/" . $subdir)) {
1907 $subdir = "style"; // check style subdir
1908 }
1909 $xml_file = $im_dir . "/" . $subdir . "/style.xml";
1910 } else { // handle xml file directly (old style)
1911 $xml_file = $im_dir . "/" . $file_name;
1912 }
1913
1914 // load information from xml file
1915 //echo "-$xml_file-";
1916 $this->createFromXMLFile($xml_file, true);
1917
1919 $this->read();
1920 $this->writeCSSFile();
1921 }
1922
1927 public function createFromXMLFile(
1928 string $a_file,
1929 bool $a_skip_parent_create = false
1930 ): void {
1931 $ilDB = $this->db;
1932
1933 $this->is_3_10_skin = false;
1934
1935 if (!$a_skip_parent_create) {
1936 parent::create();
1937 }
1938 $importParser = new ilStyleImportParser($a_file, $this);
1939 $importParser->startParsing();
1940
1941 // store style parameter
1942 foreach ($this->style as $style) {
1943 foreach ($style as $tag) {
1944 $id = $ilDB->nextId("style_parameter");
1945
1946 // migrate old table PageFrame/PageContainer to div
1947 if (in_array($tag["class"], array("PageFrame", "PageContainer")) &&
1948 $tag["tag"] == "table") {
1949 $tag["tag"] = "div";
1950 if ($tag["parameter"] == "width" && $tag["value"] == "100%") {
1951 continue;
1952 }
1953 }
1954
1955 if ($tag["type"] === "text_block" && $tag["tag"] === "div") {
1956 $tag["tag"] = "p";
1957 }
1958
1959 $q = "INSERT INTO style_parameter (id,style_id, tag, class, parameter, type, value, custom) VALUES " .
1960 "(" .
1961 $ilDB->quote($id, "integer") . "," .
1962 $ilDB->quote($this->getId(), "integer") . "," .
1963 $ilDB->quote($tag["tag"], "text") . "," .
1964 $ilDB->quote($tag["class"], "text") . "," .
1965 $ilDB->quote($tag["parameter"], "text") . "," .
1966 $ilDB->quote($tag["type"], "text") . "," .
1967 $ilDB->quote($tag["value"], "text") . "," .
1968 $ilDB->quote((bool) $tag["custom"], "integer") .
1969 ")";
1970 $ilDB->manipulate($q);
1971 }
1972 }
1973
1974 // store characteristics
1975 $this->is_3_10_skin = true;
1976 foreach ($this->chars as $char) {
1977 if ($char["type"] != "") {
1978 $s = substr($char["class"], strlen($char["class"]) - 6);
1979 if ($s != ":hover") {
1980 $ilDB->replace(
1981 "style_char",
1982 array(
1983 "style_id" => array("integer", $this->getId()),
1984 "type" => array("text", $char["type"]),
1985 "characteristic" => array("text", ilStr::subStr($char["class"], 0, 30))),
1986 array("hide" => array("integer", 0))
1987 );
1988 $this->is_3_10_skin = false;
1989 }
1990 }
1991 }
1992
1993 // add style_data record
1994 $q = "INSERT INTO style_data (id, uptodate) VALUES " .
1995 "(" . $ilDB->quote($this->getId(), "integer") . ", 0)";
1996 $ilDB->manipulate($q);
1997
1998 $this->update();
1999 $this->read();
2000
2001 if ($this->is_3_10_skin) {
2002 $this->do_3_10_Migration();
2003 }
2004 //$this->writeCSSFile();
2005 }
2006
2010 public function getStyleParameterGroups(): array
2011 {
2012 $groups = array();
2013
2014 foreach (self::$parameter as $parameter => $props) {
2015 $groups[$props["group"]][] = $parameter;
2016 }
2017 return $groups;
2018 }
2019
2020 public static function _getStyleParameterInputType(string $par): string
2021 {
2022 $input = self::$parameter[$par]["input"];
2023 return $input;
2024 }
2025
2026 public static function _getStyleParameterSubPar(string $par): string
2027 {
2028 $subpar = self::$parameter[$par]["subpar"];
2029 return $subpar;
2030 }
2031
2032 public static function _getStyleParameters(
2033 string $a_tag = ""
2034 ): array {
2035 if ($a_tag == "") {
2036 return self::$parameter;
2037 }
2038 $par = array();
2039 foreach (self::$parameter as $k => $v) {
2040 if (isset(self::$filtered_groups[$v["group"]]) &&
2041 !in_array($a_tag, self::$filtered_groups[$v["group"]])) {
2042 continue;
2043 }
2044 $par[$k] = $v;
2045 }
2046 return $par;
2047 }
2048
2049 public static function _getFilteredGroups(): array
2050 {
2051 return self::$filtered_groups;
2052 }
2053
2054 public static function _getStyleParameterNumericUnits(
2055 bool $a_no_percentage = false
2056 ): array {
2057 if ($a_no_percentage) {
2058 return self::$num_unit_no_perc;
2059 }
2060 return self::$num_unit;
2061 }
2062
2063 public static function _getStyleParameterValues(
2064 string $par
2065 ): array {
2066 return self::$parameter[$par]["values"];
2067 }
2068
2069 public static function _getStyleSuperTypes(): array
2070 {
2071 return self::$style_super_types;
2072 }
2073
2074 public static function _isExpandable(string $a_type): bool
2075 {
2076 return in_array($a_type, self::$expandable_types);
2077 }
2078
2079 public static function _isHideable(string $a_type): bool
2080 {
2081 return in_array($a_type, self::$hideable_types);
2082 }
2083
2084 public static function _getStyleSuperTypeForType(
2085 string $a_type
2086 ): string {
2087 foreach (self::$style_super_types as $s => $t) {
2088 if (in_array($a_type, $t)) {
2089 return $s;
2090 }
2091 if ($a_type == $s) {
2092 return $s;
2093 }
2094 }
2095 return "";
2096 }
2097
2098 public static function _getCoreStyles(): array
2099 {
2100 $c_styles = array();
2101 foreach (self::$core_styles as $cstyle) {
2102 $c_styles[$cstyle["type"] . "." . ilObjStyleSheet::_determineTag($cstyle["type"]) . "." . $cstyle["class"]]
2103 = array("type" => $cstyle["type"],
2104 "tag" => ilObjStyleSheet::_determineTag($cstyle["type"]),
2105 "class" => $cstyle["class"]);
2106 }
2107 return $c_styles;
2108 }
2109
2110 public static function isCoreStyle(
2111 string $a_type,
2112 string $a_class
2113 ): bool {
2114 foreach (self::$core_styles as $s) {
2115 if ($s["type"] == $a_type && $s["class"] == $a_class) {
2116 return true;
2117 }
2118 }
2119 return false;
2120 }
2121
2125 public static function _getTemplateClassTypes(
2126 string $a_template_type = ""
2127 ): array {
2128 if ($a_template_type == "") {
2129 return self::$templates;
2130 }
2131 return self::$templates[$a_template_type];
2132 }
2133
2134 public static function _getPseudoClasses(string $tag): array
2135 {
2136 return self::$pseudo_classes[$tag] ?? [];
2137 }
2138
2139 // e.g. table, row_head > table_cell
2141 string $t,
2142 string $k
2143 ): string {
2144 return self::$templates[$t][$k];
2145 }
2146
2147 public static function _determineTag(string $a_type): string
2148 {
2149 return self::$assigned_tags[$a_type];
2150 }
2151
2152 public static function getAvailableParameters(): array
2153 {
2154 $pars = array();
2155 foreach (self::$parameter as $p => $v) {
2156 $pars[$p] = $v["values"];
2157 }
2158
2159 return $pars;
2160 }
2161
2165 public static function _addMissingStyleClassesToStyle(
2166 int $a_id
2167 ): void {
2168 $styles = array(array("id" => $a_id));
2170 }
2171
2177 ?array $a_styles = null
2178 ): void {
2179 global $DIC;
2180
2181 $ilDB = $DIC->database();
2182
2183 if (is_null($a_styles)) {
2184 $styles = ilObject::_getObjectsDataForType("sty");
2185 } else {
2186 $styles = $a_styles;
2187 }
2188 $core_styles = ilObjStyleSheet::_getCoreStyles();
2190
2191 // get all core image files
2192 $core_images = array();
2193 $core_dir = self::$basic_style_image_dir;
2194 if (is_dir($core_dir)) {
2195 $dir = opendir($core_dir);
2196 while ($file = readdir($dir)) {
2197 if (substr($file, 0, 1) != "." && is_file($core_dir . "/" . $file)) {
2198 $core_images[] = $file;
2199 }
2200 }
2201 }
2202
2203 foreach ($styles as $style) {
2204 $id = $style["id"];
2205
2206 foreach ($core_styles as $cs) {
2207 // check, whether core style class exists
2208 $set = $ilDB->queryF(
2209 "SELECT * FROM style_char WHERE style_id = %s " .
2210 "AND type = %s AND characteristic = %s",
2211 array("integer", "text", "text"),
2212 array($id, $cs["type"], $cs["class"])
2213 );
2214
2215 // if not, add core style class
2216 if (!($rec = $ilDB->fetchAssoc($set))) {
2217 $ilDB->manipulateF(
2218 "INSERT INTO style_char (style_id, type, characteristic) " .
2219 " VALUES (%s,%s,%s) ",
2220 array("integer", "text", "text"),
2221 array($id, $cs["type"], $cs["class"])
2222 );
2223
2224 $xpath = new DOMXPath($bdom);
2225 $par_nodes = $xpath->query("/StyleSheet/Style[@Tag = '" . $cs["tag"] . "' and @Type='" .
2226 $cs["type"] . "' and @Class='" . $cs["class"] . "']/StyleParameter");
2227 foreach ($par_nodes as $par_node) {
2228 // check whether style parameter exists
2229 $set = $ilDB->queryF(
2230 "SELECT * FROM style_parameter WHERE style_id = %s " .
2231 "AND type = %s AND class = %s AND tag = %s AND parameter = %s",
2232 array("integer", "text", "text", "text", "text"),
2233 array($id, $cs["type"], $cs["class"],
2234 $cs["tag"], $par_node->getAttribute("Name"))
2235 );
2236
2237 // if not, create style parameter
2238 if (!($ilDB->fetchAssoc($set))) {
2239 $spid = $ilDB->nextId("style_parameter");
2240 $st = $ilDB->manipulateF(
2241 "INSERT INTO style_parameter (id, style_id, type, class, tag, parameter, value) " .
2242 " VALUES (%s,%s,%s,%s,%s,%s,%s)",
2243 array("integer", "integer", "text", "text", "text", "text", "text"),
2244 array($spid, $id, $cs["type"], $cs["class"], $cs["tag"],
2245 $par_node->getAttribute("Name"), $par_node->getAttribute("Value"))
2246 );
2247 }
2248 }
2249 }
2250 }
2251
2252 // now check, whether some core image files are missing
2255 foreach ($core_images as $cim) {
2256 if (!is_file($imdir . "/" . $cim)) {
2257 copy($core_dir . "/" . $cim, $imdir . "/" . $cim);
2258 }
2259 }
2260 }
2261 }
2262
2263 //
2264 // Color management
2265 //
2266
2270 public function do_3_10_Migration(): void
2271 {
2272 $ilDB = $this->db;
2273
2274 $this->do_3_9_Migration($this->getId());
2275
2276 $this->do_3_10_CharMigration($this->getId());
2277
2278 // style_char: type for characteristic
2279 $st = $ilDB->prepareManip("UPDATE style_char SET type = ? WHERE characteristic = ?" .
2280 " AND style_id = ? ", array("text", "text", "integer"));
2281 $ilDB->execute($st, array("media_cont", "Media", $this->getId()));
2282 $ilDB->execute($st, array("media_caption", "MediaCaption", $this->getId()));
2283 $ilDB->execute($st, array("page_fn", "Footnote", $this->getId()));
2284 $ilDB->execute($st, array("page_nav", "LMNavigation", $this->getId()));
2285 $ilDB->execute($st, array("page_title", "PageTitle", $this->getId()));
2286 $ilDB->execute($st, array("page_cont", "Page", $this->getId()));
2287
2288 // style_parameter: type for class
2289 $st = $ilDB->prepareManip("UPDATE style_parameter SET type = ? WHERE class = ?" .
2290 " AND style_id = ? ", array("text", "text", "integer"));
2291 $ilDB->execute($st, array("media_cont", "Media", $this->getId()));
2292 $ilDB->execute($st, array("media_caption", "MediaCaption", $this->getId()));
2293 $ilDB->execute($st, array("page_fn", "Footnote", $this->getId()));
2294 $ilDB->execute($st, array("page_nav", "LMNavigation", $this->getId()));
2295 $ilDB->execute($st, array("page_title", "PageTitle", $this->getId()));
2296 $ilDB->execute($st, array("table", "Page", $this->getId()));
2297
2298 $st = $ilDB->prepareManip("UPDATE style_parameter SET tag = ? WHERE class = ?" .
2299 " AND style_id = ? ", array("text", "text", "integer"));
2300 $ilDB->execute($st, array("div", "MediaCaption", $this->getId()));
2301
2302 // style_char: characteristic for characteristic
2303 $st = $ilDB->prepareManip("UPDATE style_char SET characteristic = ? WHERE characteristic = ?" .
2304 " AND style_id = ? ", array("text", "text", "integer"));
2305 $ilDB->execute($st, array("MediaContainer", "Media", $this->getId()));
2306 $ilDB->execute($st, array("PageContainer", "Page", $this->getId()));
2307
2308 // style_parameter: class for class
2309 $st = $ilDB->prepareManip("UPDATE style_parameter SET class = ? WHERE class = ?" .
2310 " AND style_id = ? ", array("text", "text", "integer"));
2311 $ilDB->execute($st, array("MediaContainer", "Media", $this->getId()));
2312 $ilDB->execute($st, array("PageContainer", "Page", $this->getId()));
2313
2314 // force rewriting of container style
2315 $st = $ilDB->prepareManip("DELETE FROM style_char WHERE type = ?" .
2316 " AND style_id = ? ", array("text", "integer"));
2317 $ilDB->execute($st, array("page_cont", $this->getId()));
2318 $st = $ilDB->prepareManip("DELETE FROM style_parameter WHERE type = ?" .
2319 " AND style_id = ? ", array("text", "integer"));
2320 $ilDB->execute($st, array("page_cont", $this->getId()));
2321 }
2322
2328 public function do_3_10_CharMigration(int $a_id = 0): void
2329 {
2330 $ilDB = $this->db;
2331
2332 $add_str = "";
2333 if ($a_id > 0) {
2334 $add_str = " AND style_id = " . $ilDB->quote($a_id, "integer");
2335 }
2336
2337 $set = $ilDB->query($q = "SELECT DISTINCT style_id, tag, class FROM style_parameter WHERE " .
2338 $ilDB->equals("type", "", "text", true) . " " . $add_str);
2339
2340 while ($rec = $ilDB->fetchAssoc($set)) {
2341 // derive types from tag
2342 $types = array();
2343 switch ($rec["tag"]) {
2344 case "div":
2345 case "p":
2346 if (in_array($rec["class"], array("Headline3", "Headline1",
2347 "Headline2", "TableContent", "List", "Standard", "Remark",
2348 "Additional", "Mnemonic", "Citation", "Example"))) {
2349 $types[] = "text_block";
2350 }
2351 if (in_array($rec["class"], array("Block", "Remark",
2352 "Additional", "Mnemonic", "Example", "Excursus", "Special"))) {
2353 $types[] = "section";
2354 }
2355 if (in_array($rec["class"], array("Page", "Footnote", "PageTitle", "LMNavigation"))) {
2356 $types[] = "page";
2357 }
2358 break;
2359
2360 case "td":
2361 $types[] = "table_cell";
2362 break;
2363
2364 case "a":
2365 if (in_array($rec["class"], array("ExtLink", "IntLink", "FootnoteLink"))) {
2366 $types[] = "link";
2367 }
2368 break;
2369
2370 case "span":
2371 $types[] = "text_inline";
2372 break;
2373
2374 case "table":
2375 $types[] = "table";
2376 break;
2377 }
2378
2379 // check if style_char set exists
2380 foreach ($types as $t) {
2381 // check if second type already exists
2382 $set4 = $ilDB->queryF(
2383 "SELECT * FROM style_char " .
2384 " WHERE style_id = %s AND type = %s AND characteristic = %s",
2385 array("integer", "text", "text"),
2386 array($rec["style_id"], $t, $rec["class"])
2387 );
2388 if ($rec4 = $ilDB->fetchAssoc($set4)) {
2389 // ok
2390 } else {
2391 //echo "<br>1-".$rec["style_id"]."-".$t."-".$rec["class"]."-";
2392 $ilDB->manipulateF(
2393 "INSERT INTO style_char " .
2394 " (style_id, type, characteristic) VALUES " .
2395 " (%s,%s,%s) ",
2396 array("integer", "text", "text"),
2397 array($rec["style_id"], $t, $rec["class"])
2398 );
2399 }
2400 }
2401
2402 // update types
2403 if ($rec["type"] == "") {
2404 if (count($types) > 0) {
2405 $ilDB->manipulateF(
2406 "UPDATE style_parameter SET type = %s " .
2407 " WHERE style_id = %s AND class = %s AND " . $ilDB->equals("type", "", "text", true),
2408 array("text", "integer", "text"),
2409 array($types[0], $rec["style_id"], $rec["class"])
2410 );
2411 //echo "<br>3-".$types[0]."-".$rec["style_id"]."-".$rec["class"]."-";
2412
2413 // links extra handling
2414 if ($types[0] == "link") {
2415 $ilDB->manipulateF(
2416 "UPDATE style_parameter SET type = %s " .
2417 " WHERE style_id = %s AND (class = %s OR class = %s) AND " . $ilDB->equals("type", "", "text", true),
2418 array("text", "integer", "text", "text"),
2419 array($types[0], $rec["style_id"], $rec["class"] . ":visited",
2420 $rec["class"] . ":hover")
2421 );
2422 }
2423 }
2424
2425 if (count($types) == 2) {
2426 // select all records of first type and add second type
2427 // records if necessary.
2428 $set2 = $ilDB->queryF(
2429 "SELECT * FROM style_parameter " .
2430 " WHERE style_id = %s AND class = %s AND type = %s",
2431 array("integer", "text", "text"),
2432 array($rec["style_id"], $rec["class"], $types[0])
2433 );
2434 while ($rec2 = $ilDB->fetchAssoc($set2)) {
2435 // check if second type already exists
2436 $set3 = $ilDB->queryF(
2437 "SELECT * FROM style_parameter " .
2438 " WHERE style_id = %s AND tag = %s AND class = %s AND type = %s AND parameter = %s",
2439 array("integer", "text", "text", "text", "text"),
2440 array($rec["style_id"], $rec["tag"], $rec["class"], $types[1], $rec["parameter"])
2441 );
2442 if ($rec3 = $ilDB->fetchAssoc($set3)) {
2443 // ok
2444 } else {
2445 $nid = $ilDB->nextId("style_parameter");
2446 $ilDB->manipulateF(
2447 "INSERT INTO style_parameter " .
2448 " (id, style_id, tag, class, parameter, value, type) VALUES " .
2449 " (%s, %s,%s,%s,%s,%s,%s) ",
2450 array("integer", "integer", "text", "text", "text", "text", "text"),
2451 array($nid, $rec2["style_id"], $rec2["tag"], $rec2["class"],
2452 $rec2["parameter"], $rec2["value"], $types[1])
2453 );
2454 }
2455 }
2456 }
2457 }
2458 }
2459 }
2460
2464 public function do_3_9_Migration(int $a_id): void
2465 {
2466 $ilDB = $this->db;
2467
2468 $classes = array("Example", "Additional", "Citation", "Mnemonic", "Remark");
2469 $pars = array("margin-top", "margin-bottom");
2470
2471 foreach ($classes as $curr_class) {
2472 foreach ($pars as $curr_par) {
2473 $res2 = $ilDB->queryF(
2474 "SELECT id FROM style_parameter WHERE style_id = %s" .
2475 " AND tag = %s AND class= %s AND parameter = %s",
2476 array("integer", "text", "text", "text"),
2477 array($a_id, "p", $curr_class, $curr_par)
2478 );
2479 if ($row2 = $ilDB->fetchAssoc($res2)) {
2480 $ilDB->manipulateF(
2481 "UPDATE style_parameter SET value= %s WHERE id = %s",
2482 array("text", "integer"),
2483 array("10px", $row2["id"])
2484 );
2485 } else {
2486 $nid = $ilDB->nextId("style_parameter");
2487 $ilDB->manipulateF(
2488 "INSERT INTO style_parameter " .
2489 "(id, style_id, tag, class, parameter,value) VALUES (%s,%s,%s,%s,%s,%s)",
2490 array("integer", "integer", "text", "text", "text", "text"),
2491 array($nid, $a_id, "div", $curr_class, $curr_par, "10px")
2492 );
2493 }
2494 }
2495 }
2496
2497 $ilDB->manipulateF(
2498 "UPDATE style_parameter SET tag = %s WHERE tag = %s and style_id = %s",
2499 array("text", "text", "integer"),
2500 array("div", "p", $a_id)
2501 );
2502 }
2503
2507
2511 public function getColors(): array
2512 {
2513 $ilDB = $this->db;
2514
2515 $set = $ilDB->query("SELECT * FROM style_color WHERE " .
2516 "style_id = " . $ilDB->quote($this->getId(), "integer") . " " .
2517 "ORDER BY color_name");
2518
2519 $colors = array();
2520 while ($rec = $ilDB->fetchAssoc($set)) {
2521 $colors[] = array(
2522 "name" => $rec["color_name"],
2523 "code" => $rec["color_code"]
2524 );
2525 }
2526
2527 return $colors;
2528 }
2529
2533 public function removeColor(string $a_name): void
2534 {
2535 $ilDB = $this->db;
2536
2537 $ilDB->manipulate("DELETE FROM style_color WHERE " .
2538 " style_id = " . $ilDB->quote($this->getId(), "integer") . " AND " .
2539 " color_name = " . $ilDB->quote($a_name, "text"));
2540 }
2541
2542 public function getColorCodeForName(string $a_name): string
2543 {
2544 $ilDB = $this->db;
2545 $a_i = "";
2546 $pos = strpos($a_name, "(");
2547 if ($pos > 0) {
2548 $a_i = substr($a_name, $pos + 1);
2549 $a_i = str_replace(")", "", $a_i);
2550 $a_name = substr($a_name, 0, $pos);
2551 }
2552
2553 $set = $ilDB->query("SELECT color_code FROM style_color WHERE " .
2554 " style_id = " . $ilDB->quote($this->getId(), "integer") . " AND " .
2555 " color_name = " . $ilDB->quote($a_name, "text"));
2556 if ($rec = $ilDB->fetchAssoc($set)) {
2557 if ($a_i == "") {
2558 return "#" . $rec["color_code"];
2559 } else {
2561 $rec["color_code"],
2562 (int) $a_i
2563 );
2564 }
2565 }
2566 return "";
2567 }
2568
2572 public static function _getColorFlavor(
2573 string $a_rgb,
2574 int $a_i
2575 ): string {
2576 $rgb = ilObjStyleSheet::_explodeRGB($a_rgb, true);
2577 $hls = ilObjStyleSheet::_RGBToHLS($rgb);
2578
2579 if ($a_i > 0) {
2580 $hls["l"] = $hls["l"] + ((255 - $hls["l"]) * ($a_i / 100));
2581 }
2582 if ($a_i < 0) {
2583 $hls["l"] = $hls["l"] - (($hls["l"]) * (-$a_i / 100));
2584 }
2585
2586 $rgb = ilObjStyleSheet::_HLSToRGB($hls);
2587
2588 foreach ($rgb as $k => $v) {
2589 $rgb[$k] = str_pad(dechex((int) $v), 2, "0", STR_PAD_LEFT);
2590 }
2591
2592 return $rgb["r"] . $rgb["g"] . $rgb["b"];
2593 }
2594
2598 public static function _explodeRGB(
2599 string $a_rgb,
2600 bool $as_dec = false
2601 ): array {
2602 $r["r"] = substr($a_rgb, 0, 2);
2603 $r["g"] = substr($a_rgb, 2, 2);
2604 $r["b"] = substr($a_rgb, 4, 2);
2605 if ($as_dec) {
2606 $r["r"] = self::hexdec($r["r"]);
2607 $r["g"] = self::hexdec($r["g"]);
2608 $r["b"] = self::hexdec($r["b"]);
2609 }
2610
2611 return $r;
2612 }
2613
2614 protected static function hexdec(string $hex): int
2615 {
2616 $hex = preg_replace("/[^a-fA-F0-9]+/", "", $hex);
2617 if ($hex === "") {
2618 $hex = "0";
2619 }
2620 return (int) hexdec($hex);
2621 }
2622
2626 public static function _RGBToHLS(array $a_rgb): array
2627 {
2628 $r = $a_rgb["r"] / 255;
2629 $g = $a_rgb["g"] / 255;
2630 $b = $a_rgb["b"] / 255;
2631 $h = 0;
2632
2633 // max / min
2634 $max = max($r, $g, $b);
2635 $min = min($r, $g, $b);
2636
2637 //lightness
2638 $l = ($max + $min) / 2;
2639
2640 if ($max == $min) {
2641 $s = 0;
2642 } else {
2643 if ($l < 0.5) {
2644 $s = ($max - $min) / ($max + $min);
2645 } else {
2646 $s = ($max - $min) / (2.0 - $max - $min);
2647 }
2648
2649 if ($r == $max) {
2650 $h = ($g - $b) / ($max - $min);
2651 } elseif ($g == $max) {
2652 $h = 2.0 + ($b - $r) / ($max - $min);
2653 } elseif ($b == $max) {
2654 $h = 4.0 + ($r - $g) / ($max - $min);
2655 }
2656 }
2657
2658 $hls["h"] = round(($h / 6) * 255);
2659 $hls["l"] = round($l * 255);
2660 $hls["s"] = round($s * 255);
2661
2662 return $hls;
2663 }
2664
2668 public static function _HLSToRGB(array $a_hls): array
2669 {
2670 $h = $a_hls["h"] / 255;
2671 $l = $a_hls["l"] / 255;
2672 $s = $a_hls["s"] / 255;
2673 $temp3 = 0;
2674
2675 $rgb["r"] = $rgb["g"] = $rgb["b"] = 0;
2676
2677 // If S=0, define R, G, and B all to L
2678 if ($s == 0) {
2679 $rgb["r"] = $rgb["g"] = $rgb["b"] = $l;
2680 } else {
2681 if ($l < 0.5) {
2682 $temp2 = $l * (1.0 + $s);
2683 } else {
2684 $temp2 = $l + $s - $l * $s;
2685 }
2686
2687 $temp1 = 2.0 * $l - $temp2;
2688
2689
2690 # For each of R, G, B, compute another temporary value, temp3, as follows:
2691 foreach ($rgb as $k => $v) {
2692 switch ($k) {
2693 case "r":
2694 $temp3 = $h + 1.0 / 3.0;
2695 break;
2696
2697 case "g":
2698 $temp3 = $h;
2699 break;
2700
2701 case "b":
2702 $temp3 = $h - 1.0 / 3.0;
2703 break;
2704 }
2705 if ($temp3 < 0) {
2706 $temp3 = $temp3 + 1.0;
2707 }
2708 if ($temp3 > 1) {
2709 $temp3 = $temp3 - 1.0;
2710 }
2711
2712 if (6.0 * $temp3 < 1) {
2713 $rgb[$k] = $temp1 + ($temp2 - $temp1) * 6.0 * $temp3;
2714 } elseif (2.0 * $temp3 < 1) {
2715 $rgb[$k] = $temp2;
2716 } elseif (3.0 * $temp3 < 2) {
2717 $rgb[$k] = $temp1 + ($temp2 - $temp1) * ((2.0 / 3.0) - $temp3) * 6.0;
2718 } else {
2719 $rgb[$k] = $temp1;
2720 }
2721 }
2722 }
2723
2724 $rgb["r"] = round($rgb["r"] * 255);
2725 $rgb["g"] = round($rgb["g"] * 255);
2726 $rgb["b"] = round($rgb["b"] * 255);
2727
2728 return $rgb;
2729 }
2730
2731 //
2732 // Media queries
2733 //
2734
2738
2739 public function getMediaQueries(): array
2740 {
2741 $ilDB = $this->db;
2742
2743 $set = $ilDB->query("SELECT * FROM sty_media_query WHERE " .
2744 "style_id = " . $ilDB->quote($this->getId(), "integer") . " " .
2745 "ORDER BY order_nr");
2746
2747 $mq = array();
2748 while ($rec = $ilDB->fetchAssoc($set)) {
2749 $mq[] = $rec;
2750 }
2751
2752 return $mq;
2753 }
2754
2755 public function addMediaQuery(
2756 string $a_mquery,
2757 int $order_nr = 0
2758 ): int {
2759 $ilDB = $this->db;
2760
2761 $id = $ilDB->nextId("sty_media_query");
2762 if ($order_nr == 0) {
2763 $order_nr = $this->getMaxMQueryOrderNr() + 10;
2764 }
2765
2766 $ilDB->manipulate("INSERT INTO sty_media_query (id, style_id, mquery, order_nr)" .
2767 " VALUES (" .
2768 $ilDB->quote($id, "integer") . "," .
2769 $ilDB->quote($this->getId(), "integer") . "," .
2770 $ilDB->quote($a_mquery, "text") . "," .
2771 $ilDB->quote($order_nr, "integer") .
2772 ")");
2773
2774 return $id;
2775 }
2776
2780 public function getMaxMQueryOrderNr(): int
2781 {
2782 $ilDB = $this->db;
2783
2784 $set = $ilDB->query(
2785 "SELECT max(order_nr) mnr FROM sty_media_query " .
2786 " WHERE style_id = " . $ilDB->quote($this->getId(), "integer")
2787 );
2788 $rec = $ilDB->fetchAssoc($set);
2789
2790 return (int) $rec["mnr"];
2791 }
2792
2793 public function updateMediaQuery(
2794 int $a_id,
2795 string $a_mquery
2796 ): void {
2797 $ilDB = $this->db;
2798
2799 $ilDB->manipulate(
2800 "UPDATE sty_media_query SET " .
2801 " mquery = " . $ilDB->quote($a_mquery, "text") .
2802 " WHERE id = " . $ilDB->quote($a_id, "integer")
2803 );
2804 }
2805
2812 public function getMediaQueryForId(
2813 int $a_id
2814 ): array {
2815 $ilDB = $this->db;
2816
2817 $set = $ilDB->query(
2818 "SELECT * FROM sty_media_query " .
2819 " WHERE id = " . $ilDB->quote($a_id, "integer")
2820 );
2821 return $ilDB->fetchAssoc($set);
2822 }
2823
2829 public function deleteMediaQuery(
2830 int $a_id
2831 ): void {
2832 $ilDB = $this->db;
2833
2834 $ilDB->manipulate(
2835 "DELETE FROM sty_media_query WHERE " .
2836 " style_id = " . $ilDB->quote($this->getId(), "integer") .
2837 " AND id = " . $ilDB->quote($a_id, "integer")
2838 );
2839 $this->saveMediaQueryOrder();
2840 }
2841
2845 public function saveMediaQueryOrder(
2846 ?array $a_order_nr = null
2847 ): void {
2848 $ilDB = $this->db;
2849
2850 $mqueries = $this->getMediaQueries();
2851 if (is_array($a_order_nr)) {
2852 foreach ($mqueries as $k => $mq) {
2853 $mqueries[$k]["order_nr"] = $a_order_nr[$mq["id"]];
2854 }
2855 $mqueries = ilArrayUtil::sortArray($mqueries, "order_nr", "", true);
2856 }
2857 $cnt = 10;
2858 foreach ($mqueries as $mq) {
2859 $ilDB->manipulate(
2860 "UPDATE sty_media_query SET " .
2861 " order_nr = " . $ilDB->quote($cnt, "integer") .
2862 " WHERE id = " . $ilDB->quote($mq["id"], "integer")
2863 );
2864 $cnt += 10;
2865 }
2866 }
2867
2868
2869 //
2870 // Table template management
2871 //
2872
2876 public function getTemplates(
2877 string $a_type
2878 ): array {
2879 $ilDB = $this->db;
2880
2881 $set = $ilDB->query("SELECT * FROM style_template WHERE " .
2882 "style_id = " . $ilDB->quote($this->getId(), "integer") . " AND " .
2883 "temp_type = " . $ilDB->quote($a_type, "text") . " " .
2884 "ORDER BY name");
2885
2886 $templates = array();
2887 while ($rec = $ilDB->fetchAssoc($set)) {
2888 $rec["classes"] = $this->getTemplateClasses((int) $rec["id"]);
2889 $templates[] = $rec;
2890 }
2891
2892 return $templates;
2893 }
2894
2898 public function getTemplateClasses(
2899 int $a_tid
2900 ): array {
2901 $ilDB = $this->db;
2902 $set = $ilDB->query("SELECT * FROM style_template_class WHERE " .
2903 "template_id = " . $ilDB->quote($a_tid, "integer"));
2904
2905 $class = array();
2906 while ($rec = $ilDB->fetchAssoc($set)) {
2907 $key = $rec["class_type"];
2908 $class[$key] = $rec["class"];
2909 }
2910
2911 return $class;
2912 }
2913
2914
2918 public function addTemplate(
2919 string $a_type,
2920 string $a_name,
2921 array $a_classes
2922 ): int {
2923 $ilDB = $this->db;
2924
2925 $tid = $ilDB->nextId("style_template");
2926 $ilDB->manipulate("INSERT INTO style_template " .
2927 "(id, style_id, name, temp_type)" .
2928 " VALUES (" .
2929 $ilDB->quote($tid, "integer") . "," .
2930 $ilDB->quote($this->getId(), "integer") . "," .
2931 $ilDB->quote($a_name, "text") . "," .
2932 $ilDB->quote($a_type, "text") .
2933 ")");
2934
2935 foreach ($a_classes as $t => $c) {
2936 $ilDB->manipulate("INSERT INTO style_template_class " .
2937 "(template_id, class_type, class)" .
2938 " VALUES (" .
2939 $ilDB->quote($tid, "integer") . "," .
2940 $ilDB->quote($t, "text") . "," .
2941 $ilDB->quote($c, "text") .
2942 ")");
2943 }
2944
2945 $this->writeTemplatePreview(
2946 $tid,
2947 ilObjStyleSheetGUI::_getTemplatePreview($this, $a_type, $tid, true)
2948 );
2949
2950 return $tid;
2951 }
2952
2956 public function updateTemplate(
2957 int $a_t_id,
2958 string $a_name,
2959 array $a_classes
2960 ): void {
2961 $ilDB = $this->db;
2962
2963 $ilDB->manipulate("UPDATE style_template SET " .
2964 "name = " . $ilDB->quote($a_name, "text") .
2965 " WHERE id = " . $ilDB->quote($a_t_id, "integer"));
2966
2967 $ilDB->manipulate(
2968 "DELETE FROM style_template_class WHERE " .
2969 "template_id = " . $ilDB->quote($a_t_id, "integer")
2970 );
2971 foreach ($a_classes as $t => $c) {
2972 $ilDB->manipulate("INSERT INTO style_template_class " .
2973 "(template_id, class_type, class)" .
2974 " VALUES (" .
2975 $ilDB->quote($a_t_id, "integer") . "," .
2976 $ilDB->quote($t, "text") . "," .
2977 $ilDB->quote($c, "text") .
2978 ")");
2979 }
2980 }
2981
2982 public function addTemplateClass(
2983 int $a_t_id,
2984 string $a_type,
2985 string $a_class
2986 ): void {
2987 $ilDB = $this->db;
2988
2989 $ilDB->manipulate("INSERT INTO style_template_class " .
2990 "(template_id, class_type, class)" .
2991 " VALUES (" .
2992 $ilDB->quote($a_t_id, "integer") . "," .
2993 $ilDB->quote($a_type, "text") . "," .
2994 $ilDB->quote($a_class, "text") .
2995 ")");
2996 }
2997
3001 public function templateExists(
3002 string $a_template_name
3003 ): bool {
3004 $ilDB = $this->db;
3005
3006 $set = $ilDB->query("SELECT * FROM style_template WHERE " .
3007 "style_id = " . $ilDB->quote($this->getId(), "integer") . " AND " .
3008 "name = " . $ilDB->quote($a_template_name, "text"));
3009 if ($ilDB->fetchAssoc($set)) {
3010 return true;
3011 }
3012 return false;
3013 }
3014
3018 public function getTemplate(int $a_t_id): array
3019 {
3020 $ilDB = $this->db;
3021
3022 $set = $ilDB->query("SELECT * FROM style_template WHERE " .
3023 "style_id = " . $ilDB->quote($this->getId(), "integer") . " " .
3024 " AND id = " . $ilDB->quote($a_t_id, "integer"));
3025
3026 if ($rec = $ilDB->fetchAssoc($set)) {
3027 $rec["classes"] = $this->getTemplateClasses((int) $rec["id"]);
3028
3029 $template = $rec;
3030 return $template;
3031 }
3032 return array();
3033 }
3034
3038 public function lookupTemplateName(int $a_t_id): string
3039 {
3040 return self::_lookupTemplateName($a_t_id);
3041 }
3042
3046 public static function _lookupTemplateName(int $a_t_id): ?string
3047 {
3048 global $DIC;
3049
3050 $ilDB = $DIC->database();
3051
3052 $set = $ilDB->query("SELECT name FROM style_template WHERE " .
3053 " id = " . $ilDB->quote($a_t_id, "integer"));
3054
3055 if ($rec = $ilDB->fetchAssoc($set)) {
3056 return $rec["name"];
3057 }
3058
3059 return null;
3060 }
3061
3065 public function getTemplateXML(): string
3066 {
3067 $ilDB = $this->db;
3068
3069 $tag = "<StyleTemplates>";
3070
3071 $ttypes = array("table", "vaccordion", "haccordion", "carousel");
3072
3073 foreach ($ttypes as $ttype) {
3074 $ts = $this->getTemplates($ttype);
3075
3076 foreach ($ts as $t) {
3078 /*$atts = array("table" => "TableClass",
3079 "caption" => "CaptionClass",
3080 "row_head" => "RowHeadClass",
3081 "row_foot" => "RowFootClass",
3082 "col_head" => "ColHeadClass",
3083 "col_foot" => "ColFootClass",
3084 "odd_row" => "OddRowClass",
3085 "even_row" => "EvenRowClass",
3086 "odd_col" => "OddColClass",
3087 "even_col" => "EvenColClass");*/
3088 $c = $t["classes"];
3089
3090 $tag .= '<StyleTemplate Name="' . $t["name"] . '">';
3091
3092 foreach ($atts as $type => $t2) {
3093 if (($c[$type] ?? "") != "") {
3094 $tag .= '<StyleClass Type="' . $type . '" Value="' . $c[$type] . '" />';
3095 }
3096 }
3097
3098 $tag .= "</StyleTemplate>";
3099 }
3100 }
3101
3102 $tag .= "</StyleTemplates>";
3103
3104 //echo htmlentities($tag);
3105 return $tag;
3106 }
3107
3111 public function writeTemplatePreview(
3112 int $a_t_id,
3113 string $a_preview_html
3114 ): void {
3115 $ilDB = $this->db;
3116 $a_preview_html = str_replace(' width=""', "", $a_preview_html);
3117 $a_preview_html = str_replace(' valign="top"', "", $a_preview_html);
3118 $a_preview_html = str_replace('<div class="ilc_text_block_TableContent">', "<div>", $a_preview_html);
3119 //echo "1-".strlen($a_preview_html)."-";
3120 //echo htmlentities($a_preview_html);
3121 if (strlen($a_preview_html) > 4000) {
3122 //echo "2";
3123 $a_preview_html = "";
3124 }
3125 $ilDB->manipulate("UPDATE style_template SET " .
3126 "preview = " . $ilDB->quote($a_preview_html, "text") .
3127 " WHERE id = " . $ilDB->quote($a_t_id, "integer"));
3128 }
3129
3133 public function lookupTemplatePreview(int $a_t_id): string
3134 {
3135 $ilDB = $this->db;
3136
3137 $set = $ilDB->query("SELECT preview FROM style_template " .
3138 " WHERE id = " . $ilDB->quote($a_t_id, "integer"));
3139 if ($rec = $ilDB->fetchAssoc($set)) {
3140 return $rec["preview"] ?? "";
3141 }
3142
3143 return "";
3144 }
3145
3149 public static function _lookupTemplateIdByName(
3150 int $a_style_id,
3151 string $a_name
3152 ): ?int {
3153 global $DIC;
3154
3155 $ilDB = $DIC->database();
3156
3157 $set = $ilDB->query("SELECT id FROM style_template " .
3158 " WHERE style_id = " . $ilDB->quote($a_style_id, "integer") .
3159 " AND name = " . $ilDB->quote($a_name, "text"));
3160 if ($rec = $ilDB->fetchAssoc($set)) {
3161 return (int) $rec["id"];
3162 }
3163
3164 return null;
3165 }
3166
3170 public function removeTemplate(int $a_t_id): void
3171 {
3172 $ilDB = $this->db;
3173
3174 $ilDB->manipulate("DELETE FROM style_template WHERE " .
3175 " style_id = " . $ilDB->quote($this->getId(), "integer") . " AND " .
3176 " id = " . $ilDB->quote($a_t_id, "integer"));
3177
3178 $ilDB->manipulate(
3179 "DELETE FROM style_template_class WHERE " .
3180 "template_id = " . $ilDB->quote($a_t_id, "integer")
3181 );
3182 }
3183
3184 public function writeStyleSetting(
3185 string $a_name,
3186 string $a_value
3187 ): void {
3188 $ilDB = $this->db;
3189
3190 $ilDB->manipulate(
3191 "DELETE FROM style_setting WHERE " .
3192 " style_id = " . $ilDB->quote($this->getId(), "integer") .
3193 " AND name = " . $ilDB->quote($a_name, "text")
3194 );
3195
3196 $ilDB->manipulate("INSERT INTO style_setting " .
3197 "(style_id, name, value) VALUES (" .
3198 $ilDB->quote($this->getId(), "integer") . "," .
3199 $ilDB->quote($a_name, "text") . "," .
3200 $ilDB->quote($a_value, "text") .
3201 ")");
3202 }
3203
3207 public function lookupStyleSetting(string $a_name): string
3208 {
3209 $ilDB = $this->db;
3210
3211 $set = $ilDB->query(
3212 "SELECT value FROM style_setting " .
3213 " WHERE style_id = " . $ilDB->quote($this->getId(), "integer") .
3214 " AND name = " . $ilDB->quote($a_name, "text")
3215 );
3216 $rec = $ilDB->fetchAssoc($set);
3217
3218 return $rec["value"] ?? '';
3219 }
3220
3224 public static function writeStyleUsage(
3225 int $a_obj_id,
3226 int $a_style_id
3227 ): void {
3228 global $DIC;
3229
3230 $ilDB = $DIC->database();
3231
3232 $ilDB->replace(
3233 "style_usage",
3234 array(
3235 "obj_id" => array("integer", $a_obj_id)),
3236 array(
3237 "style_id" => array("integer", $a_style_id))
3238 );
3239 }
3240
3244 public static function lookupObjectStyle(
3245 int $a_obj_id
3246 ): int {
3247 global $DIC;
3248
3249 $ilDB = $DIC->database();
3250
3251 $set = $ilDB->query(
3252 "SELECT style_id FROM style_usage " .
3253 " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer")
3254 );
3255 $rec = $ilDB->fetchAssoc($set);
3256 if (!is_array($rec)) {
3257 return 0;
3258 }
3259
3260 if (ilObject::_lookupType((int) $rec["style_id"]) == "sty") {
3261 return (int) $rec["style_id"];
3262 }
3263
3264 return 0;
3265 }
3266
3271 public static function lookupObjectForStyle(
3272 int $a_style_id
3273 ): array {
3274 global $DIC;
3275
3276 $ilDB = $DIC->database();
3277
3278 $obj_ids = array();
3279 if (ilObject::_lookupType($a_style_id) == "sty") {
3280 $set = $ilDB->query(
3281 "SELECT DISTINCT obj_id FROM style_usage " .
3282 " WHERE style_id = " . $ilDB->quote($a_style_id, "integer")
3283 );
3284
3285 while ($rec = $ilDB->fetchAssoc($set)) {
3286 $obj_ids[] = (int) $rec["obj_id"];
3287 }
3288 }
3289 return $obj_ids;
3290 }
3291}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
return true
static sortArray(array $array, string $a_array_sortby_key, string $a_array_sortorder="asc", bool $a_numeric=false, bool $a_keep_keys=false)
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
static getWebspaceDir(string $mode="filesystem")
get webspace directory
static zip(string $a_dir, string $a_file, bool $compress_content=false)
static makeDir(string $a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static getDataDir()
get data directory (outside webspace)
static moveUploadedFile(string $a_file, string $a_name, string $a_target, bool $a_raise_errors=true, string $a_mode="move_uploaded")
move uploaded file
static rCopy(string $a_sdir, string $a_tdir, bool $preserveTimeAttributes=false)
Copies content of a directory $a_sdir recursively to a directory $a_tdir.
static _deleteStyleAssignments(int $a_style_id)
delete all style references to style
static _lookupContObjIdByStyleId(int $a_style_id)
static _getTemplatePreview(ilObjStyleSheet $a_style, string $a_type, int $a_t_id, bool $a_small_mode=false)
Get table template preview.
Class ilObjStyleSheet.
handleXmlString(string $a_str)
getMediaQueryForId(int $a_id)
Get media query for id.
getHideStatus(string $a_type, string $a_char)
Get characteristic hidden status.
setStyle(array $a_style)
getMaxMQueryOrderNr()
Get maximum media query order nr.
static _explodeRGB(string $a_rgb, bool $as_dec=false)
Explode an RGB string into an array.
static _addMissingStyleClassesToAllStyles(?array $a_styles=null)
Add missing style classes to all styles todo: add mq_id and custom handling.
do_3_10_CharMigration(int $a_id=0)
This is more or less a copy of Services/Migration/DBUpdate_1385/classes ilStyleMigration->addMissingS...
static _lookupStandard(int $a_id)
Lookup standard flag.
static array $filtered_groups
static _writeActive(int $a_id, bool $a_active)
static _lookupTemplateIdByName(int $a_style_id, string $a_name)
Lookup table template preview.
addTemplateClass(int $a_t_id, string $a_type, string $a_class)
read()
read style properties
updateStyleParameter(int $a_id, string $a_value)
update style parameter per id
saveMediaQueryOrder(?array $a_order_nr=null)
Save media query order.
static _getClonableContentStyles()
Get all clonable styles (active standard styles and individual learning module styles with write perm...
updateMediaQuery(int $a_id, string $a_mquery)
static _lookupActive(int $a_id)
Lookup active flag.
static string $basic_style_file
setUpToDate(bool $a_up_to_date=true)
Set style up to date (false + update will trigger css generation next time)
setExportSubDir(string $a_dir)
Set local directory, that will be included within the zip file.
writeCSSFile(string $a_target_file="", string $a_image_dir="")
write css file to webspace directory
static array $pseudo_classes
getColorCodeForName(string $a_name)
static array $expandable_types
setCharacteristics(array $a_chars)
static getContentStylePath(int $a_style_id, bool $add_random=true, bool $add_token=true)
get content style path static (to avoid full reading)
create(int $a_from_style=0, bool $a_import_mode=false)
Create a new style.
createFromXMLFile(string $a_file, bool $a_skip_parent_create=false)
create style from xml file todo: add mq_id and custom
getCharacteristics(string $a_type="", bool $a_no_hidden=false, bool $a_include_core=true)
Get characteristics.
static _getPseudoClasses(string $tag)
static _writeScope(int $a_id, int $a_scope)
__construct(int $a_id=0, bool $a_call_by_reference=false)
characteristicExists(string $a_char, string $a_style_type)
Check whether characteristic exists.
static string $basic_style_zip
ilClone()
clone style sheet (note: styles have no ref ids and return an object id)
static _createImagesDirectory(int $a_style_id)
Create images directory <data_dir>/sty/sty_<id>/images.
static hexdec(string $hex)
addTemplate(string $a_type, string $a_name, array $a_classes)
Add table template.
static _getStandardStyles(bool $a_exclude_default_style=false, bool $a_include_deactivated=false, int $a_scope=0)
Get standard styles.
static writeStyleUsage(int $a_obj_id, int $a_style_id)
Write style usage.
copyImagesToDir(string $a_target)
Copy images to directory.
static _getStyleParameterNumericUnits(bool $a_no_percentage=false)
static _getStyleParameterSubPar(string $par)
static _lookupUpToDate(int $a_id)
static isCoreStyle(string $a_type, string $a_class)
InternalDomainService $domain
static _getImagesDirectory(int $a_style_id)
getTemplateXML()
Get table template xml.
static _getStyleParameterInputType(string $par)
static _HLSToRGB(array $a_hls)
HLS to RGB (both arrays, 0..255)
writeTemplatePreview(int $a_t_id, string $a_preview_html)
Write table template preview.
addMediaQuery(string $a_mquery, int $order_nr=0)
exportXML(string $a_dir)
export style xml file to directory
getStyleParameterGroups()
Get grouped parameter.
lookupTemplateName(int $a_t_id)
Lookup table template name for template ID.
static getEffectiveContentStyleId(int $a_style_id)
Get effective Style Id.
updateTemplate(int $a_t_id, string $a_name, array $a_classes)
Update table template.
getTemplateClasses(int $a_tid)
Get template classes.
getTemplates(string $a_type)
Get table templates of style.
deleteCustomStylePars(string $a_tag, string $a_class, string $a_type, int $a_mq_id=0)
Delete style parameter by tag/class/parameter.
lookupStyleSetting(string $a_name)
Lookup style setting.
static lookupObjectForStyle(int $a_style_id)
Lookup objects for style.
getExportSubDir()
The local directory, that will be included within the zip file.
ILIAS Style Content InternalRepoService $repo
removeTemplate(int $a_t_id)
Remove table template.
addCharacteristic(string $a_type, string $a_char, bool $a_hidden=false, int $order_nr=0, bool $outdated=false)
static _addMissingStyleClassesToStyle(int $a_id)
Add missing style classes to all styles.
saveHideStatus(string $a_type, string $a_char, bool $a_hide)
Save characteristic hidden status.
static _getColorFlavor(string $a_rgb, int $a_i)
Get color flavor.
static _RGBToHLS(array $a_rgb)
RGB to HLS (both arrays, 0..255)
deleteStyleParOfChar(string $a_type, string $a_class)
Delete style parameters of characteristic.
static _writeStandard(int $a_id, bool $a_std)
Write standard flag.
getParametersOfClass(string $a_type, string $a_class, int $a_mq_id=0)
static array $num_unit_no_perc
static writeOwner($obj_id, $style_id)
static DOMDocument $basic_style_dom
do_3_10_Migration()
Migrates 3.10 style to 3.11 style.
static _determineTag(string $a_type)
templateExists(string $a_template_name)
Check whether template exists.
static string $basic_style_image_dir
deleteMediaQuery(int $a_id)
Delete media query.
deleteParameter(int $a_id)
delete style parameter
getColors()
Get colors of style.
static _isHideable(string $a_type)
createImagesDirectory()
Create images directory <data_dir>/sty/sty_<id>/images.
static _writeUpToDate(int $a_id, bool $a_up_to_date)
static array $hideable_types
removeColor(string $a_name)
Remove a color.
lookupTemplatePreview(int $a_t_id)
Lookup table template preview.
writeStyleSetting(string $a_name, string $a_value)
static lookupObjectStyle(int $a_obj_id)
Lookup object style.
addParameter(string $a_tag, string $a_par, string $a_type, int $a_mq_id=0, bool $a_custom=false)
write style parameter to db
static _getTemplateClassTypes(string $a_template_type="")
Get template class types.
static array $style_super_types
determineTemplateStyleClassType(string $t, string $k)
static _getStyleSuperTypeForType(string $a_type)
getXML()
get xml representation of style object todo: add mq_id
static _getStyleParameters(string $a_tag="")
static _isExpandable(string $a_type)
static _lookupTemplateName(int $a_t_id)
Lookup table template name for template ID.
do_3_9_Migration(int $a_id)
Migrate old 3.9 styles.
static _getStyleParameterValues(string $par)
Class ilObject Basic functions for all objects.
static _lookupType(int $id, bool $reference=false)
static _getAllReferences(int $id)
get all reference ids for object ID
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
static _getObjectsDataForType(string $type, bool $omit_trash=false)
get all objects of a certain type
static _lookupTitle(int $obj_id)
static subStr(string $a_str, int $a_start, ?int $a_length=null)
Definition: class.ilStr.php:21
$c
Definition: deliver.php:25
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$ref_id
Definition: ltiauth.php:66
$service
Definition: ltiresult.php:36
$path
Definition: ltiservices.php:30
$res
Definition: ltiservices.php:69
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
Class ilObjForumAdministration.
global $lng
Definition: privfeed.php:31
global $ilSetting
Definition: privfeed.php:31
$ilErr
Definition: raiseError.php:33
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26
$q
Definition: shib_logout.php:23