Learning catalogue

Whoops! There was an error.
Whoops \ Exception \ ErrorException (E_WARNING)
mkdir(): File exists Whoops\Exception\ErrorException thrown with message "mkdir(): File exists" Stacktrace: #14 Whoops\Exception\ErrorException in /var/www/html/public/lib/filestorage/file_system_filedir.php:97 #13 mkdir in /var/www/html/public/lib/filestorage/file_system_filedir.php:97 #12 file_system_filedir:__construct in /var/www/html/public/lib/filestorage/file_storage.php:81 #11 file_storage:setup_file_system in /var/www/html/public/lib/filestorage/file_storage.php:62 #10 file_storage:__construct in /var/www/html/public/lib/moodlelib.php:6381 #9 get_file_storage in /var/www/html/public/local/lernhive/classes/dashboard/course_catalog_provider.php:1365 #8 local_lernhive\dashboard\course_catalog_provider:course_image_url in /var/www/html/public/local/lernhive/classes/dashboard/course_catalog_provider.php:1128 #7 local_lernhive\dashboard\course_catalog_provider:course_to_offering in /var/www/html/public/local/lernhive/classes/dashboard/course_catalog_provider.php:165 #6 local_lernhive\dashboard\course_catalog_provider:get_offering_window in /var/www/html/public/local/lernhive/classes/hook_callbacks.php:235 #5 local_lernhive\hook_callbacks:contribute_course_catalog_offerings in /var/www/html/public/lib/classes/hook/manager.php:323 #4 call_user_func in /var/www/html/public/lib/classes/hook/manager.php:323 #3 core\hook\manager:dispatch in /var/www/html/public/local/lernhive/classes/dashboard/catalog_registry.php:97 #2 local_lernhive\dashboard\catalog_registry:collect in /var/www/html/public/local/lernhive/classes/dashboard/catalog_registry.php:74 #1 local_lernhive\dashboard\catalog_registry:collect_page in /var/www/html/public/local/lernhive/classes/output/catalog_page.php:144 #0 local_lernhive\output\catalog_page:export_for_template in /var/www/html/public/local/lernhive/catalog.php:144
Stack frames (15)
14
Whoops\Exception\ErrorException
…/public/lib/filestorage/file_system_filedir.php:97
13
mkdir
…/public/lib/filestorage/file_system_filedir.php:97
12
file_system_filedir __construct
…/public/lib/filestorage/file_storage.php:81
11
file_storage setup_file_system
…/public/lib/filestorage/file_storage.php:62
10
file_storage __construct
…/public/lib/moodlelib.php:6381
9
get_file_storage
…/public/local/lernhive/classes/dashboard/course_catalog_provider.php:1365
8
local_lernhive\dashboard\course_catalog_provider course_image_url
…/public/local/lernhive/classes/dashboard/course_catalog_provider.php:1128
7
local_lernhive\dashboard\course_catalog_provider course_to_offering
…/public/local/lernhive/classes/dashboard/course_catalog_provider.php:165
6
local_lernhive\dashboard\course_catalog_provider get_offering_window
…/public/local/lernhive/classes/hook_callbacks.php:235
5
local_lernhive\hook_callbacks contribute_course_catalog_offerings
…/public/lib/classes/hook/manager.php:323
4
call_user_func
…/public/lib/classes/hook/manager.php:323
3
core\hook\manager dispatch
…/public/local/lernhive/classes/dashboard/catalog_registry.php:97
2
local_lernhive\dashboard\catalog_registry collect
…/public/local/lernhive/classes/dashboard/catalog_registry.php:74
1
local_lernhive\dashboard\catalog_registry collect_page
…/public/local/lernhive/classes/output/catalog_page.php:144
0
local_lernhive\output\catalog_page export_for_template
…/public/local/lernhive/catalog.php:144
/var/www/html/public/lib/filestorage/file_system_filedir.php
 
        // Make sure the file pool directory exists.
        if (!is_dir($this->filedir)) {
            if (!mkdir($this->filedir, $this->dirpermissions, true)) {
                // Permission trouble.
                throw new file_exception('storedfilecannotcreatefiledirs');
            }
 
            // Place warning file in file pool root.
            if (!file_exists($this->filedir.'/warning.txt')) {
                file_put_contents($this->filedir.'/warning.txt',
                        'This directory contains the content of uploaded files and is controlled by Moodle code. ' .
                        'Do not manually move, change or rename any of the files and subdirectories here.');
                chmod($this->filedir . '/warning.txt', $this->filepermissions);
            }
        }
 
        // Make sure the trashdir directory exists too.
        if (!is_dir($this->trashdir)) {
            if (!mkdir($this->trashdir, $this->dirpermissions, true)) {
                // Permission trouble.
                throw new file_exception('storedfilecannotcreatefiledirs');
            }
        }
    }
 
    /**
     * Get the full path for the specified hash, including the path to the filedir.
     *
     * @param string $contenthash The content hash
     * @param bool $fetchifnotfound Whether to attempt to fetch from the remote path if not found.
     * @return string The full path to the content file
     */
    protected function get_local_path_from_hash($contenthash, $fetchifnotfound = false) {
        return $this->get_fulldir_from_hash($contenthash) . '/' .$contenthash;
    }
 
    /**
     * Get a remote filepath for the specified stored file.
     *
/var/www/html/public/lib/filestorage/file_system_filedir.php
 
        // Make sure the file pool directory exists.
        if (!is_dir($this->filedir)) {
            if (!mkdir($this->filedir, $this->dirpermissions, true)) {
                // Permission trouble.
                throw new file_exception('storedfilecannotcreatefiledirs');
            }
 
            // Place warning file in file pool root.
            if (!file_exists($this->filedir.'/warning.txt')) {
                file_put_contents($this->filedir.'/warning.txt',
                        'This directory contains the content of uploaded files and is controlled by Moodle code. ' .
                        'Do not manually move, change or rename any of the files and subdirectories here.');
                chmod($this->filedir . '/warning.txt', $this->filepermissions);
            }
        }
 
        // Make sure the trashdir directory exists too.
        if (!is_dir($this->trashdir)) {
            if (!mkdir($this->trashdir, $this->dirpermissions, true)) {
                // Permission trouble.
                throw new file_exception('storedfilecannotcreatefiledirs');
            }
        }
    }
 
    /**
     * Get the full path for the specified hash, including the path to the filedir.
     *
     * @param string $contenthash The content hash
     * @param bool $fetchifnotfound Whether to attempt to fetch from the remote path if not found.
     * @return string The full path to the content file
     */
    protected function get_local_path_from_hash($contenthash, $fetchifnotfound = false) {
        return $this->get_fulldir_from_hash($contenthash) . '/' .$contenthash;
    }
 
    /**
     * Get a remote filepath for the specified stored file.
     *
/var/www/html/public/lib/filestorage/file_storage.php
        $this->setup_file_system();
    }
 
    /**
     * Complete setup procedure for the file_system component.
     *
     * @return file_system
     */
    public function setup_file_system() {
        global $CFG;
        if ($this->filesystem === null) {
            require_once($CFG->libdir . '/filestorage/file_system.php');
            if (!empty($CFG->alternative_file_system_class)) {
                $class = $CFG->alternative_file_system_class;
            } else {
                // The default file_system is the filedir.
                require_once($CFG->libdir . '/filestorage/file_system_filedir.php');
                $class = file_system_filedir::class;
            }
            $this->filesystem = new $class();
        }
 
        return $this->filesystem;
    }
 
    /**
     * Return the file system instance.
     *
     * @return file_system
     */
    public function get_file_system() {
        return $this->filesystem;
    }
 
    /**
     * Calculates sha1 hash of unique full path name information.
     *
     * This hash is a unique file identifier - it is used to improve
     * performance and overcome db index size limits.
     *
/var/www/html/public/lib/filestorage/file_storage.php
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 * @since     Moodle 2.0
 */
