| 1 | efrain | 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 | namespace core;
 | 
        
           |  |  | 18 |   | 
        
           |  |  | 19 | /**
 | 
        
           |  |  | 20 |  * Tests for Moodle's String Formatter.
 | 
        
           |  |  | 21 |  *
 | 
        
           |  |  | 22 |  * @package   core
 | 
        
           |  |  | 23 |  * @copyright 2023 Andrew Nicols <andrew@nicols.co.uk>
 | 
        
           |  |  | 24 |  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 25 |  * @covers    \core\formatting
 | 
        
           |  |  | 26 |  * @coversDefaultClass \core\formatting
 | 
        
           |  |  | 27 |  */
 | 
        
           | 1441 | ariadna | 28 | final class formatting_test extends \advanced_testcase {
 | 
        
           | 1 | efrain | 29 |     /**
 | 
        
           |  |  | 30 |      * @covers ::format_string
 | 
        
           |  |  | 31 |      */
 | 
        
           |  |  | 32 |     public function test_format_string_striptags_cfg(): void {
 | 
        
           |  |  | 33 |         global $CFG;
 | 
        
           |  |  | 34 |   | 
        
           |  |  | 35 |         $this->resetAfterTest();
 | 
        
           |  |  | 36 |   | 
        
           |  |  | 37 |         $formatting = new formatting();
 | 
        
           |  |  | 38 |   | 
        
           |  |  | 39 |         // Check < and > signs.
 | 
        
           |  |  | 40 |         $CFG->formatstringstriptags = false;
 | 
        
           |  |  | 41 |         $this->assertSame('x < 1', $formatting->format_string('x < 1'));
 | 
        
           |  |  | 42 |         $this->assertSame('x > 1', $formatting->format_string('x > 1'));
 | 
        
           |  |  | 43 |         $this->assertSame('x < 1 and x > 0', $formatting->format_string('x < 1 and x > 0'));
 | 
        
           |  |  | 44 |   | 
        
           |  |  | 45 |         $CFG->formatstringstriptags = true;
 | 
        
           |  |  | 46 |         $this->assertSame('x < 1', $formatting->format_string('x < 1'));
 | 
        
           |  |  | 47 |         $this->assertSame('x > 1', $formatting->format_string('x > 1'));
 | 
        
           |  |  | 48 |         $this->assertSame('x < 1 and x > 0', $formatting->format_string('x < 1 and x > 0'));
 | 
        
           |  |  | 49 |     }
 | 
        
           |  |  | 50 |   | 
        
           |  |  | 51 |     /**
 | 
        
           |  |  | 52 |      * @covers ::format_string
 | 
        
           |  |  | 53 |      */
 | 
        
           |  |  | 54 |     public function test_format_string_striptags_prop(): void {
 | 
        
           |  |  | 55 |         $formatting = new formatting();
 | 
        
           |  |  | 56 |   | 
        
           |  |  | 57 |         // Check < and > signs.
 | 
        
           |  |  | 58 |         $formatting->set_striptags(false);
 | 
        
           |  |  | 59 |         $this->assertSame('x < 1', $formatting->format_string('x < 1'));
 | 
        
           |  |  | 60 |         $this->assertSame('x > 1', $formatting->format_string('x > 1'));
 | 
        
           |  |  | 61 |         $this->assertSame('x < 1 and x > 0', $formatting->format_string('x < 1 and x > 0'));
 | 
        
           |  |  | 62 |   | 
        
           |  |  | 63 |         $formatting->set_striptags(true);
 | 
        
           |  |  | 64 |         $this->assertSame('x < 1', $formatting->format_string('x < 1'));
 | 
        
           |  |  | 65 |         $this->assertSame('x > 1', $formatting->format_string('x > 1'));
 | 
        
           |  |  | 66 |         $this->assertSame('x < 1 and x > 0', $formatting->format_string('x < 1 and x > 0'));
 | 
        
           |  |  | 67 |     }
 | 
        
           |  |  | 68 |   | 
        
           |  |  | 69 |     /**
 | 
        
           |  |  | 70 |      * @covers ::format_string
 | 
        
           |  |  | 71 |      * @dataProvider format_string_provider
 | 
        
           |  |  | 72 |      * @param string $expected
 | 
        
           |  |  | 73 |      * @param mixed $input
 | 
        
           |  |  | 74 |      * @param array $options
 | 
        
           |  |  | 75 |      */
 | 
        
           |  |  | 76 |     public function test_format_string_values(
 | 
        
           |  |  | 77 |         string $expected,
 | 
        
           |  |  | 78 |         array $params,
 | 
        
           |  |  | 79 |     ): void {
 | 
        
           |  |  | 80 |         $formatting = new formatting();
 | 
        
           |  |  | 81 |         $this->assertSame(
 | 
        
           |  |  | 82 |             $expected,
 | 
        
           |  |  | 83 |             $formatting->format_string(...$params),
 | 
        
           |  |  | 84 |         );
 | 
        
           |  |  | 85 |     }
 | 
        
           |  |  | 86 |   | 
        
           |  |  | 87 |     /**
 | 
        
           |  |  | 88 |      * Data provider for format_string tests.
 | 
        
           |  |  | 89 |      *
 | 
        
           |  |  | 90 |      * @return array
 | 
        
           |  |  | 91 |      */
 | 
        
           |  |  | 92 |     public static function format_string_provider(): array {
 | 
        
           |  |  | 93 |         return [
 | 
        
           |  |  | 94 |             // Ampersands.
 | 
        
           |  |  | 95 |             [
 | 
        
           |  |  | 96 |                 'expected' => "& &&&&& &&",
 | 
        
           |  |  | 97 |                 'params' => ["& &&&&& &&"],
 | 
        
           |  |  | 98 |             ],
 | 
        
           |  |  | 99 |             [
 | 
        
           |  |  | 100 |                 'expected' => "ANother & &&&&& Category",
 | 
        
           |  |  | 101 |                 'params' => ["ANother & &&&&& Category"],
 | 
        
           |  |  | 102 |             ],
 | 
        
           |  |  | 103 |             [
 | 
        
           |  |  | 104 |                 'expected' => "ANother & &&&&& Category",
 | 
        
           |  |  | 105 |                 'params' => [
 | 
        
           |  |  | 106 |                     'string' => "ANother & &&&&& Category",
 | 
        
           |  |  | 107 |                     'striplinks' => true,
 | 
        
           |  |  | 108 |                 ],
 | 
        
           |  |  | 109 |             ],
 | 
        
           |  |  | 110 |             [
 | 
        
           |  |  | 111 |                 'expected' => "Nick's Test Site & Other things",
 | 
        
           |  |  | 112 |                 'params' => [
 | 
        
           |  |  | 113 |                     'string' => "Nick's Test Site & Other things",
 | 
        
           |  |  | 114 |                     'striplinks' => true,
 | 
        
           |  |  | 115 |                 ],
 | 
        
           |  |  | 116 |             ],
 | 
        
           |  |  | 117 |             [
 | 
        
           |  |  | 118 |                 'expected' => "& < > \" '",
 | 
        
           |  |  | 119 |                 'params' => [
 | 
        
           |  |  | 120 |                     'string' => "& < > \" '",
 | 
        
           |  |  | 121 |                     'striplinks' => true,
 | 
        
           |  |  | 122 |                     'escape' => false,
 | 
        
           |  |  | 123 |                 ],
 | 
        
           |  |  | 124 |             ],
 | 
        
           |  |  | 125 |   | 
        
           |  |  | 126 |             // String entities.
 | 
        
           |  |  | 127 |             [
 | 
        
           |  |  | 128 |                 'expected' => """,
 | 
        
           |  |  | 129 |                 'params' => ["""],
 | 
        
           |  |  | 130 |             ],
 | 
        
           |  |  | 131 |   | 
        
           |  |  | 132 |             // Digital entities.
 | 
        
           |  |  | 133 |             [
 | 
        
           |  |  | 134 |                 'expected' => "&11234;",
 | 
        
           |  |  | 135 |                 'params' => ["&11234;"],
 | 
        
           |  |  | 136 |             ],
 | 
        
           |  |  | 137 |   | 
        
           |  |  | 138 |             // Unicode entities.
 | 
        
           |  |  | 139 |             [
 | 
        
           |  |  | 140 |                 'expected' => "ᅻ",
 | 
        
           |  |  | 141 |                 'params' => ["ᅻ"],
 | 
        
           |  |  | 142 |             ],
 | 
        
           |  |  | 143 |   | 
        
           |  |  | 144 |             // Nulls.
 | 
        
           |  |  | 145 |             ['', [null]],
 | 
        
           |  |  | 146 |             [
 | 
        
           |  |  | 147 |                 'expected' => '',
 | 
        
           |  |  | 148 |                 'params' => [
 | 
        
           |  |  | 149 |                     'string' => null,
 | 
        
           |  |  | 150 |                     'striplinks' => true,
 | 
        
           |  |  | 151 |                     'escape' => false,
 | 
        
           |  |  | 152 |                 ],
 | 
        
           |  |  | 153 |             ],
 | 
        
           |  |  | 154 |         ];
 | 
        
           |  |  | 155 |     }
 | 
        
           |  |  | 156 |   | 
        
           |  |  | 157 |     /**
 | 
        
           |  |  | 158 |      * The format string static caching should include the filters option to make
 | 
        
           |  |  | 159 |      * sure filters are correctly applied when requested.
 | 
        
           |  |  | 160 |      */
 | 
        
           |  |  | 161 |     public function test_format_string_static_caching_with_filters(): void {
 | 
        
           |  |  | 162 |         global $CFG;
 | 
        
           |  |  | 163 |   | 
        
           |  |  | 164 |         $this->resetAfterTest(true);
 | 
        
           |  |  | 165 |         $this->setAdminUser();
 | 
        
           |  |  | 166 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 167 |         $course = $generator->create_course();
 | 
        
           |  |  | 168 |         $user = $generator->create_user();
 | 
        
           |  |  | 169 |   | 
        
           |  |  | 170 |         $rawstring = '<span lang="en" class="multilang">English</span><span lang="ca" class="multilang">Catalan</span>';
 | 
        
           |  |  | 171 |         $expectednofilter = strip_tags($rawstring);
 | 
        
           |  |  | 172 |         $expectedfilter = 'English';
 | 
        
           |  |  | 173 |         $context = \core\context\course::instance($course->id);
 | 
        
           |  |  | 174 |         $options = [
 | 
        
           |  |  | 175 |             'striplinks' => true,
 | 
        
           |  |  | 176 |             'context' => $context,
 | 
        
           |  |  | 177 |             'escape' => true,
 | 
        
           |  |  | 178 |             'filter' => false,
 | 
        
           |  |  | 179 |         ];
 | 
        
           |  |  | 180 |   | 
        
           |  |  | 181 |         $this->setUser($user);
 | 
        
           |  |  | 182 |   | 
        
           |  |  | 183 |         $formatting = new formatting();
 | 
        
           |  |  | 184 |   | 
        
           |  |  | 185 |         // Format the string without filters. It should just strip the
 | 
        
           |  |  | 186 |         // links.
 | 
        
           |  |  | 187 |         $nofilterresult = $formatting->format_string($rawstring, ...$options);
 | 
        
           |  |  | 188 |         $this->assertEquals($expectednofilter, $nofilterresult);
 | 
        
           |  |  | 189 |   | 
        
           |  |  | 190 |         // Add the multilang filter. Make sure it's enabled globally.
 | 
        
           |  |  | 191 |         $CFG->stringfilters = 'multilang';
 | 
        
           |  |  | 192 |         filter_set_global_state('multilang', TEXTFILTER_ON);
 | 
        
           |  |  | 193 |         filter_set_local_state('multilang', $context->id, TEXTFILTER_ON);
 | 
        
           |  |  | 194 |   | 
        
           |  |  | 195 |         // Even after setting the filters, no filters are applied yet.
 | 
        
           |  |  | 196 |         $nofilterresult = $formatting->format_string($rawstring,...$options);
 | 
        
           |  |  | 197 |         $this->assertEquals($expectednofilter, $nofilterresult);
 | 
        
           |  |  | 198 |   | 
        
           |  |  | 199 |         // Apply the filter as an option.
 | 
        
           |  |  | 200 |         $options['filter'] = true;
 | 
        
           |  |  | 201 |         $filterresult = $formatting->format_string($rawstring,  ...$options);
 | 
        
           |  |  | 202 |         $this->assertMatchesRegularExpression("/$expectedfilter/", $filterresult);
 | 
        
           |  |  | 203 |   | 
        
           |  |  | 204 |         // Apply it as a formatting setting.
 | 
        
           |  |  | 205 |         unset($options['filter']);
 | 
        
           |  |  | 206 |         $formatting->set_filterall(true);
 | 
        
           |  |  | 207 |         $filterresult = $formatting->format_string($rawstring,  ...$options);
 | 
        
           |  |  | 208 |         $this->assertMatchesRegularExpression("/$expectedfilter/", $filterresult);
 | 
        
           |  |  | 209 |   | 
        
           |  |  | 210 |         // Unset it and we do not filter.
 | 
        
           |  |  | 211 |         $formatting->set_filterall(false);
 | 
        
           |  |  | 212 |         $nofilterresult = $formatting->format_string($rawstring,  ...$options);
 | 
        
           |  |  | 213 |         $this->assertEquals($expectednofilter, $nofilterresult);
 | 
        
           |  |  | 214 |   | 
        
           |  |  | 215 |         // Set it again.
 | 
        
           |  |  | 216 |         $formatting->set_filterall(true);
 | 
        
           |  |  | 217 |         filter_set_local_state('multilang', $context->id, TEXTFILTER_OFF);
 | 
        
           |  |  | 218 |   | 
        
           |  |  | 219 |         // Confirm that we get back the cached string. The result should be
 | 
        
           |  |  | 220 |         // the same as the filtered text above even though we've disabled the
 | 
        
           |  |  | 221 |         // multilang filter in between.
 | 
        
           |  |  | 222 |         $cachedresult = $formatting->format_string($rawstring, ...$options);
 | 
        
           |  |  | 223 |         $this->assertMatchesRegularExpression("/$expectedfilter/", $cachedresult);
 | 
        
           |  |  | 224 |     }
 | 
        
           |  |  | 225 |   | 
        
           |  |  | 226 |     /**
 | 
        
           |  |  | 227 |      * Test trust option of format_text().
 | 
        
           |  |  | 228 |      *
 | 
        
           |  |  | 229 |      * @covers ::format_text
 | 
        
           |  |  | 230 |      * @dataProvider format_text_trusted_provider
 | 
        
           |  |  | 231 |      */
 | 
        
           |  |  | 232 |     public function test_format_text_trusted(
 | 
        
           |  |  | 233 |         $expected,
 | 
        
           |  |  | 234 |         int $enabletrusttext,
 | 
        
           |  |  | 235 |         mixed $input,
 | 
        
           |  |  | 236 |         // Yes... FORMAT_ constants are strings of ints.
 | 
        
           |  |  | 237 |         string $format,
 | 
        
           |  |  | 238 |         array $options = [],
 | 
        
           |  |  | 239 |     ): void {
 | 
        
           |  |  | 240 |         global $CFG;
 | 
        
           |  |  | 241 |         $this->resetAfterTest();
 | 
        
           |  |  | 242 |   | 
        
           |  |  | 243 |         $CFG->enabletrusttext = $enabletrusttext;
 | 
        
           |  |  | 244 |   | 
        
           |  |  | 245 |         $formatter = new formatting();
 | 
        
           |  |  | 246 |         $this->assertEquals(
 | 
        
           |  |  | 247 |             $expected,
 | 
        
           |  |  | 248 |             $formatter->format_text($input, $format, ...$options),
 | 
        
           |  |  | 249 |         );
 | 
        
           |  |  | 250 |     }
 | 
        
           |  |  | 251 |   | 
        
           |  |  | 252 |     public static function format_text_trusted_provider(): array {
 | 
        
           |  |  | 253 |         $text = "lala <object>xx</object>";
 | 
        
           |  |  | 254 |         return [
 | 
        
           |  |  | 255 |             [
 | 
        
           |  |  | 256 |                 s($text),
 | 
        
           |  |  | 257 |                 0,
 | 
        
           |  |  | 258 |                 $text,
 | 
        
           |  |  | 259 |                 FORMAT_PLAIN,
 | 
        
           |  |  | 260 |                 ['trusted' => true],
 | 
        
           |  |  | 261 |             ],
 | 
        
           |  |  | 262 |             [
 | 
        
           |  |  | 263 |                 "<p>lala xx</p>\n",
 | 
        
           |  |  | 264 |                 0,
 | 
        
           |  |  | 265 |                 $text,
 | 
        
           |  |  | 266 |                 FORMAT_MARKDOWN,
 | 
        
           |  |  | 267 |                 ['trusted' => true],
 | 
        
           |  |  | 268 |             ],
 | 
        
           |  |  | 269 |             [
 | 
        
           |  |  | 270 |                 '<div class="text_to_html">lala xx</div>',
 | 
        
           |  |  | 271 |                 0,
 | 
        
           |  |  | 272 |                 $text,
 | 
        
           |  |  | 273 |                 FORMAT_MOODLE,
 | 
        
           |  |  | 274 |                 ['trusted' => true],
 | 
        
           |  |  | 275 |             ],
 | 
        
           |  |  | 276 |             [
 | 
        
           |  |  | 277 |                 'lala xx',
 | 
        
           |  |  | 278 |                 0,
 | 
        
           |  |  | 279 |                 $text,
 | 
        
           |  |  | 280 |                 FORMAT_HTML,
 | 
        
           |  |  | 281 |                 ['trusted' => true],
 | 
        
           |  |  | 282 |             ],
 | 
        
           |  |  | 283 |   | 
        
           |  |  | 284 |             [
 | 
        
           |  |  | 285 |                 s($text),
 | 
        
           |  |  | 286 |                 0,
 | 
        
           |  |  | 287 |                 $text,
 | 
        
           |  |  | 288 |                 FORMAT_PLAIN,
 | 
        
           |  |  | 289 |                 ['trusted' => false],
 | 
        
           |  |  | 290 |             ],
 | 
        
           |  |  | 291 |             [
 | 
        
           |  |  | 292 |                 "<p>lala xx</p>\n",
 | 
        
           |  |  | 293 |                 0,
 | 
        
           |  |  | 294 |                 $text,
 | 
        
           |  |  | 295 |                 FORMAT_MARKDOWN,
 | 
        
           |  |  | 296 |                 ['trusted' => false],
 | 
        
           |  |  | 297 |             ],
 | 
        
           |  |  | 298 |             [
 | 
        
           |  |  | 299 |                 '<div class="text_to_html">lala xx</div>',
 | 
        
           |  |  | 300 |                 0,
 | 
        
           |  |  | 301 |                 $text,
 | 
        
           |  |  | 302 |                 FORMAT_MOODLE,
 | 
        
           |  |  | 303 |                 ['trusted' => false],
 | 
        
           |  |  | 304 |             ],
 | 
        
           |  |  | 305 |             [
 | 
        
           |  |  | 306 |                 'lala xx',
 | 
        
           |  |  | 307 |                 0,
 | 
        
           |  |  | 308 |                 $text,
 | 
        
           |  |  | 309 |                 FORMAT_HTML,
 | 
        
           |  |  | 310 |                 ['trusted' => false],
 | 
        
           |  |  | 311 |             ],
 | 
        
           |  |  | 312 |   | 
        
           |  |  | 313 |             [
 | 
        
           |  |  | 314 |                 s($text),
 | 
        
           |  |  | 315 |                 1,
 | 
        
           |  |  | 316 |                 $text,
 | 
        
           |  |  | 317 |                 FORMAT_PLAIN,
 | 
        
           |  |  | 318 |                 ['trusted' => true],
 | 
        
           |  |  | 319 |             ],
 | 
        
           |  |  | 320 |             [
 | 
        
           |  |  | 321 |                 "<p>lala xx</p>\n",
 | 
        
           |  |  | 322 |                 1,
 | 
        
           |  |  | 323 |                 $text,
 | 
        
           |  |  | 324 |                 FORMAT_MARKDOWN,
 | 
        
           |  |  | 325 |                 ['trusted' => true],
 | 
        
           |  |  | 326 |             ],
 | 
        
           |  |  | 327 |             [
 | 
        
           |  |  | 328 |                 '<div class="text_to_html">lala <object>xx</object></div>',
 | 
        
           |  |  | 329 |                 1,
 | 
        
           |  |  | 330 |                 $text,
 | 
        
           |  |  | 331 |                 FORMAT_MOODLE,
 | 
        
           |  |  | 332 |                 ['trusted' => true],
 | 
        
           |  |  | 333 |             ],
 | 
        
           |  |  | 334 |             [
 | 
        
           |  |  | 335 |                 'lala <object>xx</object>',
 | 
        
           |  |  | 336 |                 1,
 | 
        
           |  |  | 337 |                 $text,
 | 
        
           |  |  | 338 |                 FORMAT_HTML,
 | 
        
           |  |  | 339 |                 ['trusted' => true],
 | 
        
           |  |  | 340 |             ],
 | 
        
           |  |  | 341 |   | 
        
           |  |  | 342 |             [
 | 
        
           |  |  | 343 |                 s($text),
 | 
        
           |  |  | 344 |                 1,
 | 
        
           |  |  | 345 |                 $text,
 | 
        
           |  |  | 346 |                 FORMAT_PLAIN,
 | 
        
           |  |  | 347 |                 ['trusted' => false],
 | 
        
           |  |  | 348 |             ],
 | 
        
           |  |  | 349 |             [
 | 
        
           |  |  | 350 |                 "<p>lala xx</p>\n",
 | 
        
           |  |  | 351 |                 1,
 | 
        
           |  |  | 352 |                 $text,
 | 
        
           |  |  | 353 |                 FORMAT_MARKDOWN,
 | 
        
           |  |  | 354 |                 ['trusted' => false],
 | 
        
           |  |  | 355 |             ],
 | 
        
           |  |  | 356 |             [
 | 
        
           |  |  | 357 |                 '<div class="text_to_html">lala xx</div>',
 | 
        
           |  |  | 358 |                 1,
 | 
        
           |  |  | 359 |                 $text,
 | 
        
           |  |  | 360 |                 FORMAT_MOODLE,
 | 
        
           |  |  | 361 |                 ['trusted' => false],
 | 
        
           |  |  | 362 |             ],
 | 
        
           |  |  | 363 |             [
 | 
        
           |  |  | 364 |                 'lala xx',
 | 
        
           |  |  | 365 |                 1,
 | 
        
           |  |  | 366 |                 $text,
 | 
        
           |  |  | 367 |                 FORMAT_HTML,
 | 
        
           |  |  | 368 |                 ['trusted' => false],
 | 
        
           |  |  | 369 |             ],
 | 
        
           |  |  | 370 |   | 
        
           |  |  | 371 |             [
 | 
        
           |  |  | 372 |                 "<p>lala <object>xx</object></p>\n",
 | 
        
           |  |  | 373 |                 1,
 | 
        
           |  |  | 374 |                 $text,
 | 
        
           |  |  | 375 |                 FORMAT_MARKDOWN,
 | 
        
           |  |  | 376 |                 ['trusted' => true, 'clean' => false],
 | 
        
           |  |  | 377 |             ],
 | 
        
           |  |  | 378 |             [
 | 
        
           |  |  | 379 |                 "<p>lala <object>xx</object></p>\n",
 | 
        
           |  |  | 380 |                 1,
 | 
        
           |  |  | 381 |                 $text,
 | 
        
           |  |  | 382 |                 FORMAT_MARKDOWN,
 | 
        
           |  |  | 383 |                 ['trusted' => false, 'clean' => false],
 | 
        
           |  |  | 384 |             ],
 | 
        
           |  |  | 385 |         ];
 | 
        
           |  |  | 386 |     }
 | 
        
           |  |  | 387 |   | 
        
           |  |  | 388 |     public function test_format_text_format_html(): void {
 | 
        
           |  |  | 389 |         $this->resetAfterTest();
 | 
        
           |  |  | 390 |         $formatter = new formatting();
 | 
        
           |  |  | 391 |   | 
        
           |  |  | 392 |         filter_set_global_state('emoticon', TEXTFILTER_ON);
 | 
        
           |  |  | 393 |         $this->assertMatchesRegularExpression(
 | 
        
           |  |  | 394 |             '~^<p><img class="icon emoticon" alt="smile" title="smile" ' .
 | 
        
           |  |  | 395 |                 'src="https://www.example.com/moodle/theme/image.php/boost/core/1/s/smiley" /></p>$~',
 | 
        
           |  |  | 396 |             $formatter->format_text('<p>:-)</p>', FORMAT_HTML)
 | 
        
           |  |  | 397 |         );
 | 
        
           |  |  | 398 |     }
 | 
        
           |  |  | 399 |   | 
        
           |  |  | 400 |     public function test_format_text_format_html_no_filters(): void {
 | 
        
           |  |  | 401 |         $this->resetAfterTest();
 | 
        
           |  |  | 402 |         $formatter = new formatting();
 | 
        
           |  |  | 403 |   | 
        
           |  |  | 404 |         filter_set_global_state('emoticon', TEXTFILTER_ON);
 | 
        
           |  |  | 405 |         $this->assertEquals(
 | 
        
           |  |  | 406 |             '<p>:-)</p>',
 | 
        
           |  |  | 407 |             $formatter->format_text(
 | 
        
           |  |  | 408 |                 '<p>:-)</p>',
 | 
        
           |  |  | 409 |                 FORMAT_HTML,
 | 
        
           |  |  | 410 |                 filter: false,
 | 
        
           |  |  | 411 |             )
 | 
        
           |  |  | 412 |         );
 | 
        
           |  |  | 413 |     }
 | 
        
           |  |  | 414 |   | 
        
           |  |  | 415 |     public function test_format_text_format_plain(): void {
 | 
        
           |  |  | 416 |         // Note FORMAT_PLAIN does not filter ever, no matter we ask for filtering.
 | 
        
           |  |  | 417 |         $this->resetAfterTest();
 | 
        
           |  |  | 418 |         $formatter = new formatting();
 | 
        
           |  |  | 419 |   | 
        
           |  |  | 420 |         filter_set_global_state('emoticon', TEXTFILTER_ON);
 | 
        
           |  |  | 421 |         $this->assertEquals(
 | 
        
           |  |  | 422 |             ':-)',
 | 
        
           |  |  | 423 |             $formatter->format_text(':-)', FORMAT_PLAIN)
 | 
        
           |  |  | 424 |         );
 | 
        
           |  |  | 425 |     }
 | 
        
           |  |  | 426 |   | 
        
           |  |  | 427 |     public function test_format_text_format_plain_no_filters(): void {
 | 
        
           |  |  | 428 |         $this->resetAfterTest();
 | 
        
           |  |  | 429 |         $formatter = new formatting();
 | 
        
           |  |  | 430 |   | 
        
           |  |  | 431 |         filter_set_global_state('emoticon', TEXTFILTER_ON);
 | 
        
           |  |  | 432 |         $this->assertEquals(
 | 
        
           |  |  | 433 |             ':-)',
 | 
        
           |  |  | 434 |             $formatter->format_text(
 | 
        
           |  |  | 435 |                 ':-)',
 | 
        
           |  |  | 436 |                 FORMAT_PLAIN,
 | 
        
           |  |  | 437 |                 filter: false,
 | 
        
           |  |  | 438 |             )
 | 
        
           |  |  | 439 |         );
 | 
        
           |  |  | 440 |     }
 | 
        
           |  |  | 441 |   | 
        
           |  |  | 442 |     public function test_format_text_format_markdown(): void {
 | 
        
           |  |  | 443 |         $this->resetAfterTest();
 | 
        
           |  |  | 444 |         $formatter = new formatting();
 | 
        
           |  |  | 445 |   | 
        
           |  |  | 446 |         filter_set_global_state('emoticon', TEXTFILTER_ON);
 | 
        
           |  |  | 447 |         $this->assertMatchesRegularExpression(
 | 
        
           |  |  | 448 |             '~^<p><em><img class="icon emoticon" alt="smile" title="smile" ' .
 | 
        
           |  |  | 449 |                 'src="https://www.example.com/moodle/theme/image.php/boost/core/1/s/smiley" />' .
 | 
        
           |  |  | 450 |                 '</em></p>\n$~',
 | 
        
           |  |  | 451 |             $formatter->format_text('*:-)*', FORMAT_MARKDOWN)
 | 
        
           |  |  | 452 |         );
 | 
        
           |  |  | 453 |     }
 | 
        
           |  |  | 454 |   | 
        
           |  |  | 455 |     public function test_format_text_format_markdown_nofilter(): void {
 | 
        
           |  |  | 456 |         $this->resetAfterTest();
 | 
        
           |  |  | 457 |         $formatter = new formatting();
 | 
        
           |  |  | 458 |   | 
        
           |  |  | 459 |         filter_set_global_state('emoticon', TEXTFILTER_ON);
 | 
        
           |  |  | 460 |         $this->assertEquals(
 | 
        
           |  |  | 461 |             "<p><em>:-)</em></p>\n",
 | 
        
           |  |  | 462 |             $formatter->format_text('*:-)*', FORMAT_MARKDOWN, filter: false)
 | 
        
           |  |  | 463 |         );
 | 
        
           |  |  | 464 |     }
 | 
        
           |  |  | 465 |   | 
        
           |  |  | 466 |     public function test_format_text_format_moodle(): void {
 | 
        
           |  |  | 467 |         $this->resetAfterTest();
 | 
        
           |  |  | 468 |         $formatter = new formatting();
 | 
        
           |  |  | 469 |   | 
        
           |  |  | 470 |         filter_set_global_state('emoticon', TEXTFILTER_ON);
 | 
        
           |  |  | 471 |         $this->assertMatchesRegularExpression(
 | 
        
           |  |  | 472 |             '~^<div class="text_to_html"><p>' .
 | 
        
           |  |  | 473 |                 '<img class="icon emoticon" alt="smile" title="smile" ' .
 | 
        
           |  |  | 474 |                 'src="https://www.example.com/moodle/theme/image.php/boost/core/1/s/smiley" /></p></div>$~',
 | 
        
           |  |  | 475 |             $formatter->format_text('<p>:-)</p>', FORMAT_MOODLE)
 | 
        
           |  |  | 476 |         );
 | 
        
           |  |  | 477 |     }
 | 
        
           |  |  | 478 |   | 
        
           |  |  | 479 |     public function test_format_text_format_moodle_no_filters(): void {
 | 
        
           |  |  | 480 |         $this->resetAfterTest();
 | 
        
           |  |  | 481 |         $formatter = new formatting();
 | 
        
           |  |  | 482 |   | 
        
           |  |  | 483 |         filter_set_global_state('emoticon', TEXTFILTER_ON);
 | 
        
           |  |  | 484 |         $this->assertEquals(
 | 
        
           |  |  | 485 |             '<div class="text_to_html"><p>:-)</p></div>',
 | 
        
           |  |  | 486 |             $formatter->format_text('<p>:-)</p>', FORMAT_MOODLE, filter: false)
 | 
        
           |  |  | 487 |         );
 | 
        
           |  |  | 488 |     }
 | 
        
           |  |  | 489 |   | 
        
           |  |  | 490 |     /**
 | 
        
           |  |  | 491 |      * Make sure that nolink tags and spans prevent linking in filters that support it.
 | 
        
           |  |  | 492 |      */
 | 
        
           |  |  | 493 |     public function test_format_text_nolink(): void {
 | 
        
           |  |  | 494 |         global $CFG;
 | 
        
           |  |  | 495 |         $this->resetAfterTest();
 | 
        
           |  |  | 496 |         $formatter = new formatting();
 | 
        
           |  |  | 497 |   | 
        
           |  |  | 498 |         filter_set_global_state('activitynames', TEXTFILTER_ON);
 | 
        
           |  |  | 499 |   | 
        
           |  |  | 500 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 501 |         $context = \context_course::instance($course->id);
 | 
        
           |  |  | 502 |         $page = $this->getDataGenerator()->create_module(
 | 
        
           |  |  | 503 |             'page',
 | 
        
           |  |  | 504 |             ['course' => $course->id, 'name' => 'Test 1'],
 | 
        
           |  |  | 505 |         );
 | 
        
           |  |  | 506 |         $cm = get_coursemodule_from_instance('page', $page->id, $page->course, false, MUST_EXIST);
 | 
        
           |  |  | 507 |         $pageurl = $CFG->wwwroot . '/mod/page/view.php?id=' . $cm->id;
 | 
        
           |  |  | 508 |   | 
        
           |  |  | 509 |         $this->assertSame(
 | 
        
           |  |  | 510 |             '<p>Read <a class="autolink" title="Test 1" href="' . $pageurl . '">Test 1</a>.</p>',
 | 
        
           |  |  | 511 |             $formatter->format_text('<p>Read Test 1.</p>', FORMAT_HTML, context: $context),
 | 
        
           |  |  | 512 |         );
 | 
        
           |  |  | 513 |   | 
        
           |  |  | 514 |         $this->assertSame(
 | 
        
           |  |  | 515 |             '<p>Read <a class="autolink" title="Test 1" href="' . $pageurl . '">Test 1</a>.</p>',
 | 
        
           |  |  | 516 |             $formatter->format_text(
 | 
        
           |  |  | 517 |                 '<p>Read Test 1.</p>',
 | 
        
           |  |  | 518 |                 FORMAT_HTML,
 | 
        
           |  |  | 519 |                 context: $context,
 | 
        
           |  |  | 520 |                 clean: false,
 | 
        
           |  |  | 521 |             ),
 | 
        
           |  |  | 522 |         );
 | 
        
           |  |  | 523 |   | 
        
           |  |  | 524 |         $this->assertSame(
 | 
        
           |  |  | 525 |             '<p>Read Test 1.</p>',
 | 
        
           |  |  | 526 |             $formatter->format_text(
 | 
        
           |  |  | 527 |                 '<p><nolink>Read Test 1.</nolink></p>',
 | 
        
           |  |  | 528 |                 FORMAT_HTML,
 | 
        
           |  |  | 529 |                 context: $context,
 | 
        
           |  |  | 530 |                 clean: true,
 | 
        
           |  |  | 531 |             ),
 | 
        
           |  |  | 532 |         );
 | 
        
           |  |  | 533 |   | 
        
           |  |  | 534 |         $this->assertSame(
 | 
        
           |  |  | 535 |             '<p>Read Test 1.</p>',
 | 
        
           |  |  | 536 |             $formatter->format_text(
 | 
        
           |  |  | 537 |                 '<p><nolink>Read Test 1.</nolink></p>',
 | 
        
           |  |  | 538 |                 FORMAT_HTML,
 | 
        
           |  |  | 539 |                 context: $context,
 | 
        
           |  |  | 540 |                 clean: false,
 | 
        
           |  |  | 541 |             ),
 | 
        
           |  |  | 542 |         );
 | 
        
           |  |  | 543 |   | 
        
           |  |  | 544 |         $this->assertSame(
 | 
        
           |  |  | 545 |             '<p><span class="nolink">Read Test 1.</span></p>',
 | 
        
           |  |  | 546 |             $formatter->format_text(
 | 
        
           |  |  | 547 |                 '<p><span class="nolink">Read Test 1.</span></p>',
 | 
        
           |  |  | 548 |                 FORMAT_HTML,
 | 
        
           |  |  | 549 |                 context: $context,
 | 
        
           |  |  | 550 |             ),
 | 
        
           |  |  | 551 |         );
 | 
        
           |  |  | 552 |     }
 | 
        
           |  |  | 553 |   | 
        
           |  |  | 554 |     public function test_format_text_overflowdiv(): void {
 | 
        
           |  |  | 555 |         $formatter = new formatting();
 | 
        
           |  |  | 556 |   | 
        
           |  |  | 557 |         $this->assertEquals(
 | 
        
           |  |  | 558 |             '<div class="no-overflow"><p>Hello world</p></div>',
 | 
        
           |  |  | 559 |             $formatter->format_text(
 | 
        
           |  |  | 560 |                 '<p>Hello world</p>',
 | 
        
           |  |  | 561 |                 FORMAT_HTML,
 | 
        
           |  |  | 562 |                 overflowdiv: true,
 | 
        
           |  |  | 563 |             ),
 | 
        
           |  |  | 564 |         );
 | 
        
           |  |  | 565 |     }
 | 
        
           |  |  | 566 |   | 
        
           |  |  | 567 |     /**
 | 
        
           |  |  | 568 |      * Test adding blank target attribute to links
 | 
        
           |  |  | 569 |      *
 | 
        
           |  |  | 570 |      * @dataProvider format_text_blanktarget_testcases
 | 
        
           |  |  | 571 |      * @param string $link The link to add target="_blank" to
 | 
        
           |  |  | 572 |      * @param string $expected The expected filter value
 | 
        
           |  |  | 573 |      */
 | 
        
           |  |  | 574 |     public function test_format_text_blanktarget($link, $expected): void {
 | 
        
           |  |  | 575 |         $formatter = new formatting();
 | 
        
           |  |  | 576 |         $actual = $formatter->format_text(
 | 
        
           |  |  | 577 |             $link,
 | 
        
           |  |  | 578 |             FORMAT_MOODLE,
 | 
        
           |  |  | 579 |             blanktarget: true,
 | 
        
           |  |  | 580 |             filter: false,
 | 
        
           |  |  | 581 |             clean: false,
 | 
        
           |  |  | 582 |         );
 | 
        
           |  |  | 583 |         $this->assertEquals($expected, $actual);
 | 
        
           |  |  | 584 |     }
 | 
        
           |  |  | 585 |   | 
        
           |  |  | 586 |     /**
 | 
        
           |  |  | 587 |      * Data provider for the test_format_text_blanktarget testcase
 | 
        
           |  |  | 588 |      *
 | 
        
           |  |  | 589 |      * @return array of testcases
 | 
        
           |  |  | 590 |      */
 | 
        
           |  |  | 591 |     public static function format_text_blanktarget_testcases(): array {
 | 
        
           |  |  | 592 |         return [
 | 
        
           |  |  | 593 |             'Simple link' => [
 | 
        
           |  |  | 594 |                 '<a href="https://www.youtube.com/watch?v=JeimE8Wz6e4">Hey, that\'s pretty good!</a>',
 | 
        
           |  |  | 595 |                 '<div class="text_to_html"><a href="https://www.youtube.com/watch?v=JeimE8Wz6e4" target="_blank"' .
 | 
        
           |  |  | 596 |                     ' rel="noreferrer">Hey, that\'s pretty good!</a></div>',
 | 
        
           |  |  | 597 |             ],
 | 
        
           |  |  | 598 |             'Link with rel' => [
 | 
        
           |  |  | 599 |                 '<a href="https://www.youtube.com/watch?v=JeimE8Wz6e4" rel="nofollow">Hey, that\'s pretty good!</a>',
 | 
        
           |  |  | 600 |                 '<div class="text_to_html"><a href="https://www.youtube.com/watch?v=JeimE8Wz6e4" rel="nofollow noreferrer"' .
 | 
        
           |  |  | 601 |                     ' target="_blank">Hey, that\'s pretty good!</a></div>',
 | 
        
           |  |  | 602 |             ],
 | 
        
           |  |  | 603 |             'Link with rel noreferrer' => [
 | 
        
           |  |  | 604 |                 '<a href="https://www.youtube.com/watch?v=JeimE8Wz6e4" rel="noreferrer">Hey, that\'s pretty good!</a>',
 | 
        
           |  |  | 605 |                 '<div class="text_to_html"><a href="https://www.youtube.com/watch?v=JeimE8Wz6e4" rel="noreferrer"' .
 | 
        
           |  |  | 606 |                     ' target="_blank">Hey, that\'s pretty good!</a></div>',
 | 
        
           |  |  | 607 |             ],
 | 
        
           |  |  | 608 |             'Link with target' => [
 | 
        
           |  |  | 609 |                 '<a href="https://www.youtube.com/watch?v=JeimE8Wz6e4" target="_self">Hey, that\'s pretty good!</a>',
 | 
        
           |  |  | 610 |                 '<div class="text_to_html"><a href="https://www.youtube.com/watch?v=JeimE8Wz6e4" target="_self">' .
 | 
        
           |  |  | 611 |                     'Hey, that\'s pretty good!</a></div>',
 | 
        
           |  |  | 612 |             ],
 | 
        
           |  |  | 613 |             'Link with target blank' => [
 | 
        
           |  |  | 614 |                 '<a href="https://www.youtube.com/watch?v=JeimE8Wz6e4" target="_blank">Hey, that\'s pretty good!</a>',
 | 
        
           |  |  | 615 |                 '<div class="text_to_html"><a href="https://www.youtube.com/watch?v=JeimE8Wz6e4" target="_blank"' .
 | 
        
           |  |  | 616 |                     ' rel="noreferrer">Hey, that\'s pretty good!</a></div>',
 | 
        
           |  |  | 617 |             ],
 | 
        
           |  |  | 618 |             'Link with Frank\'s casket inscription' => [
 | 
        
           |  |  | 619 |                 // phpcs:ignore moodle.Files.LineLength
 | 
        
           |  |  | 620 |                 '<a href="https://en.wikipedia.org/wiki/Franks_Casket">áš á›á›‹áš³á›«áš á›šáš©á›žáš¢á›«ášªáš»áš©áš áš©áš¾áš á›–ᚱᚷ ᛖᚾᛒᛖᚱá›áš· ᚹᚪᚱᚦᚷᚪ᛬ᛋᚱá›áš³áš·áš±áš©áš±áš¾áš¦áš«áš±áš»á›–ᚩᚾᚷᚱᛖᚢá›áš·á›á›‹áš¹áš©á›— áš»' .
 | 
        
           |  |  | 621 |                     'ᚱᚩᚾᚫᛋᛒᚪᚾ ᛗᚫᚷá›áš á›á›‹áš³á›«áš á›šáš©á›žáš¢á›«ášªáš»áš©áš áš©áš¾áš á›–ᚱᚷ ᛖᚾᛒᛖᚱá›áš· ᚹᚪᚱᚦᚷᚪ᛬ᛋᚱá›áš³áš·áš±áš©áš±áš¾áš¦áš«áš±áš»á›–ᚩᚾᚷᚱᛖᚢá›áš·á›á›‹áš¹áš©á›— ᚻᚱᚩᚾᚫᛋᛒᚪᚾ ᛗᚫᚷá›</a>',
 | 
        
           |  |  | 622 |                     '<div class="text_to_html"><a href="https://en.wikipedia.org/wiki/Franks_Casket" target="_blank" ' .
 | 
        
           |  |  | 623 |                     // phpcs:ignore moodle.Files.LineLength
 | 
        
           |  |  | 624 |                     'rel="noreferrer">áš á›á›‹áš³á›«áš á›šáš©á›žáš¢á›«ášªáš»áš©áš áš©áš¾áš á›–ᚱᚷ ᛖᚾᛒᛖᚱá›áš· ᚹᚪᚱᚦᚷᚪ᛬ᛋᚱá›áš³áš·áš±áš©áš±áš¾áš¦áš«áš±áš»á›–ᚩᚾᚷᚱᛖᚢá›áš·á›á›‹áš¹áš©á›— ᚻᚱᚩᚾᚫᛋᛒᚪᚾ ᛗᚫᚷá›áš á›á›‹áš³á›«áš á›šáš©á›žáš¢á›«ášªáš»áš©áš áš©áš¾áš á›–ᚱᚷ á›–áš¾' .
 | 
        
           |  |  | 625 |                     'á›’á›–áš±á›áš· ᚹᚪᚱᚦᚷᚪ᛬ᛋᚱá›áš³áš·áš±áš©áš±áš¾áš¦áš«áš±áš»á›–ᚩᚾᚷᚱᛖᚢá›áš·á›á›‹áš¹áš©á›— ᚻᚱᚩᚾᚫᛋᛒᚪᚾ ᛗᚫᚷá›</a></div>',
 | 
        
           |  |  | 626 |             ],
 | 
        
           |  |  | 627 |             'No link' => [
 | 
        
           |  |  | 628 |                 'Some very boring text written with the Latin script',
 | 
        
           |  |  | 629 |                 '<div class="text_to_html">Some very boring text written with the Latin script</div>',
 | 
        
           |  |  | 630 |             ],
 | 
        
           |  |  | 631 |             'No link with Thror\'s map runes' => [
 | 
        
           |  |  | 632 |                 // phpcs:ignore moodle.Files.LineLength
 | 
        
           |  |  | 633 |                 'ᛋá›áš«áš¾á›ž ᛒᚣ ᚦᛖ ᚷᚱᛖᚣ ᛋá›áš©áš¾á›– ᚻᚹá›á›šá›– ᚦᛖ ᚦᚱᚢᛋᚻ ᚾᚩᚳᛋ ᚫᚾᛞ ᚦᛖ ᛋᛖá›á›á›áš¾áš· ᛋᚢᚾ áš¹á›áš¦ ᚦᛖ ᛚᚫᛋᛠᛚá›áš·áš»á› ᚩᚠ ᛞᚢᚱá›áš¾á›‹ ᛞᚫᚣ áš¹á›á›šá›š ᛋᚻá›áš¾á›– ᚢᛈᚩᚾ ᚦᛖ ᚳᛖᚣᚻᚩᛚᛖ',
 | 
        
           |  |  | 634 |                 // phpcs:ignore moodle.Files.LineLength
 | 
        
           |  |  | 635 |                 '<div class="text_to_html">ᛋá›áš«áš¾á›ž ᛒᚣ ᚦᛖ ᚷᚱᛖᚣ ᛋá›áš©áš¾á›– ᚻᚹá›á›šá›– ᚦᛖ ᚦᚱᚢᛋᚻ ᚾᚩᚳᛋ ᚫᚾᛞ ᚦᛖ ᛋᛖá›á›á›áš¾áš· ᛋᚢᚾ áš¹á›áš¦ ᚦᛖ ᛚᚫᛋᛠᛚá›áš·áš»á› ᚩᚠ ᛞᚢᚱá›áš¾á›‹ ᛞᚫᚣ áš¹' .
 | 
        
           |  |  | 636 |                     'á›á›šá›š ᛋᚻá›áš¾á›– ᚢᛈᚩᚾ ᚦᛖ ᚳᛖᚣᚻᚩᛚᛖ</div>',
 | 
        
           |  |  | 637 |             ],
 | 
        
           |  |  | 638 |         ];
 | 
        
           |  |  | 639 |     }
 | 
        
           |  |  | 640 |   | 
        
           |  |  | 641 |     /**
 | 
        
           |  |  | 642 |      * Test ability to force cleaning of otherwise non-cleaned content.
 | 
        
           |  |  | 643 |      *
 | 
        
           |  |  | 644 |      * @dataProvider format_text_cleaning_testcases
 | 
        
           |  |  | 645 |      *
 | 
        
           |  |  | 646 |      * @param string $input Input text
 | 
        
           |  |  | 647 |      * @param string $nocleaned Expected output of format_text() with noclean=true
 | 
        
           |  |  | 648 |      * @param string $cleaned Expected output of format_text() with noclean=false
 | 
        
           |  |  | 649 |      */
 | 
        
           |  |  | 650 |     public function test_format_text_cleaning($input, $nocleaned, $cleaned): void {
 | 
        
           |  |  | 651 |         $formatter = new formatting();
 | 
        
           |  |  | 652 |   | 
        
           |  |  | 653 |         $formatter->set_forceclean(false);
 | 
        
           |  |  | 654 |         $actual = $formatter->format_text($input, FORMAT_HTML, filter: false, clean: true);
 | 
        
           |  |  | 655 |         $this->assertEquals($cleaned, $actual);
 | 
        
           |  |  | 656 |   | 
        
           |  |  | 657 |         $formatter->set_forceclean(true);
 | 
        
           |  |  | 658 |         $actual = $formatter->format_text($input, FORMAT_HTML, filter: false, clean: true);
 | 
        
           |  |  | 659 |         $this->assertEquals($cleaned, $actual);
 | 
        
           |  |  | 660 |   | 
        
           |  |  | 661 |         $formatter->set_forceclean(false);
 | 
        
           |  |  | 662 |         $actual = $formatter->format_text($input, FORMAT_HTML, filter: false, clean: false);
 | 
        
           |  |  | 663 |         $this->assertEquals($nocleaned, $actual);
 | 
        
           |  |  | 664 |   | 
        
           |  |  | 665 |         $formatter->set_forceclean(true);
 | 
        
           |  |  | 666 |         $actual = $formatter->format_text($input, FORMAT_HTML, filter: false, clean: false);
 | 
        
           |  |  | 667 |         $this->assertEquals($cleaned, $actual);
 | 
        
           |  |  | 668 |     }
 | 
        
           |  |  | 669 |   | 
        
           |  |  | 670 |     /**
 | 
        
           |  |  | 671 |      * Data provider for the test_format_text_cleaning testcase
 | 
        
           |  |  | 672 |      *
 | 
        
           |  |  | 673 |      * @return array of testcases (string)testcasename => [(string)input, (string)nocleaned, (string)cleaned]
 | 
        
           |  |  | 674 |      */
 | 
        
           |  |  | 675 |     public static function format_text_cleaning_testcases(): array {
 | 
        
           |  |  | 676 |         return [
 | 
        
           |  |  | 677 |             'JavaScript' => [
 | 
        
           |  |  | 678 |                 'Hello <script type="text/javascript">alert("XSS");</script> world',
 | 
        
           |  |  | 679 |                 'Hello <script type="text/javascript">alert("XSS");</script> world',
 | 
        
           |  |  | 680 |                 'Hello  world',
 | 
        
           |  |  | 681 |             ],
 | 
        
           |  |  | 682 |             'Inline frames' => [
 | 
        
           |  |  | 683 |                 'Let us go phishing! <iframe src="https://1.2.3.4/google.com"></iframe>',
 | 
        
           |  |  | 684 |                 'Let us go phishing! <iframe src="https://1.2.3.4/google.com"></iframe>',
 | 
        
           |  |  | 685 |                 'Let us go phishing! ',
 | 
        
           |  |  | 686 |             ],
 | 
        
           |  |  | 687 |             'Malformed A tags' => [
 | 
        
           |  |  | 688 |                 '<a onmouseover="alert(document.cookie)">xxs link</a>',
 | 
        
           |  |  | 689 |                 '<a onmouseover="alert(document.cookie)">xxs link</a>',
 | 
        
           |  |  | 690 |                 '<a>xxs link</a>',
 | 
        
           |  |  | 691 |             ],
 | 
        
           |  |  | 692 |             'Malformed IMG tags' => [
 | 
        
           |  |  | 693 |                 '<IMG """><SCRIPT>alert("XSS")</SCRIPT>">',
 | 
        
           |  |  | 694 |                 '<IMG """><SCRIPT>alert("XSS")</SCRIPT>">',
 | 
        
           |  |  | 695 |                 '">',
 | 
        
           |  |  | 696 |             ],
 | 
        
           |  |  | 697 |             'On error alert' => [
 | 
        
           |  |  | 698 |                 '<IMG SRC=/ onerror="alert(String.fromCharCode(88,83,83))"></img>',
 | 
        
           |  |  | 699 |                 '<IMG SRC=/ onerror="alert(String.fromCharCode(88,83,83))"></img>',
 | 
        
           |  |  | 700 |                 '<img src="/" alt="" />',
 | 
        
           |  |  | 701 |             ],
 | 
        
           |  |  | 702 |             'IMG onerror and javascript alert encode' => [
 | 
        
           |  |  | 703 |                 '<img src=x onerror="javascSS')">',
 | 
        
           |  |  | 704 |                 '<img src=x onerror="javascSS')">',
 | 
        
           |  |  | 705 |                 '<img src="x" alt="x" />',
 | 
        
           |  |  | 706 |             ],
 | 
        
           |  |  | 707 |             'DIV background-image' => [
 | 
        
           |  |  | 708 |                 '<DIV STYLE="background-image: url(javascript:alert(\'XSS\'))">',
 | 
        
           |  |  | 709 |                 '<DIV STYLE="background-image: url(javascript:alert(\'XSS\'))">',
 | 
        
           |  |  | 710 |                 '<div></div>',
 | 
        
           |  |  | 711 |             ],
 | 
        
           |  |  | 712 |         ];
 | 
        
           |  |  | 713 |     }
 | 
        
           |  |  | 714 | }
 |