Пример #1
0
 /**
  * Compute the quiz statistics.
  *
  * @param int   $quizid            the quiz id.
  * @param int $whichattempts which attempts to use, represented internally as one of the constants as used in
  *                                   $quiz->grademethod ie.
  *                                   QUIZ_GRADEAVERAGE, QUIZ_GRADEHIGHEST, QUIZ_ATTEMPTLAST or QUIZ_ATTEMPTFIRST
  *                                   we calculate stats based on which attempts would affect the grade for each student.
  * @param \core\dml\sql_join $groupstudentsjoins Contains joins, wheres, params for students in this group.
  * @param int   $p                 number of positions (slots).
  * @param float $sumofmarkvariance sum of mark variance, calculated as part of question statistics
  * @return calculated $quizstats The statistics for overall attempt scores.
  */
 public function calculate($quizid, $whichattempts, \core\dml\sql_join $groupstudentsjoins, $p, $sumofmarkvariance)
 {
     $this->progress->start_progress('', 3);
     $quizstats = new calculated($whichattempts);
     $countsandaverages = $this->attempt_counts_and_averages($quizid, $groupstudentsjoins);
     $this->progress->progress(1);
     foreach ($countsandaverages as $propertyname => $value) {
         $quizstats->{$propertyname} = $value;
     }
     $s = $quizstats->s();
     if ($s != 0) {
         // Recalculate sql again this time possibly including test for first attempt.
         list($fromqa, $whereqa, $qaparams) = quiz_statistics_attempts_sql($quizid, $groupstudentsjoins, $whichattempts);
         $quizstats->median = $this->median($s, $fromqa, $whereqa, $qaparams);
         $this->progress->progress(2);
         if ($s > 1) {
             $powers = $this->sum_of_powers_of_difference_to_mean($quizstats->avg(), $fromqa, $whereqa, $qaparams);
             $this->progress->progress(3);
             $quizstats->standarddeviation = sqrt($powers->power2 / ($s - 1));
             // Skewness.
             if ($s > 2) {
                 // See http://docs.moodle.org/dev/Quiz_item_analysis_calculations_in_practise#Skewness_and_Kurtosis.
                 $m2 = $powers->power2 / $s;
                 $m3 = $powers->power3 / $s;
                 $m4 = $powers->power4 / $s;
                 $k2 = $s * $m2 / ($s - 1);
                 $k3 = $s * $s * $m3 / (($s - 1) * ($s - 2));
                 if ($k2 != 0) {
                     $quizstats->skewness = $k3 / pow($k2, 3 / 2);
                     // Kurtosis.
                     if ($s > 3) {
                         $k4 = $s * $s * (($s + 1) * $m4 - 3 * ($s - 1) * $m2 * $m2) / (($s - 1) * ($s - 2) * ($s - 3));
                         $quizstats->kurtosis = $k4 / ($k2 * $k2);
                     }
                     if ($p > 1) {
                         $quizstats->cic = 100 * $p / ($p - 1) * (1 - $sumofmarkvariance / $k2);
                         $quizstats->errorratio = 100 * sqrt(1 - $quizstats->cic / 100);
                         $quizstats->standarderror = $quizstats->errorratio * $quizstats->standarddeviation / 100;
                     }
                 }
             }
         }
         $quizstats->cache(quiz_statistics_qubaids_condition($quizid, $groupstudentsjoins, $whichattempts));
     }
     $this->progress->end_progress();
     return $quizstats;
 }
 /**
  * Get details information for main moodle_backup.xml file, extracting it from
  * the specified controller.
  *
  * If you specify the progress monitor, this will start a new progress section
  * to track progress in processing (in case this task takes a long time).
  *
  * @param string $backupid Backup ID
  * @param \core\progress\base $progress Optional progress monitor
  */
 public static function get_moodle_backup_information($backupid, \core\progress\base $progress = null)
 {
     // Start tracking progress if required (for load_controller).
     if ($progress) {
         $progress->start_progress('get_moodle_backup_information', 2);
     }
     $detailsinfo = array();
     // Information details
     $contentsinfo = array();
     // Information about backup contents
     $settingsinfo = array();
     // Information about backup settings
     $bc = self::load_controller($backupid);
     // Load controller
     // Note that we have loaded controller.
     if ($progress) {
         $progress->progress(1);
     }
     // Details info
     $detailsinfo['id'] = $bc->get_id();
     $detailsinfo['backup_id'] = $bc->get_backupid();
     $detailsinfo['type'] = $bc->get_type();
     $detailsinfo['format'] = $bc->get_format();
     $detailsinfo['interactive'] = $bc->get_interactive();
     $detailsinfo['mode'] = $bc->get_mode();
     $detailsinfo['execution'] = $bc->get_execution();
     $detailsinfo['executiontime'] = $bc->get_executiontime();
     $detailsinfo['userid'] = $bc->get_userid();
     $detailsinfo['courseid'] = $bc->get_courseid();
     // Init content placeholders
     $contentsinfo['activities'] = array();
     $contentsinfo['sections'] = array();
     $contentsinfo['course'] = array();
     // Get tasks and start nested progress.
     $tasks = $bc->get_plan()->get_tasks();
     if ($progress) {
         $progress->start_progress('get_moodle_backup_information', count($tasks));
         $done = 1;
     }
     // Contents info (extract information from tasks)
     foreach ($tasks as $task) {
         if ($task instanceof backup_activity_task) {
             // Activity task
             if ($task->get_setting_value('included')) {
                 // Only return info about included activities
                 list($contentinfo, $settings) = self::get_activity_backup_information($task);
                 $contentsinfo['activities'][] = $contentinfo;
                 $settingsinfo = array_merge($settingsinfo, $settings);
             }
         } else {
             if ($task instanceof backup_section_task) {
                 // Section task
                 if ($task->get_setting_value('included')) {
                     // Only return info about included sections
                     list($contentinfo, $settings) = self::get_section_backup_information($task);
                     $contentsinfo['sections'][] = $contentinfo;
                     $settingsinfo = array_merge($settingsinfo, $settings);
                 }
             } else {
                 if ($task instanceof backup_course_task) {
                     // Course task
                     list($contentinfo, $settings) = self::get_course_backup_information($task);
                     $contentsinfo['course'][] = $contentinfo;
                     $settingsinfo = array_merge($settingsinfo, $settings);
                 } else {
                     if ($task instanceof backup_root_task) {
                         // Root task
                         list($contentinfo, $settings) = self::get_root_backup_information($task);
                         $settingsinfo = array_merge($settingsinfo, $settings);
                     }
                 }
             }
         }
         // Report task handled.
         if ($progress) {
             $progress->progress($done++);
         }
     }
     $bc->destroy();
     // Always need to destroy controller to handle circular references
     // Finish progress reporting.
     if ($progress) {
         $progress->end_progress();
         $progress->end_progress();
     }
     return array(array((object) $detailsinfo), $contentsinfo, $settingsinfo);
 }
 /**
  * Moves all the existing 'item' annotations to their final 'itemfinal' ones
  * for a given backup.
  *
  * @param string $backupid Backup ID
  * @param string $itemname Item name
  * @param \core\progress\base $progress Progress tracker
  */
 public static function move_annotations_to_final($backupid, $itemname, \core\progress\base $progress)
 {
     global $DB;
     $progress->start_progress('move_annotations_to_final');
     $rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $backupid, 'itemname' => $itemname));
     $progress->progress();
     foreach ($rs as $annotation) {
         // If corresponding 'itemfinal' annotation does not exist, update 'item' to 'itemfinal'
         if (!$DB->record_exists('backup_ids_temp', array('backupid' => $backupid, 'itemname' => $itemname . 'final', 'itemid' => $annotation->itemid))) {
             $DB->set_field('backup_ids_temp', 'itemname', $itemname . 'final', array('id' => $annotation->id));
         }
         $progress->progress();
     }
     $rs->close();
     // All the remaining $itemname annotations can be safely deleted
     $DB->delete_records('backup_ids_temp', array('backupid' => $backupid, 'itemname' => $itemname));
     $progress->end_progress();
 }
