Proyectos de Subversion Moodle

Rev

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