class file_storage {
 
    /** @var string tempdir */
    private $tempdir;
 
    /** @var file_system filesystem */
    private $filesystem;
 
    /**
     * Constructor - do not use directly use {@link get_file_storage()} call instead.
     */
    public function __construct() {
        // The tempdir must always remain on disk, but shared between all ndoes in a cluster. Its content is not subject
        // to the file_system abstraction.
        $this->tempdir = make_temp_directory('filestorage');
 
        $this->setup_file_system();
    }
 
    /**
     * Complete setup procedure for the file_system component.
     *
     * @return file_system
     */
    public function setup_file_system() {
        global $CFG;
        if ($this->filesystem === null) {
            require_once($CFG->libdir . '/filestorage/file_system.php');
            if (!empty($CFG->alternative_file_system_class)) {
                $class = $CFG->alternative_file_system_class;
            } else {
                // The default file_system is the filedir.
                require_once($CFG->libdir . '/filestorage/file_system_filedir.php');
                $class = file_system_filedir::class;
            }
            $this->filesystem = new $class();
        }
/var/www/html/public/lib/moodlelib.php
 *
 * @return ?file_storage
 */
function get_file_storage($reset = false) {
    global $CFG;
 
    static $fs = null;
 
    if ($reset) {
        $fs = null;
        return;
    }
 
    if ($fs) {
        return $fs;
    }
 
    require_once("$CFG->libdir/filelib.php");
 
    $fs = new file_storage();
 
    return $fs;
}
 
/**
 * Returns local file storage instance
 *
 * @return file_browser
 */
function get_file_browser() {
    global $CFG;
 
    static $fb = null;
 
    if ($fb) {
        return $fb;
    }
 
    require_once("$CFG->libdir/filelib.php");
 
/var/www/html/public/local/lernhive/classes/dashboard/course_catalog_provider.php
     * @return string|null
     */
    private static function course_image_url(
        \stdClass $course,
        \context_course $context,
        string $categorypath = ''
    ): ?string {
        // 1. Explicit per-course "Catalogue image" pick wins when set — but only
        // when its asset actually exists, so a stale slug (e.g. a default that
        // ships no image yet) does not shadow the real course image below.
        $override = course_image_library::override_for_course((int) $course->id);
        if ($override !== null) {
            $overrideurl = course_image_library::image_file_url($override);
            if ($overrideurl !== null) {
                return $overrideurl->out(false);
            }
        }
 
        // 2. The course's own image (course settings → Course image).
        $fs = get_file_storage();
        $files = $fs->get_area_files(
            $context->id,
            'course',
            'overviewfiles',
            0,
            'sortorder,filename',
            false
        );
        foreach ($files as $file) {
            if (strpos((string) $file->get_mimetype(), 'image/') !== 0) {
                continue;
            }
 
            // Course overviewfiles are stored with itemid 0 but MUST be served
            // with a null itemid (matching core's course_image cache builder) —
            // a literal /0/ segment in the pluginfile URL fails to resolve.
            return \moodle_url::make_pluginfile_url(
                $file->get_contextid(),
                $file->get_component(),
                $file->get_filearea(),
/var/www/html/public/local/lernhive/classes/dashboard/course_catalog_provider.php
                $capacitystatus = offering_data::CAPACITY_ENROLLED;
                $capacitylabel = get_string('catalog_provider_course_inprogress', 'local_lernhive');
                $capacityfill = $percent;
            } else {
                $capacitystatus = offering_data::CAPACITY_ENROLLED;
                $capacitylabel = get_string('catalog_provider_course_enrolled', 'local_lernhive');
                $capacityfill = 0;
            }
        } else {
            $capacitystatus = offering_data::CAPACITY_OK;
            $capacitylabel = get_string('catalog_provider_course_available', 'local_lernhive');
            $capacityfill = 100;
        }
 
        return new offering_data(
            id: 'course-' . (int) $course->id,
            sourcecomponent: 'local_lernhive',
            title: $title,
            summary: self::card_summary($course, $offermetadata),
            imageurl: self::course_image_url($course, $context, $categorypath),
            metalines: [],
            badges: self::badges($course, $categorypath, $markings),
            ctaurl: $url,
            ctalabel: $requiresapproval
                ? get_string('catalog_provider_course_request', 'local_lernhive')
                : get_string('catalog_provider_course_cta', 'local_lernhive'),
            categorypath: $categorypath,
            startat: !empty($course->startdate) ? (int) $course->startdate : null,
            timecreated: !empty($course->timecreated) ? (int) $course->timecreated : null,
            availability: $requiresapproval
                ? offering_data::AVAILABILITY_ON_REQUEST
                : offering_data::AVAILABILITY_BOOKABLE,
            score: !empty($markings['featured']) ? 40 : 10,
            metaitems: $meta,
            capacitystatus: $capacitystatus,
            capacitylabel: $capacitylabel,
            capacityfill: $capacityfill,
            capacityisprogress: $isenrolled,
            showcapacitybar: $isenrolled,
            trainers: self::trainers_data($context),
/var/www/html/public/local/lernhive/classes/dashboard/course_catalog_provider.php
            $window = $filter->limit;
        } else {
            $window = $total;
        }
 
        // Card data for the whole window in one go (task18).
        $windowcourses = array_slice($courses, 0, $window, true);
        $viewer = self::viewer($userid);
        self::preload_cards(array_map('intval', array_column($windowcourses, 'id')));
        $offerings = [];
        try {
            foreach ($courses as $course) {
                if (count($offerings) >= $window) {
                    break;
                }
                $context = \context_course::instance((int) $course->id, IGNORE_MISSING);
                if (!$context) {
                    continue;
                }
                $offerings[] = self::course_to_offering($course, $context, $userid, null, $viewer);
            }
        } finally {
            self::$cardbatch = null;
        }
 
        return ['offerings' => $offerings, 'total' => $total];
    }
 
    /**
     * Order light course rows like the catalogue's built-in sort modes,
     * including the registry's tie-break on the offering id.
     *
     * @param \stdClass[] $courses Rows from {@see matching_courses()}.
     * @param string $sort One of {@see WINDOW_SORTS}.
     * @return \stdClass[]
     */
    private static function sort_courses(array $courses, string $sort): array {
        $nullslast = static fn(\stdClass $c): int => (int) $c->startdate > 0 ? (int) $c->startdate : PHP_INT_MAX;
        $titles = [];
        if ($sort === 'title') {
/var/www/html/public/local/lernhive/classes/hook_callbacks.php
     * myprofile tree stay untouched. The setting local_lernhive/profile_modern_style
     * turns it off again.
     *
     * @param before_html_attributes $hook HTML-attribute hook.
     */
    public static function add_profile_scope_attribute(before_html_attributes $hook): void {
        if (!get_config('local_lernhive', 'profile_modern_style')) {
            return;
        }
 
        $hook->add_attribute('data-lh-profile', 'person');
    }
 
    /**
     * Contribute ordinary Moodle courses to the central LernHive catalogue.
     *
     * @param collect_offerings $hook
     */
    public static function contribute_course_catalog_offerings(collect_offerings $hook): void {
        $window = course_catalog_provider::get_offering_window($hook->userid, $hook->filter);
        $hook->add_offerings($window['offerings']);
        $hook->set_total('local_lernhive', $window['total']);
    }
 
    /**
     * Contribute core catalogue facets.
     *
     * @param collect_facets $hook
     */
    public static function contribute_course_catalog_facets(collect_facets $hook): void {
        $hook->add_facets(course_catalog_provider::get_facets($hook->userid));
    }
 
    /**
     * Register core catalogue sort options.
     *
     * @param collect_sort_options $hook Sort-option collection hook.
     */
    public static function contribute_course_catalog_sort_options(collect_sort_options $hook): void {
        // Core owns the built-in modes. Feature plugins may register more modes.
/var/www/html/public/lib/classes/hook/manager.php
        if (empty($callbacks)) {
            // Nothing is interested in this hook.
            return $event;
        }
 
        foreach ($callbacks as $callback) {
            // Note: PSR-14 states:
            // If passed a Stoppable Event, a Dispatcher
            // MUST call isPropagationStopped() on the Event before each Listener has been called.
            // If that method returns true it MUST return the Event to the Emitter immediately and
            // MUST NOT call any further Listeners. This implies that if an Event is passed to the
            // Dispatcher that always returns true from isPropagationStopped(), zero listeners will be called.
            // Ergo, we check for a stopped event before calling each listener, not afterwards.
            if ($event instanceof StoppableEventInterface) {
                if ($event->isPropagationStopped()) {
                    return $event;
                }
            }
 
            call_user_func($callback, $event);
        }
 
        // Developers need to be careful to not create infinite loops in hook callbacks.
        return $event;
    }
 
    /**
     * Initialise list of all callbacks for each hook.
     */
    private function init_standard_callbacks(): void {
        global $CFG;
 
        $this->allcallbacks = [];
        $this->alldeprecations = [];
 
        // @codeCoverageIgnoreStart
        $shouldcache = $this->should_cache();
        if ($shouldcache) {
            $cache = $this->get_cache();
 
/var/www/html/public/lib/classes/hook/manager.php
        if (empty($callbacks)) {
            // Nothing is interested in this hook.
            return $event;
        }
 
        foreach ($callbacks as $callback) {
            // Note: PSR-14 states:
            // If passed a Stoppable Event, a Dispatcher
            // MUST call isPropagationStopped() on the Event before each Listener has been called.
            // If that method returns true it MUST return the Event to the Emitter immediately and
            // MUST NOT call any further Listeners. This implies that if an Event is passed to the
            // Dispatcher that always returns true from isPropagationStopped(), zero listeners will be called.
            // Ergo, we check for a stopped event before calling each listener, not afterwards.
            if ($event instanceof StoppableEventInterface) {
                if ($event->isPropagationStopped()) {
                    return $event;
                }
            }
 
            call_user_func($callback, $event);
        }
 
        // Developers need to be careful to not create infinite loops in hook callbacks.
        return $event;
    }
 
    /**
     * Initialise list of all callbacks for each hook.
     */
    private function init_standard_callbacks(): void {
        global $CFG;
 
        $this->allcallbacks = [];
        $this->alldeprecations = [];
 
        // @codeCoverageIgnoreStart
        $shouldcache = $this->should_cache();
        if ($shouldcache) {
            $cache = $this->get_cache();
 
/var/www/html/public/local/lernhive/classes/dashboard/catalog_registry.php
            return self::collect_page($userid, $filter, $sortid, $lastpage, $perpage);
        }
        return [
            'offerings' => array_slice($result['offerings'], $page * $perpage, $perpage),
            'total' => $result['total'],
            'page' => $page,
        ];
    }
 
    /**
     * Dispatch the hook, filter, sort and count.
     *
     * @param int $userid Viewer id.
     * @param search_filter $filter Filter, possibly with a window.
     * @param string $sortid Sort mode id.
     * @return array{offerings:offering_data[],total:int}
     */
    private static function collect(int $userid, search_filter $filter, string $sortid): array {
        $hook = new collect_offerings($userid, $filter);
        di::get(hook_manager::class)->dispatch($hook);
 
        $offerings = $hook->get_offerings();
        $offerings = self::apply_visibility_filters($userid, $offerings, $filter);
 
        $option = self::sort_option($userid, $sortid);
        usort($offerings, static function (offering_data $a, offering_data $b) use ($option): int {
            $result = $option->compare($a, $b);
            return $result !== 0 ? $result : [$a->sourcecomponent, $a->id] <=> [$b->sourcecomponent, $b->id];
        });
 
        // Providers that reported a full count (they applied the visibility
        // rules themselves) count with it; every other provider with what
        // survived the filters above.
        $totals = $hook->get_totals();
        $total = array_sum($totals);
        foreach ($offerings as $offering) {
            if (!array_key_exists($offering->sourcecomponent, $totals)) {
                $total++;
            }
        }
/var/www/html/public/local/lernhive/classes/dashboard/catalog_registry.php
     * Merging the sorted heads of every provider yields the same first
     * `($page + 1) * $perpage` offerings as sorting everything.
     *
     * @param int $userid Viewer id, 0 for the public catalogue.
     * @param search_filter $filter Resolved filter values.
     * @param string $sortid Sort mode id.
     * @param int $page Zero-based page.
     * @param int $perpage Offerings per page.
     * @return array{offerings:offering_data[],total:int,page:int} The page (clamped to the last one) and the total.
     */
    public static function collect_page(
        int $userid,
        search_filter $filter,
        string $sortid,
        int $page,
        int $perpage
    ): array {
        $perpage = max(1, $perpage);
        $page = max(0, $page);
        $result = self::collect($userid, $filter->with_window($sortid, ($page + 1) * $perpage), $sortid);
        $lastpage = max(0, (int) ceil($result['total'] / $perpage) - 1);
        if ($page > $lastpage) {
            // A stale deep link past the end shows the last page instead of nothing.
            return self::collect_page($userid, $filter, $sortid, $lastpage, $perpage);
        }
        return [
            'offerings' => array_slice($result['offerings'], $page * $perpage, $perpage),
            'total' => $result['total'],
            'page' => $page,
        ];
    }
 
    /**
     * Dispatch the hook, filter, sort and count.
     *
     * @param int $userid Viewer id.
     * @param search_filter $filter Filter, possibly with a window.
     * @param string $sortid Sort mode id.
     * @return array{offerings:offering_data[],total:int}
     */
/var/www/html/public/local/lernhive/classes/output/catalog_page.php
            ? new \moodle_url($this->baseurl)
            : new \moodle_url('/local/lernhive/catalog.php');
        foreach ($params as $name => $value) {
            $url->param($name, $value);
        }
        return $url;
    }
 
    /**
     * Export the catalogue template context.
     *
     * @param \renderer_base $output Renderer instance.
     * @return array<string,mixed> Template context.
     */
    public function export_for_template(\renderer_base $output): array {
        $sortid = (string) ($this->rawparams['sort'] ?? 'relevance');
        // Real paging over the whole result (task36): providers build cards
        // only for the window, the counts come from their full match counts.
        // A host without paging shows the first page.
        $result = catalog_registry::collect_page($this->userid, $this->filter, $sortid, $this->page ?? 0, self::PER_PAGE);
        $offerings = $result['offerings'];
        $matchcount = $result['total'];
        $totalcount = catalog_registry::collect_page($this->userid, new search_filter(), $sortid, 0, 1)['total'];
        $pagingbar = '';
        if ($this->page !== null && $matchcount > self::PER_PAGE) {
            $pagingbar = $output->render(new \paging_bar(
                $matchcount,
                $result['page'],
                self::PER_PAGE,
                $this->url($this->rawparams)
            ));
        }
        $sortoptions = catalog_registry::collect_sort_options($this->userid);
        $selectedsort = catalog_registry::sort_option($this->userid, $sortid);
 
        // Preserve any non-search params (e.g. format=, category=) across the
        // search-submit so a click on the search button does not silently drop
        // an active tag-driven filter.
        $extras = [];
        foreach ($this->rawparams as $name => $value) {
/var/www/html/public/local/lernhive/catalog.php
 
// View switcher (cards | month) — shared with the full-view catalogue block,
// see `catalog_view`.
$togglebase = new moodle_url('/local/lernhive/catalog.php', $rawparams);
echo catalog_view::view_toggle($togglebase, $view);
 
if ($view === catalog_view::VIEW_MONTH) {
    $monthhtml = catalog_view::month_html(
        $OUTPUT,
        $PAGE,
        $togglebase,
        $filter,
        $rawparams,
        $calendartime,
        (int) ($rawparams['expand'] ?? 0)
    );
    $renderable = new catalog_page($userid, $filter, $rawparams, $monthhtml, null, $dateerror);
    echo $OUTPUT->render_from_template(
        'local_lernhive/catalog_page',
        $renderable->export_for_template($OUTPUT)
    );
} else {
    $renderable = new catalog_page($userid, $filter, $rawparams, null, null, $dateerror, $page);
    echo $OUTPUT->render_from_template(
        'local_lernhive/catalog_page',
        $renderable->export_for_template($OUTPUT)
    );
}
 
echo html_writer::end_div();
echo $OUTPUT->footer();
 

Environment & details:

Key Value
format online,in_person,hybrid
time 3066163200
view month
empty
empty
empty
Key Value
USER stdClass Object ( [id] => 0 [mnethostid] => 1 [access] => Array ( [ra] => Array ( [/1] => Array ( [6] => 6 ) ) [time] => 1794121411 [rsw] => Array ( ) ) [enrol] => Array ( [enrolled] => Array ( ) [tempguest] => Array ( ) ) [sesskey] => xMVBd6u2uX [preference] => Array ( ) )
SESSION stdClass Object ( [isnewsessioncookie] => 1 [cachestore_session] => Array ( [default_session-core/coursecat] => Array ( [__lastaccess__u0_9f2d2c3e66eeaa409981cf2ad09fda25] => Array ( [0] => 1794121411 [1] => 1794121411 ) [u0_9f2d2c3e66eeaa409981cf2ad09fda25_260b57ae1c3966b1910137be05eb286db0e0c867] => Array ( [0] => 1794121411.8577-6af01ec3d16838.75170093 [1] => 1794121411 ) [u0_9f2d2c3e66eeaa409981cf2ad09fda25_0878690aecf796a687f345a5cf7ce17a758a13e6] => Array ( [0] => Array ( [2] => Array ( [name] => Admin User [path] => /2 ) [58] => Array ( [name] => Praxisbeispiele [path] => /58 ) [59] => Array ( [name] => Einstieg und Pflichtwissen [path] => /58/59 ) [60] => Array ( [name] => Zusammenarbeit und Führung [path] => /58/60 ) [61] => Array ( [name] => Kunden, Produkt und Daten [path] => /58/61 ) [62] => Array ( [name] => Seminarveranstaltungen [path] => /62 ) [63] => Array ( [name] => Vorlagen [path] => /63 ) [64] => Array ( [name] => Nugget-Pool [path] => /64 ) ) [1] => 1794121411 ) [u0_9f2d2c3e66eeaa409981cf2ad09fda25_eae4bdad609813f1131741916a481c2b05ca4ee3] => Array ( [0] => Array ( ) [1] => 1794121411 ) [u0_9f2d2c3e66eeaa409981cf2ad09fda25_f94cf60b9b9490154c92b9fc367aa7e1af8368de] => Array ( [0] => Array ( [0] => 2 [1] => 58 [2] => 62 [3] => 63 [4] => 64 ) [1] => 1794121411 ) ) [default_session-core/navigation_cache] => Array ( [__lastaccess__u0_9f2d2c3e66eeaa409981cf2ad09fda25] => Array ( [0] => 1794121411 [1] => 1794121411 ) ) [default_session-theme_boost_union/flavours] => Array ( [__lastaccess__u0_9f2d2c3e66eeaa409981cf2ad09fda25] => Array ( [0] => 1794121411 [1] => 0 ) [u0_9f2d2c3e66eeaa409981cf2ad09fda25_lastinvalidation-ab95758982f7eb97b18eb12d60b3d0cb] => Array ( [0] => 1794121411.8577-6af01ec3d16838.75170093 [1] => 0 ) [u0_9f2d2c3e66eeaa409981cf2ad09fda25_0-ab95758982f7eb97b18eb12d60b3d0cb] => Array ( [0] => [1] => 0 ) ) ) [theme_boost_union_menu_purgesessioncache] => 1 [theme_boost_union_prevlang] => en )
Key Value
HTTP_HOST dev.lernhive.de
HTTP_USER_AGENT Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
HTTP_ACCEPT */*
HTTP_ACCEPT_ENCODING gzip, br, zstd, deflate
HTTP_VIA 2.0 Caddy
HTTP_X_FORWARDED_FOR 216.73.216.38
HTTP_X_FORWARDED_HOST dev.lernhive.de
HTTP_X_FORWARDED_PROTO https
HTTP_X_REAL_IP 216.73.216.38
PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LD_LIBRARY_PATH /usr/local/instantclient
SERVER_SIGNATURE <address>Apache/2.4.66 (Debian) Server at dev.lernhive.de Port 80</address>
SERVER_SOFTWARE Apache/2.4.66 (Debian)
SERVER_NAME dev.lernhive.de
SERVER_ADDR 172.23.0.2
SERVER_PORT 443
REMOTE_ADDR 172.23.0.3
DOCUMENT_ROOT /var/www/html/public
REQUEST_SCHEME http
CONTEXT_PREFIX
CONTEXT_DOCUMENT_ROOT /var/www/html/public
SERVER_ADMIN webmaster@localhost
SCRIPT_FILENAME /var/www/html/public/local/lernhive/catalog.php
REMOTE_PORT 45670
GATEWAY_INTERFACE CGI/1.1
SERVER_PROTOCOL HTTP/1.1
REQUEST_METHOD GET
QUERY_STRING format=online%2Cin_person%2Chybrid&time=3066163200&view=month
REQUEST_URI /local/lernhive/catalog.php?format=online%2Cin_person%2Chybrid&time=3066163200&view=month
SCRIPT_NAME /local/lernhive/catalog.php
PHP_SELF /local/lernhive/catalog.php
REQUEST_TIME_FLOAT 1794121411.83
REQUEST_TIME 1794121411
argv Array ( [0] => format=online%2Cin_person%2Chybrid&time=3066163200&view=month )
argc 1
HTTPS on
Key Value
MOODLE_DOCKER_DBUSER moodle
MOODLE_DOCKER_DBNAME moodle
MOODLE_DOCKER_TIMEOUT_FACTOR 1
HOSTNAME f5ad226f3b16
PHP_VERSION 8.3.30
APACHE_CONFDIR /etc/apache2
PHP_INI_DIR /usr/local/etc/php
GPG_KEYS 1198C0117593497A5EC5C199286AF1F9897469DC C28D937575603EB4ABB725861C0779DC5C0A9DE4 AFD8691FDAEDF03BDF6E460563F15A9B715376CA
PHP_LDFLAGS -Wl,-O1 -pie
MOODLE_DOCKER_RUNNING 1
PWD /var/www/html
APACHE_DOCUMENT_ROOT /var/www/html/public
MOODLE_DOCKER_WEB_PORT 127.0.0.1:8000
APACHE_LOG_DIR /var/log/apache2
LANG C
PHP_SHA256 67f084d36852daab6809561a7c8023d130ca07fc6af8fb040684dd1414934d48
TARGETPLATFORM linux/amd64
MOODLE_DOCKER_DBTYPE pgsql
MOODLE_DOCKER_WEB_HOST localhost
APACHE_PID_FILE /var/run/apache2/apache2.pid
PHPIZE_DEPS autoconf dpkg-dev file g++ gcc libc-dev make pkg-config re2c
MOODLE_DOCKER_BROWSER firefox
PHP_URL https://www.php.net/distributions/php-8.3.30.tar.xz
APACHE_RUN_GROUP www-data
APACHE_LOCK_DIR /var/lock/apache2
SHLVL 0
PHP_CFLAGS -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
MOODLE_DOCKER_DBPASS m@0dl3ing
LD_LIBRARY_PATH /usr/local/instantclient
APACHE_RUN_DIR /var/run/apache2
APACHE_ENVVARS /etc/apache2/envvars
APACHE_RUN_USER www-data
PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PHP_ASC_URL https://www.php.net/distributions/php-8.3.30.tar.xz.asc
PHP_CPPFLAGS -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
0. Whoops\Handler\PrettyPageHandler
1. Whoops\Handler\CallbackHandler