Proyectos de Subversion Moodle

Rev

Rev 161 | Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
namespace theme_universe\output;
18
 
19
use html_writer;
20
use stdClass;
21
use moodle_url;
22
use context_course;
23
use context_system;
24
use core_course_list_element;
25
use custom_menu;
26
use action_menu_filler;
27
use action_menu_link_secondary;
28
use action_menu;
29
use action_link;
30
use core_text;
31
use coding_exception;
32
use navigation_node;
33
use context_header;
34
use pix_icon;
35
use renderer_base;
36
use theme_config;
37
use get_string;
38
use core_course_category;
39
use theme_universe\util\user;
40
use theme_universe\util\course;
41
 
42
/**
43
 * Renderers to align Moodle's HTML with that expected by Bootstrap
44
 *
45
 * @package    theme_universe
46
 * @copyright  2023 Marcin Czaja (https://rosea.io)
47
 * @license    Commercial https://themeforest.net/licenses
48
 */
49
class core_renderer extends \core_renderer {
50
 
51
    public function edit_button(moodle_url $url, string $method = 'post') {
52
        if ($this->page->theme->haseditswitch) {
53
            return;
54
        }
55
        $url->param('sesskey', sesskey());
56
        if ($this->page->user_is_editing()) {
57
            $url->param('edit', 'off');
58
            $editstring = get_string('turneditingoff');
59
        } else {
60
            $url->param('edit', 'on');
61
            $editstring = get_string('turneditingon');
62
        }
63
        $button = new \single_button($url, $editstring, 'post', ['class' => 'btn btn-primary']);
64
        return $this->render_single_button($button);
65
    }
66
 
67
    /**
68
     * The standard tags (meta tags, links to stylesheets and JavaScript, etc.)
69
     * that should be included in the <head> tag. Designed to be called in theme
70
     * layout.php files.
71
     *
72
     * @return string HTML fragment.
73
     */
74
    public function standard_head_html() {
75
        $output = parent::standard_head_html();
76
        global $USER;
77
 
78
        $googleanalyticscode = "<script
79
                                    async
80
                                    src='https://www.googletagmanager.com/gtag/js?id=GOOGLE-ANALYTICS-CODE'>
81
                                </script>
82
                                <script>
83
                                    window.dataLayer = window.dataLayer || [];
84
                                    function gtag() {
85
                                        dataLayer.push(arguments);
86
                                    }
87
                                    gtag('js', new Date());
88
                                    gtag('config', 'GOOGLE-ANALYTICS-CODE');
89
                                </script>";
90
 
91
        $theme = theme_config::load('universe');
92
 
93
        if (!empty($theme->settings->googleanalytics) && isloggedin()) {
94
            $output .= str_replace(
95
                "GOOGLE-ANALYTICS-CODE",
96
                trim($theme->settings->googleanalytics),
97
                $googleanalyticscode
98
            );
99
        }
100
 
101
        return $output;
102
    }
103
 
104
    /*
105
    *
106
    * Method to get reference to $CFG->themedir variable
107
    *
108
    */
109
    function theme_universe_themedir()
110
    {
111
        global $CFG;
112
 
113
        $teme_dir = '/theme';
114
 
115
        if ( isset( $CFG->themedir ) )
116
        {
117
            $teme_dir = $CFG->themedir;
118
            $teme_dir = str_replace($CFG->dirroot, '', $CFG->themedir);
119
        }
120
 
121
        return $teme_dir;
122
    }
123
 
124
 
125
    /**
126
     *
127
     * Method to load theme element form 'layout/parts' folder
128
     *
129
     */
130
    public function theme_part($name, $vars = array()) {
131
 
132
        global $CFG;
133
 
134
        $element = $name . '.php';
135
        $candidate1 = $this->page->theme->dir . '/layout/parts/' . $element;
136
 
137
        // Require for child theme.
138
        if (file_exists($candidate1)) {
139
            $candidate = $candidate1;
140
        } else {
141
            $candidate = $CFG->dirroot . theme_universe_themedir() . '/universe/layout/parts/' . $element;
142
        }
143
 
144
        if (!is_readable($candidate)) {
145
            debugging("Could not include element $name.");
146
            return;
147
        }
148
 
149
        ob_start();
150
        include($candidate);
151
        $output = ob_get_clean();
152
        return $output;
153
    }
154
 
155
    /**
156
     * Renders the custom menu
157
     *
158
     * @param custom_menu $menu
159
     * @return mixed
160
     */
161
    protected function render_custom_menu(custom_menu $menu) {
162
        if (!$menu->has_children()) {
163
            return '';
164
        }
165
 
166
        $content = '';
167
        foreach ($menu->get_children() as $item) {
168
            $context = $item->export_for_template($this);
169
            $content .= $this->render_from_template('core/moremenu_children', $context);
170
        }
171
 
172
        return $content;
173
    }
174
 
175
    /**
176
     * Outputs the favicon urlbase.
177
     *
178
     * @return string an url
179
     */
180
    public function favicon() {
181
        global $CFG;
182
        $theme = theme_config::load('universe');
183
        $favicon = $theme->setting_file_url('favicon', 'favicon');
184
 
185
        if (!empty(($favicon))) {
186
            $urlreplace = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
187
            $favicon = str_replace($urlreplace, '', $favicon);
188
 
189
            return new moodle_url($favicon);
190
        }
191
 
192
        return parent::favicon();
193
    }
194
 
195
    public function render_lang_menu() {
196
        $langs = get_string_manager()->get_list_of_translations();
197
        $haslangmenu = $this->lang_menu() != '';
198
        $menu = new custom_menu;
199
 
200
        if ($haslangmenu) {
201
            $strlang = get_string('language');
202
            $currentlang = current_language();
203
            if (isset($langs[$currentlang])) {
204
                $currentlang = $langs[$currentlang];
205
            } else {
206
                $currentlang = $strlang;
207
            }
208
            $this->language = $menu->add($currentlang, new moodle_url('#'), $strlang, 10000);
209
            foreach ($langs as $langtype => $langname) {
210
                $this->language->add($langname, new moodle_url($this->page->url, array('lang' => $langtype)), $langname);
211
            }
212
            foreach ($menu->get_children() as $item) {
213
                $context = $item->export_for_template($this);
214
            }
215
 
216
            $context->currentlangname = array_search($currentlang, $langs);
217
 
218
            if (isset($context)) {
219
                return $this->render_from_template('theme_universe/lang_menu', $context);
220
            }
221
        }
222
    }
223
 
224
    public function render_lang_menu_login() {
225
        $langs = get_string_manager()->get_list_of_translations();
226
        $haslangmenu = $this->lang_menu() != '';
227
        $menu = new custom_menu;
228
 
229
        if ($haslangmenu) {
230
            $strlang = get_string('language');
231
            $currentlang = current_language();
232
            if (isset($langs[$currentlang])) {
233
                $currentlang = $langs[$currentlang];
234
            } else {
235
                $currentlang = $strlang;
236
            }
237
            $this->language = $menu->add($currentlang, new moodle_url('#'), $strlang, 10000);
238
            foreach ($langs as $langtype => $langname) {
239
                $this->language->add($langname, new moodle_url($this->page->url, array('lang' => $langtype)), $langname);
240
            }
241
            foreach ($menu->get_children() as $item) {
242
                $context = $item->export_for_template($this);
243
            }
244
 
245
            $context->currentlangname = array_search($currentlang, $langs);
246
 
247
            if (isset($context)) {
248
                return $this->render_from_template('theme_universe/lang_menu_login', $context);
249
            }
250
        }
251
    }
252
 
253
    public static function get_course_progress_count($course, $userid = 0) {
254
        global $USER;
255
 
256
        // Make sure we continue with a valid userid.
257
        if (empty($userid)) {
258
            $userid = $USER->id;
259
        }
260
 
261
        $completion = new \completion_info($course);
262
 
263
        // First, let's make sure completion is enabled.
264
        if (!$completion->is_enabled()) {
265
            return null;
266
        }
267
 
268
        if (!$completion->is_tracked_user($userid)) {
269
            return null;
270
        }
271
 
272
        // Before we check how many modules have been completed see if the course has.
273
        if ($completion->is_course_complete($userid)) {
274
            return 100;
275
        }
276
 
277
        // Get the number of modules that support completion.
278
        $modules = $completion->get_activities();
279
        $count = count($modules);
280
        if (!$count) {
281
            return null;
282
        }
283
 
284
        // Get the number of modules that have been completed.
285
        $completed = 0;
286
        foreach ($modules as $module) {
287
            $data = $completion->get_data($module, true, $userid);
288
            $completed += $data->completionstate == COMPLETION_INCOMPLETE ? 0 : 1;
289
        }
290
 
291
        return ($completed / $count) * 100;
292
    }
293
 
294
    /**
295
     *
296
     * Outputs the course progress if course completion is on.
297
     *
298
     * @return string Markup.
299
     */
300
    protected function courseprogress($course) {
301
        global $USER;
302
        $theme = \theme_config::load('universe');
303
 
304
        $output = '';
305
        $courseformat = course_get_format($course);
306
 
307
        if (get_class($courseformat) != 'format_tiles') {
308
            $completion = new \completion_info($course);
309
 
310
            // Start Course progress count.
311
            // Make sure we continue with a valid userid.
312
            if (empty($userid)) {
313
                $userid = $USER->id;
314
            }
315
            $completion = new \completion_info($course);
316
 
317
            // Get the number of modules that support completion.
318
            $modules = $completion->get_activities();
319
            $count = count($modules);
320
            if (!$count) {
321
                return null;
322
            }
323
 
324
            // Get the number of modules that have been completed.
325
            $completed = 0;
326
            foreach ($modules as $module) {
327
                $data = $completion->get_data($module, true, $userid);
328
                $completed += $data->completionstate == COMPLETION_INCOMPLETE ? 0 : 1;
329
            }
330
            $progresscountc = $completed;
331
            $progresscounttotal = $count;
332
            // End progress count.
333
 
334
            if ($completion->is_enabled()) {
335
                $templatedata = new \stdClass;
336
                $templatedata->progress = \core_completion\progress::get_course_progress_percentage($course);
337
                $templatedata->progresscountc = $progresscountc;
338
                $templatedata->progresscounttotal = $progresscounttotal;
339
 
340
                if (!is_null($templatedata->progress)) {
341
                    $templatedata->progress = floor($templatedata->progress);
342
                } else {
343
                    $templatedata->progress = 0;
344
                }
345
                if (get_config('theme_universe', 'courseprogressbar') == 1) {
346
                    $progressbar = '<div class="rui-course-progresschart">' .
347
                        $this->render_from_template('theme_universe/progress-chart', $templatedata) .
348
                        '</div>';
349
                    if (has_capability('report/progress:view',  \context_course::instance($course->id))) {
350
                        $courseprogress = new \moodle_url('/report/progress/index.php');
351
                        $courseprogress->param('course', $course->id);
352
                        $courseprogress->param('sesskey', sesskey());
353
                        $output .= html_writer::link($courseprogress, $progressbar, array('class' => 'rui-course-progressbar border rounded px-3 pt-2 mb-3'));
354
                    } else {
355
                        $output .= $progressbar;
356
                    }
357
                }
358
            }
359
        }
360
 
361
        return $output;
362
    }
363
 
364
 
365
    /**
366
     *
367
     * Returns HTML to display course contacts.
368
     *
369
     */
370
    public function course_teachers() {
371
        global $CFG, $COURSE, $DB;
372
        $course = $DB->get_record('course', ['id' => $COURSE->id]);
373
        $course = new core_course_list_element($course);
374
        $instructors = $course->get_course_contacts();
375
 
376
        if (!empty($instructors)) {
377
            $content = html_writer::start_div('course-teachers-box');
378
 
379
            foreach ($instructors as $key => $instructor) {
380
                $name = $instructor['username'];
381
                $role = $instructor['rolename'];
382
                $roleshortname = $instructor['role']->shortname;
383
 
384
                if ($instructor['role']->id == '3') {
385
                    $url = $CFG->wwwroot . '/user/profile.php?id=' . $key;
386
                    $user = $instructor['user'];
387
                    $userutil = new user($user->id);
388
                    $picture = $userutil->get_user_picture();
389
 
390
                    $content .= "<div class='course-contact-title-item'>
391
                        <a href='{$url}' 'title='{$name}'
392
                            class='course-contact rui-user-{$roleshortname}'>";
393
                    $content .= "<img src='{$picture}'
394
                        class='course-teacher-avatar' alt='{$name}'
395
                        title='{$name} - {$role}' data-toggle='tooltip'/>";
396
                    $content .= "<div class='course-teacher-content'>
397
                        <span class='course-teacher-role'>{$role}</span>
398
                        <h4 class='course-teacher-name'>{$name}</h4></div>";
399
                    $content .= "</a></div>";
400
                }
401
            }
402
 
403
            $content .= html_writer::end_div(); // End .teachers-box.
404
            return $content;
405
        }
406
    }
407
 
408
    public function course_contacts() {
409
        global $CFG, $COURSE, $DB;
410
        $course = $DB->get_record('course', ['id' => $COURSE->id]);
411
        $course = new core_course_list_element($course);
412
        $instructors = $course->get_course_contacts();
413
 
414
        if (!empty($instructors)) {
415
            $content = html_writer::start_div('course-teachers-box w-100');
416
 
417
            foreach ($instructors as $key => $instructor) {
418
                $name = $instructor['username'];
419
                $role = $instructor['rolename'];
420
                $roleshortname = $instructor['role']->shortname;
421
 
422
                $url = $CFG->wwwroot . '/user/profile.php?id=' . $key;
423
                $user = $instructor['user'];
424
                $userutil = new user($user->id);
425
                $picture = $userutil->get_user_picture(384);
426
 
427
                $user = $DB->get_record('user', array('id' => $key));
428
                $desc = $user->description;
429
 
430
                $content .= "<div class='rui-block-team-item text-center text-md-left
431
                    d-inline-flex flex-wrap align-items-start align-items-md-center'>";
432
                $content .= "<div class='rui-card-team--img-smpl'><img src='{$picture}'
433
                    class='rui-card-team--img-smpl mr-3 mr-md-5'
434
                    alt='{$name}, {$role}'/></div>";
435
                $content .= "<div class='rui-course-teacher--item col px-0 text-left'>
436
                    <a href='{$url}' 'title='{$name}'
437
                        class='course-contact rui-user-{$roleshortname}'>
438
                        <h4 class='mb-0'>{$name}</h4></a>
439
                        <span class='rui-block-text--3 rui-block-text--light mb-3'>{$role}</span>";
440
                $content .= "<div class='rui-block-text--2 mt-2'>{$desc}</div></div></div>";
441
            }
442
            $content .= html_writer::end_div(); // End .teachers-box.
443
            return $content;
444
        }
445
    }
446
 
447
    /**
448
     *
449
     * Returns HTML to display course details.
450
     *
451
     */
452
    protected function course_details() {
453
        global $CFG, $COURSE, $DB;
454
        $course = $DB->get_record('course', ['id' => $COURSE->id]);
455
        $course = new core_course_list_element($course);
456
        $content = '';
457
        $tempcourse = $DB->get_record('course_categories', ['id' => $COURSE->id]);
458
 
459
        $content .= html_writer::start_div('rui-course-details mt-4');
460
            $content .= html_writer::start_div('rui-custom-field-box rui-course-startdate');
461
                $content .= html_writer::tag('span', get_string('startdate', 'moodle'), ['class' => 'rui-custom-field-name']);
462
                $content .= html_writer::tag('span', date("F j, Y", $COURSE->startdate), ['class' => 'rui-custom-field-value']);
463
            $content .= html_writer::end_div();
464
 
465
            // Course End date.
466
            $courseenddate = $COURSE->enddate;
467
            if ($courseenddate != '0') {
468
                $content .= html_writer::start_div('rui-custom-field-box rui-course-startdate');
469
                    $content .= html_writer::tag('span', get_string('enddate', 'moodle'), ['class' => 'rui-course-enddate-label rui-custom-field-name']);
470
                    $content .= html_writer::tag('span', date("F j, Y", $courseenddate), ['class' => 'rui-course-enddate rui-custom-field-value']);
471
                $content .= html_writer::end_div();
472
            }
473
        $content .= html_writer::end_div(); // .rui-course-details.
474
 
475
        return $content;
476
    }
477
 
478
    /**
479
     *
480
     * Returns HTML to display course summary.
481
     *
482
     */
483
    protected function course_summary($courseid = 0, $content = '') {
484
        global $COURSE, $CFG;
485
        $output = '';
486
 
487
        require_once($CFG->libdir . '/filelib.php');
488
 
489
        $iscourseid = $courseid ? $courseid : $COURSE->id;
490
        $iscontent = $content ? $content : $COURSE->summary;
491
        $context = context_course::instance($iscourseid);
492
        $desc = file_rewrite_pluginfile_urls($iscontent, 'pluginfile.php', $context->id, 'course', 'summary', null);
493
 
494
        $output .= html_writer::start_div('rui-course-desc');
495
        $output .= format_text($desc, FORMAT_HTML);
496
        $output .= html_writer::end_div();
497
 
498
        return $output;
499
    }
500
 
501
    /**
502
     * Outputs the pix url base
503
     *
504
     * @return string an URL.
505
     */
506
    public function get_pix_image_url_base() {
507
        global $CFG;
508
 
509
        return $CFG->wwwroot . "/theme/universe/pix";
510
    }
511
 
512
    /**
513
     *
514
     */
515
    public function course_hero_url() {
516
        global $CFG, $COURSE, $DB;
517
 
518
        $course = $DB->get_record('course', ['id' => $COURSE->id]);
519
 
520
        $course = new core_course_list_element($course);
521
 
522
        $courseimage = '';
523
        $imageindex = 1;
524
        foreach ($course->get_course_overviewfiles() as $file) {
525
            $isimage = $file->is_valid_image();
526
 
527
            $url = new moodle_url("$CFG->wwwroot/pluginfile.php" . '/' .
528
                $file->get_contextid() . '/' . $file->get_component() . '/' .
529
                $file->get_filearea() .
530
                $file->get_filepath() .
531
                $file->get_filename(), ['forcedownload' => !$isimage]);
532
 
533
            if ($isimage) {
534
                $courseimage = $url;
535
            }
536
 
537
            if ($imageindex == 2) {
538
                break;
539
            }
540
 
541
            $imageindex++;
542
        }
543
 
544
        $html = '';
545
        // Create html for header.
546
        if (!empty($courseimage)) {
547
            $html .= $courseimage;
548
        }
549
        return $html;
550
    }
551
 
552
    /**
553
     * Returns HTML to display course hero.
554
     *
555
     */
556
    public function course_hero() {
557
        global $CFG, $COURSE, $DB;
558
 
559
        $course = $DB->get_record('course', ['id' => $COURSE->id]);
560
 
561
        $course = new core_course_list_element($course);
562
 
563
        $courseimage = '';
564
 
565
        $courseutil = new course($course);
566
        $courseimage = $courseutil->get_summary_image(false); // Remove repeatable pattern on the course page.
567
 
568
        $html = '';
569
        // Create html for header.
570
        if (!empty($courseimage)) {
571
            $html .= $courseimage;
572
        }
573
        return $html;
574
    }
575
 
576
 
577
    /**
578
     * Breadcrumbs
579
     *
580
     */
581
    public function breadcrumbs() {
582
        global $USER, $COURSE, $CFG;
583
 
584
        $header = new stdClass();
585
        $header->hasnavbar = empty($this->page->layout_options['nonavbar']);
586
        $header->navbar = $this->navbar();
587
        $header->courseheader = $this->course_header();
588
        $html = $this->render_from_template('theme_universe/breadcrumbs', $header);
589
 
590
        return $html;
591
    }
592
 
593
 
594
    /**
595
     * Wrapper for header elements.
596
     *
597
     * @return string HTML to display the main header.
598
     */
599
    public function simple_header() {
600
 
601
        global $USER, $COURSE, $CFG;
602
        $html = null;
603
 
604
        if (
605
            $this->page->include_region_main_settings_in_header_actions() &&
606
            !$this->page->blocks->is_block_present('settings')
607
        ) {
608
            // Only include the region main settings if the page has requested it and it doesn't already have
609
            // the settings block on it. The region main settings are included in the settings block and
610
            // duplicating the content causes behat failures.
611
            $this->page->add_header_action(html_writer::div(
612
                $this->region_main_settings_menu(),
613
                'd-print-none',
614
                ['id' => 'region-main-settings-menu']
615
            ));
616
        }
617
 
618
        $header = new stdClass();
619
        $header->settingsmenu = $this->context_header_settings_menu();
620
        $header->contextheader = $this->context_header();
621
        $header->hasnavbar = empty($this->page->layout_options['nonavbar']);
622
        $header->navbar = $this->navbar();
623
        $header->pageheadingbutton = $this->page_heading_button();
624
        $header->courseheader = $this->course_header();
625
        $header->headeractions = $this->page->get_header_actions();
626
 
627
        if ($this->page->pagelayout != 'admin') {
628
            $html .= $this->render_from_template('theme_universe/header', $header);
629
        }
630
 
631
        if ($this->page->pagelayout == 'admin') {
632
            $html .= $this->render_from_template('theme_universe/header_admin', $header);
633
        }
634
 
635
        return $html;
636
    }
637
 
638
 
639
 
640
 
641
    public function display_course_progress() {
642
        $html = null;
643
        $html .= $this->courseprogress($this->page->course);
644
        return $html;
645
    }
646
 
647
    /**
648
     * Wrapper for header elements.
649
     *
650
     * @return string HTML to display the main header.
651
     */
652
    public function full_header() {
653
        global $USER, $COURSE, $CFG;
654
        $theme = \theme_config::load('universe');
655
        $html = null;
656
        $pagetype = $this->page->pagetype;
657
        $homepage = get_home_page();
658
        $homepagetype = null;
659
        // Add a special case since /my/courses is a part of the /my subsystem.
660
        if ($homepage == HOMEPAGE_MY || $homepage == HOMEPAGE_MYCOURSES) {
661
            $homepagetype = 'my-index';
662
        } else if ($homepage == HOMEPAGE_SITE) {
663
            $homepagetype = 'site-index';
664
        }
665
        if (
666
            $this->page->include_region_main_settings_in_header_actions() &&
667
            !$this->page->blocks->is_block_present('settings')
668
        ) {
669
            // Only include the region main settings if the page has requested it and it doesn't already have
670
            // the settings block on it. The region main settings are included in the settings block and
671
            // duplicating the content causes behat failures.
672
            $this->page->add_header_action(html_writer::div(
673
                $this->region_main_settings_menu(),
674
                'd-print-none',
675
                ['id' => 'region-main-settings-menu']
676
            ));
677
        }
678
 
679
        $header = new stdClass();
680
        $header->settingsmenu = $this->context_header_settings_menu();
681
        $header->contextheader = $this->context_header();
682
        $header->hasnavbar = empty($this->page->layout_options['nonavbar']);
683
        $header->navbar = $this->navbar();
684
        $header->pageheadingbutton = $this->page_heading_button();
685
        $header->courseheader = $this->course_header();
686
        $header->headeractions = $this->page->get_header_actions();
687
 
688
        if ($this->page->theme->settings->ipcoursedetails == 1) {
689
            $html .= $this->course_details();
690
        }
691
 
692
        $html .= $this->render_from_template('theme_universe/header', $header);
693
        if ($this->page->theme->settings->ipcoursesummary == 1) {
694
            $html .= $this->course_summary();
695
        }
696
 
697
        $html .= html_writer::start_tag('div', array('class' => 'rui-course-header-color'));
698
        if ($this->page->theme->settings->cccteachers == 1) {
699
            $html .= $this->course_teachers();
700
        }
701
 
702
        $html .= html_writer::end_tag('div'); // End .rui-course-header.
703
 
704
        return $html;
705
    }
706
 
707
 
708
    /**
709
     * Wrapper for header elements.
710
     *
711
     * @return string HTML to display the main header.
712
     */
713
    public function clean_header() {
714
        global $USER, $COURSE, $CFG;
715
        $theme = \theme_config::load('universe');
716
        $html = null;
717
        $pagetype = $this->page->pagetype;
718
        $homepage = get_home_page();
719
        $homepagetype = null;
720
        // Add a special case since /my/courses is a part of the /my subsystem.
721
        if ($homepage == HOMEPAGE_MY || $homepage == HOMEPAGE_MYCOURSES) {
722
            $homepagetype = 'my-index';
723
        } else if ($homepage == HOMEPAGE_SITE) {
724
            $homepagetype = 'site-index';
725
        }
726
        if (
727
            $this->page->include_region_main_settings_in_header_actions() &&
728
            !$this->page->blocks->is_block_present('settings')
729
        ) {
730
            // Only include the region main settings if the page has requested it and it doesn't already have
731
            // the settings block on it. The region main settings are included in the settings block and
732
            // duplicating the content causes behat failures.
733
            $this->page->add_header_action(html_writer::div(
734
                $this->region_main_settings_menu(),
735
                'd-print-none',
736
                ['id' => 'region-main-settings-menu']
737
            ));
738
        }
739
 
740
        $header = new stdClass();
741
        $header->courseheader = $this->course_header();
742
        $header->headeractions = $this->page->get_header_actions();
743
 
744
        $html .= $this->render_from_template('theme_universe/header', $header);
745
 
746
        return $html;
747
    }
748
 
749
 
750
    /**
751
     * Returns standard navigation between activities in a course.
752
     *
753
     * @return string the navigation HTML.
754
     */
755
    public function activity_navigation() {
756
        // First we should check if we want to add navigation.
757
        $context = $this->page->context;
758
        if (($this->page->pagelayout !== 'incourse' && $this->page->pagelayout !== 'frametop')
759
            || $context->contextlevel != CONTEXT_MODULE
760
        ) {
761
            return '';
762
        }
763
        // If the activity is in stealth mode, show no links.
764
        if ($this->page->cm->is_stealth()) {
765
            return '';
766
        }
767
        $course = $this->page->cm->get_course();
768
        $courseformat = course_get_format($course);
769
 
770
        // Get a list of all the activities in the course.
771
        $modules = get_fast_modinfo($course->id)->get_cms();
772
        // Put the modules into an array in order by the position they are shown in the course.
773
        $mods = [];
774
        $activitylist = [];
775
        foreach ($modules as $module) {
776
            // Only add activities the user can access, aren't in stealth mode and have a url (eg. mod_label does not).
777
            if (!$module->uservisible || $module->is_stealth() || empty($module->url)) {
778
                continue;
779
            }
780
            $mods[$module->id] = $module;
781
            // No need to add the current module to the list for the activity dropdown menu.
782
            if ($module->id == $this->page->cm->id) {
783
                continue;
784
            }
785
            // Module name.
786
            $modname = $module->get_formatted_name();
787
            // Display the hidden text if necessary.
788
            if (!$module->visible) {
789
                $modname .= ' ' . get_string('hiddenwithbrackets');
790
            }
791
            // Module URL.
792
            $linkurl = new moodle_url($module->url, array('forceview' => 1));
793
            // Add module URL (as key) and name (as value) to the activity list array.
794
            $activitylist[$linkurl->out(false)] = $modname;
795
        }
796
        $nummods = count($mods);
797
        // If there is only one mod then do nothing.
798
        if ($nummods == 1) {
799
            return '';
800
        }
801
        // Get an array of just the course module ids used to get the cmid value based on their position in the course.
802
        $modids = array_keys($mods);
803
        // Get the position in the array of the course module we are viewing.
804
        $position = array_search($this->page->cm->id, $modids);
805
        $prevmod = null;
806
        $nextmod = null;
807
        // Check if we have a previous mod to show.
808
        if ($position > 0) {
809
            $prevmod = $mods[$modids[$position - 1]];
810
        }
811
        // Check if we have a next mod to show.
812
        if ($position < ($nummods - 1)) {
813
            $nextmod = $mods[$modids[$position + 1]];
814
        }
815
        $activitynav = new \core_course\output\activity_navigation($prevmod, $nextmod, $activitylist);
816
        $renderer = $this->page->get_renderer('core', 'course');
817
        return $renderer->render($activitynav);
818
    }
819
 
820
 
821
    /**
822
     * This is an optional menu that can be added to a layout by a theme. It contains the
823
     * menu for the course administration, only on the course main page.
824
     *
825
     * @return string
826
     */
827
    public function context_header_settings_menu() {
828
        $context = $this->page->context;
829
        $menu = new action_menu();
830
 
831
        $items = $this->page->navbar->get_items();
832
        $currentnode = end($items);
833
 
834
        $showcoursemenu = false;
835
        $showfrontpagemenu = false;
836
        $showusermenu = false;
837
 
838
        // We are on the course home page.
839
        if (($context->contextlevel == CONTEXT_COURSE) &&
840
            !empty($currentnode) &&
841
            ($currentnode->type == navigation_node::TYPE_COURSE || $currentnode->type == navigation_node::TYPE_SECTION)
842
        ) {
843
            $showcoursemenu = true;
844
        }
845
 
846
        $courseformat = course_get_format($this->page->course);
847
        // This is a single activity course format, always show the course menu on the activity main page.
848
        if (
849
            $context->contextlevel == CONTEXT_MODULE &&
850
            !$courseformat->has_view_page()
851
        ) {
852
 
853
            $this->page->navigation->initialise();
854
            $activenode = $this->page->navigation->find_active_node();
855
            // If the settings menu has been forced then show the menu.
856
            if ($this->page->is_settings_menu_forced()) {
857
                $showcoursemenu = true;
858
            } else if (!empty($activenode) && ($activenode->type == navigation_node::TYPE_ACTIVITY ||
859
                $activenode->type == navigation_node::TYPE_RESOURCE)) {
860
 
861
                // We only want to show the menu on the first page of the activity. This means
862
                // the breadcrumb has no additional nodes.
863
                if ($currentnode && ($currentnode->key == $activenode->key && $currentnode->type == $activenode->type)) {
864
                    $showcoursemenu = true;
865
                }
866
            }
867
        }
868
 
869
        // This is the site front page.
870
        if (
871
            $context->contextlevel == CONTEXT_COURSE &&
872
            !empty($currentnode) &&
873
            $currentnode->key === 'home'
874
        ) {
875
            $showfrontpagemenu = true;
876
        }
877
 
878
        // This is the user profile page.
879
        if (
880
            $context->contextlevel == CONTEXT_USER &&
881
            !empty($currentnode) &&
882
            ($currentnode->key === 'myprofile')
883
        ) {
884
            $showusermenu = true;
885
        }
886
 
887
        if ($showfrontpagemenu) {
888
            $settingsnode = $this->page->settingsnav->find('frontpage', navigation_node::TYPE_SETTING);
889
            if ($settingsnode) {
890
                // Build an action menu based on the visible nodes from this navigation tree.
891
                $skipped = $this->build_action_menu_from_navigation($menu, $settingsnode, false, true);
892
 
893
                // We only add a list to the full settings menu if we didn't include every node in the short menu.
894
                if ($skipped) {
895
                    $text = get_string('morenavigationlinks');
896
                    $url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
897
                    $link = new action_link($url, $text, null, null, new pix_icon('t/edit', $text));
898
                    $menu->add_secondary_action($link);
899
                }
900
            }
901
        } else if ($showcoursemenu) {
902
            $settingsnode = $this->page->settingsnav->find('courseadmin', navigation_node::TYPE_COURSE);
903
            if ($settingsnode) {
904
                // Build an action menu based on the visible nodes from this navigation tree.
905
                $skipped = $this->build_action_menu_from_navigation($menu, $settingsnode, false, true);
906
 
907
                // We only add a list to the full settings menu if we didn't include every node in the short menu.
908
                if ($skipped) {
909
                    $text = get_string('morenavigationlinks');
910
                    $url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
911
                    $link = new action_link($url, $text, null, null, new pix_icon('t/edit', $text));
912
                    $menu->add_secondary_action($link);
913
                }
914
            }
915
        } else if ($showusermenu) {
916
            // Get the course admin node from the settings navigation.
917
            $settingsnode = $this->page->settingsnav->find('useraccount', navigation_node::TYPE_CONTAINER);
918
            if ($settingsnode) {
919
                // Build an action menu based on the visible nodes from this navigation tree.
920
                $this->build_action_menu_from_navigation($menu, $settingsnode);
921
            }
922
        }
923
 
924
        return $this->render($menu);
925
    }
926
 
927
    public function customeditblockbtn() {
928
        $header = new stdClass();
929
        $header->settingsmenu = $this->context_header_settings_menu();
930
        $header->pageheadingbutton = $this->page_heading_button();
931
 
932
        $html = $this->render_from_template('theme_universe/header_settings_menu', $header);
933
 
934
        return $html;
935
    }
936
 
937
    /**
938
     * Renders the context header for the page.
939
     *
940
     * @param array $headerinfo Heading information.
941
     * @param int $headinglevel What 'h' level to make the heading.
942
     * @return string A rendered context header.
943
     */
944
    public function context_header($headerinfo = null, $headinglevel = 1): string {
945
        global $DB, $USER, $CFG, $SITE;
946
        require_once($CFG->dirroot . '/user/lib.php');
947
        $context = $this->page->context;
948
        $heading = null;
949
        $imagedata = null;
950
        $subheader = null;
951
        $userbuttons = null;
952
 
953
        // Make sure to use the heading if it has been set.
954
        if (isset($headerinfo['heading'])) {
955
            $heading = $headerinfo['heading'];
956
        } else {
957
            $heading = $this->page->heading;
958
        }
959
 
960
        // The user context currently has images and buttons. Other contexts may follow.
961
        if ((isset($headerinfo['user']) || $context->contextlevel == CONTEXT_USER) && $this->page->pagetype !== 'my-index') {
962
            if (isset($headerinfo['user'])) {
963
                $user = $headerinfo['user'];
964
            } else {
965
                // Look up the user information if it is not supplied.
966
                $user = $DB->get_record('user', array('id' => $context->instanceid));
967
            }
968
 
969
            // If the user context is set, then use that for capability checks.
970
            if (isset($headerinfo['usercontext'])) {
971
                $context = $headerinfo['usercontext'];
972
            }
973
 
974
            // Only provide user information if the user is the current user, or a user which the current user can view.
975
            // When checking user_can_view_profile(), either:
976
            // If the page context is course, check the course context (from the page object) or;
977
            // If page context is NOT course, then check across all courses.
978
            $course = ($this->page->context->contextlevel == CONTEXT_COURSE) ? $this->page->course : null;
979
 
980
            if (user_can_view_profile($user, $course)) {
981
                // Use the user's full name if the heading isn't set.
982
                if (empty($heading)) {
983
                    $heading = fullname($user);
984
                }
985
 
986
                $imagedata = $this->user_picture($user, array('size' => 100));
987
 
988
                // Check to see if we should be displaying a message button.
989
                if (!empty($CFG->messaging) && has_capability('moodle/site:sendmessage', $context)) {
990
                    $userbuttons = array(
991
                        'messages' => array(
992
                            'buttontype' => 'message',
993
                            'title' => get_string('message', 'message'),
994
                            'url' => new moodle_url('/message/index.php', array('id' => $user->id)),
995
                            'image' => 'message',
996
                            'linkattributes' => \core_message\helper::messageuser_link_params($user->id),
997
                            'page' => $this->page
998
                        )
999
                    );
1000
 
1001
                    if ($USER->id != $user->id) {
1002
                        $iscontact = \core_message\api::is_contact($USER->id, $user->id);
1003
                        $contacttitle = $iscontact ? 'removefromyourcontacts' : 'addtoyourcontacts';
1004
                        $contacturlaction = $iscontact ? 'removecontact' : 'addcontact';
1005
                        $contactimage = $iscontact ? 'removecontact' : 'addcontact';
1006
                        $userbuttons['togglecontact'] = array(
1007
                            'buttontype' => 'togglecontact',
1008
                            'title' => get_string($contacttitle, 'message'),
1009
                            'url' => new moodle_url(
1010
                                '/message/index.php',
1011
                                array(
1012
                                    'user1' => $USER->id,
1013
                                    'user2' => $user->id,
1014
                                    $contacturlaction => $user->id,
1015
                                    'sesskey' => sesskey()
1016
                                )
1017
                            ),
1018
                            'image' => $contactimage,
1019
                            'linkattributes' => \core_message\helper::togglecontact_link_params($user, $iscontact),
1020
                            'page' => $this->page
1021
                        );
1022
                    }
1023
 
1024
                    $this->page->requires->string_for_js('changesmadereallygoaway', 'moodle');
1025
                }
1026
            } else {
1027
                $heading = null;
1028
            }
1029
        }
1030
 
1031
        $prefix = null;
1032
        if ($context->contextlevel == CONTEXT_MODULE) {
1033
            if ($this->page->course->format === 'singleactivity') {
1034
                $heading = $this->page->course->fullname;
1035
            } else {
1036
                $heading = $this->page->cm->get_formatted_name();
1037
                $imagedata = $this->pix_icon('monologo', '', $this->page->activityname, ['class' => 'activityicon']);
1038
                $purposeclass = plugin_supports('mod', $this->page->activityname, FEATURE_MOD_PURPOSE);
1039
                $purposeclass .= ' activityiconcontainer';
1040
                $purposeclass .= ' modicon_' . $this->page->activityname;
1041
                $imagedata = html_writer::tag('div', $imagedata, ['class' => $purposeclass]);
1042
                $prefix = get_string('modulename', $this->page->activityname);
1043
            }
1044
        }
1045
 
1046
        $contextheader = new \context_header($heading, $headinglevel, $imagedata, $userbuttons, $prefix);
1047
        return $this->render_context_header($contextheader);
1048
    }
1049
 
1050
 
1051
    /**
1052
     * Construct a user menu, returning HTML that can be echoed out by a
1053
     * layout file.
1054
     *
1055
     * @param stdClass $user A user object, usually $USER.
1056
     * @param bool $withlinks true if a dropdown should be built.
1057
     * @return string HTML fragment.
1058
     */
1059
    public function user_menu($user = null, $withlinks = null) {
1060
        global $USER, $CFG;
1061
        require_once($CFG->dirroot . '/user/lib.php');
1062
 
1063
        if (is_null($user)) {
1064
            $user = $USER;
1065
        }
1066
 
1067
        // Note: this behaviour is intended to match that of core_renderer::login_info,
1068
        // but should not be considered to be good practice; layout options are
1069
        // intended to be theme-specific. Please don't copy this snippet anywhere else.
1070
        if (is_null($withlinks)) {
1071
            $withlinks = empty($this->page->layout_options['nologinlinks']);
1072
        }
1073
 
1074
        // Add a class for when $withlinks is false.
1075
        $usermenuclasses = 'usermenu';
1076
        if (!$withlinks) {
1077
            $usermenuclasses .= ' withoutlinks';
1078
        }
1079
 
1080
        $returnstr = "";
1081
 
1082
        // If during initial install, return the empty return string.
1083
        if (during_initial_install()) {
1084
            return $returnstr;
1085
        }
1086
 
1087
        $loginpage = $this->is_login_page();
1088
        $loginurl = get_login_url();
1089
        // If not logged in, show the typical not-logged-in string.
1090
        if (!isloggedin()) {
1091
            if (!$loginpage) {
1092
                $returnstr .= "<a class=\"rui-topbar-btn rui-login-btn\" href=\"$loginurl\"><span class=\"rui-login-btn-txt\">" .
1093
                    get_string('login') .
1094
                    '</span>
1095
                <svg class="ml-2" width="20" height="20" fill="none" viewBox="0 0 24 24">
1096
                <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
1097
                d="M9.75 8.75L13.25 12L9.75 15.25"></path>
1098
                <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
1099
                d="M9.75 4.75H17.25C18.3546 4.75 19.25 5.64543 19.25 6.75V17.25C19.25 18.3546 18.3546 19.25 17.25 19.25H9.75">
1100
                </path>
1101
                <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 12H4.75"></path>
1102
                </svg></a>';
1103
            }
1104
            return html_writer::div(
1105
                html_writer::span(
1106
                    $returnstr,
1107
                    'login'
1108
                ),
1109
                $usermenuclasses
1110
            );
1111
        }
1112
 
1113
        // If logged in as a guest user, show a string to that effect.
1114
        if (isguestuser()) {
1115
            $icon = '<svg class="mr-2"
1116
                width="24"
1117
                height="24"
1118
                viewBox="0 0 24 24"
1119
                fill="none"
1120
                xmlns="http://www.w3.org/2000/svg">
1121
            <path d="M10 12C10 12.5523 9.55228 13 9 13C8.44772 13 8 12.5523 8
1122
            12C8 11.4477 8.44772 11 9 11C9.55228 11 10 11.4477 10 12Z"
1123
                fill="currentColor"
1124
                />
1125
            <path d="M15 13C15.5523 13 16 12.5523 16 12C16 11.4477 15.5523 11
1126
            15 11C14.4477 11 14 11.4477 14 12C14 12.5523 14.4477 13 15 13Z"
1127
                fill="currentColor"
1128
                />
1129
            <path fill-rule="evenodd"
1130
                clip-rule="evenodd"
1131
                d="M12.0244 2.00003L12 2C6.47715 2 2 6.47715 2 12C2 17.5228
1132
                6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.74235
1133
            17.9425 2.43237 12.788 2.03059L12.7886 2.0282C12.5329 2.00891
1134
            12.278 1.99961 12.0244 2.00003ZM12 20C16.4183 20 20 16.4183 20
1135
            12C20 11.3014 19.9105 10.6237 19.7422
1136
            9.97775C16.1597 10.2313 12.7359 8.52461 10.7605 5.60246C9.31322
1137
            7.07886 7.2982 7.99666 5.06879 8.00253C4.38902 9.17866 4 10.5439 4
1138
            12C4 16.4183 7.58172 20
1139
            12 20ZM11.9785 4.00003L12.0236 4.00003L12 4L11.9785 4.00003Z"
1140
                fill="currentColor"
1141
                /></svg>';
1142
            $returnstr = '<div class="rui-badge-guest">' . $icon . get_string('loggedinasguest') . '</div>';
1143
            if (!$loginpage && $withlinks) {
1144
                $returnstr .= "<a class=\"rui-topbar-btn rui-login-btn\"
1145
                    href=\"$loginurl\"><span class=\"rui-login-btn-txt\">" .
1146
                    get_string('login') .
1147
                    '</span>
1148
                <svg class="ml-2"
1149
                    width="20"
1150
                    height="20"
1151
                    fill="none"
1152
                    viewBox="0 0 24 24">
1153
                <path stroke="currentColor"
1154
                    stroke-linecap="round"
1155
                    stroke-linejoin="round"
1156
                    stroke-width="2"
1157
                    d="M9.75 8.75L13.25 12L9.75 15.25"></path>
1158
                <path stroke="currentColor"
1159
                    stroke-linecap="round"
1160
                    stroke-linejoin="round"
1161
                    stroke-width="2"
1162
                    d="M9.75 4.75H17.25C18.3546 4.75 19.25 5.64543 19.25
1163
                    6.75V17.25C19.25 18.3546 18.3546 19.25 17.25 19.25H9.75"></path>
1164
                    <path stroke="currentColor"
1165
                        stroke-linecap="round"
1166
                        stroke-linejoin="round"
1167
                        stroke-width="2"
1168
                        d="M13 12H4.75"></path></svg></a>';
1169
            }
1170
 
1171
            return html_writer::div(
1172
                html_writer::span(
1173
                    $returnstr,
1174
                    'login'
1175
                ),
1176
                $usermenuclasses
1177
            );
1178
        }
1179
 
1180
        // Get some navigation opts.
1181
        $opts = user_get_user_navigation_info($user, $this->page, array('avatarsize' => 56));
1182
 
1183
        $avatarclasses = "avatars";
1184
        $avatarcontents = html_writer::span($opts->metadata['useravatar'], 'avatar current');
1185
        $usertextcontents = '<span class="rui-fullname">' . $opts->metadata['userfullname'] . '</span>';
1186
        $usertextmail = $user->email;
1187
        $usernick = '<svg class="mr-1"
1188
            width="16"
1189
            height="16"
1190
            fill="none"
1191
            viewBox="0 0 24 24">
1192
        <path stroke="currentColor"
1193
            stroke-linecap="round"
1194
            stroke-linejoin="round"
1195
            stroke-width="2"
1196
            d="M12 13V15"></path>
1197
        <circle cx="12"
1198
            cy="9"
1199
            r="1"
1200
            fill="currentColor"></circle>
1201
        <circle cx="12"
1202
            cy="12"
1203
            r="7.25"
1204
            stroke="currentColor"
1205
            stroke-linecap="round"
1206
            stroke-linejoin="round"
1207
            stroke-width="1.5"></circle>
1208
        </svg>' . $user->username;
1209
 
1210
        // Other user.
1211
        $usermeta = '';
1212
        if (!empty($opts->metadata['asotheruser'])) {
1213
            $avatarcontents .= html_writer::span(
1214
                $opts->metadata['realuseravatar'],
1215
                'avatar realuser'
1216
            );
1217
            $usermeta .= $opts->metadata['realuserfullname'];
1218
            $usermeta .= html_writer::tag(
1219
                'span',
1220
                get_string(
1221
                    'loggedinas',
1222
                    'moodle',
1223
                    html_writer::span(
1224
                        $opts->metadata['userfullname'],
1225
                        'value'
1226
                    )
1227
                ),
1228
                array('class' => 'meta viewingas')
1229
            );
1230
        }
1231
 
1232
        // Role.
1233
        if (!empty($opts->metadata['asotherrole'])) {
1234
            $role = core_text::strtolower(preg_replace('#[ ]+#', '-', trim($opts->metadata['rolename'])));
1235
            $usermeta .= html_writer::span(
1236
                $opts->metadata['rolename'],
1237
                'meta role role-' . $role
1238
            );
1239
        }
1240
 
1241
        // User login failures.
1242
        if (!empty($opts->metadata['userloginfail'])) {
1243
            $usermeta .= html_writer::div(
1244
                '<svg class="mr-1"
1245
                width="16"
1246
                height="16"
1247
                fill="none"
1248
                viewBox="0 0 24 24"><path stroke="currentColor"
1249
                stroke-linecap="round"
1250
                stroke-linejoin="round"
1251
                stroke-width="1.5"
1252
                d="M4.9522 16.3536L10.2152 5.85658C10.9531 4.38481 13.0539
1253
                4.3852 13.7913 5.85723L19.0495 16.3543C19.7156 17.6841 18.7487
1254
                19.25 17.2613 19.25H6.74007C5.25234
1255
                19.25 4.2854 17.6835 4.9522 16.3536Z">
1256
                </path><path stroke="currentColor"
1257
                stroke-linecap="round"
1258
                stroke-linejoin="round"
1259
                stroke-width="2"
1260
                d="M12 10V12"></path>
1261
                <circle cx="12" cy="16" r="1" fill="currentColor"></circle></svg>' .
1262
                    $opts->metadata['userloginfail'],
1263
                'meta loginfailures'
1264
            );
1265
        }
1266
 
1267
        // MNet.
1268
        if (!empty($opts->metadata['asmnetuser'])) {
1269
            $mnet = strtolower(preg_replace('#[ ]+#', '-', trim($opts->metadata['mnetidprovidername'])));
1270
            $usermeta .= html_writer::span(
1271
                $opts->metadata['mnetidprovidername'],
1272
                'meta mnet mnet-' . $mnet
1273
            );
1274
        }
1275
 
1276
        $returnstr .= html_writer::span(
1277
            html_writer::span($avatarcontents, $avatarclasses),
1278
            'userbutton'
1279
        );
1280
 
1281
        // Create a divider (well, a filler).
1282
        $divider = new action_menu_filler();
1283
        $divider->primary = false;
1284
 
1285
        $am = new action_menu();
1286
        $am->set_menu_trigger(
1287
            $returnstr
1288
        );
1289
        $am->set_action_label(get_string('usermenu'));
1290
        $am->set_nowrap_on_items();
1291
 
1292
        if ($CFG->enabledashboard) {
1293
            $dashboardlink = '<div class="dropdown-item-wrapper"><a class="dropdown-item" href="' .
1294
                new moodle_url('/my/') .
1295
                '" data-identifier="dashboard,moodle" title="dashboard,moodle">' .
1296
                get_string('myhome', 'moodle') .
1297
                '</a></div>';
1298
        } else {
1299
            $dashboardlink = null;
1300
        }
1301
 
1302
        $am->add(
1303
            '<div class="dropdown-user-wrapper"><div class="dropdown-user">' . $usertextcontents  . '</div>'
1304
                . '<div class="dropdown-user-mail text-truncate" title="' . $usertextmail . '">' . $usertextmail . '</div>'
1305
                . '<span class="dropdown-user-nick w-100">' . $usernick . '</span>'
1306
                . '<div class="dropdown-user-meta"><span class="badge-xs badge-sq badge-warning flex-wrap">' .
1307
                $usermeta . '</span></div>'
1308
                . '</div><div class="dropdown-divider dropdown-divider-user"></div>' . $dashboardlink
1309
        );
1310
 
1311
        if ($withlinks) {
1312
            $navitemcount = count($opts->navitems);
1313
            $idx = 0;
1314
            foreach ($opts->navitems as $key => $value) {
1315
 
1316
                switch ($value->itemtype) {
1317
                    case 'divider':
1318
                        // If the nav item is a divider, add one and skip link processing.
1319
                        $am->add($divider);
1320
                        break;
1321
 
1322
                    case 'invalid':
1323
                        // Silently skip invalid entries (should we post a notification?).
1324
                        break;
1325
 
1326
                    case 'link':
1327
                        $al = '<a class="dropdown-item" href="' .
1328
                            $value->url .
1329
                            '" data-identifier="' .
1330
                            $value->titleidentifier .
1331
                            '" title="' .
1332
                            $value->titleidentifier .
1333
                            '">' .
1334
                            $value->title . '</a>';
1335
                        $am->add($al);
1336
                        break;
1337
                }
1338
 
1339
                $idx++;
1340
 
1341
                // Add dividers after the first item and before the last item.
1342
                if ($idx == 1 || $idx == $navitemcount - 1) {
1343
                    $am->add($divider);
1344
                }
1345
            }
1346
        }
1347
 
1348
        return html_writer::div(
1349
            $this->render($am),
1350
            $usermenuclasses
1351
        );
1352
    }
1353
 
1354
 
1355
    /**
1356
     * Returns standard main content placeholder.
1357
     * Designed to be called in theme layout.php files.
1358
     *
1359
     * @return string HTML fragment.
1360
     */
1361
    public function main_content() {
1362
        // This is here because it is the only place we can inject the "main" role over the entire main content area
1363
        // without requiring all theme's to manually do it, and without creating yet another thing people need to
1364
        // remember in the theme.
1365
        // This is an unfortunate hack. DO NO EVER add anything more here.
1366
        // DO NOT add classes.
1367
        // DO NOT add an id.
1368
        return '<div class="main-content" role="main">' . $this->unique_main_content_token . '</div>';
1369
    }
1370
 
1371
    /**
1372
     * Outputs a heading
1373
     *
1374
     * @param string $text The text of the heading
1375
     * @param int $level The level of importance of the heading. Defaulting to 2
1376
     * @param string $classes A space-separated list of CSS classes. Defaulting to null
1377
     * @param string $id An optional ID
1378
     * @return string the HTML to output.
1379
     */
1380
    public function heading($text, $level = 2, $classes = null, $id = null) {
1381
        $level = (int) $level;
1382
        if ($level < 1 || $level > 6) {
1383
            throw new coding_exception('Heading level must be an integer between 1 and 6.');
1384
        }
1385
        return html_writer::tag('div', html_writer::tag('h' .
1386
            $level, $text, array('id' => $id, 'class' => renderer_base::prepare_classes($classes) .
1387
            ' rui-main-content-title rui-main-content-title--h' .
1388
            $level)), array('class' => 'rui-title-container'));
1389
    }
1390
 
1391
 
1392
    public function headingwithavatar($text, $level = 2, $classes = null, $id = null) {
1393
        $level = (int) $level;
1394
        if ($level < 1 || $level > 6) {
1395
            throw new coding_exception('Heading level must be an integer between 1 and 6.');
1396
        }
1397
        return html_writer::tag('div', html_writer::tag('h' .
1398
            $level, $text, array('id' => $id, 'class' => renderer_base::prepare_classes($classes) .
1399
            ' rui-main-content-title-with-avatar')), array('class' => 'rui-title-container-with-avatar'));
1400
    }
1401
 
1402
    /**
1403
     * Renders the login form.
1404
     *
1405
     * @param \core_auth\output\login $form The renderable.
1406
     * @return string
1407
     */
1408
    public function render_login(\core_auth\output\login $form) {
1409
        global $CFG, $SITE;
1410
 
1411
        $context = $form->export_for_template($this);
1412
 
1413
        // Override because rendering is not supported in template yet.
1414
        if ($CFG->rememberusername == 0) {
1415
            $context->cookieshelpiconformatted = $this->help_icon('cookiesenabledonlysession');
1416
        } else {
1417
            $context->cookieshelpiconformatted = $this->help_icon('cookiesenabled');
1418
        }
1419
        $context->errorformatted = $this->error_text($context->error);
1420
        $url = $this->get_logo_url();
1421
        if ($url) {
1422
            $url = $url->out(false);
1423
        }
1424
        $context->logourl = $url;
1425
        $context->sitename = format_string(
1426
            $SITE->fullname,
1427
            true,
1428
            ['context' => context_course::instance(SITEID), "escape" => false]
1429
        );
1430
 
1431
        if ($this->page->theme->settings->setloginlayout == 1) {
1432
            $context->loginlayout1 = 1;
1433
        } else if ($this->page->theme->settings->setloginlayout == 2) {
1434
            $context->loginlayout2 = 1;
1435
            if (isset($this->page->theme->settings->loginbg)) {
1436
                $context->loginlayoutimg = 1;
1437
            }
1438
        } else if ($this->page->theme->settings->setloginlayout == 3) {
1439
            $context->loginlayout3 = 1;
1440
            if (isset($this->page->theme->settings->loginbg)) {
1441
                $context->loginlayoutimg = 1;
1442
            }
1443
        } else if ($this->page->theme->settings->setloginlayout == 4) {
1444
            $context->loginlayout4 = 1;
1445
        } else if ($this->page->theme->settings->setloginlayout == 5) {
1446
            $context->loginlayout5 = 1;
1447
        }
1448
 
1449
        if (isset($this->page->theme->settings->loginlogooutside)) {
1450
            $context->loginlogooutside = $this->page->theme->settings->loginlogooutside;
1451
        }
1452
 
1453
        if (isset($this->page->theme->settings->customsignupoutside)) {
1454
            $context->customsignupoutside = $this->page->theme->settings->customsignupoutside;
1455
        }
1456
 
1457
        if (isset($this->page->theme->settings->loginidprovtop)) {
1458
            $context->loginidprovtop = $this->page->theme->settings->loginidprovtop;
1459
        }
1460
 
1461
        if (isset($this->page->theme->settings->stringca)) {
1462
            $context->stringca = format_text(($this->page->theme->settings->stringca),
1463
                FORMAT_HTML,
1464
                array('noclean' => true)
1465
            );
1466
        }
1467
 
1468
        if (isset($this->page->theme->settings->stringca)) {
1469
            $context->stringca = format_text(($this->page->theme->settings->stringca),
1470
                FORMAT_HTML,
1471
                array('noclean' => true)
1472
            );
1473
        }
1474
 
1475
        if (isset($this->page->theme->settings->loginhtmlcontent1)) {
1476
            $context->loginhtmlcontent1 = format_text(($this->page->theme->settings->loginhtmlcontent1),
1477
                FORMAT_HTML,
1478
                array('noclean' => true)
1479
            );
1480
        }
1481
 
1482
        if (isset($this->page->theme->settings->loginhtmlcontent2)) {
1483
            $context->loginhtmlcontent2 = format_text(($this->page->theme->settings->loginhtmlcontent2),
1484
                FORMAT_HTML,
1485
                array('noclean' => true)
1486
            );
1487
        }
1488
 
1489
        if (isset($this->page->theme->settings->loginhtmlcontent3)) {
1490
            $context->loginhtmlcontent3 = format_text(($this->page->theme->settings->loginhtmlcontent3),
1491
                FORMAT_HTML,
1492
                array('noclean' => true)
1493
            );
1494
        }
1495
 
1496
        if (isset($this->page->theme->settings->loginhtmlcontent2)) {
1497
            $context->loginhtmlcontent2 = format_text(($this->page->theme->settings->loginhtmlcontent2),
1498
                FORMAT_HTML,
1499
                array('noclean' => true)
1500
            );
1501
        }
1502
 
1503
        if (isset($this->page->theme->settings->logincustomfooterhtml)) {
1504
            $context->logincustomfooterhtml = format_text(($this->page->theme->settings->logincustomfooterhtml),
1505
                FORMAT_HTML,
1506
                array('noclean' => true)
1507
            );
1508
        }
1509
 
1510
        if (isset($this->page->theme->settings->loginhtmlblockbottom)) {
1511
            $context->loginhtmlblockbottom = format_text(($this->page->theme->settings->loginhtmlblockbottom),
1512
                FORMAT_HTML,
1513
                array('noclean' => true)
1514
            );
1515
        }
1516
 
1517
        if (isset($this->page->theme->settings->loginfootercontent)) {
1518
            $context->loginfootercontent = format_text(($this->page->theme->settings->loginfootercontent),
1519
                FORMAT_HTML,
1520
                array('noclean' => true)
1521
            );
1522
        }
1523
 
1524
        if (isset($this->page->theme->settings->footercopy)) {
1525
            $context->footercopy = format_text(($this->page->theme->settings->footercopy),
1526
                FORMAT_HTML,
1527
                array('noclean' => true)
1528
            );
1529
        }
1530
 
1531
        if (isset($this->page->theme->settings->loginintrotext)) {
1532
            $context->loginintrotext = format_text(($this->page->theme->settings->loginintrotext),
1533
                FORMAT_HTML,
1534
                array('noclean' => true)
1535
            );
1536
        }
1537
 
1538
        if (isset($this->page->theme->settings->loginintrotext)) {
1539
            $context->loginintrotext = format_text(($this->page->theme->settings->loginintrotext),
1540
                FORMAT_HTML,
1541
                array('noclean' => true)
1542
            );
1543
        }
1544
 
1545
        if (isset($this->page->theme->settings->customloginlogo)) {
1546
            $context->customloginlogo = $this->page->theme->setting_file_url('customloginlogo', 'customloginlogo');
1547
        }
1548
 
1549
        if (isset($this->page->theme->settings->loginbg)) {
1550
            $context->loginbg = $this->page->theme->setting_file_url('loginbg', 'loginbg');
1551
        }
1552
 
1553
        if (isset($this->page->theme->settings->hideforgotpassword)) {
1554
            $context->hideforgotpassword = $this->page->theme->settings->hideforgotpassword == 1;
1555
        }
1556
 
1557
        if (isset($this->page->theme->settings->logininfobox)) {
1558
            $context->logininfobox = format_text(($this->page->theme->settings->logininfobox),
1559
                FORMAT_HTML,
1560
                array('noclean' => true)
1561
            );
1562
        }
1563
 
1564
        return $this->render_from_template('core/loginform', $context);
1565
    }
1566
 
1567
    /**
1568
     * Render the login signup form into a nice template for the theme.
1569
     *
1570
     * @param mform $form
1571
     * @return string
1572
     */
1573
    public function render_login_signup_form($form) {
1574
        global $SITE;
1575
 
1576
        $context = $form->export_for_template($this);
1577
        $url = $this->get_logo_url();
1578
        if ($url) {
1579
            $url = $url->out(false);
1580
        }
1581
        $context['logourl'] = $url;
1582
        $context['sitename'] = format_string(
1583
            $SITE->fullname,
1584
            true,
1585
            ['context' => context_course::instance(SITEID), "escape" => false]
1586
        );
1587
 
1588
        if ($this->page->theme->settings->setloginlayout == 1) {
1589
            $context['loginlayout1'] = 1;
1590
        } else if ($this->page->theme->settings->setloginlayout == 2) {
1591
            $context['loginlayout2'] = 1;
1592
            if (isset($this->page->theme->settings->loginbg)) {
1593
                $context['loginlayoutimg'] = 1;
1594
            }
1595
        } else if ($this->page->theme->settings->setloginlayout == 3) {
1596
            $context['loginlayout3'] = 1;
1597
            if (isset($this->page->theme->settings->loginbg)) {
1598
                $context['loginlayoutimg'] = 1;
1599
            }
1600
        } else if ($this->page->theme->settings->setloginlayout == 4) {
1601
            $context['loginlayout4'] = 1;
1602
        } else if ($this->page->theme->settings->setloginlayout == 5) {
1603
            $context['loginlayout5'] = 1;
1604
        }
1605
 
1606
        if (isset($this->page->theme->settings->loginlogooutside)) {
1607
            $context['loginlogooutside'] = $this->page->theme->settings->loginlogooutside;
1608
        }
1609
 
1610
        if (isset($this->page->theme->settings->stringbacktologin)) {
1611
            $context['stringbacktologin'] = format_text(($this->page->theme->settings->stringbacktologin),
1612
                FORMAT_HTML,
1613
                array('noclean' => true)
1614
            );
1615
        }
1616
        if (isset($this->page->theme->settings->signupintrotext)) {
1617
            $context['signupintrotext'] = format_text(($this->page->theme->settings->signupintrotext),
1618
                FORMAT_HTML,
1619
                array('noclean' => true)
1620
            );
1621
        }
1622
        if (isset($this->page->theme->settings->signuptext)) {
1623
            $context['signuptext'] = format_text(($this->page->theme->settings->signuptext),
1624
                FORMAT_HTML,
1625
                array('noclean' => true)
1626
            );
1627
        }
1628
 
1629
        if (!empty($this->page->theme->settings->customloginlogo)) {
1630
            $url = $this->page->theme->setting_file_url('customloginlogo', 'customloginlogo');
1631
            $context['customloginlogo'] = $url;
1632
        }
1633
 
1634
        if (!empty($this->page->theme->settings->loginbg)) {
1635
            $url = $this->page->theme->setting_file_url('loginbg', 'loginbg');
1636
            $context['loginbg'] = $url;
1637
        }
1638
 
1639
        if (isset($this->page->theme->settings->loginfootercontent)) {
1640
            $context['loginfootercontent'] = format_text(($this->page->theme->settings->loginfootercontent),
1641
                FORMAT_HTML,
1642
                array('noclean' => true)
1643
            );
1644
        }
1645
 
1646
        return $this->render_from_template('core/signup_form_layout', $context);
1647
    }
1648
 
1649
 
1650
    /**
1651
     * Renders the header bar.
1652
     *
1653
     * @param context_header $contextheader Header bar object.
1654
     * @return string HTML for the header bar.
1655
     */
1656
    protected function render_context_header(\context_header $contextheader) {
1657
        $heading = null;
1658
        $imagedata = null;
1659
        $html = null;
1660
 
1661
        // Generate the heading first and before everything else as we might have to do an early return.
1662
        if (!isset($contextheader->heading)) {
1663
            $heading = $this->heading($this->page->heading, $contextheader->headinglevel);
1664
        } else {
1665
            $heading = $this->heading($contextheader->heading, $contextheader->headinglevel);
1666
        }
1667
 
1668
        // All the html stuff goes here.
1669
        $html = html_writer::start_div('page-context-header d-flex align-items-center flex-wrap');
1670
 
1671
        // Image data.
1672
        if (isset($contextheader->imagedata)) {
1673
            // Header specific image.
1674
            $html .= html_writer::div($contextheader->imagedata, 'page-header-image');
1675
        }
1676
 
1677
        // Headings.
1678
        if (isset($contextheader->prefix)) {
1679
            $prefix = html_writer::div($contextheader->prefix, 'text-muted text-uppercase small line-height-3');
1680
            $heading = $prefix . $heading;
1681
        }
1682
 
1683
        if (!isset($contextheader->heading)) {
1684
            $html .= html_writer::tag('h3', $heading, array('class' => 'rui-page-title rui-page-title--page'));
1685
        } else if (isset($contextheader->imagedata)) {
1686
            $html .= html_writer::tag(
1687
                'div',
1688
                $this->heading($contextheader->heading, 4),
1689
                array('class' => 'rui-page-title rui-page-title--icon')
1690
            );
1691
        } else {
1692
            $html .= html_writer::tag('h2', $heading, array('class' => 'page-header-headings
1693
                rui-page-title rui-page-title--context'));
1694
        }
1695
 
1696
        // Buttons.
1697
        if (isset($contextheader->additionalbuttons)) {
1698
            $html .= html_writer::start_div('btn-group header-button-group my-2 my-lg-0 ml-lg-4');
1699
            foreach ($contextheader->additionalbuttons as $button) {
1700
                if (!isset($button->page)) {
1701
                    // Include js for messaging.
1702
                    if ($button['buttontype'] === 'togglecontact') {
1703
                        \core_message\helper::togglecontact_requirejs();
1704
                    }
1705
                    if ($button['buttontype'] === 'message') {
1706
                        \core_message\helper::messageuser_requirejs();
1707
                    }
1708
                    $image = $this->pix_icon($button['formattedimage'], $button['title'], 'moodle', array(
1709
                        'class' => 'iconsmall',
1710
                        'role' => 'presentation'
1711
                    ));
1712
                    $image .= html_writer::span($button['title'], 'header-button-title');
1713
                } else {
1714
                    $image = html_writer::empty_tag('img', array(
1715
                        'src' => $button['formattedimage'],
1716
                        'role' => 'presentation'
1717
                    ));
1718
                }
1719
                $html .= html_writer::link($button['url'], html_writer::tag('span', $image), $button['linkattributes']);
1720
            }
1721
            $html .= html_writer::end_div();
1722
        }
1723
        $html .= html_writer::end_div();
1724
 
1725
        return $html;
1726
    }
1727
 
1728
    public function header() {
1729
        global $USER, $COURSE;
1730
        $theme = theme_config::load('universe');
1731
 
1732
        $context = context_course::instance($COURSE->id);
1733
        $roles = get_user_roles($context, $USER->id, true);
1734
 
1735
        if (is_array($roles) && !empty($roles)) {
1736
            foreach ($roles as $role) {
1737
                $this->page->add_body_class('role-' . $role->shortname);
1738
            }
1739
        } else {
1740
            $this->page->add_body_class('role-none');
1741
        }
1742
 
1743
        if ($theme->settings->topbareditmode == '1') {
1744
            $this->page->add_body_class('rui-editmode--top');
1745
        } else {
1746
            $this->page->add_body_class('rui-editmode--footer');
1747
        }
1748
 
1749
        return parent::header();
1750
    }
1751
 
1752
 
1753
    /**
1754
     * See if this is the first view of the current cm in the session if it has fake blocks.
1755
     *
1756
     * (We track up to 100 cms so as not to overflow the session.)
1757
     * This is done for drawer regions containing fake blocks so we can show blocks automatically.
1758
     *
1759
     * @return boolean true if the page has fakeblocks and this is the first visit.
1760
     */
1761
    public function firstview_fakeblocks(): bool {
1762
        global $SESSION;
1763
 
1764
        $firstview = false;
1765
        if ($this->page->cm) {
1766
            if (!$this->page->blocks->region_has_fakeblocks('side-pre')) {
1767
                return false;
1768
            }
1769
            if (!property_exists($SESSION, 'firstview_fakeblocks')) {
1770
                $SESSION->firstview_fakeblocks = [];
1771
            }
1772
            if (array_key_exists($this->page->cm->id, $SESSION->firstview_fakeblocks)) {
1773
                $firstview = false;
1774
            } else {
1775
                $SESSION->firstview_fakeblocks[$this->page->cm->id] = true;
1776
                $firstview = true;
1777
                if (count($SESSION->firstview_fakeblocks) > 100) {
1778
                    array_shift($SESSION->firstview_fakeblocks);
1779
                }
1780
            }
1781
        }
1782
        return $firstview;
1783
    }
1784
 
1785
 
1786
    /**
1787
     * Build the guest access hint HTML code.
1788
     *
1789
     * @param int $courseid The course ID.
1790
     * @return string.
1791
     */
1792
    public function theme_universe_get_course_guest_access_hint($courseid) {
1793
        global $CFG;
1794
        require_once($CFG->dirroot . '/enrol/self/lib.php');
1795
 
1796
        $html = '';
1797
        $instances = enrol_get_instances($courseid, true);
1798
        $plugins = enrol_get_plugins(true);
1799
        foreach ($instances as $instance) {
1800
            if (!isset($plugins[$instance->enrol])) {
1801
                continue;
1802
            }
1803
            $plugin = $plugins[$instance->enrol];
1804
            if ($plugin->show_enrolme_link($instance)) {
1805
                $html = html_writer::tag('div', get_string(
1806
                    'showhintcourseguestaccesssettinglink',
1807
                    'theme_universe',
1808
                    array('url' => $CFG->wwwroot . '/enrol/index.php?id=' . $courseid)
1809
                ));
1810
                break;
1811
            }
1812
        }
1813
 
1814
        return $html;
1815
    }
1816
 
1817
 
1818
    /**
1819
     * Color Customization
1820
     * @return string HTML fragment.
1821
     */
1822
    public function additional_head_html() {
1823
        global $SITE, $DB, $CFG, $COURSE, $PAGE;
1824
 
1825
        $output = null;
1826
 
1827
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
1828
            if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor1'), 'id')) {
1829
                // Get custom field by name
1830
                $customfieldid1 = $DB->get_record('customfield_field', array('shortname' => 'maincolor1'));
1831
                // Get value
1832
                $mainthemecolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid1->id, 'instanceid' => $COURSE->id));
1833
            } else {
1834
                $mainthemecolor = null;
1835
            }
1836
 
1837
            if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor2'), 'id')) {
1838
                $customfieldid2 = $DB->get_record('customfield_field', array('shortname' => 'maincolor2'));
1839
                $mainthemecolor2 = $DB->get_record('customfield_data', array('fieldid' => $customfieldid2->id, 'instanceid' => $COURSE->id));
1840
            }
