ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilTextAreaInputGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
28 {
29  protected array $rteSupport = [];
30  protected string $value = "";
31  protected int $cols = 30;
32  protected int $rows = 5;
33  protected bool $usert = false;
34  protected array $rtetags = [];
35  protected array $plugins = [];
36  protected array $removeplugins = [];
37  protected array $buttons = [];
38  protected array $rtesupport = [];
39  protected bool $use_tags_for_rte_only = true;
40  protected int $max_num_chars = 0;
41  protected int $min_num_chars = 0;
42  protected int $initial_rte_width = 795;
43  protected array $disabled_buttons = array();
44  protected bool $usePurifier = false;
46  protected ?string $root_block_element = null;
47  private ilObjUser $user;
48 
49  protected array $rte_tag_set = array(
50  "mini" => array("strong", "em", "u", "ol", "li", "ul", "blockquote", "a", "p", "span", "br"), // #13286/#17981
51  "standard" => array("strong", "em", "u", "ol", "li", "ul", "p", "div",
52  "i", "b", "code", "sup", "sub", "pre", "strike", "gap"),
53  "extended" => array(
54  "a","blockquote","br","cite","code","div","em","h1","h2","h3",
55  "h4","h5","h6","hr","li","ol","p",
56  "pre","span","strike","strong","sub","sup","u","ul",
57  "i", "b", "gap"),
58  "extended_img" => array(
59  "a","blockquote","br","cite","code","div","em","h1","h2","h3",
60  "h4","h5","h6","hr","img","li","ol","p",
61  "pre","span","strike","strong","sub","sup","u","ul",
62  "i", "b", "gap"),
63  "extended_table" => array(
64  "a","blockquote","br","cite","code","div","em","h1","h2","h3",
65  "h4","h5","h6","hr","li","ol","p",
66  "pre","span","strike","strong","sub","sup","table","td",
67  "tr","u","ul", "i", "b", "gap"),
68  "extended_table_img" => array(
69  "a","blockquote","br","cite","code","div","em","h1","h2","h3",
70  "h4","h5","h6","hr","img","li","ol","p",
71  "pre","span","strike","strong","sub","sup","table","td",
72  "tr","u","ul", "i", "b", "gap"),
73  "full" => array(
74  "a","blockquote","br","cite","code","div","em","h1","h2","h3",
75  "h4","h5","h6","hr","img","li","ol","p",
76  "pre","span","strike","strong","sub","sup","table","td",
77  "tr","u","ul","ruby","rbc","rtc","rb","rt","rp", "i", "b", "gap"));
78 
79  public function __construct(
80  string $a_title = "",
81  string $a_postvar = ""
82  ) {
83  global $DIC;
84 
85  $this->lng = $DIC->language();
86  $this->user = $DIC->user();
87  parent::__construct($a_title, $a_postvar);
88  $this->setType("textarea");
89  $this->setRteTagSet("standard");
90  $this->plugins = array();
91  $this->removeplugins = array();
92  $this->buttons = array();
93  $this->rteSupport = array();
94  }
95 
96  public function setValue(string $a_value): void
97  {
98  $this->value = $a_value;
99  }
100 
101  public function getValue(): string
102  {
103  return $this->value;
104  }
105 
109  public function setCols(int $a_cols): void
110  {
111  // obsolete because of bootstrap
112  $this->cols = $a_cols;
113  }
114 
115  public function getCols(): int
116  {
117  return $this->cols;
118  }
119 
120  public function setRows(int $a_rows): void
121  {
122  $this->rows = $a_rows;
123  }
124 
125  public function getRows(): int
126  {
127  return $this->rows;
128  }
129 
130  // Set Maximum number of characters allowed.
131  public function setMaxNumOfChars(int $a_number): void
132  {
133  $this->max_num_chars = $a_number;
134  }
135 
136  public function getMaxNumOfChars(): int
137  {
138  return $this->max_num_chars;
139  }
140 
141  public function setMinNumOfChars(int $a_number): void
142  {
143  $this->min_num_chars = $a_number;
144  }
145 
146  public function getMinNumOfChars(): int
147  {
148  return $this->min_num_chars;
149  }
150 
151  public function setUseRte(bool $a_usert, string $version = ''): void
152  {
153  $this->usert = $a_usert;
154  $this->rteSupport['version'] = $version;
155  }
156 
157  public function getUseRte(): bool
158  {
159  return $this->usert;
160  }
161 
162  public function addPlugin(string $a_plugin): void
163  {
164  $this->plugins[$a_plugin] = $a_plugin;
165  }
166 
167  public function removePlugin(string $a_plugin): void
168  {
169  $this->removeplugins[$a_plugin] = $a_plugin;
170  }
171 
172  // Add RTE button.
173  public function addButton(string $a_button): void
174  {
175  $this->buttons[$a_button] = $a_button;
176  }
177 
178  public function removeButton(string $a_button): void
179  {
180  unset($this->buttons[$a_button]);
181  }
182 
186  public function setRTESupport(
187  int $obj_id,
188  string $obj_type,
189  string $module,
190  ?string $cfg_template = null,
191  bool $hide_switch = false,
192  ?string $version = null
193  ): void {
194  $this->rteSupport = array(
195  "obj_id" => $obj_id,
196  "obj_type" => $obj_type,
197  "module" => $module,
198  'cfg_template' => $cfg_template,
199  'hide_switch' => $hide_switch,
200  'version' => $version
201  );
202  }
203 
204  public function removeRTESupport(): void
205  {
206  $this->rteSupport = array();
207  }
208 
209  public function setRteTags(array $a_rtetags): void
210  {
211  $this->rtetags = $a_rtetags;
212  }
213 
214  public function getRteTags(): array
215  {
216  return $this->rtetags;
217  }
218 
223  public function setRteTagSet(string $a_set_name): void
224  {
225  $this->setRteTags($this->rte_tag_set[$a_set_name]);
226  }
227 
228  public function getRteTagSet($a_set_name): array
229  {
230  return $this->rte_tag_set[$a_set_name];
231  }
232 
233  public function getRteTagString(): string
234  {
235  $result = "";
236  foreach ($this->getRteTags() as $tag) {
237  $result .= "<$tag>";
238  }
239  return $result;
240  }
241 
245  public function setUseTagsForRteOnly(bool $a_val): void
246  {
247  $this->use_tags_for_rte_only = $a_val;
248  }
249 
250  public function getUseTagsForRteOnly(): bool
251  {
253  }
254 
255  public function setValueByArray(array $a_values): void
256  {
257  $this->setValue($a_values[$this->getPostVar()] ?? "");
258 
259  foreach ($this->getSubItems() as $item) {
260  $item->setValueByArray($a_values);
261  }
262  }
263 
264  public function checkInput(): bool
265  {
266  $lng = $this->lng;
267 
268  $value = $this->getInput();
269  if ($this->getRequired() && trim($value) == "") {
270  $this->setAlert($lng->txt("msg_input_is_required"));
271  return false;
272  }
273 
274  if ($this->isCharLimited()) {
275  //avoid whitespace surprises. #20630, #20674
276  $ascii_whitespaces = chr(194) . chr(160);
277  $ascii_breaklines = chr(13) . chr(10);
278 
279  $to_replace = array($ascii_whitespaces, $ascii_breaklines, "&lt;", "&gt;", "&amp;");
280  $replace_to = array(' ', '', "_", "_", "_");
281 
282  #20630 mbstring extension is mandatory for 5.4
283  $chars_entered = mb_strlen(strip_tags(str_replace($to_replace, $replace_to, $value)));
284 
285  if ($this->getMaxNumOfChars() && ($chars_entered > $this->getMaxNumOfChars())) {
286  $this->setAlert($lng->txt("msg_input_char_limit_max"));
287  return false;
288  } elseif ($this->getMinNumOfChars() && ($chars_entered < $this->getMinNumOfChars())) {
289  $this->setAlert($lng->txt("msg_input_char_limit_min"));
290  return false;
291  }
292  }
293 
294  return $this->checkSubItemsInput();
295  }
296 
297  public function getInput(): string
298  {
299  if ($this->usePurifier() && $this->getPurifier()) {
300  $value = $this->getPurifier()->purify($this->raw($this->getPostVar()));
301  } else {
302  $allowed = $this->getRteTagString();
303  if (isset($this->plugins["latex"]) && $this->plugins["latex"] == "latex" && !is_int(strpos($allowed, "<span>"))) {
304  $allowed .= "<span>";
305  }
306  $value = ($this->getUseRte() || !$this->getUseTagsForRteOnly())
307  ? ilUtil::stripSlashes($this->raw($this->getPostVar()), true, $allowed)
308  : $this->str($this->getPostVar());
309  }
310 
311  $value = self::removeProhibitedCharacters($value);
312  return $value;
313  }
314 
315  public function insert(ilTemplate $a_tpl): void
316  {
317  $lng = $this->lng;
318 
319  $ttpl = new ilTemplate("tpl.prop_textarea.html", true, true, "components/ILIAS/Form");
320 
321  if ($this->getInfo() !== '') {
322  $ttpl->setCurrentBlock('described_by_description');
323  $ttpl->setVariable('DESCRIBED_BY_DESCRIPTION_FIELD_ID', $this->getFieldId());
324  $ttpl->parseCurrentBlock();
325  }
326 
327  // disabled rte
328  if ($this->getUseRte() && $this->getDisabled()) {
329  $ttpl->setCurrentBlock("disabled_rte");
330  $ttpl->setVariable("DR_VAL", $this->getValue());
331  } else {
332  if ($this->getUseRte()) {
333  $ttpl->touchBlock("rteditor");
334  $rtestring = ilRTE::_getRTEClassname();
335  $rte = new $rtestring((string) $this->rteSupport['version']);
336  $rte->setInitialWidth($this->getInitialRteWidth());
337 
338  // @todo: Check this.
339  $rte->addPlugin("emoticons");
340  foreach ($this->plugins as $plugin) {
341  if (strlen($plugin)) {
342  $rte->addPlugin($plugin);
343  }
344  }
345  foreach ($this->removeplugins as $plugin) {
346  if (strlen($plugin)) {
347  $rte->removePlugin($plugin);
348  }
349  }
350 
351  foreach ($this->buttons as $button) {
352  if (strlen($button)) {
353  $rte->addButton($button);
354  }
355  }
356 
357  $rte->disableButtons($this->getDisabledButtons());
358 
359  if ($this->getRTERootBlockElement() !== null) {
360  $rte->setRTERootBlockElement($this->getRTERootBlockElement());
361  }
362 
363  if (count($this->rteSupport) >= 3) {
364  $rte->addRTESupport(
365  $this->lng,
366  $this->user,
367  $this->rteSupport["obj_id"],
368  $this->rteSupport["obj_type"],
369  $this->rteSupport["module"],
370  false,
371  $this->rteSupport['cfg_template']
372  );
373  } else {
374  // disable all plugins for mini-tagset
375  if (!array_diff($this->getRteTags(), $this->getRteTagSet("mini"))) {
376  $rte->removeAllPlugins();
377 
378  // #13603 - "paste from word" is essential
379  $rte->addPlugin("paste");
380  //Add plugins 'lists', 'code' and 'link': in tinymce 3 it wasnt necessary to configure these plugins
381  $rte->addPlugin("lists");
382  $rte->addPlugin("link");
383  $rte->addPlugin("code");
384 
385  if (method_exists($rte, 'removeAllContextMenuItems')) {
386  $rte->removeAllContextMenuItems(); //https://github.com/ILIAS-eLearning/ILIAS/pull/3088#issuecomment-805830050
387  }
388 
389  // #11980 - p-tag is mandatory but we do not want the icons it comes with
390  $rte->disableButtons(array("anchor", "alignleft", "aligncenter",
391  "alignright", "alignjustify", "formatselect", "removeformat",
392  "cut", "copy", "paste", "pastetext")); // JF, 2013-12-09
393  }
394  $rte->addCustomRTESupport(0, "", $this->getRteTags());
395  }
396 
397  $ttpl->touchBlock("prop_ta_w");
398  } else {
399  if ($this->getCols() > 5) {
400  $ttpl->setCurrentBlock("prop_ta_c");
401  $ttpl->setVariable("COLS", $this->getCols());
402  $ttpl->parseCurrentBlock();
403  } else {
404  $ttpl->touchBlock("prop_ta_w");
405  }
406  }
407  $ttpl->setCurrentBlock("prop_textarea");
408  $ttpl->setVariable("ROWS", $this->getRows());
409  $ttpl->setVariable("POST_VAR", $this->getPostVar());
410  $ttpl->setVariable("ID", $this->getFieldId());
411  if ($this->getDisabled()) {
412  $ttpl->setVariable('DISABLED', 'disabled="disabled" ');
413  }
414  $ttpl->setVariable("PROPERTY_VALUE", ilLegacyFormElementsUtil::prepareFormOutput($this->getValue()));
415 
416  if ($this->getRequired()) {
417  $ttpl->setVariable("REQUIRED", "required=\"required\"");
418  }
419 
420  if ($this->isCharLimited()) {
421  $ttpl->setVariable("MAXCHARS", $this->getMaxNumOfChars());
422  $ttpl->setVariable("MINCHARS", $this->getMinNumOfChars());
423 
424  $lng->toJS("form_chars_remaining");
425  }
426  }
427  $ttpl->parseCurrentBlock();
428 
429  if ($this->isCharLimited()) {
430  $ttpl->setVariable("FEEDBACK_MAX_LIMIT", $this->getMaxNumOfChars());
431  $ttpl->setVariable("FEEDBACK_ID", $this->getFieldId());
432  $ttpl->setVariable("CHARS_REMAINING", $lng->txt("form_chars_remaining"));
433  }
434 
435  if ($this->getDisabled()) {
436  $ttpl->setVariable(
437  "HIDDEN_INPUT",
438  $this->getHiddenTag($this->getPostVar(), $this->getValue())
439  );
440  }
441  $a_tpl->setCurrentBlock("prop_generic");
442  $a_tpl->setVariable("PROP_GENERIC", $ttpl->get());
443  $a_tpl->parseCurrentBlock();
444  }
445 
451  public function usePurifier(?bool $a_flag = null)
452  {
453  if (null === $a_flag) {
454  return $this->usePurifier;
455  }
456 
457  $this->usePurifier = $a_flag;
458  return $this;
459  }
460 
464  public function setPurifier(ilHtmlPurifierInterface $Purifier): self
465  {
466  $this->Purifier = $Purifier;
467  return $this;
468  }
469 
471  {
472  return $this->Purifier;
473  }
474 
475  public function setRTERootBlockElement(?string $a_root_block_element): self
476  {
477  $this->root_block_element = $a_root_block_element;
478  return $this;
479  }
480 
481  public function getRTERootBlockElement(): ?string
482  {
484  }
485 
491  public function disableButtons($a_button): self
492  {
493  if (is_array($a_button)) {
494  $this->disabled_buttons = array_unique(array_merge($this->disabled_buttons, $a_button));
495  } else {
496  $this->disabled_buttons = array_unique(array_merge($this->disabled_buttons, array($a_button)));
497  }
498  return $this;
499  }
500 
504  public function getDisabledButtons(bool $as_array = true)
505  {
506  if (!$as_array) {
507  return implode(',', $this->disabled_buttons);
508  } else {
510  }
511  }
512 
513  public function getInitialRteWidth(): int
514  {
516  }
517 
518  public function setInitialRteWidth(int $initial_rte_width): void
519  {
520  $this->initial_rte_width = $initial_rte_width;
521  }
522 
523  public function isCharLimited(): bool
524  {
525  if ($this->getMaxNumOfChars() || $this->getMinNumOfChars()) {
526  return true;
527  }
528 
529  return false;
530  }
531 }
static _getRTEClassname()
parseCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
ilHtmlPurifierInterface $Purifier
removePlugin(string $a_plugin)
setValueByArray(array $a_values)
setRTERootBlockElement(?string $a_root_block_element)
$version
Definition: plugin.php:24
setRTESupport(int $obj_id, string $obj_type, string $module, ?string $cfg_template=null, bool $hide_switch=false, ?string $version=null)
Set RTE support for a special module.
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
setInitialRteWidth(int $initial_rte_width)
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
__construct(string $a_title="", string $a_postvar="")
static prepareFormOutput($a_str, bool $a_strip=false)
setRteTagSet(string $a_set_name)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
Interface for html sanitizing functionality.
disableButtons($a_button)
Sets buttons which should be disabled in TinyMCE.
setVariable($variable, $value='')
Sets a variable value.
Definition: IT.php:544
global $DIC
Definition: shib_login.php:26
getHiddenTag(string $a_post_var, string $a_value)
setCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
setUseTagsForRteOnly(bool $a_val)
Set use tags for RTE only (default is true)
removeButton(string $a_button)
usePurifier(?bool $a_flag=null)
Setter/Getter for the html purifier usage.
__construct(Container $dic, ilPlugin $plugin)
This class represents a property that may include a sub form.
This class represents a text area property in a property form.
setPurifier(ilHtmlPurifierInterface $Purifier)
Setter for the html purifier.
setUseRte(bool $a_usert, string $version='')
toJS($a_lang_key, ?ilGlobalTemplateInterface $a_tpl=null)
Transfer text to Javascript.
getDisabledButtons(bool $as_array=true)