diff --git a/blog/lib.php b/blog/lib.php index 2e53d979284..b81c645c0cc 100644 --- a/blog/lib.php +++ b/blog/lib.php @@ -135,6 +135,25 @@ function blog_remove_associations_for_course($courseid) { $DB->delete_records('blog_association', array('contextid' => $context->id)); } +/** + * Remove module associated blogs and blog tag instances. + * + * @param int $modcontextid Module context ID. + */ +function blog_remove_associations_for_module($modcontextid) { + global $DB; + + if (!empty($assocblogids = $DB->get_fieldset_select('blog_association', 'blogid', + 'contextid = :contextid', ['contextid' => $modcontextid]))) { + list($sql, $params) = $DB->get_in_or_equal($assocblogids, SQL_PARAMS_NAMED); + + $DB->delete_records_select('tag_instance', "itemid $sql", $params); + $DB->delete_records_select('post', "id $sql AND module = :module", + array_merge($params, ['module' => 'blog'])); + $DB->delete_records('blog_association', ['contextid' => $modcontextid]); + } +} + /** * Given a record in the {blog_external} table, checks the blog's URL * for new entries not yet copied into Moodle. diff --git a/course/lib.php b/course/lib.php index bf54e66c07d..aba5bdc9d54 100644 --- a/course/lib.php +++ b/course/lib.php @@ -1169,6 +1169,9 @@ function course_delete_module($cmid, $async = false) { } } + // Delete associated blogs and blog tag instances. + blog_remove_associations_for_module($modcontext->id); + // Delete completion and availability data; it is better to do this even if the // features are not turned on, in case they were turned on previously (these will be // very quick on an empty table). diff --git a/course/tests/courselib_test.php b/course/tests/courselib_test.php index 249948d5aef..ce1850485f7 100644 --- a/course/tests/courselib_test.php +++ b/course/tests/courselib_test.php @@ -303,6 +303,50 @@ class core_course_courselib_testcase extends advanced_testcase { return $moduleinfo; } + /** + * Create module associated blog and tags. + * + * @param object $course Course. + * @param object $modulecontext The context of the module. + */ + private function create_module_asscociated_blog($course, $modulecontext) { + global $DB, $CFG; + + // Create default group. + $group = new stdClass(); + $group->courseid = $course->id; + $group->name = 'Group'; + $group->id = $DB->insert_record('groups', $group); + + // Create default user. + $user = $this->getDataGenerator()->create_user(array( + 'username' => 'testuser', + 'firstname' => 'Firsname', + 'lastname' => 'Lastname' + )); + + // Create default post. + $post = new stdClass(); + $post->userid = $user->id; + $post->groupid = $group->id; + $post->content = 'test post content text'; + $post->module = 'blog'; + $post->id = $DB->insert_record('post', $post); + + // Create default tag. + $tag = $this->getDataGenerator()->create_tag(array('userid' => $user->id, + 'rawname' => 'Testtagname', 'isstandard' => 1)); + // Apply the tag to the blog. + $DB->insert_record('tag_instance', array('tagid' => $tag->id, 'itemtype' => 'user', + 'component' => 'core', 'itemid' => $post->id, 'ordering' => 0)); + + require_once($CFG->dirroot . '/blog/locallib.php'); + $blog = new blog_entry($post->id); + $blog->add_association($modulecontext->id); + + return $blog; + } + /** * Test create_module() for multiple modules defined in the $modules array (first declaration of the function). */ @@ -1521,6 +1565,8 @@ class core_course_courselib_testcase extends advanced_testcase { // Get the module context. $modcontext = context_module::instance($module->cmid); + $assocblog = $this->create_module_asscociated_blog($course, $modcontext); + // Verify context exists. $this->assertInstanceOf('context_module', $modcontext); @@ -1565,6 +1611,18 @@ class core_course_courselib_testcase extends advanced_testcase { $cmcount = $DB->count_records('course_modules', array('id' => $module->cmid)); $this->assertEmpty($cmcount); + // Verify the blog_association record has been deleted. + $this->assertCount(0, $DB->get_records('blog_association', + array('contextid' => $modcontext->id))); + + // Verify the blog post record has been deleted. + $this->assertCount(0, $DB->get_records('post', + array('id' => $assocblog->id))); + + // Verify the tag instance record has been deleted. + $this->assertCount(0, $DB->get_records('tag_instance', + array('itemid' => $assocblog->id))); + // Test clean up of module specific messes. switch ($type) { case 'assign': diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 8fbb66aabe5..80f33f80858 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -2301,5 +2301,32 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2018073000.00); } + if ($oldversion < 2018083100.01) { + // Remove module associated blog posts for non-existent (deleted) modules. + $sql = "SELECT ba.contextid as modcontextid + FROM {blog_association} ba + JOIN {post} p + ON p.id = ba.blogid + LEFT JOIN {context} c + ON c.id = ba.contextid + WHERE p.module = :module + AND c.contextlevel IS NULL + GROUP BY ba.contextid"; + if ($deletedmodules = $DB->get_records_sql($sql, array('module' => 'blog'))) { + foreach ($deletedmodules as $module) { + $assocblogids = $DB->get_fieldset_select('blog_association', 'blogid', + 'contextid = :contextid', ['contextid' => $module->modcontextid]); + list($sql, $params) = $DB->get_in_or_equal($assocblogids, SQL_PARAMS_NAMED); + + $DB->delete_records_select('tag_instance', "itemid $sql", $params); + $DB->delete_records_select('post', "id $sql AND module = :module", + array_merge($params, ['module' => 'blog'])); + $DB->delete_records('blog_association', ['contextid' => $module->modcontextid]); + } + } + // Main savepoint reached. + upgrade_main_savepoint(true, 2018083100.01); + } + return true; } diff --git a/version.php b/version.php index 6bfb0600e02..4a22036ebf1 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2018083100.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2018083100.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes.