ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
ilCharSelectorConfig.php
Go to the documentation of this file.
1 <?php
2 
20 {
25  public const INACTIVE = 0; // default for admin: deactivates the whole tool
26  public const INHERIT = 0; // default for user and test: take the plattform default
27  public const ENABLED = 1; // enable the selector
28  public const DISABLED = 2; // disable the selector
29 
33  public const CONTEXT_NONE = ''; // no context => no initialisation
34  public const CONTEXT_ADMIN = 'admin'; // administrative settings
35  public const CONTEXT_USER = 'user'; // user specific settings
36  public const CONTEXT_TEST = 'test'; // test specific settings
37 
42  public static array $unicode_blocks = array(
43  'basic_latin' => array('Basic Latin', '0020', '007F'), // only printing characters
44  'latin_1_supplement' => array('Latin-1 Supplement', '00A0', '00FF'), // only printing characters
45  'latin_extended_a' => array('Latin Extended-A', '0100', '017F'),
46  'latin_extended_b' => array('Latin Extended-B', '0180', '024F'),
47  'ipa_extensions' => array('IPA Extensions', '0250', '02AF'),
48  'spacing_modifier_letters' => array('Spacing Modifier Letters', '02B0', '02FF'),
49  'combining_diacritical_marks' => array('Combining Diacritical Marks', '0300', '036F'),
50  'greek_and_coptic' => array('Greek and Coptic', '0370', '03FF'),
51  'cyrillic' => array('Cyrillic', '0400', '04FF'),
52  'cyrillic_supplement' => array('Cyrillic Supplement', '0500', '052F'),
53  'armenian' => array('Armenian', '0530', '058F'),
54  'hebrew' => array('Hebrew', '0590', '05FF'),
55  'arabic' => array('Arabic', '0600', '06FF'),
56  'syriac' => array('Syriac', '0700', '074F'),
57  'arabic_supplement' => array('Arabic Supplement', '0750', '077F'),
58  'thaana' => array('Thaana', '0780', '07BF'),
59  'nko' => array('NKo', '07C0', '07FF'),
60  'samaritan' => array('Samaritan', '0800', '083F'),
61  'mandaic' => array('Mandaic', '0840', '085F'),
62  'arabic_extended_a' => array('Arabic Extended-A', '08A0', '08FF'),
63  'devanagari' => array('Devanagari', '0900', '097F'),
64  'bengali' => array('Bengali', '0980', '09FF'),
65  'gurmukhi' => array('Gurmukhi', '0A00', '0A7F'),
66  'gujarati' => array('Gujarati', '0A80', '0AFF'),
67  'oriya' => array('Oriya', '0B00', '0B7F'),
68  'tamil' => array('Tamil', '0B80', '0BFF'),
69  'telugu' => array('Telugu', '0C00', '0C7F'),
70  'kannada' => array('Kannada', '0C80', '0CFF'),
71  'malayalam' => array('Malayalam', '0D00', '0D7F'),
72  'sinhala' => array('Sinhala', '0D80', '0DFF'),
73  'thai' => array('Thai', '0E00', '0E7F'),
74  'lao' => array('Lao', '0E80', '0EFF'),
75  'tibetan' => array('Tibetan', '0F00', '0FFF'),
76  'myanmar' => array('Myanmar', '1000', '109F'),
77  'georgian' => array('Georgian', '10A0', '10FF'),
78  'hangul_jamo' => array('Hangul Jamo', '1100', '11FF'),
79  'ethiopic' => array('Ethiopic', '1200', '137F'),
80  'ethiopic_supplement' => array('Ethiopic Supplement', '1380', '139F'),
81  'cherokee' => array('Cherokee', '13A0', '13FF'),
82  'unified_canadian_aboriginal_syllabics' => array('Unified Canadian Aboriginal Syllabics', '1400', '167F'),
83  'ogham' => array('Ogham', '1680', '169F'),
84  'runic' => array('Runic', '16A0', '16FF'),
85  'tagalog' => array('Tagalog', '1700', '171F'),
86  'hanunoo' => array('Hanunoo', '1720', '173F'),
87  'buhid' => array('Buhid', '1740', '175F'),
88  'tagbanwa' => array('Tagbanwa', '1760', '177F'),
89  'khmer' => array('Khmer', '1780', '17FF'),
90  'mongolian' => array('Mongolian', '1800', '18AF'),
91  'unified_canadian_aboriginal_syllabics_extended' => array('Unified Canadian Aboriginal Syllabics Extended',
92  '18B0',
93  '18FF'
94  ),
95  'limbu' => array('Limbu', '1900', '194F'),
96  'tai_le' => array('Tai Le', '1950', '197F'),
97  'new_tai_lue' => array('New Tai Lue', '1980', '19DF'),
98  'khmer_symbols' => array('Khmer Symbols', '19E0', '19FF'),
99  'buginese' => array('Buginese', '1A00', '1A1F'),
100  'tai_tham' => array('Tai Tham', '1A20', '1AAF'),
101  'balinese' => array('Balinese', '1B00', '1B7F'),
102  'sundanese' => array('Sundanese', '1B80', '1BBF'),
103  'batak' => array('Batak', '1BC0', '1BFF'),
104  'lepcha' => array('Lepcha', '1C00', '1C4F'),
105  'ol_chiki' => array('Ol Chiki', '1C50', '1C7F'),
106  'sundanese_supplement' => array('Sundanese Supplement', '1CC0', '1CCF'),
107  'vedic_extensions' => array('Vedic Extensions', '1CD0', '1CFF'),
108  'phonetic_extensions' => array('Phonetic Extensions', '1D00', '1D7F'),
109  'phonetic_extensions_supplement' => array('Phonetic Extensions Supplement', '1D80', '1DBF'),
110  'combining_diacritical_marks_supplement' => array('Combining Diacritical Marks Supplement', '1DC0', '1DFF'),
111  'latin_extended_additional' => array('Latin Extended Additional', '1E00', '1EFF'),
112  'greek_extended' => array('Greek Extended', '1F00', '1FFF'),
113  'general_punctuation' => array('General Punctuation', '2000', '206F'),
114  'superscripts_and_subscripts' => array('Superscripts and Subscripts', '2070', '209F'),
115  'currency_symbols' => array('Currency Symbols', '20A0', '20CF'),
116  'combining_diacritical_marks_for_symbols' => array('Combining Diacritical Marks for Symbols', '20D0', '20FF'),
117  'letterlike_symbols' => array('Letterlike Symbols', '2100', '214F'),
118  'number_forms' => array('Number Forms', '2150', '218F'),
119  'arrows' => array('Arrows', '2190', '21FF'),
120  'mathematical_operators' => array('Mathematical Operators', '2200', '22FF'),
121  'miscellaneous_technical' => array('Miscellaneous Technical', '2300', '23FF'),
122  'control_pictures' => array('Control Pictures', '2400', '243F'),
123  'optical_character_recognition' => array('Optical Character Recognition', '2440', '245F'),
124  'enclosed_alphanumerics' => array('Enclosed Alphanumerics', '2460', '24FF'),
125  'box_drawing' => array('Box Drawing', '2500', '257F'),
126  'block_elements' => array('Block Elements', '2580', '259F'),
127  'geometric_shapes' => array('Geometric Shapes', '25A0', '25FF'),
128  'miscellaneous_symbols' => array('Miscellaneous Symbols', '2600', '26FF'),
129  'dingbats' => array('Dingbats', '2700', '27BF'),
130  'miscellaneous_mathematical_symbols_a' => array('Miscellaneous Mathematical Symbols-A', '27C0', '27EF'),
131  'supplemental_arrows_a' => array('Supplemental Arrows-A', '27F0', '27FF'),
132  'braille_patterns' => array('Braille Patterns', '2800', '28FF'),
133  'supplemental_arrows_b' => array('Supplemental Arrows-B', '2900', '297F'),
134  'miscellaneous_mathematical_symbols_b' => array('Miscellaneous Mathematical Symbols-B', '2980', '29FF'),
135  'supplemental_mathematical_operators' => array('Supplemental Mathematical Operators', '2A00', '2AFF'),
136  'miscellaneous_symbols_and_arrows' => array('Miscellaneous Symbols and Arrows', '2B00', '2BFF'),
137  'glagolitic' => array('Glagolitic', '2C00', '2C5F'),
138  'latin_extended_c' => array('Latin Extended-C', '2C60', '2C7F'),
139  'coptic' => array('Coptic', '2C80', '2CFF'),
140  'georgian_supplement' => array('Georgian Supplement', '2D00', '2D2F'),
141  'tifinagh' => array('Tifinagh', '2D30', '2D7F'),
142  'ethiopic_extended' => array('Ethiopic Extended', '2D80', '2DDF'),
143  'cyrillic_extended_a' => array('Cyrillic Extended-A', '2DE0', '2DFF'),
144  'supplemental_punctuation' => array('Supplemental Punctuation', '2E00', '2E7F'),
145  'cjk_radicals_supplement' => array('CJK Radicals Supplement', '2E80', '2EFF'),
146  'kangxi_radicals' => array('Kangxi Radicals', '2F00', '2FDF'),
147  'ideographic_description_characters' => array('Ideographic Description Characters', '2FF0', '2FFF'),
148  'cjk_symbols_and_punctuation' => array('CJK Symbols and Punctuation', '3000', '303F'),
149  'hiragana' => array('Hiragana', '3040', '309F'),
150  'katakana' => array('Katakana', '30A0', '30FF'),
151  'bopomofo' => array('Bopomofo', '3100', '312F'),
152  'hangul_compatibility_jamo' => array('Hangul Compatibility Jamo', '3130', '318F'),
153  'kanbun' => array('Kanbun', '3190', '319F'),
154  'bopomofo_extended' => array('Bopomofo Extended', '31A0', '31BF'),
155  'cjk_strokes' => array('CJK Strokes', '31C0', '31EF'),
156  'katakana_phonetic_extensions' => array('Katakana Phonetic Extensions', '31F0', '31FF'),
157  'enclosed_cjk_letters_and_months' => array('Enclosed CJK Letters and Months', '3200', '32FF'),
158  'cjk_compatibility' => array('CJK Compatibility', '3300', '33FF'),
159  'cjk_unified_ideographs_extension_a' => array('CJK Unified Ideographs Extension A', '3400', '4DBF'),
160  'yijing_hexagram_symbols' => array('Yijing Hexagram Symbols', '4DC0', '4DFF'),
161  'cjk_unified_ideographs' => array('CJK Unified Ideographs', '4E00', '9FFF'),
162  'yi_syllables' => array('Yi Syllables', 'A000', 'A48F'),
163  'yi_radicals' => array('Yi Radicals', 'A490', 'A4CF'),
164  'lisu' => array('Lisu', 'A4D0', 'A4FF'),
165  'vai' => array('Vai', 'A500', 'A63F'),
166  'cyrillic_extended_b' => array('Cyrillic Extended-B', 'A640', 'A69F'),
167  'bamum' => array('Bamum', 'A6A0', 'A6FF'),
168  'modifier_tone_letters' => array('Modifier Tone Letters', 'A700', 'A71F'),
169  'latin_extended_d' => array('Latin Extended-D', 'A720', 'A7FF'),
170  'syloti_nagri' => array('Syloti Nagri', 'A800', 'A82F'),
171  'common_indic_number_forms' => array('Common Indic Number Forms', 'A830', 'A83F'),
172  'phags_pa' => array('Phags-pa', 'A840', 'A87F'),
173  'saurashtra' => array('Saurashtra', 'A880', 'A8DF'),
174  'devanagari_extended' => array('Devanagari Extended', 'A8E0', 'A8FF'),
175  'kayah_li' => array('Kayah Li', 'A900', 'A92F'),
176  'rejang' => array('Rejang', 'A930', 'A95F'),
177  'hangul_jamo_extended_a' => array('Hangul Jamo Extended-A', 'A960', 'A97F'),
178  'javanese' => array('Javanese', 'A980', 'A9DF'),
179  'cham' => array('Cham', 'AA00', 'AA5F'),
180  'myanmar_extended_a' => array('Myanmar Extended-A', 'AA60', 'AA7F'),
181  'tai_viet' => array('Tai Viet', 'AA80', 'AADF'),
182  'meetei_mayek_extensions' => array('Meetei Mayek Extensions', 'AAE0', 'AAFF'),
183  'ethiopic_extended_a' => array('Ethiopic Extended-A', 'AB00', 'AB2F'),
184  'meetei_mayek' => array('Meetei Mayek', 'ABC0', 'ABFF'),
185  'hangul_syllables' => array('Hangul Syllables', 'AC00', 'D7AF'),
186  'hangul_jamo_extended_b' => array('Hangul Jamo Extended-B', 'D7B0', 'D7FF'),
187  'high_surrogates' => array('High Surrogates', 'D800', 'DB7F'),
188  'high_private_use_surrogates' => array('High Private Use Surrogates', 'DB80', 'DBFF'),
189  'low_surrogates' => array('Low Surrogates', 'DC00', 'DFFF'),
190  'private_use_area' => array('Private Use Area', 'E000', 'F8FF'),
191  'cjk_compatibility_ideographs' => array('CJK Compatibility Ideographs', 'F900', 'FAFF'),
192  'alphabetic_presentation_forms' => array('Alphabetic Presentation Forms', 'FB00', 'FB4F'),
193  'arabic_presentation_forms_a' => array('Arabic Presentation Forms-A', 'FB50', 'FDFF'),
194  'variation_selectors' => array('Variation Selectors', 'FE00', 'FE0F'),
195  'vertical_forms' => array('Vertical Forms', 'FE10', 'FE1F'),
196  'combining_half_marks' => array('Combining Half Marks', 'FE20', 'FE2F'),
197  'cjk_compatibility_forms' => array('CJK Compatibility Forms', 'FE30', 'FE4F'),
198  'small_form_variants' => array('Small Form Variants', 'FE50', 'FE6F'),
199  'arabic_presentation_forms_b' => array('Arabic Presentation Forms-B', 'FE70', 'FEFF'),
200  'halfwidth_and_fullwidth_forms' => array('Halfwidth and Fullwidth Forms', 'FF00', 'FFEF'),
201  'specials' => array('Specials', 'FFF0', 'FFFF'),
202  /* here ends the Basic Multilinguage Plane (BMP) */
203 
204  /*
205  * The following blocks are not yet supported well.
206  * It seems that the chars are taken from the BMP instead
207  *
208  'linear_b_syllabary' => array('Linear B Syllabary', '10000', '1007F'),
209  'linear_b_ideograms' => array('Linear B Ideograms', '10080', '100FF'),
210  'aegean_numbers' => array('Aegean Numbers', '10100', '1013F'),
211  'ancient_greek_numbers' => array('Ancient Greek Numbers', '10140', '1018F'),
212  'ancient_symbols' => array('Ancient Symbols', '10190', '101CF'),
213  'phaistos_disc' => array('Phaistos Disc', '101D0', '101FF'),
214  'lycian' => array('Lycian', '10280', '1029F'),
215  'carian' => array('Carian', '102A0', '102DF'),
216  'old_italic' => array('Old Italic', '10300', '1032F'),
217  'gothic' => array('Gothic', '10330', '1034F'),
218  'ugaritic' => array('Ugaritic', '10380', '1039F'),
219  'old_persian' => array('Old Persian', '103A0', '103DF'),
220  'deseret' => array('Deseret', '10400', '1044F'),
221  'shavian' => array('Shavian', '10450', '1047F'),
222  'osmanya' => array('Osmanya', '10480', '104AF'),
223  'cypriot_syllabary' => array('Cypriot Syllabary', '10800', '1083F'),
224  'imperial_aramaic' => array('Imperial Aramaic', '10840', '1085F'),
225  'phoenician' => array('Phoenician', '10900', '1091F'),
226  'lydian' => array('Lydian', '10920', '1093F'),
227  'meroitic_hieroglyphs' => array('Meroitic Hieroglyphs', '10980', '1099F'),
228  'meroitic_cursive' => array('Meroitic Cursive', '109A0', '109FF'),
229  'kharoshthi' => array('Kharoshthi', '10A00', '10A5F'),
230  'old_south_arabian' => array('Old South Arabian', '10A60', '10A7F'),
231  'avestan' => array('Avestan', '10B00', '10B3F'),
232  'inscriptional_parthian' => array('Inscriptional Parthian', '10B40', '10B5F'),
233  'inscriptional_pahlavi' => array('Inscriptional Pahlavi', '10B60', '10B7F'),
234  'old_turkic' => array('Old Turkic', '10C00', '10C4F'),
235  'rumi_numeral_symbols' => array('Rumi Numeral Symbols', '10E60', '10E7F'),
236  'brahmi' => array('Brahmi', '11000', '1107F'),
237  'kaithi' => array('Kaithi', '11080', '110CF'),
238  'sora_sompeng' => array('Sora Sompeng', '110D0', '110FF'),
239  'chakma' => array('Chakma', '11100', '1114F'),
240  'sharada' => array('Sharada', '11180', '111DF'),
241  'takri' => array('Takri', '11680', '116CF'),
242  'cuneiform' => array('Cuneiform', '12000', '123FF'),
243  'cuneiform_numbers_and_punctuation' => array('Cuneiform Numbers and Punctuation', '12400', '1247F'),
244  'egyptian_hieroglyphs' => array('Egyptian Hieroglyphs', '13000', '1342F'),
245  'bamum_supplement' => array('Bamum Supplement', '16800', '16A3F'),
246  'miao' => array('Miao', '16F00', '16F9F'),
247  'kana_supplement' => array('Kana Supplement', '1B000', '1B0FF'),
248  'byzantine_musical_symbols' => array('Byzantine Musical Symbols', '1D000', '1D0FF'),
249  'musical_symbols' => array('Musical Symbols', '1D100', '1D1FF'),
250  'ancient_greek_musical_notation' => array('Ancient Greek Musical Notation', '1D200', '1D24F'),
251  'tai_xuan_jing_symbols' => array('Tai Xuan Jing Symbols', '1D300', '1D35F'),
252  'counting_rod_numerals' => array('Counting Rod Numerals', '1D360', '1D37F'),
253  'mathematical_alphanumeric_symbols' => array('Mathematical Alphanumeric Symbols', '1D400', '1D7FF'),
254  'arabic_mathematical_alphabetic_symbols' => array('Arabic Mathematical Alphabetic Symbols', '1EE00', '1EEFF'),
255  'mahjong_tiles' => array('Mahjong Tiles', '1F000', '1F02F'),
256  'domino_tiles' => array('Domino Tiles', '1F030', '1F09F'),
257  'playing_cards' => array('Playing Cards', '1F0A0', '1F0FF'),
258  'enclosed_alphanumeric_supplement' => array('Enclosed Alphanumeric Supplement', '1F100', '1F1FF'),
259  'enclosed_ideographic_supplement' => array('Enclosed Ideographic Supplement', '1F200', '1F2FF'),
260  'miscellaneous_symbols_and_pictographs' => array('Miscellaneous Symbols And Pictographs', '1F300', '1F5FF'),
261  'emoticons' => array('Emoticons', '1F600', '1F64F'),
262  'transport_and_map_symbols' => array('Transport And Map Symbols', '1F680', '1F6FF'),
263  'alchemical_symbols' => array('Alchemical Symbols', '1F700', '1F77F'),
264  'cjk_unified_ideographs_extension_b' => array('CJK Unified Ideographs Extension B', '20000', '2A6DF'),
265  'cjk_unified_ideographs_extension_c' => array('CJK Unified Ideographs Extension C', '2A700', '2B73F'),
266  'cjk_unified_ideographs_extension_d' => array('CJK Unified Ideographs Extension D', '2B740', '2B81F'),
267  'cjk_compatibility_ideographs_supplement' => array('CJK Compatibility Ideographs Supplement', '2F800', '2FA1F'),
268  'tags' => array('Tags', 'E0000', 'E007F'),
269  'variation_selectors_supplement' => array('Variation Selectors Supplement', 'E0100', 'E01EF'),
270  'supplementary_private_use_area_a' => array('Supplementary Private Use Area-A', 'F0000', 'FFFFF'),
271  'supplementary_private_use_area_b' => array('Supplementary Private Use Area-B', '100000', '10FFFF')
272  */
273  );
274 
275  // settings context
276  private string $context = self::CONTEXT_NONE;
277 
278  // availability of the character selector
279  private int $availability = self::INHERIT;
280 
281  // list of added unicode block names
282  private array $added_blocks = array();
283 
284  // list of custom selector items (splitted custom block)
285  private array $custom_items = array();
286 
287  public function __construct(string $a_context = self::CONTEXT_NONE)
288  {
289  switch ($a_context) {
290  case self::CONTEXT_ADMIN:
291  case self::CONTEXT_TEST:
292  case self::CONTEXT_USER:
293  $this->context = $a_context;
294  break;
295  default:
296  $this->context = self::CONTEXT_NONE;
297  }
298  }
299 
303  public static function _getCurrentConfig(ilObjTest $a_test_obj = null): self
304  {
305  global $ilSetting, $ilUser;
306 
307  // check configuration from administration settings
308  $admin_config = new self(self::CONTEXT_ADMIN);
309  $admin_config->setAvailability((int) $ilSetting->get('char_selector_availability'));
310  $admin_config->setDefinition((string) $ilSetting->get('char_selector_definition'));
311  if ($admin_config->getAvailability() === self::INACTIVE) {
312  // a globally inactive selector can't be overwritten by users or tests
313  return $admin_config;
314  }
315 
316  // a test configuration is relevant for test runs
317  if (isset($a_test_obj)) {
318  $test_config = new self(self::CONTEXT_TEST);
319  $test_config->setAvailability((int) $a_test_obj->getCharSelectorAvailability());
320  $test_config->setDefinition((string) $a_test_obj->getCharSelectorDefinition());
321  if ($test_config->getAvailability() !== self::INHERIT) {
322  // a specific test configuration has precedence over user configuration
323  return $test_config;
324  }
325  }
326 
327  // check configuration from user settings
328  $user_config = new self(self::CONTEXT_USER);
329  $user_config->setAvailability((int) $ilUser->getPref('char_selector_availability'));
330  $user_config->setDefinition((string) $ilUser->getPref('char_selector_definition'));
331  if ($user_config->getAvailability() !== self::INHERIT) {
332  // take user specific config
333  return $user_config;
334  } else {
335  // take admin config as default
336  return $admin_config;
337  }
338  }
339 
344  public function getContext(): string
345  {
346  return $this->context;
347  }
348 
349  public function setAvailability(int $a_availability): void
350  {
351  switch ($a_availability) {
352  case self::INACTIVE:
353  case self::INHERIT:
354  case self::ENABLED:
355  case self::DISABLED:
356  $this->availability = $a_availability;
357  break;
358  default:
359  $this->availability = self::INHERIT;
360  }
361  }
362 
363  public function getAvailability(): int
364  {
365  return $this->availability;
366  }
367 
371  public function setAddedBlocks(array $a_blocks = array()): void
372  {
373  $this->added_blocks = array();
374  foreach ($a_blocks as $block_name) {
375  if ($block_name === "all" || array_key_exists($block_name, self::$unicode_blocks)) {
376  $this->added_blocks[] = $block_name;
377  }
378  }
379  }
380 
381  public function getAddedBlocks(): array
382  {
383  return $this->added_blocks;
384  }
385 
390  public function setCustomItems(string $a_items = ''): void
391  {
392  $this->custom_items = explode(' ', $a_items);
393  }
394 
399  public function getCustomItems(): string
400  {
401  return implode(' ', $this->custom_items);
402  }
403 
420  public function setDefinition(string $a_definition = ''): void
421  {
422  // first reset all previous settings
423  $this->added_blocks = array();
424  $this->custom_items = array();
425 
426  // set the default definition to all unicode blocks
427  if (trim($a_definition) === '') {
428  $a_definition = "[all]";
429  }
430 
431  // analyze definition items
432  $items = explode(' ', $a_definition);
433  foreach ($items as $item) {
434  if (($block_name = $this->extractUnicodeBlock($item)) !== '') {
435  $this->added_blocks[] = $block_name;
436  } elseif ($item !== '') {
437  $this->custom_items[] = trim($item);
438  }
439  }
440  }
441 
446  public function getDefinition(): string
447  {
448  $definition = implode(' ', $this->custom_items);
449  foreach ($this->added_blocks as $block_name) {
450  $definition .= ' [' . $block_name . ']';
451  }
452  return trim($definition);
453  }
454 
458  public function getBlockOptions(): array
459  {
460  global $lng;
461 
462  $options = array(
463  '' => $lng->txt('please_select'),
464  'all' => $lng->txt('char_selector_unicode_all')
465  );
466  foreach (array_keys(self::$unicode_blocks) as $block_name) {
467  $options[$block_name] = $this->getBlockTitle($block_name);
468  }
469  return $options;
470  }
471 
476  public function getBlockTitle(string $a_block_name): string
477  {
478  global $lng;
479 
480  $langvar = 'char_selector_unicode_' . $a_block_name;
481  if ($lng->txt($langvar) !== '-' . $langvar . '-') {
482  return $lng->txt($langvar);
483  } else {
484  return self::$unicode_blocks[$a_block_name][0];
485  }
486  }
487 
493  private function extractUnicodeBlock(string $a_item = ''): string
494  {
495  $a_item = trim($a_item);
496  $matches = array();
497  if (preg_match('/^\[(.+)\]$/', $a_item, $matches)) {
498  $block_name = $matches[1];
499  if ($block_name === 'all' || array_key_exists($block_name, self::$unicode_blocks)) {
500  return $block_name;
501  }
502  }
503  return '';
504  }
505 
511  public function getCharPages(): array
512  {
513  global $lng;
514 
515  $pages = array();
516 
517  // add custom block
518  //
519  $page = array($lng->txt('char_selector_custom_items'));
520  foreach ($this->custom_items as $item) {
521  if (strpos($item, '-') > 0) {
522  // handle range
523  $subitems = explode('-', $item);
524  $start = $this->getItemCodepoint($subitems[0]);
525  $end = $this->getItemCodepoint($subitems[1]);
526  $page[] = array($start, $end);
527  } else {
528  // handle normal item
529  $page[] = $this->getItemParsed($item);
530  }
531  }
532  if (count($page) > 1) {
533  $pages[] = $page;
534  }
535 
536  // add unicode blocks
537  //
538  $blocks = in_array('all', $this->added_blocks) ?
539  array_keys(self::$unicode_blocks) :
541 
542  foreach ($blocks as $block_name) {
543  $start = hexdec(self::$unicode_blocks[$block_name][1]);
544  $end = hexdec(self::$unicode_blocks[$block_name][2]);
545  $page = array($this->getBlockTitle($block_name), array($start, $end));
546  $pages[] = $page;
547  }
548 
549  return $pages;
550  }
551 
555  private function getItemCodepoint(string $a_item): string
556  {
557  if (preg_match('/^[uU]\+[0-9a-fA-F]+$/', $a_item)) {
558  return (int) hexdec(substr($a_item, 2));
559  } else {
560  //take the codepoint of the first character
561  return $this->utf8ToCodepoint($a_item);
562  }
563  }
564 
568  private function getItemParsed(string $a_item): string
569  {
570  return preg_replace_callback(
571  '/[uU]\+[0-9a-fA-F]+/',
572  array($this, 'getItemParsedCallback'),
573  $a_item
574  );
575  }
576 
582  private function getItemParsedCallback(array $matches): string
583  {
584  return $this->codepointToUtf8((int) hexdec(substr($matches[0], 2)));
585  }
586 
596  private function codepointToUtf8(int $codepoint): string
597  {
598  if ($codepoint < 0x80) {
599  return chr($codepoint);
600  }
601  if ($codepoint < 0x800) {
602  return chr($codepoint >> 6&0x3f|0xc0) .
603  chr($codepoint&0x3f|0x80);
604  }
605  if ($codepoint < 0x10000) {
606  return chr($codepoint >> 12&0x0f|0xe0) .
607  chr($codepoint >> 6&0x3f|0x80) .
608  chr($codepoint&0x3f|0x80);
609  }
610  if ($codepoint < 0x110000) {
611  return chr($codepoint >> 18&0x07|0xf0) .
612  chr($codepoint >> 12&0x3f|0x80) .
613  chr($codepoint >> 6&0x3f|0x80) .
614  chr($codepoint&0x3f|0x80);
615  }
616 
617  return '';
618  }
619 
629  private function utf8ToCodepoint(string $char): int
630  {
631  # Find the length
632  $z = ord($char[0]);
633  if ($z&0x80) {
634  $length = 0;
635  while ($z&0x80) {
636  $length++;
637  $z <<= 1;
638  }
639  } else {
640  $length = 1;
641  }
642 
643  if ($length != strlen($char)) {
644  return false;
645  }
646  if ($length == 1) {
647  return ord($char);
648  }
649 
650  # Mask off the length-determining bits and shift back to the original location
651  $z &= 0xff;
652  $z >>= $length;
653 
654  # Add in the free bits from subsequent bytes
655  for ($i = 1; $i < $length; $i++) {
656  $z <<= 6;
657  $z |= ord($char[$i])&0x3f;
658  }
659 
660  return $z;
661  }
662 }
setCustomItems(string $a_items='')
set the custom items
getBlockOptions()
get the options for a block selection
const CONTEXT_NONE
Configuration contexts.
$lng
static _getCurrentConfig(ilObjTest $a_test_obj=null)
Get the configuration that should be used for the current selector.
setAddedBlocks(array $a_blocks=array())
__construct(string $a_context=self::CONTEXT_NONE)
setDefinition(string $a_definition='')
utf8ToCodepoint(string $char)
Determine the Unicode codepoint of a single-character UTF-8 sequence.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const INACTIVE
Availabilities INACTIVE/INHERIT corresponds to an unconfigured selector (no database entries) ...
getItemParsedCallback(array $matches)
callback for replacement of unicode notations
getBlockTitle(string $a_block_name)
Get the title of a unicode block for display or selection A translation is used if it exists...
setAvailability(int $a_availability)
getDefinition()
Set the definition of the available characters.
global $ilSetting
Definition: privfeed.php:17
$ilUser
Definition: imgupload.php:34
extractUnicodeBlock(string $a_item='')
Extract the unicode block name from a definition item.
codepointToUtf8(int $codepoint)
Return the UTF-8 sequence for a given Unicode code point.
getItemCodepoint(string $a_item)
get the unicode index of an item
getItemParsed(string $a_item)
replace unicode notations with their utf8 chars in a string
getCharPages()
Get the character pages.
getCustomItems()
set the custom items
getContext()
get the context of the configuration (the context is set at initialisation and can&#39;t be changed) ...
$i
Definition: metadata.php:41