Proyectos de Subversion Moodle

Rev

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