1841
 
1842
            if ($DB->record_exists('customfield_field', array('shortname' => 'topbarcolor'), 'id')) {
1843
                // Get custom field by name
1844
                $customfieldid3 = $DB->get_record('customfield_field', array('shortname' => 'topbarcolor'));
1845
                // Get value
1846
                $topbarcolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid3->id, 'instanceid' => $COURSE->id));
1847
            }
1848
 
1849
            if ($DB->record_exists('customfield_field', array('shortname' => 'dmtopbarcolor'), 'id')) {
1850
                // Get custom field by name
1851
                $customfieldid3 = $DB->get_record('customfield_field', array('shortname' => 'dmtopbarcolor'));
1852
                // Get value
1853
                $dmtopbarcolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid3->id, 'instanceid' => $COURSE->id));
1854
            } else {
1855
                $dmtopbarcolor = null;
1856
            }
1857
 
1858
 
1859
            if ($DB->record_exists('customfield_field', array('shortname' => 'footerbgcolor'), 'id')) {
1860
                // Get custom field by name
1861
                $customfieldid4 = $DB->get_record('customfield_field', array('shortname' => 'footerbgcolor'));
1862
                // Get value
1863
                $footercolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid4->id, 'instanceid' => $COURSE->id));
1864
            } else {
1865
                $footercolor = null;
1866
            }
