Common tern with fish
Fullføringsbetingelser
Vis
Whoops \ Exception \ ErrorException
(E_USER_NOTICE)
Stack frames (13)
12
debugging
…/lib/classes/collator.php102
11
core_collator
ensure_collator_available
…/lib/classes/collator.php188
10
core_collator
asort
…/lib/classes/collator.php263
9
core_collator
asort_objects_by_property
…/filter/activitynames/classes/text_filter.php113
8
filter_activitynames\text_filter
get_activity_list
…/filter/activitynames/classes/text_filter.php79
7
filter_activitynames\text_filter
get_cached_activity_list
…/filter/activitynames/classes/text_filter.php43
6
filter_activitynames\text_filter
filter
…/filter/classes/text_filter.php116
5
core_filters\text_filter
filter_stage_post_clean
…/filter/classes/filter_manager.php185
4
core_filters\filter_manager
apply_filter_chain
…/filter/classes/filter_manager.php231
3
core_filters\filter_manager
filter_text
…/lib/classes/formatting.php240
2
core\formatting
format_text
…/lib/weblib.php617
1
format_text
…/mod/resource/locallib.php107
0
resource_display_embed
…/mod/resource/view.php100
/opt/moodle/lib/classes/collator.php
if ($errorcode !== 0) {
// Get the actual locale being used, e.g. en, he, zh
$localeinuse = $collator->getLocale(Locale::ACTUAL_LOCALE);
// Check for the common fallback warning error codes. If any of the two
// following errors occurred, there is normally little to worry about:
// * U_USING_FALLBACK_WARNING (-128) indicates that a fall back locale was
// used. For example, 'de_CH' was requested, but nothing was found
// there, so 'de' was used.
// * U_USING_DEFAULT_WARNING (-127) indicates that the default locale
// data was used; neither the requested locale nor any of its fall
// back locales could be found. For example, 'pt' was requested, but
// UCA was used (Unicode Collation Algorithm http://unicode.org/reports/tr10/).
// See http://www.icu-project.org/apiref/icu4c/classicu_1_1ResourceBundle.html
if ($errorcode === -127 || $errorcode === -128) {
// Check if the locale in use is UCA default one ('root') or
// if it is anything like the locale we asked for
if ($localeinuse !== 'root' && strpos($locale, $localeinuse) !== 0) {
// The locale we asked for is completely different to the locale
// we have received, let the user know via debugging
debugging('Locale warning (not fatal) '.$errormessage.': '.
'Requested locale "'.$locale.'" not found, locale "'.$localeinuse.'" used instead. '.
'The most specific locale supported by ICU relatively to the requested locale is "'.
$collator->getLocale(Locale::VALID_LOCALE).'".');
} else {
// Nothing to do here, this is expected!
// The Moodle locale setting isn't what the collator expected but
// it is smart enough to match the first characters of our locale
// to find the correct locale or to use UCA collation
}
} else {
// We've received some other sort of non fatal warning - let the
// user know about it via debugging.
debugging('Problem with locale: '.$errormessage.'. '.
'Requested locale: "'.$locale.'", actual locale "'.$localeinuse.'". '.
'The most specific locale supported by ICU relatively to the requested locale is "'.
$collator->getLocale(Locale::VALID_LOCALE).'".');
}
}
// Store the collator object now that we can be sure it is in a workable condition
self::$collator = $collator;
/opt/moodle/lib/classes/collator.php
* @param array $arr array to be sorted (reference)
* @param int $sortflag One of core_collator::SORT_NUMERIC, core_collator::SORT_STRING, core_collator::SORT_NATURAL, core_collator::SORT_REGULAR
* optionally "|" core_collator::CASE_SENSITIVE
* @return bool True on success
*/
public static function asort(array &$arr, $sortflag = core_collator::SORT_STRING) {
if (empty($arr)) {
// nothing to do
return true;
}
$original = null;
$casesensitive = (bool)($sortflag & core_collator::CASE_SENSITIVE);
$sortflag = ($sortflag & ~core_collator::CASE_SENSITIVE);
if ($sortflag != core_collator::SORT_NATURAL and $sortflag != core_collator::SORT_STRING) {
$casesensitive = false;
}
if (self::ensure_collator_available()) {
if ($sortflag == core_collator::SORT_NUMERIC) {
$flag = Collator::SORT_NUMERIC;
} else if ($sortflag == core_collator::SORT_REGULAR) {
$flag = Collator::SORT_REGULAR;
} else {
$flag = Collator::SORT_STRING;
}
if ($sortflag == core_collator::SORT_NATURAL) {
$original = $arr;
if ($sortflag == core_collator::SORT_NATURAL) {
foreach ($arr as $key => $value) {
$arr[$key] = self::naturalise((string)$value);
}
}
}
if ($casesensitive) {
self::$collator->setAttribute(Collator::CASE_FIRST, Collator::UPPER_FIRST);
/opt/moodle/lib/classes/collator.php
}
return $result;
}
/**
* Locale aware sort of objects by a property in common to all objects
*
* @param array $objects An array of objects to sort (handled by reference)
* @param string $property The property to use for comparison
* @param int $sortflag One of core_collator::SORT_NUMERIC, core_collator::SORT_STRING, core_collator::SORT_NATURAL, core_collator::SORT_REGULAR
* optionally "|" core_collator::CASE_SENSITIVE
* @return bool True on success
*/
public static function asort_objects_by_property(array &$objects, $property, $sortflag = core_collator::SORT_STRING) {
$original = $objects;
foreach ($objects as $key => $object) {
$objects[$key] = $object->$property;
}
$result = self::asort($objects, $sortflag);
self::restore_array($objects, $original);
return $result;
}
/**
* Locale aware sort of objects by a method in common to all objects
*
* @param array $objects An array of objects to sort (handled by reference)
* @param string $method The method to call to generate a value for comparison
* @param int $sortflag One of core_collator::SORT_NUMERIC, core_collator::SORT_STRING, core_collator::SORT_NATURAL, core_collator::SORT_REGULAR
* optionally "|" core_collator::CASE_SENSITIVE
* @return bool True on success
*/
public static function asort_objects_by_method(array &$objects, $method, $sortflag = core_collator::SORT_STRING) {
$original = $objects;
foreach ($objects as $key => $object) {
$objects[$key] = $object->{$method}();
}
$result = self::asort($objects, $sortflag);
self::restore_array($objects, $original);
/opt/moodle/filter/activitynames/classes/text_filter.php
$modinfo = get_fast_modinfo($courseid);
if (!empty($modinfo->cms)) {
$activitylist = []; // We will store all the created filters here.
// Create array of visible activities sorted by the name length (we are only interested in properties name and url).
$sortedactivities = [];
foreach ($modinfo->cms as $cm) {
// Use normal access control and visibility, but exclude labels and hidden activities.
if ($cm->visible && $cm->has_view() && $cm->uservisible) {
$sortedactivities[] = (object)[
'name' => $cm->name,
'url' => $cm->url,
'id' => $cm->id,
'namelen' => -strlen($cm->name), // Negative value for reverse sorting.
];
}
}
// Sort activities by the length of the activity name in reverse order.
core_collator::asort_objects_by_property($sortedactivities, 'namelen', core_collator::SORT_NUMERIC);
foreach ($sortedactivities as $cm) {
$title = s(trim(strip_tags($cm->name)));
$currentname = trim($cm->name);
$entitisedname = s($currentname);
// Avoid empty or unlinkable activity names.
if (!empty($title)) {
$hreftagbegin = html_writer::start_tag(
'a',
['class' => 'autolink', 'title' => $title,
'href' => $cm->url, ]
);
$activitylist[$cm->id] = new filterobject($currentname, $hreftagbegin, '</a>', false, true);
if ($currentname != $entitisedname) {
// If name has some entity (& " < >) add that filter too. MDL-17545.
$activitylist[$cm->id . '-e'] = new filterobject($entitisedname, $hreftagbegin, '</a>', false, true);
}
}
}
}
/opt/moodle/filter/activitynames/classes/text_filter.php
}
}
/**
* Get all the cached activity list for a course
*
* @param int $courseid id of the course
* @return filterobject[] the activities
*/
protected function get_cached_activity_list($courseid) {
global $USER;
$cached = cache::make_from_params(cache_store::MODE_REQUEST, 'filter', 'activitynames');
// Return cached activity list.
if ($cached->get('cachecourseid') == $courseid && $cached->get('cacheuserid') == $USER->id) {
return $cached->get('activitylist');
}
// Not cached yet, get activity list and set cache.
$activitylist = $this->get_activity_list($courseid);
$cached->set('cacheuserid', $USER->id);
$cached->set('cachecourseid', $courseid);
$cached->set('activitylist', $activitylist);
return $activitylist;
}
/**
* Get all the activity list for a course
*
* @param int $courseid id of the course
* @return filterobject[] the activities
*/
protected function get_activity_list($courseid) {
$activitylist = [];
$modinfo = get_fast_modinfo($courseid);
if (!empty($modinfo->cms)) {
$activitylist = []; // We will store all the created filters here.
// Create array of visible activities sorted by the name length (we are only interested in properties name and url).
/opt/moodle/filter/activitynames/classes/text_filter.php
/**
* This filter provides automatic linking to
* activities when its name (title) is found inside every Moodle text
*
* @package filter_activitynames
* @subpackage activitynames
* @copyright 2004 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class text_filter extends \core_filters\text_filter {
#[\Override]
public function filter($text, array $options = []) {
$coursectx = $this->context->get_course_context(false);
if (!$coursectx) {
return $text;
}
$courseid = $coursectx->instanceid;
$activitylist = $this->get_cached_activity_list($courseid);
$filterslist = [];
if (!empty($activitylist)) {
$cmid = $this->context->instanceid;
if ($this->context->contextlevel == CONTEXT_MODULE && isset($activitylist[$cmid])) {
// Remove filterobjects for the current module.
$filterslist = array_values(array_diff_key($activitylist, [$cmid => 1, $cmid . '-e' => 1]));
} else {
$filterslist = array_values($activitylist);
}
}
if ($filterslist) {
return $text = filter_phrases($text, $filterslist);
} else {
return $text;
}
}
/**
/opt/moodle/filter/classes/text_filter.php
* @param array $options
* @return string
*/
public function filter_stage_pre_clean(string $text, array $options): string {
// NOTE: override if necessary.
return $text;
}
/**
* Filter HTML text at the very end after text is sanitised.
*
* NOTE: this is called even if $options['noclean'] is true and text is not cleaned.
*
* @param string $text
* @param array $options
* @return string
*/
public function filter_stage_post_clean(string $text, array $options): string {
// NOTE: override if necessary.
return $this->filter($text, $options);
}
/**
* Filter simple text coming from format_string().
*
* Note that unless $CFG->formatstringstriptags is disabled
* HTML tags are not expected in returned value.
*
* @param string $text
* @param array $options
* @return string
*/
public function filter_stage_string(string $text, array $options): string {
// NOTE: override if necessary.
return $this->filter($text, $options);
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
/opt/moodle/filter/classes/filter_manager.php
array $options = [],
?array $skipfilters = null
) {
if (!isset($options['stage'])) {
$filtermethod = 'filter';
} else if (in_array($options['stage'], ['pre_format', 'pre_clean', 'post_clean', 'string'], true)) {
$filtermethod = 'filter_stage_' . $options['stage'];
} else {
$filtermethod = 'filter';
debugging('Invalid filter stage specified in options: ' . $options['stage'], DEBUG_DEVELOPER);
}
if ($text === null || $text === '') {
// Nothing to filter.
return '';
}
foreach ($filterchain as $filtername => $filter) {
if ($skipfilters !== null && in_array($filtername, $skipfilters)) {
continue;
}
$text = $filter->$filtermethod($text, $options);
}
return $text;
}
/**
* Get all the filters that apply to a given context for calls to format_text.
*
* @param context $context
* @return moodle_text_filter[] A text filter
*/
protected function get_text_filters($context) {
if (!isset($this->textfilters[$context->id])) {
$this->load_filters($context);
}
return $this->textfilters[$context->id];
}
/**
* Get all the filters that apply to a given context for calls to format_string.
*
/opt/moodle/filter/classes/filter_manager.php
}
return $this->stringfilters[$context->id];
}
/**
* Filter some text
*
* @param string $text The text to filter
* @param context $context the context.
* @param array $options options passed to the filters
* @param null|array $skipfilters of filter names. Any filters that should not be applied to this text.
* @return string resulting text
*/
public function filter_text(
$text,
$context,
array $options = [],
?array $skipfilters = null
) {
$text = $this->apply_filter_chain($text, $this->get_text_filters($context), $options, $skipfilters);
if (!isset($options['stage']) || $options['stage'] === 'post_clean') {
// Remove <nolink> tags for XHTML compatibility after the last filtering stage.
$text = str_replace(['<nolink>', '</nolink>'], '', $text);
}
return $text;
}
/**
* Filter a piece of string
*
* @param string $string The text to filter
* @param context $context the context.
* @return string resulting string
*/
public function filter_string($string, $context) {
return $this->apply_filter_chain($string, $this->get_string_filters($context), ['stage' => 'string']);
}
/**
* Setup page with filters requirements and other prepare stuff.
/opt/moodle/lib/classes/formatting.php
];
} else {
$filtermanager = new \null_filter_manager();
$filteroptions = [];
}
switch ($format) {
case FORMAT_HTML:
$filteroptions['stage'] = 'pre_format';
$text = $filtermanager->filter_text($text, $context, $filteroptions);
// Text is already in HTML format, so just continue to the next filtering stage.
$filteroptions['stage'] = 'pre_clean';
$text = $filtermanager->filter_text($text, $context, $filteroptions);
if ($clean) {
$text = clean_text($text, FORMAT_HTML, [
'allowid' => $allowid,
]);
}
$filteroptions['stage'] = 'post_clean';
$text = $filtermanager->filter_text($text, $context, $filteroptions);
break;
case FORMAT_PLAIN:
$text = s($text); // Cleans dangerous JS.
$text = rebuildnolinktag($text);
$text = str_replace(' ', ' ', $text);
$text = nl2br($text);
break;
case FORMAT_MARKDOWN:
$filteroptions['stage'] = 'pre_format';
$text = $filtermanager->filter_text($text, $context, $filteroptions);
$text = markdown_to_html($text);
$filteroptions['stage'] = 'pre_clean';
$text = $filtermanager->filter_text($text, $context, $filteroptions);
if ($clean) {
$text = clean_text($text, FORMAT_HTML, [
'allowid' => $allowid,
]);
}
/opt/moodle/lib/weblib.php
unset($options[$option]);
}
}
foreach ($options as $option => $value) {
$params[$option] = $value;
}
// The noclean option has been renamed to clean.
if (array_key_exists('noclean', $params)) {
$params['clean'] = !$params['noclean'];
unset($params['noclean']);
}
}
if ($format !== null) {
$params['format'] = $format;
}
return \core\di::get(\core\formatting::class)->format_text(...$params);
}
/**
* Resets some data related to filters, called during upgrade or when general filter settings change.
*
* @param bool $phpunitreset true means called from our PHPUnit integration test reset
* @return void
*/
function reset_text_filters_cache($phpunitreset = false) {
global $CFG, $DB;
if ($phpunitreset) {
// HTMLPurifier does not change, DB is already reset to defaults,
// nothing to do here, the dataroot was cleared too.
return;
}
// The purge_all_caches() deals with cachedir and localcachedir purging,
// the individual filter caches are invalidated as necessary elsewhere.
/opt/moodle/mod/resource/locallib.php
$code = resourcelib_embed_pdf($moodleurl->out(), $title, $clicktoopen);
} else if ($mediamanager->can_embed_url($moodleurl, $embedoptions)) {
// Media (audio/video) file.
$code = $mediamanager->embed_url($moodleurl, $title, 0, 0, $embedoptions);
} else {
// We need a way to discover if we are loading remote docs inside an iframe.
$moodleurl->param('embed', 1);
// anything else - just try object tag enlarged as much as possible
$code = resourcelib_embed_general($moodleurl, $title, $clicktoopen, $mimetype);
}
// Let the module handle the display.
$PAGE->activityheader->set_description(resource_get_intro($resource, $cm));
resource_print_header($resource, $cm, $course);
echo format_text($code, FORMAT_HTML, ['noclean' => true]);
echo $OUTPUT->footer();
die;
}
/**
* Display resource frames.
* @param object $resource
* @param object $cm
* @param object $course
* @param stored_file $file main file
* @return does not return
*/
function resource_display_frame($resource, $cm, $course, $file) {
global $PAGE, $OUTPUT, $CFG;
$frame = optional_param('frameset', 'main', PARAM_ALPHA);
if ($frame === 'top') {
$PAGE->set_pagelayout('frametop');
/opt/moodle/mod/resource/view.php
}
// Don't redirect teachers, otherwise they can not access course or module settings.
if ($redirect && !course_get_format($course)->has_view_page() &&
(has_capability('moodle/course:manageactivities', $context) ||
has_capability('moodle/course:update', context_course::instance($course->id)))) {
$redirect = false;
}
if ($redirect && !$forceview) {
// coming from course page or url index page
// this redirect trick solves caching problems when tracking views ;-)
$path = '/'.$context->id.'/mod_resource/content/'.$resource->revision.$file->get_filepath().$file->get_filename();
$fullurl = moodle_url::make_file_url('/pluginfile.php', $path, $displaytype == RESOURCELIB_DISPLAY_DOWNLOAD);
redirect($fullurl);
}
switch ($displaytype) {
case RESOURCELIB_DISPLAY_EMBED:
resource_display_embed($resource, $cm, $course, $file);
break;
case RESOURCELIB_DISPLAY_FRAME:
resource_display_frame($resource, $cm, $course, $file);
break;
default:
resource_print_workaround($resource, $cm, $course, $file);
break;
}
Environment & details:
Key | Value |
id | 665 |
lang | no |
empty
empty
Key | Value |
MoodleSession | ct4kubq0lf50cr50rpbeqlc5mk |
Key | Value |
USER | stdClass Object ( [id] => 1 [auth] => manual [confirmed] => 1 [policyagreed] => 0 [deleted] => 0 [suspended] => 0 [mnethostid] => 1 [username] => guest [idnumber] => [firstname] => บุคคลทั่วไป [lastname] => [email] => root@localhost [emailstop] => 0 [phone1] => [phone2] => [institution] => [department] => [address] => [city] => [country] => [lang] => th [calendartype] => gregorian [theme] => [timezone] => 99 [firstaccess] => 0 [lastaccess] => 0 [lastlogin] => 0 [currentlogin] => 0 [lastip] => [secret] => [picture] => 0 [descriptionformat] => 1 [mailformat] => 1 [maildigest] => 0 [maildisplay] => 2 [autosubscribe] => 1 [trackforums] => 0 [timecreated] => 0 [timemodified] => 1566869212 [trustbitmask] => 0 [imagealt] => [lastnamephonetic] => [firstnamephonetic] => [middlename] => [alternatename] => [moodlenetprofile] => [lastcourseaccess] => Array ( ) [currentcourseaccess] => Array ( ) [profile] => Array ( ) [sesskey] => Du500GkKb7 [preference] => Array ( ) [autologinguest] => 1 [access] => Array ( [ra] => Array ( [/1] => Array ( [6] => 6 ) [/1/483/1554] => Array ( [6] => 6 ) ) [time] => 1760380332 [rsw] => Array ( ) ) [enrol] => Array ( [enrolled] => Array ( ) [tempguest] => Array ( [1459] => 2147483647 ) ) ) |
SESSION | stdClass Object ( [isnewsessioncookie] => 1 [cachestore_session] => Array ( [default_session-core/courseeditorstate] => Array ( [u1_ct4kubq0lf50cr50rpbeqlc5mk_1459-9c2da51ccf478beee423a2ff95f19327] => Array ( [0] => 1760360671_1760380367 [1] => 0 ) ) [default_session-core/navigation_cache] => Array ( [__lastaccess__u1_ct4kubq0lf50cr50rpbeqlc5mk] => Array ( [0] => 1760380367 [1] => 1760380367 ) ) [default_session-core/coursecat] => Array ( [u1_ct4kubq0lf50cr50rpbeqlc5mk_ddc4bc4754192dc4e0b41497b22ffd5dd660bcf6] => Array ( [0] => 1760380332.4681-68ed45ac724737.32746280 [1] => 1760380332 ) [u1_ct4kubq0lf50cr50rpbeqlc5mk_a432eb3ace283db7eeab490890072df5526386cd] => Array ( [0] => Array ( [0] => 1 [1] => 2 ) [1] => 1760380332 ) [u1_ct4kubq0lf50cr50rpbeqlc5mk_f0ce9beeda1b212e5bdf3402a555b5c93aafce2f] => Array ( [0] => Array ( [0] => 6 [1] => 3 ) [1] => 1760380332 ) [__lastaccess__u1_ct4kubq0lf50cr50rpbeqlc5mk] => Array ( [0] => 1760380367 [1] => 1760380367 ) ) ) [lang] => no [firstview_fakeblocks] => Array ( [672] => 1 ) ) |
Key | Value |
USER | www-data |
HOME | /var/www |
HTTP_HOST | moodle.openlearner.org |
HTTP_ACCEPT_ENCODING | gzip, br, zstd, deflate |
HTTP_COOKIE | MoodleSession=ct4kubq0lf50cr50rpbeqlc5mk |
HTTP_USER_AGENT | Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com) |
HTTP_ACCEPT | */* |
SCRIPT_FILENAME | /opt/moodle/mod/resource/view.php |
PATH_INFO | |
REDIRECT_STATUS | 200 |
SERVER_NAME | moodle.openlearner.org |
SERVER_PORT | 443 |
SERVER_ADDR | 204.48.16.209 |
REMOTE_USER | |
REMOTE_PORT | 13901 |
REMOTE_ADDR | 216.73.216.32 |
SERVER_SOFTWARE | nginx/1.26.3 |
GATEWAY_INTERFACE | CGI/1.1 |
HTTPS | on |
REQUEST_SCHEME | https |
SERVER_PROTOCOL | HTTP/1.1 |
DOCUMENT_ROOT | /opt/moodle |
DOCUMENT_URI | /mod/resource/view.php |
REQUEST_URI | /mod/resource/view.php?id=665&lang=no |
SCRIPT_NAME | /mod/resource/view.php |
CONTENT_LENGTH | |
CONTENT_TYPE | |
REQUEST_METHOD | GET |
QUERY_STRING | id=665&lang=no |
FCGI_ROLE | RESPONDER |
PHP_SELF | /mod/resource/view.php |
REQUEST_TIME_FLOAT | 1760380367.1496 |
REQUEST_TIME | 1760380367 |
empty
0. Whoops\Handler\PrettyPageHandler
1. Whoops\Handler\CallbackHandler