MDL-40081 completion: clean up criteria records for deleted courses.
authorPaul Holden <paulh@moodle.com>
Thu, 26 Mar 2020 21:25:54 +0000 (21:25 +0000)
committerPaul Holden <paulh@moodle.com>
Mon, 6 Apr 2020 11:22:51 +0000 (12:22 +0100)
lib/completionlib.php
lib/db/upgrade.php
lib/tests/completionlib_test.php
version.php

index db3abeb..2258259 100644 (file)
@@ -498,7 +498,16 @@ class completion_info {
      */
     public function clear_criteria() {
         global $DB;
-        $DB->delete_records('course_completion_criteria', array('course' => $this->course_id));
+
+        // Remove completion criteria records for the course itself, and any records that refer to the course.
+        $select = 'course = :course OR (criteriatype = :type AND courseinstance = :courseinstance)';
+        $params = [
+            'course' => $this->course_id,
+            'type' => COMPLETION_CRITERIA_TYPE_COURSE,
+            'courseinstance' => $this->course_id,
+        ];
+
+        $DB->delete_records_select('course_completion_criteria', $select, $params);
         $DB->delete_records('course_completion_aggr_methd', array('course' => $this->course_id));
 
         $this->delete_course_completion_data();
index 6ce9568..558f346 100644 (file)
@@ -2212,5 +2212,16 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2020013000.01);
     }
 
+    if ($oldversion < 2020040200.01) {
+        // Clean up completion criteria records referring to courses that no longer exist.
+        $select = 'criteriatype = :type AND courseinstance NOT IN (SELECT id FROM {course})';
+        $params = ['type' => 8]; // COMPLETION_CRITERIA_TYPE_COURSE.
+
+        $DB->delete_records_select('course_completion_criteria', $select, $params);
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2020040200.01);
+    }
+
     return true;
 }
index 208aeb1..53e4071 100644 (file)
@@ -875,6 +875,44 @@ class core_completionlib_testcase extends advanced_testcase {
         $this->assertFalse($c2->has_activities());
     }
 
+    /**
+     * Test that data is cleaned up when we delete courses that are set as completion criteria for other courses
+     *
+     * @return void
+     */
+    public function test_course_delete_prerequisite() {
+        global $DB;
+
+        $this->setup_data();
+
+        $courseprerequisite = $this->getDataGenerator()->create_course(['enablecompletion' => true]);
+
+        $criteriadata = (object) [
+            'id' => $this->course->id,
+            'criteria_course' => [$courseprerequisite->id],
+        ];
+
+        /** @var completion_criteria_course $criteria */
+        $criteria = completion_criteria::factory(['criteriatype' => COMPLETION_CRITERIA_TYPE_COURSE]);
+        $criteria->update_config($criteriadata);
+
+        // Sanity test.
+        $this->assertTrue($DB->record_exists('course_completion_criteria', [
+            'course' => $this->course->id,
+            'criteriatype' => COMPLETION_CRITERIA_TYPE_COURSE,
+            'courseinstance' => $courseprerequisite->id,
+        ]));
+
+        // Deleting the prerequisite course should remove the completion criteria.
+        delete_course($courseprerequisite, false);
+
+        $this->assertFalse($DB->record_exists('course_completion_criteria', [
+            'course' => $this->course->id,
+            'criteriatype' => COMPLETION_CRITERIA_TYPE_COURSE,
+            'courseinstance' => $courseprerequisite->id,
+        ]));
+    }
+
     /**
      * Test course module completion update event.
      */
index bbed55d..d2a1eb8 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2020040200.00;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2020040200.01;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.
 $release  = '3.9dev (Build: 20200402)'; // Human-friendly version name