1867
 
1868
 
1869
            $css = '';
1870
 
1871
            $css .= ':root { ';
1872
            if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor1'), 'id')) {
1873
                if ($mainthemecolor != null) {
1874
                    $css .= '--main-theme-color: ' . $mainthemecolor->value . '; ';
1875
                    $css .= '--primary-color-100: ' . $mainthemecolor->value . '30; ';
1876
                    $css .= '--primary-color-300: ' . $mainthemecolor->value . '70; ';
1877
                    $css .= '--main-theme-color-gradient: ' . $mainthemecolor->value . '; ';
1878
                    $css .= '--btn-primary-color-bg: ' . $mainthemecolor->value . '; ';
1879
                    $css .= '--btn-primary-color-bg-hover: ' . $mainthemecolor->value . '95; ';
1880
 
1881
                    if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor2'), 'id')) {
1882
                        if ($mainthemecolor2 != null) {
1883
                            $css .= '--main-theme-color-gradient-2: ' . $mainthemecolor2->value . '; ';
1884
                        } else {
1885
                            $css .= '--main-theme-color-gradient-2: ' . $mainthemecolor->value . '30; ';
1886
                        }
1887
                    }
1888
                }
1889
            }
1890
 
1891
            if ($DB->record_exists('customfield_field', array('shortname' => 'topbarcolor'), 'id')) {
1892
                if ($topbarcolor != null) {
1893
                    $css .= '--topbar-color: ' . $topbarcolor->value . '; ';
1894
                    if ($dmtopbarcolor != null) {
1895
                        $css .= '--dm-topbar-color: ' . $dmtopbarcolor->value . '; ';
1896
                    } else {
1897
                        $css .= '--dm-topbar-color: ' . $topbarcolor->value . '; ';
1898
                    }
1899
                }
1900
            }
