/** * Run scheduled tasks according to a cron spec. */ function elis_cron() { global $CFG; require $CFG->dirroot . '/elis/core/lib/tasklib.php'; $timenow = time(); // get all tasks that are (over-)due $tasks = get_recordset_select('elis_scheduled_tasks', 'nextruntime <= ' . $timenow, 'nextruntime ASC'); if (empty($tasks)) { return; } while ($task = rs_fetch_next_record($tasks)) { $starttime = microtime(); mtrace("Running {$task->callfunction}({$task->taskname}) from {$task->plugin}..."); if ($task->enddate !== null && $task->enddate < $timenow) { mtrace('* Cancelling task: past end date'); delete_records('elis_scheduled_tasks', 'id', $task->id); continue; } // FIXME: check for blocking tasks // FIXME: check if task is locked // See if some other cron has already run the function while we were // doing something else -- if so, skip it. $nextrun = get_field('elis_scheduled_tasks', 'nextruntime', 'id', $task->id); if ($nextrun > $timenow) { mtrace('* Skipped (someone else already ran it)'); continue; } // calculate the next run time $newtask = new stdClass(); $newtask->id = $task->id; $newtask->lastruntime = time(); $newtask->nextruntime = cron_next_run_time($newtask->lastruntime, (array) $task); // see if we have any runs left if ($task->runsremaining !== null) { $newtask->runsremaining = $task->runsremaining - 1; if ($newtask->runsremaining <= 0) { mtrace('* Cancelling task: no runs left'); delete_records('elis_scheduled_tasks', 'id', $task->id); } else { update_record('elis_scheduled_tasks', $newtask); } } else { update_record('elis_scheduled_tasks', $newtask); } // load the file and call the function if ($task->callfile) { $callfile = $CFG->dirroot . $task->callfile; if (!is_readable($callfile)) { mtrace('* Skipped (file not found)'); continue; } require_once $callfile; } call_user_func(unserialize($task->callfunction), $task->taskname); $difftime = microtime_diff($starttime, microtime()); mtrace("* {$difftime} seconds"); } }
function add_selection_all($ufiltering) { global $SESSION; $guest = get_guest(); $sqlwhere = $ufiltering->get_sql_filter("id<>{$guest->id} AND deleted <> 1"); if ($rs = get_recordset_select('user', $sqlwhere, 'fullname', 'id,' . sql_fullname() . ' AS fullname')) { while ($user = rs_fetch_next_record($rs)) { if (!isset($SESSION->bulk_users[$user->id])) { $SESSION->bulk_users[$user->id] = $user->id; } } rs_close($rs); } }
/** * Retrieves a list of note objects with specific atributes. * * @param int $courseid id of the course in which the notes were posted (0 means any) * @param int $userid id of the user to which the notes refer (0 means any) * @param string $state state of the notes (i.e. draft, public, site) ('' means any) * @param int $author id of the user who modified the note last time (0 means any) * @param string $order an order to sort the results in * @param int $limitfrom number of records to skip (offset) * @param int $limitnum number of records to fetch * @return array of note objects */ function note_list($courseid = 0, $userid = 0, $state = '', $author = 0, $order = 'lastmodified DESC', $limitfrom = 0, $limitnum = 0) { // setup filters $selects = array(); if ($courseid) { $selects[] = 'courseid=' . $courseid; } if ($userid) { $selects[] = 'userid=' . $userid; } if ($author) { $selects[] = 'usermodified=' . $author; } if ($state) { $selects[] = "publishstate='{$state}'"; } $selects[] = "module='notes'"; $select = implode(' AND ', $selects); $fields = 'id,courseid,userid,content,format,created,lastmodified,usermodified,publishstate'; // retrieve data $rs =& get_recordset_select('post', $select, $order, $fields, $limitfrom, $limitnum); return recordset_to_array($rs); }
function bulkexport_submit(Pieform $form, $values) { global $SESSION; $usernames = array(); // Read in the usernames explicitly specified foreach (explode("\n", $values['usernames']) as $username) { $username = trim($username); if (!empty($username)) { $usernames[] = $username; } } if (empty($usernames) and !empty($values['authinstance'])) { // Export all users from the selected institution $rs = get_recordset_select('usr', 'authinstance = ? AND deleted = 0', array($values['authinstance']), '', 'username'); while ($record = $rs->FetchRow()) { $usernames[] = $record['username']; } } $SESSION->set('exportdata', $usernames); $smarty = smarty(); $smarty->assign('heading', ''); $smarty->display('admin/users/bulkdownload.tpl'); exit; }
* @param string $folio_control_page_edit_security_custom The custom level of security for the page. **/ // Note, this is ../ insead of ../../../ because we're called by files in /_folio, and not from the folder that this // page is actually residing inside of. require_once '../includes.php'; $security_ident = -1; // Load variables $page_ident = required_param('page_ident', PARAM_INT); $security_type = optional_param('folio_control_page_edit_security_type', '-1'); $security_parent = optional_param('folio_control_page_edit_security_parent', -1, PARAM_INT); $security_custom = optional_param('folio_control_page_edit_security_custom', '-1'); // Test to see if we're logged in. if (!isloggedin()) { // Since the user isn't logged in, don't allow them to change the security settings for the page. // Get the previous copy's information. $pages = recordset_to_array(get_recordset_select('folio_page', "page_ident = {$page_ident} and newest= 1", null, 'title', '*')); if (!$pages[$page_ident]) { // Not found. error(' Unable to retrieve old record in folio_actions on line 46 for page ' . $page_ident . '. You may have tried to create a new page without logging in.' . ' Please log in and try again.'); } else { $security_ident = $pages[$page_ident]->security_ident; } } else { // Since we're logged in, allow user to set permissions. // Check to see if we're inheriting. if ($security_type == 'Parent') { // Inheriting $security_ident = $security_parent; } else { // Set to a custom security level. We'll need to insert/update the security record. $security_ident = $page_ident;
/** * Rebuilds the cached list of course activities stored in the database * @param int $courseid - id of course to rebuil, empty means all * @param boolean $clearonly - only clear the modinfo fields, gets rebuild automatically on the fly */ function rebuild_course_cache($courseid = 0, $clearonly = false) { global $COURSE; if ($clearonly) { $courseselect = empty($courseid) ? "" : "id = {$courseid}"; set_field_select('course', 'modinfo', null, $courseselect); // update cached global COURSE too ;-) if ($courseid == $COURSE->id) { $COURSE->modinfo = null; } // reset the fast modinfo cache $reset = 'reset'; get_fast_modinfo($reset); return; } if ($courseid) { $select = "id = '{$courseid}'"; } else { $select = ""; @set_time_limit(0); // this could take a while! MDL-10954 } if ($rs = get_recordset_select("course", $select, '', 'id,fullname')) { while ($course = rs_fetch_next_record($rs)) { $modinfo = serialize(get_array_of_activities($course->id)); if (!set_field("course", "modinfo", $modinfo, "id", $course->id)) { notify("Could not cache module information for course '" . format_string($course->fullname) . "'!"); } // update cached global COURSE too ;-) if ($course->id == $COURSE->id) { $COURSE->modinfo = $modinfo; } } rs_close($rs); } // reset the fast modinfo cache $reset = 'reset'; get_fast_modinfo($reset); }
/** * Process a chunk of the task * * @param array $state the task state */ function user_activity_task_process(&$state) { global $CFG; $sessiontimeout = $state['sessiontimeout']; $sessiontail = $state['sessiontail']; $starttime = $state['starttime']; // find the record ID corresponding to our start time $startrec = get_field_select('log', 'MIN(id)', "time >= {$starttime}"); $startrec = empty($startrec) ? 0 : $startrec; // find the last record that's close to our chunk size, without // splitting a second between runs $endtime = get_field_select('log', 'MIN(time)', 'id >= ' . ($startrec + USERACT_RECORD_CHUNK)); if (!$endtime) { $endtime = time(); } // Get the logs between the last time we ran, and the current time. Sort // by userid (so all records for a given user are together), and then by // time (so that we process a user's logs sequentially). $recstarttime = max(0, $starttime - $state['sessiontimeout']); $rs = get_recordset_select('log', "time >= {$recstarttime} AND time < {$endtime} AND userid != 0", 'userid, time'); if ($CFG->debug >= DEBUG_ALL) { mtrace("* processing records from time:{$starttime} to time:{$endtime}"); } $curuser = -1; $session_start = 0; $last_course = -1; $module_session_start = 0; $last_module = -1; $last_time = 0; if ($rs) { while ($rec = rs_fetch_next_record($rs)) { if ($rec->userid != $curuser) { // end of user's record if ($curuser > 0 && $session_start > 0) { // flush current session data if ($last_time > $endtime - $sessiontimeout) { /* Last record is within the session timeout of our end * time for this run. Just use our last logged time as * the session end time, and the rest will be picked up * by the next run of the sessionizer. */ $session_end = $last_time; } else { /* Last record is not within the session timeout of our * end time for this run, so do our normal session * ending. */ $session_end = $last_time + $sessiontail; } user_activity_add_session($curuser, $last_course, $session_start, $session_end); if ($last_module > 0) { user_module_activity_add_session($curuser, $last_course, $last_module, $module_session_start, $session_end); } } $curuser = $rec->userid; $session_start = 0; $last_course = -1; $module_session_start = 0; $last_module = -1; $last_time = 0; } if ($rec->time < $starttime) { // Find the last log for the user before our start time, that's // within the session timeout, and start the session with that // record. $session_start = $rec->time; $last_time = $rec->time; $last_course = $rec->course; $module_session_start = $rec->time; $last_module = $rec->cmid; } elseif ($rec->time > $last_time + $sessiontimeout) { if ($last_course >= 0) { // session timed out -- add record if (defined('ETLUA_EXTRA_DEBUG') && $CFG->debug >= DEBUG_DEVELOPER) { mtrace('** session timed out'); } $session_end = $last_time + $sessiontail; user_activity_add_session($curuser, $last_course, $session_start, $session_end); if ($last_module > 0) { user_module_activity_add_session($curuser, $last_course, $last_module, $module_session_start, $session_end); } } // start a new session with the current record $session_start = $rec->time; $last_course = $rec->course; $module_session_start = $rec->time; $last_module = $rec->cmid; } elseif ($rec->action === 'logout') { // user logged out -- add record if (defined('ETLUA_EXTRA_DEBUG') && $CFG->debug >= DEBUG_DEVELOPER) { mtrace('** user logged out'); } $session_end = $rec->time; user_activity_add_session($curuser, $last_course, $session_start, $session_end); if ($last_module > 0) { user_module_activity_add_session($curuser, $last_course, $last_module, $module_session_start, $session_end); } // clear session info $session_start = 0; $module_session_start = 0; } elseif ($rec->course != $last_course) { // user switched to a different course -- start new session record if ($last_course >= 0) { if (defined('ETLUA_EXTRA_DEBUG') && $CFG->debug >= DEBUG_DEVELOPER) { mtrace('** user switched courses'); } $session_end = $rec->time; user_activity_add_session($curuser, $last_course, $session_start, $session_end); if ($last_module > 0) { user_module_activity_add_session($curuser, $last_course, $last_module, $module_session_start, $session_end); } } $session_start = $rec->time; $last_course = $rec->course; $module_session_start = $rec->time; $last_module = $rec->cmid; } elseif ($rec->cmid != $last_module) { // user switched to a different module -- start new module session if ($last_module > 0) { if (defined('ETLUA_EXTRA_DEBUG') && $CFG->debug >= DEBUG_DEVELOPER) { mtrace('** user switched modules'); } $session_end = $rec->time; user_module_activity_add_session($curuser, $last_course, $last_module, $module_session_start, $session_end); } $module_session_start = $rec->time; $last_module = $rec->cmid; } $last_time = $rec->time; } } if ($curuser > 0 && $session_start > 0) { // flush session data if ($last_time > $endtime - $sessiontimeout) { $session_end = $last_time; } else { $session_end = $last_time + $sessiontail; } user_activity_add_session($curuser, $last_course, $session_start, $session_end); } $state['starttime'] = $endtime; $endrec = get_field_select('log', 'MAX(id)', "time < {$endtime}"); // possibly skip the last time when calculating the total number of // records, since we are purposely skipping anything less than $endtime $lasttime = get_field_select('log', 'MAX(time)', 'TRUE'); $totalrec = get_field_select('log', 'MAX(id)', "time < {$lasttime}"); $totalrec = max($totalrec, $endrec); return array($endrec ? $endrec - $state['startrec'] : 0, $totalrec ? $totalrec - $state['startrec'] : 0); }
/** * Factory method - uses the parameters to retrieve all matching instances from the DB. * @static final protected * @return mixed array of object instances or false if not found */ function fetch_all_helper($table, $classname, $params) { $instance = new $classname(); $classvars = (array) $instance; $params = (array) $params; $wheresql = array(); // remove incorrect params foreach ($params as $var => $value) { if (!in_array($var, $instance->required_fields) and !array_key_exists($var, $instance->optional_fields)) { continue; } if (is_null($value)) { $wheresql[] = " {$var} IS NULL "; } else { $value = addslashes($value); $wheresql[] = " {$var} = '{$value}' "; } } if (empty($wheresql)) { $wheresql = ''; } else { $wheresql = implode("AND", $wheresql); } if ($rs = get_recordset_select($table, $wheresql, 'id')) { $result = array(); while ($data = rs_fetch_next_record($rs)) { $instance = new $classname(); grade_object::set_properties($instance, $data); $result[$instance->id] = $instance; } rs_close($rs); return $result; } else { return false; } }
function get_submission($userid = 0, $createnew = false, $teachermodified = false) { global $CFG; $submission = parent::get_submission($userid, $createnew, $teachermodified); if ($submission) { $onlinejudge = get_record('assignment_oj_submissions', 'submission', $submission->id); if (empty($onlinejudge) && $createnew) { $newsubmission = new Object(); $newsubmission->submission = $submission->id; if (!insert_record("assignment_oj_submissions", $newsubmission)) { error("Could not insert a new empty onlinejudge submission"); } unset($newsubmission); } $onlinejudge = get_record('assignment_oj_submissions', 'submission', $submission->id); if ($onlinejudge) { $submission->judged = $onlinejudge->judged; $submission->oj_id = $onlinejudge->id; } else { $submission->judged = 0; } if ($submission->judged) { $results = get_recordset_select('assignment_oj_results', 'submission = ' . $submission->id . ' AND judgetime >= ' . $submission->timemodified, 'judgetime DESC', '*', '', '1'); $results = recordset_to_array($results); if ($results) { $result = array_pop($results); $submission->info = $result->info; $submission->status = $result->status; $submission->judgetime = $result->judgetime; $submission->output = $result->output; } else { $submission->judged = 0; //It is been judging $submission->status = 'pending'; } } else { if (($files = get_directory_list($CFG->dataroot . '/' . $this->file_area_name($userid))) && count($files) != 0) { // Submitted but unjudged $submission->status = 'pending'; } } } return $submission; }
/** * Performs the necessary calculations on the grades_final referenced by this grade_item. * Also resets the needsupdate flag once successfully performed. * * This function must be used ONLY from lib/gradeslib.php/grade_regrade_final_grades(), * because the regrading must be done in correct order!! * * @return boolean true if ok, error string otherwise */ function regrade_final_grades($userid = null) { global $CFG; // locked grade items already have correct final grades if ($this->is_locked()) { return true; } // calculation produces final value using formula from other final values if ($this->is_calculated()) { if ($this->compute($userid)) { return true; } else { return "Could not calculate grades for grade item"; // TODO: improve and localize } // noncalculated outcomes already have final values - raw grades not used } else { if ($this->is_outcome_item()) { return true; // aggregate the category grade } else { if ($this->is_category_item() or $this->is_course_item()) { // aggregate category grade item $category = $this->get_item_category(); $category->grade_item =& $this; if ($category->generate_grades($userid)) { return true; } else { return "Could not aggregate final grades for category:" . $this->id; // TODO: improve and localize } } else { if ($this->is_manual_item()) { // manual items track only final grades, no raw grades return true; } else { if (!$this->is_raw_used()) { // hmm - raw grades are not used- nothing to regrade return true; } } } } } // normal grade item - just new final grades $result = true; $grade_inst = new grade_grade(); $fields = implode(',', $grade_inst->required_fields); if ($userid) { $rs = get_recordset_select('grade_grades', "itemid={$this->id} AND userid={$userid}", '', $fields); } else { $rs = get_recordset('grade_grades', 'itemid', $this->id, '', $fields); } if ($rs) { while ($grade_record = rs_fetch_next_record($rs)) { $grade = new grade_grade($grade_record, false); if (!empty($grade_record->locked) or !empty($grade_record->overridden)) { // this grade is locked - final grade must be ok continue; } $grade->finalgrade = $this->adjust_raw_grade($grade->rawgrade, $grade->rawgrademin, $grade->rawgrademax); if (grade_floats_different($grade_record->finalgrade, $grade->finalgrade)) { if (!$grade->update('system')) { $result = "Internal error updating final grade"; } } } rs_close($rs); } return $result; }
/** * Gets the default category in the most specific context. * If no categories exist yet then default ones are created in all contexts. * * @param array $contexts The context objects for this context and all parent contexts. * @return object The default category - the category in the course context */ function question_make_default_categories($contexts) { $toreturn = null; // If it already exists, just return it. foreach ($contexts as $key => $context) { if (!($categoryrs = get_recordset_select("question_categories", "contextid = '{$context->id}'", 'sortorder, name', '*', '', 1))) { error('error getting category record'); } else { if (!($category = rs_fetch_record($categoryrs))) { // Otherwise, we need to make one $category = new stdClass(); $contextname = print_context_name($context, false, true); $category->name = addslashes(get_string('defaultfor', 'question', $contextname)); $category->info = addslashes(get_string('defaultinfofor', 'question', $contextname)); $category->contextid = $context->id; $category->parent = 0; $category->sortorder = 999; // By default, all categories get this number, and are sorted alphabetically. $category->stamp = make_unique_id_code(); if (!($category->id = insert_record('question_categories', $category))) { error('Error creating a default category for context ' . print_context_name($context)); } } } if ($context->contextlevel == CONTEXT_COURSE) { $toreturn = clone $category; } } return $toreturn; }
$lasttime = optional_param('lasttime', 0, PARAM_INT); $CFG->limitviewentries = !isset($CFG->limitviewentries) || empty($CFG->limitviewentries) ? 600 : 6 * $CFG->limitviewentries; //add_to_log(1, 1, "filter: $filter, lasttime: $lasttime", true); //debug mode // check for the lastes entries in the log $where = "id > '{$lasttime}'"; if ($filter != '') { $where .= " AND ip = '{$filter}'"; } if (!($count = count_records_select('log', $where))) { $return = '{"response":""}'; //add_to_log(1, 1, $return, true); //debug mode echo $return; die; } $count = $count > $CFG->limitviewentries ? $count - $CFG->limitviewentries : 0; if (!($entries = get_recordset_select('log', $where, 'time ASC', '*', $count, $CFG->limitviewentries))) { $return = '{"response":"KO"}'; //add_to_log(1, 1, $return, true); //debug mode echo $return; die; } if (!($entries = recordset_to_array($entries))) { $return = '{"response":""}'; //add_to_log(1, 1, $return, true); //debug mode echo $return; die; } /// set return entries in json format {"response":[{"ip":"","time":"","smarttime":"","category":"","info":""}]} $return = '{"response":['; foreach ($entries as $entri) { /// search for category names
/** * Gets the list of categories for the user or for the group * @param $groupid Id of the group for which we need the categories'list. If 0 or NULL, then get the list of categories of the user */ function fm_get_cat_list($groupid = 0) { global $USER; // $cats = array(); $cats[0] = get_string('btnnoassigncat', 'block_file_manager'); if ($groupid == 0) { $ownertype = OWNERISUSER; $rs = get_recordset_select('fmanager_categories', "owner={$USER->id} AND ownertype={$ownertype}", 'name'); $catsrec = recordset_to_array($rs); } else { $ownertype = OWNERISGROUP; $rs = get_recordset_select('fmanager_categories', "owner={$groupid} AND ownertype={$ownertype}", 'name'); $catsrec = recordset_to_array($rs); } if ($catsrec) { foreach ($catsrec as $c) { $cats[$c->id] = $c->name; } } return $cats; }
* script for bulk user delete operations */ require_once '../../config.php'; require_once $CFG->libdir . '/adminlib.php'; $confirm = optional_param('confirm', 0, PARAM_BOOL); admin_externalpage_setup('userbulk'); require_capability('moodle/user:update', get_context_instance(CONTEXT_SYSTEM)); $return = $CFG->wwwroot . '/' . $CFG->admin . '/user/user_bulk.php'; if (empty($SESSION->bulk_users)) { redirect($return); } admin_externalpage_print_header(); //TODO: add support for large number of users if ($confirm and confirm_sesskey()) { $in = implode(',', $SESSION->bulk_users); if ($rs = get_recordset_select('user', "id IN ({$in})", '', 'id, username, secret, confirmed, auth, firstname, lastname')) { while ($user = rs_fetch_next_record($rs)) { if ($user->confirmed) { continue; } $auth = get_auth_plugin($user->auth); $result = $auth->user_confirm(addslashes($user->username), addslashes($user->secret)); if ($result != AUTH_CONFIRM_OK && $result != AUTH_CONFIRM_ALREADY) { notify(get_string('usernotconfirmed', '', fullname($user, true))); } } rs_close($rs); } redirect($return, get_string('changessaved')); } else { $in = implode(',', $SESSION->bulk_users);
/** * Update grades for this class * * @param array The class grades */ function update_all_class_grades($classgrades = array()) { global $CURMAN; if (isset($this->course) && get_class($this->course) == 'course') { $elements = $this->course->get_completion_elements(); } else { $elements = false; } $timenow = time(); if (!empty($elements)) { // for each student, find out how many required completion elements are // incomplete, and when the last completion element was graded $sql = "SELECT s.*, grades.incomplete, grades.maxtime\n FROM {$CURMAN->db->prefix_table(STUTABLE)} s\n JOIN (SELECT s.userid, COUNT(CASE WHEN grades.id IS NULL AND cc.required = 1 THEN 1\n ELSE NULL END) AS incomplete,\n MAX(timegraded) AS maxtime\n FROM {$CURMAN->db->prefix_table(STUTABLE)} s\n JOIN {$CURMAN->db->prefix_table(CRSCOMPTABLE)} cc\n ON cc.courseid = {$this->courseid}\n LEFT JOIN {$CURMAN->db->prefix_table(CLSGRTABLE)} grades\n ON grades.userid = s.userid\n AND grades.completionid = cc.id\n AND grades.classid = {$this->id}\n AND grades.grade >= cc.completion_grade\n WHERE s.classid = {$this->id} AND s.locked = 0\n GROUP BY s.userid\n ) grades ON grades.userid = s.userid\n WHERE s.classid = {$this->id} AND s.locked = 0"; $rs = get_recordset_sql($sql); if ($rs) { while ($rec = rs_fetch_next_record($rs)) { if ($rec->incomplete == 0 && $rec->grade > 0 && $rec->grade >= $this->course->completion_grade) { $student = new student($rec, $this, null); $student->completestatusid = STUSTATUS_PASSED; $student->completetime = $rec->maxtime; $student->credits = $this->course->credits; $student->locked = 1; $student->complete(); } } } } else { /// We have no completion elements so just make sure the user's grade is at least the /// minimum value required for the course. /// Get all unlocked enrolments $select = "classid = {$this->id} AND locked = 0"; $rs = get_recordset_select(STUTABLE, $select, 'userid'); if ($rs) { while ($rec = rs_fetch_next_record($rs)) { if ($rec->grade > 0 && $rec->grade >= $this->course->completion_grade) { $student = new student($rec, $this, null); $student->completestatusid = STUSTATUS_PASSED; $student->completetime = $timenow; $student->credits = $this->course->credits; $student->locked = 1; $student->complete(); } } } } }
/** * Adds groups and group assignments at the site-level either globally * or for a particular cluster * * @param int $clusterid The particular cluster's id, or zero for all */ function cluster_groups_update_site_course($clusterid = 0, $add_members = false, $userid = 0) { global $CFG, $CURMAN; //make sure this functionality is even enabled if (!empty($CURMAN->config->site_course_cluster_groups)) { $select_parts = array(); $cluster_select = ''; if (!empty($clusterid)) { $select_parts[] = "(clst.id = {$clusterid})"; } if (!empty($userid)) { $select_parts[] = "(mdluser.id = {$userid})"; } $select = empty($select_parts) ? '' : 'WHERE ' . implode('AND', $select_parts); $siteid = SITEID; //query to get clusters, groups, and possibly users $sql = "SELECT grp.id AS groupid, clst.id AS clusterid, clst.name AS clustername, mdluser.id AS userid FROM\n {$CURMAN->db->prefix_table(CLSTTABLE)} clst\n LEFT JOIN {$CURMAN->db->prefix_table('groups')} grp\n ON clst.name = grp.name\n AND grp.courseid = {$siteid}\n LEFT JOIN\n ({$CURMAN->db->prefix_table(CLSTUSERTABLE)} usrclst\n JOIN {$CURMAN->db->prefix_table(USRTABLE)} crlmuser\n ON usrclst.userid = crlmuser.id\n JOIN {$CURMAN->db->prefix_table('user')} mdluser\n ON crlmuser.idnumber = mdluser.idnumber)\n ON clst.id = usrclst.clusterid\n {$select}\n ORDER BY clst.id"; if ($recordset = get_recordset_sql($sql)) { $last_clusterid = 0; $last_group_id = 0; while ($record = rs_fetch_next_record($recordset)) { if ($last_clusterid != $record->clusterid) { $last_group_id = $record->groupid; } if (cluster_groups_cluster_allows_groups($record->clusterid)) { //handle group record if (empty($record->groupid) && (empty($last_clusterid) || $last_clusterid !== $record->clusterid)) { //create group $group = new stdClass(); $group->courseid = SITEID; $group->name = addslashes($record->clustername); $group->id = groups_create_group($group); $last_group_id = $group->id; } //handle adding members if ($add_members && !empty($last_group_id) && !empty($record->userid)) { cluster_groups_add_member($last_group_id, $record->userid); } //set up groupings if (empty($last_clusterid) || $last_clusterid !== $record->clusterid) { cluster_groups_grouping_helper($record->clusterid, $record->clustername); } } $last_clusterid = $record->clusterid; } } } if (!empty($CFG->enablegroupings) && !empty($CURMAN->config->cluster_groupings)) { //query condition $select = '1 = 1'; if (!empty($clusterid)) { $select = "id = {$clusterid}"; } //go through all appropriate clusters if ($recordset = get_recordset_select(CLSTTABLE, $select)) { while ($record = rs_fetch_next_record($recordset)) { //set up groupings cluster_groups_grouping_helper($record->id, $record->name); } } } return true; }
function bulkexport_submit(Pieform $form, $values) { global $SESSION; $usernames = array(); // Read in the usernames explicitly specified foreach (explode("\n", $values['usernames']) as $username) { $username = trim($username); if (!empty($username)) { $usernames[] = $username; } } if (empty($usernames) and !empty($values['authinstance'])) { // Export all users from the selected institution $rs = get_recordset_select('usr', 'authinstance = ? AND deleted = 0', array($values['authinstance']), '', 'username'); while ($record = $rs->FetchRow()) { $usernames[] = $record['username']; } } safe_require('export', 'leap'); $listing = array(); $files = array(); $exportcount = 0; $exporterrors = array(); $num_users = count($usernames); foreach ($usernames as $username) { if (!($exportcount % 25)) { set_progress_info('bulkexport', $exportcount, $num_users, get_string('validating', 'admin')); } $user = new User(); try { $user->find_by_username($username); } catch (AuthUnknownUserException $e) { continue; // Skip non-existent users } $exporter = new PluginExportLeap($user, PluginExport::EXPORT_ALL_VIEWS_COLLECTIONS, PluginExport::EXPORT_ALL_ARTEFACTS); try { $zipfile = $exporter->export(); } catch (Exception $e) { $exporterrors[] = $username; continue; } $listing[] = array($username, $zipfile); $files[] = $exporter->get('exportdir') . $zipfile; $exportcount++; } if (!($zipfile = create_zipfile($listing, $files))) { export_iframe_die(get_string('bulkexportempty', 'admin')); } log_info("Exported {$exportcount} users to {$zipfile}"); if (!empty($exporterrors)) { $SESSION->add_error_msg(get_string('couldnotexportusers', 'admin', implode(', ', $exporterrors))); } // Store the filename in the session, and redirect the iframe to it to trigger // the download. Here it would be nice to trigger the download for everyone, // but alas this is not possible for people without javascript. $SESSION->set('exportfile', $zipfile); set_progress_done('bulkexport', array('redirect' => get_config('wwwroot') . 'admin/users/bulkexport.php')); // Download the export file once it has been generated require_once 'file.php'; serve_file($zipfile, basename($zipfile), 'application/x-zip', array('lifetime' => 0, 'forcedownload' => true)); // TODO: delete the zipfile (and temporary files) once it's been downloaded }
/** * Unsets marked preferences * * @param $to_delete array Array of preference key prefixes * @param $temporary boolean If true, unset from temporary preferences, otherwise unset from * persistent preferences */ function php_report_filtering_unset_invalid_user_preferences($to_delete, $temporary) { global $SESSION; if ($temporary) { //delete temporary preferences that are not valid if (!empty($to_delete) && !empty($SESSION->php_report_default_params)) { foreach ($to_delete as $item) { foreach ($SESSION->php_report_default_params as $key => $value) { //prefix matches, so clear if ($key == $item || strpos($key, $item . '_') === 0) { unset($SESSION->php_report_default_params[$key]); } } } } } else { //delete persistent preferences that are not valid if (!empty($to_delete)) { $conditions = array(); //set up conditions for any valid prefix-matching foreach ($to_delete as $item) { $conditions[] = "name = '{$item}'"; $conditions[] = 'name ' . sql_ilike() . " '{$item}_%'"; } //try to be efficient in cases with a lot of data $where = implode(' OR ', $conditions); if ($recordset = get_recordset_select('user_preferences', $where)) { while ($record = rs_fetch_next_record($recordset)) { //user proper API function to handle stored session info unset_user_preference($record->name); } } } } }
*/ require_once '../../config.php'; require_once $CFG->libdir . '/adminlib.php'; $confirm = optional_param('confirm', 0, PARAM_BOOL); admin_externalpage_setup('userbulk'); require_capability('moodle/user:delete', get_context_instance(CONTEXT_SYSTEM)); $return = $CFG->wwwroot . '/' . $CFG->admin . '/user/user_bulk.php'; if (empty($SESSION->bulk_users)) { redirect($return); } admin_externalpage_print_header(); //TODO: add support for large number of users if ($confirm and confirm_sesskey()) { $primaryadmin = get_admin(); $in = implode(',', $SESSION->bulk_users); if ($rs = get_recordset_select('user', "id IN ({$in})")) { while ($user = rs_fetch_next_record($rs)) { if ($primaryadmin->id != $user->id and $USER->id != $user->id and delete_user($user)) { unset($SESSION->bulk_users[$user->id]); } else { notify(get_string('deletednot', '', fullname($user, true))); } } rs_close($rs); } redirect($return, get_string('changessaved')); } else { $in = implode(',', $SESSION->bulk_users); $userlist = get_records_select_menu('user', "id IN ({$in})", 'fullname', 'id,' . sql_fullname() . ' AS fullname'); $usernames = implode(', ', $userlist); $optionsyes = array();
/** * Calculates a new label for a copy of an existing PHP report schedule * based on the existing schedule's name * * @param string $parent_label The label from the original schedule instance * * @return string The label for the new schedule instance */ function block_php_report_get_copy_label($parent_label) { //first guess at to our copy number $i = 1; $done = false; while (!$done) { //get the proposed label $a = new stdClass(); $a->label = $parent_label; $a->index = $i; $label = get_string('task_copy_label', 'block_php_report', $a); //look for records containing the proposed namy anywhere in their config data //(may include false-positives but very unlikely) if ($records = get_recordset_select('php_report_schedule', 'config ' . sql_ilike() . " '%{$label}%'")) { //track whether an exact match was found $found = false; //go through all possible matches while ($record = rs_fetch_next_record($records)) { //perform an exact comparison $config = unserialize($record->config); if ($config['label'] == $label) { //exact match $found = true; break; } } if (!$found) { //all cases were false, positive, so accept $done = true; } else { //exact match, so increment and try again $i++; } } else { //no config contained the proposed label, so accept $done = true; } } return $label; }
/** * Get the first two columns from a number of records as an associative array. * * Arguments as for @see function get_recordset_select. * Return value as for @see function get_records_menu. * * @param string $table The database table to be checked against. * @param string $select A fragment of SQL to be used in a where clause in the SQL call. * @param string $sort Sort order (optional) - a valid SQL order parameter * @param string $fields A comma separated list of fields to be returned from the chosen table. * @return mixed an associative array, or false if no records were found or an error occured. */ function get_records_select_menu($table, $select = '', $values = null, $sort = '', $fields = '*') { $rs = get_recordset_select($table, $select, $values, $sort, $fields); return recordset_to_menu($rs); }
/** * Gets the default category in the most specific context. * If no categories exist yet then default ones are created in all contexts. * * @param array $contexts The context objects for this context and all parent contexts. * @return object The default category - the category in the course context */ function question_make_default_categories($contexts) { static $preferredlevels = array(CONTEXT_COURSE => 4, CONTEXT_MODULE => 3, CONTEXT_COURSECAT => 2, CONTEXT_SYSTEM => 1); $toreturn = null; $preferredness = 0; // If it already exists, just return it. foreach ($contexts as $key => $context) { if (!($categoryrs = get_recordset_select("question_categories", "contextid = '{$context->id}'", 'sortorder, name', '*', '', 1))) { error('error getting category record'); } else { if (!($category = rs_fetch_record($categoryrs))) { // Otherwise, we need to make one $category = new stdClass(); $contextname = print_context_name($context, false, true); $category->name = addslashes(get_string('defaultfor', 'question', $contextname)); $category->info = addslashes(get_string('defaultinfofor', 'question', $contextname)); $category->contextid = $context->id; $category->parent = 0; $category->sortorder = 999; // By default, all categories get this number, and are sorted alphabetically. $category->stamp = make_unique_id_code(); if (!($category->id = insert_record('question_categories', $category))) { error('Error creating a default category for context ' . print_context_name($context)); } } } if ($preferredlevels[$context->contextlevel] > $preferredness && has_any_capability(array('moodle/question:usemine', 'moodle/question:useall'), $context)) { $toreturn = $category; $preferredness = $preferredlevels[$context->contextlevel]; } } if (!is_null($toreturn)) { $toreturn = clone $toreturn; } return $toreturn; }
/** * Get the first two columns from a number of records as an associative array. * * Arguments as for @see function get_recordset_select. * Return value as for @see function get_records_menu. * * @param string $table The database table to be checked against. * @param string $select A fragment of SQL to be used in a where clause in the SQL call. * @param string $sort Sort order (optional) - a valid SQL order parameter * @param string $fields A comma separated list of fields to be returned from the chosen table. * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set). * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set). * @return mixed an associative array, or false if no records were found or an error occured. */ function get_records_select_menu($table, $select = '', $sort = '', $fields = '*', $limitfrom = '', $limitnum = '') { $rs = get_recordset_select($table, $select, $sort, $fields, $limitfrom, $limitnum); return recordset_to_menu($rs); }
public function update() { $result = parent::update(); $result = $result && field_data::set_for_context_from_datarecord('curriculum', $this); // If this setting is changed, we need to update the existing curriclum expiration values (ELIS-1172) if ($rs = get_recordset_select(CURASSTABLE, "timeexpired != 0 AND curriculumid = {$this->id}", '', 'id, userid')) { $timenow = time(); while ($curass = rs_fetch_next_record($rs)) { $update = new stdClass(); $update->id = $curass->id; $update->timeexpired = calculate_curriculum_expiry(NULL, $this->id, $curass->userid); $update->timemodified = $timenow; update_record(CURASSTABLE, $update); } rs_close($rs); } return $result; }
function backup_copy_user_files($preferences) { global $CFG; $status = true; //First we check that "user_files" exists and create it if necessary //in temp/backup/$backup_code dir $status = check_and_create_user_files_dir($preferences->backup_unique_code); //now get a list of users that we need for this backup. $backup_users = get_recordset_select("backup_ids", "backup_code='{$preferences->backup_unique_code}' AND table_name='user'", "", "id, old_id"); while ($user = rs_fetch_next_record($backup_users)) { //If this user's directory exists, copy it $userdir = make_user_directory($user->old_id, true); if (check_dir_exists($userdir)) { //first remove dirroot so we can split out the folders. $parts = explode('/', str_replace($CFG->dataroot . '/user/', '', $userdir)); $status = true; if (is_array($parts)) { $group = $parts[0]; $userid = $parts[1]; // Create group dir first $status = check_dir_exists("{$CFG->dataroot}/temp/backup/{$preferences->backup_unique_code}/user_files/" . $group, true); } $status = $status && backup_copy_file($userdir, "{$CFG->dataroot}/temp/backup/{$preferences->backup_unique_code}/user_files/{$group}/{$user->old_id}"); } //Do some output backup_flush(30); } rs_close($backup_users); return $status; }
/** * Lock the grade if needed - make sure this is called only when final grades are valid * @param array $items array of all grade item ids * @return void */ function check_locktime_all($items) { global $CFG; $items_sql = implode(',', $items); $now = time(); // no rounding needed, this is not supposed to be called every 10 seconds if ($rs = get_recordset_select('grade_grades', "itemid IN ({$items_sql}) AND locked = 0 AND locktime > 0 AND locktime < {$now}")) { while ($grade = rs_fetch_next_record($rs)) { $grade_grade = new grade_grade($grade, false); $grade_grade->locked = time(); $grade_grade->update('locktime'); } rs_close($rs); } }
/** * This function is run by admin/cron.php every time if admin has enabled this plugin. * * Everyday at settlement time (default is 00:05), it cleans up some tables * and sends email to admin/teachers about pending orders expiring if manual-capture has enabled. * * If admin set up 'Order review' and 'Capture day', it captures credits cards and enrols students. * * @access public */ function cron() { global $CFG; require_once $CFG->dirroot . '/enrol/authorize/authorizenetlib.php'; $oneday = 86400; $timenow = time(); $settlementtime = authorize_getsettletime($timenow); $timediff30 = $settlementtime - 30 * $oneday; $mconfig = get_config('enrol/authorize'); mtrace("Processing authorize cron..."); if (intval($mconfig->an_dailysettlement) < $settlementtime) { set_config('an_dailysettlement', $settlementtime, 'enrol/authorize'); mtrace(" daily cron; some cleanups and sending email to admins the count of pending orders expiring", ": "); $this->cron_daily(); mtrace("done"); } mtrace(" scheduled capture", ": "); if (empty($CFG->an_review) or !empty($CFG->an_test) or intval($CFG->an_capture_day) < 1 or !check_openssl_loaded()) { mtrace("disabled"); return; // order review disabled or test mode or manual capture or openssl wasn't loaded. } $timediffcnf = $settlementtime - intval($CFG->an_capture_day) * $oneday; $select = "(status = '" . AN_STATUS_AUTH . "') AND (timecreated < '{$timediffcnf}') AND (timecreated > '{$timediff30}')"; if (!($ordercount = count_records_select('enrol_authorize', $select))) { mtrace("no pending orders"); return; } $eachconn = intval($mconfig->an_eachconnsecs); $eachconn = $eachconn > 60 ? 60 : ($eachconn <= 0 ? 3 : $eachconn); if ($ordercount * $eachconn + intval($mconfig->an_lastcron) > $timenow) { mtrace("blocked"); return; } set_config('an_lastcron', $timenow, 'enrol/authorize'); mtrace(" {$ordercount} orders are being processed now", ": "); $faults = ''; $sendem = array(); $elapsed = time(); @set_time_limit(0); $this->log = "AUTHORIZE.NET AUTOCAPTURE CRON: " . userdate($timenow) . "\n"; $lastcourseid = 0; for ($rs = get_recordset_select('enrol_authorize', $select, 'courseid'); $order = rs_fetch_next_record($rs);) { $message = ''; $extra = NULL; if (AN_APPROVED == authorize_action($order, $message, $extra, AN_ACTION_PRIOR_AUTH_CAPTURE)) { if ($lastcourseid != $order->courseid) { $lastcourseid = $order->courseid; $course = get_record('course', 'id', $lastcourseid); $role = get_default_course_role($course); $context = get_context_instance(CONTEXT_COURSE, $lastcourseid); } $timestart = $timeend = 0; if ($course->enrolperiod) { $timestart = $timenow; $timeend = $order->settletime + $course->enrolperiod; } $user = get_record('user', 'id', $order->userid); if (role_assign($role->id, $user->id, 0, $context->id, $timestart, $timeend, 0, 'authorize')) { $this->log .= "User({$user->id}) has been enrolled to course({$course->id}).\n"; if (!empty($CFG->enrol_mailstudents)) { $sendem[] = $order->id; } } else { $faults .= "Error while trying to enrol " . fullname($user) . " in '{$course->fullname}' \n"; foreach ($order as $okey => $ovalue) { $faults .= " {$okey} = {$ovalue}\n"; } } } else { $this->log .= "Error, Order# {$order->id}: " . $message . "\n"; } } rs_close($rs); mtrace("processed"); $timenow = time(); $elapsed = $timenow - $elapsed; $eachconn = ceil($elapsed / $ordercount); set_config('an_eachconnsecs', $eachconn, 'enrol/authorize'); $this->log .= "AUTHORIZE.NET CRON FINISHED: " . userdate($timenow); $adminuser = get_admin(); if (!empty($faults)) { email_to_user($adminuser, $adminuser, "AUTHORIZE.NET CRON FAULTS", $faults); } if (!empty($CFG->enrol_mailadmins)) { email_to_user($adminuser, $adminuser, "AUTHORIZE.NET CRON LOG", $this->log); } // Send emails to students about which courses have enrolled. if (!empty($sendem)) { mtrace(" sending welcome messages to students", ": "); send_welcome_messages($sendem); mtrace("sent"); } }
/** * Function to be run periodically according to the moodle cron * Mails new conversations out to participants, checks for any new * participants, and cleans up expired/closed conversations * @return bool true when complete */ function dialogue_cron() { global $CFG, $USER; $context_cache = array(); // delete any closed conversations which have expired dialogue_delete_expired_conversations(); // Finds all dialogue entries that have yet to be mailed out, and mails them $sql = "SELECT e.* FROM {$CFG->prefix}dialogue_entries e " . "INNER JOIN {$CFG->prefix}dialogue d ON e.dialogueid = d.id " . "WHERE e.timecreated + d.edittime * 60 < " . time() . " AND e.mailed = 0 "; if ($entries = get_records_sql($sql)) { foreach ($entries as $entry) { echo "Processing dialogue entry {$entry->id}\n"; if (!($userfrom = get_record('user', 'id', $entry->userid))) { mtrace("Could not find user {$entry->userid}\n"); continue; } // get conversation record if (!($conversation = get_record('dialogue_conversations', 'id', $entry->conversationid))) { mtrace("Could not find conversation {$entry->conversationid}\n"); } if ($userfrom->id == $conversation->userid) { if (!($userto = get_record('user', 'id', $conversation->recipientid))) { mtrace("Could not find use {$conversation->recipientid}\n"); } } else { if (!($userto = get_record('user', 'id', $conversation->userid))) { mtrace("Could not find use {$conversation->userid}\n"); } } $USER->lang = $userto->lang; if (!($dialogue = get_record('dialogue', 'id', $conversation->dialogueid))) { echo "Could not find dialogue id {$conversation->dialogueid}\n"; continue; } if (!($course = get_record('course', 'id', $dialogue->course))) { echo "Could not find course {$dialogue->course}\n"; continue; } if (!($cm = get_coursemodule_from_instance('dialogue', $dialogue->id, $course->id))) { echo "Course Module ID was incorrect\n"; } if (empty($context_cache[$course->id])) { $context_cache[$course->id] = get_context_instance(CONTEXT_COURSE, $course->id); } if (!has_capability('mod/dialogue:participate', $context_cache[$course->id], $userfrom->id) && !has_capability('mod/dialogue:manage', $context_cache[$course->id], $userfrom->id)) { set_field('dialogue_entries', 'mailed', '1', 'id', $entry->id); continue; // Not an active participant } if (!has_capability('mod/dialogue:participate', $context_cache[$course->id], $userto->id) && !has_capability('mod/dialogue:manage', $context_cache[$course->id], $userto->id)) { set_field('dialogue_entries', 'mailed', '1', 'id', $entry->id); continue; // Not an active participant } $strdialogues = get_string('modulenameplural', 'dialogue'); $strdialogue = get_string('modulename', 'dialogue'); $dialogueinfo = new object(); $dialogueinfo->userfrom = fullname($userfrom); $dialogueinfo->dialogue = format_string($dialogue->name); $dialogueinfo->url = "{$CFG->wwwroot}/mod/dialogue/view.php?id={$cm->id}"; $postsubject = "{$course->shortname}: {$strdialogues}: {$dialogueinfo->dialogue}: " . get_string('newentry', 'dialogue'); $posttext = "{$course->shortname} -> {$strdialogues} -> {$dialogueinfo->dialogue}\n"; $posttext .= "---------------------------------------------------------------------\n"; $posttext .= get_string('dialoguemail', 'dialogue', $dialogueinfo) . " \n"; $posttext .= "---------------------------------------------------------------------\n"; if ($userto->mailformat == 1) { // HTML $posthtml = "<p><font face=\"sans-serif\">" . "<a href=\"{$CFG->wwwroot}/course/view.php?id={$course->id}\">{$course->shortname}</a> ->" . "<a href=\"{$CFG->wwwroot}/mod/dialogue/index.php?id={$course->id}\">dialogues</a> ->" . "<a href=\"{$CFG->wwwroot}/mod/dialogue/view.php?id={$cm->id}\">" . $dialogueinfo->dialogue . "</a></font></p>"; $posthtml .= "<hr /><font face=\"sans-serif\">"; $posthtml .= '<p>' . get_string('dialoguemailhtml', 'dialogue', $dialogueinfo) . '</p>'; $posthtml .= "</font><hr />"; } else { $posthtml = ''; } if (!email_to_user($userto, $userfrom, $postsubject, $posttext, $posthtml)) { mtrace("Error: dialogue cron: Could not send out mail for id {$entry->id} to user {$userto->id} ({$userto->email})\n"); } if (!set_field('dialogue_entries', 'mailed', '1', 'id', $entry->id)) { mtrace("Could not update the mailed field for id {$entry->id}\n"); } } } /// Find conversations sent to all participants and check for new participants $rs = get_recordset_select('dialogue_conversations', 'grouping != 0 AND grouping IS NOT NULL', 'dialogueid, grouping'); $dialogueid = 0; $grouping = 0; $groupid = null; $inconversation = array(); $newusers = array(); while ($conversation = rs_fetch_next_record($rs)) { if ($dialogueid != $conversation->dialogueid || $groupid != $conversation->groupid || $grouping != $conversation->grouping) { if ($dialogueid == 0 || $groupid === null) { $dialogueid = $conversation->dialogueid; $groupid = $conversation->groupid; } $cm = get_coursemodule_from_instance('dialogue', $dialogueid); $context = get_context_instance(CONTEXT_MODULE, $cm->id); $users = (array) get_users_by_capability($context, 'mod/dialogue:participate', 'u.id, u.firstname, u.lastname', null, null, null, empty($groupid) ? null : $groupid, null, null, null, false); $managers = (array) get_users_by_capability($context, 'mod/dialogue:manage', 'u.id, u.firstname, u.lastname', null, null, null, null, null, null, null, false); $dialogueid = $conversation->dialogueid; $groupid = $conversation->groupid; } if ($grouping != $conversation->grouping) { if ($grouping) { if ($userdiff = array_diff_key($users, $inconversation, $managers)) { foreach ($userdiff as $userid => $value) { $newusers[$userid . ',' . $grouping] = array('userid' => $userid, 'courseid' => $cm->course, 'grouping' => $grouping); } } } $inconversation = array(); $grouping = $conversation->grouping; } $inconversation[$conversation->recipientid] = true; } if (!empty($dialogueid)) { // Finish of any remaing users $cm = get_coursemodule_from_instance('dialogue', $dialogueid); $context = get_context_instance(CONTEXT_MODULE, $cm->id); $users = (array) get_users_by_capability($context, 'mod/dialogue:participate', 'u.id, u.firstname, u.lastname', null, null, null, empty($groupid) ? null : $groupid, null, null, null, false); $managers = (array) get_users_by_capability($context, 'mod/dialogue:manage', 'u.id, u.firstname, u.lastname', null, null, null, null, null, null, null, false); if ($userdiff = array_diff_key($users, $inconversation, $managers)) { foreach ($userdiff as $userid => $value) { $newusers[$userid . ',' . $grouping] = array('userid' => $userid, 'courseid' => $cm->course, 'grouping' => $grouping); } } } rs_close($rs); if (!empty($newusers)) { foreach ($newusers as $key => $newuser) { begin_sql(); course_setup($newuser['courseid']); if ($conversations = get_records('dialogue_conversations', 'grouping', $newuser['grouping'], 'id', '*', 0, 1)) { $conversation = array_pop($conversations); // we only need one to get the common field values if ($entry = get_records('dialogue_entries', 'conversationid', $conversation->id, 'id', '*', 0, 1)) { unset($conversation->id); $conversation->recipientid = $newuser['userid']; $conversation->lastrecipientid = $newuser['userid']; $conversation->timemodified = time(); $conversation->seenon = false; $conversation->closed = 0; $conversation = addslashes_object($conversation); if (!($conversationid = insert_record('dialogue_conversations', $conversation))) { rollback_sql(); continue; } $entry = array_pop($entry); $srcentry = clone $entry; unset($entry->id); $entry->conversationid = $conversationid; $entry->timecreated = $conversation->timemodified; $entry->recipientid = $conversation->recipientid; $entry->mailed = false; $entry = addslashes_object($entry); if (!($entry->id = insert_record('dialogue_entries', $entry))) { rollback_sql(); continue; } $read = new stdClass(); $lastread = time(); $read->conversationid = $conversationid; $read->entryid = $entry->id; $read->userid = $conversation->userid; $read->firstread = $lastread; $read->lastread = $lastread; insert_record('dialogue_read', $read); if ($entry->attachment) { $srcdir = dialogue_file_area($srcentry); $dstdir = dialogue_file_area($entry); copy($srcdir . '/' . $entry->attachment, $dstdir . '/' . $entry->attachment); } } else { mtrace('Failed to find entry for conversation: ' . $conversation->id); } } else { mtrace('Failed to find conversation: ' . $conversation->id); } commit_sql(); } } return true; }
/** * Notify users about enrolments that are going to expire soon! * This function is run by admin/cron.php * @return void */ function cron() { global $CFG, $USER, $SITE; if (!isset($CFG->lastexpirynotify)) { set_config('lastexpirynotify', 0); } // notify once a day only - TODO: add some tz handling here, maybe use timestamps if ($CFG->lastexpirynotify == date('Ymd')) { return; } if ($rs = get_recordset_select('course', 'enrolperiod > 0 AND expirynotify > 0 AND expirythreshold > 0')) { $cronuser = clone $USER; $admin = get_admin(); while ($course = rs_fetch_next_record($rs)) { $a = new object(); $a->coursename = $course->shortname . '/' . $course->fullname; // must be processed by format_string later $a->threshold = $course->expirythreshold / 86400; $a->extendurl = $CFG->wwwroot . '/user/index.php?id=' . $course->id; $a->current = array(); $a->past = array(); $expiry = time() + $course->expirythreshold; $cname = $course->fullname; /// Get all the manual role assignments for this course that have expired. if (!($context = get_context_instance(CONTEXT_COURSE, $course->id))) { continue; } if ($oldenrolments = get_records_sql("\n SELECT u.*, ra.timeend\n FROM {$CFG->prefix}user u\n JOIN {$CFG->prefix}role_assignments ra ON (ra.userid = u.id)\n WHERE ra.contextid = {$context->id}\n AND ra.timeend > 0 AND ra.timeend <= {$expiry}\n AND ra.enrol = 'manual'")) { // inform user who can assign roles or admin if ($teachers = get_users_by_capability($context, 'moodle/role:assign', '', '', '', '', '', '', false)) { $teachers = sort_by_roleassignment_authority($teachers, $context); $teacher = reset($teachers); } else { $teachers = array($admin); $teacher = $admin; } $a->teacherstr = fullname($teacher, true); foreach ($oldenrolments as $user) { /// Email all users about to expire $a->studentstr = fullname($user, true); if ($user->timeend < $expiry - 86400) { $a->past[] = fullname($user) . " <{$user->email}>"; } else { $a->current[] = fullname($user) . " <{$user->email}>"; if ($course->notifystudents) { // Send this guy notice // setup global $COURSE properly - needed for languages $USER = $user; course_setup($course); $a->coursename = format_string($cname); $a->course = $a->coursename; $strexpirynotifystudentsemail = get_string('expirynotifystudentsemail', '', $a); $strexpirynotify = get_string('expirynotify'); email_to_user($user, $teacher, format_string($SITE->fullname) . ' ' . $strexpirynotify, $strexpirynotifystudentsemail); } } } $a->current = implode("\n", $a->current); $a->past = implode("\n", $a->past); if ($a->current || $a->past) { foreach ($teachers as $teacher) { // setup global $COURSE properly - needed for languages $USER = $teacher; course_setup($course); $a->coursename = format_string($cname); $strexpirynotifyemail = get_string('expirynotifyemail', '', $a); $strexpirynotify = get_string('expirynotify'); email_to_user($teacher, $admin, $a->coursename . ' ' . $strexpirynotify, $strexpirynotifyemail); } } } } $USER = $cronuser; course_setup($SITE); // More environment } set_config('lastexpirynotify', date('Ymd')); }
/** * Function to be run periodically according to the moodle cron * Finds all posts that have yet to be mailed out, and mails them * out to all subscribers * @return void */ function forum_cron() { global $CFG, $USER; $cronuser = clone $USER; $site = get_site(); // all users that are subscribed to any post that needs sending $users = array(); // status arrays $mailcount = array(); $errorcount = array(); // caches $discussions = array(); $forums = array(); $courses = array(); $coursemodules = array(); $subscribedusers = array(); // Posts older than 2 days will not be mailed. This is to avoid the problem where // cron has not been running for a long time, and then suddenly people are flooded // with mail from the past few weeks or months $timenow = time(); $endtime = $timenow - $CFG->maxeditingtime; $starttime = $endtime - 48 * 3600; // Two days earlier if ($posts = forum_get_unmailed_posts($starttime, $endtime, $timenow)) { // Mark them all now as being mailed. It's unlikely but possible there // might be an error later so that a post is NOT actually mailed out, // but since mail isn't crucial, we can accept this risk. Doing it now // prevents the risk of duplicated mails, which is a worse problem. if (!forum_mark_old_posts_as_mailed($endtime)) { mtrace('Errors occurred while trying to mark some posts as being mailed.'); return false; // Don't continue trying to mail them, in case we are in a cron loop } // checking post validity, and adding users to loop through later foreach ($posts as $pid => $post) { $discussionid = $post->discussion; if (!isset($discussions[$discussionid])) { if ($discussion = get_record('forum_discussions', 'id', $post->discussion)) { $discussions[$discussionid] = $discussion; } else { mtrace('Could not find discussion ' . $discussionid); unset($posts[$pid]); continue; } } $forumid = $discussions[$discussionid]->forum; if (!isset($forums[$forumid])) { if ($forum = get_record('forum', 'id', $forumid)) { $forums[$forumid] = $forum; } else { mtrace('Could not find forum ' . $forumid); unset($posts[$pid]); continue; } } $courseid = $forums[$forumid]->course; if (!isset($courses[$courseid])) { if ($course = get_record('course', 'id', $courseid)) { $courses[$courseid] = $course; } else { mtrace('Could not find course ' . $courseid); unset($posts[$pid]); continue; } } if (!isset($coursemodules[$forumid])) { if ($cm = get_coursemodule_from_instance('forum', $forumid, $courseid)) { $coursemodules[$forumid] = $cm; } else { mtrace('Could not course module for forum ' . $forumid); unset($posts[$pid]); continue; } } // caching subscribed users of each forum if (!isset($subscribedusers[$forumid])) { if ($subusers = forum_subscribed_users($courses[$courseid], $forums[$forumid], 0, false)) { foreach ($subusers as $postuser) { // do not try to mail users with stopped email if ($postuser->emailstop) { if (!empty($CFG->forum_logblocked)) { add_to_log(SITEID, 'forum', 'mail blocked', '', '', 0, $postuser->id); } continue; } // this user is subscribed to this forum $subscribedusers[$forumid][$postuser->id] = $postuser->id; // this user is a user we have to process later $users[$postuser->id] = $postuser; } unset($subusers); // release memory } } $mailcount[$pid] = 0; $errorcount[$pid] = 0; } } if ($users && $posts) { $urlinfo = parse_url($CFG->wwwroot); $hostname = $urlinfo['host']; foreach ($users as $userto) { @set_time_limit(120); // terminate if processing of any account takes longer than 2 minutes // set this so that the capabilities are cached, and environment matches receiving user $USER = $userto; mtrace('Processing user ' . $userto->id); // init caches $userto->viewfullnames = array(); $userto->canpost = array(); $userto->markposts = array(); $userto->enrolledin = array(); // reset the caches foreach ($coursemodules as $forumid => $unused) { $coursemodules[$forumid]->cache = new object(); $coursemodules[$forumid]->cache->caps = array(); unset($coursemodules[$forumid]->uservisible); } foreach ($posts as $pid => $post) { // Set up the environment for the post, discussion, forum, course $discussion = $discussions[$post->discussion]; $forum = $forums[$discussion->forum]; $course = $courses[$forum->course]; $cm =& $coursemodules[$forum->id]; // Do some checks to see if we can bail out now if (!isset($subscribedusers[$forum->id][$userto->id])) { continue; // user does not subscribe to this forum } // Verify user is enrollend in course - if not do not send any email if (!isset($userto->enrolledin[$course->id])) { $userto->enrolledin[$course->id] = has_capability('moodle/course:view', get_context_instance(CONTEXT_COURSE, $course->id)); } if (!$userto->enrolledin[$course->id]) { // oops - this user should not receive anything from this course continue; } // Get info about the sending user if (array_key_exists($post->userid, $users)) { // we might know him/her already $userfrom = $users[$post->userid]; } else { if ($userfrom = get_record('user', 'id', $post->userid)) { $users[$userfrom->id] = $userfrom; // fetch only once, we can add it to user list, it will be skipped anyway } else { mtrace('Could not find user ' . $post->userid); continue; } } // setup global $COURSE properly - needed for roles and languages course_setup($course); // More environment // Fill caches if (!isset($userto->viewfullnames[$forum->id])) { $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); $userto->viewfullnames[$forum->id] = has_capability('moodle/site:viewfullnames', $modcontext); } if (!isset($userto->canpost[$discussion->id])) { $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); $userto->canpost[$discussion->id] = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext); } if (!isset($userfrom->groups[$forum->id])) { if (!isset($userfrom->groups)) { $userfrom->groups = array(); $users[$userfrom->id]->groups = array(); } $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id]; } // Make sure groups allow this user to see this email if ($discussion->groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used if (!groups_group_exists($discussion->groupid)) { // Can't find group continue; // Be safe and don't send it to anyone } if (!groups_is_member($discussion->groupid) and !has_capability('moodle/site:accessallgroups', $modcontext)) { // do not send posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS continue; } } // Make sure we're allowed to see it... if (!forum_user_can_see_post($forum, $discussion, $post, NULL, $cm)) { mtrace('user ' . $userto->id . ' can not see ' . $post->id); continue; } // OK so we need to send the email. // Does the user want this post in a digest? If so postpone it for now. if ($userto->maildigest > 0) { // This user wants the mails to be in digest form $queue = new object(); $queue->userid = $userto->id; $queue->discussionid = $discussion->id; $queue->postid = $post->id; $queue->timemodified = $post->created; if (!insert_record('forum_queue', $queue)) { mtrace("Error: mod/forum/cron.php: Could not queue for digest mail for id {$post->id} to user {$userto->id} ({$userto->email}) .. not trying again."); } continue; } // Prepare to actually send the post now, and build up the content $cleanforumname = str_replace('"', "'", strip_tags(format_string($forum->name))); $userfrom->customheaders = array('Precedence: Bulk', 'List-Id: "' . $cleanforumname . '" <moodleforum' . $forum->id . '@' . $hostname . '>', 'List-Help: ' . $CFG->wwwroot . '/mod/forum/view.php?f=' . $forum->id, 'Message-ID: <moodlepost' . $post->id . '@' . $hostname . '>', 'In-Reply-To: <moodlepost' . $post->parent . '@' . $hostname . '>', 'References: <moodlepost' . $post->parent . '@' . $hostname . '>', 'X-Course-Id: ' . $course->id, 'X-Course-Name: ' . format_string($course->fullname, true)); $postsubject = "{$course->shortname}: " . format_string($post->subject, true); $posttext = forum_make_mail_text($course, $forum, $discussion, $post, $userfrom, $userto); $posthtml = forum_make_mail_html($course, $forum, $discussion, $post, $userfrom, $userto); // Send the post now! mtrace('Sending ', ''); if (!($mailresult = email_to_user($userto, $userfrom, $postsubject, $posttext, $posthtml, '', '', $CFG->forum_replytouser))) { mtrace("Error: mod/forum/cron.php: Could not send out mail for id {$post->id} to user {$userto->id}" . " ({$userto->email}) .. not trying again."); add_to_log($course->id, 'forum', 'mail error', "discuss.php?d={$discussion->id}#p{$post->id}", substr(format_string($post->subject, true), 0, 30), $cm->id, $userto->id); $errorcount[$post->id]++; } else { if ($mailresult === 'emailstop') { // should not be reached anymore - see check above } else { $mailcount[$post->id]++; // Mark post as read if forum_usermarksread is set off if (!$CFG->forum_usermarksread) { $userto->markposts[$post->id] = $post->id; } } } mtrace('post ' . $post->id . ': ' . $post->subject); } // mark processed posts as read forum_tp_mark_posts_read($userto, $userto->markposts); } } if ($posts) { foreach ($posts as $post) { mtrace($mailcount[$post->id] . " users were sent post {$post->id}, '{$post->subject}'"); if ($errorcount[$post->id]) { set_field("forum_posts", "mailed", "2", "id", "{$post->id}"); } } } // release some memory unset($subscribedusers); unset($mailcount); unset($errorcount); $USER = clone $cronuser; course_setup(SITEID); $sitetimezone = $CFG->timezone; // Now see if there are any digest mails waiting to be sent, and if we should send them mtrace('Starting digest processing...'); @set_time_limit(300); // terminate if not able to fetch all digests in 5 minutes if (!isset($CFG->digestmailtimelast)) { // To catch the first time set_config('digestmailtimelast', 0); } $timenow = time(); $digesttime = usergetmidnight($timenow, $sitetimezone) + $CFG->digestmailtime * 3600; // Delete any really old ones (normally there shouldn't be any) $weekago = $timenow - 7 * 24 * 3600; delete_records_select('forum_queue', "timemodified < {$weekago}"); mtrace('Cleaned old digest records'); if ($CFG->digestmailtimelast < $digesttime and $timenow > $digesttime) { mtrace('Sending forum digests: ' . userdate($timenow, '', $sitetimezone)); $digestposts_rs = get_recordset_select('forum_queue', "timemodified < {$digesttime}"); if (!rs_EOF($digestposts_rs)) { // We have work to do $usermailcount = 0; //caches - reuse the those filled before too $discussionposts = array(); $userdiscussions = array(); while ($digestpost = rs_fetch_next_record($digestposts_rs)) { if (!isset($users[$digestpost->userid])) { if ($user = get_record('user', 'id', $digestpost->userid)) { $users[$digestpost->userid] = $user; } else { continue; } } $postuser = $users[$digestpost->userid]; if ($postuser->emailstop) { if (!empty($CFG->forum_logblocked)) { add_to_log(SITEID, 'forum', 'mail blocked', '', '', 0, $postuser->id); } continue; } if (!isset($posts[$digestpost->postid])) { if ($post = get_record('forum_posts', 'id', $digestpost->postid)) { $posts[$digestpost->postid] = $post; } else { continue; } } $discussionid = $digestpost->discussionid; if (!isset($discussions[$discussionid])) { if ($discussion = get_record('forum_discussions', 'id', $discussionid)) { $discussions[$discussionid] = $discussion; } else { continue; } } $forumid = $discussions[$discussionid]->forum; if (!isset($forums[$forumid])) { if ($forum = get_record('forum', 'id', $forumid)) { $forums[$forumid] = $forum; } else { continue; } } $courseid = $forums[$forumid]->course; if (!isset($courses[$courseid])) { if ($course = get_record('course', 'id', $courseid)) { $courses[$courseid] = $course; } else { continue; } } if (!isset($coursemodules[$forumid])) { if ($cm = get_coursemodule_from_instance('forum', $forumid, $courseid)) { $coursemodules[$forumid] = $cm; } else { continue; } } $userdiscussions[$digestpost->userid][$digestpost->discussionid] = $digestpost->discussionid; $discussionposts[$digestpost->discussionid][$digestpost->postid] = $digestpost->postid; } rs_close($digestposts_rs); /// Finished iteration, let's close the resultset // Data collected, start sending out emails to each user foreach ($userdiscussions as $userid => $thesediscussions) { @set_time_limit(120); // terminate if processing of any account takes longer than 2 minutes $USER = $cronuser; course_setup(SITEID); // reset cron user language, theme and timezone settings mtrace(get_string('processingdigest', 'forum', $userid), '... '); // First of all delete all the queue entries for this user delete_records_select('forum_queue', "userid = {$userid} AND timemodified < {$digesttime}"); $userto = $users[$userid]; // Override the language and timezone of the "current" user, so that // mail is customised for the receiver. $USER = $userto; course_setup(SITEID); // init caches $userto->viewfullnames = array(); $userto->canpost = array(); $userto->markposts = array(); $postsubject = get_string('digestmailsubject', 'forum', format_string($site->shortname, true)); $headerdata = new object(); $headerdata->sitename = format_string($site->fullname, true); $headerdata->userprefs = $CFG->wwwroot . '/user/edit.php?id=' . $userid . '&course=' . $site->id; $posttext = get_string('digestmailheader', 'forum', $headerdata) . "\n\n"; $headerdata->userprefs = '<a target="_blank" href="' . $headerdata->userprefs . '">' . get_string('digestmailprefs', 'forum') . '</a>'; $posthtml = "<head>"; foreach ($CFG->stylesheets as $stylesheet) { $posthtml .= '<link rel="stylesheet" type="text/css" href="' . $stylesheet . '" />' . "\n"; } $posthtml .= "</head>\n<body id=\"email\">\n"; $posthtml .= '<p>' . get_string('digestmailheader', 'forum', $headerdata) . '</p><br /><hr size="1" noshade="noshade" />'; foreach ($thesediscussions as $discussionid) { @set_time_limit(120); // to be reset for each post $discussion = $discussions[$discussionid]; $forum = $forums[$discussion->forum]; $course = $courses[$forum->course]; $cm = $coursemodules[$forum->id]; //override language course_setup($course); // Fill caches if (!isset($userto->viewfullnames[$forum->id])) { $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); $userto->viewfullnames[$forum->id] = has_capability('moodle/site:viewfullnames', $modcontext); } if (!isset($userto->canpost[$discussion->id])) { $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); $userto->canpost[$discussion->id] = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext); } $strforums = get_string('forums', 'forum'); $canunsubscribe = !forum_is_forcesubscribed($forum); $canreply = $userto->canpost[$discussion->id]; $posttext .= "\n \n"; $posttext .= '====================================================================='; $posttext .= "\n \n"; $posttext .= "{$course->shortname} -> {$strforums} -> " . format_string($forum->name, true); if ($discussion->name != $forum->name) { $posttext .= " -> " . format_string($discussion->name, true); } $posttext .= "\n"; $posthtml .= "<p><font face=\"sans-serif\">" . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/course/view.php?id={$course->id}\">{$course->shortname}</a> -> " . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/mod/forum/index.php?id={$course->id}\">{$strforums}</a> -> " . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/mod/forum/view.php?f={$forum->id}\">" . format_string($forum->name, true) . "</a>"; if ($discussion->name == $forum->name) { $posthtml .= "</font></p>"; } else { $posthtml .= " -> <a target=\"_blank\" href=\"{$CFG->wwwroot}/mod/forum/discuss.php?d={$discussion->id}\">" . format_string($discussion->name, true) . "</a></font></p>"; } $posthtml .= '<p>'; $postsarray = $discussionposts[$discussionid]; sort($postsarray); foreach ($postsarray as $postid) { $post = $posts[$postid]; if (array_key_exists($post->userid, $users)) { // we might know him/her already $userfrom = $users[$post->userid]; } else { if ($userfrom = get_record('user', 'id', $post->userid)) { $users[$userfrom->id] = $userfrom; // fetch only once, we can add it to user list, it will be skipped anyway } else { mtrace('Could not find user ' . $post->userid); continue; } } if (!isset($userfrom->groups[$forum->id])) { if (!isset($userfrom->groups)) { $userfrom->groups = array(); $users[$userfrom->id]->groups = array(); } $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id]; } $userfrom->customheaders = array("Precedence: Bulk"); if ($userto->maildigest == 2) { // Subjects only $by = new object(); $by->name = fullname($userfrom); $by->date = userdate($post->modified); $posttext .= "\n" . format_string($post->subject, true) . ' ' . get_string("bynameondate", "forum", $by); $posttext .= "\n---------------------------------------------------------------------"; $by->name = "<a target=\"_blank\" href=\"{$CFG->wwwroot}/user/view.php?id={$userfrom->id}&course={$course->id}\">{$by->name}</a>"; $posthtml .= '<div><a target="_blank" href="' . $CFG->wwwroot . '/mod/forum/discuss.php?d=' . $discussion->id . '#p' . $post->id . '">' . format_string($post->subject, true) . '</a> ' . get_string("bynameondate", "forum", $by) . '</div>'; } else { // The full treatment $posttext .= forum_make_mail_text($course, $forum, $discussion, $post, $userfrom, $userto, true); $posthtml .= forum_make_mail_post($course, $forum, $discussion, $post, $userfrom, $userto, false, $canreply, true, false); // Create an array of postid's for this user to mark as read. if (!$CFG->forum_usermarksread) { $userto->markposts[$post->id] = $post->id; } } } if ($canunsubscribe) { $posthtml .= "\n<div align=\"right\"><font size=\"1\"><a href=\"{$CFG->wwwroot}/mod/forum/subscribe.php?id={$forum->id}\">" . get_string("unsubscribe", "forum") . "</a></font></div>"; } else { $posthtml .= "\n<div align=\"right\"><font size=\"1\">" . get_string("everyoneissubscribed", "forum") . "</font></div>"; } $posthtml .= '<hr size="1" noshade="noshade" /></p>'; } $posthtml .= '</body>'; if ($userto->mailformat != 1) { // This user DOESN'T want to receive HTML $posthtml = ''; } if (!($mailresult = email_to_user($userto, $site->shortname, $postsubject, $posttext, $posthtml, '', '', $CFG->forum_replytouser))) { mtrace("ERROR!"); echo "Error: mod/forum/cron.php: Could not send out digest mail to user {$userto->id} ({$userto->email})... not trying again.\n"; add_to_log($course->id, 'forum', 'mail digest error', '', '', $cm->id, $userto->id); } else { if ($mailresult === 'emailstop') { // should not happen anymore - see check above } else { mtrace("success."); $usermailcount++; // Mark post as read if forum_usermarksread is set off forum_tp_mark_posts_read($userto, $userto->markposts); } } } } /// We have finishied all digest emails, update $CFG->digestmailtimelast set_config('digestmailtimelast', $timenow); } $USER = $cronuser; course_setup(SITEID); // reset cron user language, theme and timezone settings if (!empty($usermailcount)) { mtrace(get_string('digestsentusers', 'forum', $usermailcount)); } if (!empty($CFG->forum_lastreadclean)) { $timenow = time(); if ($CFG->forum_lastreadclean + 24 * 3600 < $timenow) { set_config('forum_lastreadclean', $timenow); mtrace('Removing old forum read tracking info...'); forum_tp_clean_read_records(); } } else { set_config('forum_lastreadclean', time()); } return true; }