# This patch file was generated by NetBeans IDE
# This patch can be applied using context Tools: Apply Diff Patch action on respective folder.
# It uses platform neutral UTF-8 encoding.
# Above lines and this line are ignored by the patching process.
Index: moodle/backup/moodle2/backup_course_task.class.php
--- moodle/backup/moodle2/backup_course_task.class.php Base (1.7)
+++ moodle/backup/moodle2/backup_course_task.class.php Locally Modified (Based On 1.7)
@@ -96,6 +96,11 @@
             //$this->add_step(new backup_course_logs_structure_step('course_logs', 'logs.xml'));
         }
 
+        // Generate the course completion (conditionally)
+        if ($this->get_setting_value('userscompletion')) {
+            $this->add_step(new backup_course_completion_structure_step('course_completion', 'completion.xml'));
+        }
+
         // Generate the inforef file (must be after ALL steps gathering annotations of ANY type)
         $this->add_step(new backup_inforef_structure_step('course', 'inforef.xml'));
 
Index: moodle/backup/moodle2/backup_stepslib.php
--- moodle/backup/moodle2/backup_stepslib.php Base (1.42)
+++ moodle/backup/moodle2/backup_stepslib.php Locally Modified (Based On 1.42)
@@ -1531,3 +1531,68 @@
         return $book;
     }
 }
+
+/**
+ * Backups up the course completion information for the course.
+ */
+class backup_course_completion_structure_step extends backup_structure_step {
+
+    /**
+     * The structure of the course completion backup
+     *
+     * @return backup_nested_element
+     */
+    protected function define_structure() {
+        
+        $cc = new backup_nested_element('course_completion');
+
+        $criteria = new backup_nested_element('course_completion_criteria', array('id'), array(
+            'course','criteriatype', 'module', 'moduleinstance', 'courseinstanceshortname', 'enrolperiod', 'timeend', 'gradepass', 'role'
+        ));
+
+        $criteriacompletions = new backup_nested_element('course_completion_crit_completions');
+
+        $criteriacomplete = new backup_nested_element('course_completion_crit_compl', array('id'), array(
+            'userid','gradefinal','unenrolled','deleted','timecompleted'
+        ));
+
+        $coursecompletions = new backup_nested_element('course_completions', array('id'), array(
+            'userid', 'course', 'deleted', 'timenotified', 'timeenrolled','timestarted','timecompleted','reaggregate'
+        ));
+
+        $notify = new backup_nested_element('course_completion_notify', array('id'), array(
+            'course','role','message','timesent'
+        ));
+
+        $aggregatemethod = new backup_nested_element('course_completion_aggr_methd', array('id'), array(
+            'course','criteriatype','method','value'
+        ));
+
+        $cc->add_child($criteria);
+            $criteria->add_child($criteriacompletions);
+                $criteriacompletions->add_child($criteriacomplete);
+        $cc->add_child($coursecompletions);
+        $cc->add_child($notify);
+        $cc->add_child($aggregatemethod);
+
+        // We need to get the courseinstances shortname rather than an ID for restore
+        $criteria->set_source_sql("SELECT ccc.*, c.shortname courseinstanceshortname
+                               FROM {course_completion_criteria} ccc
+                               LEFT JOIN {course} c ON c.id = ccc.courseinstance
+                               WHERE ccc.course = ?", array(backup::VAR_COURSEID));
+        $criteriacomplete->set_source_table('course_completion_crit_compl', array('criteriaid' => backup::VAR_PARENTID));
+        
+        $coursecompletions->set_source_table('course_completions', array('course' => backup::VAR_COURSEID));
+        $notify->set_source_table('course_completion_notify', array('course' => backup::VAR_COURSEID));
+        $aggregatemethod->set_source_table('course_completion_aggr_methd', array('course' => backup::VAR_COURSEID));
+
+
+        $criteria->annotate_ids('role', 'role');
+        $criteriacomplete->annotate_ids('user', 'userid');
+        $coursecompletions->annotate_ids('user', 'userid');
+        $notify->annotate_ids('role', 'role');
+
+        return $cc;
+
+    }
+}
\ No newline at end of file
Index: moodle/backup/moodle2/restore_course_task.class.php
--- moodle/backup/moodle2/restore_course_task.class.php Base (1.9)
+++ moodle/backup/moodle2/restore_course_task.class.php Locally Modified (Based On 1.9)
@@ -82,6 +82,10 @@
             $this->add_step(new restore_comments_structure_step('course_comments', 'comments.xml'));
         }
 
+        if ($this->get_setting_value('userscompletion')) {
+            $this->add_step(new restore_course_completion_structure_step('course_completion', 'completion.xml'));
+        }
+
         // Restore course logs (conditionally)
         if ($this->get_setting_value('logs')) {
             //$this->add_step(new restore_course_logs_structure_step('course_logs', 'logs.xml'));
Index: moodle/backup/moodle2/restore_stepslib.php
--- moodle/backup/moodle2/restore_stepslib.php Base (1.35)
+++ moodle/backup/moodle2/restore_stepslib.php Locally Modified (Based On 1.35)
@@ -1167,7 +1167,188 @@
     }
 }
 