1901
 
1902
            if ($DB->record_exists('customfield_field', array('shortname' => 'footerbgcolor'), 'id')) {
1903
                if ($footercolor != null) {
1904
                    $css .= '--footer-color: ' . $footercolor->value . '; ';
1905
                }
1906
            }
1907
 
1908
            $css .= '}';
1909
 
1910
            if ($css) {
1911
                $output .= '<style>' . $css . '</style>';
1912
            }
1913
        }
1914
 
1915
        return $output;
1916
    }
1917
 
1918
    public function custom_course_logo() {
1919
        global $DB, $CFG, $COURSE, $PAGE;
1920
 
1921
        $output = null;
1922
 
1923
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
1924
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcourselogo'))) {
1925
                // Get custom field ID
1926
                $customfieldpic = $DB->get_record('customfield_field', array('shortname' => 'customcourselogo'));
1927
                $customfieldpicid = $customfieldpic->id;
1928
                // Get value
1929
                $customlogo = $DB->get_record(
1930
                    'customfield_data',
1931
                    array('fieldid' => $customfieldpicid, 'instanceid' => $COURSE->id)
1932
                );
1933
 
1934
                $customlogoid = $customlogo->id;
1935
                $contextid = $customlogo->contextid;
1936
 
1937
                if ($customfieldpic != null) {
1938
                    $files = get_file_storage()->get_area_files(
1939
                        $contextid,
1940
                        'customfield_picture',
1941
                        'file',
1942
                        $customlogoid,
1943
                        '',
1944
                        false
1945
                    );
1946
 
1947
                    if (empty($files)) {
1948
                        return null;
1949
                    }
1950
 
1951
                    $file = reset($files);
1952
                    $fileurl = moodle_url::make_pluginfile_url(
1953
                        $file->get_contextid(),
1954
                        $file->get_component(),
1955
                        $file->get_filearea(),
1956
                        $file->get_itemid(),
1957
                        $file->get_filepath(),
1958
                        $file->get_filename()
1959
                    );
1960
 
1961
                    $output .= $fileurl;
1962
                }
1963
            }
