Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

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

   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 the moodle1 converter
  19   *
  20   * @package    core_backup
  21   * @subpackage backup-convert
  22   * @category   phpunit
  23   * @copyright  2011 Mark Nielsen <mark@moodlerooms.com>
  24   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  global $CFG;
  30  require_once($CFG->dirroot . '/backup/converter/moodle1/lib.php');
  31  
  32  
  33  class core_backup_moodle1_converter_testcase extends advanced_testcase {
  34  
  35      /** @var string the name of the directory containing the unpacked Moodle 1.9 backup */
  36      protected $tempdir;
  37  
  38      /** @var string the full name of the directory containing the unpacked Moodle 1.9 backup */
  39      protected $tempdirpath;
  40  
  41      /** @var string saved hash of an icon file used during testing */
  42      protected $iconhash;
  43  
  44      protected function setUp(): void {
  45          global $CFG;
  46  
  47          $this->tempdir = convert_helper::generate_id('unittest');
  48          $this->tempdirpath = make_backup_temp_directory($this->tempdir);
  49          check_dir_exists("$this->tempdirpath/course_files/sub1");
  50          check_dir_exists("$this->tempdirpath/moddata/unittest/4/7");
  51          copy(
  52              "$CFG->dirroot/backup/converter/moodle1/tests/fixtures/moodle.xml",
  53              "$this->tempdirpath/moodle.xml"
  54          );
  55          copy(
  56              "$CFG->dirroot/backup/converter/moodle1/tests/fixtures/icon.gif",
  57              "$this->tempdirpath/course_files/file1.gif"
  58          );
  59          copy(
  60              "$CFG->dirroot/backup/converter/moodle1/tests/fixtures/icon.gif",
  61              "$this->tempdirpath/course_files/sub1/file2.gif"
  62          );
  63          copy(
  64              "$CFG->dirroot/backup/converter/moodle1/tests/fixtures/icon.gif",
  65              "$this->tempdirpath/moddata/unittest/4/file1.gif"
  66          );
  67          copy(
  68              "$CFG->dirroot/backup/converter/moodle1/tests/fixtures/icon.gif",
  69              "$this->tempdirpath/moddata/unittest/4/icon.gif"
  70          );
  71          $this->iconhash = file_storage::hash_from_path($this->tempdirpath.'/moddata/unittest/4/icon.gif');
  72          copy(
  73              "$CFG->dirroot/backup/converter/moodle1/tests/fixtures/icon.gif",
  74              "$this->tempdirpath/moddata/unittest/4/7/icon.gif"
  75          );
  76      }
  77  
  78      protected function tearDown(): void {
  79          global $CFG;
  80          if (empty($CFG->keeptempdirectoriesonbackup)) {
  81              fulldelete($this->tempdirpath);
  82          }
  83      }
  84  
  85      public function test_detect_format() {
  86          $detected = moodle1_converter::detect_format($this->tempdir);
  87          $this->assertEquals(backup::FORMAT_MOODLE1, $detected);
  88      }
  89  
  90      public function test_convert_factory() {
  91          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
  92          $this->assertInstanceOf('moodle1_converter', $converter);
  93      }
  94  
  95      public function test_stash_storage_not_created() {
  96          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
  97          $this->expectException(moodle1_convert_storage_exception::class);
  98          $converter->set_stash('tempinfo', 12);
  99      }
 100  
 101      public function test_stash_requiring_empty_stash() {
 102          $this->resetAfterTest(true);
 103          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
 104          $converter->create_stash_storage();
 105          $converter->set_stash('tempinfo', 12);
 106          try {
 107              $converter->get_stash('anothertempinfo');
 108  
 109          } catch (moodle1_convert_empty_storage_exception $e) {
 110              // we must drop the storage here so we are able to re-create it in the next test
 111              $this->expectException(moodle1_convert_empty_storage_exception::class);
 112              $converter->drop_stash_storage();
 113              throw new moodle1_convert_empty_storage_exception('rethrowing');
 114          }
 115      }
 116  
 117      public function test_stash_storage() {
 118          $this->resetAfterTest(true);
 119          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
 120          $converter->create_stash_storage();
 121  
 122          // no implicit stashes
 123          $stashes = $converter->get_stash_names();
 124          $this->assertEquals(gettype($stashes), 'array');
 125          $this->assertTrue(empty($stashes));
 126  
 127          // test stashes without itemid
 128          $converter->set_stash('tempinfo1', 12);
 129          $converter->set_stash('tempinfo2', array('a' => 2, 'b' => 3));
 130          $stashes = $converter->get_stash_names();
 131          $this->assertEquals('array', gettype($stashes));
 132          $this->assertEquals(2, count($stashes));
 133          $this->assertTrue(in_array('tempinfo1', $stashes));
 134          $this->assertTrue(in_array('tempinfo2', $stashes));
 135          $this->assertEquals(12, $converter->get_stash('tempinfo1'));
 136          $this->assertEquals(array('a' => 2, 'b' => 3), $converter->get_stash('tempinfo2'));
 137  
 138          // overwriting a stashed value is allowed
 139          $converter->set_stash('tempinfo1', '13');
 140          $this->assertNotSame(13, $converter->get_stash('tempinfo1'));
 141          $this->assertSame('13', $converter->get_stash('tempinfo1'));
 142  
 143          // repeated reading is allowed
 144          $this->assertEquals('13', $converter->get_stash('tempinfo1'));
 145  
 146          // storing empty array
 147          $converter->set_stash('empty_array_stash', array());
 148          $restored = $converter->get_stash('empty_array_stash');
 149          //$this->assertEquals(gettype($restored), 'array'); // todo return null now, this needs MDL-27713 to be fixed, then uncomment
 150          $this->assertTrue(empty($restored));
 151  
 152          // test stashes with itemid
 153          $converter->set_stash('tempinfo', 'Hello', 1);
 154          $converter->set_stash('tempinfo', 'World', 2);
 155          $this->assertSame('Hello', $converter->get_stash('tempinfo', 1));
 156          $this->assertSame('World', $converter->get_stash('tempinfo', 2));
 157  
 158          // test get_stash_itemids()
 159          $ids = $converter->get_stash_itemids('course_fileref');
 160          $this->assertEquals(gettype($ids), 'array');
 161          $this->assertTrue(empty($ids));
 162  
 163          $converter->set_stash('course_fileref', null, 34);
 164          $converter->set_stash('course_fileref', null, 52);
 165          $ids = $converter->get_stash_itemids('course_fileref');
 166          $this->assertEquals(2, count($ids));
 167          $this->assertTrue(in_array(34, $ids));
 168          $this->assertTrue(in_array(52, $ids));
 169  
 170          $converter->drop_stash_storage();
 171      }
 172  
 173      public function test_get_stash_or_default() {
 174          $this->resetAfterTest(true);
 175          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
 176          $converter->create_stash_storage();
 177  
 178          $this->assertTrue(is_null($converter->get_stash_or_default('stashname')));
 179          $this->assertTrue(is_null($converter->get_stash_or_default('stashname', 7)));
 180          $this->assertTrue('default' === $converter->get_stash_or_default('stashname', 0, 'default'));
 181          $this->assertTrue(array('foo', 'bar') === $converter->get_stash_or_default('stashname', 42, array('foo', 'bar')));
 182  
 183          //$converter->set_stash('stashname', 0);
 184          //$this->assertFalse(is_null($converter->get_stash_or_default('stashname'))); // todo returns true now, this needs MDL-27713 to be fixed
 185  
 186          //$converter->set_stash('stashname', '');
 187          //$this->assertFalse(is_null($converter->get_stash_or_default('stashname'))); // todo returns true now, this needs MDL-27713 to be fixed
 188  
 189          //$converter->set_stash('stashname', array());
 190          //$this->assertFalse(is_null($converter->get_stash_or_default('stashname'))); // todo returns true now, this needs MDL-27713 to be fixed
 191  
 192          $converter->set_stash('stashname', 42);
 193          $this->assertTrue(42 === $converter->get_stash_or_default('stashname'));
 194          $this->assertTrue(is_null($converter->get_stash_or_default('stashname', 1)));
 195          $this->assertTrue(42 === $converter->get_stash_or_default('stashname', 0, 61));
 196  
 197          $converter->set_stash('stashname', array(42 => (object)array('id' => 42)), 18);
 198          $stashed = $converter->get_stash_or_default('stashname', 18, 1984);
 199          $this->assertEquals(gettype($stashed), 'array');
 200          $this->assertTrue(is_object($stashed[42]));
 201          $this->assertTrue($stashed[42]->id === 42);
 202  
 203          $converter->drop_stash_storage();
 204      }
 205  
 206      public function test_get_contextid() {
 207          $this->resetAfterTest(true);
 208  
 209          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
 210  
 211          // stash storage must be created in advance
 212          $converter->create_stash_storage();
 213  
 214          // ids are generated on the first call
 215          $id1 = $converter->get_contextid(CONTEXT_BLOCK, 10);
 216          $id2 = $converter->get_contextid(CONTEXT_BLOCK, 11);
 217          $id3 = $converter->get_contextid(CONTEXT_MODULE, 10);
 218  
 219          $this->assertNotEquals($id1, $id2);
 220          $this->assertNotEquals($id1, $id3);
 221          $this->assertNotEquals($id2, $id3);
 222  
 223          // and then re-used if called with the same params
 224          $this->assertEquals($id1, $converter->get_contextid(CONTEXT_BLOCK, 10));
 225          $this->assertEquals($id2, $converter->get_contextid(CONTEXT_BLOCK, 11));
 226          $this->assertEquals($id3, $converter->get_contextid(CONTEXT_MODULE, 10));
 227  
 228          // for system and course level, the instance is irrelevant
 229          // as we need only one system and one course
 230          $id1 = $converter->get_contextid(CONTEXT_COURSE);
 231          $id2 = $converter->get_contextid(CONTEXT_COURSE, 10);
 232          $id3 = $converter->get_contextid(CONTEXT_COURSE, 14);
 233  
 234          $this->assertEquals($id1, $id2);
 235          $this->assertEquals($id1, $id3);
 236  
 237          $id1 = $converter->get_contextid(CONTEXT_SYSTEM);
 238          $id2 = $converter->get_contextid(CONTEXT_SYSTEM, 11);
 239          $id3 = $converter->get_contextid(CONTEXT_SYSTEM, 15);
 240  
 241          $this->assertEquals($id1, $id2);
 242          $this->assertEquals($id1, $id3);
 243  
 244          $converter->drop_stash_storage();
 245      }
 246  
 247      public function test_get_nextid() {
 248          $this->resetAfterTest(true);
 249  
 250          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
 251  
 252          $id1 = $converter->get_nextid();
 253          $id2 = $converter->get_nextid();
 254          $id3 = $converter->get_nextid();
 255  
 256          $this->assertTrue(0 < $id1);
 257          $this->assertTrue($id1 < $id2);
 258          $this->assertTrue($id2 < $id3);
 259      }
 260  
 261      public function test_migrate_file() {
 262          $this->resetAfterTest(true);
 263  
 264          // set-up the file manager
 265          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
 266          $converter->create_stash_storage();
 267          $contextid = $converter->get_contextid(CONTEXT_MODULE, 32);
 268          $fileman   = $converter->get_file_manager($contextid, 'mod_unittest', 'testarea');
 269          // this fileman has not converted anything yet
 270          $fileids = $fileman->get_fileids();
 271          $this->assertEquals(gettype($fileids), 'array');
 272          $this->assertEquals(0, count($fileids));
 273          // try to migrate an invalid file
 274          $fileman->itemid = 1;
 275          $thrown = false;
 276          try {
 277              $fileman->migrate_file('/../../../../../../../../../../../../../../etc/passwd');
 278          } catch (moodle1_convert_exception $e) {
 279              $thrown = true;
 280          }
 281          $this->assertTrue($thrown);
 282          // migrate a single file
 283          $fileman->itemid = 4;
 284          $fileman->migrate_file('moddata/unittest/4/icon.gif');
 285          $subdir = substr($this->iconhash, 0, 2);
 286          $this->assertTrue(is_file($converter->get_workdir_path().'/files/'.$subdir.'/'.$this->iconhash));
 287          // get the file id
 288          $fileids = $fileman->get_fileids();
 289          $this->assertEquals(gettype($fileids), 'array');
 290          $this->assertEquals(1, count($fileids));
 291          // migrate another single file into another file area
 292          $fileman->filearea = 'anotherarea';
 293          $fileman->itemid = 7;
 294          $fileman->migrate_file('moddata/unittest/4/7/icon.gif', '/', 'renamed.gif');
 295          // get the file records
 296          $filerecordids = $converter->get_stash_itemids('files');
 297          foreach ($filerecordids as $filerecordid) {
 298              $filerecord = $converter->get_stash('files', $filerecordid);
 299              $this->assertEquals($this->iconhash, $filerecord['contenthash']);
 300              $this->assertEquals($contextid, $filerecord['contextid']);
 301              $this->assertEquals('mod_unittest', $filerecord['component']);
 302              if ($filerecord['filearea'] === 'testarea') {
 303                  $this->assertEquals(4, $filerecord['itemid']);
 304                  $this->assertEquals('icon.gif', $filerecord['filename']);
 305              }
 306          }
 307          // explicitly clear the list of migrated files
 308          $this->assertTrue(count($fileman->get_fileids()) > 0);
 309          $fileman->reset_fileids();
 310          $this->assertTrue(count($fileman->get_fileids()) == 0);
 311          $converter->drop_stash_storage();
 312      }
 313  
 314      public function test_migrate_directory() {
 315          $this->resetAfterTest(true);
 316  
 317          // Set-up the file manager.
 318          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
 319          $converter->create_stash_storage();
 320          $contextid = $converter->get_contextid(CONTEXT_MODULE, 32);
 321          $fileman   = $converter->get_file_manager($contextid, 'mod_unittest', 'testarea');
 322          // This fileman has not converted anything yet.
 323          $fileids = $fileman->get_fileids();
 324          $this->assertEquals(gettype($fileids), 'array');
 325          $this->assertEquals(0, count($fileids));
 326          // Try to migrate a non-existing directory.
 327          $returned = $fileman->migrate_directory('not/existing/directory');
 328          $this->assertEquals(gettype($returned), 'array');
 329          $this->assertEquals(0, count($returned));
 330          $fileids = $fileman->get_fileids();
 331          $this->assertEquals(gettype($fileids), 'array');
 332          $this->assertEquals(0, count($fileids));
 333          // Try to migrate whole course_files.
 334          $returned = $fileman->migrate_directory('course_files');
 335          $this->assertEquals(gettype($returned), 'array');
 336          $this->assertEquals(4, count($returned)); // Two files, two directories.
 337          $fileids = $fileman->get_fileids();
 338          $this->assertEquals(gettype($fileids), 'array');
 339          $this->assertEquals(4, count($fileids));
 340          $subdir = substr($this->iconhash, 0, 2);
 341          $this->assertTrue(is_file($converter->get_workdir_path().'/files/'.$subdir.'/'.$this->iconhash));
 342  
 343          // Check the file records.
 344          $files = array();
 345          $filerecordids = $converter->get_stash_itemids('files');
 346          foreach ($filerecordids as $filerecordid) {
 347              $filerecord = $converter->get_stash('files', $filerecordid);
 348              $files[$filerecord['filepath'].$filerecord['filename']] = $filerecord;
 349          }
 350          $this->assertEquals('array', gettype($files['/.']));
 351          $this->assertEquals('array', gettype($files['/file1.gif']));
 352          $this->assertEquals('array', gettype($files['/sub1/.']));
 353          $this->assertEquals('array', gettype($files['/sub1/file2.gif']));
 354          $this->assertEquals(file_storage::hash_from_string(''), $files['/.']['contenthash']);
 355          $this->assertEquals(file_storage::hash_from_string(''), $files['/sub1/.']['contenthash']);
 356          $this->assertEquals($this->iconhash, $files['/file1.gif']['contenthash']);
 357          $this->assertEquals($this->iconhash, $files['/sub1/file2.gif']['contenthash']);
 358  
 359          $converter->drop_stash_storage();
 360      }
 361  
 362      public function test_migrate_directory_with_trailing_slash() {
 363          $this->resetAfterTest(true);
 364  
 365          // Set-up the file manager.
 366          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
 367          $converter->create_stash_storage();
 368          $contextid = $converter->get_contextid(CONTEXT_MODULE, 32);
 369          $fileman   = $converter->get_file_manager($contextid, 'mod_unittest', 'testarea');
 370          // Try to migrate a subdirectory passed with the trailing slash.
 371          $returned = $fileman->migrate_directory('course_files/sub1/');
 372          // Debugging message must be thrown in this case.
 373          $this->assertDebuggingCalled(null, DEBUG_DEVELOPER);
 374          $this->assertEquals(gettype($returned), 'array');
 375          $this->assertEquals(2, count($returned)); // One file, one directory.
 376  
 377          $converter->drop_stash_storage();
 378      }
 379  
 380      public function test_convert_path() {
 381          $path = new convert_path('foo_bar', '/ROOT/THINGS/FOO/BAR');
 382          $this->assertEquals('foo_bar', $path->get_name());
 383          $this->assertEquals('/ROOT/THINGS/FOO/BAR', $path->get_path());
 384          $this->assertEquals('process_foo_bar', $path->get_processing_method());
 385          $this->assertEquals('on_foo_bar_start', $path->get_start_method());
 386          $this->assertEquals('on_foo_bar_end', $path->get_end_method());
 387      }
 388  
 389      public function test_convert_path_implicit_recipes() {
 390          $path = new convert_path('foo_bar', '/ROOT/THINGS/FOO/BAR');
 391          $data = array(
 392              'ID' => 76,
 393              'ELOY' => 'stronk7',
 394              'MARTIN' => 'moodler',
 395              'EMPTY' => null,
 396          );
 397          // apply default recipes (converting keys to lowercase)
 398          $data = $path->apply_recipes($data);
 399          $this->assertEquals(4, count($data));
 400          $this->assertEquals(76, $data['id']);
 401          $this->assertEquals('stronk7', $data['eloy']);
 402          $this->assertEquals('moodler', $data['martin']);
 403          $this->assertSame(null, $data['empty']);
 404      }
 405  
 406      public function test_convert_path_explicit_recipes() {
 407          $path = new convert_path(
 408              'foo_bar', '/ROOT/THINGS/FOO/BAR',
 409              array(
 410                  'newfields' => array(
 411                      'david' => 'mudrd8mz',
 412                      'petr'  => 'skodak',
 413                  ),
 414                  'renamefields' => array(
 415                      'empty' => 'nothing',
 416                  ),
 417                  'dropfields' => array(
 418                      'id'
 419                  ),
 420              )
 421          );
 422          $data = array(
 423              'ID' => 76,
 424              'ELOY' => 'stronk7',
 425              'MARTIN' => 'moodler',
 426              'EMPTY' => null,
 427          );
 428          $data = $path->apply_recipes($data);
 429  
 430          $this->assertEquals(5, count($data));
 431          $this->assertFalse(array_key_exists('id', $data));
 432          $this->assertEquals('stronk7', $data['eloy']);
 433          $this->assertEquals('moodler', $data['martin']);
 434          $this->assertEquals('mudrd8mz', $data['david']);
 435          $this->assertEquals('skodak', $data['petr']);
 436          $this->assertSame(null, $data['nothing']);
 437      }
 438  
 439      public function test_grouped_data_on_nongrouped_convert_path() {
 440          // prepare some grouped data
 441          $data = array(
 442              'ID' => 77,
 443              'NAME' => 'Pale lagers',
 444              'BEERS' => array(
 445                  array(
 446                      'BEER' => array(
 447                          'ID' => 67,
 448                          'NAME' => 'Pilsner Urquell',
 449                      )
 450                  ),
 451                  array(
 452                      'BEER' => array(
 453                          'ID' => 34,
 454                          'NAME' => 'Heineken',
 455                      )
 456                  ),
 457              )
 458          );
 459  
 460          // declare a non-grouped path
 461          $path = new convert_path('beer_style', '/ROOT/BEER_STYLES/BEER_STYLE');
 462  
 463          // an attempt to apply recipes throws exception because we do not expect grouped data
 464          $this->expectException(convert_path_exception::class);
 465          $data = $path->apply_recipes($data);
 466      }
 467  
 468      public function test_grouped_convert_path_with_recipes() {
 469          // prepare some grouped data
 470          $data = array(
 471              'ID' => 77,
 472              'NAME' => 'Pale lagers',
 473              'BEERS' => array(
 474                  array(
 475                      'BEER' => array(
 476                          'ID' => 67,
 477                          'NAME' => 'Pilsner Urquell',
 478                      )
 479                  ),
 480                  array(
 481                      'BEER' => array(
 482                          'ID' => 34,
 483                          'NAME' => 'Heineken',
 484                      )
 485                  ),
 486              )
 487          );
 488  
 489          // implict recipes work for grouped data if the path is declared as grouped
 490          $path = new convert_path('beer_style', '/ROOT/BEER_STYLES/BEER_STYLE', array(), true);
 491          $data = $path->apply_recipes($data);
 492          $this->assertEquals('Heineken', $data['beers'][1]['beer']['name']);
 493  
 494          // an attempt to provide explicit recipes on grouped elements throws exception
 495          $this->expectException(convert_path_exception::class);
 496          $path = new convert_path(
 497              'beer_style', '/ROOT/BEER_STYLES/BEER_STYLE',
 498              array(
 499                  'renamefields' => array(
 500                      'name' => 'beername',   // note this is confusing recipe because the 'name' is used for both
 501                      // beer-style name ('Pale lagers') and beer name ('Pilsner Urquell')
 502                  )
 503              ), true);
 504      }
 505  
 506      public function test_referenced_course_files() {
 507  
 508          $text = 'This is a text containing links to file.php
 509  as it is parsed from the backup file. <br /><br /><img border="0" width="110" vspace="0" hspace="0" height="92" title="News" alt="News" src="$@FILEPHP@$$@SLASH@$pics$@SLASH@$news.gif" /><a href="$@FILEPHP@$$@SLASH@$pics$@SLASH@$news.gif$@FORCEDOWNLOAD@$">download image</a><br />
 510      <div><a href=\'$@FILEPHP@$/../../../../../../../../../../../../../../../etc/passwd\'>download passwords</a></div>
 511      <div><a href=\'$@FILEPHP@$$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$etc$@SLASH@$shadow\'>download shadows</a></div>
 512      <br /><a href=\'$@FILEPHP@$$@SLASH@$MANUAL.DOC$@FORCEDOWNLOAD@$\'>download manual</a><br />';
 513  
 514          $files = moodle1_converter::find_referenced_files($text);
 515          $this->assertEquals(gettype($files), 'array');
 516          $this->assertEquals(2, count($files));
 517          $this->assertTrue(in_array('/pics/news.gif', $files));
 518          $this->assertTrue(in_array('/MANUAL.DOC', $files));
 519  
 520          $text = moodle1_converter::rewrite_filephp_usage($text, array('/pics/news.gif', '/another/file/notused.txt'));
 521          $this->assertEquals($text, 'This is a text containing links to file.php
 522  as it is parsed from the backup file. <br /><br /><img border="0" width="110" vspace="0" hspace="0" height="92" title="News" alt="News" src="@@PLUGINFILE@@/pics/news.gif" /><a href="@@PLUGINFILE@@/pics/news.gif?forcedownload=1">download image</a><br />
 523      <div><a href=\'$@FILEPHP@$/../../../../../../../../../../../../../../../etc/passwd\'>download passwords</a></div>
 524      <div><a href=\'$@FILEPHP@$$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$etc$@SLASH@$shadow\'>download shadows</a></div>
 525      <br /><a href=\'$@FILEPHP@$$@SLASH@$MANUAL.DOC$@FORCEDOWNLOAD@$\'>download manual</a><br />');
 526      }
 527  
 528      public function test_referenced_files_urlencoded() {
 529  
 530          $text = 'This is a text containing links to file.php
 531  as it is parsed from the backup file. <br /><br /><img border="0" width="110" vspace="0" hspace="0" height="92" title="News" alt="News" src="$@FILEPHP@$$@SLASH@$pics$@SLASH@$news.gif" /><a href="$@FILEPHP@$$@SLASH@$pics$@SLASH@$news.gif$@FORCEDOWNLOAD@$">no space</a><br />
 532      <br /><a href=\'$@FILEPHP@$$@SLASH@$pics$@SLASH@$news%20with%20spaces.gif$@FORCEDOWNLOAD@$\'>with urlencoded spaces</a><br />
 533  <a href="$@FILEPHP@$$@SLASH@$illegal%20pics%2Bmovies$@SLASH@$romeo%2Bjuliet.avi">Download the full AVI for free! (space and plus encoded)</a>
 534  <a href="$@FILEPHP@$$@SLASH@$illegal pics+movies$@SLASH@$romeo+juliet.avi">Download the full AVI for free! (none encoded)</a>
 535  <a href="$@FILEPHP@$$@SLASH@$illegal%20pics+movies$@SLASH@$romeo+juliet.avi">Download the full AVI for free! (only space encoded)</a>
 536  <a href="$@FILEPHP@$$@SLASH@$illegal pics%2Bmovies$@SLASH@$romeo%2Bjuliet.avi">Download the full AVI for free! (only plus)</a>';
 537  
 538          $files = moodle1_converter::find_referenced_files($text);
 539          $this->assertEquals(gettype($files), 'array');
 540          $this->assertEquals(3, count($files));
 541          $this->assertTrue(in_array('/pics/news.gif', $files));
 542          $this->assertTrue(in_array('/pics/news with spaces.gif', $files));
 543          $this->assertTrue(in_array('/illegal pics+movies/romeo+juliet.avi', $files));
 544  
 545          $text = moodle1_converter::rewrite_filephp_usage($text, $files);
 546          $this->assertEquals('This is a text containing links to file.php
 547  as it is parsed from the backup file. <br /><br /><img border="0" width="110" vspace="0" hspace="0" height="92" title="News" alt="News" src="@@PLUGINFILE@@/pics/news.gif" /><a href="@@PLUGINFILE@@/pics/news.gif?forcedownload=1">no space</a><br />
 548      <br /><a href=\'@@PLUGINFILE@@/pics/news%20with%20spaces.gif?forcedownload=1\'>with urlencoded spaces</a><br />
 549  <a href="@@PLUGINFILE@@/illegal%20pics%2Bmovies/romeo%2Bjuliet.avi">Download the full AVI for free! (space and plus encoded)</a>
 550  <a href="@@PLUGINFILE@@/illegal%20pics%2Bmovies/romeo%2Bjuliet.avi">Download the full AVI for free! (none encoded)</a>
 551  <a href="$@FILEPHP@$$@SLASH@$illegal%20pics+movies$@SLASH@$romeo+juliet.avi">Download the full AVI for free! (only space encoded)</a>
 552  <a href="$@FILEPHP@$$@SLASH@$illegal pics%2Bmovies$@SLASH@$romeo%2Bjuliet.avi">Download the full AVI for free! (only plus)</a>', $text);
 553      }
 554  
 555      public function test_question_bank_conversion() {
 556          global $CFG;
 557  
 558          $this->resetAfterTest(true);
 559  
 560          copy(
 561              "$CFG->dirroot/backup/converter/moodle1/tests/fixtures/questions.xml",
 562              "$this->tempdirpath/moodle.xml"
 563          );
 564          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
 565          $converter->convert();
 566      }
 567  
 568      public function test_convert_run_convert() {
 569          $this->resetAfterTest(true);
 570          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
 571          $converter->convert();
 572      }
 573  
 574      public function test_inforef_manager() {
 575          $converter = convert_factory::get_converter('moodle1', $this->tempdir);
 576          $inforef = $converter->get_inforef_manager('unittest');
 577          $inforef->add_ref('file', 45);
 578          $inforef->add_refs('file', array(46, 47));
 579          // todo test the write_refs() via some dummy xml_writer
 580          $this->expectException('coding_exception');
 581          $inforef->add_ref('unknown_referenced_item_name', 76);
 582      }
 583  }