Merge branch 'MDL-32203c' of git://github.com/srynot4sale/moodle
authorSam Hemelryk <sam@moodle.com>
Wed, 23 May 2012 23:42:39 +0000 (11:42 +1200)
committerSam Hemelryk <sam@moodle.com>
Wed, 23 May 2012 23:42:39 +0000 (11:42 +1200)
13 files changed:
course/completion.php
lib/completion/completion_aggregation.php
lib/completion/completion_completion.php
lib/completion/completion_criteria.php
lib/completion/completion_criteria_activity.php
lib/completion/completion_criteria_completion.php
lib/completion/completion_criteria_course.php
lib/completion/completion_criteria_date.php
lib/completion/completion_criteria_duration.php
lib/completion/completion_criteria_grade.php
lib/completion/cron.php
lib/completion/data_object.php
lib/completionlib.php

index 2bd3ed9..3d4e17b 100644 (file)
@@ -103,44 +103,43 @@ if ($form->is_cancelled()){
 
     // Handle aggregation methods
     // Overall aggregation
-    $aggregation = new completion_aggregation();
-    $aggregation->course = $data->id;
-    $aggregation->criteriatype = null;
+    $aggdata = array(
+        'course'        => $data->id,
+        'criteriatype'  => null
+    );
+    $aggregation = new completion_aggregation($aggdata);
     $aggregation->setMethod($data->overall_aggregation);
-    $aggregation->insert();
+    $aggregation->save();
 
     // Activity aggregation
     if (empty($data->activity_aggregation)) {
         $data->activity_aggregation = 0;
     }
 
-    $aggregation = new completion_aggregation();
-    $aggregation->course = $data->id;
-    $aggregation->criteriatype = COMPLETION_CRITERIA_TYPE_ACTIVITY;
+    $aggdata['criteriatype'] = COMPLETION_CRITERIA_TYPE_ACTIVITY;
+    $aggregation = new completion_aggregation($aggdata);
     $aggregation->setMethod($data->activity_aggregation);
-    $aggregation->insert();
+    $aggregation->save();
 
     // Course aggregation
     if (empty($data->course_aggregation)) {
         $data->course_aggregation = 0;
     }
 
-    $aggregation = new completion_aggregation();
-    $aggregation->course = $data->id;
-    $aggregation->criteriatype = COMPLETION_CRITERIA_TYPE_COURSE;
+    $aggdata['criteriatype'] = COMPLETION_CRITERIA_TYPE_COURSE;
+    $aggregation = new completion_aggregation($aggdata);
     $aggregation->setMethod($data->course_aggregation);
-    $aggregation->insert();
+    $aggregation->save();
 
     // Role aggregation
     if (empty($data->role_aggregation)) {
         $data->role_aggregation = 0;
     }
 
-    $aggregation = new completion_aggregation();
-    $aggregation->course = $data->id;
-    $aggregation->criteriatype = COMPLETION_CRITERIA_TYPE_ROLE;
+    $aggdata['criteriatype'] = COMPLETION_CRITERIA_TYPE_ROLE;
+    $aggregation = new completion_aggregation($aggdata);
     $aggregation->setMethod($data->role_aggregation);
-    $aggregation->insert();
+    $aggregation->save();
 
     // Update course total passing grade
     if (!empty($data->criteria_grade)) {
@@ -152,7 +151,10 @@ if ($form->is_cancelled()){
         }
     }
 
-    redirect($CFG->wwwroot."/course/view.php?id=$course->id", get_string('changessaved'));
+    add_to_log($course->id, 'course', 'completion updated', 'completion.php?id='.$course->id);
+
+    $url = new moodle_url('/course/view.php', array('id' => $course->id));
+    redirect($url);
 }
 
 
index e7a0786..e6e626a 100644 (file)
@@ -49,13 +49,16 @@ class completion_aggregation extends data_object {
      */
     public $required_fields = array('id', 'course', 'criteriatype', 'method', 'value');
 
+    /* @var array Array of unique fields, used in where clauses */
+    public $unique_fields = array('course', 'criteriatype');
+
     /* @var int Course id */
     public $course;
 
     /* @var int Criteria type this aggregation method applies to, or NULL for overall course aggregation */
     public $criteriatype;
 
-    /* @var int Aggregation method (COMPLETION_AGGREGATION_* constant)*/
+    /* @var int Aggregation method (COMPLETION_AGGREGATION_* constant) */
     public $method;
 
     /* @var mixed Method value */
@@ -98,4 +101,19 @@ class completion_aggregation extends data_object {
             $this->method = COMPLETION_AGGREGATION_ALL;
         }
     }
+
+
+    /**
+     * Save aggregation method to database
+     *
+     * @access  public
+     * @return  boolean
+     */
+    public function save() {
+        if ($this->id) {
+            return $this->update();
+        } else {
+            return $this->insert();
+        }
+    }
 }
