diff --git a/lib/accesslib.php b/lib/accesslib.php index 65bc9d86272..bf5653cf5b9 100644 --- a/lib/accesslib.php +++ b/lib/accesslib.php @@ -5249,6 +5249,10 @@ abstract class context extends stdClass implements IteratorAggregate { $fs = get_file_storage(); $fs->delete_area_files($this->_id); + // Delete all repository instances attached to this context. + require_once($CFG->dirroot . '/repository/lib.php'); + repository::delete_all_for_context($this->_id); + // delete all advanced grading data attached to this context require_once($CFG->dirroot.'/grade/grading/lib.php'); grading_manager::delete_all_for_context($this->_id); diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index cb30c60c291..ba5eb758d4a 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -1749,5 +1749,24 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2012120304.06); } + if ($oldversion < 2012120305.01) { + + // Remove orphan repository instances. + if ($DB->get_dbfamily() === 'mysql') { + $sql = "DELETE {repository_instances} FROM {repository_instances} + LEFT JOIN {context} ON {context}.id = {repository_instances}.contextid + WHERE {context}.id IS NULL"; + } else { + $sql = "DELETE FROM {repository_instances} + WHERE NOT EXISTS ( + SELECT 'x' FROM {context} + WHERE {context}.id = {repository_instances}.contextid)"; + } + $DB->execute($sql); + + // Main savepoint reached. + upgrade_main_savepoint(true, 2012120305.01); + } + return true; } diff --git a/repository/lib.php b/repository/lib.php index 7ccb28603ba..7d8fa9b2062 100644 --- a/repository/lib.php +++ b/repository/lib.php @@ -1952,6 +1952,32 @@ abstract class repository { return true; } + /** + * Delete all the instances associated to a context. + * + * This method is intended to be a callback when deleting + * a course or a user to delete all the instances associated + * to their context. The usual way to delete a single instance + * is to use {@link self::delete()}. + * + * @param int $contextid context ID. + * @param boolean $downloadcontents true to convert references to hard copies. + * @return void + */ + final public static function delete_all_for_context($contextid, $downloadcontents = true) { + global $DB; + $repoids = $DB->get_fieldset_select('repository_instances', 'id', 'contextid = :contextid', array('contextid' => $contextid)); + if ($downloadcontents) { + foreach ($repoids as $repoid) { + $repo = repository::get_repository_by_id($repoid, $contextid); + $repo->convert_references_to_local(); + } + } + cache::make('core', 'repositories')->purge(); + $DB->delete_records_list('repository_instances', 'id', $repoids); + $DB->delete_records_list('repository_instance_config', 'instanceid', $repoids); + } + /** * Hide/Show a repository * diff --git a/repository/tests/repository_test.php b/repository/tests/repository_test.php index 9a965094648..b68f571a071 100644 --- a/repository/tests/repository_test.php +++ b/repository/tests/repository_test.php @@ -287,4 +287,86 @@ class repositorylib_testcase extends advanced_testcase { $this->assertTrue($notprivaterepo->check_capability()); } + function test_delete_all_for_context() { + global $DB; + $this->resetAfterTest(true); + + $this->setAdminUser(); + $course = $this->getDataGenerator()->create_course(); + $user = $this->getDataGenerator()->create_user(); + $this->getDataGenerator()->create_repository_type('flickr_public'); + $this->getDataGenerator()->create_repository_type('filesystem'); + $coursecontext = context_course::instance($course->id); + $usercontext = context_user::instance($user->id); + + // Creating course instances. + $repo = $this->getDataGenerator()->create_repository('flickr_public', array('contextid' => $coursecontext->id)); + $courserepo1 = repository::get_repository_by_id($repo->id, $coursecontext); + $this->assertEquals(1, $DB->count_records('repository_instances', array('contextid' => $coursecontext->id))); + + $repo = $this->getDataGenerator()->create_repository('filesystem', array('contextid' => $coursecontext->id)); + $courserepo2 = repository::get_repository_by_id($repo->id, $coursecontext); + $this->assertEquals(2, $DB->count_records('repository_instances', array('contextid' => $coursecontext->id))); + + // Creating user instances. + $repo = $this->getDataGenerator()->create_repository('flickr_public', array('contextid' => $usercontext->id)); + $userrepo1 = repository::get_repository_by_id($repo->id, $usercontext); + $this->assertEquals(1, $DB->count_records('repository_instances', array('contextid' => $usercontext->id))); + + $repo = $this->getDataGenerator()->create_repository('filesystem', array('contextid' => $usercontext->id)); + $userrepo2 = repository::get_repository_by_id($repo->id, $usercontext); + $this->assertEquals(2, $DB->count_records('repository_instances', array('contextid' => $usercontext->id))); + + // Simulation of course deletion. + repository::delete_all_for_context($coursecontext->id); + $this->assertEquals(0, $DB->count_records('repository_instances', array('contextid' => $coursecontext->id))); + $this->assertEquals(0, $DB->count_records('repository_instances', array('id' => $courserepo1->id))); + $this->assertEquals(0, $DB->count_records('repository_instances', array('id' => $courserepo2->id))); + $this->assertEquals(0, $DB->count_records('repository_instance_config', array('instanceid' => $courserepo1->id))); + $this->assertEquals(0, $DB->count_records('repository_instance_config', array('instanceid' => $courserepo2->id))); + + // Simulation of user deletion. + repository::delete_all_for_context($usercontext->id); + $this->assertEquals(0, $DB->count_records('repository_instances', array('contextid' => $usercontext->id))); + $this->assertEquals(0, $DB->count_records('repository_instances', array('id' => $userrepo1->id))); + $this->assertEquals(0, $DB->count_records('repository_instances', array('id' => $userrepo2->id))); + $this->assertEquals(0, $DB->count_records('repository_instance_config', array('instanceid' => $userrepo1->id))); + $this->assertEquals(0, $DB->count_records('repository_instance_config', array('instanceid' => $userrepo2->id))); + + // Checking deletion upon course context deletion. + $course = $this->getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + $repo = $this->getDataGenerator()->create_repository('flickr_public', array('contextid' => $coursecontext->id)); + $courserepo = repository::get_repository_by_id($repo->id, $coursecontext); + $this->assertEquals(1, $DB->count_records('repository_instances', array('contextid' => $coursecontext->id))); + $coursecontext->delete(); + $this->assertEquals(0, $DB->count_records('repository_instances', array('contextid' => $coursecontext->id))); + + // Checking deletion upon user context deletion. + $user = $this->getDataGenerator()->create_user(); + $usercontext = context_user::instance($user->id); + $repo = $this->getDataGenerator()->create_repository('flickr_public', array('contextid' => $usercontext->id)); + $userrepo = repository::get_repository_by_id($repo->id, $usercontext); + $this->assertEquals(1, $DB->count_records('repository_instances', array('contextid' => $usercontext->id))); + $usercontext->delete(); + $this->assertEquals(0, $DB->count_records('repository_instances', array('contextid' => $usercontext->id))); + + // Checking deletion upon course deletion. + $course = $this->getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + $repo = $this->getDataGenerator()->create_repository('flickr_public', array('contextid' => $coursecontext->id)); + $courserepo = repository::get_repository_by_id($repo->id, $coursecontext); + $this->assertEquals(1, $DB->count_records('repository_instances', array('contextid' => $coursecontext->id))); + delete_course($course, false); + $this->assertEquals(0, $DB->count_records('repository_instances', array('contextid' => $coursecontext->id))); + + // Checking deletion upon user deletion. + $user = $this->getDataGenerator()->create_user(); + $usercontext = context_user::instance($user->id); + $repo = $this->getDataGenerator()->create_repository('flickr_public', array('contextid' => $usercontext->id)); + $userrepo = repository::get_repository_by_id($repo->id, $usercontext); + $this->assertEquals(1, $DB->count_records('repository_instances', array('contextid' => $usercontext->id))); + delete_user($user); + $this->assertEquals(0, $DB->count_records('repository_instances', array('contextid' => $usercontext->id))); + } } diff --git a/version.php b/version.php index 3ee75609c16..b15a17fae85 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2012120305.00; // 20121203 = branching date YYYYMMDD - do not modify! +$version = 2012120305.01; // 20121203 = branching date YYYYMMDD - do not modify! // RR = release increments - 00 in DEV branches // .XX = incremental changes