Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 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 * Unit tests for core\content\exportable_items\exportable_textarea. 19 * 20 * @package core 21 * @category test 22 * @copyright 2020 Andrew Nicols <andrew@nicols.co.uk> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 declare(strict_types=1); 27 28 namespace core\content\export\exportable_items; 29 30 use advanced_testcase; 31 use context; 32 use context_module; 33 use context_system; 34 use core\content\export\zipwriter; 35 use moodle_url; 36 use stdClass; 37 38 /** 39 * Unit tests for the `exportable_textarea` export item class. 40 * 41 * @coversDefaultClass \core\content\exportable_items\exportable_textarea 42 */ 43 class exportable_textarea_test extends advanced_testcase { 44 45 /** 46 * Ensure that an exportable textarea which does not relate to any content, does not attempt to export any content. 47 */ 48 public function test_valid_table_without_content(): void { 49 $this->resetAfterTest(true); 50 51 $user = $this->getDataGenerator()->create_user(); 52 53 $context = context_system::instance(); 54 $component = 'page'; 55 $uservisiblename = 'Page content'; 56 $tablename = 'page'; 57 $fieldname = 'content'; 58 $fieldid = -1; 59 $formatfieldname = 'contentformat'; 60 $filearea = 'content'; 61 62 $exportable = new exportable_textarea( 63 $context, 64 $component, 65 $uservisiblename, 66 $tablename, 67 $fieldname, 68 $fieldid, 69 $formatfieldname 70 ); 71 72 $this->assertInstanceOf(exportable_textarea::class, $exportable); 73 74 $this->assert_exportable_empty($component, $user, $context, $exportable); 75 } 76 77 /** 78 * Ensure that the an exportable textarea exports content from the appropriate locations, but without any files. 79 */ 80 public function test_valid_table_with_content_no_filearea_specified(): void { 81 $this->resetAfterTest(true); 82 83 $content = '<h1>Hello</h1><p>World!</p>'; 84 85 $user = $this->getDataGenerator()->create_user(); 86 $course = $this->getDataGenerator()->create_course(); 87 $page = $this->getDataGenerator()->create_module('page', (object) [ 88 'course' => $course, 89 'content' => $content, 90 'contentformat' => FORMAT_HTML, 91 ]); 92 93 $context = context_module::instance($page->cmid); 94 $expectedfiles = $this->create_files($context, 'mod_page', 'content', (int) $page->id, 5); 95 96 // Unexpected files. 97 $this->create_files($context, 'mod_page', 'content', (int) $page->id + 1, 5); 98 $this->create_files($context, 'mod_page', 'othercontent', (int) $page->id, 5); 99 $this->create_files($context, 'mod_foo', 'content', (int) $page->id, 5); 100 101 $component = 'page'; 102 $uservisiblename = 'Page content'; 103 $tablename = 'page'; 104 $fieldname = 'content'; 105 $fieldid = (int) $page->id; 106 $formatfieldname = 'contentformat'; 107 108 $exportable = new exportable_textarea( 109 $context, 110 $component, 111 $uservisiblename, 112 $tablename, 113 $fieldname, 114 $fieldid, 115 $formatfieldname 116 ); 117 118 $this->assertInstanceOf(exportable_textarea::class, $exportable); 119 120 // Although files exist, the filearea and itemid were not included. 121 $this->assert_exportable_matches_file($component, $user, $context, null, $content, [], '', $exportable); 122 } 123 124 /** 125 * Ensure that the an exportable textarea exports content from the appropriate locations, but without any files. 126 */ 127 public function test_valid_table_with_content_no_itemid_specified(): void { 128 $this->resetAfterTest(true); 129 130 $content = '<h1>Hello</h1><p>World!</p>'; 131 132 $user = $this->getDataGenerator()->create_user(); 133 $course = $this->getDataGenerator()->create_course(); 134 $page = $this->getDataGenerator()->create_module('page', (object) [ 135 'course' => $course, 136 'content' => $content, 137 'contentformat' => FORMAT_HTML, 138 ]); 139 140 $context = context_module::instance($page->cmid); 141 $expectedfiles = $this->create_files($context, 'mod_page', 'content', (int) $page->id, 5); 142 143 // Unexpected files. 144 $this->create_files($context, 'mod_page', 'content', (int) $page->id + 1, 5); 145 $this->create_files($context, 'mod_page', 'othercontent', (int) $page->id, 5); 146 $this->create_files($context, 'mod_foo', 'content', (int) $page->id, 5); 147 148 $component = 'page'; 149 $uservisiblename = 'Page content'; 150 $tablename = 'page'; 151 $fieldname = 'content'; 152 $fieldid = (int) $page->id; 153 $formatfieldname = 'contentformat'; 154 $filearea = 'content'; 155 156 $exportable = new exportable_textarea( 157 $context, 158 $component, 159 $uservisiblename, 160 $tablename, 161 $fieldname, 162 $fieldid, 163 $formatfieldname, 164 $filearea 165 ); 166 167 $this->assertInstanceOf(exportable_textarea::class, $exportable); 168 169 // Although files exist, the filearea and itemid were not included. 170 $this->assert_exportable_matches_file($component, $user, $context, null, $content, [], '', $exportable); 171 } 172 173 /** 174 * Ensure that the an exportable textarea exports content from the appropriate locations, with files. 175 */ 176 public function test_valid_table_with_content_and_files(): void { 177 $this->resetAfterTest(true); 178 $user = $this->getDataGenerator()->create_user(); 179 180 $contentin = <<<EOF 181 <h1>Hello</h1><p>World!</p> 182 <img src='@@PLUGINFILE@@/file.txt'> 183 <img src='@@PLUGINFILE@@/other/file.txt'> 184 EOF; 185 $course = $this->getDataGenerator()->create_course(); 186 $page = $this->getDataGenerator()->create_module('page', (object) [ 187 'course' => $course, 188 'content' => $contentin, 189 'contentformat' => FORMAT_HTML, 190 ]); 191 192 $this->setUser($user); 193 194 $context = context_module::instance($page->cmid); 195 $expectedfiles = $this->create_files( 196 $context, 197 'mod_page', 198 'content', 199 (int) $page->id, 200 5, 201 'contentformat', 202 'content', 203 (int) $page->id, 204 5 205 ); 206 207 // Unexpected files. 208 $this->create_files($context, 'mod_page', 'content', (int) $page->id + 1, 5); 209 $this->create_files($context, 'mod_page', 'othercontent', (int) $page->id, 5); 210 $this->create_files($context, 'mod_foo', 'content', (int) $page->id, 5); 211 212 $component = 'mod_page'; 213 $uservisiblename = 'Page content'; 214 $tablename = 'page'; 215 $fieldname = 'content'; 216 $fieldid = (int) $page->id; 217 $formatfieldname = 'contentformat'; 218 $filearea = 'content'; 219 $itemid = (int) $page->id; 220 221 $exportable = new exportable_textarea( 222 $context, 223 $component, 224 $uservisiblename, 225 $tablename, 226 $fieldname, 227 $fieldid, 228 $formatfieldname, 229 $filearea, 230 $itemid, 231 null 232 ); 233 234 $this->assertInstanceOf(exportable_textarea::class, $exportable); 235 236 $pluginfilebase = moodle_url::make_pluginfile_url( 237 $context->id, $component, $filearea, null, '', '', false, true 238 )->out(false); 239 $expectedcontent = <<<EOF 240 <h1>Hello</h1><p>World!</p> 241 <img src='content/file.txt'> 242 <img src='{$pluginfilebase}/other/file.txt'> 243 EOF; 244 245 // Although files exist, the filearea and itemid were not included. 246 $this->assert_exportable_matches_file( 247 $component, $user, $context, $filearea, $expectedcontent, $expectedfiles, '', $exportable 248 ); 249 } 250 251 /** 252 * Create files for use in testing. 253 * 254 * @param context $context 255 * @param string $component 256 * @param string $filearea 257 * @param int $itemid 258 * @param int $count 259 * @return stored_file[] 260 */ 261 protected function create_files(context $context, string $component, string $filearea, int $itemid, int $count = 1): array { 262 $fs = get_file_storage(); 263 264 $files = []; 265 for ($i = 0; $i < $count; $i++) { 266 267 $filepath = '/'; 268 for ($j = 0; $j < $i; $j++) { 269 $filepath .= "{$j}/"; 270 } 271 272 $files[] = $fs->create_file_from_string( 273 (object) [ 274 'contextid' => $context->id, 275 'component' => $component, 276 'filearea' => $filearea, 277 'filepath' => $filepath, 278 'filename' => "file.txt", 279 'itemid' => $itemid, 280 ], 281 "File content: {$i}" 282 ); 283 } 284 285 return $files; 286 } 287 288 /** 289 * Assert that the supplied expotable matches the supplied file. 290 * 291 * @param string $component 292 * @param stdClass $user 293 * @param context $context 294 * @param string $filearea 295 * @param string $content 296 * @param stored_file[] $expectedfiles 297 * @param string $subdir 298 * @param exportable_textarea $exportable 299 */ 300 protected function assert_exportable_matches_file( 301 string $component, 302 stdClass $user, 303 context $context, 304 ?string $filearea, 305 string $content, 306 array $expectedfiles, 307 string $subdir, 308 exportable_textarea $exportable 309 ): void { 310 $archive = $this->getMockBuilder(zipwriter::class) 311 ->setConstructorArgs([$this->getMockBuilder(\ZipStream\ZipStream::class)->getmock()]) 312 ->setMethods([ 313 'is_file_in_archive', 314 'add_file_from_string', 315 'add_file_from_stored_file', 316 ]) 317 ->getMock(); 318 319 $archive->expects($this->any()) 320 ->method('is_file_in_archive') 321 ->willReturn(true); 322 323 $storedfileargs = []; 324 foreach ($expectedfiles as $file) { 325 $filepathinzip = dirname($subdir) . $file->get_filearea() . '/' . $file->get_filepath() . $file->get_filename(); 326 $filepathinzip = ltrim(preg_replace('#/+#', '/', $filepathinzip), '/'); 327 $storedfileargs[] = [ 328 $this->equalTo($context), 329 $this->equalTo($filepathinzip), 330 $this->equalTo($file), 331 ]; 332 } 333 334 $archive->expects($this->exactly(count($expectedfiles))) 335 ->method('add_file_from_stored_file') 336 ->withConsecutive(...$storedfileargs); 337 338 $archive->expects($this->never()) 339 ->method('add_file_from_string'); 340 341 $exportable->add_to_archive($archive); 342 } 343 344 /** 345 * Assert that the supplied expotable matches the supplied file. 346 * 347 * @param string $component 348 * @param stdClass $user 349 * @param context $context 350 * @param exportable_textarea $exportable 351 */ 352 protected function assert_exportable_empty( 353 string $component, 354 stdClass $user, 355 context $context, 356 exportable_textarea $exportable 357 ): void { 358 $archive = $this->getMockBuilder(zipwriter::class) 359 ->setConstructorArgs([$this->getMockBuilder(\ZipStream\ZipStream::class)->getmock()]) 360 ->setMethods([ 361 'add_file_from_stored_file', 362 'add_file_from_string', 363 'add_file_from_template', 364 ]) 365 ->getMock(); 366 367 $archive->expects($this->never()) 368 ->method('add_file_from_stored_file'); 369 $archive->expects($this->never()) 370 ->method('add_file_from_string'); 371 $archive->expects($this->never()) 372 ->method('add_file_from_template'); 373 374 $exportable->add_to_archive($archive); 375 } 376 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body