1964
        }
1965
 
1966
        return $output;
1967
    }
1968
 
1969
    public function custom_course_dmlogo() {
1970
        global $DB, $CFG, $COURSE, $PAGE;
1971
 
1972
        $output = null;
1973
 
1974
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
1975
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcoursedmlogo'))) {
1976
                // Get custom field ID
1977
                $customfieldpic = $DB->get_record('customfield_field', array('shortname' => 'customcoursedmlogo'));
1978
                $customfieldpicid = $customfieldpic->id;
1979
                // Get value
1980
                $customlogo = $DB->get_record(
1981
                    'customfield_data',
1982
                    array('fieldid' => $customfieldpicid, 'instanceid' => $COURSE->id)
1983
                );
1984
 
1985
                $customlogoid = $customlogo->id;
1986
                $contextid = $customlogo->contextid;
1987
 
1988
                if ($customfieldpic != null) {
1989
                    $files = get_file_storage()->get_area_files(
1990
                        $contextid,
1991
                        'customfield_picture',
1992
                        'file',
1993
                        $customlogoid,
1994
                        '',
1995
                        false
1996
                    );
1997
 
1998
                    if (empty($files)) {
1999
                        return null;
2000
                    }
2001
 
2002
                    $file = reset($files);
2003
                    $fileurl = moodle_url::make_pluginfile_url(
2004
                        $file->get_contextid(),
2005
                        $file->get_component(),
2006
                        $file->get_filearea(),
2007
                        $file->get_itemid(),
2008
                        $file->get_filepath(),
2009
                        $file->get_filename()
2010
                    );
2011
 
2012
                    $output .= $fileurl;
2013
                }
2014
            }