Пример #4
0
 /**
  * Check all the included users, deciding the action to perform
  * for each one (mapping / creation) and returning one array
  * of problems in case something is wrong (lack of permissions,
  * conficts)
  *
  * @param string $restoreid Restore id
  * @param int $courseid Course id
  * @param int $userid User id
  * @param bool $samesite True if restore is to same site
  * @param \core\progress\base $progress Progress reporter
  */
 public static function precheck_included_users($restoreid, $courseid, $userid, $samesite, \core\progress\base $progress)
 {
     global $CFG, $DB;
     // To return any problem found
     $problems = array();
     // We are going to map mnethostid, so load all the available ones
     $mnethosts = $DB->get_records('mnet_host', array(), 'wwwroot', 'wwwroot, id');
     // Calculate the context we are going to use for capability checking
     $context = context_course::instance($courseid);
     // Calculate if we have perms to create users, by checking:
     // to 'moodle/restore:createuser' and 'moodle/restore:userinfo'
     // and also observe $CFG->disableusercreationonrestore
     $cancreateuser = false;
     if (has_capability('moodle/restore:createuser', $context, $userid) and has_capability('moodle/restore:userinfo', $context, $userid) and empty($CFG->disableusercreationonrestore)) {
         // Can create users
         $cancreateuser = true;
     }
     // Prepare for reporting progress.
     $conditions = array('backupid' => $restoreid, 'itemname' => 'user');
     $max = $DB->count_records('backup_ids_temp', $conditions);
     $done = 0;
     $progress->start_progress('Checking users', $max);
     // Iterate over all the included users
     $rs = $DB->get_recordset('backup_ids_temp', $conditions, '', 'itemid, info');
     foreach ($rs as $recuser) {
         $user = (object) backup_controller_dbops::decode_backup_temp_info($recuser->info);
         // Find the correct mnethostid for user before performing any further check
         if (empty($user->mnethosturl) || $user->mnethosturl === $CFG->wwwroot) {
             $user->mnethostid = $CFG->mnet_localhost_id;
         } else {
             // fast url-to-id lookups
             if (isset($mnethosts[$user->mnethosturl])) {
                 $user->mnethostid = $mnethosts[$user->mnethosturl]->id;
             } else {
                 $user->mnethostid = $CFG->mnet_localhost_id;
             }
         }
         // Now, precheck that user and, based on returned results, annotate action/problem
         $usercheck = self::precheck_user($user, $samesite);
         if (is_object($usercheck)) {
             // No problem, we have found one user in DB to be mapped to
             // Annotate it, for later process. Set newitemid to mapping user->id
             self::set_backup_ids_record($restoreid, 'user', $recuser->itemid, $usercheck->id);
         } else {
             if ($usercheck === false) {
                 // Found conflict, report it as problem
                 $problems[] = get_string('restoreuserconflict', '', $user->username);
             } else {
                 if ($usercheck === true) {
                     // User needs to be created, check if we are able
                     if ($cancreateuser) {
                         // Can create user, set newitemid to 0 so will be created later
                         self::set_backup_ids_record($restoreid, 'user', $recuser->itemid, 0, null, (array) $user);
                     } else {
                         // Cannot create user, report it as problem
                         $problems[] = get_string('restorecannotcreateuser', '', $user->username);
                     }
                 } else {
                     // Shouldn't arrive here ever, something is for sure wrong. Exception
                     throw new restore_dbops_exception('restore_error_processing_user', $user->username);
                 }
             }
         }
         $done++;
         $progress->progress($done);
     }
     $rs->close();
     $progress->end_progress();
     return $problems;
 }