[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/filestorage/tests/ -> file_storage_test.php (source)

   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 /lib/filestorage/file_storage.php
  19   *
  20   * @package   core_files
  21   * @category  phpunit
  22   * @copyright 2012 David Mudrak <[email protected]>
  23   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  global $CFG;
  29  require_once($CFG->libdir . '/filelib.php');
  30  require_once($CFG->dirroot . '/repository/lib.php');
  31  require_once($CFG->libdir . '/filestorage/stored_file.php');
  32  
  33  class core_files_file_storage_testcase extends advanced_testcase {
  34  
  35      /**
  36       * Files can be created from strings.
  37       */
  38      public function test_create_file_from_string() {
  39          global $DB;
  40  
  41          $this->resetAfterTest(true);
  42  
  43          // Number of files installed in the database on a fresh Moodle site.
  44          $installedfiles = $DB->count_records('files', array());
  45  
  46          $content = 'abcd';
  47          $syscontext = context_system::instance();
  48          $filerecord = array(
  49              'contextid' => $syscontext->id,
  50              'component' => 'core',
  51              'filearea'  => 'unittest',
  52              'itemid'    => 0,
  53              'filepath'  => '/images/',
  54              'filename'  => 'testfile.txt',
  55          );
  56          $pathhash = sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].$filerecord['filename']);
  57  
  58          $fs = get_file_storage();
  59          $file = $fs->create_file_from_string($filerecord, $content);
  60  
  61          $this->assertInstanceOf('stored_file', $file);
  62          $this->assertSame(sha1($content), $file->get_contenthash());
  63          $this->assertSame($pathhash, $file->get_pathnamehash());
  64  
  65          $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>$pathhash)));
  66  
  67          $location = test_stored_file_inspection::get_pretected_pathname($file);
  68  
  69          $this->assertFileExists($location);
  70  
  71          // Verify the dir placeholder files are created.
  72          $this->assertEquals($installedfiles + 3, $DB->count_records('files', array()));
  73          $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].'/.'))));
  74          $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].'.'))));
  75  
  76          // Tests that missing content file is recreated.
  77  
  78          unlink($location);
  79          $this->assertFileNotExists($location);
  80  
  81          $filerecord['filename'] = 'testfile2.txt';
  82          $file2 = $fs->create_file_from_string($filerecord, $content);
  83          $this->assertInstanceOf('stored_file', $file2);
  84          $this->assertSame($file->get_contenthash(), $file2->get_contenthash());
  85          $this->assertFileExists($location);
  86  
  87          $this->assertEquals($installedfiles + 4, $DB->count_records('files', array()));
  88  
  89          // Test that borked content file is recreated.
  90  
  91          $this->assertSame(2, file_put_contents($location, 'xx'));
  92  
  93          $filerecord['filename'] = 'testfile3.txt';
  94          $file3 = $fs->create_file_from_string($filerecord, $content);
  95          $this->assertInstanceOf('stored_file', $file3);
  96          $this->assertSame($file->get_contenthash(), $file3->get_contenthash());
  97          $this->assertFileExists($location);
  98  
  99          $this->assertSame($content, file_get_contents($location));
 100          $this->assertDebuggingCalled();
 101  
 102          $this->assertEquals($installedfiles + 5, $DB->count_records('files', array()));
 103      }
 104  
 105      /**
 106       * Local files can be added to the filepool
 107       */
 108      public function test_create_file_from_pathname() {
 109          global $CFG, $DB;
 110  
 111          $this->resetAfterTest(true);
 112  
 113          // Number of files installed in the database on a fresh Moodle site.
 114          $installedfiles = $DB->count_records('files', array());
 115  
 116          $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
 117          $syscontext = context_system::instance();
 118          $filerecord = array(
 119              'contextid' => $syscontext->id,
 120              'component' => 'core',
 121              'filearea'  => 'unittest',
 122              'itemid'    => 0,
 123              'filepath'  => '/images/',
 124              'filename'  => 'testimage.jpg',
 125          );
 126          $pathhash = sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].$filerecord['filename']);
 127  
 128          $fs = get_file_storage();
 129          $file = $fs->create_file_from_pathname($filerecord, $filepath);
 130  
 131          $this->assertInstanceOf('stored_file', $file);
 132          $this->assertSame(sha1_file($filepath), $file->get_contenthash());
 133  
 134          $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>$pathhash)));
 135  
 136          $location = test_stored_file_inspection::get_pretected_pathname($file);
 137  
 138          $this->assertFileExists($location);
 139  
 140          // Verify the dir placeholder files are created.
 141          $this->assertEquals($installedfiles + 3, $DB->count_records('files', array()));
 142          $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].'/.'))));
 143          $this->assertTrue($DB->record_exists('files', array('pathnamehash'=>sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].'.'))));
 144  
 145          // Tests that missing content file is recreated.
 146  
 147          unlink($location);
 148          $this->assertFileNotExists($location);
 149  
 150          $filerecord['filename'] = 'testfile2.jpg';
 151          $file2 = $fs->create_file_from_pathname($filerecord, $filepath);
 152          $this->assertInstanceOf('stored_file', $file2);
 153          $this->assertSame($file->get_contenthash(), $file2->get_contenthash());
 154          $this->assertFileExists($location);
 155  
 156          $this->assertEquals($installedfiles + 4, $DB->count_records('files', array()));
 157  
 158          // Test that borked content file is recreated.
 159  
 160          $this->assertSame(2, file_put_contents($location, 'xx'));
 161  
 162          $filerecord['filename'] = 'testfile3.jpg';
 163          $file3 = $fs->create_file_from_pathname($filerecord, $filepath);
 164          $this->assertInstanceOf('stored_file', $file3);
 165          $this->assertSame($file->get_contenthash(), $file3->get_contenthash());
 166          $this->assertFileExists($location);
 167  
 168          $this->assertSame(file_get_contents($filepath), file_get_contents($location));
 169          $this->assertDebuggingCalled();
 170  
 171          $this->assertEquals($installedfiles + 5, $DB->count_records('files', array()));
 172  
 173          // Test invalid file creation.
 174  
 175          $filerecord['filename'] = 'testfile4.jpg';
 176          try {
 177              $fs->create_file_from_pathname($filerecord, $filepath.'nonexistent');
 178              $this->fail('Exception expected when trying to add non-existent stored file.');
 179          } catch (Exception $e) {
 180              $this->assertInstanceOf('file_exception', $e);
 181          }
 182      }
 183  
 184      /**
 185       * Tests get get file.
 186       */
 187      public function test_get_file() {
 188          global $CFG;
 189  
 190          $this->resetAfterTest(false);
 191  
 192          $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
 193          $syscontext = context_system::instance();
 194          $filerecord = array(
 195              'contextid' => $syscontext->id,
 196              'component' => 'core',
 197              'filearea'  => 'unittest',
 198              'itemid'    => 0,
 199              'filepath'  => '/images/',
 200              'filename'  => 'testimage.jpg',
 201          );
 202          $pathhash = sha1('/'.$filerecord['contextid'].'/'.$filerecord['component'].'/'.$filerecord['filearea'].'/'.$filerecord['itemid'].$filerecord['filepath'].$filerecord['filename']);
 203  
 204          $fs = get_file_storage();
 205          $file = $fs->create_file_from_pathname($filerecord, $filepath);
 206  
 207          $this->assertInstanceOf('stored_file', $file);
 208          $this->assertEquals($syscontext->id, $file->get_contextid());
 209          $this->assertEquals('core', $file->get_component());
 210          $this->assertEquals('unittest', $file->get_filearea());
 211          $this->assertEquals(0, $file->get_itemid());
 212          $this->assertEquals('/images/', $file->get_filepath());
 213          $this->assertEquals('testimage.jpg', $file->get_filename());
 214          $this->assertEquals(filesize($filepath), $file->get_filesize());
 215          $this->assertEquals($pathhash, $file->get_pathnamehash());
 216  
 217          return $file;
 218      }
 219  
 220      /**
 221       * Local images can be added to the filepool and their preview can be obtained
 222       *
 223       * @depends test_get_file
 224       */
 225      public function test_get_file_preview(stored_file $file) {
 226          global $CFG;
 227  
 228          $this->resetAfterTest();
 229          $fs = get_file_storage();
 230  
 231          $previewtinyicon = $fs->get_file_preview($file, 'tinyicon');
 232          $this->assertInstanceOf('stored_file', $previewtinyicon);
 233          $this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename());
 234  
 235          $previewtinyicon = $fs->get_file_preview($file, 'thumb');
 236          $this->assertInstanceOf('stored_file', $previewtinyicon);
 237          $this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename());
 238  
 239          $this->setExpectedException('file_exception');
 240          $fs->get_file_preview($file, 'amodewhichdoesntexist');
 241      }
 242  
 243      public function test_get_file_preview_nonimage() {
 244          $this->resetAfterTest(true);
 245          $syscontext = context_system::instance();
 246          $filerecord = array(
 247              'contextid' => $syscontext->id,
 248              'component' => 'core',
 249              'filearea'  => 'unittest',
 250              'itemid'    => 0,
 251              'filepath'  => '/textfiles/',
 252              'filename'  => 'testtext.txt',
 253          );
 254  
 255          $fs = get_file_storage();
 256          $fs->create_file_from_string($filerecord, 'text contents');
 257          $textfile = $fs->get_file($syscontext->id, $filerecord['component'], $filerecord['filearea'],
 258              $filerecord['itemid'], $filerecord['filepath'], $filerecord['filename']);
 259  
 260          $preview = $fs->get_file_preview($textfile, 'thumb');
 261          $this->assertFalse($preview);
 262      }
 263  
 264      /**
 265       * Make sure renaming is working
 266       *
 267       * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org}
 268       */
 269      public function test_file_renaming() {
 270          global $CFG;
 271  
 272          $this->resetAfterTest();
 273          $fs = get_file_storage();
 274          $syscontext = context_system::instance();
 275          $component = 'core';
 276          $filearea  = 'unittest';
 277          $itemid    = 0;
 278          $filepath  = '/';
 279          $filename  = 'test.txt';
 280  
 281          $filerecord = array(
 282              'contextid' => $syscontext->id,
 283              'component' => $component,
 284              'filearea'  => $filearea,
 285              'itemid'    => $itemid,
 286              'filepath'  => $filepath,
 287              'filename'  => $filename,
 288          );
 289  
 290          $originalfile = $fs->create_file_from_string($filerecord, 'Test content');
 291          $this->assertInstanceOf('stored_file', $originalfile);
 292          $contenthash = $originalfile->get_contenthash();
 293          $newpath = '/test/';
 294          $newname = 'newtest.txt';
 295  
 296          // This should work.
 297          $originalfile->rename($newpath, $newname);
 298          $file = $fs->get_file($syscontext->id, $component, $filearea, $itemid, $newpath, $newname);
 299          $this->assertInstanceOf('stored_file', $file);
 300          $this->assertEquals($contenthash, $file->get_contenthash());
 301  
 302          // Try break it.
 303          $this->setExpectedException('file_exception',
 304                  'Can not create file "1/core/unittest/0/test/newtest.txt" (file exists, cannot rename)');
 305          // This shall throw exception.
 306          $originalfile->rename($newpath, $newname);
 307      }
 308  
 309      /**
 310       * Create file from reference tests
 311       *
 312       * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org}
 313       */
 314      public function test_create_file_from_reference() {
 315          global $CFG, $DB;
 316  
 317          $this->resetAfterTest();
 318          // Create user.
 319          $generator = $this->getDataGenerator();
 320          $user = $generator->create_user();
 321          $this->setUser($user);
 322          $usercontext = context_user::instance($user->id);
 323          $syscontext = context_system::instance();
 324  
 325          $fs = get_file_storage();
 326  
 327          $repositorypluginname = 'user';
 328          // Override repository permission.
 329          $capability = 'repository/' . $repositorypluginname . ':view';
 330          $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');
 331          assign_capability($capability, CAP_ALLOW, $allroles['guest'], $syscontext->id, true);
 332  
 333          $args = array();
 334          $args['type'] = $repositorypluginname;
 335          $repos = repository::get_instances($args);
 336          $userrepository = reset($repos);
 337          $this->assertInstanceOf('repository', $userrepository);
 338  
 339          $component = 'user';
 340          $filearea  = 'private';
 341          $itemid    = 0;
 342          $filepath  = '/';
 343          $filename  = 'userfile.txt';
 344  
 345          $filerecord = array(
 346              'contextid' => $usercontext->id,
 347              'component' => $component,
 348              'filearea'  => $filearea,
 349              'itemid'    => $itemid,
 350              'filepath'  => $filepath,
 351              'filename'  => $filename,
 352          );
 353  
 354          $content = 'Test content';
 355          $originalfile = $fs->create_file_from_string($filerecord, $content);
 356          $this->assertInstanceOf('stored_file', $originalfile);
 357  
 358          $newfilerecord = array(
 359              'contextid' => $syscontext->id,
 360              'component' => 'core',
 361              'filearea'  => 'phpunit',
 362              'itemid'    => 0,
 363              'filepath'  => $filepath,
 364              'filename'  => $filename,
 365          );
 366          $ref = $fs->pack_reference($filerecord);
 367          $newstoredfile = $fs->create_file_from_reference($newfilerecord, $userrepository->id, $ref);
 368          $this->assertInstanceOf('stored_file', $newstoredfile);
 369          $this->assertEquals($userrepository->id, $newstoredfile->get_repository_id());
 370          $this->assertEquals($originalfile->get_contenthash(), $newstoredfile->get_contenthash());
 371          $this->assertEquals($originalfile->get_filesize(), $newstoredfile->get_filesize());
 372          $this->assertRegExp('#' . $filename. '$#', $newstoredfile->get_reference_details());
 373  
 374          // Test looking for references.
 375          $count = $fs->get_references_count_by_storedfile($originalfile);
 376          $this->assertEquals(1, $count);
 377          $files = $fs->get_references_by_storedfile($originalfile);
 378          $file = reset($files);
 379          $this->assertEquals($file, $newstoredfile);
 380  
 381          // Look for references by repository ID.
 382          $files = $fs->get_external_files($userrepository->id);
 383          $file = reset($files);
 384          $this->assertEquals($file, $newstoredfile);
 385  
 386          // Try convert reference to local file.
 387          $importedfile = $fs->import_external_file($newstoredfile);
 388          $this->assertFalse($importedfile->is_external_file());
 389          $this->assertInstanceOf('stored_file', $importedfile);
 390          // Still readable?
 391          $this->assertEquals($content, $importedfile->get_content());
 392      }
 393  
 394      private function setup_three_private_files() {
 395  
 396          $this->resetAfterTest();
 397  
 398          $generator = $this->getDataGenerator();
 399          $user = $generator->create_user();
 400          $this->setUser($user->id);
 401          $usercontext = context_user::instance($user->id);
 402          // Create a user private file.
 403          $file1 = new stdClass;
 404          $file1->contextid = $usercontext->id;
 405          $file1->component = 'user';
 406          $file1->filearea  = 'private';
 407          $file1->itemid    = 0;
 408          $file1->filepath  = '/';
 409          $file1->filename  = '1.txt';
 410          $file1->source    = 'test';
 411  
 412          $fs = get_file_storage();
 413          $userfile1 = $fs->create_file_from_string($file1, 'file1 content');
 414          $this->assertInstanceOf('stored_file', $userfile1);
 415  
 416          $file2 = clone($file1);
 417          $file2->filename = '2.txt';
 418          $userfile2 = $fs->create_file_from_string($file2, 'file2 content longer');
 419          $this->assertInstanceOf('stored_file', $userfile2);
 420  
 421          $file3 = clone($file1);
 422          $file3->filename = '3.txt';
 423          $userfile3 = $fs->create_file_from_storedfile($file3, $userfile2);
 424          $this->assertInstanceOf('stored_file', $userfile3);
 425  
 426          $user->ctxid = $usercontext->id;
 427  
 428          return $user;
 429      }
 430  
 431      public function test_get_area_files() {
 432          $user = $this->setup_three_private_files();
 433          $fs = get_file_storage();
 434  
 435          // Get area files with default options.
 436          $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
 437  
 438          // Should be the two files we added plus the folder.
 439          $this->assertEquals(4, count($areafiles));
 440  
 441          // Verify structure.
 442          foreach ($areafiles as $key => $file) {
 443              $this->assertInstanceOf('stored_file', $file);
 444              $this->assertEquals($key, $file->get_pathnamehash());
 445          }
 446  
 447          // Get area files without a folder.
 448          $folderlessfiles = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'sortorder', false);
 449          // Should be the two files without folder.
 450          $this->assertEquals(3, count($folderlessfiles));
 451  
 452          // Verify structure.
 453          foreach ($folderlessfiles as $key => $file) {
 454              $this->assertInstanceOf('stored_file', $file);
 455              $this->assertEquals($key, $file->get_pathnamehash());
 456          }
 457  
 458          // Get area files ordered by id.
 459          $filesbyid  = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'id', false);
 460          // Should be the two files without folder.
 461          $this->assertEquals(3, count($filesbyid));
 462  
 463          // Verify structure.
 464          foreach ($filesbyid as $key => $file) {
 465              $this->assertInstanceOf('stored_file', $file);
 466              $this->assertEquals($key, $file->get_pathnamehash());
 467          }
 468  
 469          // Test with an itemid with no files.
 470          $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private', 666, 'sortorder', false);
 471          // Should be none.
 472          $this->assertEmpty($areafiles);
 473      }
 474  
 475      public function test_get_area_tree() {
 476          $user = $this->setup_three_private_files();
 477          $fs = get_file_storage();
 478  
 479          // Get area files with default options.
 480          $areatree = $fs->get_area_tree($user->ctxid, 'user', 'private', 0);
 481          $this->assertEmpty($areatree['subdirs']);
 482          $this->assertNotEmpty($areatree['files']);
 483          $this->assertCount(3, $areatree['files']);
 484  
 485          // Ensure an empty try with a fake itemid.
 486          $emptytree = $fs->get_area_tree($user->ctxid, 'user', 'private', 666);
 487          $this->assertEmpty($emptytree['subdirs']);
 488          $this->assertEmpty($emptytree['files']);
 489  
 490          // Create a subdir.
 491          $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/');
 492          $this->assertInstanceOf('stored_file', $dir);
 493  
 494          // Add a file to the subdir.
 495          $filerecord = array(
 496              'contextid' => $user->ctxid,
 497              'component' => 'user',
 498              'filearea'  => 'private',
 499              'itemid'    => 0,
 500              'filepath'  => '/testsubdir/',
 501              'filename'  => 'test-get-area-tree.txt',
 502          );
 503  
 504          $directoryfile = $fs->create_file_from_string($filerecord, 'Test content');
 505          $this->assertInstanceOf('stored_file', $directoryfile);
 506  
 507          $areatree = $fs->get_area_tree($user->ctxid, 'user', 'private', 0);
 508  
 509          // At the top level there should still be 3 files.
 510          $this->assertCount(3, $areatree['files']);
 511  
 512          // There should now be a subdirectory.
 513          $this->assertCount(1, $areatree['subdirs']);
 514  
 515          // The test subdir is named testsubdir.
 516          $subdir = $areatree['subdirs']['testsubdir'];
 517          $this->assertNotEmpty($subdir);
 518          // It should have one file we added.
 519          $this->assertCount(1, $subdir['files']);
 520          // And no subdirs itself.
 521          $this->assertCount(0, $subdir['subdirs']);
 522  
 523          // Verify the file is the one we added.
 524          $subdirfile = reset($subdir['files']);
 525          $this->assertInstanceOf('stored_file', $subdirfile);
 526          $this->assertEquals($filerecord['filename'], $subdirfile->get_filename());
 527      }
 528  
 529      public function test_get_file_by_id() {
 530          $user = $this->setup_three_private_files();
 531          $fs = get_file_storage();
 532  
 533          $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
 534  
 535          // Test get_file_by_id.
 536          $filebyid = reset($areafiles);
 537          $shouldbesame = $fs->get_file_by_id($filebyid->get_id());
 538          $this->assertEquals($filebyid->get_contenthash(), $shouldbesame->get_contenthash());
 539  
 540          // Test an id which doens't exist.
 541          $doesntexist = $fs->get_file_by_id(99999);
 542          $this->assertFalse($doesntexist);
 543      }
 544  
 545      public function test_get_file_by_hash() {
 546          $user = $this->setup_three_private_files();
 547          $fs = get_file_storage();
 548  
 549          $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
 550          // Test get_file_by_hash.
 551          $filebyhash = reset($areafiles);
 552          $shouldbesame = $fs->get_file_by_hash($filebyhash->get_pathnamehash());
 553          $this->assertEquals($filebyhash->get_id(), $shouldbesame->get_id());
 554  
 555          // Test an hash which doens't exist.
 556          $doesntexist = $fs->get_file_by_hash('DOESNTEXIST');
 557          $this->assertFalse($doesntexist);
 558      }
 559  
 560      public function test_get_external_files() {
 561          $user = $this->setup_three_private_files();
 562          $fs = get_file_storage();
 563  
 564          $repos = repository::get_instances(array('type'=>'user'));
 565          $userrepository = reset($repos);
 566          $this->assertInstanceOf('repository', $userrepository);
 567  
 568          // No aliases yet.
 569          $exfiles = $fs->get_external_files($userrepository->id, 'id');
 570          $this->assertEquals(array(), $exfiles);
 571  
 572          // Create three aliases linking the same original: $aliasfile1 and $aliasfile2 are
 573          // created via create_file_from_reference(), $aliasfile3 created from $aliasfile2.
 574          $originalfile = null;
 575          foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
 576              if (!$areafile->is_directory()) {
 577                  $originalfile = $areafile;
 578                  break;
 579              }
 580          }
 581          $this->assertInstanceOf('stored_file', $originalfile);
 582          $originalrecord = array(
 583              'contextid' => $originalfile->get_contextid(),
 584              'component' => $originalfile->get_component(),
 585              'filearea'  => $originalfile->get_filearea(),
 586              'itemid'    => $originalfile->get_itemid(),
 587              'filepath'  => $originalfile->get_filepath(),
 588              'filename'  => $originalfile->get_filename(),
 589          );
 590  
 591          $aliasrecord = $this->generate_file_record();
 592          $aliasrecord->filepath = '/foo/';
 593          $aliasrecord->filename = 'one.txt';
 594  
 595          $ref = $fs->pack_reference($originalrecord);
 596          $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $userrepository->id, $ref);
 597  
 598          $aliasrecord->filepath = '/bar/';
 599          $aliasrecord->filename = 'uno.txt';
 600          // Change the order of the items in the array to make sure that it does not matter.
 601          ksort($originalrecord);
 602          $ref = $fs->pack_reference($originalrecord);
 603          $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $userrepository->id, $ref);
 604  
 605          $aliasrecord->filepath = '/bar/';
 606          $aliasrecord->filename = 'jedna.txt';
 607          $aliasfile3 = $fs->create_file_from_storedfile($aliasrecord, $aliasfile2);
 608  
 609          // Make sure we get three aliases now.
 610          $exfiles = $fs->get_external_files($userrepository->id, 'id');
 611          $this->assertEquals(3, count($exfiles));
 612          foreach ($exfiles as $exfile) {
 613              $this->assertTrue($exfile->is_external_file());
 614          }
 615          // Make sure they all link the same original (thence that all are linked with the same
 616          // record in {files_reference}).
 617          $this->assertEquals($aliasfile1->get_referencefileid(), $aliasfile2->get_referencefileid());
 618          $this->assertEquals($aliasfile3->get_referencefileid(), $aliasfile2->get_referencefileid());
 619      }
 620  
 621      public function test_create_directory_contextid_negative() {
 622          $fs = get_file_storage();
 623  
 624          $this->setExpectedException('file_exception');
 625          $fs->create_directory(-1, 'core', 'unittest', 0, '/');
 626      }
 627  
 628      public function test_create_directory_contextid_invalid() {
 629          $fs = get_file_storage();
 630  
 631          $this->setExpectedException('file_exception');
 632          $fs->create_directory('not an int', 'core', 'unittest', 0, '/');
 633      }
 634  
 635      public function test_create_directory_component_invalid() {
 636          $fs = get_file_storage();
 637          $syscontext = context_system::instance();
 638  
 639          $this->setExpectedException('file_exception');
 640          $fs->create_directory($syscontext->id, 'bad/component', 'unittest', 0, '/');
 641      }
 642  
 643      public function test_create_directory_filearea_invalid() {
 644          $fs = get_file_storage();
 645          $syscontext = context_system::instance();
 646  
 647          $this->setExpectedException('file_exception');
 648          $fs->create_directory($syscontext->id, 'core', 'bad-filearea', 0, '/');
 649      }
 650  
 651      public function test_create_directory_itemid_negative() {
 652          $fs = get_file_storage();
 653          $syscontext = context_system::instance();
 654  
 655          $this->setExpectedException('file_exception');
 656          $fs->create_directory($syscontext->id, 'core', 'unittest', -1, '/');
 657      }
 658  
 659      public function test_create_directory_itemid_invalid() {
 660          $fs = get_file_storage();
 661          $syscontext = context_system::instance();
 662  
 663          $this->setExpectedException('file_exception');
 664          $fs->create_directory($syscontext->id, 'core', 'unittest', 'notanint', '/');
 665      }
 666  
 667      public function test_create_directory_filepath_invalid() {
 668          $fs = get_file_storage();
 669          $syscontext = context_system::instance();
 670  
 671          $this->setExpectedException('file_exception');
 672          $fs->create_directory($syscontext->id, 'core', 'unittest', 0, '/not-with-trailing/or-leading-slash');
 673      }
 674  
 675      public function test_get_directory_files() {
 676          $user = $this->setup_three_private_files();
 677          $fs = get_file_storage();
 678  
 679          $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/');
 680          $this->assertInstanceOf('stored_file', $dir);
 681  
 682          // Add a file to the subdir.
 683          $filerecord = array(
 684              'contextid' => $user->ctxid,
 685              'component' => 'user',
 686              'filearea'  => 'private',
 687              'itemid'    => 0,
 688              'filepath'  => '/testsubdir/',
 689              'filename'  => 'test-get-area-tree.txt',
 690          );
 691  
 692          $directoryfile = $fs->create_file_from_string($filerecord, 'Test content');
 693          $this->assertInstanceOf('stored_file', $directoryfile);
 694  
 695          // Don't recurse without dirs.
 696          $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, false, 'id');
 697          // 3 files only.
 698          $this->assertCount(3, $files);
 699          foreach ($files as $key => $file) {
 700              $this->assertInstanceOf('stored_file', $file);
 701              $this->assertEquals($key, $file->get_pathnamehash());
 702          }
 703  
 704          // Don't recurse with dirs.
 705          $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, true, 'id');
 706          // 3 files + 1 directory.
 707          $this->assertCount(4, $files);
 708          foreach ($files as $key => $file) {
 709              $this->assertInstanceOf('stored_file', $file);
 710              $this->assertEquals($key, $file->get_pathnamehash());
 711          }
 712  
 713          // Recurse with dirs.
 714          $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, true, 'id');
 715          // 3 files + 1 directory +  1 subdir file.
 716          $this->assertCount(5, $files);
 717          foreach ($files as $key => $file) {
 718              $this->assertInstanceOf('stored_file', $file);
 719              $this->assertEquals($key, $file->get_pathnamehash());
 720          }
 721  
 722          // Recurse without dirs.
 723          $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, false, 'id');
 724          // 3 files +  1 subdir file.
 725          $this->assertCount(4, $files);
 726          foreach ($files as $key => $file) {
 727              $this->assertInstanceOf('stored_file', $file);
 728              $this->assertEquals($key, $file->get_pathnamehash());
 729          }
 730      }
 731  
 732      public function test_search_references() {
 733          $user = $this->setup_three_private_files();
 734          $fs = get_file_storage();
 735          $repos = repository::get_instances(array('type'=>'user'));
 736          $repo = reset($repos);
 737  
 738          $alias1 = array(
 739              'contextid' => $user->ctxid,
 740              'component' => 'user',
 741              'filearea'  => 'private',
 742              'itemid'    => 0,
 743              'filepath'  => '/aliases/',
 744              'filename'  => 'alias-to-1.txt'
 745          );
 746  
 747          $alias2 = array(
 748              'contextid' => $user->ctxid,
 749              'component' => 'user',
 750              'filearea'  => 'private',
 751              'itemid'    => 0,
 752              'filepath'  => '/aliases/',
 753              'filename'  => 'another-alias-to-1.txt'
 754          );
 755  
 756          $reference = file_storage::pack_reference(array(
 757              'contextid' => $user->ctxid,
 758              'component' => 'user',
 759              'filearea'  => 'private',
 760              'itemid'    => 0,
 761              'filepath'  => '/',
 762              'filename'  => '1.txt'
 763          ));
 764  
 765          // There are no aliases now.
 766          $result = $fs->search_references($reference);
 767          $this->assertEquals(array(), $result);
 768  
 769          $result = $fs->search_references_count($reference);
 770          $this->assertSame($result, 0);
 771  
 772          // Create two aliases and make sure they are returned.
 773          $fs->create_file_from_reference($alias1, $repo->id, $reference);
 774          $fs->create_file_from_reference($alias2, $repo->id, $reference);
 775  
 776          $result = $fs->search_references($reference);
 777          $this->assertTrue(is_array($result));
 778          $this->assertEquals(count($result), 2);
 779          foreach ($result as $alias) {
 780              $this->assertTrue($alias instanceof stored_file);
 781          }
 782  
 783          $result = $fs->search_references_count($reference);
 784          $this->assertSame($result, 2);
 785  
 786          // The method can't be used for references to files outside the filepool.
 787          $exceptionthrown = false;
 788          try {
 789              $fs->search_references('http://dl.dropbox.com/download/1234567/naked-dougiamas.jpg');
 790          } catch (file_reference_exception $e) {
 791              $exceptionthrown = true;
 792          }
 793          $this->assertTrue($exceptionthrown);
 794  
 795          $exceptionthrown = false;
 796          try {
 797              $fs->search_references_count('http://dl.dropbox.com/download/1234567/naked-dougiamas.jpg');
 798          } catch (file_reference_exception $e) {
 799              $exceptionthrown = true;
 800          }
 801          $this->assertTrue($exceptionthrown);
 802      }
 803  
 804      public function test_delete_area_files() {
 805          $user = $this->setup_three_private_files();
 806          $fs = get_file_storage();
 807  
 808          // Get area files with default options.
 809          $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
 810          // Should be the two files we added plus the folder.
 811          $this->assertEquals(4, count($areafiles));
 812          $fs->delete_area_files($user->ctxid, 'user', 'private');
 813  
 814          $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
 815          // Should be the two files we added plus the folder.
 816          $this->assertEquals(0, count($areafiles));
 817      }
 818  
 819      public function test_delete_area_files_itemid() {
 820          $user = $this->setup_three_private_files();
 821          $fs = get_file_storage();
 822  
 823          // Get area files with default options.
 824          $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
 825          // Should be the two files we added plus the folder.
 826          $this->assertEquals(4, count($areafiles));
 827          $fs->delete_area_files($user->ctxid, 'user', 'private', 9999);
 828  
 829          $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
 830          $this->assertEquals(4, count($areafiles));
 831      }
 832  
 833      public function test_delete_area_files_select() {
 834          $user = $this->setup_three_private_files();
 835          $fs = get_file_storage();
 836  
 837          // Get area files with default options.
 838          $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
 839          // Should be the two files we added plus the folder.
 840          $this->assertEquals(4, count($areafiles));
 841          $fs->delete_area_files_select($user->ctxid, 'user', 'private', '!= :notitemid', array('notitemid'=>9999));
 842  
 843          $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
 844          // Should be the two files we added plus the folder.
 845          $this->assertEquals(0, count($areafiles));
 846      }
 847  
 848      public function test_delete_component_files() {
 849          $user = $this->setup_three_private_files();
 850          $fs = get_file_storage();
 851  
 852          $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
 853          $this->assertEquals(4, count($areafiles));
 854          $fs->delete_component_files('user');
 855          $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private');
 856          $this->assertEquals(0, count($areafiles));
 857      }
 858  
 859      public function test_create_file_from_url() {
 860          $this->resetAfterTest(true);
 861  
 862          $syscontext = context_system::instance();
 863          $filerecord = array(
 864              'contextid' => $syscontext->id,
 865              'component' => 'core',
 866              'filearea'  => 'unittest',
 867              'itemid'    => 0,
 868              'filepath'  => '/downloadtest/',
 869          );
 870          $url = $this->getExternalTestFileUrl('/test.html');
 871  
 872          $fs = get_file_storage();
 873  
 874          // Test creating file without filename.
 875          $file1 = $fs->create_file_from_url($filerecord, $url);
 876          $this->assertInstanceOf('stored_file', $file1);
 877  
 878          // Set filename.
 879          $filerecord['filename'] = 'unit-test-filename.html';
 880          $file2 = $fs->create_file_from_url($filerecord, $url);
 881          $this->assertInstanceOf('stored_file', $file2);
 882  
 883          // Use temporary file.
 884          $filerecord['filename'] = 'unit-test-with-temp-file.html';
 885          $file3 = $fs->create_file_from_url($filerecord, $url, null, true);
 886          $file3 = $this->assertInstanceOf('stored_file', $file3);
 887      }
 888  
 889      public function test_cron() {
 890          $this->resetAfterTest(true);
 891  
 892          // Note: this is only testing DB compatibility atm, rather than
 893          // that work is done.
 894          $fs = get_file_storage();
 895  
 896          $this->expectOutputRegex('/Cleaning up/');
 897          $fs->cron();
 898      }
 899  
 900      public function test_is_area_empty() {
 901          $user = $this->setup_three_private_files();
 902          $fs = get_file_storage();
 903  
 904          $this->assertFalse($fs->is_area_empty($user->ctxid, 'user', 'private'));
 905  
 906          // File area with madeup itemid should be empty.
 907          $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999));
 908          // Still empty with dirs included.
 909          $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999, false));
 910      }
 911  
 912      public function test_move_area_files_to_new_context() {
 913          $this->resetAfterTest(true);
 914  
 915          // Create a course with a page resource.
 916          $course = $this->getDataGenerator()->create_course();
 917          $page1 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
 918          $page1context = context_module::instance($page1->cmid);
 919  
 920          // Add a file to the page.
 921          $fs = get_file_storage();
 922          $filerecord = array(
 923              'contextid' => $page1context->id,
 924              'component' => 'mod_page',
 925              'filearea'  => 'content',
 926              'itemid'    => 0,
 927              'filepath'  => '/',
 928              'filename'  => 'unit-test-file.txt',
 929          );
 930  
 931          $originalfile = $fs->create_file_from_string($filerecord, 'Test content');
 932          $this->assertInstanceOf('stored_file', $originalfile);
 933  
 934          $pagefiles = $fs->get_area_files($page1context->id, 'mod_page', 'content', 0, 'sortorder', false);
 935          // Should be one file in filearea.
 936          $this->assertFalse($fs->is_area_empty($page1context->id, 'mod_page', 'content'));
 937  
 938          // Create a new page.
 939          $page2 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
 940          $page2context = context_module::instance($page2->cmid);
 941  
 942          // Newly created page area is empty.
 943          $this->assertTrue($fs->is_area_empty($page2context->id, 'mod_page', 'content'));
 944  
 945          // Move the files.
 946          $fs->move_area_files_to_new_context($page1context->id, $page2context->id, 'mod_page', 'content');
 947  
 948          // Page2 filearea should no longer be empty.
 949          $this->assertFalse($fs->is_area_empty($page2context->id, 'mod_page', 'content'));
 950  
 951          // Page1 filearea should now be empty.
 952          $this->assertTrue($fs->is_area_empty($page1context->id, 'mod_page', 'content'));
 953  
 954          $page2files = $fs->get_area_files($page2context->id, 'mod_page', 'content', 0, 'sortorder', false);
 955          $movedfile = reset($page2files);
 956  
 957          // The two files should have the same content hash.
 958          $this->assertEquals($movedfile->get_contenthash(), $originalfile->get_contenthash());
 959      }
 960  
 961      public function test_convert_image() {
 962          global $CFG;
 963  
 964          $this->resetAfterTest(false);
 965  
 966          $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
 967          $syscontext = context_system::instance();
 968          $filerecord = array(
 969              'contextid' => $syscontext->id,
 970              'component' => 'core',
 971              'filearea'  => 'unittest',
 972              'itemid'    => 0,
 973              'filepath'  => '/images/',
 974              'filename'  => 'testimage.jpg',
 975          );
 976  
 977          $fs = get_file_storage();
 978          $original = $fs->create_file_from_pathname($filerecord, $filepath);
 979  
 980          $filerecord['filename'] = 'testimage-converted-10x10.jpg';
 981          $converted = $fs->convert_image($filerecord, $original, 10, 10, true, 100);
 982          $this->assertInstanceOf('stored_file', $converted);
 983  
 984          $filerecord['filename'] = 'testimage-convereted-nosize.jpg';
 985          $converted = $fs->convert_image($filerecord, $original);
 986          $this->assertInstanceOf('stored_file', $converted);
 987      }
 988  
 989      private function generate_file_record() {
 990          $syscontext = context_system::instance();
 991          $filerecord = new stdClass();
 992          $filerecord->contextid = $syscontext->id;
 993          $filerecord->component = 'core';
 994          $filerecord->filearea = 'phpunit';
 995          $filerecord->filepath = '/';
 996          $filerecord->filename = 'testfile.txt';
 997          $filerecord->itemid = 0;
 998  
 999          return $filerecord;
1000      }
1001  
1002      public function test_create_file_from_storedfile_file_invalid() {
1003          $this->resetAfterTest(true);
1004  
1005          $filerecord = $this->generate_file_record();
1006  
1007          $fs = get_file_storage();
1008          $this->setExpectedException('file_exception');
1009          // Create a file from a file id which doesn't exist.
1010          $fs->create_file_from_storedfile($filerecord,  9999);
1011      }
1012  
1013      public function test_create_file_from_storedfile_contextid_invalid() {
1014          $this->resetAfterTest(true);
1015  
1016          $filerecord = $this->generate_file_record();
1017  
1018          $fs = get_file_storage();
1019          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1020          $this->assertInstanceOf('stored_file', $file1);
1021  
1022          $filerecord->filename = 'invalid.txt';
1023          $filerecord->contextid = 'invalid';
1024  
1025          $this->setExpectedException('file_exception', 'Invalid contextid');
1026          $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1027      }
1028  
1029      public function test_create_file_from_storedfile_component_invalid() {
1030          $this->resetAfterTest(true);
1031  
1032          $filerecord = $this->generate_file_record();
1033  
1034          $fs = get_file_storage();
1035          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1036          $this->assertInstanceOf('stored_file', $file1);
1037  
1038          $filerecord->filename = 'invalid.txt';
1039          $filerecord->component = 'bad/component';
1040  
1041          $this->setExpectedException('file_exception', 'Invalid component');
1042          $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1043      }
1044  
1045      public function test_create_file_from_storedfile_filearea_invalid() {
1046          $this->resetAfterTest(true);
1047  
1048          $filerecord = $this->generate_file_record();
1049  
1050          $fs = get_file_storage();
1051          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1052          $this->assertInstanceOf('stored_file', $file1);
1053  
1054          $filerecord->filename = 'invalid.txt';
1055          $filerecord->filearea = 'bad-filearea';
1056  
1057          $this->setExpectedException('file_exception', 'Invalid filearea');
1058          $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1059      }
1060  
1061      public function test_create_file_from_storedfile_itemid_invalid() {
1062          $this->resetAfterTest(true);
1063  
1064          $filerecord = $this->generate_file_record();
1065  
1066          $fs = get_file_storage();
1067          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1068          $this->assertInstanceOf('stored_file', $file1);
1069  
1070          $filerecord->filename = 'invalid.txt';
1071          $filerecord->itemid = 'bad-itemid';
1072  
1073          $this->setExpectedException('file_exception', 'Invalid itemid');
1074          $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1075      }
1076  
1077      public function test_create_file_from_storedfile_filepath_invalid() {
1078          $this->resetAfterTest(true);
1079  
1080          $filerecord = $this->generate_file_record();
1081  
1082          $fs = get_file_storage();
1083          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1084          $this->assertInstanceOf('stored_file', $file1);
1085  
1086          $filerecord->filename = 'invalid.txt';
1087          $filerecord->filepath = 'a-/bad/-filepath';
1088  
1089          $this->setExpectedException('file_exception', 'Invalid file path');
1090          $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1091      }
1092  
1093      public function test_create_file_from_storedfile_filename_invalid() {
1094          $this->resetAfterTest(true);
1095  
1096          $filerecord = $this->generate_file_record();
1097  
1098          $fs = get_file_storage();
1099          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1100          $this->assertInstanceOf('stored_file', $file1);
1101  
1102          $filerecord->filename = '';
1103  
1104          $this->setExpectedException('file_exception', 'Invalid file name');
1105          $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1106      }
1107  
1108      public function test_create_file_from_storedfile_timecreated_invalid() {
1109          $this->resetAfterTest(true);
1110  
1111          $filerecord = $this->generate_file_record();
1112  
1113          $fs = get_file_storage();
1114          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1115          $this->assertInstanceOf('stored_file', $file1);
1116  
1117          $filerecord->filename = 'invalid.txt';
1118          $filerecord->timecreated = 'today';
1119  
1120          $this->setExpectedException('file_exception', 'Invalid file timecreated');
1121          $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1122      }
1123  
1124      public function test_create_file_from_storedfile_timemodified_invalid() {
1125          $this->resetAfterTest(true);
1126  
1127          $filerecord = $this->generate_file_record();
1128  
1129          $fs = get_file_storage();
1130          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1131          $this->assertInstanceOf('stored_file', $file1);
1132  
1133          $filerecord->filename = 'invalid.txt';
1134          $filerecord->timemodified  = 'today';
1135  
1136          $this->setExpectedException('file_exception', 'Invalid file timemodified');
1137          $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1138      }
1139  
1140      public function test_create_file_from_storedfile_duplicate() {
1141          $this->resetAfterTest(true);
1142  
1143          $filerecord = $this->generate_file_record();
1144  
1145          $fs = get_file_storage();
1146          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1147          $this->assertInstanceOf('stored_file', $file1);
1148  
1149          // Creating a file validating unique constraint.
1150          $this->setExpectedException('stored_file_creation_exception', 'Can not create file "1/core/phpunit/0/testfile.txt"');
1151          $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1152      }
1153  
1154      public function test_create_file_from_storedfile() {
1155          $this->resetAfterTest(true);
1156  
1157          $syscontext = context_system::instance();
1158  
1159          $filerecord = new stdClass();
1160          $filerecord->contextid = $syscontext->id;
1161          $filerecord->component = 'core';
1162          $filerecord->filearea = 'phpunit';
1163          $filerecord->filepath = '/';
1164          $filerecord->filename = 'testfile.txt';
1165          $filerecord->itemid = 0;
1166  
1167          $fs = get_file_storage();
1168  
1169          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1170          $this->assertInstanceOf('stored_file', $file1);
1171  
1172          $filerecord->filename = 'test-create-file-from-storedfile.txt';
1173          $file2 = $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1174          $this->assertInstanceOf('stored_file', $file2);
1175  
1176          // These will be normalised to current time..
1177          $filerecord->timecreated = -100;
1178          $filerecord->timemodified= -100;
1179          $filerecord->filename = 'test-create-file-from-storedfile-bad-dates.txt';
1180  
1181          $file3 = $fs->create_file_from_storedfile($filerecord, $file1->get_id());
1182          $this->assertInstanceOf('stored_file', $file3);
1183  
1184          $this->assertNotEquals($file3->get_timemodified(), $filerecord->timemodified);
1185          $this->assertNotEquals($file3->get_timecreated(), $filerecord->timecreated);
1186      }
1187  
1188      public function test_create_file_from_string_contextid_invalid() {
1189          $this->resetAfterTest(true);
1190  
1191          $filerecord = $this->generate_file_record();
1192          $fs = get_file_storage();
1193  
1194          $filerecord->contextid = 'invalid';
1195  
1196          $this->setExpectedException('file_exception', 'Invalid contextid');
1197          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1198      }
1199  
1200      public function test_create_file_from_string_component_invalid() {
1201          $this->resetAfterTest(true);
1202  
1203          $filerecord = $this->generate_file_record();
1204          $fs = get_file_storage();
1205  
1206          $filerecord->component = 'bad/component';
1207  
1208          $this->setExpectedException('file_exception', 'Invalid component');
1209          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1210      }
1211  
1212      public function test_create_file_from_string_filearea_invalid() {
1213          $this->resetAfterTest(true);
1214  
1215          $filerecord = $this->generate_file_record();
1216          $fs = get_file_storage();
1217  
1218          $filerecord->filearea = 'bad-filearea';
1219  
1220          $this->setExpectedException('file_exception', 'Invalid filearea');
1221          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1222      }
1223  
1224      public function test_create_file_from_string_itemid_invalid() {
1225          $this->resetAfterTest(true);
1226  
1227          $filerecord = $this->generate_file_record();
1228          $fs = get_file_storage();
1229  
1230          $filerecord->itemid = 'bad-itemid';
1231  
1232          $this->setExpectedException('file_exception', 'Invalid itemid');
1233          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1234      }
1235  
1236      public function test_create_file_from_string_filepath_invalid() {
1237          $this->resetAfterTest(true);
1238  
1239          $filerecord = $this->generate_file_record();
1240          $fs = get_file_storage();
1241  
1242          $filerecord->filepath = 'a-/bad/-filepath';
1243  
1244          $this->setExpectedException('file_exception', 'Invalid file path');
1245          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1246      }
1247  
1248      public function test_create_file_from_string_filename_invalid() {
1249          $this->resetAfterTest(true);
1250  
1251          $filerecord = $this->generate_file_record();
1252          $fs = get_file_storage();
1253  
1254          $filerecord->filename = '';
1255  
1256          $this->setExpectedException('file_exception', 'Invalid file name');
1257          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1258      }
1259  
1260      public function test_create_file_from_string_timecreated_invalid() {
1261          $this->resetAfterTest(true);
1262  
1263          $filerecord = $this->generate_file_record();
1264          $fs = get_file_storage();
1265  
1266          $filerecord->timecreated = 'today';
1267  
1268          $this->setExpectedException('file_exception', 'Invalid file timecreated');
1269          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1270      }
1271  
1272      public function test_create_file_from_string_timemodified_invalid() {
1273          $this->resetAfterTest(true);
1274  
1275          $filerecord = $this->generate_file_record();
1276          $fs = get_file_storage();
1277  
1278          $filerecord->timemodified  = 'today';
1279  
1280          $this->setExpectedException('file_exception', 'Invalid file timemodified');
1281          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1282      }
1283  
1284      public function test_create_file_from_string_duplicate() {
1285          $this->resetAfterTest(true);
1286  
1287          $filerecord = $this->generate_file_record();
1288          $fs = get_file_storage();
1289  
1290          $file1 = $fs->create_file_from_string($filerecord, 'text contents');
1291  
1292          // Creating a file validating unique constraint.
1293          $this->setExpectedException('stored_file_creation_exception');
1294          $file2 = $fs->create_file_from_string($filerecord, 'text contents');
1295      }
1296  
1297      public function test_create_file_from_pathname_contextid_invalid() {
1298          global $CFG;
1299          $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1300  
1301          $this->resetAfterTest(true);
1302  
1303          $filerecord = $this->generate_file_record();
1304          $fs = get_file_storage();
1305  
1306          $filerecord->contextid = 'invalid';
1307  
1308          $this->setExpectedException('file_exception', 'Invalid contextid');
1309          $file1 = $fs->create_file_from_pathname($filerecord, $path);
1310      }
1311  
1312      public function test_create_file_from_pathname_component_invalid() {
1313          global $CFG;
1314          $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1315  
1316          $this->resetAfterTest(true);
1317  
1318          $filerecord = $this->generate_file_record();
1319          $fs = get_file_storage();
1320  
1321          $filerecord->component = 'bad/component';
1322  
1323          $this->setExpectedException('file_exception', 'Invalid component');
1324          $file1 = $fs->create_file_from_pathname($filerecord, $path);
1325      }
1326  
1327      public function test_create_file_from_pathname_filearea_invalid() {
1328          global $CFG;
1329          $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1330  
1331          $this->resetAfterTest(true);
1332  
1333          $filerecord = $this->generate_file_record();
1334          $fs = get_file_storage();
1335  
1336          $filerecord->filearea = 'bad-filearea';
1337  
1338          $this->setExpectedException('file_exception', 'Invalid filearea');
1339          $file1 = $fs->create_file_from_pathname($filerecord, $path);
1340      }
1341  
1342      public function test_create_file_from_pathname_itemid_invalid() {
1343          global $CFG;
1344          $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1345  
1346          $this->resetAfterTest(true);
1347  
1348          $filerecord = $this->generate_file_record();
1349          $fs = get_file_storage();
1350  
1351          $filerecord->itemid = 'bad-itemid';
1352  
1353          $this->setExpectedException('file_exception', 'Invalid itemid');
1354          $file1 = $fs->create_file_from_pathname($filerecord, $path);
1355      }
1356  
1357      public function test_create_file_from_pathname_filepath_invalid() {
1358          global $CFG;
1359          $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1360  
1361          $this->resetAfterTest(true);
1362  
1363          $filerecord = $this->generate_file_record();
1364          $fs = get_file_storage();
1365  
1366          $filerecord->filepath = 'a-/bad/-filepath';
1367  
1368          $this->setExpectedException('file_exception', 'Invalid file path');
1369          $file1 = $fs->create_file_from_pathname($filerecord, $path);
1370      }
1371  
1372      public function test_create_file_from_pathname_filename_invalid() {
1373          global $CFG;
1374          $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1375  
1376          $this->resetAfterTest(true);
1377  
1378          $filerecord = $this->generate_file_record();
1379          $fs = get_file_storage();
1380  
1381          $filerecord->filename = '';
1382  
1383          $this->setExpectedException('file_exception', 'Invalid file name');
1384          $file1 = $fs->create_file_from_pathname($filerecord, $path);
1385      }
1386  
1387      public function test_create_file_from_pathname_timecreated_invalid() {
1388          global $CFG;
1389          $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1390  
1391          $this->resetAfterTest(true);
1392  
1393          $filerecord = $this->generate_file_record();
1394          $fs = get_file_storage();
1395  
1396          $filerecord->timecreated = 'today';
1397  
1398          $this->setExpectedException('file_exception', 'Invalid file timecreated');
1399          $file1 = $fs->create_file_from_pathname($filerecord, $path);
1400      }
1401  
1402      public function test_create_file_from_pathname_timemodified_invalid() {
1403          global $CFG;
1404          $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1405  
1406          $this->resetAfterTest(true);
1407  
1408          $filerecord = $this->generate_file_record();
1409          $fs = get_file_storage();
1410  
1411          $filerecord->timemodified  = 'today';
1412  
1413          $this->setExpectedException('file_exception', 'Invalid file timemodified');
1414          $file1 = $fs->create_file_from_pathname($filerecord, $path);
1415      }
1416  
1417      public function test_create_file_from_pathname_duplicate_file() {
1418          global $CFG;
1419          $this->resetAfterTest(true);
1420  
1421          $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
1422  
1423          $filerecord = $this->generate_file_record();
1424          $fs = get_file_storage();
1425  
1426          $file1 = $fs->create_file_from_pathname($filerecord, $path);
1427          $this->assertInstanceOf('stored_file', $file1);
1428  
1429          // Creating a file validating unique constraint.
1430          $this->setExpectedException('stored_file_creation_exception', 'Can not create file "1/core/phpunit/0/testfile.txt"');
1431          $file2 = $fs->create_file_from_pathname($filerecord, $path);
1432      }
1433  
1434      /**
1435       * Calling stored_file::delete_reference() on a non-reference file throws coding_exception
1436       */
1437      public function test_delete_reference_on_nonreference() {
1438  
1439          $this->resetAfterTest(true);
1440          $user = $this->setup_three_private_files();
1441          $fs = get_file_storage();
1442          $repos = repository::get_instances(array('type'=>'user'));
1443          $repo = reset($repos);
1444  
1445          $file = null;
1446          foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
1447              if (!$areafile->is_directory()) {
1448                  $file = $areafile;
1449                  break;
1450              }
1451          }
1452          $this->assertInstanceOf('stored_file', $file);
1453          $this->assertFalse($file->is_external_file());
1454  
1455          $this->setExpectedException('coding_exception');
1456          $file->delete_reference();
1457      }
1458  
1459      /**
1460       * Calling stored_file::delete_reference() on a reference file does not affect other
1461       * symlinks to the same original
1462       */
1463      public function test_delete_reference_one_symlink_does_not_rule_them_all() {
1464  
1465          $this->resetAfterTest(true);
1466          $user = $this->setup_three_private_files();
1467          $fs = get_file_storage();
1468          $repos = repository::get_instances(array('type'=>'user'));
1469          $repo = reset($repos);
1470  
1471          // Create two aliases linking the same original.
1472  
1473          $originalfile = null;
1474          foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) {
1475              if (!$areafile->is_directory()) {
1476                  $originalfile = $areafile;
1477                  break;
1478              }
1479          }
1480          $this->assertInstanceOf('stored_file', $originalfile);
1481  
1482          // Calling delete_reference() on a non-reference file.
1483  
1484          $originalrecord = array(
1485              'contextid' => $originalfile->get_contextid(),
1486              'component' => $originalfile->get_component(),
1487              'filearea'  => $originalfile->get_filearea(),
1488              'itemid'    => $originalfile->get_itemid(),
1489              'filepath'  => $originalfile->get_filepath(),
1490              'filename'  => $originalfile->get_filename(),
1491          );
1492  
1493          $aliasrecord = $this->generate_file_record();
1494          $aliasrecord->filepath = '/A/';
1495          $aliasrecord->filename = 'symlink.txt';
1496  
1497          $ref = $fs->pack_reference($originalrecord);
1498          $aliasfile1 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref);
1499  
1500          $aliasrecord->filepath = '/B/';
1501          $aliasrecord->filename = 'symlink.txt';
1502          $ref = $fs->pack_reference($originalrecord);
1503          $aliasfile2 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref);
1504  
1505          // Refetch A/symlink.txt file.
1506          $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1507              $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt');
1508          $this->assertTrue($symlink1->is_external_file());
1509  
1510          // Unlink the A/symlink.txt file.
1511          $symlink1->delete_reference();
1512          $this->assertFalse($symlink1->is_external_file());
1513  
1514          // Make sure that B/symlink.txt has not been affected.
1515          $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1516              $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt');
1517          $this->assertTrue($symlink2->is_external_file());
1518      }
1519  
1520      /**
1521       * Make sure that when internal file is updated all references to it are
1522       * updated immediately. When it is deleted, the references are converted
1523       * to true copies.
1524       */
1525      public function test_update_reference_internal() {
1526          purge_all_caches();
1527          $this->resetAfterTest(true);
1528          $user = $this->setup_three_private_files();
1529          $fs = get_file_storage();
1530          $repos = repository::get_instances(array('type' => 'user'));
1531          $repo = reset($repos);
1532  
1533          // Create two aliases linking the same original.
1534  
1535          $areafiles = array_values($fs->get_area_files($user->ctxid, 'user', 'private', false, 'filename', false));
1536  
1537          $originalfile = $areafiles[0];
1538          $this->assertInstanceOf('stored_file', $originalfile);
1539          $contenthash = $originalfile->get_contenthash();
1540          $filesize = $originalfile->get_filesize();
1541  
1542          $substitutefile = $areafiles[1];
1543          $this->assertInstanceOf('stored_file', $substitutefile);
1544          $newcontenthash = $substitutefile->get_contenthash();
1545          $newfilesize = $substitutefile->get_filesize();
1546  
1547          $originalrecord = array(
1548              'contextid' => $originalfile->get_contextid(),
1549              'component' => $originalfile->get_component(),
1550              'filearea'  => $originalfile->get_filearea(),
1551              'itemid'    => $originalfile->get_itemid(),
1552              'filepath'  => $originalfile->get_filepath(),
1553              'filename'  => $originalfile->get_filename(),
1554          );
1555  
1556          $aliasrecord = $this->generate_file_record();
1557          $aliasrecord->filepath = '/A/';
1558          $aliasrecord->filename = 'symlink.txt';
1559  
1560          $ref = $fs->pack_reference($originalrecord);
1561          $symlink1 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref);
1562          // Make sure created alias is a reference and has the same size and contenthash as source.
1563          $this->assertEquals($contenthash, $symlink1->get_contenthash());
1564          $this->assertEquals($filesize, $symlink1->get_filesize());
1565          $this->assertEquals($repo->id, $symlink1->get_repository_id());
1566          $this->assertNotEmpty($symlink1->get_referencefileid());
1567          $referenceid = $symlink1->get_referencefileid();
1568  
1569          $aliasrecord->filepath = '/B/';
1570          $aliasrecord->filename = 'symlink.txt';
1571          $ref = $fs->pack_reference($originalrecord);
1572          $symlink2 = $fs->create_file_from_reference($aliasrecord, $repo->id, $ref);
1573          // Make sure created alias is a reference and has the same size and contenthash as source.
1574          $this->assertEquals($contenthash, $symlink2->get_contenthash());
1575          $this->assertEquals($filesize, $symlink2->get_filesize());
1576          $this->assertEquals($repo->id, $symlink2->get_repository_id());
1577          // Make sure both aliases have the same reference id.
1578          $this->assertEquals($referenceid, $symlink2->get_referencefileid());
1579  
1580          // Overwrite ofiginal file.
1581          $originalfile->replace_file_with($substitutefile);
1582          $this->assertEquals($newcontenthash, $originalfile->get_contenthash());
1583          $this->assertEquals($newfilesize, $originalfile->get_filesize());
1584  
1585          // References to the internal files must be synchronised immediately.
1586          // Refetch A/symlink.txt file.
1587          $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1588              $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt');
1589          $this->assertTrue($symlink1->is_external_file());
1590          $this->assertEquals($newcontenthash, $symlink1->get_contenthash());
1591          $this->assertEquals($newfilesize, $symlink1->get_filesize());
1592          $this->assertEquals($repo->id, $symlink1->get_repository_id());
1593          $this->assertEquals($referenceid, $symlink1->get_referencefileid());
1594  
1595          // Refetch B/symlink.txt file.
1596          $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1597              $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt');
1598          $this->assertTrue($symlink2->is_external_file());
1599          $this->assertEquals($newcontenthash, $symlink2->get_contenthash());
1600          $this->assertEquals($newfilesize, $symlink2->get_filesize());
1601          $this->assertEquals($repo->id, $symlink2->get_repository_id());
1602          $this->assertEquals($referenceid, $symlink2->get_referencefileid());
1603  
1604          // Remove original file.
1605          $originalfile->delete();
1606  
1607          // References must be converted to independend files.
1608          // Refetch A/symlink.txt file.
1609          $symlink1 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1610              $aliasrecord->filearea, $aliasrecord->itemid, '/A/', 'symlink.txt');
1611          $this->assertFalse($symlink1->is_external_file());
1612          $this->assertEquals($newcontenthash, $symlink1->get_contenthash());
1613          $this->assertEquals($newfilesize, $symlink1->get_filesize());
1614          $this->assertNull($symlink1->get_repository_id());
1615          $this->assertNull($symlink1->get_referencefileid());
1616  
1617          // Refetch B/symlink.txt file.
1618          $symlink2 = $fs->get_file($aliasrecord->contextid, $aliasrecord->component,
1619              $aliasrecord->filearea, $aliasrecord->itemid, '/B/', 'symlink.txt');
1620          $this->assertFalse($symlink2->is_external_file());
1621          $this->assertEquals($newcontenthash, $symlink2->get_contenthash());
1622          $this->assertEquals($newfilesize, $symlink2->get_filesize());
1623          $this->assertNull($symlink2->get_repository_id());
1624          $this->assertNull($symlink2->get_referencefileid());
1625      }
1626  
1627      public function test_get_unused_filename() {
1628          global $USER;
1629          $this->resetAfterTest(true);
1630  
1631          $fs = get_file_storage();
1632          $this->setAdminUser();
1633          $contextid = context_user::instance($USER->id)->id;
1634          $component = 'user';
1635          $filearea = 'private';
1636          $itemid = 0;
1637          $filepath = '/';
1638  
1639          // Create some private files.
1640          $file = new stdClass;
1641          $file->contextid = $contextid;
1642          $file->component = 'user';
1643          $file->filearea  = 'private';
1644          $file->itemid    = 0;
1645          $file->filepath  = '/';
1646          $file->source    = 'test';
1647          $filenames = array('foo.txt', 'foo (1).txt', 'foo (20).txt', 'foo (999)', 'bar.jpg', 'What (a cool file).jpg',
1648                  'Hurray! (1).php', 'Hurray! (2).php', 'Hurray! (9a).php', 'Hurray! (abc).php');
1649          foreach ($filenames as $key => $filename) {
1650              $file->filename = $filename;
1651              $userfile = $fs->create_file_from_string($file, "file $key $filename content");
1652              $this->assertInstanceOf('stored_file', $userfile);
1653          }
1654  
1655          // Asserting new generated names.
1656          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'unused.txt');
1657          $this->assertEquals('unused.txt', $newfilename);
1658          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo.txt');
1659          $this->assertEquals('foo (21).txt', $newfilename);
1660          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (1).txt');
1661          $this->assertEquals('foo (21).txt', $newfilename);
1662          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (2).txt');
1663          $this->assertEquals('foo (2).txt', $newfilename);
1664          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (20).txt');
1665          $this->assertEquals('foo (21).txt', $newfilename);
1666          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo');
1667          $this->assertEquals('foo', $newfilename);
1668          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (123)');
1669          $this->assertEquals('foo (123)', $newfilename);
1670          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'foo (999)');
1671          $this->assertEquals('foo (1000)', $newfilename);
1672          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.png');
1673          $this->assertEquals('bar.png', $newfilename);
1674          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (12).png');
1675          $this->assertEquals('bar (12).png', $newfilename);
1676          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar.jpg');
1677          $this->assertEquals('bar (1).jpg', $newfilename);
1678          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'bar (1).jpg');
1679          $this->assertEquals('bar (1).jpg', $newfilename);
1680          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'What (a cool file).jpg');
1681          $this->assertEquals('What (a cool file) (1).jpg', $newfilename);
1682          $newfilename = $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, 'Hurray! (1).php');
1683          $this->assertEquals('Hurray! (3).php', $newfilename);
1684  
1685          $this->setExpectedException('coding_exception');
1686          $fs->get_unused_filename($contextid, $component, $filearea, $itemid, $filepath, '');
1687      }
1688  }
1689  
1690  class test_stored_file_inspection extends stored_file {
1691      public static function get_pretected_pathname(stored_file $file) {
1692          return $file->get_pathname_by_contenthash();
1693      }
1694  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1