index 2b5d8bf..e6523ea 100644 (file)
@@ -111,7 +111,7 @@ class completion_completion extends data_object {
             $this->timeenrolled = $timeenrolled;
         }
 
-        $this->_save();
+        return $this->_save();
     }
 
     /**
@@ -137,7 +137,7 @@ class completion_completion extends data_object {
             $this->timestarted = $timestarted;
         }
 
-        $this->_save();
+        return $this->_save();
     }
 
     /**
@@ -165,24 +165,24 @@ class completion_completion extends data_object {
         $this->timecompleted = $timecomplete;
 
         // Save record
-        $this->_save();
+        return $this->_save();
     }
 
     /**
      * Save course completion status
      *
      * This method creates a course_completions record if none exists
+     * @access  private
+     * @return  bool
      */
     private function _save() {
-        global $DB;
-
         if ($this->timeenrolled === null) {
             $this->timeenrolled = 0;
         }
 
         // Save record
         if ($this->id) {
-            $this->update();
+            return $this->update();
         } else {
             // Make sure reaggregate field is not null
             if (!$this->reaggregate) {
@@ -191,10 +191,10 @@ class completion_completion extends data_object {
 
             // Make sure timestarted is not null
             if (!$this->timestarted) {
-                    $this->timestarted = 0;
+                $this->timestarted = 0;
             }
-                       
-            $this->insert();
+
+            return $this->insert();
         }
     }
 }
index d93e9a0..31f5187 100644 (file)
@@ -167,11 +167,11 @@ abstract class completion_criteria extends data_object {
     public static function factory($params) {
         global $CFG, $COMPLETION_CRITERIA_TYPES;
 
-        if (!isset($params->criteriatype) || !isset($COMPLETION_CRITERIA_TYPES[$params->criteriatype])) {
+        if (!isset($params['criteriatype']) || !isset($COMPLETION_CRITERIA_TYPES[$params['criteriatype']])) {
             error('invalidcriteriatype', 'completion');
         }
 
-        $class = 'completion_criteria_'.$COMPLETION_CRITERIA_TYPES[$params->criteriatype];
+        $class = 'completion_criteria_'.$COMPLETION_CRITERIA_TYPES[$params['criteriatype']];
         require_once($CFG->libdir.'/completion/'.$class.'.php');
 
         return new $class($params, false);
index 409bf42..ba27546 100644 (file)
@@ -235,8 +235,7 @@ class completion_criteria_activity extends completion_criteria {
         // Loop through completions, and mark as complete
         $rs = $DB->get_recordset_sql($sql);
         foreach ($rs as $record) {
-
-            $completion = new completion_criteria_completion((array)$record);
+            $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY);
             $completion->mark_complete($record->timecompleted);
         }
         $rs->close();
index f4d700d..7f44800 100644 (file)
@@ -44,6 +44,9 @@ class completion_criteria_completion extends data_object {
     /* @var array Array of required table fields, must start with 'id'. */
     public $required_fields = array('id', 'userid', 'course', 'criteriaid', 'gradefinal', 'rpl', 'deleted', 'unenroled', 'timecompleted');
 
+    /* @var array Array of unique fields, used in where clauses */
+    public $unique_fields = array('userid', 'course', 'criteriaid');
+
     /* @var int User ID */
     public $userid;
 
index 882ee63..04be448 100644 (file)
@@ -193,8 +193,8 @@ class completion_criteria_course extends completion_criteria {
         // Loop through completions, and mark as complete
         $rs = $DB->get_recordset_sql($sql);
         foreach ($rs as $record) {
-            $completion = new completion_criteria_completion((array)$record);
-            $completion->mark_complete($record->timecompleted);
+            $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY);
+            $completion->mark_complete($record['timecompleted']);
         }
         $rs->close();
     }
index e6e81c0..bacc144 100644 (file)
@@ -179,8 +179,8 @@ class completion_criteria_date extends completion_criteria {
         // Loop through completions, and mark as complete
         $rs = $DB->get_recordset_sql($sql, array(time()));
         foreach ($rs as $record) {
-            $completion = new completion_criteria_completion((array)$record);
-            $completion->mark_complete($record->timeend);
+            $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY);
+            $completion->mark_complete($record['timeend']);
         }
         $rs->close();
     }
index 97bcb92..962b052 100644 (file)
@@ -229,8 +229,7 @@ class completion_criteria_duration extends completion_criteria {
         $now = time();
         $rs = $DB->get_recordset_sql($sql, array($now, $now));
         foreach ($rs as $record) {
-
-            $completion = new completion_criteria_completion((array)$record);
+            $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY);
 
             // Use time start if not 0, otherwise use timeenrolled
             if ($record->otimestart) {
index e452454..3e0da11 100644 (file)
@@ -215,8 +215,8 @@ class completion_criteria_grade extends completion_criteria {
         // Loop through completions, and mark as complete
         $rs = $DB->get_recordset_sql($sql);
         foreach ($rs as $record) {
-            $completion = new completion_criteria_completion((array)$record);
-            $completion->mark_complete($record->timecompleted);
+            $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY);
+            $completion->mark_complete($record['timecompleted']);
         }
         $rs->close();
     }
index be480d4..3645c06 100644 (file)
@@ -317,7 +317,7 @@ function completion_cron_completions() {
             foreach ($completions as $params) {
                 $timecompleted = max($timecompleted, $params->timecompleted);
 
-                $completion = new completion_criteria_completion($params, false);
+                $completion = new completion_criteria_completion((array)$params, false);
 
                 // Handle aggregation special cases
                 if ($params->criteriatype == COMPLETION_CRITERIA_TYPE_ACTIVITY) {
index 01345ee..9d862ba 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
+
+/**
+ * Trigger for the new data_object api.
+ *
+ * See data_object::__constructor
+ */
+define('DATA_OBJECT_FETCH_BY_KEY',  2);
+
 /**
  * A data abstraction object that holds methods and attributes
  *
@@ -50,32 +58,74 @@ abstract class data_object {
      */
     public $optional_fields = array();
 
+    /* @var Array of unique fields, used in where clauses and constructor */
+    public $unique_fields = array();
+
     /* @var int The primary key */
     public $id;
 
+
     /**
      * Constructor. Optionally (and by default) attempts to fetch corresponding row from DB.
      *
-     * @param array $params an array with required parameters for this data object.
-     * @param bool $fetch Whether to fetch corresponding row from DB or not,
-     *        optional fields might not be defined if false used
+     * If $fetch is not false, there are a few different things that can happen:
+     * - true:
+     *   load corresponding row from the database, using $params as the WHERE clause
+     *
+     * - DATA_OBJECT_FETCH_BY_KEY:
+     *  load corresponding row from the database, using only the $id in the WHERE clause (if set),
+     *  otherwise using the columns listed in $this->unique_fields.
+     *
+     * - array():
+     *   load corresponding row from the database, using the columns listed in this array
+     *   in the WHERE clause
+     *
+     * @param   array   $params     required parameters and their values for this data object
+     * @param   mixed   $fetch      if false, do not attempt to fetch from the database, otherwise see notes
      */
     public function __construct($params = null, $fetch = true) {
-        if (!empty($params) and (is_array($params) or is_object($params))) {
-            if ($fetch) {
-                if ($data = $this->fetch($params)) {
-                    self::set_properties($this, $data);
-                } else {
-                    self::set_properties($this, $this->optional_fields);//apply defaults for optional fields
-                    self::set_properties($this, $params);
-                }
 
-            } else {
-                self::set_properties($this, $params);
+        if (is_object($params)) {
+            throw new coding_exception('data_object params should be in the form of an array, not an object');
+        }
+
+        // If no params given, apply defaults for optional fields
+        if (empty($params) || !is_array($params)) {
+            self::set_properties($this, $this->optional_fields);
+            return;
+        }
+
+        // If fetch is false, do not load from database
+        if ($fetch === false) {
+            self::set_properties($this, $params);
+            return;
+        }
+
+        // Compose where clause only from fields in unique_fields
+        if ($fetch === DATA_OBJECT_FETCH_BY_KEY && !empty($this->unique_fields)) {
+            if (empty($params['id'])) {
+                $where = array_intersect_key($params, array_flip($this->unique_fields));
+            }
+            else {
+                $where = array('id' => $params['id']);
             }
+        // Compose where clause from given field names
+        } else if (is_array($fetch) && !empty($fetch)) {
+            $where = array_intersect_key($params, array_flip($fetch));
+        // Use entire params array for where clause
+        } else {
+            $where = $params;
+        }
 
+        // Attempt to load from database
+        if ($data = $this->fetch($where)) {
+            // Apply data from database, then data sent to constructor
+            self::set_properties($this, $data);
+            self::set_properties($this, $params);
         } else {
-            self::set_properties($this, $this->optional_fields);//apply defaults for optional fields
+            // Apply defaults for optional fields, then data from constructor
+            self::set_properties($this, $this->optional_fields);
+            self::set_properties($this, $params);
         }
     }
 
@@ -339,4 +389,4 @@ abstract class data_object {
      */
     public function notify_changed($deleted) {
     }
-}
\ No newline at end of file
+}
index a47a1f8..2034af1 100644 (file)
@@ -322,8 +322,9 @@ class completion_info {
      */
     public function get_user_completion($user_id, $criteria) {
         $params = array(
+            'course'        => $this->course_id,
+            'userid'        => $user_id,
             'criteriaid'    => $criteria->id,
-            'userid'        => $user_id
         );
 
         $completion = new completion_criteria_completion($params);
@@ -362,7 +363,7 @@ class completion_info {
             // Build array of criteria objects
             $this->criteria = array();
             foreach ($records as $record) {
-                $this->criteria[$record->id] = completion_criteria::factory($record);
+                $this->criteria[$record->id] = completion_criteria::factory((array)$record);
             }
         }