ParseError
Stack frames (24)
23
ParseError
…/mod/coursebooking/classes/shortcodes.php683
22
core\component
classloader
[internal]0
21
is_callable
…/filter/shortcodes/lib/helpers.php44
20
filter_shortcodes_definition_from_data
…/filter/shortcodes/classes/local/registry/plugin_registry.php117
19
filter_shortcodes\local\registry\plugin_registry
fetch_definitions
…/filter/shortcodes/classes/local/registry/plugin_registry.php134
18
filter_shortcodes\local\registry\plugin_registry
init
…/filter/shortcodes/classes/local/registry/plugin_registry.php74
17
filter_shortcodes\local\registry\plugin_registry
get_handler
…/filter/shortcodes/classes/local/processor/standard_processor.php66
16
filter_shortcodes\local\processor\standard_processor
filter_shortcodes\local\processor\{closure}
…/filter/shortcodes/lib/helpers.php230
15
filter_shortcodes_process_text
…/filter/shortcodes/classes/local/processor/standard_processor.php65
14
filter_shortcodes\local\processor\standard_processor
internal_process
…/filter/shortcodes/classes/local/processor/standard_processor.php93
13
filter_shortcodes\local\processor\standard_processor
process
…/filter/shortcodes/classes/text_filter.php78
12
filter_shortcodes\text_filter
filter
…/filter/classes/text_filter.php116
11
core_filters\text_filter
filter_stage_post_clean
…/filter/classes/filter_manager.php185
10
core_filters\filter_manager
apply_filter_chain
…/filter/classes/filter_manager.php231
9
core_filters\filter_manager
filter_text
…/lib/classes/formatting.php277
8
core\formatting
format_text
…/lib/weblib.php617
7
format_text
…/course/renderer.php2030
6
coursecat_helper
get_course_formatted_summary
…/theme/space/classes/util/course.php134
5
theme_space\util\course
get_summary
…/theme/space/classes/output/core/course_renderer.php374
4
theme_space\output\core\course_renderer
coursecat_coursebox_content
…/theme/space/classes/output/core/course_renderer.php424
3
theme_space\output\core\course_renderer
coursecat_coursebox
…/theme/space/classes/output/core/course_renderer.php202
2
theme_space\output\core\course_renderer
coursecat_courses
…/course/renderer.php1444
1
core_course_renderer
frontpage_available_courses
…/course/renderer.php1723
0
core_course_renderer
frontpage
…/index.php141
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/mod/coursebooking/classes/shortcodes.php
}
if ($data['hasteachers']) {
$html .= '<p class="text-muted"><i class="fa fa-user"></i> ' . $data['teachers'] . '</p>';
}
if ($data['hasdates']) {
$html .= '<p class="text-muted"><i class="fa fa-calendar"></i> ' . $data['dates'] . '</p>';
}
if ($data['haslocation']) {
$html .= '<p class="text-muted"><i class="fa fa-map-marker"></i> ' . s($data['location']) . '</p>';
}
if ($data['hasprice']) {
$html .= '<p class="font-weight-bold">' . $data['price'] . '</p>';
}
$html .= '<div class="mt-2">' . $data['bookitbutton'] . '</div>';
$html .= '</div></div>';
return $html;
}
More info
https://docs.moodle.org/405/da/error/moodle/generalexceptionmessage
[internal]
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/filter/shortcodes/lib/helpers.php
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Create a definition from data.
*
* This defines what a definition looks like, and what keys are expected to be given as argument.
*
* @param string $shortcode The shortcode.
* @param array $data The data.
* @return object
*/
function filter_shortcodes_definition_from_data($shortcode, array $data) {
global $CFG;
if ($CFG->debugdeveloper) {
validate_param($shortcode, PARAM_ALPHANUM);
if (!isset($data['callback']) || !is_callable($data['callback'])) {
throw new coding_exception("The callback for shortcode '{$shortcode}' is invalid.");
}
if (!isset($data['component'])) {
throw new coding_exception("A shortcode must belong to a component.");
}
if (isset($data['description'])) {
$stringman = get_string_manager();
if (!$stringman->string_exists($data['description'], $data['component'])) {
debugging("The definition string for shortcode '{$shortcode}' is invalid.", DEBUG_DEVELOPER);
$data['description'] = null;
}
}
}
return (object) [
'shortcode' => $shortcode,
'callback' => $data['callback'],
'component' => $data['component'],
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/filter/shortcodes/classes/local/registry/plugin_registry.php
$component = $plugintype . '_' . $name;
$info = $pluginman->get_plugin_info($component);
// Skip unfound or disabled plugins. Note that the plugin manager can return null when
// the status is unknown. In that case we keep the plugin (e.g. local plugins).
if (!$info || $info->is_enabled() === false) {
continue;
}
// Is the file there? I wish we could use core_component::get_plugin_list_with_file().
// But we cannot because only a few files are mapped, and ours isn't.
$file = $rootdir . '/db/shortcodes.php';
if (!file_exists($file)) {
continue;
}
$shortcodes = $saferead($file);
foreach ($shortcodes as $shortcode => $data) {
$data['component'] = $component;
$definitions[] = filter_shortcodes_definition_from_data($shortcode, $data);
}
}
}
return $definitions;
}
/**
* Load the things if need be.
*
* @return void
*/
protected function init() {
if ($this->registry === null) {
$definitions = $this->cache->get('definitions');
if ($definitions === false) {
$definitions = $this->fetch_definitions();
$this->cache->set('definitions', $definitions);
}
$this->registry = new static_registry($definitions);
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/filter/shortcodes/classes/local/registry/plugin_registry.php
foreach ($shortcodes as $shortcode => $data) {
$data['component'] = $component;
$definitions[] = filter_shortcodes_definition_from_data($shortcode, $data);
}
}
}
return $definitions;
}
/**
* Load the things if need be.
*
* @return void
*/
protected function init() {
if ($this->registry === null) {
$definitions = $this->cache->get('definitions');
if ($definitions === false) {
$definitions = $this->fetch_definitions();
$this->cache->set('definitions', $definitions);
}
$this->registry = new static_registry($definitions);
}
}
}
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/filter/shortcodes/classes/local/registry/plugin_registry.php
}
/**
* Get the definitions.
*
* @return \Iterator
*/
public function get_definitions() {
$this->init();
return $this->registry->get_definitions();
}
/**
* Get a handler.
*
* @param string $shortcode The shortcode.
* @return object|null
*/
public function get_handler($shortcode) {
$this->init();
return $this->registry->get_handler($shortcode);
}
/**
* Fetch all the definitions.
*
* @return array
*/
protected function fetch_definitions() {
$saferead = function ($file) {
$shortcodes = [];
include($file);
return $shortcodes;
};
$pluginman = \core_plugin_manager::instance();
$stringman = get_string_manager();
$definitions = [];
$types = core_component::get_plugin_types();
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/filter/shortcodes/classes/local/processor/standard_processor.php
/**
* Constructor
*
* @param registry $registry The registry.
*/
public function __construct(registry $registry) {
$this->registry = $registry;
}
/**
* Internal processing.
*
* @param string $text The text.
* @param Closure $next The function to pipe the resulting content through, if needed.
* @return string
*/
protected function internal_process($text, $next) {
return filter_shortcodes_process_text($text, function ($shortcode) use ($next) {
$handler = $this->registry->get_handler($shortcode);
if (!$handler) {
return;
}
$processor = $handler->processor;
return (object) [
'hascontent' => $handler->wraps,
'contentprocessor' => function ($args, $content) use ($processor, $shortcode, $next) {
// We decorate the handler method to pass through the other needed arguments.
return $processor($shortcode, $args, $content, $this->env, $next);
},
];
});
}
/**
* The filtering occurs here.
*
* @param string $text The content to process.
* @return string The resulting text.
*/
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/filter/shortcodes/lib/helpers.php
return $text;
}
$start = $firstfind;
$end = $end === null ? core_text::strlen($text) : $end;
$pos = $firstfind + 1;
// Find out what the tag is.
$tag = '';
do {
$char = core_text::substr($text, $pos, 1);
if (!preg_match($charregex, $char)) {
break;
}
$tag .= $char;
$pos++;
} while ($pos < $end);
// We have a tag and can we handle it?
if ($tag && is_object($info = $informant($tag))) {
if ($lastcloseself < $pos) {
// The tag does not have an end.
continue;
}
$tagclosed = false;
$attrs = '';
$inquote = false;
do {
$char = core_text::substr($text, $pos, 1);
// Detect when we are in quotes, in order to avoid closing the tag too early.
if ($char == '"') {
if ($inquote) {
$inquote = core_text::substr($text, $pos - 1, 1) !== '\\' ? false : true;
} else {
$inquote = true;
}
}
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/filter/shortcodes/classes/local/processor/standard_processor.php
protected $registry;
/**
* Constructor
*
* @param registry $registry The registry.
*/
public function __construct(registry $registry) {
$this->registry = $registry;
}
/**
* Internal processing.
*
* @param string $text The text.
* @param Closure $next The function to pipe the resulting content through, if needed.
* @return string
*/
protected function internal_process($text, $next) {
return filter_shortcodes_process_text($text, function ($shortcode) use ($next) {
$handler = $this->registry->get_handler($shortcode);
if (!$handler) {
return;
}
$processor = $handler->processor;
return (object) [
'hascontent' => $handler->wraps,
'contentprocessor' => function ($args, $content) use ($processor, $shortcode, $next) {
// We decorate the handler method to pass through the other needed arguments.
return $processor($shortcode, $args, $content, $this->env, $next);
},
];
});
}
/**
* The filtering occurs here.
*
* @param string $text The content to process.
* @return string The resulting text.
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/filter/shortcodes/classes/local/processor/standard_processor.php
// We decorate the handler method to pass through the other needed arguments.
return $processor($shortcode, $args, $content, $this->env, $next);
},
];
});
}
/**
* The filtering occurs here.
*
* @param string $text The content to process.
* @return string The resulting text.
*/
public function process($text) {
if ($this->env === null) {
throw new \coding_exception('The environment must be set between process calls.');
}
$env = $this->env;
$result = $this->internal_process($text, function ($text) use ($env) {
$result = $this->process($text);
$this->set_env($env);
return $result;
});
$this->env = null;
return $result;
}
/**
* Set the environment.
*
* @param stdClass $env The environment, must conform to filter_shortcodes_make_env.
*/
public function set_env(stdClass $env) {
$this->env = $env;
}
}
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/filter/shortcodes/classes/text_filter.php
* @copyright 2024 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class text_filter extends core_text_filter {
/** @var processor The processor. */
private $processor;
/**
* The filtering occurs here.
*
* @param string $text HTML content.
* @param array $options Options passed to the filter.
* @return string The new content.
*/
public function filter($text, array $options = []) {
$env = filter_shortcodes_make_env($this->context, $options);
$processor = $this->get_processor();
$processor->set_env($env);
return $processor->process($text);
}
/**
* Get the processor.
*
* @return standard_processor
*/
private function get_processor() {
if ($this->processor === null) {
$this->processor = new standard_processor(new plugin_registry());
}
return $this->processor;
}
}
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/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.
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/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.
*
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/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.
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/lib/classes/formatting.php
'allowid' => $allowid,
]);
}
$filteroptions['stage'] = 'post_clean';
$text = $filtermanager->filter_text($text, $context, $filteroptions);
break;
case FORMAT_MOODLE:
$filteroptions['stage'] = 'pre_format';
$text = $filtermanager->filter_text($text, $context, $filteroptions);
$text = text_to_html($text, null, $para, $newlines);
$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;
default: // FORMAT_MOODLE or anything else.
throw new \coding_exception("Unknown format passed to format_text: {$format}");
}
if ($filter) {
// At this point there should not be any draftfile links any more,
// this happens when developers forget to post process the text.
// The only potential problem is that somebody might try to format
// the text before storing into database which would be itself big bug.
$text = str_replace("\"$CFG->wwwroot/draftfile.php", "\"$CFG->wwwroot/brokenfile.php#", $text);
if ($CFG->debugdeveloper) {
if (strpos($text, '@@PLUGINFILE@@/') !== false) {
debugging(
'Before calling format_text(), the content must be processed with file_rewrite_pluginfile_urls()',
DEBUG_DEVELOPER
);
}
}
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/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.
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/course/renderer.php
/**
* Returns given course's summary with proper embedded files urls and formatted
*
* @param core_course_list_element $course
* @param array|stdClass $options additional formatting options
* @return string
*/
public function get_course_formatted_summary($course, $options = array()) {
global $CFG;
require_once($CFG->libdir. '/filelib.php');
if (!$course->has_summary()) {
return '';
}
$options = (array)$options;
$context = context_course::instance($course->id);
if (!isset($options['context'])) {
$options['context'] = $context;
}
$summary = file_rewrite_pluginfile_urls($course->summary, 'pluginfile.php', $context->id, 'course', 'summary', null);
$summary = format_text($summary, $course->summaryformat, $options);
if (!empty($this->searchcriteria['search'])) {
$summary = highlight($this->searchcriteria['search'], $summary);
}
return $summary;
}
/**
* Returns course name as it is configured to appear in courses lists formatted to course context
*
* @param core_course_list_element $course
* @param array|stdClass $options additional formatting options
* @return string
*/
public function get_course_formatted_name($course, $options = array()) {
$options = (array)$options;
if (!isset($options['context'])) {
$options['context'] = context_course::instance($course->id);
}
$name = format_string(get_course_display_name_for_list($course), true, $options);
if (!empty($this->searchcriteria['search'])) {
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/theme/space/classes/util/course.php
* @throws \moodle_exception
*/
public function get_category(): string {
$cat = core_course_category::get($this->course->category, IGNORE_MISSING);
if (!$cat) {
return '';
}
return $cat->get_formatted_name();
}
/**
* Returns course summary.
*
* @param coursecat_helper $chelper
*/
public function get_summary(coursecat_helper $chelper): string {
if ($this->course->has_summary()) {
return $chelper->get_course_formatted_summary(
$this->course,
['overflowdiv' => true, 'noclean' => true, 'para' => false]
);
}
return false;
}
/**
* Returns course custom fields.
*
* @return string
*/
public function get_custom_fields(): string {
if ($this->course->has_custom_fields()) {
$handler = \core_course\customfield\course_handler::create();
return $handler->display_custom_fields_data($this->course->get_custom_fields());
}
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/theme/space/classes/output/core/course_renderer.php
if ($courseprogressbar == 1 && $hasprogress == true) {
$cccfooter = false;
}
$forcedlanguage = ($theme->settings->courselangbadge == 1) ? strval($course->lang) : null;
$showcustomfields = ($theme->settings->showcustomfields == 1) ? true : false;
$stringaccess = format_text(theme_space_get_setting('stringaccess'), FORMAT_HTML, ['noclean' => true]);
$courseimage = $courseutil->get_summary_image(false);
if (empty($courseimage)) {
$courseimage = $this->get_theme_core_renderer()->get_generated_image_for_id($course->id);
}
$data = [
'id' => $course->id,
'fullname' => $chelper->get_course_formatted_name($course),
'visible' => $course->visible,
'image' => $courseimage,
'summary' => $courseutil->get_summary($chelper),
'category' => $courseutil->get_category(),
'customfields' => $courseutil->get_custom_fields(),
'showcustomfields' => $showcustomfields,
'hasprogress' => $hasprogress,
'progress' => (int) $courseprogress,
'hasenrolmenticons' => $courseenrolmenticons != false,
'enrolmenticons' => $courseenrolmenticons,
'hascontacts' => !empty($coursecontacts),
'contacts' => $coursecontacts,
'stringaccess' => $stringaccess,
'cccteachers' => $cccteachers,
'cccfooter' => $cccfooter,
'cccsummary' => $cccsummary,
'coursecarddesclimit' => $coursecarddesclimit,
'forcedlanguage' => $forcedlanguage,
];
if ($theme->settings->courselistview == 1) {
return $this->render_from_template('theme_space/custom_courselist', $data);
} else {
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/theme/space/classes/output/core/course_renderer.php
* @param coursecat_helper $chelper various display options
* @param core_course_list_element|stdClass $course
* @param string $additionalclasses additional classes to add to the main <div> tag (usually
* depend on the course position in list - first/last/even/odd)
* @return string
*/
protected function coursecat_coursebox(coursecat_helper $chelper, $course, $additionalclasses = '') {
if (!isset($this->strings->summary)) {
$this->strings->summary = get_string('summary');
}
if ($chelper->get_show_courses() <= self::COURSECAT_SHOW_COURSES_COUNT) {
return '';
}
if ($course instanceof stdClass) {
$course = new core_course_list_element($course);
}
return $this->coursecat_coursebox_content($chelper, $course);
}
/**
* Returns HTML to display a tree of subcategories and courses in the given category
*
* @param coursecat_helper $chelper various display options
* @param core_course_category $coursecat top category (this category's name and description will NOT be added to the tree)
* @return string
*/
protected function coursecat_tree(coursecat_helper $chelper, $coursecat) {
// Reset the category expanded flag for this course category tree first.
$this->categoryexpandedonload = false;
$categorycontent = $this->coursecat_category_content($chelper, $coursecat, 1);
if (empty($categorycontent)) {
return '';
}
// Start content generation.
$content = '';
$attributes = $chelper->get_and_erase_attributes('course_category_tree clearfix');
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/theme/space/classes/output/core/course_renderer.php
}
// Display list of courses.
$attributes = $chelper->get_and_erase_attributes('courses');
$content = html_writer::start_tag('div', $attributes);
if (!empty($pagingbar)) {
$content .= $pagingbar;
}
$coursecount = 1;
if ($theme->settings->courselistview == 1) {
$content .= html_writer::start_tag('div', ['class' => 'rui-course--list mt-2']);
} else {
$content .= html_writer::start_tag('div', ['class' => 'rui-course-card-deck mt-2', 'role' => 'list']);
}
foreach ($courses as $course) {
$content .= $this->coursecat_coursebox($chelper, $course);
$coursecount++;
}
$content .= html_writer::end_tag('div');
if (!empty($pagingbar)) {
$content .= $pagingbar;
}
if (!empty($morelink)) {
$content .= $morelink;
}
$content .= html_writer::end_tag('div'); // End courses.
return $content;
}
/**
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/course/renderer.php
*/
public function frontpage_available_courses() {
global $CFG;
$chelper = new coursecat_helper();
$chelper->set_show_courses(self::COURSECAT_SHOW_COURSES_EXPANDED)->
set_courses_display_options(array(
'recursive' => true,
'limit' => $CFG->frontpagecourselimit,
'viewmoreurl' => new moodle_url('/course/index.php'),
'viewmoretext' => new lang_string('fulllistofcourses')));
$chelper->set_attributes(array('class' => 'frontpage-course-list-all'));
$courses = core_course_category::top()->get_courses($chelper->get_courses_display_options());
$totalcount = core_course_category::top()->get_courses_count($chelper->get_courses_display_options());
if (!$totalcount && !$this->page->user_is_editing() && has_capability('moodle/course:create', context_system::instance())) {
// Print link to create a new course, for the 1st available category.
return $this->add_new_course_button();
}
return $this->coursecat_courses($chelper, $courses, $totalcount);
}
/**
* Returns HTML to the "add new course" button for the page
*
* @return string
*/
public function add_new_course_button() {
global $CFG;
// Print link to create a new course, for the 1st available category.
$output = $this->container_start('buttons');
$url = new moodle_url('/course/edit.php', array('category' => $CFG->defaultrequestcategory, 'returnto' => 'topcat'));
$output .= $this->single_button($url, get_string('addnewcourse'), 'get');
$output .= $this->container_end('buttons');
return $output;
}
/**
* Returns HTML to print tree with course categories and courses for the frontpage
*
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/course/renderer.php
require_once($CFG->dirroot .'/mod/forum/lib.php');
if (($newsforum = forum_get_course_forum($SITE->id, 'news')) &&
($forumcontents = $this->frontpage_news($newsforum))) {
$newsforumcm = get_fast_modinfo($SITE)->instances['forum'][$newsforum->id];
$output .= $this->frontpage_part('skipsitenews', 'site-news-forum',
$newsforumcm->get_formatted_name(), $forumcontents);
}
}
break;
case FRONTPAGEENROLLEDCOURSELIST:
$mycourseshtml = $this->frontpage_my_courses();
if (!empty($mycourseshtml)) {
$output .= $this->frontpage_part('skipmycourses', 'frontpage-course-list',
get_string('mycourses'), $mycourseshtml);
}
break;
case FRONTPAGEALLCOURSELIST:
$availablecourseshtml = $this->frontpage_available_courses();
$output .= $this->frontpage_part('skipavailablecourses', 'frontpage-available-course-list',
get_string('availablecourses'), $availablecourseshtml);
break;
case FRONTPAGECATEGORYNAMES:
$output .= $this->frontpage_part('skipcategories', 'frontpage-category-names',
get_string('categories'), $this->frontpage_categories_list());
break;
case FRONTPAGECATEGORYCOMBO:
$output .= $this->frontpage_part('skipcourses', 'frontpage-category-combo',
get_string('courses'), $this->frontpage_combo_list());
break;
case FRONTPAGECOURSESEARCH:
$output .= $this->box($this->course_search_form(''), 'd-flex justify-content-center');
break;
}
$output .= '<br />';
/home/opkvalificer-45x/htdocs/45x.opkvalificer.com/index.php
$siteformatoptions = course_get_format($SITE)->get_format_options();
$modinfo = get_fast_modinfo($SITE);
$modnamesused = $modinfo->get_used_module_names();
// Print Section or custom info.
if (!empty($CFG->customfrontpageinclude)) {
// Pre-fill some variables that custom front page might use.
$modnames = get_module_types_names();
$modnamesplural = get_module_types_names(true);
$mods = $modinfo->get_cms();
include($CFG->customfrontpageinclude);
} else if ($siteformatoptions['numsections'] > 0) {
echo $courserenderer->frontpage_section1();
}
// Include course AJAX.
include_course_ajax($SITE, $modnamesused);
echo $courserenderer->frontpage();
if ($editing && has_capability('moodle/course:create', context_system::instance())) {
echo $courserenderer->add_new_course_button();
}
echo $OUTPUT->footer();
Environment & details:
empty
empty
empty
empty
| Key | Value |
| USER | stdClass Object ( [id] => 1 [auth] => manual [confirmed] => 1 [policyagreed] => 0 [deleted] => 0 [suspended] => 0 [mnethostid] => 1 [username] => guest [idnumber] => [firstname] => Gæst [lastname] => [email] => root@localhost [emailstop] => 0 [phone1] => [phone2] => [institution] => [department] => [address] => [city] => [country] => [lang] => da [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] => 1772482531 [trustbitmask] => 0 [imagealt] => [lastnamephonetic] => [firstnamephonetic] => [middlename] => [alternatename] => [moodlenetprofile] => [lastcourseaccess] => Array ( ) [currentcourseaccess] => Array ( ) [profile] => Array ( ) [sesskey] => OWWHG0iKBp [preference] => Array ( ) [autologinguest] => 1 [access] => Array ( [ra] => Array ( [/1] => Array ( [6] => 6 ) ) [time] => 1779918175 [rsw] => Array ( ) ) [enrol] => Array ( [enrolled] => Array ( ) [tempguest] => Array ( ) ) ) |
| SESSION | stdClass Object ( [isnewsessioncookie] => 1 [justloggedin] => 1 [lang] => da [cachestore_session] => Array ( [default_session-core/navigation_cache] => Array ( [__lastaccess__u1_t8p9bopjc70is318n8rtaab7p9] => Array ( [0] => 1779918175 [1] => 1779918175 ) ) [default_session-core/coursecat] => Array ( [__lastaccess__u1_t8p9bopjc70is318n8rtaab7p9] => Array ( [0] => 1779918175 [1] => 1779918175 ) [u1_t8p9bopjc70is318n8rtaab7p9_a1eb530ebc7014678e691708db825df552bac9ab] => Array ( [0] => 1779918175.455-6a17655f6f16a6.78205774 [1] => 1779918175 ) [u1_t8p9bopjc70is318n8rtaab7p9_a777ccc9041fa05bb5b5d610ddc841149c79b99c] => Array ( [0] => Array ( ) [1] => 1779918175 ) [u1_t8p9bopjc70is318n8rtaab7p9_9c7c3e6b6bed05961590ec77cfc3f6ccb0c064e7] => Array ( [0] => Array ( [0] => 1 ) [1] => 1779918175 ) [u1_t8p9bopjc70is318n8rtaab7p9_9c17c33e3835b67b886d2ceb655d206203b300d6] => Array ( [0] => Array ( [0] => 5 [1] => 4 [2] => 3 [3] => 2 ) [1] => 1779918175 ) [u1_t8p9bopjc70is318n8rtaab7p9_1851c710a42f394720e9f49e5418a70e4b954de3] => Array ( [0] => 4 [1] => 1779918175 ) ) ) ) |
| Key | Value |
| USER | opkvalificer-45x |
| HOME | /home/opkvalificer-45x |
| HTTP_ACCEPT_ENCODING | gzip, br, zstd, deflate |
| HTTP_USER_AGENT | Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com) |
| HTTP_ACCEPT | */* |
| HTTP_CONNECTION | close |
| HTTP_X_FORWARDED_PROTO | https |
| HTTP_X_FORWARDED_FOR | 216.73.216.7 |
| HTTP_X_REAL_IP | 216.73.216.7 |
| HTTP_X_FORWARDED_HOST | 45x.opkvalificer.com |
| HTTP_HOST | 45x.opkvalificer.com |
| PHP_VALUE | error_log=/home/opkvalificer-45x/logs/php/error.log; memory_limit=2G; max_execution_time=3600; max_input_time=3600; max_input_vars=10000; post_max_size=1G; upload_max_filesize=5G; date.timezone=UTC; display_errors=off; |
| HTTPS | on |
| PATH_TRANSLATED | /home/opkvalificer-45x/htdocs/45x.opkvalificer.com |
| PATH_INFO | |
| MGT | 1 |
| GEOIP_LONGITUDE | -119.1091 |
| GEOIP_LATITUDE | 34.1453 |
| GEOIP_CITY_CONTINENT_CODE | NA |
| GEOIP_POSTAL_CODE | 93033 |
| GEOIP_CITY | Oxnard |
| GEOIP_REGION | CA |
| GEOIP_CITY_COUNTRY_NAME | United States |
| GEOIP_CITY_COUNTRY_CODE3 | USA |
| GEOIP_CITY_COUNTRY_CODE | US |
| GEOIP_COUNTRY_NAME | United States |
| GEOIP_COUNTRY_CODE3 | USA |
| GEOIP_COUNTRY_CODE | US |
| REDIRECT_STATUS | 200 |
| SERVER_NAME | 45x.opkvalificer.com |
| SERVER_PORT | 443 |
| SERVER_ADDR | 127.0.0.1 |
| REMOTE_PORT | |
| REMOTE_ADDR | 216.73.216.7 |
| SERVER_SOFTWARE | nginx/1.21.4 |
| GATEWAY_INTERFACE | CGI/1.1 |
| SERVER_PROTOCOL | HTTP/1.0 |
| DOCUMENT_ROOT | /home/opkvalificer-45x/htdocs/45x.opkvalificer.com |
| DOCUMENT_URI | /index.php |
| REQUEST_URI | /sitemap.xml |
| SCRIPT_NAME | /index.php |
| SCRIPT_FILENAME | /home/opkvalificer-45x/htdocs/45x.opkvalificer.com/index.php |
| CONTENT_LENGTH | |
| CONTENT_TYPE | |
| REQUEST_METHOD | GET |
| QUERY_STRING | |
| FCGI_ROLE | RESPONDER |
| PHP_SELF | /index.php |
| REQUEST_TIME_FLOAT | 1779918175.4165 |
| REQUEST_TIME | 1779918175 |
empty
0. Whoops\Handler\PrettyPageHandler
1. Whoops\Handler\CallbackHandler