Ejemplo n.º 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;
 }
Ejemplo n.º 2
0
 /**
  * Given one fullpath to directory, delete its contents recursively
  * Copied originally from somewhere in the net.
  * TODO: Modernise this
  *
  * If supplied, progress object should be ready to receive indeterminate
  * progress reports.
  *
  * @param string $dir Directory to delete
  * @param string $excludedir Exclude this directory
  * @param \core\progress\base $progress Optional progress reporting object
  */
 public static function delete_dir_contents($dir, $excludeddir = '', \core\progress\base $progress = null)
 {
     global $CFG;
     if ($progress) {
         $progress->progress();
     }
     if (!is_dir($dir)) {
         // if we've been given a directory that doesn't exist yet, return true.
         // this happens when we're trying to clear out a course that has only just
         // been created.
         return true;
     }
     $slash = "/";
     // Create arrays to store files and directories
     $dir_files = array();
     $dir_subdirs = array();
     // Make sure we can delete it
     chmod($dir, $CFG->directorypermissions);
     if (($handle = opendir($dir)) == false) {
         // The directory could not be opened
         return false;
     }
     // Loop through all directory entries, and construct two temporary arrays containing files and sub directories
     while (false !== ($entry = readdir($handle))) {
         if (is_dir($dir . $slash . $entry) && $entry != ".." && $entry != "." && $entry != $excludeddir) {
             $dir_subdirs[] = $dir . $slash . $entry;
         } else {
             if ($entry != ".." && $entry != "." && $entry != $excludeddir) {
                 $dir_files[] = $dir . $slash . $entry;
             }
         }
     }
     // Delete all files in the curent directory return false and halt if a file cannot be removed
     for ($i = 0; $i < count($dir_files); $i++) {
         chmod($dir_files[$i], $CFG->directorypermissions);
         if (unlink($dir_files[$i]) == false) {
             return false;
         }
     }
     // Empty sub directories and then remove the directory
     for ($i = 0; $i < count($dir_subdirs); $i++) {
         chmod($dir_subdirs[$i], $CFG->directorypermissions);
         if (self::delete_dir_contents($dir_subdirs[$i], '', $progress) == false) {
             return false;
         } else {
             if (remove_dir($dir_subdirs[$i]) == false) {
                 return false;
             }
         }
     }
     // Close directory
     closedir($handle);
     // Success, every thing is gone return true
     return true;
 }
Ejemplo n.º 3
0
 /**
  * Appropriate instance depending if we want html output for the user or not.
  *
  * @return \core\progress\base child of \core\progress\base to handle the display (or not) of task progress.
  */
 protected function get_progress_trace_instance()
 {
     if ($this->progress === null) {
         if (!$this->table->is_downloading()) {
             $this->progress = new \core\progress\display_if_slow(get_string('calculatingallstats', 'quiz_statistics'));
             $this->progress->set_display_names();
         } else {
             $this->progress = new \core\progress\none();
         }
     }
     return $this->progress;
 }
 /**
  * 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();
 }
Ejemplo n.º 6
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;
 }
Ejemplo n.º 7
0
 /**
  * Update all documents for ousearch.
  *
  * If specified, the progress object should be ready to receive indeterminate
  * progress calls.
  *
  * @param bool $feedback If true, prints feedback as HTML list items
  * @param int $courseid If specified, restricts to particular courseid
  * @param int $cmid If specified, restricts to particular cmid
  * @param \core\progress\base $progress Set to a progress object or null
  */
 public static function search_update_all($feedback = false, $courseid = 0, $cmid = 0, \core\progress\base $progress = null)
 {
     global $DB;
     raise_memory_limit(MEMORY_EXTRA);
     // If cmid is specified, only retrieve that one
     if ($cmid) {
         $cmrestrict = "cm.id = ? AND";
         $cmrestrictparams = array($cmid);
     } else {
         $cmrestrict = '';
         $cmrestrictparams = array();
     }
     // Get module-instances that need updating
     $cms = $DB->get_records_sql("\nSELECT\n    cm.id, cm.course, cm.instance, f.name\nFROM\n    {forumng} f\n    INNER JOIN {course_modules} cm ON cm.instance = f.id\nWHERE\n    {$cmrestrict}\n    cm.module = (SELECT id FROM {modules} m WHERE name = 'forumng')" . ($courseid ? " AND f.course = ?" : ''), array_merge($cmrestrictparams, $courseid ? array($courseid) : array()));
     // Print count
     if ($feedback && !$cmid) {
         print '<li>' . get_string('search_update_count', 'forumng', '<strong>' . count($cms) . '</strong>') . '</li>';
     }
     // This can take a while, so let's be sure to have a long time limit.
     $timelimitbefore = 300;
     // Loop around updating
     foreach ($cms as $cm) {
         $transaction = $DB->start_delegated_transaction();
         // Wipe existing search data, if any
         local_ousearch_document::delete_module_instance_data($cm);
         // Get all discussions for this forum
         $discussions = $DB->get_records('forumng_discussions', array('forumngid' => $cm->instance), '', 'id, postid');
         if ($feedback) {
             print '<li><strong>' . $cm->name . '</strong> (' . count($discussions) . '):';
         }
         // Process each discussion
         foreach ($discussions as $discussionrec) {
             // Ignore discussion with no postid
             // (This should not happen, where ther is a $discussionrec->id
             // it also shopuld have a $discussionrec->postid. This if-statement
             // fixes bug 10497 and would not have any side-effect.)
             if (!$discussionrec->postid) {
                 continue;
             }
             set_time_limit($timelimitbefore);
             $discussion = mod_forumng_discussion::get_from_id($discussionrec->id, self::CLONE_DIRECT, -1);
             $root = $discussion->get_root_post();
             $root->search_update();
             $root->search_update_children();
             $root = null;
             if ($feedback) {
                 echo '. ';
                 flush();
             }
             if ($progress) {
                 $progress->progress(\core\progress\base::INDETERMINATE);
             }
         }
         $transaction->allow_commit();
         if ($feedback) {
             print '</li>';
         }
     }
 }