Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.

Differences Between: [Versions 310 and 400] [Versions 311 and 400] [Versions 39 and 400] [Versions 400 and 401] [Versions 400 and 402] [Versions 400 and 403]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * core_text unit tests.
  19   *
  20   * @package    core
  21   * @category   phpunit
  22   * @copyright  2012 Petr Skoda {@link http://skodak.org}
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  
  29  /**
  30   * Unit tests for our utf-8 aware text processing.
  31   *
  32   * @package    core
  33   * @category   phpunit
  34   * @copyright  2010 Petr Skoda (http://skodak.org)
  35   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36   * @coversDefaultClass \core_text
  37   *
  38   */
  39  class text_test extends advanced_testcase {
  40  
  41      /**
  42       * Tests the static parse charset method.
  43       *
  44       * @covers ::parse_charset()
  45       */
  46      public function test_parse_charset() {
  47          $this->assertSame('windows-1250', core_text::parse_charset('Cp1250'));
  48          // Some encoding moodle does not use.
  49          $this->assertSame('windows-1252', core_text::parse_charset('ms-ansi'));
  50      }
  51  
  52      /**
  53       * Tests the static convert method.
  54       *
  55       * @covers ::convert()
  56       */
  57      public function test_convert() {
  58          $this->assertSame('', core_text::convert('', 'utf-8', 'utf-8'));
  59          $utf8 = "Žluťoučký koníček";
  60          $iso2 = pack("H*", "ae6c75bb6f75e86bfd206b6f6eede8656b");
  61          $win  = pack("H*", "8e6c759d6f75e86bfd206b6f6eede8656b");
  62          $this->assertSame($iso2, core_text::convert($utf8, 'utf-8', 'iso-8859-2'));
  63          $this->assertSame($utf8, core_text::convert($iso2, 'iso-8859-2', 'utf-8'));
  64          $this->assertSame($win, core_text::convert($utf8, 'utf-8', 'win-1250'));
  65          $this->assertSame($utf8, core_text::convert($win, 'win-1250', 'utf-8'));
  66          $this->assertSame($iso2, core_text::convert($win, 'win-1250', 'iso-8859-2'));
  67          $this->assertSame($win, core_text::convert($iso2, 'iso-8859-2', 'win-1250'));
  68          $this->assertSame($iso2, core_text::convert($iso2, 'iso-8859-2', 'iso-8859-2'));
  69          $this->assertSame($win, core_text::convert($win, 'win-1250', 'cp1250'));
  70          $this->assertSame($utf8, core_text::convert($utf8, 'utf-8', 'utf-8'));
  71  
  72          $utf8 = '言語設定';
  73          $str = pack("H*", "b8c0b8ecc0dfc4ea"); // EUC-JP
  74          $this->assertSame($str, core_text::convert($utf8, 'utf-8', 'EUC-JP'));
  75          $this->assertSame($utf8, core_text::convert($str, 'EUC-JP', 'utf-8'));
  76          $this->assertSame($utf8, core_text::convert($utf8, 'utf-8', 'utf-8'));
  77  
  78          $str = pack("H*", "1b24423840386c405f446a1b2842"); // ISO-2022-JP
  79          $this->assertSame($str, core_text::convert($utf8, 'utf-8', 'ISO-2022-JP'));
  80          $this->assertSame($utf8, core_text::convert($str, 'ISO-2022-JP', 'utf-8'));
  81          $this->assertSame($utf8, core_text::convert($utf8, 'utf-8', 'utf-8'));
  82  
  83          $str = pack("H*", "8cbe8cea90dd92e8"); // SHIFT-JIS
  84          $this->assertSame($str, core_text::convert($utf8, 'utf-8', 'SHIFT-JIS'));
  85          $this->assertSame($utf8, core_text::convert($str, 'SHIFT-JIS', 'utf-8'));
  86          $this->assertSame($utf8, core_text::convert($utf8, 'utf-8', 'utf-8'));
  87  
  88          $utf8 = '简体中文';
  89          $str = pack("H*", "bcf2cce5d6d0cec4"); // GB2312
  90          $this->assertSame($str, core_text::convert($utf8, 'utf-8', 'GB2312'));
  91          $this->assertSame($utf8, core_text::convert($str, 'GB2312', 'utf-8'));
  92          $this->assertSame($utf8, core_text::convert($utf8, 'utf-8', 'utf-8'));
  93  
  94          $str = pack("H*", "bcf2cce5d6d0cec4"); // GB18030
  95          $this->assertSame($str, core_text::convert($utf8, 'utf-8', 'GB18030'));
  96          $this->assertSame($utf8, core_text::convert($str, 'GB18030', 'utf-8'));
  97          $this->assertSame($utf8, core_text::convert($utf8, 'utf-8', 'utf-8'));
  98  
  99          $utf8 = "Žluťoučký koníček";
 100          $this->assertSame('Zlutoucky konicek', core_text::convert($utf8, 'utf-8', 'ascii'));
 101          $this->assertSame($utf8, core_text::convert($utf8.chr(130), 'utf-8', 'utf-8'));
 102          $utf8 = "Der eine stößt den Speer zum Mann";
 103          $this->assertSame('Der eine stosst den Speer zum Mann', core_text::convert($utf8, 'utf-8', 'ascii'));
 104          $iso1 = core_text::convert($utf8, 'utf-8', 'iso-8859-1');
 105          $this->assertSame('Der eine stosst den Speer zum Mann', core_text::convert($iso1, 'iso-8859-1', 'ascii'));
 106          $utf8 = "A æ Übérmensch på høyeste nivå! И я люблю PHP! есть. アクセシビリティ. fi";
 107          $this->assertSame("A ae Ubermensch pa hoyeste niva! I a lublu PHP! est'. akuseshibiriti. fi",
 108              core_text::convert($utf8, 'utf-8', 'ascii'));
 109      }
 110  
 111      /**
 112       * Tests the static sub string method.
 113       *
 114       * @covers ::substr()
 115       */
 116      public function test_substr() {
 117          $str = "Žluťoučký koníček";
 118          $this->assertSame($str, core_text::substr($str, 0));
 119          $this->assertSame('luťoučký koníček', core_text::substr($str, 1));
 120          $this->assertSame('luť', core_text::substr($str, 1, 3));
 121          $this->assertSame($str, core_text::substr($str, 0, 100));
 122          $this->assertSame('če', core_text::substr($str, -3, 2));
 123  
 124          $iso2 = pack("H*", "ae6c75bb6f75e86bfd206b6f6eede8656b");
 125          $this->assertSame(core_text::convert('luť', 'utf-8', 'iso-8859-2'), core_text::substr($iso2, 1, 3, 'iso-8859-2'));
 126          $this->assertSame(core_text::convert($str, 'utf-8', 'iso-8859-2'), core_text::substr($iso2, 0, 100, 'iso-8859-2'));
 127          $this->assertSame(core_text::convert('če', 'utf-8', 'iso-8859-2'), core_text::substr($iso2, -3, 2, 'iso-8859-2'));
 128  
 129          $win  = pack("H*", "8e6c759d6f75e86bfd206b6f6eede8656b");
 130          $this->assertSame(core_text::convert('luť', 'utf-8', 'cp1250'), core_text::substr($win, 1, 3, 'cp1250'));
 131          $this->assertSame(core_text::convert($str, 'utf-8', 'cp1250'), core_text::substr($win, 0, 100, 'cp1250'));
 132          $this->assertSame(core_text::convert('če', 'utf-8', 'cp1250'), core_text::substr($win, -3, 2, 'cp1250'));
 133  
 134          $str = pack("H*", "b8c0b8ecc0dfc4ea"); // EUC-JP
 135          $s = pack("H*", "b8ec"); // EUC-JP
 136          $this->assertSame($s, core_text::substr($str, 1, 1, 'EUC-JP'));
 137  
 138          $str = pack("H*", "1b24423840386c405f446a1b2842"); // ISO-2022-JP
 139          $s = pack("H*", "1b2442386c1b2842"); // ISO-2022-JP
 140          $this->assertSame($s, core_text::substr($str, 1, 1, 'ISO-2022-JP'));
 141  
 142          $str = pack("H*", "8cbe8cea90dd92e8"); // SHIFT-JIS
 143          $s = pack("H*", "8cea"); // SHIFT-JIS
 144          $this->assertSame($s, core_text::substr($str, 1, 1, 'SHIFT-JIS'));
 145  
 146          $str = pack("H*", "bcf2cce5d6d0cec4"); // GB2312
 147          $s = pack("H*", "cce5"); // GB2312
 148          $this->assertSame($s, core_text::substr($str, 1, 1, 'GB2312'));
 149  
 150          $str = pack("H*", "bcf2cce5d6d0cec4"); // GB18030
 151          $s = pack("H*", "cce5"); // GB18030
 152          $this->assertSame($s, core_text::substr($str, 1, 1, 'GB18030'));
 153      }
 154  
 155      /**
 156       * Tests the static string length method.
 157       *
 158       * @covers ::strlen()
 159       */
 160      public function test_strlen() {
 161          $str = "Žluťoučký koníček";
 162          $this->assertSame(17, core_text::strlen($str));
 163  
 164          $iso2 = pack("H*", "ae6c75bb6f75e86bfd206b6f6eede8656b");
 165          $this->assertSame(17, core_text::strlen($iso2, 'iso-8859-2'));
 166  
 167          $win  = pack("H*", "8e6c759d6f75e86bfd206b6f6eede8656b");
 168          $this->assertSame(17, core_text::strlen($win, 'cp1250'));
 169  
 170          $str = pack("H*", "b8ec"); // EUC-JP
 171          $this->assertSame(1, core_text::strlen($str, 'EUC-JP'));
 172          $str = pack("H*", "b8c0b8ecc0dfc4ea"); // EUC-JP
 173          $this->assertSame(4, core_text::strlen($str, 'EUC-JP'));
 174  
 175          $str = pack("H*", "1b2442386c1b2842"); // ISO-2022-JP
 176          $this->assertSame(1, core_text::strlen($str, 'ISO-2022-JP'));
 177          $str = pack("H*", "1b24423840386c405f446a1b2842"); // ISO-2022-JP
 178          $this->assertSame(4, core_text::strlen($str, 'ISO-2022-JP'));
 179  
 180          $str = pack("H*", "8cea"); // SHIFT-JIS
 181          $this->assertSame(1, core_text::strlen($str, 'SHIFT-JIS'));
 182          $str = pack("H*", "8cbe8cea90dd92e8"); // SHIFT-JIS
 183          $this->assertSame(4, core_text::strlen($str, 'SHIFT-JIS'));
 184  
 185          $str = pack("H*", "cce5"); // GB2312
 186          $this->assertSame(1, core_text::strlen($str, 'GB2312'));
 187          $str = pack("H*", "bcf2cce5d6d0cec4"); // GB2312
 188          $this->assertSame(4, core_text::strlen($str, 'GB2312'));
 189  
 190          $str = pack("H*", "cce5"); // GB18030
 191          $this->assertSame(1, core_text::strlen($str, 'GB18030'));
 192          $str = pack("H*", "bcf2cce5d6d0cec4"); // GB18030
 193          $this->assertSame(4, core_text::strlen($str, 'GB18030'));
 194      }
 195  
 196      /**
 197       * Test unicode safe string truncation.
 198       *
 199       * @covers ::str_max_bytes()
 200       */
 201      public function test_str_max_bytes() {
 202          // These are all 3 byte characters, so this is a 12-byte string.
 203          $str = '言語設定';
 204  
 205          $this->assertEquals(12, strlen($str));
 206  
 207          // Step back, shortening the string 1 byte at a time. Should remove in 1 char chunks.
 208          $conv = core_text::str_max_bytes($str, 12);
 209          $this->assertEquals(12, strlen($conv));
 210          $this->assertSame('言語設定', $conv);
 211          $conv = core_text::str_max_bytes($str, 11);
 212          $this->assertEquals(9, strlen($conv));
 213          $this->assertSame('言語設', $conv);
 214          $conv = core_text::str_max_bytes($str, 10);
 215          $this->assertEquals(9, strlen($conv));
 216          $this->assertSame('言語設', $conv);
 217          $conv = core_text::str_max_bytes($str, 9);
 218          $this->assertEquals(9, strlen($conv));
 219          $this->assertSame('言語設', $conv);
 220          $conv = core_text::str_max_bytes($str, 8);
 221          $this->assertEquals(6, strlen($conv));
 222          $this->assertSame('言語', $conv);
 223  
 224          // Now try a mixed byte string.
 225          $str = '言語設a定';
 226  
 227          $this->assertEquals(13, strlen($str));
 228  
 229          $conv = core_text::str_max_bytes($str, 11);
 230          $this->assertEquals(10, strlen($conv));
 231          $this->assertSame('言語設a', $conv);
 232          $conv = core_text::str_max_bytes($str, 10);
 233          $this->assertEquals(10, strlen($conv));
 234          $this->assertSame('言語設a', $conv);
 235          $conv = core_text::str_max_bytes($str, 9);
 236          $this->assertEquals(9, strlen($conv));
 237          $this->assertSame('言語設', $conv);
 238          $conv = core_text::str_max_bytes($str, 8);
 239          $this->assertEquals(6, strlen($conv));
 240          $this->assertSame('言語', $conv);
 241  
 242          // Test 0 byte case.
 243          $conv = core_text::str_max_bytes($str, 0);
 244          $this->assertEquals(0, strlen($conv));
 245          $this->assertSame('', $conv);
 246      }
 247  
 248      /**
 249       * Tests the static strtolower method.
 250       *
 251       * @covers ::strtolower()
 252       */
 253      public function test_strtolower() {
 254          $str = "Žluťoučký koníček";
 255          $low = 'žluťoučký koníček';
 256          $this->assertSame($low, core_text::strtolower($str));
 257  
 258          $iso2 = pack("H*", "ae6c75bb6f75e86bfd206b6f6eede8656b");
 259          $this->assertSame(core_text::convert($low, 'utf-8', 'iso-8859-2'), core_text::strtolower($iso2, 'iso-8859-2'));
 260  
 261          $win  = pack("H*", "8e6c759d6f75e86bfd206b6f6eede8656b");
 262          $this->assertSame(core_text::convert($low, 'utf-8', 'cp1250'), core_text::strtolower($win, 'cp1250'));
 263  
 264          $str = '言語設定';
 265          $this->assertSame($str, core_text::strtolower($str));
 266  
 267          $str = '简体中文';
 268          $this->assertSame($str, core_text::strtolower($str));
 269  
 270          $str = pack("H*", "1b24423840386c405f446a1b2842"); // ISO-2022-JP
 271          $this->assertSame($str, core_text::strtolower($str, 'ISO-2022-JP'));
 272  
 273          $str = pack("H*", "8cbe8cea90dd92e8"); // SHIFT-JIS
 274          $this->assertSame($str, core_text::strtolower($str, 'SHIFT-JIS'));
 275  
 276          $str = pack("H*", "bcf2cce5d6d0cec4"); // GB2312
 277          $this->assertSame($str, core_text::strtolower($str, 'GB2312'));
 278  
 279          $str = pack("H*", "bcf2cce5d6d0cec4"); // GB18030
 280          $this->assertSame($str, core_text::strtolower($str, 'GB18030'));
 281  
 282          $str = 1309528800;
 283          $this->assertSame((string)$str, core_text::strtolower($str));
 284      }
 285  
 286      /**
 287       * Tests the static strtoupper.
 288       *
 289       * @covers ::strtoupper()
 290       */
 291      public function test_strtoupper() {
 292          $str = "Žluťoučký koníček";
 293          $up  = 'ŽLUŤOUČKÝ KONÍČEK';
 294          $this->assertSame($up, core_text::strtoupper($str));
 295  
 296          $iso2 = pack("H*", "ae6c75bb6f75e86bfd206b6f6eede8656b");
 297          $this->assertSame(core_text::convert($up, 'utf-8', 'iso-8859-2'), core_text::strtoupper($iso2, 'iso-8859-2'));
 298  
 299          $win  = pack("H*", "8e6c759d6f75e86bfd206b6f6eede8656b");
 300          $this->assertSame(core_text::convert($up, 'utf-8', 'cp1250'), core_text::strtoupper($win, 'cp1250'));
 301  
 302          $str = '言語設定';
 303          $this->assertSame($str, core_text::strtoupper($str));
 304  
 305          $str = '简体中文';
 306          $this->assertSame($str, core_text::strtoupper($str));
 307  
 308          $str = pack("H*", "1b24423840386c405f446a1b2842"); // ISO-2022-JP
 309          $this->assertSame($str, core_text::strtoupper($str, 'ISO-2022-JP'));
 310  
 311          $str = pack("H*", "8cbe8cea90dd92e8"); // SHIFT-JIS
 312          $this->assertSame($str, core_text::strtoupper($str, 'SHIFT-JIS'));
 313  
 314          $str = pack("H*", "bcf2cce5d6d0cec4"); // GB2312
 315          $this->assertSame($str, core_text::strtoupper($str, 'GB2312'));
 316  
 317          $str = pack("H*", "bcf2cce5d6d0cec4"); // GB18030
 318          $this->assertSame($str, core_text::strtoupper($str, 'GB18030'));
 319      }
 320  
 321      /**
 322       * Test the strrev method.
 323       *
 324       * @covers ::strrev()
 325       */
 326      public function test_strrev() {
 327          $strings = array(
 328              "Žluťoučký koníček" => "kečínok ýkčuoťulŽ",
 329              'ŽLUŤOUČKÝ KONÍČEK' => "KEČÍNOK ÝKČUOŤULŽ",
 330              '言語設定' => '定設語言',
 331              '简体中文' => '文中体简',
 332              "Der eine stößt den Speer zum Mann" => "nnaM muz reepS ned tßöts enie reD"
 333          );
 334          foreach ($strings as $before => $after) {
 335              // Make sure we can reverse it both ways and that it comes out the same.
 336              $this->assertSame($after, core_text::strrev($before));
 337              $this->assertSame($before, core_text::strrev($after));
 338              // Reverse it twice to be doubly sure.
 339              $this->assertSame($after, core_text::strrev(core_text::strrev($after)));
 340          }
 341      }
 342  
 343      /**
 344       * Tests the static strpos method.
 345       *
 346       * @covers ::strpos()
 347       */
 348      public function test_strpos() {
 349          $str = "Žluťoučký koníček";
 350          $this->assertSame(10, core_text::strpos($str, 'koníč'));
 351      }
 352  
 353      /**
 354       * Tests the static strrpos.
 355       *
 356       * @covers ::strrpos()
 357       */
 358      public function test_strrpos() {
 359          $str = "Žluťoučký koníček";
 360          $this->assertSame(11, core_text::strrpos($str, 'o'));
 361      }
 362  
 363      /**
 364       * Tests the static specialtoascii method.
 365       *
 366       * @covers ::specialtoascii()
 367       */
 368      public function test_specialtoascii() {
 369          $str = "Žluťoučký koníček";
 370          $this->assertSame('Zlutoucky konicek', core_text::specialtoascii($str));
 371  
 372          $utf8 = "Der eine stößt den Speer zum Mann";
 373          $iso1 = core_text::convert($utf8, 'utf-8', 'iso-8859-1');
 374          $this->assertSame('Der eine stosst den Speer zum Mann', core_text::specialtoascii($utf8));
 375          $this->assertSame('Der eine stosst den Speer zum Mann', core_text::specialtoascii($iso1, 'iso-8859-1'));
 376  
 377          $str = 'àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ';
 378          $this->assertSame('aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY', core_text::specialtoascii($str));
 379  
 380          $utf8 = 'A æ Übérmensch på høyeste nivå! И я люблю PHP! есть. fi';
 381          $this->assertSame('A ae Ubermensch pa hoyeste niva! I a lublu PHP! est\'. fi', core_text::specialtoascii($utf8, 'utf8'));
 382  
 383          $utf8 = 'キャンパス Αλφαβητικός Κατάλογος Лорем ипсум долор сит амет';
 384          $this->assertSame('kyanpasu Alphabetikos Katalogos Lorem ipsum dolor sit amet', core_text::specialtoascii($utf8));
 385      }
 386  
 387      /**
 388       * Tests the static encode_mimeheader method.
 389       *
 390       * @covers ::encode_mimeheader()
 391       * @covers \moodle_phpmailer::encodeHeader()
 392       */
 393      public function test_encode_mimeheader() {
 394          global $CFG;
 395          require_once($CFG->libdir.'/phpmailer/moodle_phpmailer.php');
 396          $mailer = new moodle_phpmailer();
 397  
 398          // Encode short string with non-latin characters.
 399          $str = "Žluťoučký koníček";
 400          $encodedstr = '=?utf-8?B?xb1sdcWlb3XEjWvDvSBrb27DrcSNZWs=?=';
 401          $this->assertSame($encodedstr, core_text::encode_mimeheader($str));
 402          $this->assertSame($encodedstr, $mailer->encodeHeader($str));
 403          $this->assertSame('"' . $encodedstr . '"', $mailer->encodeHeader($str, 'phrase'));
 404  
 405          // Encode short string without non-latin characters. Make sure the quotes are escaped in quoted email headers.
 406          $latinstr = 'text"with quotes';
 407          $this->assertSame($latinstr, core_text::encode_mimeheader($latinstr));
 408          $this->assertSame($latinstr, $mailer->encodeHeader($latinstr));
 409          $this->assertSame('"text\\"with quotes"', $mailer->encodeHeader($latinstr, 'phrase'));
 410  
 411          // Encode long string without non-latin characters.
 412          $longlatinstr = 'This is a very long text that still should not be split into several lines in the email headers because '.
 413              'it does not have any non-latin characters. The "quotes" and \\backslashes should be escaped only if it\'s a part of email address';
 414          $this->assertSame($longlatinstr, core_text::encode_mimeheader($longlatinstr));
 415          $this->assertSame($longlatinstr, $mailer->encodeHeader($longlatinstr));
 416          $longlatinstrwithslash = preg_replace(['/\\\\/', "/\"/"], ['\\\\\\', '\\"'], $longlatinstr);
 417          $this->assertSame('"' . $longlatinstrwithslash . '"', $mailer->encodeHeader($longlatinstr, 'phrase'));
 418  
 419          // Encode long string with non-latin characters.
 420          $longstr = "Неопознанная ошибка в файле C:\\tmp\\: \"Не пользуйтесь виндоуз\"";
 421          $encodedlongstr = "=?utf-8?B?0J3QtdC+0L/QvtC30L3QsNC90L3QsNGPINC+0YjQuNCx0LrQsCDQsiDRhNCw?=
 422   =?utf-8?B?0LnQu9C1IEM6XHRtcFw6ICLQndC1INC/0L7Qu9GM0LfRg9C50YLQtdGB?=
 423   =?utf-8?B?0Ywg0LLQuNC90LTQvtGD0Lci?=";
 424          $this->assertSame($encodedlongstr, $mailer->encodeHeader($longstr));
 425          $this->assertSame('"' . $encodedlongstr . '"', $mailer->encodeHeader($longstr, 'phrase'));
 426      }
 427  
 428      /**
 429       * Tests the static entities_to_utf8 method.
 430       *
 431       * @covers ::entities_to_utf8()
 432       */
 433      public function test_entities_to_utf8() {
 434          $str = "&#x17d;lu&#x165;ou&#x10d;k&#xfd; kon&iacute;&#269;ek&copy;&quot;&amp;&lt;&gt;&sect;&laquo;";
 435          $this->assertSame("Žluťoučký koníček©\"&<>§«", core_text::entities_to_utf8($str));
 436      }
 437  
 438      /**
 439       * Tests the static utf8_to_entities method.
 440       *
 441       * @covers ::utf8_to_entities()
 442       */
 443      public function test_utf8_to_entities() {
 444          $str = "&#x17d;luťoučký kon&iacute;ček&copy;&quot;&amp;&lt;&gt;&sect;&laquo;";
 445          $this->assertSame("&#x17d;lu&#x165;ou&#x10d;k&#xfd; kon&iacute;&#x10d;ek&copy;&quot;&amp;&lt;&gt;&sect;&laquo;", core_text::utf8_to_entities($str));
 446          $this->assertSame("&#381;lu&#357;ou&#269;k&#253; kon&iacute;&#269;ek&copy;&quot;&amp;&lt;&gt;&sect;&laquo;", core_text::utf8_to_entities($str, true));
 447  
 448          $str = "&#381;luťoučký kon&iacute;ček&copy;&quot;&amp;&lt;&gt;&sect;&laquo;";
 449          $this->assertSame("&#x17d;lu&#x165;ou&#x10d;k&#xfd; kon&#xed;&#x10d;ek&#xa9;\"&<>&#xa7;&#xab;", core_text::utf8_to_entities($str, false, true));
 450          $this->assertSame("&#381;lu&#357;ou&#269;k&#253; kon&#237;&#269;ek&#169;\"&<>&#167;&#171;", core_text::utf8_to_entities($str, true, true));
 451      }
 452  
 453      /**
 454       * Tests the static trim_utf8_bom method.
 455       *
 456       * @covers ::trim_utf8_bom()
 457       */
 458      public function test_trim_utf8_bom() {
 459          $bom = "\xef\xbb\xbf";
 460          $str = "Žluťoučký koníček";
 461          $this->assertSame($str.$bom, core_text::trim_utf8_bom($bom.$str.$bom));
 462      }
 463  
 464      /**
 465       * Tests the static remove_unicode_non_characters method.
 466       *
 467       * @covers ::remove_unicode_non_characters()
 468       */
 469      public function test_remove_unicode_non_characters() {
 470          // Confirm that texts which don't contain these characters are unchanged.
 471          $this->assertSame('Frogs!', core_text::remove_unicode_non_characters('Frogs!'));
 472  
 473          // Even if they contain some very scary characters.
 474          $example = html_entity_decode('A&#xfffd;&#x1d15f;B');
 475          $this->assertSame($example, core_text::remove_unicode_non_characters($example));
 476  
 477          // Non-characters are removed wherever they may be, with other characters left.
 478          $example = html_entity_decode('&#xfffe;A&#xffff;B&#x8fffe;C&#xfdd0;D&#xfffd;E&#xfdd5;');
 479          $expected = html_entity_decode('ABCD&#xfffd;E');
 480          $this->assertSame($expected, core_text::remove_unicode_non_characters($example));
 481  
 482          // If you only have a non-character, you get empty string.
 483          $example = html_entity_decode('&#xfffe;');
 484          $this->assertSame('', core_text::remove_unicode_non_characters($example));
 485      }
 486  
 487      /**
 488       * Tests the static get_encodings method.
 489       *
 490       * @covers ::get_encodings()
 491       */
 492      public function test_get_encodings() {
 493          $encodings = core_text::get_encodings();
 494          $this->assertTrue(is_array($encodings));
 495          $this->assertTrue(count($encodings) > 1);
 496          $this->assertTrue(isset($encodings['UTF-8']));
 497      }
 498  
 499      /**
 500       * Tests the static code2utf8 method.
 501       *
 502       * @covers ::code2utf8()
 503       */
 504      public function test_code2utf8() {
 505          $this->assertSame('Ž', core_text::code2utf8(381));
 506      }
 507  
 508      /**
 509       * Tests the static utf8ord method.
 510       *
 511       * @covers ::utf8ord()
 512       */
 513      public function test_utf8ord() {
 514          $this->assertSame(ord(''), core_text::utf8ord(''));
 515          $this->assertSame(ord('f'), core_text::utf8ord('f'));
 516          $this->assertSame(0x03B1, core_text::utf8ord('α'));
 517          $this->assertSame(0x0439, core_text::utf8ord('й'));
 518          $this->assertSame(0x2FA1F, core_text::utf8ord('𯨟'));
 519          $this->assertSame(381, core_text::utf8ord('Ž'));
 520      }
 521  
 522      /**
 523       * Tests the static strtotitle method.
 524       *
 525       * @covers ::strtotitle()
 526       */
 527      public function test_strtotitle() {
 528          $str = "žluťoučký koníček";
 529          $this->assertSame("Žluťoučký Koníček", core_text::strtotitle($str));
 530      }
 531  
 532      /**
 533       * Test strrchr.
 534       *
 535       * @covers ::strrchr()
 536       */
 537      public function test_strrchr() {
 538          $str = "Žluťoučký koníček";
 539          $this->assertSame('koníček', core_text::strrchr($str, 'koní'));
 540          $this->assertSame('Žluťoučký ', core_text::strrchr($str, 'koní', true));
 541          $this->assertFalse(core_text::strrchr($str, 'A'));
 542          $this->assertFalse(core_text::strrchr($str, 'ç', true));
 543      }
 544  
 545      /**
 546       * Tests the static checker is_charset_supported
 547       *
 548       * @dataProvider is_charset_supported_provider()
 549       * @param string $charset
 550       * @param bool $expected
 551       * @covers ::is_charset_supported()
 552       */
 553      public function test_is_charset_supported(string $charset, bool $expected) {
 554          $charset = core_text::parse_charset($charset);
 555          $this->assertEquals($expected, core_text::is_charset_supported($charset));
 556      }
 557  
 558      /**
 559       * Provider for the test_is_charset_supported()
 560       * @return array[]
 561       */
 562      public function is_charset_supported_provider() {
 563          return [
 564              "Check unsupported windows charset" => [
 565                  "cp1250", false
 566              ],
 567              "Check supported windows charset" => [
 568                  "cp1252", true
 569              ]
 570          ];
 571      }
 572  }