2015
        }
2016
 
2017
        return $output;
2018
    }
2019
 
2020
    public function custom_course_favicon() {
2021
        global $DB, $CFG, $COURSE, $PAGE;
2022
 
2023
        $output = null;
2024
 
2025
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
2026
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcoursefavicon'))) {
2027
                // Get custom field ID
2028
                $customfieldpic = $DB->get_record('customfield_field', array('shortname' => 'customcoursefavicon'));
2029
                $customfieldpicid = $customfieldpic->id;
2030
                // Get value
2031
                $customfavicon = $DB->get_record(
2032
                    'customfield_data',
2033
                    array('fieldid' => $customfieldpicid, 'instanceid' => $COURSE->id)
2034
                );
2035
 
2036
                $customfaviconid = $customfavicon->id;
2037
                $contextid = $customfavicon->contextid;
2038
 
2039
                if ($customfieldpic != null) {
2040
                    $files = get_file_storage()->get_area_files(
2041
                        $contextid,
2042
                        'customfield_picture',
2043
                        'file',
2044
                        $customfaviconid,
2045
                        '',
2046
                        false
2047
                    );
2048
 
2049
                    if (empty($files)) {
2050
                        return null;
2051
                    }
2052
 
2053
                    $file = reset($files);
2054
                    $fileurl = moodle_url::make_pluginfile_url(
2055
                        $file->get_contextid(),
2056
                        $file->get_component(),
2057
                        $file->get_filearea(),
2058
                        $file->get_itemid(),
2059
                        $file->get_filepath(),
2060
                        $file->get_filename()
2061
                    );
2062
 
2063
                    $output .= $fileurl;
2064
                }
2065
            }