+class restore_course_completion_structure_step extends restore_structure_step {
+
 /**
+     * Define the course completion structure
+     *
+     * @return array Array of restore_path_element
+     */
+    protected function define_structure() {
+        
+        $paths = array(
+            new restore_path_element('course_completion_criteria', '/course_completion/course_completion_criteria'),
+            new restore_path_element('course_completion_crit_compl', '/course_completion/course_completion_criteria/course_completion_crit_completions/course_completion_crit_compl'),
+            new restore_path_element('course_completions', '/course_completion/course_completions'),
+            new restore_path_element('course_completion_notify', '/course_completion/course_completion_notify'),
+            new restore_path_element('course_completion_aggr_methd', '/course_completion/course_completion_aggr_methd')
+        );
+
+        return $paths;
+
+    }
+
+    /**
+     * Process course completion criteria
+     *
+     * @global moodle_database $DB
+     * @param stdClass $data
+     */
+    public function process_course_completion_criteria($data) {
+        global $DB;
+
+        $data = (object)$data;
+        $data->course = $this->get_courseid();
+
+        // Apply the date offset to the time end field
+        if (!empty($data->timeend)) {
+            $data->timeend = $this->apply_date_offset($data->timeend);
+        }
+
+        // Map the role from the criteria
+        if (!empty($data->role)) {
+            $data->role = $this->get_mappingid('role', $data->role);
+        }
+
+        // We backup the course shortname rather than the ID so that we can match back to the course
+        if (!empty($data->courseinstanceshortname)) {
+            $courseinstanceid = $DB->get_field('course', 'id', array('shortname'=>$data->courseinstanceshortname));
+            if (!$courseinstanceid) {
+                $courseinstanceid = null;
+            }
+        } else {
+            $courseinstanceid = null;
+        }
+        $data->courseinstance = $courseinstanceid;
+
+        // TODO: Deal with activity completion criteria and other course completion criteria.
+        // Currently we just ignore them, not great at all.
+        if (empty($data->moduleinstance) || !is_numeric($data->moduleinstance)) {
+            $params = array(
+                'course' => $data->course,
+                'criteriatype' => $data->criteriatype,
+                'enrolperiod' => $data->enrolperiod,
+                'courseinstance' => $data->courseinstance,
+                'timeend' => $data->timeend,
+                'gradepass' => $data->gradepass,
+                'role' => $data->role
+            );
+            $newid = $DB->insert_record('course_completion_criteria', $params);
+            $this->set_mapping('course_completion_criteria', $data->id, $newid);
+        }
+    }
+
+    /**
+     * Processes course compltion criteria complete records
+     *
+     * @global moodle_database $DB
+     * @param stdClass $data
+     */
+    public function process_course_completion_crit_compl($data) {
+        global $DB;
+
+        $data = (object)$data;
+
+        $data->criteriaid = $this->get_new_parentid('course_completion_criteria');
+        $data->course = $this->get_courseid();
+        $data->userid = $this->get_mappingid('user', $data->userid);
+
+        if (!empty($data->criteriaid) && !empty($data->userid)) {
+            $params = array(
+                'userid' => $data->userid,
+                'course' => $data->course,
+                'criteriaid' => $data->criteriaid,
+                'gradefinal' => $data->gradefinal,
+                'unenroled' => $data->unenroled,
+                'deleted' => $data->deleted,
+                'timecompleted' => $data->timecompleted
+            );
+            $DB->insert_record('course_completion_crit_compl', $params);
+        }
+    }
+
+    /**
+     * Process course completions
+     *
+     * @global moodle_database $DB
+     * @param stdClass $data
+     */
+    public function process_course_completions($data) {
+        global $DB;
+
+        $data = (object)$data;
+
+        $data->course = $this->get_courseid();
+        $data->userid = $this->get_mappingid('user', $data->userid);
+
+        if (!empty($data->userid)) {
+            $params = array(
+                'userid' => $data->userid,
+                'course' => $data->course,
+                'deleted' => $data->deleted,
+                'timenotified' => $data->timenotified,
+                'timeenrolled' => $data->timeenrolled,
+                'timestarted' => $data->timestarted,
+                'timecompleted' => $data->timecompleted,
+                'reaggregate' => $data->reaggregate
+            );
+            $DB->insert_record('course_completions', $params);
+        }
+    }
+
+    /**
+     * Process course completion notification records.
+     *
+     * Note: As of Moodle 2.0 this table is not being used however it has been
+     * left in in the hopes that one day the functionality there will be completed
+     *
+     * @global moodle_database $DB
+     * @param stdClass $data
+     */
+    public function process_course_completion_notify($data) {
+        global $DB;
+
+        $data = (object)$data;
+
+        $data->course = $this->get_courseid();
+        if (!empty($data->role)) {
+            $data->role = $this->get_mappingid('role', $data->role);
+        }
+
+        $params = array(
+            'course' => $data->course,
+            'role' => $data->role,
+            'message' => $data->message,
+            'timesent' => $data->timesent,
+        );
+        $DB->insert_record('course_completion_notify', $params);
+    }
+
+    /**
+     * Process course completion aggregate methods
+     *
+     * @global moodle_database $DB
+     * @param stdClass $data
+     */
+    public function process_course_completion_aggr_methd($data) {
+        global $DB;
+
+        $data = (object)$data;
+
+        $data->course = $this->get_courseid();
+
+        $params = array(
+            'course' => $data->course,
+            'criteriatype' => $data->criteriatype,
+            'method' => $data->method,
+            'value' => $data->value,
+        );
+        $DB->insert_record('course_completion_aggr_methd', $params);
+    }
+
+}
+
+/**
  * This structure step restores the grade items associated with one activity
  * All the grade items are made child of the "course" grade item but the original
  * categoryid is saved as parentitemid in the backup_ids table, so, when restoring
