Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 39 and 401]

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