2066
        }
2067
 
2068
        return $output;
2069
    }
2070
 
2071
    public function custom_course_name() {
2072
        global $DB, $CFG, $COURSE, $PAGE;
2073
 
2074
        $output = null;
2075
 
2076
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
2077
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcoursename'), 'id')) {
2078
                // Get custom field by name
2079
                $customfieldid = $DB->get_record('customfield_field', array('shortname' => 'customcoursename'));
2080
                // Get value
2081
                $customcoursename = $DB->get_record('customfield_data', array('fieldid' => $customfieldid->id, 'instanceid' => $COURSE->id));
2082
                if (!empty($customcoursename)) {
2083
                    $output .= $customcoursename->value;
2084
                }
2085
            } else {
2086
                $customcoursename = null;
2087
            }
2088
        }
2089
 
2090
        return $output;
2091
    }
2092
 
2093
        /**
2094
     * Get the course pattern datauri to show on a course card.
2095
     *
2096
     * The datauri is an encoded svg that can be passed as a url.
2097
     * @param int $id Id to use when generating the pattern
2098
     * @return string datauri
2099
     */
2100
    public function get_generated_image_for_id($id) {
2101
        global $CFG;
2102
 
2103
        $theme = \theme_config::load('universe');
2104
        // Add custom course cover.
2105
        $customcover = $theme->setting_file_url('defaultcourseimg', 'defaultcourseimg');
2106
 
2107
        if (!empty(($customcover))) {
2108
            $urlreplace = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2109
            $customcover = str_replace($urlreplace, '', $customcover);
2110
            $txt = new moodle_url($customcover);
2111
            return strval($txt);
2112
        } else {
2113
            $color = $this->get_generated_color_for_id($id);
2114
            $pattern = new \core_geopattern();
2115
            $pattern->setColor($color);
2116
            $pattern->patternbyid($id);
2117
            return $pattern->datauri();
2118
        }
2119
    }
