/**
  * Updates completion data for a particular coursemodule and user (user is
  * determined from $data).
  *
  * (Internal function. Not private, so we can unit-test it.)
  *
  * @param stdClass|cm_info $cm Activity
  * @param stdClass $data Data about completion for that user
  */
 public function internal_set_data($cm, $data)
 {
     global $USER, $SESSION, $DB;
     $transaction = $DB->start_delegated_transaction();
     if (!$data->id) {
         // Check there isn't really a row
         $data->id = $DB->get_field('course_modules_completion', 'id', array('coursemoduleid' => $data->coursemoduleid, 'userid' => $data->userid));
     }
     if (!$data->id) {
         // Didn't exist before, needs creating
         $data->id = $DB->insert_record('course_modules_completion', $data);
     } else {
         // Has real (nonzero) id meaning that a database row exists, update
         $DB->update_record('course_modules_completion', $data);
     }
     $transaction->allow_commit();
     $cmcontext = context_module::instance($data->coursemoduleid, MUST_EXIST);
     $coursecontext = $cmcontext->get_parent_context();
     // Trigger an event for course module completion changed.
     $event = \core\event\course_module_completion_updated::create(array('objectid' => $data->id, 'context' => $cmcontext, 'relateduserid' => $data->userid, 'other' => array('relateduserid' => $data->userid)));
     $event->add_record_snapshot('course_modules_completion', $data);
     $event->trigger();
     if ($data->userid == $USER->id) {
         $SESSION->completioncache[$cm->course][$cm->id] = $data;
         // reset modinfo for user (no need to call rebuild_course_cache())
         get_fast_modinfo($cm->course, 0, true);
     }
 }