/** * Return time options, which should be shown for record filtering. * * @param int $minlog Time of first log record available. * @return array time options. */ function report_participation_get_time_options($minlog) { $timeoptions = array(); $now = usergetmidnight(time()); // Days. for ($i = 1; $i < 7; $i++) { if (strtotime('-' . $i . ' days', $now) >= $minlog) { $timeoptions[strtotime('-' . $i . ' days', $now)] = get_string('numdays', 'moodle', $i); } } // Weeks. for ($i = 1; $i < 10; $i++) { if (strtotime('-' . $i . ' weeks', $now) >= $minlog) { $timeoptions[strtotime('-' . $i . ' weeks', $now)] = get_string('numweeks', 'moodle', $i); } } // Months. for ($i = 2; $i < 12; $i++) { if (strtotime('-' . $i . ' months', $now) >= $minlog) { $timeoptions[strtotime('-' . $i . ' months', $now)] = get_string('nummonths', 'moodle', $i); } } // Try a year. if (strtotime('-1 year', $now) >= $minlog) { $timeoptions[strtotime('-1 year', $now)] = get_string('lastyear'); } return $timeoptions; }
function __construct($script, $value, $params, $extra) { $this->key = 'date_referred'; $this->value = $this->get_value_or_default($value); $this->params = $params; $this->script = $script; $this->now = usergetmidnight(time()) + 60 * 60 * 23 + 3599; }
function get_all_elements() { $elements = array(); $components = cr_unserialize($this->config->components); $config = (isset($components['timeline']['config'])) ? $components['timeline']['config'] : new stdclass(); if (isset($config->timemode)) { $daysecs = 60 * 60 * 24; if ($config->timemode == 'previous') { $config->starttime = gmmktime() - $config->previousstart * $daysecs; $config->endtime = gmmktime() - $config->previousend * $daysecs; if (isset($config->forcemidnight)) { $config->starttime = usergetmidnight($config->starttime); $config->endtime = usergetmidnight($config->endtime) + ($daysecs - 1); } } $filter_starttime = optional_param('filter_starttime', 0, PARAM_RAW); $filter_endtime = optional_param('filter_endtime', 0, PARAM_RAW); if ($filter_starttime and $filter_endtime) { $filter_starttime = make_timestamp($filter_starttime['year'], $filter_starttime['month'], $filter_starttime['day']); $filter_endtime = make_timestamp($filter_endtime['year'], $filter_endtime['month'], $filter_endtime['day']); $config->starttime = usergetmidnight($filter_starttime); $config->endtime = usergetmidnight($filter_endtime) + 24 * 60 * 60; } for ($i = $config->starttime; $i < $config->endtime; $i += $config->interval * $daysecs) { $row = new stdclass(); $row->id = $i; $row->starttime = $i; $row->endtime = $row->starttime + ($config->interval * $daysecs - 1); if ($row->endtime > $config->endtime) $row->endtime = $config->endtime; $this->timeline[$row->starttime] = $row; $elements[] = $row->starttime; } if ($config->ordering == 'desc') rsort($elements); } return $elements; }
if (!isset($hiddenfields['lastaccess'])) { // Get minimum lastaccess for this course and display a dropbox to filter by lastaccess going back this far. // We need to make it diferently for normal courses and site course. if (!$isfrontpage) { $minlastaccess = $DB->get_field_sql('SELECT min(timeaccess) FROM {user_lastaccess} WHERE courseid = ? AND timeaccess != 0', array($course->id)); $lastaccess0exists = $DB->record_exists('user_lastaccess', array('courseid' => $course->id, 'timeaccess' => 0)); } else { $minlastaccess = $DB->get_field_sql('SELECT min(lastaccess) FROM {user} WHERE lastaccess != 0'); $lastaccess0exists = $DB->record_exists('user', array('lastaccess' => 0)); } $now = usergetmidnight(time()); $timeaccess = array(); $baseurl->remove_params('accesssince'); // Makes sense for this to go first. $timeoptions[0] = get_string('selectperiod'); // Days. for ($i = 1; $i < 7; $i++) { if (strtotime('-' . $i . ' days', $now) >= $minlastaccess) { $timeoptions[strtotime('-' . $i . ' days', $now)] = get_string('numdays', 'moodle', $i); } } // Weeks. for ($i = 1; $i < 10; $i++) { if (strtotime('-' . $i . ' weeks', $now) >= $minlastaccess) { $timeoptions[strtotime('-' . $i . ' weeks', $now)] = get_string('numweeks', 'moodle', $i); }
if (empty($CFG->grade_profilereport) or !file_exists($CFG->dirroot . '/grade/report/' . $CFG->grade_profilereport . '/lib.php')) { $CFG->grade_profilereport = 'user'; } require_once $CFG->libdir . '/gradelib.php'; require_once $CFG->dirroot . '/grade/lib.php'; require_once $CFG->dirroot . '/grade/report/' . $CFG->grade_profilereport . '/lib.php'; $functionname = 'grade_report_' . $CFG->grade_profilereport . '_profilereport'; if (function_exists($functionname)) { $functionname($course, $user); } break; case "todaylogs": echo '<div class="graph">'; print_log_graph($course, $user->id, "userday.png"); echo '</div>'; print_log($course, $user->id, usergetmidnight(time()), "l.time DESC", $page, $perpage, "user.php?id={$course->id}&user={$user->id}&mode={$mode}"); break; case "alllogs": echo '<div class="graph">'; print_log_graph($course, $user->id, "usercourse.png"); echo '</div>'; print_log($course, $user->id, 0, "l.time DESC", $page, $perpage, "user.php?id={$course->id}&user={$user->id}&mode={$mode}"); break; case 'stats': if (empty($CFG->enablestats)) { error("Stats is not enabled."); } require_once $CFG->dirroot . '/lib/statslib.php'; $statsstatus = stats_check_uptodate($course->id); if ($statsstatus !== NULL) { notify($statsstatus);
function instance_config_print() { global $CFG, $DB; if (!isset($this->config)) { // ... teacher has not yet configured the block, let's put some default values here to explain things $this->config->title = get_string('blockname', 'block_glossary_random'); $this->config->refresh = 0; $this->config->showconcept = 1; $this->config->cache = get_string('notyetconfigured', 'block_glossary_random'); $this->config->addentry = get_string('addentry', 'block_glossary_random'); $this->config->viewglossary = get_string('viewglossary', 'block_glossary_random'); $this->config->invisible = get_string('invisible', 'block_glossary_random'); } // select glossaries to put in dropdown box ... $glossaries = $DB->get_records_menu('glossary', array('course' => $this->course->id), 'name', 'id,name'); //format menu texts to avoid html and to filter multilang values if (!empty($glossaries)) { foreach ($glossaries as $key => $value) { $glossaries[$key] = strip_tags(format_string($value, true)); } } // and select quotetypes to put in dropdown box $type[0] = get_string('random', 'block_glossary_random'); $type[1] = get_string('lastmodified', 'block_glossary_random'); $type[2] = get_string('nextone', 'block_glossary_random'); $this->config->nexttime = usergetmidnight(time()) + DAYSECS * $this->config->refresh; // display the form if (is_file($CFG->dirroot . '/blocks/' . $this->name() . '/config_instance.html')) { print_simple_box_start('center', '', '', 5, 'blockconfigglobal'); include $CFG->dirroot . '/blocks/' . $this->name() . '/config_instance.html'; print_simple_box_end(); } else { notice(get_string('blockconfigbad'), str_replace('blockaction=', 'dummy=', qualified_me())); } return true; }
$graph->parameter['tick_length'] = 0; $graph->parameter['shadow'] = 'none'; error_reporting(5); // Ignore most warnings such as font problems etc. $graph->draw_stack(); } else { $site = get_site(); if ($course->id == $site->id) { $courseselect = 0; } else { $courseselect = $course->id; } if ($date) { $daystart = usergetmidnight($date); } else { $daystart = usergetmidnight(time()); } $dayfinish = $daystart + 86400; $hours = array(); for ($i = 0; $i <= 23; $i++) { $logs[$i] = 0; $hour = $daystart + $i * 3600; $hours[$i] = $i; } $rawlogs = report_log_userday($user->id, $courseselect, $daystart, $logreader); if (empty($rawlogs)) { return; } foreach ($rawlogs as $rawlog) { $logs[$rawlog->hour] = $rawlog->num; }
/** * Function to be run periodically according to the scheduled task. * * Finds all posts that have yet to be mailed out, and mails them * out to all subscribers as well as other maintance tasks. * * NOTE: Since 2.7.2 this function is run by scheduled task rather * than standard cron. * * @todo MDL-44734 The function will be split up into seperate tasks. */ function forum_cron() { global $CFG, $USER, $DB, $PAGE; $site = get_site(); // The main renderers. $htmlout = $PAGE->get_renderer('mod_forum', 'email', 'htmlemail'); $textout = $PAGE->get_renderer('mod_forum', 'email', 'textemail'); $htmldigestfullout = $PAGE->get_renderer('mod_forum', 'emaildigestfull', 'htmlemail'); $textdigestfullout = $PAGE->get_renderer('mod_forum', 'emaildigestfull', 'textemail'); $htmldigestbasicout = $PAGE->get_renderer('mod_forum', 'emaildigestbasic', 'htmlemail'); $textdigestbasicout = $PAGE->get_renderer('mod_forum', 'emaildigestbasic', 'textemail'); // All users that are subscribed to any post that needs sending, // please increase $CFG->extramemorylimit on large sites that // send notifications to a large number of users. $users = array(); $userscount = 0; // Cached user counter - count($users) in PHP is horribly slow!!! // Status arrays. $mailcount = array(); $errorcount = array(); // caches $discussions = array(); $forums = array(); $courses = array(); $coursemodules = array(); $subscribedusers = array(); $messageinboundhandlers = 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 // Get the list of forum subscriptions for per-user per-forum maildigest settings. $digestsset = $DB->get_recordset('forum_digests', null, '', 'id, userid, forum, maildigest'); $digests = array(); foreach ($digestsset as $thisrow) { if (!isset($digests[$thisrow->forum])) { $digests[$thisrow->forum] = array(); } $digests[$thisrow->forum][$thisrow->userid] = $thisrow->maildigest; } $digestsset->close(); // Create the generic messageinboundgenerator. $messageinboundgenerator = new \core\message\inbound\address_manager(); $messageinboundgenerator->set_handler('\\mod_forum\\message\\inbound\\reply_handler'); 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 = $DB->get_record('forum_discussions', array('id' => $post->discussion))) { $discussions[$discussionid] = $discussion; \mod_forum\subscriptions::fill_subscription_cache($discussion->forum); \mod_forum\subscriptions::fill_discussion_subscription_cache($discussion->forum); } else { mtrace('Could not find discussion ' . $discussionid); unset($posts[$pid]); continue; } } $forumid = $discussions[$discussionid]->forum; if (!isset($forums[$forumid])) { if ($forum = $DB->get_record('forum', array('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 = $DB->get_record('course', array('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 find course module for forum ' . $forumid); unset($posts[$pid]); continue; } } // Save the Inbound Message datakey here to reduce DB queries later. $messageinboundgenerator->set_data($pid); $messageinboundhandlers[$pid] = $messageinboundgenerator->fetch_data_key(); // Caching subscribed users of each forum. if (!isset($subscribedusers[$forumid])) { $modcontext = context_module::instance($coursemodules[$forumid]->id); if ($subusers = \mod_forum\subscriptions::fetch_subscribed_users($forums[$forumid], 0, $modcontext, 'u.*', true)) { foreach ($subusers as $postuser) { // this user is subscribed to this forum $subscribedusers[$forumid][$postuser->id] = $postuser->id; $userscount++; if ($userscount > FORUM_CRON_USER_CACHE) { // Store minimal user info. $minuser = new stdClass(); $minuser->id = $postuser->id; $users[$postuser->id] = $minuser; } else { // Cache full user record. forum_cron_minimise_user_record($postuser); $users[$postuser->id] = $postuser; } } // Release memory. unset($subusers); unset($postuser); } } $mailcount[$pid] = 0; $errorcount[$pid] = 0; } } if ($users && $posts) { foreach ($users as $userto) { // Terminate if processing of any account takes longer than 2 minutes. core_php_time_limit::raise(120); mtrace('Processing user ' . $userto->id); // Init user caches - we keep the cache for one cycle only, otherwise it could consume too much memory. if (isset($userto->username)) { $userto = clone $userto; } else { $userto = $DB->get_record('user', array('id' => $userto->id)); forum_cron_minimise_user_record($userto); } $userto->viewfullnames = array(); $userto->canpost = array(); $userto->markposts = array(); // Setup this user so that the capabilities are cached, and environment matches receiving user. cron_setup_user($userto); // Reset the caches. foreach ($coursemodules as $forumid => $unused) { $coursemodules[$forumid]->cache = new stdClass(); $coursemodules[$forumid]->cache->caps = array(); unset($coursemodules[$forumid]->uservisible); } foreach ($posts as $pid => $post) { $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. // Only active enrolled users are in the list of subscribers. // This does not necessarily mean that the user is subscribed to the forum or to the discussion though. if (!isset($subscribedusers[$forum->id][$userto->id])) { // The user does not subscribe to this forum. continue; } if (!\mod_forum\subscriptions::is_subscribed($userto->id, $forum, $post->discussion, $coursemodules[$forum->id])) { // The user does not subscribe to this forum, or to this specific discussion. continue; } if ($subscriptiontime = \mod_forum\subscriptions::fetch_discussion_subscription($forum->id, $userto->id)) { // Skip posts if the user subscribed to the discussion after it was created. if (isset($subscriptiontime[$post->discussion]) && $subscriptiontime[$post->discussion] > $post->created) { continue; } } // Don't send email if the forum is Q&A and the user has not posted. // Initial topics are still mailed. if ($forum->type == 'qanda' && !forum_get_user_posted_time($discussion->id, $userto->id) && $pid != $discussion->firstpost) { mtrace('Did not email ' . $userto->id . ' because user has not posted in discussion'); continue; } // Get info about the sending user. if (array_key_exists($post->userid, $users)) { // We might know the user already. $userfrom = $users[$post->userid]; if (!isset($userfrom->idnumber)) { // Minimalised user info, fetch full record. $userfrom = $DB->get_record('user', array('id' => $userfrom->id)); forum_cron_minimise_user_record($userfrom); } } else { if ($userfrom = $DB->get_record('user', array('id' => $post->userid))) { forum_cron_minimise_user_record($userfrom); // Fetch only once if possible, we can add it to user list, it will be skipped anyway. if ($userscount <= FORUM_CRON_USER_CACHE) { $userscount++; $users[$userfrom->id] = $userfrom; } } else { mtrace('Could not find user ' . $post->userid . ', author of post ' . $post->id . '. Unable to send message.'); continue; } } // Note: If we want to check that userto and userfrom are not the same person this is probably the spot to do it. // Setup global $COURSE properly - needed for roles and languages. cron_setup_user($userto, $course); // Fill caches. if (!isset($userto->viewfullnames[$forum->id])) { $modcontext = context_module::instance($cm->id); $userto->viewfullnames[$forum->id] = has_capability('moodle/site:viewfullnames', $modcontext); } if (!isset($userto->canpost[$discussion->id])) { $modcontext = context_module::instance($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(); if (isset($users[$userfrom->id])) { $users[$userfrom->id]->groups = array(); } } $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); if (isset($users[$userfrom->id])) { $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 - be safe and don't this message. continue; } 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 the post. if (!forum_user_can_see_post($forum, $discussion, $post, null, $cm)) { mtrace('User ' . $userto->id . ' can not see ' . $post->id . '. Not sending message.'); continue; } // OK so we need to send the email. // Does the user want this post in a digest? If so postpone it for now. $maildigest = forum_get_user_maildigest_bulk($digests, $userto, $forum->id); if ($maildigest > 0) { // This user wants the mails to be in digest form. $queue = new stdClass(); $queue->userid = $userto->id; $queue->discussionid = $discussion->id; $queue->postid = $post->id; $queue->timemodified = $post->created; $DB->insert_record('forum_queue', $queue); 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('List-Id: "' . $cleanforumname . '" ' . generate_email_messageid('moodleforum' . $forum->id), 'List-Help: ' . $CFG->wwwroot . '/mod/forum/view.php?f=' . $forum->id, 'Message-ID: ' . forum_get_email_message_id($post->id, $userto->id), 'X-Course-Id: ' . $course->id, 'X-Course-Name: ' . format_string($course->fullname, true), 'Precedence: Bulk', 'X-Auto-Response-Suppress: All', 'Auto-Submitted: auto-generated'); $shortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id))); // Generate a reply-to address from using the Inbound Message handler. $replyaddress = null; if ($userto->canpost[$discussion->id] && array_key_exists($post->id, $messageinboundhandlers)) { $messageinboundgenerator->set_data($post->id, $messageinboundhandlers[$post->id]); $replyaddress = $messageinboundgenerator->generate($userto->id); } if (!isset($userto->canpost[$discussion->id])) { $canreply = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext); } else { $canreply = $userto->canpost[$discussion->id]; } $data = new \mod_forum\output\forum_post_email($course, $cm, $forum, $discussion, $post, $userfrom, $userto, $canreply); $userfrom->customheaders[] = sprintf('List-Unsubscribe: <%s>', $data->get_unsubscribediscussionlink()); if (!isset($userto->viewfullnames[$forum->id])) { $data->viewfullnames = has_capability('moodle/site:viewfullnames', $modcontext, $userto->id); } else { $data->viewfullnames = $userto->viewfullnames[$forum->id]; } // Not all of these variables are used in the default language // string but are made available to support custom subjects. $a = new stdClass(); $a->subject = $data->get_subject(); $a->forumname = $cleanforumname; $a->sitefullname = format_string($site->fullname); $a->siteshortname = format_string($site->shortname); $a->courseidnumber = $data->get_courseidnumber(); $a->coursefullname = $data->get_coursefullname(); $a->courseshortname = $data->get_coursename(); $postsubject = html_to_text(get_string('postmailsubject', 'forum', $a), 0); $rootid = forum_get_email_message_id($discussion->firstpost, $userto->id); if ($post->parent) { // This post is a reply, so add reply header (RFC 2822). $parentid = forum_get_email_message_id($post->parent, $userto->id); $userfrom->customheaders[] = "In-Reply-To: {$parentid}"; // If the post is deeply nested we also reference the parent message id and // the root message id (if different) to aid threading when parts of the email // conversation have been deleted (RFC1036). if ($post->parent != $discussion->firstpost) { $userfrom->customheaders[] = "References: {$rootid} {$parentid}"; } else { $userfrom->customheaders[] = "References: {$parentid}"; } } // MS Outlook / Office uses poorly documented and non standard headers, including // Thread-Topic which overrides the Subject and shouldn't contain Re: or Fwd: etc. $a->subject = $discussion->name; $threadtopic = html_to_text(get_string('postmailsubject', 'forum', $a), 0); $userfrom->customheaders[] = "Thread-Topic: {$threadtopic}"; $userfrom->customheaders[] = "Thread-Index: " . substr($rootid, 1, 28); // Send the post now! mtrace('Sending ', ''); $eventdata = new \core\message\message(); $eventdata->courseid = $course->id; $eventdata->component = 'mod_forum'; $eventdata->name = 'posts'; $eventdata->userfrom = $userfrom; $eventdata->userto = $userto; $eventdata->subject = $postsubject; $eventdata->fullmessage = $textout->render($data); $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = $htmlout->render($data); $eventdata->notification = 1; $eventdata->replyto = $replyaddress; if (!empty($replyaddress)) { // Add extra text to email messages if they can reply back. $textfooter = "\n\n" . get_string('replytopostbyemail', 'mod_forum'); $htmlfooter = html_writer::tag('p', get_string('replytopostbyemail', 'mod_forum')); $additionalcontent = array('fullmessage' => array('footer' => $textfooter), 'fullmessagehtml' => array('footer' => $htmlfooter)); $eventdata->set_additional_content('email', $additionalcontent); } $smallmessagestrings = new stdClass(); $smallmessagestrings->user = fullname($userfrom); $smallmessagestrings->forumname = "{$shortname}: " . format_string($forum->name, true) . ": " . $discussion->name; $smallmessagestrings->message = $post->message; // Make sure strings are in message recipients language. $eventdata->smallmessage = get_string_manager()->get_string('smallmessage', 'forum', $smallmessagestrings, $userto->lang); $contexturl = new moodle_url('/mod/forum/discuss.php', array('d' => $discussion->id), 'p' . $post->id); $eventdata->contexturl = $contexturl->out(); $eventdata->contexturlname = $discussion->name; $mailresult = message_send($eventdata); if (!$mailresult) { mtrace("Error: mod/forum/lib.php forum_cron(): Could not send out mail for id {$post->id} to user {$userto->id}" . " ({$userto->email}) .. not trying again."); $errorcount[$post->id]++; } 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. if (get_user_preferences('forum_markasreadonnotification', 1, $userto->id) == 1) { forum_tp_mark_posts_read($userto, $userto->markposts); } unset($userto); } } if ($posts) { foreach ($posts as $post) { mtrace($mailcount[$post->id] . " users were sent post {$post->id}, '{$post->subject}'"); if ($errorcount[$post->id]) { $DB->set_field('forum_posts', 'mailed', FORUM_MAILED_ERROR, array('id' => $post->id)); } } } // release some memory unset($subscribedusers); unset($mailcount); unset($errorcount); cron_setup_user(); $sitetimezone = core_date::get_server_timezone(); // Now see if there are any digest mails waiting to be sent, and if we should send them mtrace('Starting digest processing...'); core_php_time_limit::raise(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; $DB->delete_records_select('forum_queue', "timemodified < ?", array($weekago)); mtrace('Cleaned old digest records'); if ($CFG->digestmailtimelast < $digesttime and $timenow > $digesttime) { mtrace('Sending forum digests: ' . userdate($timenow, '', $sitetimezone)); $digestposts_rs = $DB->get_recordset_select('forum_queue', "timemodified < ?", array($digesttime)); if ($digestposts_rs->valid()) { // We have work to do $usermailcount = 0; //caches - reuse the those filled before too $discussionposts = array(); $userdiscussions = array(); foreach ($digestposts_rs as $digestpost) { if (!isset($posts[$digestpost->postid])) { if ($post = $DB->get_record('forum_posts', array('id' => $digestpost->postid))) { $posts[$digestpost->postid] = $post; } else { continue; } } $discussionid = $digestpost->discussionid; if (!isset($discussions[$discussionid])) { if ($discussion = $DB->get_record('forum_discussions', array('id' => $discussionid))) { $discussions[$discussionid] = $discussion; } else { continue; } } $forumid = $discussions[$discussionid]->forum; if (!isset($forums[$forumid])) { if ($forum = $DB->get_record('forum', array('id' => $forumid))) { $forums[$forumid] = $forum; } else { continue; } } $courseid = $forums[$forumid]->course; if (!isset($courses[$courseid])) { if ($course = $DB->get_record('course', array('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; } $digestposts_rs->close(); /// Finished iteration, let's close the resultset // Data collected, start sending out emails to each user foreach ($userdiscussions as $userid => $thesediscussions) { core_php_time_limit::raise(120); // terminate if processing of any account takes longer than 2 minutes cron_setup_user(); mtrace(get_string('processingdigest', 'forum', $userid), '... '); // First of all delete all the queue entries for this user $DB->delete_records_select('forum_queue', "userid = ? AND timemodified < ?", array($userid, $digesttime)); // Init user caches - we keep the cache for one cycle only, // otherwise it would unnecessarily consume memory. if (array_key_exists($userid, $users) and isset($users[$userid]->username)) { $userto = clone $users[$userid]; } else { $userto = $DB->get_record('user', array('id' => $userid)); forum_cron_minimise_user_record($userto); } $userto->viewfullnames = array(); $userto->canpost = array(); $userto->markposts = array(); // Override the language and timezone of the "current" user, so that // mail is customised for the receiver. cron_setup_user($userto); $postsubject = get_string('digestmailsubject', 'forum', format_string($site->shortname, true)); $headerdata = new stdClass(); $headerdata->sitename = format_string($site->fullname, true); $headerdata->userprefs = $CFG->wwwroot . '/user/forum.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 = '<p>' . get_string('digestmailheader', 'forum', $headerdata) . '</p>' . '<br /><hr size="1" noshade="noshade" />'; foreach ($thesediscussions as $discussionid) { core_php_time_limit::raise(120); // to be reset for each post $discussion = $discussions[$discussionid]; $forum = $forums[$discussion->forum]; $course = $courses[$forum->course]; $cm = $coursemodules[$forum->id]; //override language cron_setup_user($userto, $course); // Fill caches if (!isset($userto->viewfullnames[$forum->id])) { $modcontext = context_module::instance($cm->id); $userto->viewfullnames[$forum->id] = has_capability('moodle/site:viewfullnames', $modcontext); } if (!isset($userto->canpost[$discussion->id])) { $modcontext = context_module::instance($cm->id); $userto->canpost[$discussion->id] = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext); } $strforums = get_string('forums', 'forum'); $canunsubscribe = !\mod_forum\subscriptions::is_forcesubscribed($forum); $canreply = $userto->canpost[$discussion->id]; $shortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id))); $posttext .= "\n \n"; $posttext .= '====================================================================='; $posttext .= "\n \n"; $posttext .= "{$shortname} -> {$strforums} -> " . format_string($forum->name, true); if ($discussion->name != $forum->name) { $posttext .= " -> " . format_string($discussion->name, true); } $posttext .= "\n"; $posttext .= $CFG->wwwroot . '/mod/forum/discuss.php?d=' . $discussion->id; $posttext .= "\n"; $posthtml .= "<p><font face=\"sans-serif\">" . "<a target=\"_blank\" href=\"{$CFG->wwwroot}/course/view.php?id={$course->id}\">{$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); $sentcount = 0; foreach ($postsarray as $postid) { $post = $posts[$postid]; if (array_key_exists($post->userid, $users)) { // we might know him/her already $userfrom = $users[$post->userid]; if (!isset($userfrom->idnumber)) { $userfrom = $DB->get_record('user', array('id' => $userfrom->id)); forum_cron_minimise_user_record($userfrom); } } else { if ($userfrom = $DB->get_record('user', array('id' => $post->userid))) { forum_cron_minimise_user_record($userfrom); if ($userscount <= FORUM_CRON_USER_CACHE) { $userscount++; $users[$userfrom->id] = $userfrom; } } else { mtrace('Could not find user ' . $post->userid); continue; } } if (!isset($userfrom->groups[$forum->id])) { if (!isset($userfrom->groups)) { $userfrom->groups = array(); if (isset($users[$userfrom->id])) { $users[$userfrom->id]->groups = array(); } } $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); if (isset($users[$userfrom->id])) { $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id]; } } // Headers to help prevent auto-responders. $userfrom->customheaders = array("Precedence: Bulk", 'X-Auto-Response-Suppress: All', 'Auto-Submitted: auto-generated'); $maildigest = forum_get_user_maildigest_bulk($digests, $userto, $forum->id); if (!isset($userto->canpost[$discussion->id])) { $canreply = forum_user_can_post($forum, $discussion, $userto, $cm, $course, $modcontext); } else { $canreply = $userto->canpost[$discussion->id]; } $data = new \mod_forum\output\forum_post_email($course, $cm, $forum, $discussion, $post, $userfrom, $userto, $canreply); if (!isset($userto->viewfullnames[$forum->id])) { $data->viewfullnames = has_capability('moodle/site:viewfullnames', $modcontext, $userto->id); } else { $data->viewfullnames = $userto->viewfullnames[$forum->id]; } if ($maildigest == 2) { // Subjects and link only. $posttext .= $textdigestbasicout->render($data); $posthtml .= $htmldigestbasicout->render($data); } else { // The full treatment. $posttext .= $textdigestfullout->render($data); $posthtml .= $htmldigestfullout->render($data); // Create an array of postid's for this user to mark as read. if (!$CFG->forum_usermarksread) { $userto->markposts[$post->id] = $post->id; } } $sentcount++; } $footerlinks = array(); if ($canunsubscribe) { $footerlinks[] = "<a href=\"{$CFG->wwwroot}/mod/forum/subscribe.php?id={$forum->id}\">" . get_string("unsubscribe", "forum") . "</a>"; } else { $footerlinks[] = get_string("everyoneissubscribed", "forum"); } $footerlinks[] = "<a href='{$CFG->wwwroot}/mod/forum/index.php?id={$forum->course}'>" . get_string("digestmailpost", "forum") . '</a>'; $posthtml .= "\n<div class='mdl-right'><font size=\"1\">" . implode(' ', $footerlinks) . '</font></div>'; $posthtml .= '<hr size="1" noshade="noshade" /></p>'; } if (empty($userto->mailformat) || $userto->mailformat != 1) { // This user DOESN'T want to receive HTML $posthtml = ''; } $eventdata = new \core\message\message(); $eventdata->courseid = SITEID; $eventdata->component = 'mod_forum'; $eventdata->name = 'digests'; $eventdata->userfrom = core_user::get_noreply_user(); $eventdata->userto = $userto; $eventdata->subject = $postsubject; $eventdata->fullmessage = $posttext; $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = $posthtml; $eventdata->notification = 1; $eventdata->smallmessage = get_string('smallmessagedigest', 'forum', $sentcount); $mailresult = message_send($eventdata); if (!$mailresult) { mtrace("ERROR: mod/forum/cron.php: Could not send out digest mail to user {$userto->id} " . "({$userto->email})... not trying again."); } else { mtrace("success."); $usermailcount++; // Mark post as read if forum_usermarksread is set off if (get_user_preferences('forum_markasreadonnotification', 1, $userto->id) == 1) { forum_tp_mark_posts_read($userto, $userto->markposts); } } } } /// We have finishied all digest emails, update $CFG->digestmailtimelast set_config('digestmailtimelast', $timenow); } cron_setup_user(); 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; }
/** * This function will empty a course of user data. * It will retain the activities and the structure of the course. * * @param object $data an object containing all the settings including courseid (without magic quotes) * @return array status array of array component, item, error */ function reset_course_userdata($data) { global $CFG, $DB; require_once $CFG->libdir . '/gradelib.php'; require_once $CFG->libdir . '/completionlib.php'; require_once $CFG->dirroot . '/group/lib.php'; $data->courseid = $data->id; $context = context_course::instance($data->courseid); $eventparams = array('context' => $context, 'courseid' => $data->id, 'other' => array('reset_options' => (array) $data)); $event = \core\event\course_reset_started::create($eventparams); $event->trigger(); // Calculate the time shift of dates. if (!empty($data->reset_start_date)) { // Time part of course startdate should be zero. $data->timeshift = $data->reset_start_date - usergetmidnight($data->reset_start_date_old); } else { $data->timeshift = 0; } // Result array: component, item, error. $status = array(); // Start the resetting. $componentstr = get_string('general'); // Move the course start time. if (!empty($data->reset_start_date) and $data->timeshift) { // Change course start data. $DB->set_field('course', 'startdate', $data->reset_start_date, array('id' => $data->courseid)); // Update all course and group events - do not move activity events. $updatesql = "UPDATE {event}\n SET timestart = timestart + ?\n WHERE courseid=? AND instance=0"; $DB->execute($updatesql, array($data->timeshift, $data->courseid)); // Update any date activity restrictions. if ($CFG->enableavailability) { \availability_date\condition::update_all_dates($data->courseid, $data->timeshift); } $status[] = array('component' => $componentstr, 'item' => get_string('datechanged'), 'error' => false); } if (!empty($data->reset_end_date)) { // If the user set a end date value respect it. $DB->set_field('course', 'enddate', $data->reset_end_date, array('id' => $data->courseid)); } else { if ($data->timeshift > 0 && $data->reset_end_date_old) { // If there is a time shift apply it to the end date as well. $enddate = $data->reset_end_date_old + $data->timeshift; $DB->set_field('course', 'enddate', $enddate, array('id' => $data->courseid)); } } if (!empty($data->reset_events)) { $DB->delete_records('event', array('courseid' => $data->courseid)); $status[] = array('component' => $componentstr, 'item' => get_string('deleteevents', 'calendar'), 'error' => false); } if (!empty($data->reset_notes)) { require_once $CFG->dirroot . '/notes/lib.php'; note_delete_all($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('deletenotes', 'notes'), 'error' => false); } if (!empty($data->delete_blog_associations)) { require_once $CFG->dirroot . '/blog/lib.php'; blog_remove_associations_for_course($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('deleteblogassociations', 'blog'), 'error' => false); } if (!empty($data->reset_completion)) { // Delete course and activity completion information. $course = $DB->get_record('course', array('id' => $data->courseid)); $cc = new completion_info($course); $cc->delete_all_completion_data(); $status[] = array('component' => $componentstr, 'item' => get_string('deletecompletiondata', 'completion'), 'error' => false); } if (!empty($data->reset_competency_ratings)) { \core_competency\api::hook_course_reset_competency_ratings($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('deletecompetencyratings', 'core_competency'), 'error' => false); } $componentstr = get_string('roles'); if (!empty($data->reset_roles_overrides)) { $children = $context->get_child_contexts(); foreach ($children as $child) { $DB->delete_records('role_capabilities', array('contextid' => $child->id)); } $DB->delete_records('role_capabilities', array('contextid' => $context->id)); // Force refresh for logged in users. $context->mark_dirty(); $status[] = array('component' => $componentstr, 'item' => get_string('deletecourseoverrides', 'role'), 'error' => false); } if (!empty($data->reset_roles_local)) { $children = $context->get_child_contexts(); foreach ($children as $child) { role_unassign_all(array('contextid' => $child->id)); } // Force refresh for logged in users. $context->mark_dirty(); $status[] = array('component' => $componentstr, 'item' => get_string('deletelocalroles', 'role'), 'error' => false); } // First unenrol users - this cleans some of related user data too, such as forum subscriptions, tracking, etc. $data->unenrolled = array(); if (!empty($data->unenrol_users)) { $plugins = enrol_get_plugins(true); $instances = enrol_get_instances($data->courseid, true); foreach ($instances as $key => $instance) { if (!isset($plugins[$instance->enrol])) { unset($instances[$key]); continue; } } foreach ($data->unenrol_users as $withroleid) { if ($withroleid) { $sql = "SELECT ue.*\n FROM {user_enrolments} ue\n JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)\n JOIN {context} c ON (c.contextlevel = :courselevel AND c.instanceid = e.courseid)\n JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.roleid = :roleid AND ra.userid = ue.userid)"; $params = array('courseid' => $data->courseid, 'roleid' => $withroleid, 'courselevel' => CONTEXT_COURSE); } else { // Without any role assigned at course context. $sql = "SELECT ue.*\n FROM {user_enrolments} ue\n JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)\n JOIN {context} c ON (c.contextlevel = :courselevel AND c.instanceid = e.courseid)\n LEFT JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.userid = ue.userid)\n WHERE ra.id IS null"; $params = array('courseid' => $data->courseid, 'courselevel' => CONTEXT_COURSE); } $rs = $DB->get_recordset_sql($sql, $params); foreach ($rs as $ue) { if (!isset($instances[$ue->enrolid])) { continue; } $instance = $instances[$ue->enrolid]; $plugin = $plugins[$instance->enrol]; if (!$plugin->allow_unenrol($instance) and !$plugin->allow_unenrol_user($instance, $ue)) { continue; } $plugin->unenrol_user($instance, $ue->userid); $data->unenrolled[$ue->userid] = $ue->userid; } $rs->close(); } } if (!empty($data->unenrolled)) { $status[] = array('component' => $componentstr, 'item' => get_string('unenrol', 'enrol') . ' (' . count($data->unenrolled) . ')', 'error' => false); } $componentstr = get_string('groups'); // Remove all group members. if (!empty($data->reset_groups_members)) { groups_delete_group_members($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('removegroupsmembers', 'group'), 'error' => false); } // Remove all groups. if (!empty($data->reset_groups_remove)) { groups_delete_groups($data->courseid, false); $status[] = array('component' => $componentstr, 'item' => get_string('deleteallgroups', 'group'), 'error' => false); } // Remove all grouping members. if (!empty($data->reset_groupings_members)) { groups_delete_groupings_groups($data->courseid, false); $status[] = array('component' => $componentstr, 'item' => get_string('removegroupingsmembers', 'group'), 'error' => false); } // Remove all groupings. if (!empty($data->reset_groupings_remove)) { groups_delete_groupings($data->courseid, false); $status[] = array('component' => $componentstr, 'item' => get_string('deleteallgroupings', 'group'), 'error' => false); } // Look in every instance of every module for data to delete. $unsupportedmods = array(); if ($allmods = $DB->get_records('modules')) { foreach ($allmods as $mod) { $modname = $mod->name; $modfile = $CFG->dirroot . '/mod/' . $modname . '/lib.php'; $moddeleteuserdata = $modname . '_reset_userdata'; // Function to delete user data. if (file_exists($modfile)) { if (!$DB->count_records($modname, array('course' => $data->courseid))) { continue; // Skip mods with no instances. } include_once $modfile; if (function_exists($moddeleteuserdata)) { $modstatus = $moddeleteuserdata($data); if (is_array($modstatus)) { $status = array_merge($status, $modstatus); } else { debugging('Module ' . $modname . ' returned incorrect staus - must be an array!'); } } else { $unsupportedmods[] = $mod; } } else { debugging('Missing lib.php in ' . $modname . ' module!'); } } } // Mention unsupported mods. if (!empty($unsupportedmods)) { foreach ($unsupportedmods as $mod) { $status[] = array('component' => get_string('modulenameplural', $mod->name), 'item' => '', 'error' => get_string('resetnotimplemented')); } } $componentstr = get_string('gradebook', 'grades'); // Reset gradebook,. if (!empty($data->reset_gradebook_items)) { remove_course_grades($data->courseid, false); grade_grab_course_grades($data->courseid); grade_regrade_final_grades($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('removeallcourseitems', 'grades'), 'error' => false); } else { if (!empty($data->reset_gradebook_grades)) { grade_course_reset($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('removeallcoursegrades', 'grades'), 'error' => false); } } // Reset comments. if (!empty($data->reset_comments)) { require_once $CFG->dirroot . '/comment/lib.php'; comment::reset_course_page_comments($context); } $event = \core\event\course_reset_ended::create($eventparams); $event->trigger(); return $status; }
/** * Returns today sessions suitable for copying attendance log * * Fetches data from {attendance_sessions} * * @return array of records or an empty array */ public function get_today_sessions_for_copy($sess) { global $DB; $count = sizeof($sess); if ($count > 0) { $start = usergetmidnight($sess->sessdate); $sql = "SELECT * FROM {local_attendance_sessions} WHERE sessdate >= :start AND sessdate <= :end AND (groupid = 0 OR groupid = :groupid) AND lasttaken > 0 AND attendanceid = :aid"; $params = array( 'start' => $start, 'end' => $sess->sessdate, 'groupid' => $sess->groupid, 'aid' => $this->id); return $DB->get_records_sql($sql, $params); } else return array(); }
/** * Send expiry notifications. * * Plugin that wants to have expiry notification MUST implement following: * - expirynotifyhour plugin setting, * - configuration options in instance edit form (expirynotify, notifyall and expirythreshold), * - notification strings (expirymessageenrollersubject, expirymessageenrollerbody, * expirymessageenrolledsubject and expirymessageenrolledbody), * - expiry_notification provider in db/messages.php, * - upgrade code that sets default thresholds for existing courses (should be 1 day), * - something that calls this method, such as cron. * * @param bool $verbose verbose CLI output */ public function send_expiry_notifications($verbose = false) { global $DB, $CFG; // Unfortunately this may take a long time, it should not be interrupted, // otherwise users get duplicate notification. @set_time_limit(0); raise_memory_limit(MEMORY_HUGE); $name = $this->get_name(); $expirynotifylast = $this->get_config('expirynotifylast', 0); $expirynotifyhour = $this->get_config('expirynotifyhour'); if (is_null($expirynotifyhour)) { debugging("send_expiry_notifications() in {$name} enrolment plugin needs expirynotifyhour setting"); return; } $timenow = time(); $notifytime = usergetmidnight($timenow, $CFG->timezone) + $expirynotifyhour * 3600; if ($expirynotifylast > $notifytime) { if ($verbose) { mtrace($name . ' enrolment expiry notifications were already sent today at ' . userdate($expirynotifylast, '', $CFG->timezone) . '.'); } return; } else { if ($timenow < $notifytime) { if ($verbose) { mtrace($name . ' enrolment expiry notifications will be sent at ' . userdate($notifytime, '', $CFG->timezone) . '.'); } return; } } if ($verbose) { mtrace('Processing ' . $name . ' enrolment expiration notifications...'); } // Notify users responsible for enrolment once every day. $sql = "SELECT ue.*, e.expirynotify, e.notifyall, e.expirythreshold, e.courseid, c.fullname\n FROM {user_enrolments} ue\n JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = :name AND e.expirynotify > 0 AND e.status = :enabled)\n JOIN {course} c ON (c.id = e.courseid)\n JOIN {user} u ON (u.id = ue.userid AND u.deleted = 0 AND u.suspended = 0)\n WHERE ue.status = :active AND ue.timeend > 0 AND ue.timeend > :now1 AND ue.timeend < (e.expirythreshold + :now2)\n ORDER BY ue.enrolid ASC, u.lastname ASC, u.firstname ASC, u.id ASC"; $params = array('enabled' => ENROL_INSTANCE_ENABLED, 'active' => ENROL_USER_ACTIVE, 'now1' => $timenow, 'now2' => $timenow, 'name' => $name); $rs = $DB->get_recordset_sql($sql, $params); $lastenrollid = 0; $users = array(); foreach ($rs as $ue) { if ($lastenrollid and $lastenrollid != $ue->enrolid) { $this->notify_expiry_enroller($lastenrollid, $users, $verbose); $users = array(); } $lastenrollid = $ue->enrolid; $enroller = $this->get_enroller($ue->enrolid); $context = context_course::instance($ue->courseid); $user = $DB->get_record('user', array('id' => $ue->userid)); $users[] = array('fullname' => fullname($user, has_capability('moodle/site:viewfullnames', $context, $enroller)), 'timeend' => $ue->timeend); if (!$ue->notifyall) { continue; } if ($ue->timeend - $ue->expirythreshold + 86400 < $timenow) { // Notify enrolled users only once at the start of the threshold. if ($verbose) { mtrace(" user {$ue->userid} was already notified that enrolment in course {$ue->courseid} expires on " . userdate($ue->timeend, '', $CFG->timezone)); } continue; } $this->notify_expiry_enrolled($user, $ue, $verbose); } $rs->close(); if ($lastenrollid and $users) { $this->notify_expiry_enroller($lastenrollid, $users, $verbose); } if ($verbose) { mtrace('...notification processing finished.'); } $this->set_config('expirynotifylast', $timenow); }
function construct_sessions_data_for_add($formdata) { global $CFG; $duration = $formdata->durtime['hours'] * HOURSECS + $formdata->durtime['minutes'] * MINSECS; $now = time(); $sessions = array(); if (isset($formdata->addmultiply)) { $startdate = $formdata->sessiondate; $starttime = $startdate - usergetmidnight($startdate); $enddate = $formdata->sessionenddate + DAYSECS; // because enddate in 0:0am if ($enddate < $startdate) { return NULL; } $days = (int) ceil(($enddate - $startdate) / DAYSECS); // Getting first day of week $sdate = $startdate; $dinfo = usergetdate($sdate); if ($CFG->calendar_startwday === '0') { //week start from sunday $startweek = $startdate - $dinfo['wday'] * DAYSECS; //call new variable } else { $wday = $dinfo['wday'] === 0 ? 7 : $dinfo['wday']; $startweek = $startdate - ($wday - 1) * DAYSECS; } $wdaydesc = array(0 => 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); while ($sdate < $enddate) { if ($sdate < $startweek + WEEKSECS) { $dinfo = usergetdate($sdate); if (key_exists($wdaydesc[$dinfo['wday']], $formdata->sdays)) { $sess->sessdate = usergetmidnight($sdate) + $starttime; $sess->duration = $duration; $sess->descriptionitemid = $formdata->sdescription['itemid']; $sess->description = $formdata->sdescription['text']; $sess->descriptionformat = $formdata->sdescription['format']; $sess->timemodified = $now; fill_groupid($formdata, $sessions, $sess); } $sdate += DAYSECS; } else { $startweek += WEEKSECS * $formdata->period; $sdate = $startweek; } } } else { $sess->sessdate = $formdata->sessiondate; $sess->duration = $duration; $sess->descriptionitemid = $formdata->sdescription['itemid']; $sess->description = $formdata->sdescription['text']; $sess->descriptionformat = $formdata->sdescription['format']; $sess->timemodified = $now; fill_groupid($formdata, $sessions, $sess); } return $sessions; }
/** * Performs the report function. * * @param array $formdata the form data * @param int $type the report type * @param string $saveto File to save the pdf report to. * @return bool False on failure * @uses $CFG, $DB */ function report_ncccscensus_generate_report($formdata, $type = REPORT_NCCCSCENSUS_ACTION_VIEW, $saveto = false) { global $CFG, $DB; require_once $CFG->libdir . '/moodlelib.php'; $reportname = 'report_ncccscensus'; $cid = $formdata->id; // In case the form is hacked, set a default startdate to today at midnight. if (empty($formdata->startdate)) { $formdata->startdate = usergetmidnight(time(), get_user_timezone()); } // In case the form is hacked, set a default enddate to today at midnight. if (empty($formdata->enddate)) { $formdata->enddate = $formdata->startdate; } // Advance enddate to tomorrow's midnight. $formdata->enddate += DAYSECS - 1; // This flag determines if we should display grouped users or not. $nogroups = isset($formdata->disablegroups) ? true : false; if ($nogroups) { $group = false; } else { // If group specified, do some validation. $group = isset($formdata->group) ? $formdata->group : false; // In case the form is hacked, the group could be invalid. if ($group === false || $group < 0) { throw new report_ncccscensus_exception('cannotfindgroup'); } if ($group > 0) { // Validate the group ID. if (!groups_group_exists($group)) { throw new report_ncccscensus_exception('cannotfindgroup'); } // Validate the group ID with respect to the course ID. $groupdata = groups_get_course_data($cid); $groupfound = false; foreach ($groupdata->groups as $groupobject) { if ($groupobject->id == $group) { $groupfound = true; break; } } if (!$groupfound) { throw new report_ncccscensus_exception('invalidgroupid'); } // User could still hack form to view a group that they don't have the capability to see. $context = context_course::instance($cid); if (has_capability('moodle/site:accessallgroups', $context)) { $userid = 0; } else { if (has_capability('moodle/course:managegroups', $context)) { $userid = $USER->id; } else { $userid = false; } } if ($userid === false) { throw new report_ncccscensus_exception('invalidgroupid'); } if ($userid != 0) { $grouprecs = groups_get_all_groups($course->id, $userid, 0, 'g.id, g.name'); $groupnotfound = true; foreach ($grouprecs as $grouprec) { if ($grouprec->id == $group) { $groupnotfound = false; break; } } if ($groupnotfound) { throw new report_ncccscensus_exception('invalidgroupid'); } } } } $users = array(); if ($nogroups) { $users = report_ncccscensus_get_users($cid, REPORT_NCCCSCENSUS_EXCLUDE_GROUP_MEMBERS); } else { if ($group > 0) { $users = report_ncccscensus_get_users($cid, $group); } else { $users = report_ncccscensus_get_users($cid); } } $results = report_ncccscensus_build_grades_array($cid, $users, $formdata->startdate, $formdata->enddate); if (empty($results)) { return false; } if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW) { $headers = array('student' => get_string('studentfullnamehtml', $reportname)); $showstudentid = report_ncccscensus_check_field_status('showstudentid', 'html'); } else { if ($type == REPORT_NCCCSCENSUS_ACTION_CSV) { $headers = array('student' => get_string('studentfullnamecsv', $reportname)); $showstudentid = report_ncccscensus_check_field_status('showstudentid', 'csv'); } else { $headers = array('student' => get_string('studentfullnamepdf', $reportname)); $showstudentid = report_ncccscensus_check_field_status('showstudentid', 'pdf'); } } if ($showstudentid) { $headers['studentid'] = get_string('studentid', $reportname); } $headers['activity'] = get_string('activityname', $reportname); $headers['module'] = get_string('activitymodule', $reportname); $headers['status'] = get_string('submissionstatus', $reportname); $headers['datesubmitted'] = get_string('submissiondate', $reportname); $headers['grade'] = get_string('grade', $reportname); $headers['gradedate'] = get_string('gradedate', $reportname); $context = context_course::instance($cid); $namesarrayview = array(); $namesarraypdf = array(); $instructors = ' - '; $viewlink = ': <a href="' . $CFG->wwwroot . '/user/view.php?id='; if (!empty($CFG->coursecontact)) { $coursecontactroles = explode(',', $CFG->coursecontact); sort($coursecontactroles); // If a user has multiple roles, we do not want to show user multiple times as a contact. $teachers = array(); foreach ($coursecontactroles as $roleid) { $roleid = (int) $roleid; if ($users = get_role_users($roleid, $context, true)) { $role = $DB->get_record('role', array('id' => $roleid)); $rolename = format_string(role_get_name($role, $context)); foreach ($users as $teacher) { // The $teachers array tracks whether a user is already a course contact. if (!isset($teachers[$teacher->id])) { $teachers[$teacher->id] = true; $fullname = fullname($teacher, has_capability('moodle/site:viewfullnames', $context)); $namesarrayview[] = $rolename . $viewlink . $teacher->id . '&course=' . SITEID . '">' . $fullname . '</a>'; $namesarraycsv[] = $rolename . ': ' . $fullname; $namesarraypdf[] = $rolename . ': ' . $fullname; } } } } } if ($type != REPORT_NCCCSCENSUS_ACTION_PDF) { if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW) { // Create legend for HTML view. $legend = new html_table(); $legend->head = array(get_string('legend', $reportname)); $legend->headspan = array(2); $legendrow1colour = new html_table_cell(); $legendrow1colour->style = 'width: 50px; background-color: ' . get_config('report_ncccscensus', 'gradeoverridecolour'); $legendrow1[] = $legendrow1colour; $legendrow1[] = get_string('legendgradeoverride', $reportname); $legendrow2colour = new html_table_cell(); $legendrow2colour->style = 'width: 50px; background-color: ' . get_config('report_ncccscensus', 'gradenogradecolour'); $legendrow2[] = $legendrow2colour; $legendrow2[] = get_string('legendnograde', $reportname); $legend->data = array($legendrow1, $legendrow2); $legendalign = array('center', 'left'); $legend->align = $legendalign; } $table = new html_table(); $table->head = $headers; $align = array('left'); $numheaders = count($headers); for ($i = 1; $i < $numheaders; $i++) { $align[] = 'center'; } $table->align = $align; $table->data = array(); foreach ($results as $result) { $datum = array(); $datum[] = $result->student; if ($showstudentid) { $datum[] = $result->studentid; } $datum[] = $result->activity; $datum[] = $result->module; $status = $result->status; $grade = $result->grade; if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW && $grade == get_string('nograde', $reportname)) { $specialstatus = new html_table_cell($status); $specialstatus->style = 'background-color: ' . get_config('report_ncccscensus', 'gradenogradecolour'); $status = $specialstatus; } else { if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW && $result->overridden) { $specialstatus = new html_table_cell($status); $specialstatus->style = 'background-color: ' . get_config('report_ncccscensus', 'gradeoverridecolour'); $status = $specialstatus; } } $datum[] = $status; $datum[] = $result->submitdate; if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW && $grade == get_string('nograde', $reportname)) { $nograde = new html_table_cell($grade); $nograde->style = 'background-color: ' . get_config('report_ncccscensus', 'gradenogradecolour'); $grade = $nograde; } else { if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW && $result->overridden) { $overriddengrade = new html_table_cell($grade); $overriddengrade->style = 'background-color: ' . get_config('report_ncccscensus', 'gradeoverridecolour'); $grade = $overriddengrade; } } $datum[] = $grade; $datum[] = $result->date; $table->data[] = $datum; } } $course = $DB->get_record('course', array('id' => $cid)); if ($group > 0) { $groupname = groups_get_group_name($group); } $datestring = 'n/j/y'; $reportrange = date($datestring, $formdata->startdate) . ' - ' . date($datestring, $formdata->enddate); if ($type != REPORT_NCCCSCENSUS_ACTION_VIEW) { $date = usergetdate(time(), get_user_timezone()); $filename = 'CensusRpt2_'; $filename .= date('MdY_Hi', mktime($date['hours'], $date['minutes'], 0, $date['mon'], $date['mday'], $date['year'])); } if ($type == REPORT_NCCCSCENSUS_ACTION_VIEW) { if (report_ncccscensus_check_field_status('showcoursename', 'html')) { echo '<b>' . get_string('coursetitle', $reportname) . ':</b> ' . $course->fullname . '<br>'; } if (report_ncccscensus_check_field_status('showcoursecode', 'html')) { echo '<b>' . get_string('coursecode', $reportname) . ':</b> ' . $course->shortname . '<br>'; } // Only show course ID if present. if (report_ncccscensus_check_field_status('showcourseid', 'html') && $course->idnumber !== '') { echo '<b>' . get_string('courseid', $reportname) . ':</b> ' . $course->idnumber . '<br>'; } if (report_ncccscensus_check_field_status('showteachername', 'html')) { if (!empty($namesarrayview)) { $instructors = implode(', ', $namesarrayview); echo '<b>' . get_string('instructor', $reportname) . ':</b> ' . $instructors . '<br>'; } } echo '<b>' . get_string('reportrange', $reportname) . ':</b> ' . $reportrange . '<br>'; if (isset($groupname)) { echo '<b>' . get_string('section', $reportname) . ':</b> ' . $groupname . '<br>'; } else { echo '<b>' . get_string('section', $reportname) . ':</b> ' . get_string('allgroupspdf', $reportname) . '<br>'; } echo '<br>'; echo html_writer::table($table); echo '<div id="studentfootnote" style="font-size:10px;">' . get_string('studentfootnote', $reportname) . '</div>'; echo '<br>'; echo html_writer::table($legend); echo '<br><div align="center"><a href="' . $CFG->wwwroot . '/report/ncccscensus/index.php?id=' . $formdata->id . '">'; echo get_string('backtoreport', 'report_ncccscensus') . '</a></div>'; } else { if ($type == REPORT_NCCCSCENSUS_ACTION_PDF) { $topheaders = array(); $topheaders['student'] = get_string('student', $reportname); $topheaders['activity'] = get_string('activity', $reportname); $topheaders['submission'] = get_string('submission', $reportname); $topheaders['grade'] = get_string('grade', $reportname); $bottomheaders = array(); $bottomheaders['student'] = array('fullname' => get_string('studentfullnamepdf', $reportname)); $showstudentid = report_ncccscensus_check_field_status('showstudentid', 'pdf'); if ($showstudentid) { $bottomheaders['student']['id'] = get_string('studentidpdf', $reportname); } $bottomheaders['activity'] = array('name' => get_string('activityname', $reportname), 'module' => get_string('activitymodule', $reportname)); $bottomheaders['submission'] = array('status' => get_string('submissionstatus', $reportname), 'date' => get_string('submissiondate', $reportname)); $bottomheaders['grade'] = array('grade' => get_string('grade', $reportname), 'date' => get_string('gradedatepdf', $reportname)); require_once 'report.class.php'; $censusreport = new report(); $censusreport->topheaders = $topheaders; $censusreport->bottomheaders = $bottomheaders; $censusreport->data = array(); foreach ($results as $result) { $fieldarray = array(); $fieldarray['studentfullname'] = $result->student; if ($showstudentid) { $fieldarray['studentid'] = $result->studentid; } $fieldarray['activityname'] = $result->activity; $fieldarray['activitymodule'] = $result->module; $fieldarray['submissionstatus'] = $result->status; $fieldarray['submissiondate'] = $result->submitdate; $fieldarray['gradegrade'] = $result->grade; $fieldarray['gradedate'] = $result->date; $censusreport->data[] = array('data' => $fieldarray, 'override' => $result->overridden != 0 ? true : false, 'nograde' => $result->grade == get_string('nograde', $reportname) ? true : false); } $censusreport->filename = $filename . '.pdf'; if (report_ncccscensus_check_field_status('showcoursename', 'pdf')) { $censusreport->top[] = array(get_string('coursetitlepdf', $reportname) . ':', $course->fullname); } if (report_ncccscensus_check_field_status('showcoursecode', 'pdf')) { $censusreport->top[] = array(get_string('coursecodepdf', $reportname) . ':', $course->shortname); } if (report_ncccscensus_check_field_status('showcourseid', 'pdf') && $course->idnumber !== '') { $censusreport->top[] = array(get_string('courseid', $reportname) . ':', $course->idnumber); } if (report_ncccscensus_check_field_status('showteachername', 'pdf')) { if (!empty($namesarrayview)) { $instructors = implode(', ', $namesarrayview); } $censusreport->top[] = array(get_string('instructor', $reportname) . ':', strip_tags($instructors)); } $censusreport->top[] = array(get_string('reportrangepdf', $reportname) . ':', $reportrange); if (isset($groupname)) { $censusreport->top[] = array(get_string('group', $reportname) . ':', $groupname); } else { if ($group !== false) { $censusreport->top[] = array(get_string('group', $reportname) . ':', get_string('allgroupspdf', $reportname)); } } if (report_ncccscensus_check_field_status('showsignatureline', 'pdf')) { $censusreport->signatureline = true; } if (report_ncccscensus_check_field_status('showdateline', 'pdf')) { $censusreport->dateline = true; } if ($footermessage = get_config('report_ncccscensus', 'footermessage')) { $censusreport->bottom .= $footermessage; } $censusreport->download($saveto); return true; } else { if ($type == REPORT_NCCCSCENSUS_ACTION_CSV) { if (!empty($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) { header('Expires: 0'); header('Cache-Control: private, pre-check=0, post-check=0, max-age=0, must-revalidate'); header('Connection: Keep-Alive'); header('Content-Language: ' . current_language()); header('Keep-Alive: timeout=5, max=100'); header('Pragma: no-cache'); header('Pragma: expires'); header('Expires: Mon, 20 Aug 1969 09:23:00 GMT'); header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); } header('Content-Transfer-Encoding: ascii'); header('Content-Disposition: attachment; filename=' . $filename . '.csv'); header('Content-Type: text/comma-separated-values'); $output = fopen('php://output', 'w'); fputcsv($output, array(get_string('ncccscensusreport_title', 'report_ncccscensus'))); fputcsv($output, array()); if (report_ncccscensus_check_field_status('showcoursename', 'csv')) { fputcsv($output, array(get_string('coursetitle', $reportname), $course->fullname)); } if (report_ncccscensus_check_field_status('showcoursecode', 'csv')) { fputcsv($output, array(get_string('coursecode', $reportname), $course->shortname)); } if (report_ncccscensus_check_field_status('showcourseid', 'csv') && $course->idnumber !== '') { fputcsv($output, array(get_string('courseid', $reportname), $course->idnumber)); } if (!empty($namesarrayview) && report_ncccscensus_check_field_status('showteachername', 'csv')) { fputcsv($output, array_merge(array(get_string('instructor', $reportname)), $namesarraycsv)); } fputcsv($output, array(get_string('reportrange', $reportname), $reportrange)); if (isset($groupname)) { fputcsv($output, array(get_string('section', $reportname), $groupname)); } else { fputcsv($output, array(get_string('section', $reportname), get_string('allgroups', $reportname))); } fputcsv($output, array()); fputcsv($output, $table->head); foreach ($table->data as $row) { fputcsv($output, $row); } $showsignatureline = report_ncccscensus_check_field_status('showsignatureline', 'csv'); $showdateline = report_ncccscensus_check_field_status('showdateline', 'csv'); if ($showsignatureline || $showdateline) { fputcsv($output, array()); if ($showsignatureline) { fputcsv($output, array(get_string('certified', $reportname))); fputcsv($output, array(get_string('signature', $reportname) . get_string('underscores', $reportname))); } if ($showdateline) { fputcsv($output, array(get_string('date') . get_string('underscores', 'report_ncccscensus'))); } } fclose($output); } } } }
// If a day, month and year were passed then convert it to a timestamp. If these were passed // then we can assume the day, month and year are passed as Gregorian, as no where in core // should we be passing these values rather than the time. This is done for BC. if (!empty($day) && !empty($mon) && !empty($year)) { if (checkdate($mon, $day, $year)) { $time = make_timestamp($year, $mon, $day); } } if (empty($time)) { $time = time(); } if ($courseid != SITEID) { $url->param('course', $courseid); } if ($view !== 'upcoming') { $time = usergetmidnight($time); $url->param('view', $view); } $url->param('time', $time); $PAGE->set_url($url); if ($courseid != SITEID && !empty($courseid)) { $course = $DB->get_record('course', array('id' => $courseid)); $courses = array($course->id => $course); $issite = false; navigation_node::override_active_url(new moodle_url('/course/view.php', array('id' => $course->id))); } else { $course = get_site(); $courses = calendar_get_default_courses(); $issite = true; } require_course_login($course);
if ($courseid == SITEID) { $PAGE->set_heading(fullname($user)); } else { $PAGE->set_heading($course->fullname); } // Trigger a user logs viewed event. $event = \report_log\event\user_report_viewed::create(array('context' => $coursecontext, 'relateduserid' => $userid, 'other' => array('mode' => $mode))); $event->trigger(); echo $OUTPUT->header(); if ($courseid != SITEID) { $userheading = array('user' => $user, 'usercontext' => $personalcontext); echo $OUTPUT->context_header($userheading, 2); } // Time to filter records from. if ($mode === 'today') { $timefrom = usergetmidnight(time()); } else { $timefrom = 0; } $output = $PAGE->get_renderer('report_log'); $reportlog = new report_log_renderable($logreader, $course, $user->id, 0, '', -1, -1, false, false, true, false, $PAGE->url, $timefrom, '', $page, $perpage, 'timecreated DESC'); // Setup table if log reader is enabled. if (!empty($reportlog->selectedlogreader)) { $reportlog->setup_table(); $reportlog->tablelog->is_downloadable(false); } echo $output->reader_selector($reportlog); if ($mode === 'all') { $reportlog->selecteddate = 0; } // Print the graphic chart accordingly to the mode (all, today).
/** * Function to be run periodically according to the moodle cron * This function searches for things that need to be done, such * as sending out mail, toggling flags etc ... * * @global stdClass * @global object * @return boolean */ function scorm_cron () { global $CFG, $DB; require_once($CFG->dirroot.'/mod/scorm/locallib.php'); $sitetimezone = $CFG->timezone; // Now see if there are any scorm updates to be done. if (!isset($CFG->scorm_updatetimelast)) { // To catch the first time. set_config('scorm_updatetimelast', 0); } $timenow = time(); $updatetime = usergetmidnight($timenow, $sitetimezone); if ($CFG->scorm_updatetimelast < $updatetime and $timenow > $updatetime) { set_config('scorm_updatetimelast', $timenow); mtrace('Updating scorm packages which require daily update');// We are updating. $scormsupdate = $DB->get_records('scorm', array('updatefreq' => SCORM_UPDATE_EVERYDAY)); foreach ($scormsupdate as $scormupdate) { scorm_parse($scormupdate, true); } // Now clear out AICC session table with old session data. $cfgscorm = get_config('scorm'); if (!empty($cfgscorm->allowaicchacp)) { $expiretime = time() - ($cfgscorm->aicchacpkeepsessiondata * 24 * 60 * 60); $DB->delete_records_select('scorm_aicc_session', 'timemodified < ?', array($expiretime)); } } return true; }
/** * Function to be run periodically according to the moodle cron * This function searches for things that need to be done, such * as sending out mail, toggling flags etc ... * * @return boolean */ function scorm_cron() { global $CFG; require_once 'locallib.php'; $sitetimezone = $CFG->timezone; /// Now see if there are any digest mails waiting to be sent, and if we should send them if (!isset($CFG->scorm_updatetimelast)) { // To catch the first time set_config('scorm_updatetimelast', 0); } $timenow = time(); $updatetime = usergetmidnight($timenow, $sitetimezone) + $CFG->scorm_updatetime * 3600; if ($CFG->scorm_updatetimelast < $updatetime and $timenow > $updatetime) { set_config('scorm_updatetimelast', $timenow); mtrace('Updating scorm packages which require daily update'); //We are updating $scormsupdate = get_records('scorm', 'updatefreq', UPDATE_EVERYDAY); if (!empty($scormsupdate)) { foreach ($scormsupdate as $scormupdate) { $scormupdate->instance = $scormupdate->id; $id = scorm_update_instance($scormupdate); } } } return true; }
/** * This function will empty a course of user data. * It will retain the activities and the structure of the course. * * @param object $data an object containing all the settings including courseid (without magic quotes) * @return array status array of array component, item, error */ function reset_course_userdata($data) { global $CFG, $USER, $DB; require_once $CFG->libdir . '/gradelib.php'; require_once $CFG->libdir . '/completionlib.php'; require_once $CFG->dirroot . '/group/lib.php'; $data->courseid = $data->id; $context = get_context_instance(CONTEXT_COURSE, $data->courseid); // calculate the time shift of dates if (!empty($data->reset_start_date)) { // time part of course startdate should be zero $data->timeshift = $data->reset_start_date - usergetmidnight($data->reset_start_date_old); } else { $data->timeshift = 0; } // result array: component, item, error $status = array(); // start the resetting $componentstr = get_string('general'); // move the course start time if (!empty($data->reset_start_date) and $data->timeshift) { // change course start data $DB->set_field('course', 'startdate', $data->reset_start_date, array('id' => $data->courseid)); // update all course and group events - do not move activity events $updatesql = "UPDATE {event}\n SET timestart = timestart + ?\n WHERE courseid=? AND instance=0"; $DB->execute($updatesql, array($data->timeshift, $data->courseid)); $status[] = array('component' => $componentstr, 'item' => get_string('datechanged'), 'error' => false); } if (!empty($data->reset_logs)) { $DB->delete_records('log', array('course' => $data->courseid)); $status[] = array('component' => $componentstr, 'item' => get_string('deletelogs'), 'error' => false); } if (!empty($data->reset_events)) { $DB->delete_records('event', array('courseid' => $data->courseid)); $status[] = array('component' => $componentstr, 'item' => get_string('deleteevents', 'calendar'), 'error' => false); } if (!empty($data->reset_notes)) { require_once $CFG->dirroot . '/notes/lib.php'; note_delete_all($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('deletenotes', 'notes'), 'error' => false); } if (!empty($data->delete_blog_associations)) { require_once $CFG->dirroot . '/blog/lib.php'; blog_remove_associations_for_course($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('deleteblogassociations', 'blog'), 'error' => false); } if (!empty($data->reset_course_completion)) { // Delete course completion information $course = $DB->get_record('course', array('id' => $data->courseid)); $cc = new completion_info($course); $cc->delete_course_completion_data(); $status[] = array('component' => $componentstr, 'item' => get_string('deletecoursecompletiondata', 'completion'), 'error' => false); } $componentstr = get_string('roles'); if (!empty($data->reset_roles_overrides)) { $children = get_child_contexts($context); foreach ($children as $child) { $DB->delete_records('role_capabilities', array('contextid' => $child->id)); } $DB->delete_records('role_capabilities', array('contextid' => $context->id)); //force refresh for logged in users mark_context_dirty($context->path); $status[] = array('component' => $componentstr, 'item' => get_string('deletecourseoverrides', 'role'), 'error' => false); } if (!empty($data->reset_roles_local)) { $children = get_child_contexts($context); foreach ($children as $child) { role_unassign_all(array('contextid' => $child->id)); } //force refresh for logged in users mark_context_dirty($context->path); $status[] = array('component' => $componentstr, 'item' => get_string('deletelocalroles', 'role'), 'error' => false); } // First unenrol users - this cleans some of related user data too, such as forum subscriptions, tracking, etc. $data->unenrolled = array(); if (!empty($data->unenrol_users)) { $plugins = enrol_get_plugins(true); $instances = enrol_get_instances($data->courseid, true); foreach ($instances as $key => $instance) { if (!isset($plugins[$instance->enrol])) { unset($instances[$key]); continue; } if (!$plugins[$instance->enrol]->allow_unenrol($instance)) { unset($instances[$key]); } } $sqlempty = $DB->sql_empty(); foreach ($data->unenrol_users as $withroleid) { $sql = "SELECT DISTINCT ue.userid, ue.enrolid\n FROM {user_enrolments} ue\n JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)\n JOIN {context} c ON (c.contextlevel = :courselevel AND c.instanceid = e.courseid)\n JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.roleid = :roleid AND ra.userid = ue.userid)"; $params = array('courseid' => $data->courseid, 'roleid' => $withroleid, 'courselevel' => CONTEXT_COURSE); $rs = $DB->get_recordset_sql($sql, $params); foreach ($rs as $ue) { if (!isset($instances[$ue->enrolid])) { continue; } $plugins[$instances[$ue->enrolid]->enrol]->unenrol_user($instances[$ue->enrolid], $ue->userid); $data->unenrolled[$ue->userid] = $ue->userid; } } } if (!empty($data->unenrolled)) { $status[] = array('component' => $componentstr, 'item' => get_string('unenrol', 'enrol') . ' (' . count($data->unenrolled) . ')', 'error' => false); } $componentstr = get_string('groups'); // remove all group members if (!empty($data->reset_groups_members)) { groups_delete_group_members($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('removegroupsmembers', 'group'), 'error' => false); } // remove all groups if (!empty($data->reset_groups_remove)) { groups_delete_groups($data->courseid, false); $status[] = array('component' => $componentstr, 'item' => get_string('deleteallgroups', 'group'), 'error' => false); } // remove all grouping members if (!empty($data->reset_groupings_members)) { groups_delete_groupings_groups($data->courseid, false); $status[] = array('component' => $componentstr, 'item' => get_string('removegroupingsmembers', 'group'), 'error' => false); } // remove all groupings if (!empty($data->reset_groupings_remove)) { groups_delete_groupings($data->courseid, false); $status[] = array('component' => $componentstr, 'item' => get_string('deleteallgroupings', 'group'), 'error' => false); } // Look in every instance of every module for data to delete $unsupported_mods = array(); if ($allmods = $DB->get_records('modules')) { foreach ($allmods as $mod) { $modname = $mod->name; if (!$DB->count_records($modname, array('course' => $data->courseid))) { continue; // skip mods with no instances } $modfile = $CFG->dirroot . '/mod/' . $modname . '/lib.php'; $moddeleteuserdata = $modname . '_reset_userdata'; // Function to delete user data if (file_exists($modfile)) { include_once $modfile; if (function_exists($moddeleteuserdata)) { $modstatus = $moddeleteuserdata($data); if (is_array($modstatus)) { $status = array_merge($status, $modstatus); } else { debugging('Module ' . $modname . ' returned incorrect staus - must be an array!'); } } else { $unsupported_mods[] = $mod; } } else { debugging('Missing lib.php in ' . $modname . ' module!'); } } } // mention unsupported mods if (!empty($unsupported_mods)) { foreach ($unsupported_mods as $mod) { $status[] = array('component' => get_string('modulenameplural', $mod->name), 'item' => '', 'error' => get_string('resetnotimplemented')); } } $componentstr = get_string('gradebook', 'grades'); // reset gradebook if (!empty($data->reset_gradebook_items)) { remove_course_grades($data->courseid, false); grade_grab_course_grades($data->courseid); grade_regrade_final_grades($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('removeallcourseitems', 'grades'), 'error' => false); } else { if (!empty($data->reset_gradebook_grades)) { grade_course_reset($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('removeallcoursegrades', 'grades'), 'error' => false); } } // reset comments if (!empty($data->reset_comments)) { require_once $CFG->dirroot . '/comment/lib.php'; comment::reset_course_page_comments($context); } return $status; }
/** * Get event format time * * @param calendar_event $event event object * @param int $now current time in gmt * @param array $linkparams list of params for event link * @param bool $usecommonwords the words as formatted date/time. * @param int $showtime determine the show time GMT timestamp * @return string $eventtime link/string for event time */ function calendar_format_event_time($event, $now, $linkparams = null, $usecommonwords = true, $showtime = 0) { $starttime = $event->timestart; $endtime = $event->timestart + $event->timeduration; if (empty($linkparams) || !is_array($linkparams)) { $linkparams = array(); } $linkparams['view'] = 'day'; // OK, now to get a meaningful display... // Check if there is a duration for this event. if ($event->timeduration) { // Get the midnight of the day the event will start. $usermidnightstart = usergetmidnight($starttime); // Get the midnight of the day the event will end. $usermidnightend = usergetmidnight($endtime); // Check if we will still be on the same day. if ($usermidnightstart == $usermidnightend) { // Check if we are running all day. if ($event->timeduration == DAYSECS) { $time = get_string('allday', 'calendar'); } else { // Specify the time we will be running this from. $datestart = calendar_time_representation($starttime); $dateend = calendar_time_representation($endtime); $time = $datestart . ' <strong>»</strong> ' . $dateend; } // Set printable representation. if (!$showtime) { $day = calendar_day_representation($event->timestart, $now, $usecommonwords); $url = calendar_get_link_href(new moodle_url(CALENDAR_URL . 'view.php', $linkparams), 0, 0, 0, $endtime); $eventtime = html_writer::link($url, $day) . ', ' . $time; } else { $eventtime = $time; } } else { // It must spans two or more days. $daystart = calendar_day_representation($event->timestart, $now, $usecommonwords) . ', '; if ($showtime == $usermidnightstart) { $daystart = ''; } $timestart = calendar_time_representation($event->timestart); $dayend = calendar_day_representation($event->timestart + $event->timeduration, $now, $usecommonwords) . ', '; if ($showtime == $usermidnightend) { $dayend = ''; } $timeend = calendar_time_representation($event->timestart + $event->timeduration); // Set printable representation. if ($now >= $usermidnightstart && $now < $usermidnightstart + DAYSECS) { $url = calendar_get_link_href(new moodle_url(CALENDAR_URL . 'view.php', $linkparams), 0, 0, 0, $endtime); $eventtime = $timestart . ' <strong>»</strong> ' . html_writer::link($url, $dayend) . $timeend; } else { $url = calendar_get_link_href(new moodle_url(CALENDAR_URL . 'view.php', $linkparams), 0, 0, 0, $endtime); $eventtime = html_writer::link($url, $daystart) . $timestart . ' <strong>»</strong> '; $url = calendar_get_link_href(new moodle_url(CALENDAR_URL . 'view.php', $linkparams), 0, 0, 0, $starttime); $eventtime .= html_writer::link($url, $dayend) . $timeend; } } } else { // There is no time duration. $time = calendar_time_representation($event->timestart); // Set printable representation. if (!$showtime) { $day = calendar_day_representation($event->timestart, $now, $usecommonwords); $url = calendar_get_link_href(new moodle_url(CALENDAR_URL . 'view.php', $linkparams), 0, 0, 0, $starttime); $eventtime = html_writer::link($url, $day) . ', ' . trim($time); } else { $eventtime = $time; } } // Check if It has expired. if ($event->timestart + $event->timeduration < $now) { $eventtime = '<span class="dimmed_text">' . str_replace(' href=', ' class="dimmed" href=', $eventtime) . '</span>'; } return $eventtime; }
/** * Return user's deadlines from the calendar. * * Usually called twice, once for all deadlines from today, then any from the next 12 months up to the * max requested. * * Based on the calender function calendar_get_upcoming. * * @param array $courses ids of all user's courses. * @param int $maxevents to return * @param bool $todayonly true if only the next 24 hours to be returned * @return array */ private static function get_upcoming_deadlines($courses, $maxevents, $todayonly = false) { $now = time(); if ($todayonly === true) { $starttime = usergetmidnight($now); $daysinfuture = 1; } else { $starttime = usergetmidnight($now + DAYSECS + 3 * HOURSECS); // Avoid rare DST change issues. $daysinfuture = 365; } $endtime = $starttime + $daysinfuture * DAYSECS - 1; $userevents = false; $groupevents = false; $events = calendar_get_events($starttime, $endtime, $userevents, $groupevents, $courses); $processed = 0; $output = array(); foreach ($events as $event) { if ($event->eventtype === 'course') { // Not an activity deadline. continue; } if (!empty($event->modulename)) { $modinfo = get_fast_modinfo($event->courseid); $mods = $modinfo->get_instances_of($event->modulename); if (isset($mods[$event->instance])) { $cminfo = $mods[$event->instance]; if (!$cminfo->uservisible) { continue; } } } $output[$event->id] = $event; ++$processed; if ($processed >= $maxevents) { break; } } return $output; }
/** * Get the list of admin settings for this module and apply any defaults/advanced/locked settings. * * @param $datetimeoffsets array - If passed, this is an array of fieldnames => times that the * default date/time value should be relative to. If not passed, all * date/time fields are set relative to the users current midnight. * @return void */ public function apply_admin_defaults($datetimeoffsets = array()) { // This flag triggers the settings to be locked in apply_admin_locked_flags(). $this->applyadminlockedflags = true; $settings = get_config($this->_modname); $mform = $this->_form; $usermidnight = usergetmidnight(time()); $isupdate = !empty($this->_cm); foreach ($settings as $name => $value) { if (strpos('_', $name) !== false) { continue; } if ($mform->elementExists($name)) { $element = $mform->getElement($name); if (!$isupdate) { if ($element->getType() == 'date_time_selector') { $enabledsetting = $name . '_enabled'; if (empty($settings->{$enabledsetting})) { $mform->setDefault($name, 0); } else { $relativetime = $usermidnight; if (isset($datetimeoffsets[$name])) { $relativetime = $datetimeoffsets[$name]; } $mform->setDefault($name, $relativetime + $settings->{$name}); } } else { $mform->setDefault($name, $settings->{$name}); } } $advancedsetting = $name . '_adv'; if (!empty($settings->{$advancedsetting})) { $mform->setAdvanced($name); } } } }
/** * This function will empty a course of user data. * It will retain the activities and the structure of the course. * @param object $data an object containing all the settings including courseid (without magic quotes) * @return array status array of array component, item, error */ function reset_course_userdata($data) { global $CFG, $USER; require_once $CFG->libdir . '/gradelib.php'; require_once $CFG->dirroot . '/group/lib.php'; $data->courseid = $data->id; $context = get_context_instance(CONTEXT_COURSE, $data->courseid); // calculate the time shift of dates if (!empty($data->reset_start_date)) { // time part of course startdate should be zero $data->timeshift = $data->reset_start_date - usergetmidnight($data->reset_start_date_old); } else { $data->timeshift = 0; } // result array: component, item, error $status = array(); // start the resetting $componentstr = get_string('general'); // move the course start time if (!empty($data->reset_start_date) and $data->timeshift) { // change course start data set_field('course', 'startdate', $data->reset_start_date, 'id', $data->courseid); // update all course and group events - do not move activity events $updatesql = "UPDATE {$CFG->prefix}event\n SET timestart = timestart + ({$data->timeshift})\n WHERE courseid={$data->courseid} AND instance=0"; execute_sql($updatesql, false); $status[] = array('component' => $componentstr, 'item' => get_string('datechanged'), 'error' => false); } if (!empty($data->reset_logs)) { delete_records('log', 'course', $data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('deletelogs'), 'error' => false); } if (!empty($data->reset_events)) { delete_records('event', 'courseid', $data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('deleteevents', 'calendar'), 'error' => false); } if (!empty($data->reset_notes)) { require_once $CFG->dirroot . '/notes/lib.php'; note_delete_all($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('deletenotes', 'notes'), 'error' => false); } $componentstr = get_string('roles'); if (!empty($data->reset_roles_overrides)) { $children = get_child_contexts($context); foreach ($children as $child) { delete_records('role_capabilities', 'contextid', $child->id); } delete_records('role_capabilities', 'contextid', $context->id); //force refresh for logged in users mark_context_dirty($context->path); $status[] = array('component' => $componentstr, 'item' => get_string('deletecourseoverrides', 'role'), 'error' => false); } if (!empty($data->reset_roles_local)) { $children = get_child_contexts($context); foreach ($children as $child) { role_unassign(0, 0, 0, $child->id); } //force refresh for logged in users mark_context_dirty($context->path); $status[] = array('component' => $componentstr, 'item' => get_string('deletelocalroles', 'role'), 'error' => false); } // First unenrol users - this cleans some of related user data too, such as forum subscriptions, tracking, etc. $data->unenrolled = array(); if (!empty($data->reset_roles)) { foreach ($data->reset_roles as $roleid) { if ($users = get_role_users($roleid, $context, false, 'u.id', 'u.id ASC')) { foreach ($users as $user) { role_unassign($roleid, $user->id, 0, $context->id); if (!has_capability('moodle/course:view', $context, $user->id)) { $data->unenrolled[$user->id] = $user->id; } } } } } if (!empty($data->unenrolled)) { $status[] = array('component' => $componentstr, 'item' => get_string('unenrol') . ' (' . count($data->unenrolled) . ')', 'error' => false); } $componentstr = get_string('groups'); // remove all group members if (!empty($data->reset_groups_members)) { groups_delete_group_members($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('removegroupsmembers', 'group'), 'error' => false); } // remove all groups if (!empty($data->reset_groups_remove)) { groups_delete_groups($data->courseid, false); $status[] = array('component' => $componentstr, 'item' => get_string('deleteallgroups', 'group'), 'error' => false); } // remove all grouping members if (!empty($data->reset_groupings_members)) { groups_delete_groupings_groups($data->courseid, false); $status[] = array('component' => $componentstr, 'item' => get_string('removegroupingsmembers', 'group'), 'error' => false); } // remove all groupings if (!empty($data->reset_groupings_remove)) { groups_delete_groupings($data->courseid, false); $status[] = array('component' => $componentstr, 'item' => get_string('deleteallgroupings', 'group'), 'error' => false); } // Look in every instance of every module for data to delete $unsupported_mods = array(); if ($allmods = get_records('modules')) { foreach ($allmods as $mod) { $modname = $mod->name; if (!count_records($modname, 'course', $data->courseid)) { continue; // skip mods with no instances } $modfile = $CFG->dirroot . '/mod/' . $modname . '/lib.php'; $moddeleteuserdata = $modname . '_reset_userdata'; // Function to delete user data if (file_exists($modfile)) { include_once $modfile; if (function_exists($moddeleteuserdata)) { $modstatus = $moddeleteuserdata($data); if (is_array($modstatus)) { $status = array_merge($status, $modstatus); } else { debugging('Module ' . $modname . ' returned incorrect staus - must be an array!'); } } else { $unsupported_mods[] = $mod; } } else { debugging('Missing lib.php in ' . $modname . ' module!'); } } } // mention unsupported mods if (!empty($unsupported_mods)) { foreach ($unsupported_mods as $mod) { $status[] = array('component' => get_string('modulenameplural', $mod->name), 'item' => '', 'error' => get_string('resetnotimplemented')); } } $componentstr = get_string('gradebook', 'grades'); // reset gradebook if (!empty($data->reset_gradebook_items)) { remove_course_grades($data->courseid, false); grade_grab_course_grades($data->courseid); grade_regrade_final_grades($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('removeallcourseitems', 'grades'), 'error' => false); } else { if (!empty($data->reset_gradebook_grades)) { grade_course_reset($data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('removeallcoursegrades', 'grades'), 'error' => false); } } return $status; }
/** * Returns today sessions suitable for copying attendance log * * Fetches data from {attendance_sessions} * * @return array of records or an empty array */ public function get_today_sessions_for_copy($sess) { global $DB; $start = usergetmidnight($sess->sessdate); $sql = "SELECT *\n FROM {attendance_sessions}\n WHERE sessdate >= :start AND sessdate <= :end AND\n (groupid = 0 OR groupid = :groupid) AND\n lasttaken > 0 AND attendanceid = :aid"; $params = array('start' => $start, 'end' => $sess->sessdate, 'groupid' => $sess->groupid, 'aid' => $this->id); return $DB->get_records_sql($sql, $params); }
function specialization() { global $CFG, $DB; require_once $CFG->libdir . '/filelib.php'; $this->course = $this->page->course; // load userdefined title and make sure it's never empty if (empty($this->config->title)) { $this->title = get_string('pluginname', 'block_glossary_random'); } else { $this->title = $this->config->title; } if (empty($this->config->glossary)) { return false; } if (!isset($this->config->nexttime)) { $this->config->nexttime = 0; } //check if it's time to put a new entry in cache if (time() > $this->config->nexttime) { // place glossary concept and definition in $pref->cache if (!($numberofentries = $DB->count_records('glossary_entries', array('glossaryid' => $this->config->glossary, 'approved' => 1)))) { $this->config->cache = get_string('noentriesyet', 'block_glossary_random'); $this->instance_config_commit(); } // Get module and context, to be able to rewrite urls if (!($cm = get_coursemodule_from_instance("glossary", $this->config->glossary, $this->course->id))) { return false; } $glossaryctx = get_context_instance(CONTEXT_MODULE, $cm->id); $limitfrom = 0; $limitnum = 1; switch ($this->config->type) { case BGR_RANDOMLY: $i = rand(1, $numberofentries); $limitfrom = $i - 1; $SORT = 'ASC'; break; case BGR_NEXTONE: if (isset($this->config->previous)) { $i = $this->config->previous + 1; } else { $i = 1; } if ($i > $numberofentries) { // Loop back to beginning $i = 1; } $limitfrom = $i - 1; $SORT = 'ASC'; break; default: // BGR_LASTMODIFIED $i = $numberofentries; $limitfrom = 0; $SORT = 'DESC'; break; } if ($entry = $DB->get_records_sql("SELECT id, concept, definition, definitionformat, definitiontrust\n FROM {glossary_entries}\n WHERE glossaryid = ? AND approved = 1\n ORDER BY timemodified {$SORT}", array($this->config->glossary), $limitfrom, $limitnum)) { $entry = reset($entry); if (empty($this->config->showconcept)) { $text = ''; } else { $text = "<h3>" . format_string($entry->concept, true) . "</h3>"; } $options = new stdClass(); $options->trusted = $entry->definitiontrust; $options->overflowdiv = true; $entry->definition = file_rewrite_pluginfile_urls($entry->definition, 'pluginfile.php', $glossaryctx->id, 'mod_glossary', 'entry', $entry->id); $text .= format_text($entry->definition, $entry->definitionformat, $options); $this->config->nexttime = usergetmidnight(time()) + DAYSECS * $this->config->refresh; $this->config->previous = $i; } else { $text = get_string('noentriesyet', 'block_glossary_random'); } // store the text $this->config->cache = $text; $this->instance_config_commit(); } }
function calendar_format_event_time($event, $now, $morehref, $usecommonwords = true, $showtime = 0) { $startdate = usergetdate($event->timestart); $enddate = usergetdate($event->timestart + $event->timeduration); $usermidnightstart = usergetmidnight($event->timestart); if ($event->timeduration) { // To avoid doing the math if one IF is enough :) $usermidnightend = usergetmidnight($event->timestart + $event->timeduration); } else { $usermidnightend = $usermidnightstart; } // OK, now to get a meaningful display... // First of all we have to construct a human-readable date/time representation if ($event->timeduration) { // It has a duration if ($usermidnightstart == $usermidnightend || $event->timestart == $usermidnightstart && ($event->timeduration == 86400 || $event->timeduration == 86399) || $event->timestart + $event->timeduration <= $usermidnightstart + 86400) { // But it's all on the same day $timestart = calendar_time_representation($event->timestart); $timeend = calendar_time_representation($event->timestart + $event->timeduration); $time = $timestart . ' <strong>»</strong> ' . $timeend; if ($event->timestart == $usermidnightstart && ($event->timeduration == 86400 || $event->timeduration == 86399)) { $time = get_string('allday', 'calendar'); } // Set printable representation if (!$showtime) { $day = calendar_day_representation($event->timestart, $now, $usecommonwords); $eventtime = calendar_get_link_tag($day, CALENDAR_URL . 'view.php?view=day' . $morehref . '&', $enddate['mday'], $enddate['mon'], $enddate['year']) . ', ' . $time; } else { $eventtime = $time; } } else { // It spans two or more days $daystart = calendar_day_representation($event->timestart, $now, $usecommonwords) . ', '; if ($showtime == $usermidnightstart) { $daystart = ''; } $timestart = calendar_time_representation($event->timestart); $dayend = calendar_day_representation($event->timestart + $event->timeduration, $now, $usecommonwords) . ', '; if ($showtime == $usermidnightend) { $dayend = ''; } $timeend = calendar_time_representation($event->timestart + $event->timeduration); // Set printable representation if ($now >= $usermidnightstart && $now < $usermidnightstart + 86400) { $eventtime = $timestart . ' <strong>»</strong> ' . calendar_get_link_tag($dayend, CALENDAR_URL . 'view.php?view=day' . $morehref . '&', $enddate['mday'], $enddate['mon'], $enddate['year']) . $timeend; } else { $eventtime = calendar_get_link_tag($daystart, CALENDAR_URL . 'view.php?view=day' . $morehref . '&', $startdate['mday'], $startdate['mon'], $startdate['year']) . $timestart . ' <strong>»</strong> ' . calendar_get_link_tag($dayend, CALENDAR_URL . 'view.php?view=day' . $morehref . '&', $enddate['mday'], $enddate['mon'], $enddate['year']) . $timeend; } } } else { $time = ' '; // Set printable representation if (!$showtime) { $day = calendar_day_representation($event->timestart, $now, $usecommonwords); $eventtime = calendar_get_link_tag($day, CALENDAR_URL . 'view.php?view=day' . $morehref . '&', $startdate['mday'], $startdate['mon'], $startdate['year']) . trim($time); } else { $eventtime = $time; } } if ($event->timestart + $event->timeduration < $now) { // It has expired $eventtime = '<span class="dimmed_text">' . str_replace(' href=', ' class="dimmed" href=', $eventtime) . '</span>'; } return $eventtime; }
/** * This function is used to generate and display selector form * * @global stdClass $USER * @global stdClass $CFG * @global moodle_database $DB * @global core_renderer $OUTPUT * @global stdClass $SESSION * @uses CONTEXT_SYSTEM * @uses COURSE_MAX_COURSES_PER_DROPDOWN * @uses CONTEXT_COURSE * @uses SEPARATEGROUPS * @param stdClass $course course instance * @param int $selecteduser id of the selected user * @param string $selecteddate Date selected * @param string $modname course_module->id * @param string $modid number or 'site_errors' * @param string $modaction an action as recorded in the logs * @param int $selectedgroup Group to display * @param int $showcourses whether to show courses if we're over our limit. * @param int $showusers whether to show users if we're over our limit. * @param string $logformat Format of the logs (downloadascsv, showashtml, downloadasods, downloadasexcel) * @return void */ function report_plog_print_selector_form($student, $startdate = 0, $course, $metric, $test) { global $USER, $CFG, $DB, $OUTPUT, $SESSION; $sitecontext = context_system::instance(); $context = context_course::instance($course->id); if (has_capability('report/plog:viewcourse', $context)) { $showusers = 1; } else { $showusers = 0; } //probably remove this - not currently worried about groups (should we be though?) /// Setup for group handling. if ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) { $selectedgroup = -1; $showgroups = false; } else { if ($course->groupmode) { $showgroups = true; } else { $selectedgroup = 0; $showgroups = false; } } if ($selectedgroup === -1) { if (isset($SESSION->currentgroup[$course->id])) { $selectedgroup = $SESSION->currentgroup[$course->id]; } else { $selectedgroup = groups_get_all_groups($course->id, $USER->id); if (is_array($selectedgroup)) { $selectedgroup = array_shift(array_keys($selectedgroup)); $SESSION->currentgroup[$course->id] = $selectedgroup; } else { $selectedgroup = 0; } } } // Get all the possible users $users = array(); // Define limitfrom and limitnum for queries below // If $showusers is enabled... don't apply limitfrom and limitnum $limitfrom = empty($showusers) ? 0 : ''; $limitnum = empty($showusers) ? COURSE_MAX_USERS_PER_DROPDOWN + 1 : ''; //this needs to be modified so we don't include admin and tutors for this course in the list? $courseusers = get_enrolled_users($context, '', $selectedgroup, 'u.id, u.firstname, u.lastname', null, $limitfrom, $limitnum); if ($showusers) { if ($courseusers) { foreach ($courseusers as $courseuser) { $users[$courseuser->id] = fullname($courseuser, has_capability('moodle/site:viewfullnames', $context)); } } $users[$CFG->siteguest] = get_string('guestuser'); } //echo $course->id; //$n = "select distinct clusteringname from cluster_runs r where r.courseid = $course->id"; $n = "select distinct clusteringname from cluster_runs r where r.courseid = {$course->id}"; $metrica = $DB->get_records_sql($n); //there has to be a better way of doing this... $metrics = array(); foreach ($metrica as $row) { $metrics[] = $row->clusteringname; } $strftimedate = get_string("strftimedate"); $strftimedaydate = get_string("strftimedaydate"); asort($users); $timenow = time(); // GMT // What day is it now for the user, and when is midnight that day (in GMT). $timemidnight = $today = usergetmidnight($timenow); // Put today up the top of the list //$dates = array("$timemidnight" => get_string("today").", ".userdate($timenow, $strftimedate) ); $dates = array(); if (!$course->startdate or $course->startdate > $timenow) { $course->startdate = $course->timecreated; } //want to change this so we have a number of intervals //from start of course //last week //last fortnight //last month $numdates = 1; while ($timemidnight > $course->startdate and $numdates < 5) { $timemidnight = $timemidnight - 604800; //number of seconds in a week $timenow = $timenow - 604800; $dates["{$timemidnight}"] = $numdates . " weeks:" . userdate($timenow, $strftimedaydate); $numdates++; } echo "<form class=\"logselectform\" action=\"{$CFG->wwwroot}/report/plog/index.php\" method=\"get\">\n"; echo "<div>\n"; echo "<input type=\"hidden\" name=\"chooselog\" value=\"1\" />\n"; echo "<input type=\"hidden\" name=\"showusers\" value=\"{$showusers}\" />\n"; echo "<input type=\"hidden\" name=\"test\" value=\"{$test}\" />\n"; if ($showusers) { echo html_writer::label(get_string('selctauser'), 'menuuser', false, array('class' => 'accesshide')); echo html_writer::select($users, "student", $student); } echo html_writer::label(get_string('date'), 'menudate', false, array('class' => 'accesshide')); echo html_writer::select($dates, "startdate", $startdate, get_string("alldays")); echo '<select id="menumetric" class="select menumetric" name="metric">'; foreach ($metrics as $metric) { echo "<option value='{$metric}'>{$metric}</option>"; } echo '</select>'; //echo html_writer::select($metrics, "metric", $metric, "metric"); echo '<input type="submit" value="' . get_string('gettheselogs') . '" />'; echo '</div>'; echo '</form>'; }
/** * 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 * * @global object * @global object * @global object * @uses CONTEXT_MODULE * @uses CONTEXT_COURSE * @uses SITEID * @uses FORMAT_PLAIN * @return void */ function forum_cron() { global $CFG, $USER, $DB; $site = get_site(); // All users that are subscribed to any post that needs sending, // please increase $CFG->extramemorylimit on large sites that // send notifications to a large number of users. $users = array(); $userscount = 0; // Cached user counter - count($users) in PHP is horribly slow!!! // 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 = $DB->get_record('forum_discussions', array('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 = $DB->get_record('forum', array('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 = $DB->get_record('course', array('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 find course module for forum '.$forumid); unset($posts[$pid]); continue; } } // caching subscribed users of each forum if (!isset($subscribedusers[$forumid])) { $modcontext = context_module::instance($coursemodules[$forumid]->id); if ($subusers = forum_subscribed_users($courses[$courseid], $forums[$forumid], 0, $modcontext, "u.*")) { foreach ($subusers as $postuser) { // this user is subscribed to this forum $subscribedusers[$forumid][$postuser->id] = $postuser->id; $userscount++; if ($userscount > FORUM_CRON_USER_CACHE) { // Store minimal user info. $minuser = new stdClass(); $minuser->id = $postuser->id; $users[$postuser->id] = $minuser; } else { // Cache full user record. forum_cron_minimise_user_record($postuser); $users[$postuser->id] = $postuser; } } // Release memory. unset($subusers); unset($postuser); } } $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 mtrace('Processing user '.$userto->id); // Init user caches - we keep the cache for one cycle only, // otherwise it could consume too much memory. if (isset($userto->username)) { $userto = clone($userto); } else { $userto = $DB->get_record('user', array('id' => $userto->id)); forum_cron_minimise_user_record($userto); } $userto->viewfullnames = array(); $userto->canpost = array(); $userto->markposts = array(); // set this so that the capabilities are cached, and environment matches receiving user cron_setup_user($userto); // reset the caches foreach ($coursemodules as $forumid=>$unused) { $coursemodules[$forumid]->cache = new stdClass(); $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 // Only active enrolled users are in the list of subscribers if (!isset($subscribedusers[$forum->id][$userto->id])) { continue; // user does not subscribe to this forum } // Don't send email if the forum is Q&A and the user has not posted // Initial topics are still mailed if ($forum->type == 'qanda' && !forum_get_user_posted_time($discussion->id, $userto->id) && $pid != $discussion->firstpost) { mtrace('Did not email '.$userto->id.' because user has not posted in discussion'); continue; } // Get info about the sending user if (array_key_exists($post->userid, $users)) { // we might know him/her already $userfrom = $users[$post->userid]; if (!isset($userfrom->idnumber)) { // Minimalised user info, fetch full record. $userfrom = $DB->get_record('user', array('id' => $userfrom->id)); forum_cron_minimise_user_record($userfrom); } } else if ($userfrom = $DB->get_record('user', array('id' => $post->userid))) { forum_cron_minimise_user_record($userfrom); // Fetch only once if possible, we can add it to user list, it will be skipped anyway. if ($userscount <= FORUM_CRON_USER_CACHE) { $userscount++; $users[$userfrom->id] = $userfrom; } } else { mtrace('Could not find user '.$post->userid); continue; } //if we want to check that userto and userfrom are not the same person this is probably the spot to do it // setup global $COURSE properly - needed for roles and languages cron_setup_user($userto, $course); // Fill caches if (!isset($userto->viewfullnames[$forum->id])) { $modcontext = context_module::instance($cm->id); $userto->viewfullnames[$forum->id] = has_capability('moodle/site:viewfullnames', $modcontext); } if (!isset($userto->canpost[$discussion->id])) { $modcontext = context_module::instance($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(); if (isset($users[$userfrom->id])) { $users[$userfrom->id]->groups = array(); } } $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); if (isset($users[$userfrom->id])) { $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 stdClass(); $queue->userid = $userto->id; $queue->discussionid = $discussion->id; $queue->postid = $post->id; $queue->timemodified = $post->created; $DB->insert_record('forum_queue', $queue); 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 ( // Headers to make emails easier to track 'Precedence: Bulk', 'List-Id: "'.$cleanforumname.'" <moodleforum'.$forum->id.'@'.$hostname.'>', 'List-Help: '.$CFG->wwwroot.'/mod/forum/view.php?f='.$forum->id, 'Message-ID: '.forum_get_email_message_id($post->id, $userto->id, $hostname), 'X-Course-Id: '.$course->id, 'X-Course-Name: '.format_string($course->fullname, true) ); if ($post->parent) { // This post is a reply, so add headers for threading (see MDL-22551) $userfrom->customheaders[] = 'In-Reply-To: '.forum_get_email_message_id($post->parent, $userto->id, $hostname); $userfrom->customheaders[] = 'References: '.forum_get_email_message_id($post->parent, $userto->id, $hostname); } $shortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id))); $postsubject = html_to_text("$shortname: ".format_string($post->subject, true)); $posttext = forum_make_mail_text($course, $cm, $forum, $discussion, $post, $userfrom, $userto); $posthtml = forum_make_mail_html($course, $cm, $forum, $discussion, $post, $userfrom, $userto); // Send the post now! mtrace('Sending ', ''); $eventdata = new stdClass(); $eventdata->component = 'mod_forum'; $eventdata->name = 'posts'; $eventdata->userfrom = $userfrom; $eventdata->userto = $userto; $eventdata->subject = $postsubject; $eventdata->fullmessage = $posttext; $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = $posthtml; $eventdata->notification = 1; // If forum_replytouser is not set then send mail using the noreplyaddress. if (empty($CFG->forum_replytouser)) { // Clone userfrom as it is referenced by $users. $cloneduserfrom = clone($userfrom); $cloneduserfrom->email = $CFG->noreplyaddress; $eventdata->userfrom = $cloneduserfrom; } $smallmessagestrings = new stdClass(); $smallmessagestrings->user = fullname($userfrom); $smallmessagestrings->forumname = "$shortname: ".format_string($forum->name,true).": ".$discussion->name; $smallmessagestrings->message = $post->message; //make sure strings are in message recipients language $eventdata->smallmessage = get_string_manager()->get_string('smallmessage', 'forum', $smallmessagestrings, $userto->lang); $eventdata->contexturl = "{$CFG->wwwroot}/mod/forum/discuss.php?d={$discussion->id}#p{$post->id}"; $eventdata->contexturlname = $discussion->name; $mailresult = message_send($eventdata); if (!$mailresult){ mtrace("Error: mod/forum/lib.php forum_cron(): 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 { $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); unset($userto); } } if ($posts) { foreach ($posts as $post) { mtrace($mailcount[$post->id]." users were sent post $post->id, '$post->subject'"); if ($errorcount[$post->id]) { $DB->set_field('forum_posts', 'mailed', FORUM_MAILED_ERROR, array('id' => $post->id)); } } } // release some memory unset($subscribedusers); unset($mailcount); unset($errorcount); cron_setup_user(); $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); $DB->delete_records_select('forum_queue', "timemodified < ?", array($weekago)); mtrace ('Cleaned old digest records'); if ($CFG->digestmailtimelast < $digesttime and $timenow > $digesttime) { mtrace('Sending forum digests: '.userdate($timenow, '', $sitetimezone)); $digestposts_rs = $DB->get_recordset_select('forum_queue', "timemodified < ?", array($digesttime)); if ($digestposts_rs->valid()) { // We have work to do $usermailcount = 0; //caches - reuse the those filled before too $discussionposts = array(); $userdiscussions = array(); foreach ($digestposts_rs as $digestpost) { if (!isset($posts[$digestpost->postid])) { if ($post = $DB->get_record('forum_posts', array('id' => $digestpost->postid))) { $posts[$digestpost->postid] = $post; } else { continue; } } $discussionid = $digestpost->discussionid; if (!isset($discussions[$discussionid])) { if ($discussion = $DB->get_record('forum_discussions', array('id' => $discussionid))) { $discussions[$discussionid] = $discussion; } else { continue; } } $forumid = $discussions[$discussionid]->forum; if (!isset($forums[$forumid])) { if ($forum = $DB->get_record('forum', array('id' => $forumid))) { $forums[$forumid] = $forum; } else { continue; } } $courseid = $forums[$forumid]->course; if (!isset($courses[$courseid])) { if ($course = $DB->get_record('course', array('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; } $digestposts_rs->close(); /// 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 cron_setup_user(); mtrace(get_string('processingdigest', 'forum', $userid), '... '); // First of all delete all the queue entries for this user $DB->delete_records_select('forum_queue', "userid = ? AND timemodified < ?", array($userid, $digesttime)); // Init user caches - we keep the cache for one cycle only, // otherwise it would unnecessarily consume memory. if (array_key_exists($userid, $users) and isset($users[$userid]->username)) { $userto = clone($users[$userid]); } else { $userto = $DB->get_record('user', array('id' => $userid)); forum_cron_minimise_user_record($userto); } $userto->viewfullnames = array(); $userto->canpost = array(); $userto->markposts = array(); // Override the language and timezone of the "current" user, so that // mail is customised for the receiver. cron_setup_user($userto); $postsubject = get_string('digestmailsubject', 'forum', format_string($site->shortname, true)); $headerdata = new stdClass(); $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) { //TODO: MDL-21120 $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 cron_setup_user($userto, $course); // Fill caches if (!isset($userto->viewfullnames[$forum->id])) { $modcontext = context_module::instance($cm->id); $userto->viewfullnames[$forum->id] = has_capability('moodle/site:viewfullnames', $modcontext); } if (!isset($userto->canpost[$discussion->id])) { $modcontext = context_module::instance($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]; $shortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id))); $posttext .= "\n \n"; $posttext .= '====================================================================='; $posttext .= "\n \n"; $posttext .= "$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\">$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]; if (!isset($userfrom->idnumber)) { $userfrom = $DB->get_record('user', array('id' => $userfrom->id)); forum_cron_minimise_user_record($userfrom); } } else if ($userfrom = $DB->get_record('user', array('id' => $post->userid))) { forum_cron_minimise_user_record($userfrom); if ($userscount <= FORUM_CRON_USER_CACHE) { $userscount++; $users[$userfrom->id] = $userfrom; } } else { mtrace('Could not find user '.$post->userid); continue; } if (!isset($userfrom->groups[$forum->id])) { if (!isset($userfrom->groups)) { $userfrom->groups = array(); if (isset($users[$userfrom->id])) { $users[$userfrom->id]->groups = array(); } } $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); if (isset($users[$userfrom->id])) { $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id]; } } $userfrom->customheaders = array ("Precedence: Bulk"); if ($userto->maildigest == 2) { // Subjects only $by = new stdClass(); $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, $cm, $forum, $discussion, $post, $userfrom, $userto, true); $posthtml .= forum_make_mail_post($course, $cm, $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 class='mdl-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 class='mdl-right'><font size=\"1\">".get_string("everyoneissubscribed", "forum")."</font></div>"; } $posthtml .= '<hr size="1" noshade="noshade" /></p>'; } $posthtml .= '</body>'; if (empty($userto->mailformat) || $userto->mailformat != 1) { // This user DOESN'T want to receive HTML $posthtml = ''; } $attachment = $attachname=''; // Directly email forum digests rather than sending them via messaging, use the // site shortname as 'from name', the noreply address will be used by email_to_user. $mailresult = email_to_user($userto, $site->shortname, $postsubject, $posttext, $posthtml, $attachment, $attachname); if (!$mailresult) { 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 { 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); } cron_setup_user(); 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; }
function schedule_inc_backup_next_execution($backup_course, $incremental_config, $now, $timezone) { $result = -1; //Get today's midnight GMT $midnight = usergetmidnight($now, $timezone); //Get today's day of week (0=Sunday...6=Saturday) $date = usergetdate($now, $timezone); $dayofweek = $date['wday']; //Get number of days (from today) to execute backups $scheduled_days = substr($incremental_config->backup_inc_weekdays, $dayofweek) . $incremental_config->backup_inc_weekdays; $daysfromtoday = strpos($scheduled_days, "1"); //If some day has been found if ($daysfromtoday !== false) { //Calculate distance $dist = $daysfromtoday * 86400 + $incremental_config->backup_inc_hour * 3600 + $incremental_config->backup_inc_minute * 60; //Minutes distance $result = $midnight + $dist; } //If that time is past, call the function recursively to obtain the next valid day if ($result > 0 && $result < time()) { $result = schedule_inc_backup_next_execution($backup_course, $incremental_config, $now + 86400, $timezone); } return $result; }
function print_log_selector_form($course, $selecteduser = 0, $selecteddate = 'today', $modname = "", $modid = 0, $modaction = '', $selectedgroup = -1, $showcourses = 0, $showusers = 0, $logformat = 'showashtml') { global $USER, $CFG; // first check to see if we can override showcourses and showusers $numcourses = count_records_select("course", "", "COUNT(id)"); if ($numcourses < COURSE_MAX_COURSES_PER_DROPDOWN && !$showcourses) { $showcourses = 1; } $sitecontext = get_context_instance(CONTEXT_SYSTEM, SITEID); $context = get_context_instance(CONTEXT_COURSE, $course->id); /// Setup for group handling. if ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) { $selectedgroup = get_current_group($course->id); $showgroups = false; } else { if ($course->groupmode) { $selectedgroup = $selectedgroup == -1 ? get_current_group($course->id) : $selectedgroup; $showgroups = true; } else { $selectedgroup = 0; $showgroups = false; } } // Get all the possible users $users = array(); if ($course->id != SITEID) { if ($selectedgroup) { // If using a group, only get users in that group. $courseusers = get_group_users($selectedgroup, 'u.lastname ASC', '', 'u.id, u.firstname, u.lastname, u.idnumber'); } else { $courseusers = get_course_users($course->id, '', '', 'u.id, u.firstname, u.lastname, u.idnumber'); } } else { $courseusers = get_site_users("u.lastaccess DESC", "u.id, u.firstname, u.lastname, u.idnumber"); } if (count($courseusers) < COURSE_MAX_USERS_PER_DROPDOWN && !$showusers) { $showusers = 1; } if ($showusers) { if ($courseusers) { foreach ($courseusers as $courseuser) { $users[$courseuser->id] = fullname($courseuser, has_capability('moodle/site:viewfullnames', $context)); } } if ($guest = get_guest()) { $users[$guest->id] = fullname($guest); } } if (has_capability('moodle/site:viewreports', $sitecontext) && $showcourses) { if ($ccc = get_records("course", "", "", "fullname", "id,fullname,category")) { foreach ($ccc as $cc) { if ($cc->category) { $courses["{$cc->id}"] = format_string($cc->fullname); } else { $courses["{$cc->id}"] = format_string($cc->fullname) . ' (Site)'; } } } asort($courses); } $activities = array(); $selectedactivity = ""; /// Casting $course->modinfo to string prevents one notice when the field is null if ($modinfo = unserialize((string) $course->modinfo)) { $section = 0; if ($course->format == 'weeks') { // Bodgy $strsection = get_string("week"); } else { $strsection = get_string("topic"); } foreach ($modinfo as $mod) { if ($mod->mod == "label") { continue; } if ($mod->section > 0 and $section != $mod->section) { $activities["section/{$mod->section}"] = "-------------- {$strsection} {$mod->section} --------------"; } $section = $mod->section; $mod->name = strip_tags(format_string(urldecode($mod->name), true)); if (strlen($mod->name) > 55) { $mod->name = substr($mod->name, 0, 50) . "..."; } if (!$mod->visible) { $mod->name = "(" . $mod->name . ")"; } $activities["{$mod->cm}"] = $mod->name; if ($mod->cm == $modid) { $selectedactivity = "{$mod->cm}"; } } } if (has_capability('moodle/site:viewreports', $sitecontext) && $course->id == SITEID) { $activities["site_errors"] = get_string("siteerrors"); if ($modid === "site_errors") { $selectedactivity = "site_errors"; } } $strftimedate = get_string("strftimedate"); $strftimedaydate = get_string("strftimedaydate"); asort($users); // Prepare the list of action options. $actions = array('view' => get_string('view'), 'add' => get_string('add'), 'update' => get_string('update'), 'delete' => get_string('delete'), '-view' => get_string('allchanges')); // Get all the possible dates // Note that we are keeping track of real (GMT) time and user time // User time is only used in displays - all calcs and passing is GMT $timenow = time(); // GMT // What day is it now for the user, and when is midnight that day (in GMT). $timemidnight = $today = usergetmidnight($timenow); // Put today up the top of the list $dates = array("{$timemidnight}" => get_string("today") . ", " . userdate($timenow, $strftimedate)); if (!$course->startdate or $course->startdate > $timenow) { $course->startdate = $course->timecreated; } $numdates = 1; while ($timemidnight > $course->startdate and $numdates < 365) { $timemidnight = $timemidnight - 86400; $timenow = $timenow - 86400; $dates["{$timemidnight}"] = userdate($timenow, $strftimedaydate); $numdates++; } if ($selecteddate == "today") { $selecteddate = $today; } echo "<form class=\"logselectform\" action=\"{$CFG->wwwroot}/course/report/log/index.php\" method=\"get\">\n"; echo "<div>\n"; echo "<input type=\"hidden\" name=\"chooselog\" value=\"1\" />\n"; echo "<input type=\"hidden\" name=\"showusers\" value=\"{$showusers}\" />\n"; echo "<input type=\"hidden\" name=\"showcourses\" value=\"{$showcourses}\" />\n"; if (has_capability('moodle/site:viewreports', $sitecontext) && $showcourses) { choose_from_menu($courses, "id", $course->id, ""); } else { // echo '<input type="hidden" name="id" value="'.$course->id.'" />'; $courses = array(); $courses[$course->id] = $course->fullname . ($course->id == SITEID ? ' (' . get_string('site') . ') ' : ''); choose_from_menu($courses, "id", $course->id, false); if (has_capability('moodle/site:viewreports', $sitecontext)) { $a = new object(); $a->url = "{$CFG->wwwroot}/course/report/log/index.php?chooselog=0&group={$selectedgroup}&user={$selecteduser}" . "&id={$course->id}&date={$selecteddate}&modid={$selectedactivity}&showcourses=1&showusers={$showusers}"; print_string('logtoomanycourses', 'moodle', $a); } } if ($showgroups) { if ($cgroups = groups_get_all_groups($course->id)) { foreach ($cgroups as $cgroup) { $groups[$cgroup->id] = $cgroup->name; } } else { $groups = array(); } choose_from_menu($groups, "group", $selectedgroup, get_string("allgroups")); } if ($showusers) { choose_from_menu($users, "user", $selecteduser, get_string("allparticipants")); } else { $users = array(); if (!empty($selecteduser)) { $user = get_record('user', 'id', $selecteduser); $users[$selecteduser] = fullname($user); } else { $users[0] = get_string('allparticipants'); } choose_from_menu($users, 'user', $selecteduser, false); $a = new object(); $a->url = "{$CFG->wwwroot}/course/report/log/index.php?chooselog=0&group={$selectedgroup}&user={$selecteduser}" . "&id={$course->id}&date={$selecteddate}&modid={$selectedactivity}&showusers=1&showcourses={$showcourses}"; print_string('logtoomanyusers', 'moodle', $a); } choose_from_menu($dates, "date", $selecteddate, get_string("alldays")); choose_from_menu($activities, "modid", $selectedactivity, get_string("allactivities"), "", ""); choose_from_menu($actions, 'modaction', $modaction, get_string("allactions")); $logformats = array('showashtml' => get_string('displayonpage'), 'downloadascsv' => get_string('downloadtext'), 'downloadasods' => get_string('downloadods'), 'downloadasexcel' => get_string('downloadexcel')); choose_from_menu($logformats, 'logformat', $logformat, false); echo '<input type="submit" value="' . get_string('gettheselogs') . '" />'; echo '</div>'; echo '</form>'; }
/** * Works out the next time the automated backup should be run. * * @param mixed $timezone * @param int $now * @return int */ public static function calculate_next_automated_backup($timezone, $now) { $result = -1; $config = get_config('backup'); $midnight = usergetmidnight($now, $timezone); $date = usergetdate($now, $timezone); //Get number of days (from today) to execute backups $automateddays = substr($config->backup_auto_weekdays, $date['wday']) . $config->backup_auto_weekdays; $daysfromtoday = strpos($automateddays, "1"); if (empty($daysfromtoday)) { $daysfromtoday = 1; } //If some day has been found if ($daysfromtoday !== false) { //Calculate distance $dist = $daysfromtoday * 86400 + $config->backup_auto_hour * 3600 + $config->backup_auto_minute * 60; //Minutes distance $result = $midnight + $dist; } //If that time is past, call the function recursively to obtain the next valid day if ($result > 0 && $result < time()) { $result = self::calculate_next_automated_backup($timezone, $result); } return $result; }