2120
 
2121
    public function moremenu_group_item () {
2122
        global $CFG, $COURSE;
2123
 
2124
        $theme = \theme_config::load('universe');
2125
        $courseid = $COURSE->id;
2126
        $sitehomeurl = new moodle_url('/');
2127
 
2128
        if ($this->page->theme->settings->secnavgroupitem == 1) {
2129
            if (has_capability('moodle/course:managegroups', \context_course::instance($COURSE->id))) {
2130
                $html = $sitehomeurl . "group/index.php?id=" . $courseid;
2131
                return $html;
2132
            }
2133
        }
2134
 
2135
    }
2136
 
2137
    public function moremenu_custom_items () {
2138
        global $CFG, $COURSE, $USER;
2139
 
2140
        $theme = \theme_config::load('universe');
2141
        $html = '';
2142
        $secnavcount = theme_universe_get_setting('secnavitemscount');
2143
 
2144
        // Get current user role ID.
2145
        $context = context_course::instance($COURSE->id);
2146
        $roles = get_user_roles($context, $USER->id, true);
2147
        $role = 999;
2148
        $roleid = 999;
2149
        $role = key($roles);
2150
        if ($role != null) {
2151
            $roleid = $roles[$role]->roleid;
2152
        }
2153
 
2154
        // End.
2155
 
2156
        if ($this->page->theme->settings->secnavitems == 1) {
2157
 
2158
            $secnav = new stdClass();
2159
            for ($i = 1; $i <= $secnavcount; $i++) {
2160
                $secnav->title = theme_universe_get_setting("secnavcustomnavlabel" . $i);
2161
 
2162
                $url = theme_universe_get_setting("secnavcustomnavurl" . $i);
2163
                $courseid = $COURSE->id;
2164
                $newurl = str_replace("{{courseID}}", $courseid, $url);
2165
 
2166
                // User role restriction.
2167
                $selectrole = theme_universe_get_setting("secnavuserroles" . $i);
2168
 
2169
                if($roleid == $selectrole) {
2170
                    $secnav->url = $newurl;
2171
                    $html .= $this->render_from_template('theme_universe/custom_sec_nav_item', $secnav);
2172
                }
2173
                if($roleid != $selectrole) {
2174
                    $secnav->url = $newurl;
2175
                }
2176
                if($selectrole == 0) {
2177
                    $secnav->url = $newurl;
2178
                    $html .= $this->render_from_template('theme_universe/custom_sec_nav_item', $secnav);
2179
                }
2180
                // End.
2181
 
2182
            }
2183
        }
2184
        return $html;
2185
    }
2186
 
2187
}