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