/** * Test for the forum email renderable postdate. * * @dataProvider postdate_provider * * @param array $globalconfig The configuration to set on $CFG * @param array $forumconfig The configuration for this forum * @param array $postconfig The configuration for this post * @param array $discussionconfig The configuration for this discussion * @param string $expectation The expected date */ public function test_postdate($globalconfig, $forumconfig, $postconfig, $discussionconfig, $expectation) { global $CFG, $DB; $this->resetAfterTest(true); // Apply the global configuration. foreach ($globalconfig as $key => $value) { $CFG->{$key} = $value; } // Create the fixture. $user = $this->getDataGenerator()->create_user(); $course = $this->getDataGenerator()->create_course(); $forum = $this->getDataGenerator()->create_module('forum', (object) array('course' => $course->id)); $cm = get_coursemodule_from_instance('forum', $forum->id, $course->id, false, MUST_EXIST); $this->getDataGenerator()->enrol_user($user->id, $course->id); // Create a new discussion. $discussion = $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion((object) array_merge($discussionconfig, array('course' => $course->id, 'forum' => $forum->id, 'userid' => $user->id))); // Apply the discussion configuration. // Some settings are ignored by the generator and must be set manually. $discussion = $DB->get_record('forum_discussions', array('id' => $discussion->id)); foreach ($discussionconfig as $key => $value) { $discussion->{$key} = $value; } $DB->update_record('forum_discussions', $discussion); // Apply the post configuration. // Some settings are ignored by the generator and must be set manually. $post = $DB->get_record('forum_posts', array('discussion' => $discussion->id)); foreach ($postconfig as $key => $value) { $post->{$key} = $value; } $DB->update_record('forum_posts', $post); // Create the renderable. $renderable = new mod_forum\output\forum_post_email($course, $cm, $forum, $discussion, $post, $user, $user, true); // Check the postdate matches our expectations. $this->assertEquals(userdate($expectation, "", \core_date::get_user_timezone($user)), $renderable->get_postdate()); }
public function date($message, $viewmail = false) { $tz = core_date::get_user_timezone(); $date = new DateTime('now', new DateTimeZone($tz)); $offset = ($date->getOffset() - dst_offset_on(time(), $tz)) / (3600.0); $time = ($offset < 13) ? $message->time() + $offset : $message->time(); $now = ($offset < 13) ? time() + $offset : time(); $daysago = floor($now / 86400) - floor($time / 86400); $yearsago = (int) date('Y', $now) - (int) date('Y', $time); $tooltip = userdate($time, get_string('strftimedatetime')); if ($viewmail) { $content = userdate($time, get_string('strftimedatetime')); $tooltip = ''; } else if ($daysago == 0) { $content = userdate($time, get_string('strftimetime')); } else if ($yearsago == 0) { $content = userdate($time, get_string('strftimedateshort')); } else { $content = userdate($time, get_string('strftimedate')); } return html_writer::tag('span', s($content), array('class' => 'mail_date', 'title' => $tooltip)); }
/** * Construct an array with subtitution rules for mail templates, relating to * a single appointment. Any of the parameters can be null. * @param scheduler_instance $scheduler The scheduler instance * @param scheduler_slot $slot The slot data as an MVC object * @param user $attendant A {@link $USER} object describing the attendant (teacher) * @param user $attendee A {@link $USER} object describing the attendee (student) * @param object $course A course object relating to the ontext of the message * @param object $recipient A {@link $USER} object describing the recipient of the message (used for determining the message language) * @return array A hash with mail template substitutions */ function scheduler_get_mail_variables(scheduler_instance $scheduler, scheduler_slot $slot, $attendant, $attendee, $course, $recipient) { global $CFG; $lang = scheduler_get_message_language($recipient, $course); // Force any string formatting to happen in the target language. $oldlang = force_current_language($lang); $tz = core_date::get_user_timezone($recipient); $vars = array(); if ($scheduler) { $vars['MODULE'] = $scheduler->name; $vars['STAFFROLE'] = $scheduler->get_teacher_name(); $vars['SCHEDULER_URL'] = $CFG->wwwroot . '/mod/scheduler/view.php?id=' . $scheduler->cmid; } if ($slot) { $vars['DATE'] = userdate($slot->starttime, get_string('strftimedate'), $tz); $vars['TIME'] = userdate($slot->starttime, get_string('strftimetime'), $tz); $vars['ENDTIME'] = userdate($slot->endtime, get_string('strftimetime'), $tz); $vars['LOCATION'] = format_string($slot->appointmentlocation); } if ($attendant) { $vars['ATTENDANT'] = fullname($attendant); $vars['ATTENDANT_URL'] = $CFG->wwwroot . '/user/view.php?id=' . $attendant->id . '&course=' . $scheduler->course; } if ($attendee) { $vars['ATTENDEE'] = fullname($attendee); $vars['ATTENDEE_URL'] = $CFG->wwwroot . '/user/view.php?id=' . $attendee->id . '&course=' . $scheduler->course; } // Reset language settings. force_current_language($oldlang); return $vars; }
/** * @global object * @param object $message message to be displayed. * @param mixed $chatuser user chat data * @param object $currentuser current user for whom the message should be displayed. * @param int $groupingid course module grouping id * @param string $theme name of the chat theme. * @return bool|string Returns HTML or false */ function chat_format_message_theme($message, $chatuser, $currentuser, $groupingid, $theme = 'bubble') { global $CFG, $USER, $OUTPUT, $COURSE, $DB, $PAGE; require_once $CFG->dirroot . '/mod/chat/locallib.php'; static $users; // Cache user lookups. $result = new stdClass(); if (file_exists($CFG->dirroot . '/mod/chat/gui_ajax/theme/' . $theme . '/config.php')) { include $CFG->dirroot . '/mod/chat/gui_ajax/theme/' . $theme . '/config.php'; } if (isset($users[$message->userid])) { $sender = $users[$message->userid]; } else { if ($sender = $DB->get_record('user', array('id' => $message->userid), user_picture::fields())) { $users[$message->userid] = $sender; } else { return null; } } // Find the correct timezone for displaying this message. $tz = core_date::get_user_timezone($currentuser); if (empty($chatuser->course)) { $courseid = $COURSE->id; } else { $courseid = $chatuser->course; } $message->strtime = userdate($message->timestamp, get_string('strftimemessage', 'chat'), $tz); $message->picture = $OUTPUT->user_picture($sender, array('courseid' => $courseid)); $message->picture = "<a target='_blank'" . " href=\"{$CFG->wwwroot}/user/view.php?id={$sender->id}&course={$courseid}\">{$message->picture}</a>"; // Start processing the message. if (!empty($message->system)) { $result->type = 'system'; $senderprofile = $CFG->wwwroot . '/user/view.php?id=' . $sender->id . '&course=' . $courseid; $event = get_string('message' . $message->message, 'chat', fullname($sender)); $eventmessage = new event_message($senderprofile, fullname($sender), $message->strtime, $event, $theme); $output = $PAGE->get_renderer('mod_chat'); $result->html = $output->render($eventmessage); return $result; } // It's not a system event. $text = trim($message->message); // Parse the text to clean and filter it. $options = new stdClass(); $options->para = false; $text = format_text($text, FORMAT_MOODLE, $options, $courseid); // And now check for special cases. $special = false; $outtime = $message->strtime; // Initialise variables. $outmain = ''; $patternto = '#^\\s*To\\s([^:]+):(.*)#'; if (substr($text, 0, 5) == 'beep ') { $special = true; // It's a beep! $result->type = 'beep'; $beepwho = trim(substr($text, 5)); if ($beepwho == 'all') { // Everyone. $outmain = get_string('messagebeepseveryone', 'chat', fullname($sender)); } else { if ($beepwho == $currentuser->id) { // Current user. $outmain = get_string('messagebeepsyou', 'chat', fullname($sender)); } else { if ($sender->id == $currentuser->id) { // Something is not caught? // Allow beep for a active chat user only, else user can beep anyone and get fullname. if (!empty($chatuser) && is_numeric($beepwho)) { $chatusers = chat_get_users($chatuser->chatid, $chatuser->groupid, $groupingid); if (array_key_exists($beepwho, $chatusers)) { $outmain = get_string('messageyoubeep', 'chat', fullname($chatusers[$beepwho])); } else { $outmain = get_string('messageyoubeep', 'chat', $beepwho); } } else { $outmain = get_string('messageyoubeep', 'chat', $beepwho); } } } } } else { if (substr($text, 0, 1) == '/') { // It's a user command. $special = true; $result->type = 'command'; $pattern = '#(^\\/)(\\w+).*#'; preg_match($pattern, $text, $matches); $command = isset($matches[2]) ? $matches[2] : false; // Support some IRC commands. switch ($command) { case 'me': $outmain = '*** <b>' . $sender->firstname . ' ' . substr($text, 4) . '</b>'; break; default: // Error, we set special back to false to use the classic message output. $special = false; break; } } else { if (preg_match($patternto, $text)) { $special = true; $result->type = 'dialogue'; $matches = array(); preg_match($patternto, $text, $matches); if (isset($matches[1]) && isset($matches[2])) { $outmain = $sender->firstname . ' <b>' . get_string('saidto', 'chat') . '</b> <i>' . $matches[1] . '</i>: ' . $matches[2]; } else { // Error, we set special back to false to use the classic message output. $special = false; } } } } if (!$special) { $outmain = $text; } $result->text = strip_tags($outtime . ': ' . $outmain); $mymessageclass = ''; if ($sender->id == $USER->id) { $mymessageclass = 'chat-message-mymessage'; } $senderprofile = $CFG->wwwroot . '/user/view.php?id=' . $sender->id . '&course=' . $courseid; $usermessage = new user_message($senderprofile, fullname($sender), $message->picture, $mymessageclass, $outtime, $outmain, $theme); $output = $PAGE->get_renderer('mod_chat'); $result->html = $output->render($usermessage); // When user beeps other user, then don't show any timestamp to other users in chat. if ('' === $outmain && $special) { return false; } else { return $result; } }
/** * Calculates the Daylight Saving Offset for a given date/time (timestamp) * - Note: Daylight saving only works for string timezones and not for float. * * @package core * @category time * @param int $time must NOT be compensated at all, it has to be a pure timestamp * @param int|float|string $strtimezone user timezone * @return int */ function dst_offset_on($time, $strtimezone = null) { $tz = core_date::get_user_timezone($strtimezone); $date = new DateTime('@' . $time); $date->setTimezone(new DateTimeZone($tz)); if ($date->format('I') == '1') { if ($tz === 'Australia/Lord_Howe') { return 1800; } return 3600; } return 0; }
/** * Powerful function that is used by edit and editadvanced to add common form elements/rules/etc. * * @param moodleform $mform * @param array $editoroptions * @param array $filemanageroptions * @param stdClass $user */ function useredit_shared_definition(&$mform, $editoroptions, $filemanageroptions, $user) { global $CFG, $USER, $DB; if ($user->id > 0) { useredit_load_preferences($user, false); } $strrequired = get_string('required'); $stringman = get_string_manager(); // Add the necessary names. foreach (useredit_get_required_name_fields() as $fullname) { $mform->addElement('text', $fullname, get_string($fullname), 'maxlength="100" size="30"'); if ($stringman->string_exists('missing' . $fullname, 'core')) { $strmissingfield = get_string('missing' . $fullname, 'core'); } else { $strmissingfield = $strrequired; } $mform->addRule($fullname, $strmissingfield, 'required', null, 'client'); $mform->setType($fullname, PARAM_NOTAGS); } $enabledusernamefields = useredit_get_enabled_name_fields(); // Add the enabled additional name fields. foreach ($enabledusernamefields as $addname) { $mform->addElement('text', $addname, get_string($addname), 'maxlength="100" size="30"'); $mform->setType($addname, PARAM_NOTAGS); } // Do not show email field if change confirmation is pending. if ($user->id > 0 and !empty($CFG->emailchangeconfirmation) and !empty($user->preference_newemail)) { $notice = get_string('emailchangepending', 'auth', $user); $notice .= '<br /><a href="edit.php?cancelemailchange=1&id=' . $user->id . '">' . get_string('emailchangecancel', 'auth') . '</a>'; $mform->addElement('static', 'emailpending', get_string('email'), $notice); } else { $mform->addElement('text', 'email', get_string('email'), 'maxlength="100" size="30"'); $mform->addRule('email', $strrequired, 'required', null, 'client'); $mform->setType('email', PARAM_RAW_TRIMMED); } $choices = array(); $choices['0'] = get_string('emaildisplayno'); $choices['1'] = get_string('emaildisplayyes'); $choices['2'] = get_string('emaildisplaycourse'); $mform->addElement('select', 'maildisplay', get_string('emaildisplay'), $choices); $mform->setDefault('maildisplay', core_user::get_property_default('maildisplay')); $mform->addElement('text', 'city', get_string('city'), 'maxlength="120" size="21"'); $mform->setType('city', PARAM_TEXT); if (!empty($CFG->defaultcity)) { $mform->setDefault('city', $CFG->defaultcity); } $choices = get_string_manager()->get_list_of_countries(); $choices = array('' => get_string('selectacountry') . '...') + $choices; $mform->addElement('select', 'country', get_string('selectacountry'), $choices); if (!empty($CFG->country)) { $mform->setDefault('country', core_user::get_property_default('country')); } if (isset($CFG->forcetimezone) and $CFG->forcetimezone != 99) { $choices = core_date::get_list_of_timezones($CFG->forcetimezone); $mform->addElement('static', 'forcedtimezone', get_string('timezone'), $choices[$CFG->forcetimezone]); $mform->addElement('hidden', 'timezone'); $mform->setType('timezone', core_user::get_property_type('timezone')); } else { $choices = core_date::get_list_of_timezones($user->timezone, true); $mform->addElement('select', 'timezone', get_string('timezone'), $choices); } if (!empty($CFG->allowuserthemes)) { $choices = array(); $choices[''] = get_string('default'); $themes = get_list_of_themes(); foreach ($themes as $key => $theme) { if (empty($theme->hidefromselector)) { $choices[$key] = get_string('pluginname', 'theme_' . $theme->name); } } $mform->addElement('select', 'theme', get_string('preferredtheme'), $choices); } $mform->addElement('editor', 'description_editor', get_string('userdescription'), null, $editoroptions); $mform->setType('description_editor', PARAM_CLEANHTML); $mform->addHelpButton('description_editor', 'userdescription'); if (empty($USER->newadminuser)) { $mform->addElement('header', 'moodle_picture', get_string('pictureofuser')); $mform->setExpanded('moodle_picture', true); if (!empty($CFG->enablegravatar)) { $mform->addElement('html', html_writer::tag('p', get_string('gravatarenabled'))); } $mform->addElement('static', 'currentpicture', get_string('currentpicture')); $mform->addElement('checkbox', 'deletepicture', get_string('delete')); $mform->setDefault('deletepicture', 0); $mform->addElement('filemanager', 'imagefile', get_string('newpicture'), '', $filemanageroptions); $mform->addHelpButton('imagefile', 'newpicture'); $mform->addElement('text', 'imagealt', get_string('imagealt'), 'maxlength="100" size="30"'); $mform->setType('imagealt', PARAM_TEXT); } // Display user name fields that are not currenlty enabled here if there are any. $disabledusernamefields = useredit_get_disabled_name_fields($enabledusernamefields); if (count($disabledusernamefields) > 0) { $mform->addElement('header', 'moodle_additional_names', get_string('additionalnames')); foreach ($disabledusernamefields as $allname) { $mform->addElement('text', $allname, get_string($allname), 'maxlength="100" size="30"'); $mform->setType($allname, PARAM_NOTAGS); } } if (core_tag_tag::is_enabled('core', 'user') and empty($USER->newadminuser)) { $mform->addElement('header', 'moodle_interests', get_string('interests')); $mform->addElement('tags', 'interests', get_string('interestslist'), array('itemtype' => 'user', 'component' => 'core')); $mform->addHelpButton('interests', 'interestslist'); } // Moodle optional fields. $mform->addElement('header', 'moodle_optional', get_string('optional', 'form')); $mform->addElement('text', 'url', get_string('webpage'), 'maxlength="255" size="50"'); $mform->setType('url', core_user::get_property_type('url')); $mform->addElement('text', 'icq', get_string('icqnumber'), 'maxlength="15" size="25"'); $mform->setType('icq', core_user::get_property_type('icq')); $mform->setForceLtr('icq'); $mform->addElement('text', 'skype', get_string('skypeid'), 'maxlength="50" size="25"'); $mform->setType('skype', core_user::get_property_type('skype')); $mform->setForceLtr('skype'); $mform->addElement('text', 'aim', get_string('aimid'), 'maxlength="50" size="25"'); $mform->setType('aim', core_user::get_property_type('aim')); $mform->setForceLtr('aim'); $mform->addElement('text', 'yahoo', get_string('yahooid'), 'maxlength="50" size="25"'); $mform->setType('yahoo', core_user::get_property_type('yahoo')); $mform->setForceLtr('yahoo'); $mform->addElement('text', 'msn', get_string('msnid'), 'maxlength="50" size="25"'); $mform->setType('msn', core_user::get_property_type('msn')); $mform->setForceLtr('msn'); $mform->addElement('text', 'idnumber', get_string('idnumber'), 'maxlength="255" size="25"'); $mform->setType('idnumber', core_user::get_property_type('idnumber')); $mform->addElement('text', 'institution', get_string('institution'), 'maxlength="255" size="25"'); $mform->setType('institution', core_user::get_property_type('institution')); $mform->addElement('text', 'department', get_string('department'), 'maxlength="255" size="25"'); $mform->setType('department', core_user::get_property_type('department')); $mform->addElement('text', 'phone1', get_string('phone1'), 'maxlength="20" size="25"'); $mform->setType('phone1', core_user::get_property_type('phone1')); $mform->setForceLtr('phone1'); $mform->addElement('text', 'phone2', get_string('phone2'), 'maxlength="20" size="25"'); $mform->setType('phone2', core_user::get_property_type('phone2')); $mform->setForceLtr('phone2'); $mform->addElement('text', 'address', get_string('address'), 'maxlength="255" size="25"'); $mform->setType('address', core_user::get_property_type('address')); }
$CFG->ostype = 'WINDOWS'; } else { $CFG->ostype = 'UNIX'; } $CFG->os = PHP_OS; // Configure ampersands in URLs ini_set('arg_separator.output', '&'); // Work around for a PHP bug see MDL-11237 ini_set('pcre.backtrack_limit', 20971520); // 20 MB // Work around for PHP7 bug #70110. See MDL-52475 . if (ini_get('pcre.jit')) { ini_set('pcre.jit', 0); } // Set PHP default timezone to server timezone. core_date::set_default_server_timezone(); // Location of standard files $CFG->wordlist = $CFG->libdir . '/wordlist.txt'; $CFG->moddata = 'moddata'; // neutralise nasty chars in PHP_SELF if (isset($_SERVER['PHP_SELF'])) { $phppos = strpos($_SERVER['PHP_SELF'], '.php'); if ($phppos !== false) { $_SERVER['PHP_SELF'] = substr($_SERVER['PHP_SELF'], 0, $phppos + 4); } unset($phppos); } // initialise ME's - this must be done BEFORE starting of session! initialise_fullme(); // define SYSCONTEXTID in config.php if you want to save some queries, // after install it must match the system context record id.
/** * Returns a list of files the user has formated for files api * * @param string $search A search string to do full text search on the documents * @return mixed Array of files formated for fileapoi */ public function get_file_list($search = '') { global $CFG, $OUTPUT; $url = self::DOCUMENTFEED_URL; if ($search) { $url .= '?q=' . urlencode($search); } $files = array(); $content = $this->googleoauth->get($url); try { if (strpos($content, '<?xml') !== 0) { throw new moodle_exception('invalidxmlresponse'); } $xml = new SimpleXMLElement($content); } catch (Exception $e) { // An error occured while trying to parse the XML, let's just return nothing. SimpleXML does not // return a more specific Exception, that's why the global Exception class is caught here. return $files; } date_default_timezone_set(core_date::get_user_timezone()); foreach ($xml->entry as $gdoc) { $docid = (string) $gdoc->children('http://schemas.google.com/g/2005')->resourceId; list($type, $docid) = explode(':', $docid); $title = ''; $source = ''; // FIXME: We're making hard-coded choices about format here. // If the repo api can support it, we could let the user // chose. switch ($type) { case 'document': $title = $gdoc->title . '.rtf'; $source = 'https://docs.google.com/feeds/download/documents/Export?id=' . $docid . '&exportFormat=rtf'; break; case 'presentation': $title = $gdoc->title . '.ppt'; $source = 'https://docs.google.com/feeds/download/presentations/Export?id=' . $docid . '&exportFormat=ppt'; break; case 'spreadsheet': $title = $gdoc->title . '.xls'; $source = 'https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=' . $docid . '&exportFormat=xls'; break; case 'pdf': case 'file': $title = (string) $gdoc->title; // Some files don't have a content probably because the download has been restricted. if (isset($gdoc->content)) { $source = (string) $gdoc->content[0]->attributes()->src; } break; } $files[] = array('title' => $title, 'url' => "{$gdoc->link[0]->attributes()->href}", 'source' => $source, 'date' => strtotime($gdoc->updated), 'thumbnail' => (string) $OUTPUT->pix_url(file_extension_icon($title, 32))); } core_date::set_default_server_timezone(); return $files; }
/** * Start of month * @param int $time timestamp * @return int start of month */ function stats_get_base_monthly($time = 0) { if (empty($time)) { $time = time(); } core_date::set_default_server_timezone(); $return = strtotime(date('1-M-Y', $time)); return $return; }
/** * Works out the next time the automated backup should be run. * * @param mixed $ignoredtimezone all settings are in server timezone! * @param int $now timestamp, should not be in the past, most likely time() * @return int timestamp of the next execution at server time */ public static function calculate_next_automated_backup($ignoredtimezone, $now) { $config = get_config('backup'); $backuptime = new DateTime('@' . $now); $backuptime->setTimezone(core_date::get_server_timezone_object()); $backuptime->setTime($config->backup_auto_hour, $config->backup_auto_minute); while ($backuptime->getTimestamp() < $now) { $backuptime->add(new DateInterval('P1D')); } // Get number of days from backup date to execute backups. $automateddays = substr($config->backup_auto_weekdays, $backuptime->format('w')) . $config->backup_auto_weekdays; $daysfromnow = strpos($automateddays, "1"); // Error, there are no days to schedule the backup for. if ($daysfromnow === false) { return 0; } if ($daysfromnow > 0) { $backuptime->add(new DateInterval('P' . $daysfromnow . 'D')); } return $backuptime->getTimestamp(); }
/** * this is a very cut down version of what is in forum_make_mail_post * * @global object * @param int $post * @return string */ private function prepare_post($post, $fileoutputextras = null) { global $DB; static $users; if (empty($users)) { $users = array($this->user->id => $this->user); } if (!array_key_exists($post->userid, $users)) { $users[$post->userid] = $DB->get_record('user', array('id' => $post->userid)); } // add the user object on to the post so we can pass it to the leap writer if necessary $post->author = $users[$post->userid]; $viewfullnames = true; // format the post body $options = portfolio_format_text_options(); $format = $this->get('exporter')->get('format'); $formattedtext = format_text($post->message, $post->messageformat, $options, $this->get('course')->id); $formattedtext = portfolio_rewrite_pluginfile_urls($formattedtext, $this->modcontext->id, 'mod_forum', 'post', $post->id, $format); $output = '<table border="0" cellpadding="3" cellspacing="0" class="forumpost">'; $output .= '<tr class="header"><td>'; // can't print picture. $output .= '</td>'; if ($post->parent) { $output .= '<td class="topic">'; } else { $output .= '<td class="topic starter">'; } $output .= '<div class="subject">' . format_string($post->subject) . '</div>'; $fullname = fullname($users[$post->userid], $viewfullnames); $by = new stdClass(); $by->name = $fullname; $by->date = userdate($post->modified, '', core_date::get_user_timezone($this->user)); $output .= '<div class="author">' . get_string('bynameondate', 'forum', $by) . '</div>'; $output .= '</td></tr>'; $output .= '<tr><td class="left side" valign="top">'; $output .= '</td><td class="content">'; $output .= $formattedtext; if (is_array($this->keyedfiles) && array_key_exists($post->id, $this->keyedfiles) && is_array($this->keyedfiles[$post->id]) && count($this->keyedfiles[$post->id]) > 0) { $output .= '<div class="attachments">'; $output .= '<br /><b>' . get_string('attachments', 'forum') . '</b>:<br /><br />'; foreach ($this->keyedfiles[$post->id] as $file) { $output .= $format->file_output($file) . '<br/ >'; } $output .= "</div>"; } $output .= '</td></tr></table>' . "\n\n"; return $output; }
/** * Definition of user profile fields and the expected parameter type for data validation. * * array( * 'property_name' => array( // The user property to be checked. Should match the field on the user table. * 'null' => NULL_ALLOWED, // Defaults to NULL_NOT_ALLOWED. Takes NULL_NOT_ALLOWED or NULL_ALLOWED. * 'type' => PARAM_TYPE, // Expected parameter type of the user field. * 'choices' => array(1, 2..) // An array of accepted values of the user field. * 'default' => $CFG->setting // An default value for the field. * ) * ) * * The fields choices and default are optional. * * @return void */ protected static function fill_properties_cache() { global $CFG; if (self::$propertiescache !== null) { return; } // Array of user fields properties and expected parameters. // Every new field on the user table should be added here otherwise it won't be validated. $fields = array(); $fields['id'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['auth'] = array('type' => PARAM_AUTH, 'null' => NULL_NOT_ALLOWED); $fields['confirmed'] = array('type' => PARAM_BOOL, 'null' => NULL_NOT_ALLOWED); $fields['policyagreed'] = array('type' => PARAM_BOOL, 'null' => NULL_NOT_ALLOWED); $fields['deleted'] = array('type' => PARAM_BOOL, 'null' => NULL_NOT_ALLOWED); $fields['suspended'] = array('type' => PARAM_BOOL, 'null' => NULL_NOT_ALLOWED); $fields['mnethostid'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['username'] = array('type' => PARAM_USERNAME, 'null' => NULL_NOT_ALLOWED); $fields['password'] = array('type' => PARAM_RAW, 'null' => NULL_NOT_ALLOWED); $fields['idnumber'] = array('type' => PARAM_RAW, 'null' => NULL_NOT_ALLOWED); $fields['firstname'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['lastname'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['surname'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['email'] = array('type' => PARAM_RAW_TRIMMED, 'null' => NULL_NOT_ALLOWED); $fields['emailstop'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['icq'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['skype'] = array('type' => PARAM_NOTAGS, 'null' => NULL_ALLOWED); $fields['aim'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['yahoo'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['msn'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['phone1'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['phone2'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['institution'] = array('type' => PARAM_TEXT, 'null' => NULL_NOT_ALLOWED); $fields['department'] = array('type' => PARAM_TEXT, 'null' => NULL_NOT_ALLOWED); $fields['address'] = array('type' => PARAM_TEXT, 'null' => NULL_NOT_ALLOWED); $fields['city'] = array('type' => PARAM_TEXT, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->defaultcity); $fields['country'] = array('type' => PARAM_ALPHA, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->country, 'choices' => array_merge(array('' => ''), get_string_manager()->get_list_of_countries(true, true))); $fields['lang'] = array('type' => PARAM_LANG, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->lang, 'choices' => array_merge(array('' => ''), get_string_manager()->get_list_of_translations(false))); $fields['calendartype'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->calendartype, 'choices' => array_merge(array('' => ''), \core_calendar\type_factory::get_list_of_calendar_types())); $fields['theme'] = array('type' => PARAM_THEME, 'null' => NULL_NOT_ALLOWED, 'default' => theme_config::DEFAULT_THEME, 'choices' => array_merge(array('' => ''), get_list_of_themes())); $fields['timezone'] = array('type' => PARAM_TIMEZONE, 'null' => NULL_NOT_ALLOWED, 'default' => core_date::get_server_timezone()); // Must not use choices here: timezones can come and go. $fields['firstaccess'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['lastaccess'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['lastlogin'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['currentlogin'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['lastip'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['secret'] = array('type' => PARAM_RAW, 'null' => NULL_NOT_ALLOWED); $fields['picture'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['url'] = array('type' => PARAM_URL, 'null' => NULL_NOT_ALLOWED); $fields['description'] = array('type' => PARAM_RAW, 'null' => NULL_ALLOWED); $fields['descriptionformat'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['mailformat'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->defaultpreference_mailformat); $fields['maildigest'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->defaultpreference_maildigest); $fields['maildisplay'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->defaultpreference_maildisplay); $fields['autosubscribe'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->defaultpreference_autosubscribe); $fields['trackforums'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, 'default' => $CFG->defaultpreference_trackforums); $fields['timecreated'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['timemodified'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['trustbitmask'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['imagealt'] = array('type' => PARAM_TEXT, 'null' => NULL_ALLOWED); $fields['lastnamephonetic'] = array('type' => PARAM_NOTAGS, 'null' => NULL_ALLOWED); $fields['firstnamephonetic'] = array('type' => PARAM_NOTAGS, 'null' => NULL_ALLOWED); $fields['middlename'] = array('type' => PARAM_NOTAGS, 'null' => NULL_ALLOWED); $fields['alternatename'] = array('type' => PARAM_NOTAGS, 'null' => NULL_ALLOWED); self::$propertiescache = $fields; }
*/ defined('MOODLE_INTERNAL') || die; if ($ADMIN->fulltree) { $settings->add(new admin_setting_heading('enrol_lti_settings', '', get_string('pluginname_desc', 'enrol_lti'))); if (!is_enabled_auth('lti')) { $notify = new \core\output\notification(get_string('authltimustbeenabled', 'enrol_lti'), \core\output\notification::NOTIFY_WARNING); $settings->add(new admin_setting_heading('enrol_lti_enable_auth_lti', '', $OUTPUT->render($notify))); } if (empty($CFG->allowframembedding)) { $notify = new \core\output\notification(get_string('allowframeembedding', 'enrol_lti'), \core\output\notification::NOTIFY_WARNING); $settings->add(new admin_setting_heading('enrol_lti_enable_embedding', '', $OUTPUT->render($notify))); } $settings->add(new admin_setting_heading('enrol_lti_user_default_values', get_string('userdefaultvalues', 'enrol_lti'), '')); $choices = array(0 => get_string('emaildisplayno'), 1 => get_string('emaildisplayyes'), 2 => get_string('emaildisplaycourse')); $maildisplay = isset($CFG->defaultpreference_maildisplay) ? $CFG->defaultpreference_maildisplay : 2; $settings->add(new admin_setting_configselect('enrol_lti/emaildisplay', get_string('emaildisplay'), '', $maildisplay, $choices)); $city = ''; if (!empty($CFG->defaultcity)) { $city = $CFG->defaultcity; } $settings->add(new admin_setting_configtext('enrol_lti/city', get_string('city'), '', $city)); $country = ''; if (!empty($CFG->country)) { $country = $CFG->country; } $countries = array('' => get_string('selectacountry') . '...') + get_string_manager()->get_list_of_countries(); $settings->add(new admin_setting_configselect('enrol_lti/country', get_string('selectacountry'), '', $country, $countries)); $settings->add(new admin_setting_configselect('enrol_lti/timezone', get_string('timezone'), '', 99, core_date::get_list_of_timezones(null, true))); $settings->add(new admin_setting_configselect('enrol_lti/lang', get_string('preferredlanguage'), '', $CFG->lang, get_string_manager()->get_list_of_translations())); $settings->add(new admin_setting_configtext('enrol_lti/institution', get_string('institution'), '', '')); }
public function definition() { global $USER, $CFG, $COURSE; $mform =& $this->_form; $templateuser = $USER; $context = $this->_customdata['context']; $mform->addElement('header', 'settingsheader', get_string('toolsettings', 'local_ltiprovider')); $tools = array(); $tools[$context->id] = get_string('course'); $modinfo = get_fast_modinfo($this->_customdata['courseid']); $mods = $modinfo->get_cms(); foreach ($mods as $mod) { $tools[$mod->context->id] = format_string($mod->name); } $mform->addElement('select', 'contextid', get_string('tooltobeprovide', 'local_ltiprovider'), $tools); $mform->setDefault('contextid', $context->id); $mform->addElement('checkbox', 'sendgrades', null, get_string('sendgrades', 'local_ltiprovider')); $mform->setDefault('sendgrades', 1); $mform->addElement('checkbox', 'requirecompletion', null, get_string('requirecompletion', 'local_ltiprovider')); $mform->setDefault('requirecompletion', 0); $mform->disabledIf('requirecompletion', 'sendgrades'); $mform->addElement('checkbox', 'forcenavigation', null, get_string('forcenavigation', 'local_ltiprovider')); $mform->setDefault('forcenavigation', 1); $mform->addElement('duration', 'enrolperiod', get_string('enrolperiod', 'local_ltiprovider'), array('optional' => true, 'defaultunit' => 86400)); $mform->setDefault('enrolperiod', 0); $mform->addHelpButton('enrolperiod', 'enrolperiod', 'local_ltiprovider'); $mform->addElement('date_selector', 'enrolstartdate', get_string('enrolstartdate', 'local_ltiprovider'), array('optional' => true)); $mform->setDefault('enrolstartdate', 0); $mform->addHelpButton('enrolstartdate', 'enrolstartdate', 'local_ltiprovider'); $mform->addElement('date_selector', 'enrolenddate', get_string('enrolenddate', 'local_ltiprovider'), array('optional' => true)); $mform->setDefault('enrolenddate', 0); $mform->addHelpButton('enrolenddate', 'enrolenddate', 'local_ltiprovider'); $mform->addElement('text', 'maxenrolled', get_string('maxenrolled', 'local_ltiprovider')); $mform->setDefault('maxenrolled', 0); $mform->addHelpButton('maxenrolled', 'maxenrolled', 'local_ltiprovider'); $mform->setType('maxenrolled', PARAM_INT); $assignableroles = get_assignable_roles($context); $mform->addElement('checkbox', 'enrolinst', null, get_string('enrolinst', 'local_ltiprovider')); $mform->setDefault('enrolinst', 1); $mform->addHelpButton('enrolinst', 'enrolinst', 'local_ltiprovider'); $mform->setAdvanced('enrolinst'); $mform->addElement('checkbox', 'enrollearn', null, get_string('enrollearn', 'local_ltiprovider')); $mform->setDefault('enrollearn', 1); $mform->addHelpButton('enrollearn', 'enrollearn', 'local_ltiprovider'); $mform->setAdvanced('enrollearn'); $mform->addElement('select', 'croleinst', get_string('courseroleinstructor', 'local_ltiprovider'), $assignableroles); $mform->setDefault('croleinst', '3'); $mform->setAdvanced('croleinst'); $mform->addElement('select', 'crolelearn', get_string('courserolelearner', 'local_ltiprovider'), $assignableroles); $mform->setDefault('crolelearn', '5'); $mform->setAdvanced('crolelearn'); $mform->addElement('select', 'aroleinst', get_string('activityroleinstructor', 'local_ltiprovider'), $assignableroles); $mform->disabledIf('aroleinst', 'contextid', 'eq', $context->id); $mform->setDefault('aroleinst', '3'); $mform->setAdvanced('aroleinst'); $mform->addElement('select', 'arolelearn', get_string('activityrolelearner', 'local_ltiprovider'), $assignableroles); $mform->disabledIf('arolelearn', 'contextid', 'eq', $context->id); $mform->setDefault('arolelearn', '5'); $mform->setAdvanced('arolelearn'); $mform->addElement('header', 'remotesystem', get_string('remotesystem', 'local_ltiprovider')); $mform->addElement('text', 'secret', get_string('secret', 'local_ltiprovider'), 'maxlength="64" size="25"'); $mform->setType('secret', PARAM_MULTILANG); $mform->setDefault('secret', md5(uniqid(rand(), 1))); $mform->addRule('secret', get_string('required'), 'required'); $choices = core_text::get_encodings(); $mform->addElement('select', 'encoding', get_string('remoteencoding', 'local_ltiprovider'), $choices); $mform->setDefault('encoding', 'UTF-8'); $mform->addElement('header', 'defaultheader', get_string('userdefaultvalues', 'local_ltiprovider')); $choices = array(0 => get_string('never'), 1 => get_string('always')); $mform->addElement('select', 'userprofileupdate', get_string('userprofileupdate', 'local_ltiprovider'), $choices); $userprofileupdate = get_config('local_ltiprovider', 'userprofileupdate'); if ($userprofileupdate != -1) { $mform->setDefault('userprofileupdate', $userprofileupdate); $mform->freeze('userprofileupdate'); } else { $mform->setDefault('userprofileupdate', 1); } $choices = array(0 => get_string('emaildisplayno'), 1 => get_string('emaildisplayyes'), 2 => get_string('emaildisplaycourse')); $mform->addElement('select', 'maildisplay', get_string('emaildisplay'), $choices); $mform->setDefault('maildisplay', 2); $mform->addElement('text', 'city', get_string('city'), 'maxlength="100" size="25"'); $mform->setType('city', PARAM_MULTILANG); if (empty($CFG->defaultcity)) { $mform->setDefault('city', $templateuser->city); } else { $mform->setDefault('city', $CFG->defaultcity); } $mform->addElement('select', 'country', get_string('selectacountry'), get_string_manager()->get_list_of_countries()); if (empty($CFG->country)) { $mform->setDefault('country', $templateuser->country); } else { $mform->setDefault('country', $CFG->country); } $mform->setAdvanced('country'); $choices = core_date::get_list_of_timezones(); $choices['99'] = get_string('serverlocaltime'); $mform->addElement('select', 'timezone', get_string('timezone'), $choices); $mform->setDefault('timezone', $templateuser->timezone); $mform->setAdvanced('timezone'); $mform->addElement('select', 'lang', get_string('preferredlanguage'), get_string_manager()->get_list_of_translations()); $mform->setDefault('lang', $templateuser->lang); $mform->setAdvanced('lang'); $mform->addElement('text', 'institution', get_string('institution'), 'maxlength="40" size="25"'); $mform->setType('institution', PARAM_MULTILANG); $mform->setDefault('institution', $templateuser->institution); $mform->setAdvanced('institution'); $mform->addElement('header', 'memberships', get_string('membershipsettings', 'local_ltiprovider')); $mform->addElement('checkbox', 'syncmembers', null, get_string('enablememberssync', 'local_ltiprovider')); $mform->disabledIf('syncmembers', 'contextid', 'neq', $context->id); $options = array(); $options[30 * 60] = '30 ' . get_string('minutes'); $options[60 * 60] = '1 ' . get_string('hour'); $options[2 * 60 * 60] = '2 ' . get_string('hours'); $options[6 * 60 * 60] = '6 ' . get_string('hours'); $options[12 * 60 * 60] = '12 ' . get_string('hours'); $options[24 * 60 * 60] = '24 ' . get_string('hours'); $mform->addElement('select', 'syncperiod', get_string('syncperiod', 'local_ltiprovider'), $options); $mform->setDefault('syncperiod', 30 * 60); $mform->disabledIf('syncperiod', 'contextid', 'neq', $context->id); $options = array(); $options[1] = get_string('enrolandunenrol', 'local_ltiprovider'); $options[2] = get_string('enrolnew', 'local_ltiprovider'); $options[3] = get_string('unenrolmissing', 'local_ltiprovider'); $mform->addElement('select', 'syncmode', get_string('syncmode', 'local_ltiprovider'), $options); $mform->setDefault('syncmode', 1); $mform->disabledIf('syncmode', 'contextid', 'neq', $context->id); $mform->addElement('header', 'layoutandcss', get_string('layoutandcss', 'local_ltiprovider')); $mform->addElement('checkbox', 'hidepageheader', null, get_string('hidepageheader', 'local_ltiprovider')); $mform->addElement('checkbox', 'hidepagefooter', null, get_string('hidepagefooter', 'local_ltiprovider')); $mform->addElement('checkbox', 'hideleftblocks', null, get_string('hideleftblocks', 'local_ltiprovider')); $mform->addElement('checkbox', 'hiderightblocks', null, get_string('hiderightblocks', 'local_ltiprovider')); $mform->setAdvanced('hideleftblocks'); $mform->setAdvanced('hiderightblocks'); $editoroptions = array(); $displayoptions = array('rows' => '4', 'cols' => ''); $mform->addElement('textarea', 'customcss', get_string('customcss', 'local_ltiprovider'), $displayoptions, $editoroptions); $mform->setAdvanced('customcss'); $mform->addElement('hidden', 'id'); $mform->setType('id', PARAM_INT); $mform->addElement('hidden', 'courseid'); $mform->setType('courseid', PARAM_INT); $this->add_action_buttons(); }
/** * Creates the block's main content * * @return string */ public function get_content() { global $USER, $OUTPUT, $CFG; if (isset($this->content)) { return $this->content; } // Establish settings variables based on instance config. $showserverclock = !isset($this->config->show_clocks) || $this->config->show_clocks == B_SIMPLE_CLOCK_SHOW_BOTH || $this->config->show_clocks == B_SIMPLE_CLOCK_SHOW_SERVER_ONLY; $showuserclock = !isset($this->config->show_clocks) || $this->config->show_clocks == B_SIMPLE_CLOCK_SHOW_BOTH || $this->config->show_clocks == B_SIMPLE_CLOCK_SHOW_USER_ONLY; $showicons = !isset($this->config->show_icons) || $this->config->show_icons == 1; $showseconds = isset($this->config->show_seconds) && $this->config->show_seconds == 1; $showday = isset($this->config->show_day) && $this->config->show_day == 1; $show24hrtime = isset($this->config->twenty_four_hour_time) && $this->config->twenty_four_hour_time == 1; // Start the content, which is primarily a table. $this->content = new stdClass(); $this->content->text = ''; $this->content->footer = ''; $table = new html_table(); $table->attributes = array('class' => 'clockTable'); // First item added is the server's clock. if ($showserverclock) { $row = array(); if ($showicons) { $alt = get_string('server', 'block_simple_clock'); $usingie = false; if (class_exists('core_useragent')) { $usingie = core_useragent::is_ie(); } else { $usingie = check_browser_version('MSIE'); } if ($usingie) { $servericon = $OUTPUT->pix_icon('server', $alt, 'block_simple_clock'); } else { $servericon = $OUTPUT->pix_icon('favicon', $alt, 'theme'); } $row[] = $servericon; } $row[] = get_string('server', 'block_simple_clock') . ':'; $attributes = array(); $attributes['class'] = 'clock'; $attributes['id'] = 'block_progress_serverTime'; $attributes['value'] = get_string('loading', 'block_simple_clock'); $row[] = HTML_WRITER::empty_tag('input', $attributes); $table->data[] = $row; } // Next item is the user's clock. if ($showuserclock) { $row = array(); if ($showicons) { if ($USER->id != 0) { $userpictureparams = array('size' => 16, 'link' => false, 'alt' => 'User'); $userpicture = $OUTPUT->user_picture($USER, $userpictureparams); $row[] = $userpicture; } else { $row[] = ''; } } $row[] = get_string('you', 'block_simple_clock') . ':'; $attributes = array(); $attributes['class'] = 'clock'; $attributes['id'] = 'block_progress_youTime'; $attributes['value'] = get_string('loading', 'block_simple_clock'); $row[] = HTML_WRITER::empty_tag('input', $attributes); $table->data[] = $row; } $this->content->text .= HTML_WRITER::table($table); // Set up JavaScript code needed to keep the clock going. $noscriptstring = get_string('javascript_disabled', 'block_simple_clock'); $this->content->text .= HTML_WRITER::tag('noscript', $noscriptstring); if ($CFG->timezone != 99) { // Ensure that the Moodle timezone is set correctly. $date = new DateTime('now', new DateTimeZone(core_date::normalise_timezone($CFG->timezone))); $moodletimeoffset = $date->getOffset(); // + dst_offset_on(time(), $CFG->timezone); $servertimeoffset = date_offset_get(new DateTime()); $timearray = localtime(time() + $moodletimeoffset - $servertimeoffset, true); } else { // Ensure that the server timezone is set. // From 2.9 onwards, this should never happen. $timearray = localtime(time(), true); } $arguments = array($showserverclock, $showuserclock, $showseconds, $showday, $show24hrtime, $timearray['tm_year'] + 1900, $timearray['tm_mon'], $timearray['tm_mday'], $timearray['tm_hour'], $timearray['tm_min'], $timearray['tm_sec'] + 2); $jsmodule = array('name' => 'block_simple_clock', 'fullpath' => '/blocks/simple_clock/module.js', 'requires' => array(), 'strings' => array(array('clock_separator', 'block_simple_clock'), array('before_noon', 'block_simple_clock'), array('after_noon', 'block_simple_clock'), array('day_names', 'block_simple_clock'))); $this->page->requires->js_init_call('M.block_simple_clock.initSimpleClock', $arguments, false, $jsmodule); $this->content->footer = ''; return $this->content; }
/** * Given the data about a posting, builds up the HTML to display it and * returns the HTML in a string. This is designed for sending via HTML email. * * @global object * @param object $course * @param object $cm * @param object $forum * @param object $discussion * @param object $post * @param object $userform * @param object $userto * @param bool $ownpost * @param bool $reply * @param bool $link * @param bool $rate * @param string $footer * @return string */ function forum_make_mail_post($course, $cm, $forum, $discussion, $post, $userfrom, $userto, $ownpost = false, $reply = false, $link = false, $rate = false, $footer = "") { global $CFG, $OUTPUT; $modcontext = context_module::instance($cm->id); if (!isset($userto->viewfullnames[$forum->id])) { $viewfullnames = has_capability('moodle/site:viewfullnames', $modcontext, $userto->id); } else { $viewfullnames = $userto->viewfullnames[$forum->id]; } // add absolute file links $post->message = file_rewrite_pluginfile_urls($post->message, 'pluginfile.php', $modcontext->id, 'mod_forum', 'post', $post->id); // format the post body $options = new stdClass(); $options->para = true; $formattedtext = format_text($post->message, $post->messageformat, $options, $course->id); $output = '<table border="0" cellpadding="3" cellspacing="0" class="forumpost">'; $output .= '<tr class="header"><td width="35" valign="top" class="picture left">'; $output .= $OUTPUT->user_picture($userfrom, array('courseid' => $course->id)); $output .= '</td>'; if ($post->parent) { $output .= '<td class="topic">'; } else { $output .= '<td class="topic starter">'; } $output .= '<div class="subject">' . format_string($post->subject) . '</div>'; $fullname = fullname($userfrom, $viewfullnames); $by = new stdClass(); $by->name = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $userfrom->id . '&course=' . $course->id . '">' . $fullname . '</a>'; $by->date = userdate($post->modified, '', core_date::get_user_timezone($userto)); $output .= '<div class="author">' . get_string('bynameondate', 'forum', $by) . '</div>'; $output .= '</td></tr>'; $output .= '<tr><td class="left side" valign="top">'; if (isset($userfrom->groups)) { $groups = $userfrom->groups[$forum->id]; } else { $groups = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); } if ($groups) { $output .= print_group_picture($groups, $course->id, false, true, true); } else { $output .= ' '; } $output .= '</td><td class="content">'; $attachments = forum_print_attachments($post, $cm, 'html'); if ($attachments !== '') { $output .= '<div class="attachments">'; $output .= $attachments; $output .= '</div>'; } $output .= $formattedtext; // Commands $commands = array(); if ($post->parent) { $commands[] = '<a target="_blank" href="' . $CFG->wwwroot . '/mod/forum/discuss.php?d=' . $post->discussion . '&parent=' . $post->parent . '">' . get_string('parent', 'forum') . '</a>'; } if ($reply) { $commands[] = '<a target="_blank" href="' . $CFG->wwwroot . '/mod/forum/post.php?reply=' . $post->id . '">' . get_string('reply', 'forum') . '</a>'; } $output .= '<div class="commands">'; $output .= implode(' | ', $commands); $output .= '</div>'; // Context link to post if required if ($link) { $output .= '<div class="link">'; $output .= '<a target="_blank" href="' . $CFG->wwwroot . '/mod/forum/discuss.php?d=' . $post->discussion . '#p' . $post->id . '">' . get_string('postincontext', 'forum') . '</a>'; $output .= '</div>'; } if ($footer) { $output .= '<div class="footer">' . $footer . '</div>'; } $output .= '</td></tr></table>' . "\n\n"; return $output; }
/** * Reset contents of all database tables to initial values, reset caches, etc. * * Note: this is relatively slow (cca 2 seconds for pg and 7 for mysql) - please use with care! * * @static * @param bool $detectchanges * true - changes in global state and database are reported as errors * false - no errors reported * null - only critical problems are reported as errors * @return void */ public static function reset_all_data($detectchanges = false) { global $DB, $CFG, $USER, $SITE, $COURSE, $PAGE, $OUTPUT, $SESSION; // Stop any message redirection. phpunit_util::stop_message_redirection(); // Stop any message redirection. phpunit_util::stop_event_redirection(); // Start a new email redirection. // This will clear any existing phpmailer redirection. // We redirect all phpmailer output to this message sink which is // called instead of phpmailer actually sending the message. phpunit_util::start_phpmailer_redirection(); // We used to call gc_collect_cycles here to ensure desctructors were called between tests. // This accounted for 25% of the total time running phpunit - so we removed it. // Show any unhandled debugging messages, the runbare() could already reset it. self::display_debugging_messages(); self::reset_debugging(); // reset global $DB in case somebody mocked it $DB = self::get_global_backup('DB'); if ($DB->is_transaction_started()) { // we can not reset inside transaction $DB->force_transaction_rollback(); } $resetdb = self::reset_database(); $warnings = array(); if ($detectchanges === true) { if ($resetdb) { $warnings[] = 'Warning: unexpected database modification, resetting DB state'; } $oldcfg = self::get_global_backup('CFG'); $oldsite = self::get_global_backup('SITE'); foreach ($CFG as $k => $v) { if (!property_exists($oldcfg, $k)) { $warnings[] = 'Warning: unexpected new $CFG->' . $k . ' value'; } else { if ($oldcfg->{$k} !== $CFG->{$k}) { $warnings[] = 'Warning: unexpected change of $CFG->' . $k . ' value'; } } unset($oldcfg->{$k}); } if ($oldcfg) { foreach ($oldcfg as $k => $v) { $warnings[] = 'Warning: unexpected removal of $CFG->' . $k; } } if ($USER->id != 0) { $warnings[] = 'Warning: unexpected change of $USER'; } if ($COURSE->id != $oldsite->id) { $warnings[] = 'Warning: unexpected change of $COURSE'; } if ($CFG->ostype === 'WINDOWS') { if (setlocale(LC_TIME, 0) !== 'English_Australia.1252') { $warnings[] = 'Warning: unexpected change of locale'; } } else { if (setlocale(LC_TIME, 0) !== 'en_AU.UTF-8') { $warnings[] = 'Warning: unexpected change of locale'; } } } if (ini_get('max_execution_time') != 0) { // This is special warning for all resets because we do not want any // libraries to mess with timeouts unintentionally. // Our PHPUnit integration is not supposed to change it either. if ($detectchanges !== false) { $warnings[] = 'Warning: max_execution_time was changed to ' . ini_get('max_execution_time'); } set_time_limit(0); } // restore original globals $_SERVER = self::get_global_backup('_SERVER'); $CFG = self::get_global_backup('CFG'); $SITE = self::get_global_backup('SITE'); $_GET = array(); $_POST = array(); $_FILES = array(); $_REQUEST = array(); $COURSE = $SITE; // reinitialise following globals $OUTPUT = new bootstrap_renderer(); $PAGE = new moodle_page(); $FULLME = null; $ME = null; $SCRIPT = null; // Empty sessison and set fresh new not-logged-in user. \core\session\manager::init_empty_session(); // reset all static caches \core\event\manager::phpunit_reset(); accesslib_clear_all_caches(true); get_string_manager()->reset_caches(true); reset_text_filters_cache(true); events_get_handlers('reset'); core_text::reset_caches(); get_message_processors(false, true); filter_manager::reset_caches(); core_filetypes::reset_caches(); // Reset static unit test options. if (class_exists('\\availability_date\\condition', false)) { \availability_date\condition::set_current_time_for_test(0); } // Reset internal users. core_user::reset_internal_users(); //TODO MDL-25290: add more resets here and probably refactor them to new core function // Reset course and module caches. if (class_exists('format_base')) { // If file containing class is not loaded, there is no cache there anyway. format_base::reset_course_cache(0); } get_fast_modinfo(0, 0, true); // Reset other singletons. if (class_exists('core_plugin_manager')) { core_plugin_manager::reset_caches(true); } if (class_exists('\\core\\update\\checker')) { \core\update\checker::reset_caches(true); } if (class_exists('\\core\\update\\deployer')) { \core\update\deployer::reset_caches(true); } // Clear static cache within restore. if (class_exists('restore_section_structure_step')) { restore_section_structure_step::reset_caches(); } // purge dataroot directory self::reset_dataroot(); // restore original config once more in case resetting of caches changed CFG $CFG = self::get_global_backup('CFG'); // inform data generator self::get_data_generator()->reset(); // fix PHP settings error_reporting($CFG->debug); // Reset the date/time class. core_date::phpunit_reset(); // Make sure the time locale is consistent - that is Australian English. if ($CFG->ostype === 'WINDOWS') { setlocale(LC_TIME, 'English_Australia.1252'); } else { setlocale(LC_TIME, 'en_AU.UTF-8'); } // verify db writes just in case something goes wrong in reset if (self::$lastdbwrites != $DB->perf_get_writes()) { error_log('Unexpected DB writes in phpunit_util::reset_all_data()'); self::$lastdbwrites = $DB->perf_get_writes(); } if ($warnings) { $warnings = implode("\n", $warnings); trigger_error($warnings, E_USER_WARNING); } }
// we need hotpot/lib.php for the callback validation functions require_once $CFG->dirroot . '/mod/hotpot/lib.php'; require_once $CFG->dirroot . '/mod/hotpot/locallib.php'; // admin_setting_xxx classes are defined in "lib/adminlib.php" // new admin_setting_configcheckbox($name, $visiblename, $description, $defaultsetting); // show Quizports on MyMoodle page (default=1) $settings->add(new admin_setting_configcheckbox('hotpot_enablemymoodle', get_string('enablemymoodle', 'mod_hotpot'), get_string('configenablemymoodle', 'mod_hotpot'), 1)); // enable caching of browser content for each quiz (default=1) $str = get_string('clearcache', 'mod_hotpot'); $url = new moodle_url('/mod/hotpot/tools/clear_cache.php', array('sesskey' => sesskey())); $link = html_writer::link($url, $str, array('class' => 'small', 'style' => 'white-space: nowrap', 'onclick' => "this.target='_blank'")) . "\n"; $settings->add(new admin_setting_configcheckbox('hotpot_enablecache', get_string('enablecache', 'mod_hotpot'), get_string('configenablecache', 'mod_hotpot') . ' ' . $link, 1)); // restrict cron job to certain hours of the day (default=never) if (class_exists('core_date') && method_exists('core_date', 'get_user_timezone')) { // Moodle >= 2.9 $timezone = core_date::get_user_timezone(99); $datetime = new DateTime('now', new DateTimeZone($timezone)); $timezone = ($datetime->getOffset() - dst_offset_on(time(), $timezone)) / 3600.0; } else { // Moodle <= 2.8 $timezone = get_user_timezone_offset(); } if (abs($timezone) > 13) { $timezone = 0; } else { if ($timezone > 0) { $timezone = $timezone - 24; } } $options = array(); for ($i = 0; $i <= 23; $i++) {
/** * Lazy load timezone options. * @return bool true if loaded, false if error */ public function load_choices() { global $CFG; if (is_array($this->choices)) { return true; } $current = isset($CFG->forcetimezone) ? $CFG->forcetimezone : null; $this->choices = core_date::get_list_of_timezones($current, true); $this->choices['99'] = new lang_string('timezonenotforced', 'core_admin'); return true; }
/** * Helper to falsify all forum post records for a digest run. */ protected function helper_force_digest_mail_times() { global $CFG, $DB; // Fake all of the post editing times because digests aren't sent until // the start of an hour where the modification time on the message is before // the start of that hour $sitetimezone = core_date::get_server_timezone(); $digesttime = usergetmidnight(time(), $sitetimezone) + $CFG->digestmailtime * 3600 - 60 * 60; $DB->set_field('forum_posts', 'modified', $digesttime, array('mailed' => 0)); $DB->set_field('forum_posts', 'created', $digesttime, array('mailed' => 0)); }
/** * 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 = core_date::get_server_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; }
/** * Test the temporary table creation and deletion. * * @depends test_statslib_temp_table_create_and_drop */ public function test_statslib_temp_table_fill() { global $CFG, $DB, $USER; $dataset = $this->load_xml_data_file(__DIR__ . "/fixtures/statslib-test09.xml"); $this->prepare_db($dataset[0], array('log')); // This nonsense needs to be rewritten. $date = new DateTime('now', core_date::get_server_timezone_object()); $start = self::DAY - $date->getOffset(); $end = $start + 24 * 3600; stats_temp_table_create(); stats_temp_table_fill($start, $end); $this->assertEquals(1, $DB->count_records('temp_log1')); $this->assertEquals(1, $DB->count_records('temp_log2')); stats_temp_table_drop(); // New log stores. $this->preventResetByRollback(); stats_temp_table_create(); $course = $this->getDataGenerator()->create_course(); $context = context_course::instance($course->id); $fcontext = context_course::instance(SITEID); $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $this->assertFileExists("{$CFG->dirroot}/{$CFG->admin}/tool/log/store/standard/version.php"); set_config('enabled_stores', 'logstore_standard', 'tool_log'); set_config('buffersize', 0, 'logstore_standard'); set_config('logguests', 1, 'logstore_standard'); get_log_manager(true); $DB->delete_records('logstore_standard_log'); \core_tests\event\create_executed::create(array('context' => $fcontext, 'courseid' => SITEID))->trigger(); \core_tests\event\read_executed::create(array('context' => $context, 'courseid' => $course->id))->trigger(); \core_tests\event\update_executed::create(array('context' => context_system::instance()))->trigger(); \core_tests\event\delete_executed::create(array('context' => context_system::instance()))->trigger(); \core\event\user_loggedin::create(array('userid' => $USER->id, 'objectid' => $USER->id, 'other' => array('username' => $USER->username)))->trigger(); $DB->set_field('logstore_standard_log', 'timecreated', 10); $this->assertEquals(5, $DB->count_records('logstore_standard_log')); \core_tests\event\delete_executed::create(array('context' => context_system::instance()))->trigger(); \core_tests\event\delete_executed::create(array('context' => context_system::instance()))->trigger(); // Fake the origin of events. $DB->set_field('logstore_standard_log', 'origin', 'web', array()); $this->assertEquals(7, $DB->count_records('logstore_standard_log')); stats_temp_table_fill(9, 11); $logs1 = $DB->get_records('temp_log1'); $logs2 = $DB->get_records('temp_log2'); $this->assertCount(5, $logs1); $this->assertCount(5, $logs2); // The order of records in the temp tables is not guaranteed... $viewcount = 0; $updatecount = 0; $logincount = 0; foreach ($logs1 as $log) { if ($log->course == $course->id) { $this->assertEquals('view', $log->action); $viewcount++; } else { $this->assertTrue(in_array($log->action, array('update', 'login'))); if ($log->action === 'update') { $updatecount++; } else { $logincount++; } $this->assertEquals(SITEID, $log->course); } $this->assertEquals($user->id, $log->userid); } $this->assertEquals(1, $viewcount); $this->assertEquals(3, $updatecount); $this->assertEquals(1, $logincount); set_config('enabled_stores', '', 'tool_log'); get_log_manager(true); stats_temp_table_drop(); }
/** * Update or create an event within the database * * Pass in a object containing the event properties and this function will * insert it into the database and deal with any associated files * * @see self::create() * @see self::update() * * @param stdClass $data object of event * @param bool $checkcapability if moodle should check calendar managing capability or not * @return bool event updated */ public function update($data, $checkcapability = true) { global $DB, $USER; foreach ($data as $key => $value) { $this->properties->{$key} = $value; } $this->properties->timemodified = time(); $usingeditor = !empty($this->properties->description) && is_array($this->properties->description); // Prepare event data. $eventargs = array('context' => $this->properties->context, 'objectid' => $this->properties->id, 'other' => array('repeatid' => empty($this->properties->repeatid) ? 0 : $this->properties->repeatid, 'timestart' => $this->properties->timestart, 'name' => $this->properties->name)); if (empty($this->properties->id) || $this->properties->id < 1) { if ($checkcapability) { if (!calendar_add_event_allowed($this->properties)) { print_error('nopermissiontoupdatecalendar'); } } if ($usingeditor) { switch ($this->properties->eventtype) { case 'user': $this->properties->courseid = 0; $this->properties->course = 0; $this->properties->groupid = 0; $this->properties->userid = $USER->id; break; case 'site': $this->properties->courseid = SITEID; $this->properties->course = SITEID; $this->properties->groupid = 0; $this->properties->userid = $USER->id; break; case 'course': $this->properties->groupid = 0; $this->properties->userid = $USER->id; break; case 'group': $this->properties->userid = $USER->id; break; default: // Ewww we should NEVER get here, but just incase we do lets // fail gracefully $usingeditor = false; break; } // If we are actually using the editor, we recalculate the context because some default values // were set when calculate_context() was called from the constructor. if ($usingeditor) { $this->properties->context = $this->calculate_context($this->properties); $this->editorcontext = $this->properties->context; } $editor = $this->properties->description; $this->properties->format = $this->properties->description['format']; $this->properties->description = $this->properties->description['text']; } // Insert the event into the database $this->properties->id = $DB->insert_record('event', $this->properties); if ($usingeditor) { $this->properties->description = file_save_draft_area_files($editor['itemid'], $this->editorcontext->id, 'calendar', 'event_description', $this->properties->id, $this->editoroptions, $editor['text'], $this->editoroptions['forcehttps']); $DB->set_field('event', 'description', $this->properties->description, array('id' => $this->properties->id)); } // Log the event entry. $eventargs['objectid'] = $this->properties->id; $eventargs['context'] = $this->properties->context; $event = \core\event\calendar_event_created::create($eventargs); $event->trigger(); $repeatedids = array(); if (!empty($this->properties->repeat)) { $this->properties->repeatid = $this->properties->id; $DB->set_field('event', 'repeatid', $this->properties->repeatid, array('id' => $this->properties->id)); $eventcopy = clone $this->properties; unset($eventcopy->id); $timestart = new DateTime('@' . $eventcopy->timestart); $timestart->setTimezone(core_date::get_user_timezone_object()); for ($i = 1; $i < $eventcopy->repeats; $i++) { $timestart->add(new DateInterval('P7D')); $eventcopy->timestart = $timestart->getTimestamp(); // Get the event id for the log record. $eventcopyid = $DB->insert_record('event', $eventcopy); // If the context has been set delete all associated files if ($usingeditor) { $fs = get_file_storage(); $files = $fs->get_area_files($this->editorcontext->id, 'calendar', 'event_description', $this->properties->id); foreach ($files as $file) { $fs->create_file_from_storedfile(array('itemid' => $eventcopyid), $file); } } $repeatedids[] = $eventcopyid; // Trigger an event. $eventargs['objectid'] = $eventcopyid; $eventargs['other']['timestart'] = $eventcopy->timestart; $event = \core\event\calendar_event_created::create($eventargs); $event->trigger(); } } // Hook for tracking added events self::calendar_event_hook('add_event', array($this->properties, $repeatedids)); return true; } else { if ($checkcapability) { if (!calendar_edit_event_allowed($this->properties)) { print_error('nopermissiontoupdatecalendar'); } } if ($usingeditor) { if ($this->editorcontext !== null) { $this->properties->description = file_save_draft_area_files($this->properties->description['itemid'], $this->editorcontext->id, 'calendar', 'event_description', $this->properties->id, $this->editoroptions, $this->properties->description['text'], $this->editoroptions['forcehttps']); } else { $this->properties->format = $this->properties->description['format']; $this->properties->description = $this->properties->description['text']; } } $event = $DB->get_record('event', array('id' => $this->properties->id)); $updaterepeated = !empty($this->properties->repeatid) && !empty($this->properties->repeateditall); if ($updaterepeated) { // Update all if ($this->properties->timestart != $event->timestart) { $timestartoffset = $this->properties->timestart - $event->timestart; $sql = "UPDATE {event}\n SET name = ?,\n description = ?,\n timestart = timestart + ?,\n timeduration = ?,\n timemodified = ?\n WHERE repeatid = ?"; $params = array($this->properties->name, $this->properties->description, $timestartoffset, $this->properties->timeduration, time(), $event->repeatid); } else { $sql = "UPDATE {event} SET name = ?, description = ?, timeduration = ?, timemodified = ? WHERE repeatid = ?"; $params = array($this->properties->name, $this->properties->description, $this->properties->timeduration, time(), $event->repeatid); } $DB->execute($sql, $params); // Trigger an update event for each of the calendar event. $events = $DB->get_records('event', array('repeatid' => $event->repeatid), '', 'id,timestart'); foreach ($events as $event) { $eventargs['objectid'] = $event->id; $eventargs['other']['timestart'] = $event->timestart; $event = \core\event\calendar_event_updated::create($eventargs); $event->trigger(); } } else { $DB->update_record('event', $this->properties); $event = calendar_event::load($this->properties->id); $this->properties = $event->properties(); // Trigger an update event. $event = \core\event\calendar_event_updated::create($eventargs); $event->trigger(); } // Hook for tracking event updates self::calendar_event_hook('update_event', array($this->properties, $updaterepeated)); return true; } }
/** * Change server and default php timezones. * * @param string $servertimezone timezone to set in $CFG->timezone (not validated) * @param string $defaultphptimezone timezone to fake default php timezone (must be valid) */ public static function setTimezone($servertimezone = 'Australia/Perth', $defaultphptimezone = 'Australia/Perth') { global $CFG; $CFG->timezone = $servertimezone; core_date::phpunit_override_default_php_timezone($defaultphptimezone); core_date::set_default_server_timezone(); }
function definition() { global $CFG, $USER; $mform = $this->_form; $columns = $this->_customdata['columns']; $data = $this->_customdata['data']; // I am the template user, why should it be the administrator? we have roles now, other ppl may use this script ;-) $templateuser = $USER; // upload settings and file $mform->addElement('header', 'settingsheader', get_string('settings')); $choices = array(UU_USER_ADDNEW => get_string('uuoptype_addnew', 'tool_uploaduser'), UU_USER_ADDINC => get_string('uuoptype_addinc', 'tool_uploaduser'), UU_USER_ADD_UPDATE => get_string('uuoptype_addupdate', 'tool_uploaduser'), UU_USER_UPDATE => get_string('uuoptype_update', 'tool_uploaduser')); $mform->addElement('select', 'uutype', get_string('uuoptype', 'tool_uploaduser'), $choices); $choices = array(0 => get_string('infilefield', 'auth'), 1 => get_string('createpasswordifneeded', 'auth')); $mform->addElement('select', 'uupasswordnew', get_string('uupasswordnew', 'tool_uploaduser'), $choices); $mform->setDefault('uupasswordnew', 1); $mform->disabledIf('uupasswordnew', 'uutype', 'eq', UU_USER_UPDATE); $choices = array(UU_UPDATE_NOCHANGES => get_string('nochanges', 'tool_uploaduser'), UU_UPDATE_FILEOVERRIDE => get_string('uuupdatefromfile', 'tool_uploaduser'), UU_UPDATE_ALLOVERRIDE => get_string('uuupdateall', 'tool_uploaduser'), UU_UPDATE_MISSING => get_string('uuupdatemissing', 'tool_uploaduser')); $mform->addElement('select', 'uuupdatetype', get_string('uuupdatetype', 'tool_uploaduser'), $choices); $mform->setDefault('uuupdatetype', UU_UPDATE_NOCHANGES); $mform->disabledIf('uuupdatetype', 'uutype', 'eq', UU_USER_ADDNEW); $mform->disabledIf('uuupdatetype', 'uutype', 'eq', UU_USER_ADDINC); $choices = array(0 => get_string('nochanges', 'tool_uploaduser'), 1 => get_string('update')); $mform->addElement('select', 'uupasswordold', get_string('uupasswordold', 'tool_uploaduser'), $choices); $mform->setDefault('uupasswordold', 0); $mform->disabledIf('uupasswordold', 'uutype', 'eq', UU_USER_ADDNEW); $mform->disabledIf('uupasswordold', 'uutype', 'eq', UU_USER_ADDINC); $mform->disabledIf('uupasswordold', 'uuupdatetype', 'eq', 0); $mform->disabledIf('uupasswordold', 'uuupdatetype', 'eq', 3); $choices = array(UU_PWRESET_WEAK => get_string('usersweakpassword', 'tool_uploaduser'), UU_PWRESET_NONE => get_string('none'), UU_PWRESET_ALL => get_string('all')); if (empty($CFG->passwordpolicy)) { unset($choices[UU_PWRESET_WEAK]); } $mform->addElement('select', 'uuforcepasswordchange', get_string('forcepasswordchange', 'core'), $choices); $mform->addElement('selectyesno', 'uuallowrenames', get_string('allowrenames', 'tool_uploaduser')); $mform->setDefault('uuallowrenames', 0); $mform->disabledIf('uuallowrenames', 'uutype', 'eq', UU_USER_ADDNEW); $mform->disabledIf('uuallowrenames', 'uutype', 'eq', UU_USER_ADDINC); $mform->addElement('selectyesno', 'uuallowdeletes', get_string('allowdeletes', 'tool_uploaduser')); $mform->setDefault('uuallowdeletes', 0); $mform->disabledIf('uuallowdeletes', 'uutype', 'eq', UU_USER_ADDNEW); $mform->disabledIf('uuallowdeletes', 'uutype', 'eq', UU_USER_ADDINC); $mform->addElement('selectyesno', 'uuallowsuspends', get_string('allowsuspends', 'tool_uploaduser')); $mform->setDefault('uuallowsuspends', 1); $mform->disabledIf('uuallowsuspends', 'uutype', 'eq', UU_USER_ADDNEW); $mform->disabledIf('uuallowsuspends', 'uutype', 'eq', UU_USER_ADDINC); if (!empty($CFG->allowaccountssameemail)) { $mform->addElement('selectyesno', 'uunoemailduplicates', get_string('uunoemailduplicates', 'tool_uploaduser')); $mform->setDefault('uunoemailduplicates', 1); } else { $mform->addElement('hidden', 'uunoemailduplicates', 1); } $mform->setType('uunoemailduplicates', PARAM_BOOL); $mform->addElement('selectyesno', 'uustandardusernames', get_string('uustandardusernames', 'tool_uploaduser')); $mform->setDefault('uustandardusernames', 1); $choices = array(UU_BULK_NONE => get_string('no'), UU_BULK_NEW => get_string('uubulknew', 'tool_uploaduser'), UU_BULK_UPDATED => get_string('uubulkupdated', 'tool_uploaduser'), UU_BULK_ALL => get_string('uubulkall', 'tool_uploaduser')); $mform->addElement('select', 'uubulk', get_string('uubulk', 'tool_uploaduser'), $choices); $mform->setDefault('uubulk', 0); // roles selection $showroles = false; foreach ($columns as $column) { if (preg_match('/^type\\d+$/', $column)) { $showroles = true; break; } } if ($showroles) { $mform->addElement('header', 'rolesheader', get_string('roles')); $choices = uu_allowed_roles(true); $mform->addElement('select', 'uulegacy1', get_string('uulegacy1role', 'tool_uploaduser'), $choices); if ($studentroles = get_archetype_roles('student')) { foreach ($studentroles as $role) { if (isset($choices[$role->id])) { $mform->setDefault('uulegacy1', $role->id); break; } } unset($studentroles); } $mform->addElement('select', 'uulegacy2', get_string('uulegacy2role', 'tool_uploaduser'), $choices); if ($editteacherroles = get_archetype_roles('editingteacher')) { foreach ($editteacherroles as $role) { if (isset($choices[$role->id])) { $mform->setDefault('uulegacy2', $role->id); break; } } unset($editteacherroles); } $mform->addElement('select', 'uulegacy3', get_string('uulegacy3role', 'tool_uploaduser'), $choices); if ($teacherroles = get_archetype_roles('teacher')) { foreach ($teacherroles as $role) { if (isset($choices[$role->id])) { $mform->setDefault('uulegacy3', $role->id); break; } } unset($teacherroles); } } // default values $mform->addElement('header', 'defaultheader', get_string('defaultvalues', 'tool_uploaduser')); $mform->addElement('text', 'username', get_string('uuusernametemplate', 'tool_uploaduser'), 'size="20"'); $mform->setType('username', PARAM_RAW); // No cleaning here. The process verifies it later. $mform->addRule('username', get_string('requiredtemplate', 'tool_uploaduser'), 'required', null, 'client'); $mform->disabledIf('username', 'uutype', 'eq', UU_USER_ADD_UPDATE); $mform->disabledIf('username', 'uutype', 'eq', UU_USER_UPDATE); $mform->setForceLtr('username'); $mform->addElement('text', 'email', get_string('email'), 'maxlength="100" size="30"'); $mform->setType('email', PARAM_RAW); // No cleaning here. The process verifies it later. $mform->disabledIf('email', 'uutype', 'eq', UU_USER_ADD_UPDATE); $mform->disabledIf('email', 'uutype', 'eq', UU_USER_UPDATE); $mform->setForceLtr('email'); // only enabled and known to work plugins $choices = uu_supported_auths(); $mform->addElement('select', 'auth', get_string('chooseauthmethod', 'auth'), $choices); $mform->setDefault('auth', 'manual'); // manual is a sensible backwards compatible default $mform->addHelpButton('auth', 'chooseauthmethod', 'auth'); $mform->setAdvanced('auth'); $choices = array(0 => get_string('emaildisplayno'), 1 => get_string('emaildisplayyes'), 2 => get_string('emaildisplaycourse')); $mform->addElement('select', 'maildisplay', get_string('emaildisplay'), $choices); $mform->setDefault('maildisplay', core_user::get_property_default('maildisplay')); $choices = array(0 => get_string('textformat'), 1 => get_string('htmlformat')); $mform->addElement('select', 'mailformat', get_string('emailformat'), $choices); $mform->setDefault('mailformat', core_user::get_property_default('mailformat')); $mform->setAdvanced('mailformat'); $choices = array(0 => get_string('emaildigestoff'), 1 => get_string('emaildigestcomplete'), 2 => get_string('emaildigestsubjects')); $mform->addElement('select', 'maildigest', get_string('emaildigest'), $choices); $mform->setDefault('maildigest', core_user::get_property_default('maildigest')); $mform->setAdvanced('maildigest'); $choices = array(1 => get_string('autosubscribeyes'), 0 => get_string('autosubscribeno')); $mform->addElement('select', 'autosubscribe', get_string('autosubscribe'), $choices); $mform->setDefault('autosubscribe', core_user::get_property_default('autosubscribe')); $mform->addElement('text', 'city', get_string('city'), 'maxlength="120" size="25"'); $mform->setType('city', PARAM_TEXT); if (empty($CFG->defaultcity)) { $mform->setDefault('city', $templateuser->city); } else { $mform->setDefault('city', core_user::get_property_default('city')); } $choices = get_string_manager()->get_list_of_countries(); $choices = array('' => get_string('selectacountry') . '...') + $choices; $mform->addElement('select', 'country', get_string('selectacountry'), $choices); if (empty($CFG->country)) { $mform->setDefault('country', $templateuser->country); } else { $mform->setDefault('country', core_user::get_property_default('country')); } $mform->setAdvanced('country'); $choices = core_date::get_list_of_timezones($templateuser->timezone, true); $mform->addElement('select', 'timezone', get_string('timezone'), $choices); $mform->setDefault('timezone', $templateuser->timezone); $mform->setAdvanced('timezone'); $mform->addElement('select', 'lang', get_string('preferredlanguage'), get_string_manager()->get_list_of_translations()); $mform->setDefault('lang', $templateuser->lang); $mform->setAdvanced('lang'); $editoroptions = array('maxfiles' => 0, 'maxbytes' => 0, 'trusttext' => false, 'forcehttps' => false); $mform->addElement('editor', 'description', get_string('userdescription'), null, $editoroptions); $mform->setType('description', PARAM_CLEANHTML); $mform->addHelpButton('description', 'userdescription'); $mform->setAdvanced('description'); $mform->addElement('text', 'url', get_string('webpage'), 'maxlength="255" size="50"'); $mform->setType('url', PARAM_URL); $mform->setAdvanced('url'); $mform->addElement('text', 'idnumber', get_string('idnumber'), 'maxlength="255" size="25"'); $mform->setType('idnumber', PARAM_NOTAGS); $mform->setForceLtr('idnumber'); $mform->addElement('text', 'institution', get_string('institution'), 'maxlength="255" size="25"'); $mform->setType('institution', PARAM_TEXT); $mform->setDefault('institution', $templateuser->institution); $mform->addElement('text', 'department', get_string('department'), 'maxlength="255" size="25"'); $mform->setType('department', PARAM_TEXT); $mform->setDefault('department', $templateuser->department); $mform->addElement('text', 'phone1', get_string('phone1'), 'maxlength="20" size="25"'); $mform->setType('phone1', PARAM_NOTAGS); $mform->setAdvanced('phone1'); $mform->setForceLtr('phone1'); $mform->addElement('text', 'phone2', get_string('phone2'), 'maxlength="20" size="25"'); $mform->setType('phone2', PARAM_NOTAGS); $mform->setAdvanced('phone2'); $mform->setForceLtr('phone2'); $mform->addElement('text', 'address', get_string('address'), 'maxlength="255" size="25"'); $mform->setType('address', PARAM_TEXT); $mform->setAdvanced('address'); // Next the profile defaults profile_definition($mform); // hidden fields $mform->addElement('hidden', 'iid'); $mform->setType('iid', PARAM_INT); $mform->addElement('hidden', 'previewrows'); $mform->setType('previewrows', PARAM_INT); $this->add_action_buttons(true, get_string('uploadusers', 'tool_uploaduser')); $this->set_data($data); }
public function test_get_user_timezone_object() { global $CFG, $USER; $this->resetAfterTest(); $this->setTimezone('Pacific/Auckland'); $CFG->forcetimezone = '99'; $zones = core_date::get_list_of_timezones(); foreach ($zones as $zone) { $USER->timezone = $zone; $tz = core_date::get_user_timezone_object(); $this->assertInstanceOf('DateTimeZone', $tz); $this->assertSame($zone, $tz->getName()); } }
/** * 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; }
/** * Format a timestamp to send to WebEx. Converts to GMT time. * * @param int $time Timestamp to format. * @return string The XML. */ public static function time_to_date_string($time) { // Convert the time to GMT. $dt = new \DateTime(date("o:m:d H:i:s", $time), \core_date::get_server_timezone_object()); $gmttime = $time - $dt->getOffset(); return date('m/d/Y H:i:s', $gmttime); }
/** * Get the parameter values that may be appended to URL * @param object $url module instance * @param object $cm * @param object $course * @param object $config module config options * @return array of parameter values */ function url_get_variable_values($url, $cm, $course, $config) { global $USER, $CFG; $site = get_site(); $coursecontext = context_course::instance($course->id); $values = array('courseid' => $course->id, 'coursefullname' => format_string($course->fullname), 'courseshortname' => format_string($course->shortname, true, array('context' => $coursecontext)), 'courseidnumber' => $course->idnumber, 'coursesummary' => $course->summary, 'courseformat' => $course->format, 'lang' => current_language(), 'sitename' => format_string($site->fullname), 'serverurl' => $CFG->wwwroot, 'currenttime' => time(), 'urlinstance' => $url->id, 'urlcmid' => $cm->id, 'urlname' => format_string($url->name), 'urlidnumber' => $cm->idnumber); if (isloggedin()) { $values['userid'] = $USER->id; $values['userusername'] = $USER->username; $values['useridnumber'] = $USER->idnumber; $values['userfirstname'] = $USER->firstname; $values['userlastname'] = $USER->lastname; $values['userfullname'] = fullname($USER); $values['useremail'] = $USER->email; $values['usericq'] = $USER->icq; $values['userphone1'] = $USER->phone1; $values['userphone2'] = $USER->phone2; $values['userinstitution'] = $USER->institution; $values['userdepartment'] = $USER->department; $values['useraddress'] = $USER->address; $values['usercity'] = $USER->city; $now = new DateTime('now', core_date::get_user_timezone_object()); $values['usertimezone'] = $now->getOffset() / 3600.0; // Value in hours for BC. $values['userurl'] = $USER->url; } // weak imitation of Single-Sign-On, for backwards compatibility only // NOTE: login hack is not included in 2.0 any more, new contrib auth plugin // needs to be createed if somebody needs the old functionality! if (!empty($config->secretphrase)) { $values['encryptedcode'] = url_get_encrypted_parameter($url, $config); } //hmm, this is pretty fragile and slow, why do we need it here?? if ($config->rolesinparams) { $coursecontext = context_course::instance($course->id); $roles = role_fix_names(get_all_roles($coursecontext), $coursecontext, ROLENAME_ALIAS); foreach ($roles as $role) { $values['course' . $role->shortname] = $role->localname; } } return $values; }
/** * Returns a list of timezones in the current language. * @deprecated since Moodle 2.9 * @return array */ function get_list_of_timezones() { debugging('get_list_of_timezones() is deprecated, use core_date::get_list_of_timezones() instead', DEBUG_DEVELOPER); return core_date::get_list_of_timezones(); }