MDL-63710 repository: Delete orphaned file records.
authorIlya Tregubov <ilyatregubov@catalyst-au.net>
Tue, 20 Nov 2018 00:31:27 +0000 (11:31 +1100)
committerIlya Tregubov <ilyatregubov@catalyst-au.net>
Thu, 6 Dec 2018 01:39:31 +0000 (12:39 +1100)
lib/db/upgrade.php
lib/db/upgradelib.php
lib/tests/upgradelib_test.php
version.php

index a89e7a7..35cf1da 100644 (file)
@@ -2884,5 +2884,10 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2018120300.02);
     }
 
+    if ($oldversion < 2018120301.02) {
+        upgrade_delete_orphaned_file_records();
+        upgrade_main_savepoint(true, 2018120301.02);
+    }
+
     return true;
 }
index fa7dcf7..e7e162f 100644 (file)
@@ -539,3 +539,30 @@ function upgrade_fix_serialized_objects($serializeddata) {
     }
     return [$updated, $serializeddata];
 }
+
+/**
+ * Deletes file records which have their repository deleted.
+ *
+ */
+function upgrade_delete_orphaned_file_records() {
+    global $DB;
+
+    $sql = "SELECT f.id, f.contextid, f.component, f.filearea, f.itemid, fr.id AS referencefileid
+              FROM {files} f
+              JOIN {files_reference} fr ON f.referencefileid = fr.id
+         LEFT JOIN {repository_instances} ri ON fr.repositoryid = ri.id
+             WHERE ri.id IS NULL";
+
+    $deletedfiles = $DB->get_recordset_sql($sql);
+
+    $deletedfileids = array();
+
+    $fs = get_file_storage();
+    foreach ($deletedfiles as $deletedfile) {
+        $fs->delete_area_files($deletedfile->contextid, $deletedfile->component, $deletedfile->filearea, $deletedfile->itemid);
+        $deletedfileids[] = $deletedfile->referencefileid;
+    }
+    $deletedfiles->close();
+
+    $DB->delete_records_list('files_reference', 'id', $deletedfileids);
+}
index 0dc466e..360bed6 100644 (file)
@@ -920,4 +920,90 @@ class core_upgradelib_testcase extends advanced_testcase {
         $record = $DB->get_record('block_instances', ['id' => $entryid]);
         $this->assertEquals($expected, $record->configdata);
     }
+
+    /**
+     * Check that orphaned files are deleted.
+     */
+    public function test_upgrade_delete_orphaned_file_records() {
+        global $DB, $CFG;
+        require_once($CFG->dirroot . '/repository/lib.php');
+
+        $this->resetAfterTest();
+        // Create user.
+        $generator = $this->getDataGenerator();
+        $user = $generator->create_user();
+        $this->setUser($user);
+        $usercontext = context_user::instance($user->id);
+        $syscontext = context_system::instance();
+
+        $fs = get_file_storage();
+
+        $userrepository = array();
+        $newstoredfile = array();
+        $repositorypluginname = array('user', 'areafiles');
+
+        // Create two repositories with one file in each.
+        foreach ($repositorypluginname as $key => $value) {
+            // Override repository permission.
+            $capability = 'repository/' . $value . ':view';
+            $guestroleid = $DB->get_field('role', 'id', array('shortname' => 'guest'));
+            assign_capability($capability, CAP_ALLOW, $guestroleid, $syscontext->id, true);
+
+            $args = array();
+            $args['type'] = $value;
+            $repos = repository::get_instances($args);
+            $userrepository[$key] = reset($repos);
+
+            $this->assertInstanceOf('repository', $userrepository[$key]);
+
+            $component = 'user';
+            $filearea  = 'private';
+            $itemid    = $key;
+            $filepath  = '/';
+            $filename  = 'userfile.txt';
+
+            $filerecord = array(
+                'contextid' => $usercontext->id,
+                'component' => $component,
+                'filearea'  => $filearea,
+                'itemid'    => $itemid,
+                'filepath'  => $filepath,
+                'filename'  => $filename,
+            );
+
+            $content = 'Test content';
+            $originalfile = $fs->create_file_from_string($filerecord, $content);
+            $this->assertInstanceOf('stored_file', $originalfile);
+
+            $newfilerecord = array(
+                'contextid' => $syscontext->id,
+                'component' => 'core',
+                'filearea'  => 'phpunit',
+                'itemid'    => $key,
+                'filepath'  => $filepath,
+                'filename'  => $filename,
+            );
+            $ref = $fs->pack_reference($filerecord);
+            $newstoredfile[$key] = $fs->create_file_from_reference($newfilerecord, $userrepository[$key]->id, $ref);
+
+            // Look for references by repository ID.
+            $files = $fs->get_external_files($userrepository[$key]->id);
+            $file = reset($files);
+            $this->assertEquals($file, $newstoredfile[$key]);
+        }
+
+        // Make one file orphaned by deleting first repository.
+        $DB->delete_records('repository_instances', array('id' => $userrepository[0]->id));
+        $DB->delete_records('repository_instance_config', array('instanceid' => $userrepository[0]->id));
+
+        upgrade_delete_orphaned_file_records();
+
+        $files = $fs->get_external_files($userrepository[0]->id);
+        $file = reset($files);
+        $this->assertFalse($file);
+
+        $files = $fs->get_external_files($userrepository[1]->id);
+        $file = reset($files);
+        $this->assertEquals($file, $newstoredfile[1]);
+    }
 }
index ebd27f0..c8ca564 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2018120301.00;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2018120301.02;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.