/** * Validates a value using a range comparison * * @param string $value Value to be checked * @param mixed $options Int for length, array for range * @access public * @return boolean true if value is valid */ function validate($value, $options = null) { $length = textlib::strlen($value); switch ($this->name) { case 'minlength': return $length >= $options; case 'maxlength': return $length <= $options; default: return $length >= $options[0] && $length <= $options[1]; } }
/** * @uses LABEL_MAX_NAME_LENGTH * @param object $label * @return string */ function get_label_name($label) { $name = strip_tags(format_string($label->intro,true)); if (textlib::strlen($name) > LABEL_MAX_NAME_LENGTH) { $name = textlib::substr($name, 0, LABEL_MAX_NAME_LENGTH)."..."; } if (empty($name)) { // arbitrary name $name = get_string('modulename','label'); } return $name; }
protected function action($message, $level, $options = null) { $columns = $this->columns; if ($this->datecol) { $columns[$this->datecol] = time(); } if ($this->levelcol) { $columns[$this->levelcol] = $level; } $message = clean_param($message, PARAM_NOTAGS); // Check if the message exceeds the 255 character limit in the database, // if it does, shorten it so that it can be inserted successfully. if (textlib::strlen($message) > 255) { $message = textlib::substr($message, 0, 252) . '...'; } $columns[$this->messagecol] = $message; return $this->insert_log_record($this->logtable, $columns); }
function rfc2445_fold($string) { if (textlib::strlen($string, 'utf-8') <= RFC2445_FOLDED_LINE_LENGTH) { return $string; } $retval = ''; $i = 0; $len_count = 0; //multi-byte string, get the correct length $section_len = textlib::strlen($string, 'utf-8'); while ($len_count < $section_len) { //get the current portion of the line $section = textlib::substr($string, $i * RFC2445_FOLDED_LINE_LENGTH, RFC2445_FOLDED_LINE_LENGTH, 'utf-8'); //increment the length we've processed by the length of the new portion $len_count += textlib::strlen($section, 'utf-8'); /* Add the portion to the return value, terminating with CRLF.HTAB As per RFC 2445, CRLF.HTAB will be replaced by the processor of the data */ $retval .= $section . RFC2445_CRLF . RFC2445_WSP; $i++; } return $retval; }
/** * Update categories * * @param array $categories The list of categories to update * @return null * @since Moodle 2.3 */ public static function update_categories($categories) { global $CFG, $DB; require_once $CFG->dirroot . "/course/lib.php"; // Validate parameters. $params = self::validate_parameters(self::update_categories_parameters(), array('categories' => $categories)); $transaction = $DB->start_delegated_transaction(); foreach ($params['categories'] as $cat) { if (!($category = $DB->get_record('course_categories', array('id' => $cat['id'])))) { throw new moodle_exception('unknowcategory'); } $categorycontext = context_coursecat::instance($cat['id']); self::validate_context($categorycontext); require_capability('moodle/category:manage', $categorycontext); if (!empty($cat['name'])) { if (textlib::strlen($cat['name']) > 255) { throw new moodle_exception('categorytoolong'); } $category->name = $cat['name']; } if (!empty($cat['idnumber'])) { if (textlib::strlen($cat['idnumber']) > 100) { throw new moodle_exception('idnumbertoolong'); } $category->idnumber = $cat['idnumber']; } if (!empty($cat['description'])) { $category->description = $cat['description']; $category->descriptionformat = external_validate_format($cat['descriptionformat']); } if (!empty($cat['theme'])) { $category->theme = $cat['theme']; } if (!empty($cat['parent']) && $category->parent != $cat['parent']) { // First check if parent exists. if (!($parent_cat = $DB->get_record('course_categories', array('id' => $cat['parent'])))) { throw new moodle_exception('unknowcategory'); } // Then check if we have capability. self::validate_context(get_category_or_system_context((int) $cat['parent'])); require_capability('moodle/category:manage', get_category_or_system_context((int) $cat['parent'])); // Finally move the category. move_category($category, $parent_cat); $category->parent = $cat['parent']; // Get updated path by move_category(). $category->path = $DB->get_field('course_categories', 'path', array('id' => $category->id)); } $DB->update_record('course_categories', $category); } $transaction->allow_commit(); }
/** * Strips a large title to size and adds ... if title too long * * @param string title to shorten * @param int max character length of title * @return string title s() quoted and shortened if necessary */ function format_title($title, $max = 64) { if (textlib::strlen($title) <= $max) { return s($title); } else { return s(textlib::substr($title, 0, $max - 3) . '...'); } }
/** * given a course object with shortname & fullname, this function will * truncate the the number of chars allowed and add ... if it was too long */ function course_format_name($course, $max = 100) { $context = get_context_instance(CONTEXT_COURSE, $course->id); $shortname = format_string($course->shortname, true, array('context' => $context)); $fullname = format_string($course->fullname, true, array('context' => get_context_instance(CONTEXT_COURSE, $course->id))); $str = $shortname . ': ' . $fullname; if (textlib::strlen($str) <= $max) { return $str; } else { return textlib::substr($str, 0, $max - 3) . '...'; } }
/** * Add an entry to the log table. * * Add an entry to the log table. These are "action" focussed rather * than web server hits, and provide a way to easily reconstruct what * any particular student has been doing. * * @package core * @category log * @global moodle_database $DB * @global stdClass $CFG * @global stdClass $USER * @uses SITEID * @uses DEBUG_DEVELOPER * @uses DEBUG_ALL * @param int $courseid The course id * @param string $module The module name e.g. forum, journal, resource, course, user etc * @param string $action 'view', 'update', 'add' or 'delete', possibly followed by another word to clarify. * @param string $url The file and parameters used to see the results of the action * @param string $info Additional description information * @param string $cm The course_module->id if there is one * @param string $user If log regards $user other than $USER * @return void */ function add_to_log($courseid, $module, $action, $url = '', $info = '', $cm = 0, $user = 0) { // Note that this function intentionally does not follow the normal Moodle DB access idioms. // This is for a good reason: it is the most frequently used DB update function, // so it has been optimised for speed. global $DB, $CFG, $USER; if ($cm === '' || is_null($cm)) { // postgres won't translate empty string to its default $cm = 0; } if ($user) { $userid = $user; } else { if (session_is_loggedinas()) { // Don't log return; } $userid = empty($USER->id) ? '0' : $USER->id; } if (isset($CFG->logguests) and !$CFG->logguests) { if (!$userid or isguestuser($userid)) { return; } } $REMOTE_ADDR = getremoteaddr(); $timenow = time(); $info = $info; if (!empty($url)) { // could break doing html_entity_decode on an empty var. $url = html_entity_decode($url, ENT_QUOTES, 'UTF-8'); } else { $url = ''; } // Restrict length of log lines to the space actually available in the // database so that it doesn't cause a DB error. Log a warning so that // developers can avoid doing things which are likely to cause this on a // routine basis. if (!empty($info) && textlib::strlen($info) > 255) { $info = textlib::substr($info, 0, 252) . '...'; debugging('Warning: logged very long info', DEBUG_DEVELOPER); } // If the 100 field size is changed, also need to alter print_log in course/lib.php if (!empty($url) && textlib::strlen($url) > 100) { $url = textlib::substr($url, 0, 97) . '...'; debugging('Warning: logged very long URL', DEBUG_DEVELOPER); } if (defined('MDL_PERFDB')) { global $PERF; $PERF->logwrites++; } $log = array('time' => $timenow, 'userid' => $userid, 'course' => $courseid, 'ip' => $REMOTE_ADDR, 'module' => $module, 'cmid' => $cm, 'action' => $action, 'url' => $url, 'info' => $info); try { $DB->insert_record_raw('log', $log, false); } catch (dml_exception $e) { debugging('Error: Could not insert a new entry to the Moodle log. ' . $e->error, DEBUG_ALL); // MDL-11893, alert $CFG->supportemail if insert into log failed if ($CFG->supportemail and empty($CFG->noemailever)) { // email_to_user is not usable because email_to_user tries to write to the logs table, // and this will get caught in an infinite loop, if disk is full $site = get_site(); $subject = 'Insert into log failed at your moodle site ' . $site->fullname; $message = "Insert into log table failed at " . date('l dS \\of F Y h:i:s A') . ".\n It is possible that your disk is full.\n\n"; $message .= "The failed query parameters are:\n\n" . var_export($log, true); $lasttime = get_config('admin', 'lastloginserterrormail'); if (empty($lasttime) || time() - $lasttime > 60 * 60 * 24) { // limit to 1 email per day //using email directly rather than messaging as they may not be able to log in to access a message mail($CFG->supportemail, $subject, $message); set_config('lastloginserterrormail', time(), 'admin'); } } } }
/** * Create a shorten filename * * @param string $str filename * @param int $maxlength max file name length * @return string short filename */ public function get_short_filename($str, $maxlength) { if (textlib::strlen($str) >= $maxlength) { return trim(textlib::substr($str, 0, $maxlength)) . '...'; } else { return $str; } }
/** * Internal function - prints the search results * * @param string $query String to search for * @return string empty or XHTML */ function admin_search_settings_html($query) { global $CFG, $OUTPUT; if (textlib::strlen($query) < 2) { return ''; } $query = textlib::strtolower($query); $adminroot = admin_get_root(); $findings = $adminroot->search($query); $return = ''; $savebutton = false; foreach ($findings as $found) { $page = $found->page; $settings = $found->settings; if ($page->is_hidden()) { // hidden pages are not displayed in search results continue; } if ($page instanceof admin_externalpage) { $return .= $OUTPUT->heading(get_string('searchresults', 'admin') . ' - <a href="' . $page->url . '">' . highlight($query, $page->visiblename) . '</a>', 2, 'main'); } else { if ($page instanceof admin_settingpage) { $return .= $OUTPUT->heading(get_string('searchresults', 'admin') . ' - <a href="' . $CFG->wwwroot . '/' . $CFG->admin . '/settings.php?section=' . $page->name . '">' . highlight($query, $page->visiblename) . '</a>', 2, 'main'); } else { continue; } } if (!empty($settings)) { $return .= '<fieldset class="adminsettings">' . "\n"; foreach ($settings as $setting) { if (empty($setting->nosave)) { $savebutton = true; } $return .= '<div class="clearer"><!-- --></div>' . "\n"; $fullname = $setting->get_full_name(); if (array_key_exists($fullname, $adminroot->errors)) { $data = $adminroot->errors[$fullname]->data; } else { $data = $setting->get_setting(); // do not use defaults if settings not available - upgradesettings handles the defaults! } $return .= $setting->output_html($data, $query); } $return .= '</fieldset>'; } } if ($savebutton) { $return .= '<div class="form-buttons"><input class="form-submit" type="submit" value="' . get_string('savechanges', 'admin') . '" /></div>'; } return $return; }
/** * Ensure that a question name does not contain anything nasty, and will fit in the DB field. * @param string $name the raw question name. * @return string a safe question name. */ public function clean_question_name($name) { $name = clean_param($name, PARAM_TEXT); // Matches what the question editing form does. $name = trim($name); $trimlength = 251; while (textlib::strlen($name) > 255 && $trimlength > 0) { $name = shorten_text($name, $trimlength); $trimlength -= 10; } return $name; }
public function save_usage($preferredbehaviour, $attempt, $qas, $quizlayout) { $missing = array(); $layout = explode(',', $attempt->layout); $questionkeys = array_combine(array_values($layout), array_keys($layout)); $this->set_quba_preferred_behaviour($attempt->uniqueid, $preferredbehaviour); $i = 0; foreach (explode(',', $quizlayout) as $questionid) { if ($questionid == 0) { continue; } $i++; if (!array_key_exists($questionid, $qas)) { $missing[] = $questionid; $layout[$questionkeys[$questionid]] = $questionid; continue; } $qa = $qas[$questionid]; $qa->questionusageid = $attempt->uniqueid; $qa->slot = $i; if (textlib::strlen($qa->questionsummary) > question_bank::MAX_SUMMARY_LENGTH) { // It seems some people write very long quesions! MDL-30760 $qa->questionsummary = textlib::substr($qa->questionsummary, 0, question_bank::MAX_SUMMARY_LENGTH - 3) . '...'; } $this->insert_record('question_attempts', $qa); $layout[$questionkeys[$questionid]] = $qa->slot; foreach ($qa->steps as $step) { $step->questionattemptid = $qa->id; $this->insert_record('question_attempt_steps', $step); foreach ($step->data as $name => $value) { $datum = new stdClass(); $datum->attemptstepid = $step->id; $datum->name = $name; $datum->value = $value; $this->insert_record('question_attempt_step_data', $datum, false); } } } $this->set_quiz_attempt_layout($attempt->uniqueid, implode(',', $layout)); if ($missing) { notify("Question sessions for questions " . implode(', ', $missing) . " were missing when upgrading question usage {$attempt->uniqueid}."); } }
/** * Returns all files and optionally directories * * @param int $contextid context ID * @param string $component component * @param string $filearea file area * @param int $itemid item ID * @param int $filepath directory path * @param bool $recursive include all subdirectories * @param bool $includedirs include files and directories * @param string $sort A fragment of SQL to use for sorting * @return array of stored_files indexed by pathanmehash */ public function get_directory_files($contextid, $component, $filearea, $itemid, $filepath, $recursive = false, $includedirs = true, $sort = "filepath, filename") { global $DB; if (!($directory = $this->get_file($contextid, $component, $filearea, $itemid, $filepath, '.'))) { return array(); } $orderby = !empty($sort) ? " ORDER BY {$sort}" : ''; if ($recursive) { $dirs = $includedirs ? "" : "AND filename <> '.'"; $length = textlib::strlen($filepath); $sql = "SELECT " . self::instance_sql_fields('f', 'r') . "\n FROM {files} f\n LEFT JOIN {files_reference} r\n ON f.referencefileid = r.id\n WHERE f.contextid = :contextid AND f.component = :component AND f.filearea = :filearea AND f.itemid = :itemid\n AND " . $DB->sql_substr("f.filepath", 1, $length) . " = :filepath\n AND f.id <> :dirid\n {$dirs}\n {$orderby}"; $params = array('contextid' => $contextid, 'component' => $component, 'filearea' => $filearea, 'itemid' => $itemid, 'filepath' => $filepath, 'dirid' => $directory->get_id()); $files = array(); $dirs = array(); $filerecords = $DB->get_records_sql($sql, $params); foreach ($filerecords as $filerecord) { if ($filerecord->filename == '.') { $dirs[$filerecord->pathnamehash] = $this->get_file_instance($filerecord); } else { $files[$filerecord->pathnamehash] = $this->get_file_instance($filerecord); } } $result = array_merge($dirs, $files); } else { $result = array(); $params = array('contextid' => $contextid, 'component' => $component, 'filearea' => $filearea, 'itemid' => $itemid, 'filepath' => $filepath, 'dirid' => $directory->get_id()); $length = textlib::strlen($filepath); if ($includedirs) { $sql = "SELECT " . self::instance_sql_fields('f', 'r') . "\n FROM {files} f\n LEFT JOIN {files_reference} r\n ON f.referencefileid = r.id\n WHERE f.contextid = :contextid AND f.component = :component AND f.filearea = :filearea\n AND f.itemid = :itemid AND f.filename = '.'\n AND " . $DB->sql_substr("f.filepath", 1, $length) . " = :filepath\n AND f.id <> :dirid\n {$orderby}"; $reqlevel = substr_count($filepath, '/') + 1; $filerecords = $DB->get_records_sql($sql, $params); foreach ($filerecords as $filerecord) { if (substr_count($filerecord->filepath, '/') !== $reqlevel) { continue; } $result[$filerecord->pathnamehash] = $this->get_file_instance($filerecord); } } $sql = "SELECT " . self::instance_sql_fields('f', 'r') . "\n FROM {files} f\n LEFT JOIN {files_reference} r\n ON f.referencefileid = r.id\n WHERE f.contextid = :contextid AND f.component = :component AND f.filearea = :filearea AND f.itemid = :itemid\n AND f.filepath = :filepath AND f.filename <> '.'\n {$orderby}"; $filerecords = $DB->get_records_sql($sql, $params); foreach ($filerecords as $filerecord) { $result[$filerecord->pathnamehash] = $this->get_file_instance($filerecord); } } return $result; }
/** * Returns a popup menu with course activity modules * * Given a course * This function returns a small popup menu with all the * course activity modules in it, as a navigation menu * outputs a simple list structure in XHTML * The data is taken from the serialised array stored in * the course record * * @todo Finish documenting this function * * @global object * @uses CONTEXT_COURSE * @param course $course A {@link $COURSE} object. * @param string $sections * @param string $modinfo * @param string $strsection * @param string $strjumpto * @param int $width * @param string $cmid * @return string The HTML block */ function navmenulist($course, $sections, $modinfo, $strsection, $strjumpto, $width=50, $cmid=0) { global $CFG, $OUTPUT; $section = -1; $url = ''; $menu = array(); $doneheading = false; $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); $menu[] = '<ul class="navmenulist"><li class="jumpto section"><span>'.$strjumpto.'</span><ul>'; foreach ($modinfo->cms as $mod) { if (!$mod->has_view()) { // Don't show modules which you can't link to! continue; } if ($mod->sectionnum > $course->numsections) { /// Don't show excess hidden sections break; } if (!$mod->uservisible) { // do not icnlude empty sections at all continue; } if ($mod->sectionnum >= 0 and $section != $mod->sectionnum) { $thissection = $sections[$mod->sectionnum]; if ($thissection->visible or !$course->hiddensections or has_capability('moodle/course:viewhiddensections', $coursecontext)) { $thissection->summary = strip_tags(format_string($thissection->summary,true)); if (!$doneheading) { $menu[] = '</ul></li>'; } if ($course->format == 'weeks' or empty($thissection->summary)) { $item = $strsection ." ". $mod->sectionnum; } else { if (textlib::strlen($thissection->summary) < ($width-3)) { $item = $thissection->summary; } else { $item = textlib::substr($thissection->summary, 0, $width).'...'; } } $menu[] = '<li class="section"><span>'.$item.'</span>'; $menu[] = '<ul>'; $doneheading = true; $section = $mod->sectionnum; } else { // no activities from this hidden section shown continue; } } $url = $mod->modname .'/view.php?id='. $mod->id; $mod->name = strip_tags(format_string($mod->name ,true)); if (textlib::strlen($mod->name) > ($width+5)) { $mod->name = textlib::substr($mod->name, 0, $width).'...'; } if (!$mod->visible) { $mod->name = '('.$mod->name.')'; } $class = 'activity '.$mod->modname; $class .= ($cmid == $mod->id) ? ' selected' : ''; $menu[] = '<li class="'.$class.'">'. '<img src="'.$OUTPUT->pix_url('icon', $mod->modname) . '" alt="" />'. '<a href="'.$CFG->wwwroot.'/mod/'.$url.'">'.$mod->name.'</a></li>'; } if ($doneheading) { $menu[] = '</ul></li>'; } $menu[] = '</ul></li></ul>'; return implode("\n", $menu); }
/** * Given some text (which may contain HTML) and an ideal length, * this function truncates the text neatly on a word boundary if possible * * @category string * @global stdClass $CFG * @param string $text text to be shortened * @param int $ideal ideal string length * @param boolean $exact if false, $text will not be cut mid-word * @param string $ending The string to append if the passed string is truncated * @return string $truncate shortened string */ function shorten_text($text, $ideal = 30, $exact = false, $ending = '...') { global $CFG; // If the plain text is shorter than the maximum length, return the whole text. if (textlib::strlen(preg_replace('/<.*?>/', '', $text)) <= $ideal) { return $text; } // Splits on HTML tags. Each open/close/empty tag will be the first thing // and only tag in its 'line'. preg_match_all('/(<.+?>)?([^<>]*)/s', $text, $lines, PREG_SET_ORDER); $total_length = textlib::strlen($ending); $truncate = ''; // This array stores information about open and close tags and their position // in the truncated string. Each item in the array is an object with fields // ->open (true if open), ->tag (tag name in lower case), and ->pos // (byte position in truncated text). $tagdetails = array(); foreach ($lines as $line_matchings) { // If there is any html-tag in this line, handle it and add it (uncounted) to the output. if (!empty($line_matchings[1])) { // If it's an "empty element" with or without xhtml-conform closing slash (f.e. <br/>). if (preg_match('/^<(\\s*.+?\\/\\s*|\\s*(img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param)(\\s.+?)?)>$/is', $line_matchings[1])) { // Do nothing. } else { if (preg_match('/^<\\s*\\/([^\\s]+?)\\s*>$/s', $line_matchings[1], $tag_matchings)) { // Record closing tag. $tagdetails[] = (object) array('open' => false, 'tag' => textlib::strtolower($tag_matchings[1]), 'pos' => textlib::strlen($truncate)); } else { if (preg_match('/^<\\s*([^\\s>!]+).*?>$/s', $line_matchings[1], $tag_matchings)) { // Record opening tag. $tagdetails[] = (object) array('open' => true, 'tag' => textlib::strtolower($tag_matchings[1]), 'pos' => textlib::strlen($truncate)); } } } // Add html-tag to $truncate'd text. $truncate .= $line_matchings[1]; } // Calculate the length of the plain text part of the line; handle entities as one character. $content_length = textlib::strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $line_matchings[2])); if ($total_length + $content_length > $ideal) { // The number of characters which are left. $left = $ideal - $total_length; $entities_length = 0; // Search for html entities. if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $line_matchings[2], $entities, PREG_OFFSET_CAPTURE)) { // calculate the real length of all entities in the legal range foreach ($entities[0] as $entity) { if ($entity[1] + 1 - $entities_length <= $left) { $left--; $entities_length += textlib::strlen($entity[0]); } else { // no more characters left break; } } } $breakpos = $left + $entities_length; // if the words shouldn't be cut in the middle... if (!$exact) { // ...search the last occurence of a space... for (; $breakpos > 0; $breakpos--) { if ($char = textlib::substr($line_matchings[2], $breakpos, 1)) { if ($char === '.' or $char === ' ') { $breakpos += 1; break; } else { if (strlen($char) > 2) { // Chinese/Japanese/Korean text $breakpos += 1; // can be truncated at any UTF-8 break; // character boundary. } } } } } if ($breakpos == 0) { // This deals with the test_shorten_text_no_spaces case. $breakpos = $left + $entities_length; } else { if ($breakpos > $left + $entities_length) { // This deals with the previous for loop breaking on the first char. $breakpos = $left + $entities_length; } } $truncate .= textlib::substr($line_matchings[2], 0, $breakpos); // maximum length is reached, so get off the loop break; } else { $truncate .= $line_matchings[2]; $total_length += $content_length; } // If the maximum length is reached, get off the loop. if ($total_length >= $ideal) { break; } } // Add the defined ending to the text. $truncate .= $ending; // Now calculate the list of open html tags based on the truncate position. $open_tags = array(); foreach ($tagdetails as $taginfo) { if ($taginfo->open) { // Add tag to the beginning of $open_tags list. array_unshift($open_tags, $taginfo->tag); } else { // Can have multiple exact same open tags, close the last one. $pos = array_search($taginfo->tag, array_reverse($open_tags, true)); if ($pos !== false) { unset($open_tags[$pos]); } } } // Close all unclosed html-tags. foreach ($open_tags as $tag) { $truncate .= '</' . $tag . '>'; } return $truncate; }
/** * Print a select box allowing the user to choose to view new messages, course participants etc. * * Called by message_print_contact_selector() * @param int $viewing What page is the user viewing ie MESSAGE_VIEW_UNREAD_MESSAGES, MESSAGE_VIEW_RECENT_CONVERSATIONS etc * @param array $courses array of course objects. The courses the user is enrolled in. * @param array $coursecontexts array of course contexts. Keyed on course id. * @param int $countunreadtotal how many unread messages does the user have? * @param int $countblocked how many users has the current user blocked? * @param string $strunreadmessages a preconstructed message about the number of unread messages the user has * @return void */ function message_print_usergroup_selector($viewing, $courses, $coursecontexts, $countunreadtotal, $countblocked, $strunreadmessages) { $options = array(); if ($countunreadtotal>0) { //if there are unread messages $options[MESSAGE_VIEW_UNREAD_MESSAGES] = $strunreadmessages; } $str = get_string('mycontacts', 'message'); $options[MESSAGE_VIEW_CONTACTS] = $str; $options[MESSAGE_VIEW_RECENT_CONVERSATIONS] = get_string('mostrecentconversations', 'message'); $options[MESSAGE_VIEW_RECENT_NOTIFICATIONS] = get_string('mostrecentnotifications', 'message'); if (!empty($courses)) { $courses_options = array(); foreach($courses as $course) { if (has_capability('moodle/course:viewparticipants', $coursecontexts[$course->id])) { //Not using short_text() as we want the end of the course name. Not the beginning. $shortname = format_string($course->shortname, true, array('context' => $coursecontexts[$course->id])); if (textlib::strlen($shortname) > MESSAGE_MAX_COURSE_NAME_LENGTH) { $courses_options[MESSAGE_VIEW_COURSE.$course->id] = '...'.textlib::substr($shortname, -MESSAGE_MAX_COURSE_NAME_LENGTH); } else { $courses_options[MESSAGE_VIEW_COURSE.$course->id] = $shortname; } } } if (!empty($courses_options)) { $options[] = array(get_string('courses') => $courses_options); } } if ($countblocked>0) { $str = get_string('blockedusers','message', $countblocked); $options[MESSAGE_VIEW_BLOCKED] = $str; } echo html_writer::start_tag('form', array('id' => 'usergroupform','method' => 'get','action' => '')); echo html_writer::start_tag('fieldset'); echo html_writer::label(get_string('messagenavigation', 'message'), 'viewing'); echo html_writer::select($options, 'viewing', $viewing, false, array('id' => 'viewing','onchange' => 'this.form.submit()')); echo html_writer::end_tag('fieldset'); echo html_writer::end_tag('form'); }
/** * This function trims any given text and returns it with some dots at the end * * @param string $text * @param string $limit * * @return string */ function wiki_trim_string($text, $limit = 25) { if (textlib::strlen($text) > $limit) { $text = textlib::substr($text, 0, $limit) . '...'; } return $text; }
case 'term': $params['hook2'] = $hook; $printpivot = 0; $sqlfrom .= " LEFT JOIN {glossary_alias} ga on ge.id = ga.entryid"; $where = "AND (ge.concept = :hook OR ga.alias = :hook2) "; break; case 'entry': $printpivot = 0; $where = "AND ge.id = :hook"; break; case 'letter': if ($hook != 'ALL' and $hook != 'SPECIAL') { $params['hookup'] = textlib::strtoupper($hook); $where = "AND " . $DB->sql_substr("upper(concept)", 1, textlib::strlen($hook)) . " = :hookup"; } if ($hook == 'SPECIAL') { //Create appropiate IN contents $alphabet = explode(",", get_string('alphabet', 'langconfig')); list($nia, $aparams) = $DB->get_in_or_equal($alphabet, SQL_PARAMS_NAMED, $start='a', false); $params = array_merge($params, $aparams); $where = "AND " . $DB->sql_substr("upper(concept)", 1, 1) . " $nia"; } break; } $sqlwhere = "WHERE (ge.glossaryid = :gid1 or ge.sourceglossaryid = :gid2) AND (ge.approved <> 0 $userid) $where"; switch ( $tab ) {
/** * Migrates one given file stored on disk * * @param string $sourcepath the path to the source local file within the backup archive {@example 'moddata/foobar/file.ext'} * @param string $filepath the file path of the migrated file, defaults to the root directory '/' {@example '/sub/dir/'} * @param string $filename the name of the migrated file, defaults to the same as the source file has * @param int $sortorder the sortorder of the file (main files have sortorder set to 1) * @param int $timecreated override the timestamp of when the migrated file should appear as created * @param int $timemodified override the timestamp of when the migrated file should appear as modified * @return int id of the migrated file */ public function migrate_file($sourcepath, $filepath = '/', $filename = null, $sortorder = 0, $timecreated = null, $timemodified = null) { // Normalise Windows paths a bit. $sourcepath = str_replace('\\', '/', $sourcepath); // PARAM_PATH must not be used on full OS path! if ($sourcepath !== clean_param($sourcepath, PARAM_PATH)) { throw new moodle1_convert_exception('file_invalid_path', $sourcepath); } $sourcefullpath = $this->basepath.'/'.$sourcepath; if (!is_readable($sourcefullpath)) { throw new moodle1_convert_exception('file_not_readable', $sourcefullpath); } // sanitize filepath if (empty($filepath)) { $filepath = '/'; } if (substr($filepath, -1) !== '/') { $filepath .= '/'; } $filepath = clean_param($filepath, PARAM_PATH); if (textlib::strlen($filepath) > 255) { throw new moodle1_convert_exception('file_path_longer_than_255_chars'); } if (is_null($filename)) { $filename = basename($sourcefullpath); } $filename = clean_param($filename, PARAM_FILE); if ($filename === '') { throw new moodle1_convert_exception('unsupported_chars_in_filename'); } if (is_null($timecreated)) { $timecreated = filectime($sourcefullpath); } if (is_null($timemodified)) { $timemodified = filemtime($sourcefullpath); } $filerecord = $this->make_file_record(array( 'filepath' => $filepath, 'filename' => $filename, 'sortorder' => $sortorder, 'mimetype' => mimeinfo('type', $sourcefullpath), 'timecreated' => $timecreated, 'timemodified' => $timemodified, )); list($filerecord['contenthash'], $filerecord['filesize'], $newfile) = $this->add_file_to_pool($sourcefullpath); $this->stash_file($filerecord); return $filerecord['id']; }
/** * This function is used to generate and display selector form * * @global stdClass $USER * @global stdClass $CFG * @global moodle_database $DB * @global core_renderer $OUTPUT * @global stdClass $SESSION * @uses CONTEXT_SYSTEM * @uses COURSE_MAX_COURSES_PER_DROPDOWN * @uses CONTEXT_COURSE * @uses SEPARATEGROUPS * @param stdClass $course course instance * @param int $selecteduser id of the selected user * @param string $selecteddate Date selected * @param string $modname course_module->id * @param string $modid number or 'site_errors' * @param string $modaction an action as recorded in the logs * @param int $selectedgroup Group to display * @param int $showcourses whether to show courses if we're over our limit. * @param int $showusers whether to show users if we're over our limit. * @param string $logformat Format of the logs (downloadascsv, showashtml, downloadasods, downloadasexcel) * @return void */ function report_log_print_selector_form($course, $selecteduser = 0, $selecteddate = 'today', $modname = "", $modid = 0, $modaction = '', $selectedgroup = -1, $showcourses = 0, $showusers = 0, $logformat = 'showashtml') { global $USER, $CFG, $DB, $OUTPUT, $SESSION; // first check to see if we can override showcourses and showusers $numcourses = $DB->count_records("course"); if ($numcourses < COURSE_MAX_COURSES_PER_DROPDOWN && !$showcourses) { $showcourses = 1; } $sitecontext = get_context_instance(CONTEXT_SYSTEM); $context = get_context_instance(CONTEXT_COURSE, $course->id); /// Setup for group handling. if ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) { $selectedgroup = -1; $showgroups = false; } else { if ($course->groupmode) { $showgroups = true; } else { $selectedgroup = 0; $showgroups = false; } } if ($selectedgroup === -1) { if (isset($SESSION->currentgroup[$course->id])) { $selectedgroup = $SESSION->currentgroup[$course->id]; } else { $selectedgroup = groups_get_all_groups($course->id, $USER->id); if (is_array($selectedgroup)) { $selectedgroup = array_shift(array_keys($selectedgroup)); $SESSION->currentgroup[$course->id] = $selectedgroup; } else { $selectedgroup = 0; } } } // Get all the possible users $users = array(); // Define limitfrom and limitnum for queries below // If $showusers is enabled... don't apply limitfrom and limitnum $limitfrom = empty($showusers) ? 0 : ''; $limitnum = empty($showusers) ? COURSE_MAX_USERS_PER_DROPDOWN + 1 : ''; $courseusers = get_enrolled_users($context, '', $selectedgroup, 'u.id, u.firstname, u.lastname', 'lastname ASC, firstname ASC', $limitfrom, $limitnum); if (count($courseusers) < COURSE_MAX_USERS_PER_DROPDOWN && !$showusers) { $showusers = 1; } if ($showusers) { if ($courseusers) { foreach ($courseusers as $courseuser) { $users[$courseuser->id] = fullname($courseuser, has_capability('moodle/site:viewfullnames', $context)); } } $users[$CFG->siteguest] = get_string('guestuser'); } if (has_capability('report/log:view', $sitecontext) && $showcourses) { if ($ccc = $DB->get_records("course", null, "fullname", "id,shortname,fullname,category")) { foreach ($ccc as $cc) { if ($cc->category) { $courses["{$cc->id}"] = format_string(get_course_display_name_for_list($cc)); } else { $courses["{$cc->id}"] = format_string($cc->fullname) . ' (Site)'; } } } asort($courses); } $activities = array(); $selectedactivity = ""; /// Casting $course->modinfo to string prevents one notice when the field is null if ($modinfo = unserialize((string) $course->modinfo)) { $section = 0; $sections = get_all_sections($course->id); foreach ($modinfo as $mod) { if ($mod->mod == "label") { continue; } if ($mod->section > 0 and $section != $mod->section) { $activities["section/{$mod->section}"] = '--- ' . get_section_name($course, $sections[$mod->section]) . ' ---'; } $section = $mod->section; $mod->name = strip_tags(format_string($mod->name, true)); if (textlib::strlen($mod->name) > 55) { $mod->name = textlib::substr($mod->name, 0, 50) . "..."; } if (!$mod->visible) { $mod->name = "(" . $mod->name . ")"; } $activities["{$mod->cm}"] = $mod->name; if ($mod->cm == $modid) { $selectedactivity = "{$mod->cm}"; } } } if (has_capability('report/log:view', $sitecontext) && $course->id == SITEID) { $activities["site_errors"] = get_string("siteerrors"); if ($modid === "site_errors") { $selectedactivity = "site_errors"; } } $strftimedate = get_string("strftimedate"); $strftimedaydate = get_string("strftimedaydate"); asort($users); // Prepare the list of action options. $actions = array('view' => get_string('view'), 'add' => get_string('add'), 'update' => get_string('update'), 'delete' => get_string('delete'), '-view' => get_string('allchanges')); // Get all the possible dates // Note that we are keeping track of real (GMT) time and user time // User time is only used in displays - all calcs and passing is GMT $timenow = time(); // GMT // What day is it now for the user, and when is midnight that day (in GMT). $timemidnight = $today = usergetmidnight($timenow); // Put today up the top of the list $dates = array("{$timemidnight}" => get_string("today") . ", " . userdate($timenow, $strftimedate)); if (!$course->startdate or $course->startdate > $timenow) { $course->startdate = $course->timecreated; } $numdates = 1; while ($timemidnight > $course->startdate and $numdates < 365) { $timemidnight = $timemidnight - 86400; $timenow = $timenow - 86400; $dates["{$timemidnight}"] = userdate($timenow, $strftimedaydate); $numdates++; } if ($selecteddate == "today") { $selecteddate = $today; } echo "<form class=\"logselectform\" action=\"{$CFG->wwwroot}/report/log/index.php\" method=\"get\">\n"; echo "<div>\n"; echo "<input type=\"hidden\" name=\"chooselog\" value=\"1\" />\n"; echo "<input type=\"hidden\" name=\"showusers\" value=\"{$showusers}\" />\n"; echo "<input type=\"hidden\" name=\"showcourses\" value=\"{$showcourses}\" />\n"; if (has_capability('report/log:view', $sitecontext) && $showcourses) { echo html_writer::label(get_string('selectacourse'), 'menuid', false, array('class' => 'accesshide')); echo html_writer::select($courses, "id", $course->id, false); } else { // echo '<input type="hidden" name="id" value="'.$course->id.'" />'; $courses = array(); $courses[$course->id] = get_course_display_name_for_list($course) . ($course->id == SITEID ? ' (' . get_string('site') . ') ' : ''); echo html_writer::label(get_string('selectacourse'), 'menuid', false, array('class' => 'accesshide')); echo html_writer::select($courses, "id", $course->id, false); if (has_capability('report/log:view', $sitecontext)) { $a = new stdClass(); $a->url = "{$CFG->wwwroot}/report/log/index.php?chooselog=0&group={$selectedgroup}&user={$selecteduser}" . "&id={$course->id}&date={$selecteddate}&modid={$selectedactivity}&showcourses=1&showusers={$showusers}"; print_string('logtoomanycourses', 'moodle', $a); } } if ($showgroups) { if ($cgroups = groups_get_all_groups($course->id)) { foreach ($cgroups as $cgroup) { $groups[$cgroup->id] = $cgroup->name; } } else { $groups = array(); } echo html_writer::label(get_string('selectagroup'), 'menugroup', false, array('class' => 'accesshide')); echo html_writer::select($groups, "group", $selectedgroup, get_string("allgroups")); } if ($showusers) { echo html_writer::label(get_string('selctauser'), 'menuuser', false, array('class' => 'accesshide')); echo html_writer::select($users, "user", $selecteduser, get_string("allparticipants")); } else { $users = array(); if (!empty($selecteduser)) { $user = $DB->get_record('user', array('id' => $selecteduser)); $users[$selecteduser] = fullname($user); } else { $users[0] = get_string('allparticipants'); } echo html_writer::label(get_string('selctauser'), 'menuuser', false, array('class' => 'accesshide')); echo html_writer::select($users, "user", $selecteduser, false); $a = new stdClass(); $a->url = "{$CFG->wwwroot}/report/log/index.php?chooselog=0&group={$selectedgroup}&user={$selecteduser}" . "&id={$course->id}&date={$selecteddate}&modid={$selectedactivity}&showusers=1&showcourses={$showcourses}"; print_string('logtoomanyusers', 'moodle', $a); } echo html_writer::label(get_string('date'), 'menudate', false, array('class' => 'accesshide')); echo html_writer::select($dates, "date", $selecteddate, get_string("alldays")); echo html_writer::label(get_string('activities'), 'menumodid', false, array('class' => 'accesshide')); echo html_writer::select($activities, "modid", $selectedactivity, get_string("allactivities")); echo html_writer::label(get_string('actions'), 'menumodaction', false, array('class' => 'accesshide')); echo html_writer::select($actions, 'modaction', $modaction, get_string("allactions")); $logformats = array('showashtml' => get_string('displayonpage'), 'downloadascsv' => get_string('downloadtext'), 'downloadasods' => get_string('downloadods'), 'downloadasexcel' => get_string('downloadexcel')); echo html_writer::label(get_string('logsformat', 'report_log'), 'menulogformat', false, array('class' => 'accesshide')); echo html_writer::select($logformats, 'logformat', $logformat, false); echo '<input type="submit" value="' . get_string('gettheselogs') . '" />'; echo '</div>'; echo '</form>'; }
/** * Given a record in the {blog_external} table, checks the blog's URL * for new entries not yet copied into Moodle. * Also attempts to identify and remove deleted blog entries * * @param object $externalblog * @return boolean False if the Feed is invalid */ function blog_sync_external_entries($externalblog) { global $CFG, $DB; require_once $CFG->libdir . '/simplepie/moodle_simplepie.php'; $rssfile = new moodle_simplepie_file($externalblog->url); $filetest = new SimplePie_Locator($rssfile); if (!$filetest->is_feed($rssfile)) { $externalblog->failedlastsync = 1; $DB->update_record('blog_external', $externalblog); return false; } else { if (!empty($externalblog->failedlastsync)) { $externalblog->failedlastsync = 0; $DB->update_record('blog_external', $externalblog); } } $rss = new moodle_simplepie($externalblog->url); if (empty($rss->data)) { return null; } //used to identify blog posts that have been deleted from the source feed $oldesttimestamp = null; $uniquehashes = array(); foreach ($rss->get_items() as $entry) { // If filtertags are defined, use them to filter the entries by RSS category if (!empty($externalblog->filtertags)) { $containsfiltertag = false; $categories = $entry->get_categories(); $filtertags = explode(',', $externalblog->filtertags); $filtertags = array_map('trim', $filtertags); $filtertags = array_map('strtolower', $filtertags); foreach ($categories as $category) { if (in_array(trim(strtolower($category->term)), $filtertags)) { $containsfiltertag = true; } } if (!$containsfiltertag) { continue; } } $uniquehashes[] = $entry->get_permalink(); $newentry = new stdClass(); $newentry->userid = $externalblog->userid; $newentry->module = 'blog_external'; $newentry->content = $externalblog->id; $newentry->uniquehash = $entry->get_permalink(); $newentry->publishstate = 'site'; $newentry->format = FORMAT_HTML; // Clean subject of html, just in case $newentry->subject = clean_param($entry->get_title(), PARAM_TEXT); // Observe 128 max chars in DB // TODO: +1 to raise this to 255 if (textlib::strlen($newentry->subject) > 128) { $newentry->subject = textlib::substr($newentry->subject, 0, 125) . '...'; } $newentry->summary = $entry->get_description(); //used to decide whether to insert or update //uses enty permalink plus creation date if available $existingpostconditions = array('uniquehash' => $entry->get_permalink()); //our DB doesnt allow null creation or modified timestamps so check the external blog supplied one $entrydate = $entry->get_date('U'); if (!empty($entrydate)) { $existingpostconditions['created'] = $entrydate; } //the post ID or false if post not found in DB $postid = $DB->get_field('post', 'id', $existingpostconditions); $timestamp = null; if (empty($entrydate)) { $timestamp = time(); } else { $timestamp = $entrydate; } //only set created if its a new post so we retain the original creation timestamp if the post is edited if ($postid === false) { $newentry->created = $timestamp; } $newentry->lastmodified = $timestamp; if (empty($oldesttimestamp) || $timestamp < $oldesttimestamp) { //found an older post $oldesttimestamp = $timestamp; } if (textlib::strlen($newentry->uniquehash) > 255) { // The URL for this item is too long for the field. Rather than add // the entry without the link we will skip straight over it. // RSS spec says recommended length 500, we use 255. debugging('External blog entry skipped because of oversized URL', DEBUG_DEVELOPER); continue; } if ($postid === false) { $id = $DB->insert_record('post', $newentry); // Set tags if ($tags = tag_get_tags_array('blog_external', $externalblog->id)) { tag_set('post', $id, $tags); } } else { $newentry->id = $postid; $DB->update_record('post', $newentry); } } // Look at the posts we have in the database to check if any of them have been deleted from the feed. // Only checking posts within the time frame returned by the rss feed. Older items may have been deleted or // may just not be returned anymore. We can't tell the difference so we leave older posts alone. $sql = "SELECT id, uniquehash\n FROM {post}\n WHERE module = 'blog_external'\n AND " . $DB->sql_compare_text('content') . " = " . $DB->sql_compare_text(':blogid') . "\n AND created > :ts"; $dbposts = $DB->get_records_sql($sql, array('blogid' => $externalblog->id, 'ts' => $oldesttimestamp)); $todelete = array(); foreach ($dbposts as $dbpost) { if (!in_array($dbpost->uniquehash, $uniquehashes)) { $todelete[] = $dbpost->id; } } $DB->delete_records_list('post', 'id', $todelete); $DB->update_record('blog_external', array('id' => $externalblog->id, 'timefetched' => time())); }
/** * Trim inputted text to the given maximum length. * @param string $text * @param int $length * @return string The trimmed string with a '...' appended for display. */ function lightboxgallery_resize_text($text, $length) { $textlib = new textlib(); return $textlib->strlen($text) > $length ? $textlib->substr($text, 0, $length) . '...' : $text; }
public function subquestion(question_attempt $qa, question_display_options $options, $index, question_graded_automatically $subq) { $fieldprefix = 'sub' . $index . '_'; $fieldname = $fieldprefix . 'answer'; $response = $qa->get_last_qt_var($fieldname); if ($subq->qtype->name() == 'shortanswer') { $matchinganswer = $subq->get_matching_answer(array('answer' => $response)); } else if ($subq->qtype->name() == 'numerical') { list($value, $unit, $multiplier) = $subq->ap->apply_units($response, ''); $matchinganswer = $subq->get_matching_answer($value, 1); } else { $matchinganswer = $subq->get_matching_answer($response); } if (!$matchinganswer) { if (is_null($response) || $response === '') { $matchinganswer = new question_answer(0, '', null, '', FORMAT_HTML); } else { $matchinganswer = new question_answer(0, '', 0.0, '', FORMAT_HTML); } } // Work out a good input field size. $size = max(1, textlib::strlen(trim($response)) + 1); foreach ($subq->answers as $ans) { $size = max($size, textlib::strlen(trim($ans->answer))); } $size = min(60, round($size + rand(0, $size*0.15))); // The rand bit is to make guessing harder. $inputattributes = array( 'type' => 'text', 'name' => $qa->get_qt_field_name($fieldname), 'value' => $response, 'id' => $qa->get_qt_field_name($fieldname), 'size' => $size, ); if ($options->readonly) { $inputattributes['readonly'] = 'readonly'; } $feedbackimg = ''; if ($options->correctness) { $inputattributes['class'] = $this->feedback_class($matchinganswer->fraction); $feedbackimg = $this->feedback_image($matchinganswer->fraction); } if ($subq->qtype->name() == 'shortanswer') { $correctanswer = $subq->get_matching_answer($subq->get_correct_response()); } else { $correctanswer = $subq->get_correct_answer(); } $feedbackpopup = $this->feedback_popup($subq, $matchinganswer->fraction, $subq->format_text($matchinganswer->feedback, $matchinganswer->feedbackformat, $qa, 'question', 'answerfeedback', $matchinganswer->id), s($correctanswer->answer), $options); $output = html_writer::start_tag('span', array('class' => 'subquestion')); $output .= html_writer::tag('label', get_string('answer'), array('class' => 'subq accesshide', 'for' => $inputattributes['id'])); $output .= html_writer::empty_tag('input', $inputattributes); $output .= $feedbackimg; $output .= $feedbackpopup; $output .= html_writer::end_tag('span'); return $output; }
/** * Tests the static string length method * @return void */ public function test_strlen() { $str = "Žluťoučký koníček"; $this->assertSame(textlib::strlen($str), 17); $iso2 = pack("H*", "ae6c75bb6f75e86bfd206b6f6eede8656b"); $this->assertSame(textlib::strlen($iso2, 'iso-8859-2'), 17); $win = pack("H*", "8e6c759d6f75e86bfd206b6f6eede8656b"); $this->assertSame(textlib::strlen($win, 'cp1250'), 17); $str = pack("H*", "b8ec"); //EUC-JP $this->assertSame(textlib::strlen($str, 'EUC-JP'), 1); $str = pack("H*", "b8c0b8ecc0dfc4ea"); //EUC-JP $this->assertSame(textlib::strlen($str, 'EUC-JP'), 4); $str = pack("H*", "1b2442386c1b2842"); //ISO-2022-JP $this->assertSame(textlib::strlen($str, 'ISO-2022-JP'), 1); $str = pack("H*", "1b24423840386c405f446a1b2842"); //ISO-2022-JP $this->assertSame(textlib::strlen($str, 'ISO-2022-JP'), 4); $str = pack("H*", "8cea"); //SHIFT-JIS $this->assertSame(textlib::strlen($str, 'SHIFT-JIS'), 1); $str = pack("H*", "8cbe8cea90dd92e8"); //SHIFT-JIS $this->assertSame(textlib::strlen($str, 'SHIFT-JIS'), 4); $str = pack("H*", "cce5"); //GB2312 $this->assertSame(textlib::strlen($str, 'GB2312'), 1); $str = pack("H*", "bcf2cce5d6d0cec4"); //GB2312 $this->assertSame(textlib::strlen($str, 'GB2312'), 4); $str = pack("H*", "cce5"); //GB18030 $this->assertSame(textlib::strlen($str, 'GB18030'), 1); $str = pack("H*", "bcf2cce5d6d0cec4"); //GB18030 $this->assertSame(textlib::strlen($str, 'GB18030'), 4); }
/** * Prints an individual user box * * @param user_object $user (contains the following fields: id, firstname, lastname and picture) * @param bool $return if true return html string * @return string|null a HTML string or null if this function does the output */ function tag_print_user_box($user, $return = false) { global $CFG, $OUTPUT; $usercontext = get_context_instance(CONTEXT_USER, $user->id); $profilelink = ''; if ($usercontext and has_capability('moodle/user:viewdetails', $usercontext) || has_coursecontact_role($user->id)) { $profilelink = $CFG->wwwroot . '/user/view.php?id=' . $user->id; } $output = $OUTPUT->box_start('user-box', 'user' . $user->id); $fullname = fullname($user); $alt = ''; if (!empty($profilelink)) { $output .= '<a href="' . $profilelink . '">'; $alt = $fullname; } $output .= $OUTPUT->user_picture($user, array('size' => 100)); $output .= '<br />'; if (!empty($profilelink)) { $output .= '</a>'; } //truncate name if it's too big if (textlib::strlen($fullname) > 26) { $fullname = textlib::substr($fullname, 0, 26) . '...'; } $output .= '<strong>' . $fullname . '</strong>'; $output .= $OUTPUT->box_end(); if ($return) { return $output; } else { echo $output; } }
/** * If new messages are waiting for the current user, then insert * JavaScript to pop up the messaging window into the page * * @global moodle_page $PAGE * @return void */ function message_popup_window() { global $USER, $DB, $PAGE, $CFG, $SITE; if (!$PAGE->get_popup_notification_allowed() || empty($CFG->messaging)) { return; } if (!isloggedin() || isguestuser()) { return; } if (!isset($USER->message_lastpopup)) { $USER->message_lastpopup = 0; } else { if ($USER->message_lastpopup > time() - 120) { //dont run the query to check whether to display a popup if its been run in the last 2 minutes return; } } //a quick query to check whether the user has new messages $messagecount = $DB->count_records('message', array('useridto' => $USER->id)); if ($messagecount < 1) { return; } //got unread messages so now do another query that joins with the user table $messagesql = "SELECT m.id, m.smallmessage, m.fullmessageformat, m.notification, u.firstname, u.lastname\n FROM {message} m\n JOIN {message_working} mw ON m.id=mw.unreadmessageid\n JOIN {message_processors} p ON mw.processorid=p.id\n JOIN {user} u ON m.useridfrom=u.id\n WHERE m.useridto = :userid\n AND p.name='popup'"; //if the user was last notified over an hour ago we can renotify them of old messages //so don't worry about when the new message was sent $lastnotifiedlongago = $USER->message_lastpopup < time() - 3600; if (!$lastnotifiedlongago) { $messagesql .= 'AND m.timecreated > :lastpopuptime'; } $message_users = $DB->get_records_sql($messagesql, array('userid' => $USER->id, 'lastpopuptime' => $USER->message_lastpopup)); //if we have new messages to notify the user about if (!empty($message_users)) { $strmessages = ''; if (count($message_users) > 1) { $strmessages = get_string('unreadnewmessages', 'message', count($message_users)); } else { $message_users = reset($message_users); //show who the message is from if its not a notification if (!$message_users->notification) { $strmessages = get_string('unreadnewmessage', 'message', fullname($message_users)); } //try to display the small version of the message $smallmessage = null; if (!empty($message_users->smallmessage)) { //display the first 200 chars of the message in the popup $smallmessage = null; if (textlib::strlen($message_users->smallmessage) > 200) { $smallmessage = textlib::substr($message_users->smallmessage, 0, 200) . '...'; } else { $smallmessage = $message_users->smallmessage; } //prevent html symbols being displayed if ($message_users->fullmessageformat == FORMAT_HTML) { $smallmessage = html_to_text($smallmessage); } else { $smallmessage = s($smallmessage); } } else { if ($message_users->notification) { //its a notification with no smallmessage so just say they have a notification $smallmessage = get_string('unreadnewnotification', 'message'); } } if (!empty($smallmessage)) { $strmessages .= '<div id="usermessage">' . s($smallmessage) . '</div>'; } } $strgomessage = get_string('gotomessages', 'message'); $strstaymessage = get_string('ignore', 'admin'); $url = $CFG->wwwroot . '/message/index.php'; $content = html_writer::start_tag('div', array('id' => 'newmessageoverlay', 'class' => 'mdl-align')) . html_writer::start_tag('div', array('id' => 'newmessagetext')) . $strmessages . html_writer::end_tag('div') . html_writer::start_tag('div', array('id' => 'newmessagelinks')) . html_writer::link($url, $strgomessage, array('id' => 'notificationyes')) . ' ' . html_writer::link('', $strstaymessage, array('id' => 'notificationno')) . html_writer::end_tag('div'); html_writer::end_tag('div'); $PAGE->requires->js_init_call('M.core_message.init_notification', array('', $content, $url)); $USER->message_lastpopup = time(); } }
/** * Truncate a string in the center * @param string $string The string to truncate * @param int $length The length to truncate to * @return string The truncated string */ protected function trim_center($string, $length) { $trimlength = ceil($length / 2); $start = textlib::substr($string, 0, $trimlength); $end = textlib::substr($string, textlib::strlen($string) - $trimlength); $string = $start . '...' . $end; return $string; }
$search = $val; } } } else { $search = optional_param('search', $SESSION->dataprefs[$data->id]['search'], PARAM_NOTAGS); //Paging variable not used for standard search. Set it to null. $paging = NULL; } // Disable search filters if $filter is not true: if (! $filter) { $search = ''; } if (textlib::strlen($search) < 2) { $search = ''; } $SESSION->dataprefs[$data->id]['search'] = $search; // Make it sticky $sort = optional_param('sort', $SESSION->dataprefs[$data->id]['sort'], PARAM_INT); $SESSION->dataprefs[$data->id]['sort'] = $sort; // Make it sticky $order = (optional_param('order', $SESSION->dataprefs[$data->id]['order'], PARAM_ALPHA) == 'ASC') ? 'ASC': 'DESC'; $SESSION->dataprefs[$data->id]['order'] = $order; // Make it sticky $oldperpage = get_user_preferences('data_perpage_'.$data->id, 10); $perpage = optional_param('perpage', $oldperpage, PARAM_INT); if ($perpage < 2) {
/** * Migrate giportfolio files stored in moddata folders. * * Please note it was a big mistake to store the files there in the first place! * * @param stdClass $giportfolio * @param stdClass $context * @param string $path * @return void */ function mod_giportfolio_migrate_moddata_dir_to_legacy($giportfolio, $context, $path) { global $OUTPUT, $CFG; $base = "{$CFG->dataroot}/{$giportfolio->course}/{$CFG->moddata}/giportfolio/{$giportfolio->id}"; $fulldir = $base . $path; if (!is_dir($fulldir)) { // Does not exist. return; } $fs = get_file_storage(); $items = new DirectoryIterator($fulldir); foreach ($items as $item) { if ($item->isDot()) { unset($item); // Release file handle. continue; } if ($item->isLink()) { // Do not follow symlinks - they were never supported in moddata, sorry. unset($item); // Release file handle. continue; } if ($item->isFile()) { if (!$item->isReadable()) { echo $OUTPUT->notification(" File not readable, skipping: " . $fulldir . $item->getFilename()); unset($item); // Release file handle. continue; } $filepath = clean_param("/{$CFG->moddata}/giportfolio/{$giportfolio->id}" . $path, PARAM_PATH); $filename = clean_param($item->getFilename(), PARAM_FILE); if ($filename === '') { // Unsupported chars, sorry. unset($item); // Release file handle. continue; } if (textlib::strlen($filepath) > 255) { echo $OUTPUT->notification(" File path longer than 255 chars, skipping: " . $fulldir . $item->getFilename()); unset($item); // Release file handle. continue; } if (!$fs->file_exists($context->id, 'course', 'legacy', '0', $filepath, $filename)) { $filerecord = array('contextid' => $context->id, 'component' => 'course', 'filearea' => 'legacy', 'itemid' => 0, 'filepath' => $filepath, 'filename' => $filename, 'timecreated' => $item->getCTime(), 'timemodified' => $item->getMTime()); $fs->create_file_from_pathname($filerecord, $fulldir . $item->getFilename()); } $oldpathname = $fulldir . $item->getFilename(); unset($item); // Release file handle. @unlink($oldpathname); } else { // Migrate recursively all subdirectories. $oldpathname = $base . $item->getFilename() . '/'; $subpath = $path . $item->getFilename() . '/'; unset($item); // Release file handle. giportfolio_migrate_moddata_dir_to_legacy($giportfolio, $context, $subpath); @rmdir($oldpathname); // Deletes dir if empty. } } unset($items); // Release file handles. }
/** * Updates the record with either form data or raw data * * Please note that this function does not verify access control. * * This function calls coursecat::change_parent_raw if field 'parent' is updated. * It also calls coursecat::hide_raw or coursecat::show_raw if 'visible' is updated. * Visibility is changed first and then parent is changed. This means that * if parent category is hidden, the current category will become hidden * too and it may overwrite whatever was set in field 'visible'. * * Note that fields 'path' and 'depth' can not be updated manually * Also coursecat::update() can not directly update the field 'sortoder' * * @param array|stdClass $data * @param array $editoroptions if specified, the data is considered to be * form data and file_postupdate_standard_editor() is being called to * process images in description. * @throws moodle_exception */ public function update($data, $editoroptions = null) { global $DB, $CFG; if (!$this->id) { // there is no actual DB record associated with root category return; } $data = (object) $data; $newcategory = new stdClass(); $newcategory->id = $this->id; // copy all description* fields regardless of whether this is form data or direct field update foreach ($data as $key => $value) { if (preg_match("/^description/", $key)) { $newcategory->{$key} = $value; } } if (isset($data->name) && empty($data->name)) { throw new moodle_exception('categorynamerequired'); } if (!empty($data->name) && $data->name !== $this->name) { if (textlib::strlen($data->name) > 255) { throw new moodle_exception('categorytoolong'); } $newcategory->name = $data->name; } if (isset($data->idnumber) && $data->idnumber != $this->idnumber) { if (textlib::strlen($data->idnumber) > 100) { throw new moodle_exception('idnumbertoolong'); } if ($DB->record_exists('course_categories', array('idnumber' => $data->idnumber))) { throw new moodle_exception('categoryidnumbertaken'); } $newcategory->idnumber = $data->idnumber; } if (isset($data->theme) && !empty($CFG->allowcategorythemes)) { $newcategory->theme = $data->theme; } $changes = false; if (isset($data->visible)) { if ($data->visible) { $changes = $this->show_raw(); } else { $changes = $this->hide_raw(0); } } if (isset($data->parent) && $data->parent != $this->parent) { if ($changes) { cache_helper::purge_by_event('changesincoursecat'); } $parentcat = self::get($data->parent, MUST_EXIST, true); $this->change_parent_raw($parentcat); fix_course_sortorder(); } $newcategory->timemodified = time(); if ($editoroptions) { $categorycontext = context_coursecat::instance($this->id); $newcategory = file_postupdate_standard_editor($newcategory, 'description', $editoroptions, $categorycontext, 'coursecat', 'description', 0); } $DB->update_record('course_categories', $newcategory); add_to_log(SITEID, "category", 'update', "editcategory.php?id={$this->id}", $this->id); fix_course_sortorder(); // purge cache even if fix_course_sortorder() did not do it cache_helper::purge_by_event('changesincoursecat'); // update all fields in the current object $this->restore(); }