Proyectos de Subversion Moodle

Rev

Rev 1 | Rev 168 | 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
 
593
    /**
594
     * Breadcrumbs
595
     *
596
     */
161 ariadna 597
    public function breadcrumbs()
598
    {
1 efrain 599
        global $USER, $COURSE, $CFG;
600
 
601
        $header = new stdClass();
602
        $header->hasnavbar = empty($this->page->layout_options['nonavbar']);
603
        $header->navbar = $this->navbar();
604
        $header->courseheader = $this->course_header();
605
        $html = $this->render_from_template('theme_universe/breadcrumbs', $header);
606
 
607
        return $html;
608
    }
609
 
610
 
611
    /**
612
     * Wrapper for header elements.
613
     *
614
     * @return string HTML to display the main header.
615
     */
161 ariadna 616
    public function simple_header()
617
    {
1 efrain 618
 
619
        global $USER, $COURSE, $CFG;
620
        $html = null;
621
 
622
        if (
623
            $this->page->include_region_main_settings_in_header_actions() &&
624
            !$this->page->blocks->is_block_present('settings')
625
        ) {
626
            // Only include the region main settings if the page has requested it and it doesn't already have
627
            // the settings block on it. The region main settings are included in the settings block and
628
            // duplicating the content causes behat failures.
629
            $this->page->add_header_action(html_writer::div(
630
                $this->region_main_settings_menu(),
631
                'd-print-none',
632
                ['id' => 'region-main-settings-menu']
633
            ));
634
        }
635
 
636
        $header = new stdClass();
637
        $header->settingsmenu = $this->context_header_settings_menu();
638
        $header->contextheader = $this->context_header();
639
        $header->hasnavbar = empty($this->page->layout_options['nonavbar']);
640
        $header->navbar = $this->navbar();
641
        $header->pageheadingbutton = $this->page_heading_button();
642
        $header->courseheader = $this->course_header();
643
        $header->headeractions = $this->page->get_header_actions();
644
 
645
        if ($this->page->pagelayout != 'admin') {
646
            $html .= $this->render_from_template('theme_universe/header', $header);
647
        }
648
 
649
        if ($this->page->pagelayout == 'admin') {
650
            $html .= $this->render_from_template('theme_universe/header_admin', $header);
651
        }
652
 
653
        return $html;
654
    }
655
 
656
 
657
 
658
 
161 ariadna 659
    public function display_course_progress()
660
    {
1 efrain 661
        $html = null;
662
        $html .= $this->courseprogress($this->page->course);
663
        return $html;
664
    }
665
 
666
    /**
667
     * Wrapper for header elements.
668
     *
669
     * @return string HTML to display the main header.
670
     */
161 ariadna 671
    public function full_header()
672
    {
1 efrain 673
        global $USER, $COURSE, $CFG;
674
        $theme = \theme_config::load('universe');
675
        $html = null;
676
        $pagetype = $this->page->pagetype;
677
        $homepage = get_home_page();
678
        $homepagetype = null;
679
        // Add a special case since /my/courses is a part of the /my subsystem.
680
        if ($homepage == HOMEPAGE_MY || $homepage == HOMEPAGE_MYCOURSES) {
681
            $homepagetype = 'my-index';
682
        } else if ($homepage == HOMEPAGE_SITE) {
683
            $homepagetype = 'site-index';
684
        }
685
        if (
686
            $this->page->include_region_main_settings_in_header_actions() &&
687
            !$this->page->blocks->is_block_present('settings')
688
        ) {
689
            // Only include the region main settings if the page has requested it and it doesn't already have
690
            // the settings block on it. The region main settings are included in the settings block and
691
            // duplicating the content causes behat failures.
692
            $this->page->add_header_action(html_writer::div(
693
                $this->region_main_settings_menu(),
694
                'd-print-none',
695
                ['id' => 'region-main-settings-menu']
696
            ));
697
        }
698
 
699
        $header = new stdClass();
700
        $header->settingsmenu = $this->context_header_settings_menu();
701
        $header->contextheader = $this->context_header();
702
        $header->hasnavbar = empty($this->page->layout_options['nonavbar']);
703
        $header->navbar = $this->navbar();
704
        $header->pageheadingbutton = $this->page_heading_button();
705
        $header->courseheader = $this->course_header();
706
        $header->headeractions = $this->page->get_header_actions();
707
 
708
        if ($this->page->theme->settings->ipcoursedetails == 1) {
709
            $html .= $this->course_details();
710
        }
711
 
712
        $html .= $this->render_from_template('theme_universe/header', $header);
713
        if ($this->page->theme->settings->ipcoursesummary == 1) {
714
            $html .= $this->course_summary();
715
        }
716
 
717
        $html .= html_writer::start_tag('div', array('class' => 'rui-course-header-color'));
718
        if ($this->page->theme->settings->cccteachers == 1) {
719
            $html .= $this->course_teachers();
720
        }
721
 
722
        $html .= html_writer::end_tag('div'); // End .rui-course-header.
723
 
724
        return $html;
725
    }
726
 
727
 
728
    /**
729
     * Wrapper for header elements.
730
     *
731
     * @return string HTML to display the main header.
732
     */
161 ariadna 733
    public function clean_header()
734
    {
1 efrain 735
        global $USER, $COURSE, $CFG;
736
        $theme = \theme_config::load('universe');
737
        $html = null;
738
        $pagetype = $this->page->pagetype;
739
        $homepage = get_home_page();
740
        $homepagetype = null;
741
        // Add a special case since /my/courses is a part of the /my subsystem.
742
        if ($homepage == HOMEPAGE_MY || $homepage == HOMEPAGE_MYCOURSES) {
743
            $homepagetype = 'my-index';
744
        } else if ($homepage == HOMEPAGE_SITE) {
745
            $homepagetype = 'site-index';
746
        }
747
        if (
748
            $this->page->include_region_main_settings_in_header_actions() &&
749
            !$this->page->blocks->is_block_present('settings')
750
        ) {
751
            // Only include the region main settings if the page has requested it and it doesn't already have
752
            // the settings block on it. The region main settings are included in the settings block and
753
            // duplicating the content causes behat failures.
754
            $this->page->add_header_action(html_writer::div(
755
                $this->region_main_settings_menu(),
756
                'd-print-none',
757
                ['id' => 'region-main-settings-menu']
758
            ));
759
        }
760
 
761
        $header = new stdClass();
762
        $header->courseheader = $this->course_header();
763
        $header->headeractions = $this->page->get_header_actions();
764
 
765
        $html .= $this->render_from_template('theme_universe/header', $header);
766
 
767
        return $html;
768
    }
769
 
770
 
771
    /**
772
     * Returns standard navigation between activities in a course.
773
     *
774
     * @return string the navigation HTML.
775
     */
161 ariadna 776
    public function activity_navigation()
777
    {
1 efrain 778
        // First we should check if we want to add navigation.
779
        $context = $this->page->context;
780
        if (($this->page->pagelayout !== 'incourse' && $this->page->pagelayout !== 'frametop')
781
            || $context->contextlevel != CONTEXT_MODULE
782
        ) {
783
            return '';
784
        }
785
        // If the activity is in stealth mode, show no links.
786
        if ($this->page->cm->is_stealth()) {
787
            return '';
788
        }
789
        $course = $this->page->cm->get_course();
790
        $courseformat = course_get_format($course);
791
 
792
        // Get a list of all the activities in the course.
793
        $modules = get_fast_modinfo($course->id)->get_cms();
794
        // Put the modules into an array in order by the position they are shown in the course.
795
        $mods = [];
796
        $activitylist = [];
797
        foreach ($modules as $module) {
798
            // Only add activities the user can access, aren't in stealth mode and have a url (eg. mod_label does not).
799
            if (!$module->uservisible || $module->is_stealth() || empty($module->url)) {
800
                continue;
801
            }
802
            $mods[$module->id] = $module;
803
            // No need to add the current module to the list for the activity dropdown menu.
804
            if ($module->id == $this->page->cm->id) {
805
                continue;
806
            }
807
            // Module name.
808
            $modname = $module->get_formatted_name();
809
            // Display the hidden text if necessary.
810
            if (!$module->visible) {
811
                $modname .= ' ' . get_string('hiddenwithbrackets');
812
            }
813
            // Module URL.
814
            $linkurl = new moodle_url($module->url, array('forceview' => 1));
815
            // Add module URL (as key) and name (as value) to the activity list array.
816
            $activitylist[$linkurl->out(false)] = $modname;
817
        }
818
        $nummods = count($mods);
819
        // If there is only one mod then do nothing.
820
        if ($nummods == 1) {
821
            return '';
822
        }
823
        // Get an array of just the course module ids used to get the cmid value based on their position in the course.
824
        $modids = array_keys($mods);
825
        // Get the position in the array of the course module we are viewing.
826
        $position = array_search($this->page->cm->id, $modids);
827
        $prevmod = null;
828
        $nextmod = null;
829
        // Check if we have a previous mod to show.
830
        if ($position > 0) {
831
            $prevmod = $mods[$modids[$position - 1]];
832
        }
833
        // Check if we have a next mod to show.
834
        if ($position < ($nummods - 1)) {
835
            $nextmod = $mods[$modids[$position + 1]];
836
        }
837
        $activitynav = new \core_course\output\activity_navigation($prevmod, $nextmod, $activitylist);
838
        $renderer = $this->page->get_renderer('core', 'course');
839
        return $renderer->render($activitynav);
840
    }
841
 
842
 
843
    /**
844
     * This is an optional menu that can be added to a layout by a theme. It contains the
845
     * menu for the course administration, only on the course main page.
846
     *
847
     * @return string
848
     */
161 ariadna 849
    public function context_header_settings_menu()
850
    {
1 efrain 851
        $context = $this->page->context;
852
        $menu = new action_menu();
853
 
854
        $items = $this->page->navbar->get_items();
855
        $currentnode = end($items);
856
 
857
        $showcoursemenu = false;
858
        $showfrontpagemenu = false;
859
        $showusermenu = false;
860
 
861
        // We are on the course home page.
862
        if (($context->contextlevel == CONTEXT_COURSE) &&
863
            !empty($currentnode) &&
864
            ($currentnode->type == navigation_node::TYPE_COURSE || $currentnode->type == navigation_node::TYPE_SECTION)
865
        ) {
866
            $showcoursemenu = true;
867
        }
868
 
869
        $courseformat = course_get_format($this->page->course);
870
        // This is a single activity course format, always show the course menu on the activity main page.
871
        if (
872
            $context->contextlevel == CONTEXT_MODULE &&
873
            !$courseformat->has_view_page()
874
        ) {
875
 
876
            $this->page->navigation->initialise();
877
            $activenode = $this->page->navigation->find_active_node();
878
            // If the settings menu has been forced then show the menu.
879
            if ($this->page->is_settings_menu_forced()) {
880
                $showcoursemenu = true;
881
            } else if (!empty($activenode) && ($activenode->type == navigation_node::TYPE_ACTIVITY ||
882
                $activenode->type == navigation_node::TYPE_RESOURCE)) {
883
 
884
                // We only want to show the menu on the first page of the activity. This means
885
                // the breadcrumb has no additional nodes.
886
                if ($currentnode && ($currentnode->key == $activenode->key && $currentnode->type == $activenode->type)) {
887
                    $showcoursemenu = true;
888
                }
889
            }
890
        }
891
 
892
        // This is the site front page.
893
        if (
894
            $context->contextlevel == CONTEXT_COURSE &&
895
            !empty($currentnode) &&
896
            $currentnode->key === 'home'
897
        ) {
898
            $showfrontpagemenu = true;
899
        }
900
 
901
        // This is the user profile page.
902
        if (
903
            $context->contextlevel == CONTEXT_USER &&
904
            !empty($currentnode) &&
905
            ($currentnode->key === 'myprofile')
906
        ) {
907
            $showusermenu = true;
908
        }
909
 
910
        if ($showfrontpagemenu) {
911
            $settingsnode = $this->page->settingsnav->find('frontpage', navigation_node::TYPE_SETTING);
912
            if ($settingsnode) {
913
                // Build an action menu based on the visible nodes from this navigation tree.
914
                $skipped = $this->build_action_menu_from_navigation($menu, $settingsnode, false, true);
915
 
916
                // We only add a list to the full settings menu if we didn't include every node in the short menu.
917
                if ($skipped) {
918
                    $text = get_string('morenavigationlinks');
919
                    $url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
920
                    $link = new action_link($url, $text, null, null, new pix_icon('t/edit', $text));
921
                    $menu->add_secondary_action($link);
922
                }
923
            }
924
        } else if ($showcoursemenu) {
925
            $settingsnode = $this->page->settingsnav->find('courseadmin', navigation_node::TYPE_COURSE);
926
            if ($settingsnode) {
927
                // Build an action menu based on the visible nodes from this navigation tree.
928
                $skipped = $this->build_action_menu_from_navigation($menu, $settingsnode, false, true);
929
 
930
                // We only add a list to the full settings menu if we didn't include every node in the short menu.
931
                if ($skipped) {
932
                    $text = get_string('morenavigationlinks');
933
                    $url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
934
                    $link = new action_link($url, $text, null, null, new pix_icon('t/edit', $text));
935
                    $menu->add_secondary_action($link);
936
                }
937
            }
938
        } else if ($showusermenu) {
939
            // Get the course admin node from the settings navigation.
940
            $settingsnode = $this->page->settingsnav->find('useraccount', navigation_node::TYPE_CONTAINER);
941
            if ($settingsnode) {
942
                // Build an action menu based on the visible nodes from this navigation tree.
943
                $this->build_action_menu_from_navigation($menu, $settingsnode);
944
            }
945
        }
946
 
947
        return $this->render($menu);
948
    }
949
 
161 ariadna 950
    public function customeditblockbtn()
951
    {
1 efrain 952
        $header = new stdClass();
953
        $header->settingsmenu = $this->context_header_settings_menu();
954
        $header->pageheadingbutton = $this->page_heading_button();
955
 
956
        $html = $this->render_from_template('theme_universe/header_settings_menu', $header);
957
 
958
        return $html;
959
    }
960
 
961
    /**
962
     * Renders the context header for the page.
963
     *
964
     * @param array $headerinfo Heading information.
965
     * @param int $headinglevel What 'h' level to make the heading.
966
     * @return string A rendered context header.
967
     */
161 ariadna 968
    public function context_header($headerinfo = null, $headinglevel = 1): string
969
    {
1 efrain 970
        global $DB, $USER, $CFG, $SITE;
971
        require_once($CFG->dirroot . '/user/lib.php');
972
        $context = $this->page->context;
973
        $heading = null;
974
        $imagedata = null;
975
        $subheader = null;
976
        $userbuttons = null;
977
 
978
        // Make sure to use the heading if it has been set.
979
        if (isset($headerinfo['heading'])) {
980
            $heading = $headerinfo['heading'];
981
        } else {
982
            $heading = $this->page->heading;
983
        }
984
 
985
        // The user context currently has images and buttons. Other contexts may follow.
986
        if ((isset($headerinfo['user']) || $context->contextlevel == CONTEXT_USER) && $this->page->pagetype !== 'my-index') {
987
            if (isset($headerinfo['user'])) {
988
                $user = $headerinfo['user'];
989
            } else {
990
                // Look up the user information if it is not supplied.
991
                $user = $DB->get_record('user', array('id' => $context->instanceid));
992
            }
993
 
994
            // If the user context is set, then use that for capability checks.
995
            if (isset($headerinfo['usercontext'])) {
996
                $context = $headerinfo['usercontext'];
997
            }
998
 
999
            // Only provide user information if the user is the current user, or a user which the current user can view.
1000
            // When checking user_can_view_profile(), either:
1001
            // If the page context is course, check the course context (from the page object) or;
1002
            // If page context is NOT course, then check across all courses.
1003
            $course = ($this->page->context->contextlevel == CONTEXT_COURSE) ? $this->page->course : null;
1004
 
1005
            if (user_can_view_profile($user, $course)) {
1006
                // Use the user's full name if the heading isn't set.
1007
                if (empty($heading)) {
1008
                    $heading = fullname($user);
1009
                }
1010
 
1011
                $imagedata = $this->user_picture($user, array('size' => 100));
1012
 
1013
                // Check to see if we should be displaying a message button.
1014
                if (!empty($CFG->messaging) && has_capability('moodle/site:sendmessage', $context)) {
1015
                    $userbuttons = array(
1016
                        'messages' => array(
1017
                            'buttontype' => 'message',
1018
                            'title' => get_string('message', 'message'),
1019
                            'url' => new moodle_url('/message/index.php', array('id' => $user->id)),
1020
                            'image' => 'message',
1021
                            'linkattributes' => \core_message\helper::messageuser_link_params($user->id),
1022
                            'page' => $this->page
1023
                        )
1024
                    );
1025
 
1026
                    if ($USER->id != $user->id) {
1027
                        $iscontact = \core_message\api::is_contact($USER->id, $user->id);
1028
                        $contacttitle = $iscontact ? 'removefromyourcontacts' : 'addtoyourcontacts';
1029
                        $contacturlaction = $iscontact ? 'removecontact' : 'addcontact';
1030
                        $contactimage = $iscontact ? 'removecontact' : 'addcontact';
1031
                        $userbuttons['togglecontact'] = array(
1032
                            'buttontype' => 'togglecontact',
1033
                            'title' => get_string($contacttitle, 'message'),
1034
                            'url' => new moodle_url(
1035
                                '/message/index.php',
1036
                                array(
1037
                                    'user1' => $USER->id,
1038
                                    'user2' => $user->id,
1039
                                    $contacturlaction => $user->id,
1040
                                    'sesskey' => sesskey()
1041
                                )
1042
                            ),
1043
                            'image' => $contactimage,
1044
                            'linkattributes' => \core_message\helper::togglecontact_link_params($user, $iscontact),
1045
                            'page' => $this->page
1046
                        );
1047
                    }
1048
 
1049
                    $this->page->requires->string_for_js('changesmadereallygoaway', 'moodle');
1050
                }
1051
            } else {
1052
                $heading = null;
1053
            }
1054
        }
1055
 
1056
        $prefix = null;
1057
        if ($context->contextlevel == CONTEXT_MODULE) {
1058
            if ($this->page->course->format === 'singleactivity') {
1059
                $heading = $this->page->course->fullname;
1060
            } else {
1061
                $heading = $this->page->cm->get_formatted_name();
1062
                $imagedata = $this->pix_icon('monologo', '', $this->page->activityname, ['class' => 'activityicon']);
1063
                $purposeclass = plugin_supports('mod', $this->page->activityname, FEATURE_MOD_PURPOSE);
1064
                $purposeclass .= ' activityiconcontainer';
1065
                $purposeclass .= ' modicon_' . $this->page->activityname;
1066
                $imagedata = html_writer::tag('div', $imagedata, ['class' => $purposeclass]);
1067
                $prefix = get_string('modulename', $this->page->activityname);
1068
            }
1069
        }
1070
 
1071
        $contextheader = new \context_header($heading, $headinglevel, $imagedata, $userbuttons, $prefix);
1072
        return $this->render_context_header($contextheader);
1073
    }
1074
 
1075
 
1076
    /**
1077
     * Construct a user menu, returning HTML that can be echoed out by a
1078
     * layout file.
1079
     *
1080
     * @param stdClass $user A user object, usually $USER.
1081
     * @param bool $withlinks true if a dropdown should be built.
1082
     * @return string HTML fragment.
1083
     */
161 ariadna 1084
    public function user_menu($user = null, $withlinks = null)
1085
    {
1 efrain 1086
        global $USER, $CFG;
1087
        require_once($CFG->dirroot . '/user/lib.php');
1088
 
1089
        if (is_null($user)) {
1090
            $user = $USER;
1091
        }
1092
 
1093
        // Note: this behaviour is intended to match that of core_renderer::login_info,
1094
        // but should not be considered to be good practice; layout options are
1095
        // intended to be theme-specific. Please don't copy this snippet anywhere else.
1096
        if (is_null($withlinks)) {
1097
            $withlinks = empty($this->page->layout_options['nologinlinks']);
1098
        }
1099
 
1100
        // Add a class for when $withlinks is false.
1101
        $usermenuclasses = 'usermenu';
1102
        if (!$withlinks) {
1103
            $usermenuclasses .= ' withoutlinks';
1104
        }
1105
 
1106
        $returnstr = "";
1107
 
1108
        // If during initial install, return the empty return string.
1109
        if (during_initial_install()) {
1110
            return $returnstr;
1111
        }
1112
 
1113
        $loginpage = $this->is_login_page();
1114
        $loginurl = get_login_url();
1115
        // If not logged in, show the typical not-logged-in string.
1116
        if (!isloggedin()) {
1117
            if (!$loginpage) {
1118
                $returnstr .= "<a class=\"rui-topbar-btn rui-login-btn\" href=\"$loginurl\"><span class=\"rui-login-btn-txt\">" .
1119
                    get_string('login') .
1120
                    '</span>
1121
                <svg class="ml-2" width="20" height="20" fill="none" viewBox="0 0 24 24">
1122
                <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
1123
                d="M9.75 8.75L13.25 12L9.75 15.25"></path>
1124
                <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
1125
                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">
1126
                </path>
1127
                <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 12H4.75"></path>
1128
                </svg></a>';
1129
            }
1130
            return html_writer::div(
1131
                html_writer::span(
1132
                    $returnstr,
1133
                    'login'
1134
                ),
1135
                $usermenuclasses
1136
            );
1137
        }
1138
 
1139
        // If logged in as a guest user, show a string to that effect.
1140
        if (isguestuser()) {
1141
            $icon = '<svg class="mr-2"
1142
                width="24"
1143
                height="24"
1144
                viewBox="0 0 24 24"
1145
                fill="none"
1146
                xmlns="http://www.w3.org/2000/svg">
1147
            <path d="M10 12C10 12.5523 9.55228 13 9 13C8.44772 13 8 12.5523 8
1148
            12C8 11.4477 8.44772 11 9 11C9.55228 11 10 11.4477 10 12Z"
1149
                fill="currentColor"
1150
                />
1151
            <path d="M15 13C15.5523 13 16 12.5523 16 12C16 11.4477 15.5523 11
1152
            15 11C14.4477 11 14 11.4477 14 12C14 12.5523 14.4477 13 15 13Z"
1153
                fill="currentColor"
1154
                />
1155
            <path fill-rule="evenodd"
1156
                clip-rule="evenodd"
1157
                d="M12.0244 2.00003L12 2C6.47715 2 2 6.47715 2 12C2 17.5228
1158
                6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.74235
1159
            17.9425 2.43237 12.788 2.03059L12.7886 2.0282C12.5329 2.00891
1160
            12.278 1.99961 12.0244 2.00003ZM12 20C16.4183 20 20 16.4183 20
1161
            12C20 11.3014 19.9105 10.6237 19.7422
1162
            9.97775C16.1597 10.2313 12.7359 8.52461 10.7605 5.60246C9.31322
1163
            7.07886 7.2982 7.99666 5.06879 8.00253C4.38902 9.17866 4 10.5439 4
1164
            12C4 16.4183 7.58172 20
1165
            12 20ZM11.9785 4.00003L12.0236 4.00003L12 4L11.9785 4.00003Z"
1166
                fill="currentColor"
1167
                /></svg>';
1168
            $returnstr = '<div class="rui-badge-guest">' . $icon . get_string('loggedinasguest') . '</div>';
1169
            if (!$loginpage && $withlinks) {
1170
                $returnstr .= "<a class=\"rui-topbar-btn rui-login-btn\"
1171
                    href=\"$loginurl\"><span class=\"rui-login-btn-txt\">" .
1172
                    get_string('login') .
1173
                    '</span>
1174
                <svg class="ml-2"
1175
                    width="20"
1176
                    height="20"
1177
                    fill="none"
1178
                    viewBox="0 0 24 24">
1179
                <path stroke="currentColor"
1180
                    stroke-linecap="round"
1181
                    stroke-linejoin="round"
1182
                    stroke-width="2"
1183
                    d="M9.75 8.75L13.25 12L9.75 15.25"></path>
1184
                <path stroke="currentColor"
1185
                    stroke-linecap="round"
1186
                    stroke-linejoin="round"
1187
                    stroke-width="2"
1188
                    d="M9.75 4.75H17.25C18.3546 4.75 19.25 5.64543 19.25
1189
                    6.75V17.25C19.25 18.3546 18.3546 19.25 17.25 19.25H9.75"></path>
1190
                    <path stroke="currentColor"
1191
                        stroke-linecap="round"
1192
                        stroke-linejoin="round"
1193
                        stroke-width="2"
1194
                        d="M13 12H4.75"></path></svg></a>';
1195
            }
1196
 
1197
            return html_writer::div(
1198
                html_writer::span(
1199
                    $returnstr,
1200
                    'login'
1201
                ),
1202
                $usermenuclasses
1203
            );
1204
        }
1205
 
1206
        // Get some navigation opts.
1207
        $opts = user_get_user_navigation_info($user, $this->page, array('avatarsize' => 56));
1208
 
1209
        $avatarclasses = "avatars";
1210
        $avatarcontents = html_writer::span($opts->metadata['useravatar'], 'avatar current');
1211
        $usertextcontents = '<span class="rui-fullname">' . $opts->metadata['userfullname'] . '</span>';
1212
        $usertextmail = $user->email;
1213
        $usernick = '<svg class="mr-1"
1214
            width="16"
1215
            height="16"
1216
            fill="none"
1217
            viewBox="0 0 24 24">
1218
        <path stroke="currentColor"
1219
            stroke-linecap="round"
1220
            stroke-linejoin="round"
1221
            stroke-width="2"
1222
            d="M12 13V15"></path>
1223
        <circle cx="12"
1224
            cy="9"
1225
            r="1"
1226
            fill="currentColor"></circle>
1227
        <circle cx="12"
1228
            cy="12"
1229
            r="7.25"
1230
            stroke="currentColor"
1231
            stroke-linecap="round"
1232
            stroke-linejoin="round"
1233
            stroke-width="1.5"></circle>
1234
        </svg>' . $user->username;
1235
 
1236
        // Other user.
1237
        $usermeta = '';
1238
        if (!empty($opts->metadata['asotheruser'])) {
1239
            $avatarcontents .= html_writer::span(
1240
                $opts->metadata['realuseravatar'],
1241
                'avatar realuser'
1242
            );
1243
            $usermeta .= $opts->metadata['realuserfullname'];
1244
            $usermeta .= html_writer::tag(
1245
                'span',
1246
                get_string(
1247
                    'loggedinas',
1248
                    'moodle',
1249
                    html_writer::span(
1250
                        $opts->metadata['userfullname'],
1251
                        'value'
1252
                    )
1253
                ),
1254
                array('class' => 'meta viewingas')
1255
            );
1256
        }
1257
 
1258
        // Role.
1259
        if (!empty($opts->metadata['asotherrole'])) {
1260
            $role = core_text::strtolower(preg_replace('#[ ]+#', '-', trim($opts->metadata['rolename'])));
1261
            $usermeta .= html_writer::span(
1262
                $opts->metadata['rolename'],
1263
                'meta role role-' . $role
1264
            );
1265
        }
1266
 
1267
        // User login failures.
1268
        if (!empty($opts->metadata['userloginfail'])) {
1269
            $usermeta .= html_writer::div(
1270
                '<svg class="mr-1"
1271
                width="16"
1272
                height="16"
1273
                fill="none"
1274
                viewBox="0 0 24 24"><path stroke="currentColor"
1275
                stroke-linecap="round"
1276
                stroke-linejoin="round"
1277
                stroke-width="1.5"
1278
                d="M4.9522 16.3536L10.2152 5.85658C10.9531 4.38481 13.0539
1279
                4.3852 13.7913 5.85723L19.0495 16.3543C19.7156 17.6841 18.7487
1280
                19.25 17.2613 19.25H6.74007C5.25234
1281
                19.25 4.2854 17.6835 4.9522 16.3536Z">
1282
                </path><path stroke="currentColor"
1283
                stroke-linecap="round"
1284
                stroke-linejoin="round"
1285
                stroke-width="2"
1286
                d="M12 10V12"></path>
1287
                <circle cx="12" cy="16" r="1" fill="currentColor"></circle></svg>' .
1288
                    $opts->metadata['userloginfail'],
1289
                'meta loginfailures'
1290
            );
1291
        }
1292
 
1293
        // MNet.
1294
        if (!empty($opts->metadata['asmnetuser'])) {
1295
            $mnet = strtolower(preg_replace('#[ ]+#', '-', trim($opts->metadata['mnetidprovidername'])));
1296
            $usermeta .= html_writer::span(
1297
                $opts->metadata['mnetidprovidername'],
1298
                'meta mnet mnet-' . $mnet
1299
            );
1300
        }
1301
 
1302
        $returnstr .= html_writer::span(
1303
            html_writer::span($avatarcontents, $avatarclasses),
1304
            'userbutton'
1305
        );
1306
 
1307
        // Create a divider (well, a filler).
1308
        $divider = new action_menu_filler();
1309
        $divider->primary = false;
1310
 
1311
        $am = new action_menu();
1312
        $am->set_menu_trigger(
1313
            $returnstr
1314
        );
1315
        $am->set_action_label(get_string('usermenu'));
1316
        $am->set_nowrap_on_items();
1317
 
1318
        if ($CFG->enabledashboard) {
1319
            $dashboardlink = '<div class="dropdown-item-wrapper"><a class="dropdown-item" href="' .
1320
                new moodle_url('/my/') .
1321
                '" data-identifier="dashboard,moodle" title="dashboard,moodle">' .
1322
                get_string('myhome', 'moodle') .
1323
                '</a></div>';
1324
        } else {
1325
            $dashboardlink = null;
1326
        }
1327
 
1328
        $am->add(
1329
            '<div class="dropdown-user-wrapper"><div class="dropdown-user">' . $usertextcontents  . '</div>'
1330
                . '<div class="dropdown-user-mail text-truncate" title="' . $usertextmail . '">' . $usertextmail . '</div>'
1331
                . '<span class="dropdown-user-nick w-100">' . $usernick . '</span>'
1332
                . '<div class="dropdown-user-meta"><span class="badge-xs badge-sq badge-warning flex-wrap">' .
1333
                $usermeta . '</span></div>'
1334
                . '</div><div class="dropdown-divider dropdown-divider-user"></div>' . $dashboardlink
1335
        );
1336
 
1337
        if ($withlinks) {
1338
            $navitemcount = count($opts->navitems);
1339
            $idx = 0;
1340
            foreach ($opts->navitems as $key => $value) {
1341
 
1342
                switch ($value->itemtype) {
1343
                    case 'divider':
1344
                        // If the nav item is a divider, add one and skip link processing.
1345
                        $am->add($divider);
1346
                        break;
1347
 
1348
                    case 'invalid':
1349
                        // Silently skip invalid entries (should we post a notification?).
1350
                        break;
1351
 
1352
                    case 'link':
1353
                        $al = '<a class="dropdown-item" href="' .
1354
                            $value->url .
1355
                            '" data-identifier="' .
1356
                            $value->titleidentifier .
1357
                            '" title="' .
1358
                            $value->titleidentifier .
1359
                            '">' .
1360
                            $value->title . '</a>';
1361
                        $am->add($al);
1362
                        break;
1363
                }
1364
 
1365
                $idx++;
1366
 
1367
                // Add dividers after the first item and before the last item.
1368
                if ($idx == 1 || $idx == $navitemcount - 1) {
1369
                    $am->add($divider);
1370
                }
1371
            }
1372
        }
1373
 
1374
        return html_writer::div(
1375
            $this->render($am),
1376
            $usermenuclasses
1377
        );
1378
    }
1379
 
1380
 
1381
    /**
1382
     * Returns standard main content placeholder.
1383
     * Designed to be called in theme layout.php files.
1384
     *
1385
     * @return string HTML fragment.
1386
     */
161 ariadna 1387
    public function main_content()
1388
    {
1 efrain 1389
        // This is here because it is the only place we can inject the "main" role over the entire main content area
1390
        // without requiring all theme's to manually do it, and without creating yet another thing people need to
1391
        // remember in the theme.
1392
        // This is an unfortunate hack. DO NO EVER add anything more here.
1393
        // DO NOT add classes.
1394
        // DO NOT add an id.
1395
        return '<div class="main-content" role="main">' . $this->unique_main_content_token . '</div>';
1396
    }
1397
 
1398
    /**
1399
     * Outputs a heading
1400
     *
1401
     * @param string $text The text of the heading
1402
     * @param int $level The level of importance of the heading. Defaulting to 2
1403
     * @param string $classes A space-separated list of CSS classes. Defaulting to null
1404
     * @param string $id An optional ID
1405
     * @return string the HTML to output.
1406
     */
161 ariadna 1407
    public function heading($text, $level = 2, $classes = null, $id = null)
1408
    {
1 efrain 1409
        $level = (int) $level;
1410
        if ($level < 1 || $level > 6) {
1411
            throw new coding_exception('Heading level must be an integer between 1 and 6.');
1412
        }
1413
        return html_writer::tag('div', html_writer::tag('h' .
1414
            $level, $text, array('id' => $id, 'class' => renderer_base::prepare_classes($classes) .
1415
            ' rui-main-content-title rui-main-content-title--h' .
1416
            $level)), array('class' => 'rui-title-container'));
1417
    }
1418
 
1419
 
161 ariadna 1420
    public function headingwithavatar($text, $level = 2, $classes = null, $id = null)
1421
    {
1 efrain 1422
        $level = (int) $level;
1423
        if ($level < 1 || $level > 6) {
1424
            throw new coding_exception('Heading level must be an integer between 1 and 6.');
1425
        }
1426
        return html_writer::tag('div', html_writer::tag('h' .
1427
            $level, $text, array('id' => $id, 'class' => renderer_base::prepare_classes($classes) .
1428
            ' rui-main-content-title-with-avatar')), array('class' => 'rui-title-container-with-avatar'));
1429
    }
1430
 
1431
    /**
1432
     * Renders the login form.
1433
     *
1434
     * @param \core_auth\output\login $form The renderable.
1435
     * @return string
1436
     */
161 ariadna 1437
    public function render_login(\core_auth\output\login $form)
1438
    {
1 efrain 1439
        global $CFG, $SITE;
1440
 
1441
        $context = $form->export_for_template($this);
1442
 
1443
        // Override because rendering is not supported in template yet.
1444
        if ($CFG->rememberusername == 0) {
1445
            $context->cookieshelpiconformatted = $this->help_icon('cookiesenabledonlysession');
1446
        } else {
1447
            $context->cookieshelpiconformatted = $this->help_icon('cookiesenabled');
1448
        }
1449
        $context->errorformatted = $this->error_text($context->error);
1450
        $url = $this->get_logo_url();
1451
        if ($url) {
1452
            $url = $url->out(false);
1453
        }
1454
        $context->logourl = $url;
1455
        $context->sitename = format_string(
1456
            $SITE->fullname,
1457
            true,
1458
            ['context' => context_course::instance(SITEID), "escape" => false]
1459
        );
1460
 
1461
        if ($this->page->theme->settings->setloginlayout == 1) {
1462
            $context->loginlayout1 = 1;
1463
        } else if ($this->page->theme->settings->setloginlayout == 2) {
1464
            $context->loginlayout2 = 1;
1465
            if (isset($this->page->theme->settings->loginbg)) {
1466
                $context->loginlayoutimg = 1;
1467
            }
1468
        } else if ($this->page->theme->settings->setloginlayout == 3) {
1469
            $context->loginlayout3 = 1;
1470
            if (isset($this->page->theme->settings->loginbg)) {
1471
                $context->loginlayoutimg = 1;
1472
            }
1473
        } else if ($this->page->theme->settings->setloginlayout == 4) {
1474
            $context->loginlayout4 = 1;
1475
        } else if ($this->page->theme->settings->setloginlayout == 5) {
1476
            $context->loginlayout5 = 1;
1477
        }
1478
 
1479
        if (isset($this->page->theme->settings->loginlogooutside)) {
1480
            $context->loginlogooutside = $this->page->theme->settings->loginlogooutside;
1481
        }
1482
 
1483
        if (isset($this->page->theme->settings->customsignupoutside)) {
1484
            $context->customsignupoutside = $this->page->theme->settings->customsignupoutside;
1485
        }
1486
 
1487
        if (isset($this->page->theme->settings->loginidprovtop)) {
1488
            $context->loginidprovtop = $this->page->theme->settings->loginidprovtop;
1489
        }
1490
 
1491
        if (isset($this->page->theme->settings->stringca)) {
1492
            $context->stringca = format_text(($this->page->theme->settings->stringca),
1493
                FORMAT_HTML,
1494
                array('noclean' => true)
1495
            );
1496
        }
1497
 
1498
        if (isset($this->page->theme->settings->stringca)) {
1499
            $context->stringca = format_text(($this->page->theme->settings->stringca),
1500
                FORMAT_HTML,
1501
                array('noclean' => true)
1502
            );
1503
        }
1504
 
1505
        if (isset($this->page->theme->settings->loginhtmlcontent1)) {
1506
            $context->loginhtmlcontent1 = format_text(($this->page->theme->settings->loginhtmlcontent1),
1507
                FORMAT_HTML,
1508
                array('noclean' => true)
1509
            );
1510
        }
1511
 
1512
        if (isset($this->page->theme->settings->loginhtmlcontent2)) {
1513
            $context->loginhtmlcontent2 = format_text(($this->page->theme->settings->loginhtmlcontent2),
1514
                FORMAT_HTML,
1515
                array('noclean' => true)
1516
            );
1517
        }
1518
 
1519
        if (isset($this->page->theme->settings->loginhtmlcontent3)) {
1520
            $context->loginhtmlcontent3 = format_text(($this->page->theme->settings->loginhtmlcontent3),
1521
                FORMAT_HTML,
1522
                array('noclean' => true)
1523
            );
1524
        }
1525
 
1526
        if (isset($this->page->theme->settings->loginhtmlcontent2)) {
1527
            $context->loginhtmlcontent2 = format_text(($this->page->theme->settings->loginhtmlcontent2),
1528
                FORMAT_HTML,
1529
                array('noclean' => true)
1530
            );
1531
        }
1532
 
1533
        if (isset($this->page->theme->settings->logincustomfooterhtml)) {
1534
            $context->logincustomfooterhtml = format_text(($this->page->theme->settings->logincustomfooterhtml),
1535
                FORMAT_HTML,
1536
                array('noclean' => true)
1537
            );
1538
        }
1539
 
1540
        if (isset($this->page->theme->settings->loginhtmlblockbottom)) {
1541
            $context->loginhtmlblockbottom = format_text(($this->page->theme->settings->loginhtmlblockbottom),
1542
                FORMAT_HTML,
1543
                array('noclean' => true)
1544
            );
1545
        }
1546
 
1547
        if (isset($this->page->theme->settings->loginfootercontent)) {
1548
            $context->loginfootercontent = format_text(($this->page->theme->settings->loginfootercontent),
1549
                FORMAT_HTML,
1550
                array('noclean' => true)
1551
            );
1552
        }
1553
 
1554
        if (isset($this->page->theme->settings->footercopy)) {
1555
            $context->footercopy = format_text(($this->page->theme->settings->footercopy),
1556
                FORMAT_HTML,
1557
                array('noclean' => true)
1558
            );
1559
        }
1560
 
1561
        if (isset($this->page->theme->settings->loginintrotext)) {
1562
            $context->loginintrotext = format_text(($this->page->theme->settings->loginintrotext),
1563
                FORMAT_HTML,
1564
                array('noclean' => true)
1565
            );
1566
        }
1567
 
1568
        if (isset($this->page->theme->settings->loginintrotext)) {
1569
            $context->loginintrotext = format_text(($this->page->theme->settings->loginintrotext),
1570
                FORMAT_HTML,
1571
                array('noclean' => true)
1572
            );
1573
        }
1574
 
1575
        if (isset($this->page->theme->settings->customloginlogo)) {
1576
            $context->customloginlogo = $this->page->theme->setting_file_url('customloginlogo', 'customloginlogo');
1577
        }
1578
 
1579
        if (isset($this->page->theme->settings->loginbg)) {
1580
            $context->loginbg = $this->page->theme->setting_file_url('loginbg', 'loginbg');
1581
        }
1582
 
1583
        if (isset($this->page->theme->settings->hideforgotpassword)) {
1584
            $context->hideforgotpassword = $this->page->theme->settings->hideforgotpassword == 1;
1585
        }
1586
 
1587
        if (isset($this->page->theme->settings->logininfobox)) {
1588
            $context->logininfobox = format_text(($this->page->theme->settings->logininfobox),
1589
                FORMAT_HTML,
1590
                array('noclean' => true)
1591
            );
1592
        }
1593
 
1594
        return $this->render_from_template('core/loginform', $context);
1595
    }
1596
 
1597
    /**
1598
     * Render the login signup form into a nice template for the theme.
1599
     *
1600
     * @param mform $form
1601
     * @return string
1602
     */
161 ariadna 1603
    public function render_login_signup_form($form)
1604
    {
1 efrain 1605
        global $SITE;
1606
 
1607
        $context = $form->export_for_template($this);
1608
        $url = $this->get_logo_url();
1609
        if ($url) {
1610
            $url = $url->out(false);
1611
        }
1612
        $context['logourl'] = $url;
1613
        $context['sitename'] = format_string(
1614
            $SITE->fullname,
1615
            true,
1616
            ['context' => context_course::instance(SITEID), "escape" => false]
1617
        );
1618
 
1619
        if ($this->page->theme->settings->setloginlayout == 1) {
1620
            $context['loginlayout1'] = 1;
1621
        } else if ($this->page->theme->settings->setloginlayout == 2) {
1622
            $context['loginlayout2'] = 1;
1623
            if (isset($this->page->theme->settings->loginbg)) {
1624
                $context['loginlayoutimg'] = 1;
1625
            }
1626
        } else if ($this->page->theme->settings->setloginlayout == 3) {
1627
            $context['loginlayout3'] = 1;
1628
            if (isset($this->page->theme->settings->loginbg)) {
1629
                $context['loginlayoutimg'] = 1;
1630
            }
1631
        } else if ($this->page->theme->settings->setloginlayout == 4) {
1632
            $context['loginlayout4'] = 1;
1633
        } else if ($this->page->theme->settings->setloginlayout == 5) {
1634
            $context['loginlayout5'] = 1;
1635
        }
1636
 
1637
        if (isset($this->page->theme->settings->loginlogooutside)) {
1638
            $context['loginlogooutside'] = $this->page->theme->settings->loginlogooutside;
1639
        }
1640
 
1641
        if (isset($this->page->theme->settings->stringbacktologin)) {
1642
            $context['stringbacktologin'] = format_text(($this->page->theme->settings->stringbacktologin),
1643
                FORMAT_HTML,
1644
                array('noclean' => true)
1645
            );
1646
        }
1647
        if (isset($this->page->theme->settings->signupintrotext)) {
1648
            $context['signupintrotext'] = format_text(($this->page->theme->settings->signupintrotext),
1649
                FORMAT_HTML,
1650
                array('noclean' => true)
1651
            );
1652
        }
1653
        if (isset($this->page->theme->settings->signuptext)) {
1654
            $context['signuptext'] = format_text(($this->page->theme->settings->signuptext),
1655
                FORMAT_HTML,
1656
                array('noclean' => true)
1657
            );
1658
        }
1659
 
1660
        if (!empty($this->page->theme->settings->customloginlogo)) {
1661
            $url = $this->page->theme->setting_file_url('customloginlogo', 'customloginlogo');
1662
            $context['customloginlogo'] = $url;
1663
        }
1664
 
1665
        if (!empty($this->page->theme->settings->loginbg)) {
1666
            $url = $this->page->theme->setting_file_url('loginbg', 'loginbg');
1667
            $context['loginbg'] = $url;
1668
        }
1669
 
1670
        if (isset($this->page->theme->settings->loginfootercontent)) {
1671
            $context['loginfootercontent'] = format_text(($this->page->theme->settings->loginfootercontent),
1672
                FORMAT_HTML,
1673
                array('noclean' => true)
1674
            );
1675
        }
1676
 
1677
        return $this->render_from_template('core/signup_form_layout', $context);
1678
    }
1679
 
1680
 
1681
    /**
1682
     * Renders the header bar.
1683
     *
1684
     * @param context_header $contextheader Header bar object.
1685
     * @return string HTML for the header bar.
1686
     */
161 ariadna 1687
    protected function render_context_header(\context_header $contextheader)
1688
    {
1 efrain 1689
        $heading = null;
1690
        $imagedata = null;
1691
        $html = null;
1692
 
1693
        // Generate the heading first and before everything else as we might have to do an early return.
1694
        if (!isset($contextheader->heading)) {
1695
            $heading = $this->heading($this->page->heading, $contextheader->headinglevel);
1696
        } else {
1697
            $heading = $this->heading($contextheader->heading, $contextheader->headinglevel);
1698
        }
1699
 
1700
        // All the html stuff goes here.
1701
        $html = html_writer::start_div('page-context-header d-flex align-items-center flex-wrap');
1702
 
1703
        // Image data.
1704
        if (isset($contextheader->imagedata)) {
1705
            // Header specific image.
1706
            $html .= html_writer::div($contextheader->imagedata, 'page-header-image');
1707
        }
1708
 
1709
        // Headings.
1710
        if (isset($contextheader->prefix)) {
1711
            $prefix = html_writer::div($contextheader->prefix, 'text-muted text-uppercase small line-height-3');
1712
            $heading = $prefix . $heading;
1713
        }
1714
 
1715
        if (!isset($contextheader->heading)) {
1716
            $html .= html_writer::tag('h3', $heading, array('class' => 'rui-page-title rui-page-title--page'));
1717
        } else if (isset($contextheader->imagedata)) {
1718
            $html .= html_writer::tag(
1719
                'div',
1720
                $this->heading($contextheader->heading, 4),
1721
                array('class' => 'rui-page-title rui-page-title--icon')
1722
            );
1723
        } else {
1724
            $html .= html_writer::tag('h2', $heading, array('class' => 'page-header-headings
1725
                rui-page-title rui-page-title--context'));
1726
        }
1727
 
1728
        // Buttons.
1729
        if (isset($contextheader->additionalbuttons)) {
1730
            $html .= html_writer::start_div('btn-group header-button-group my-2 my-lg-0 ml-lg-4');
1731
            foreach ($contextheader->additionalbuttons as $button) {
1732
                if (!isset($button->page)) {
1733
                    // Include js for messaging.
1734
                    if ($button['buttontype'] === 'togglecontact') {
1735
                        \core_message\helper::togglecontact_requirejs();
1736
                    }
1737
                    if ($button['buttontype'] === 'message') {
1738
                        \core_message\helper::messageuser_requirejs();
1739
                    }
1740
                    $image = $this->pix_icon($button['formattedimage'], $button['title'], 'moodle', array(
1741
                        'class' => 'iconsmall',
1742
                        'role' => 'presentation'
1743
                    ));
1744
                    $image .= html_writer::span($button['title'], 'header-button-title');
1745
                } else {
1746
                    $image = html_writer::empty_tag('img', array(
1747
                        'src' => $button['formattedimage'],
1748
                        'role' => 'presentation'
1749
                    ));
1750
                }
1751
                $html .= html_writer::link($button['url'], html_writer::tag('span', $image), $button['linkattributes']);
1752
            }
1753
            $html .= html_writer::end_div();
1754
        }
1755
        $html .= html_writer::end_div();
1756
 
1757
        return $html;
1758
    }
1759
 
161 ariadna 1760
    public function header()
1761
    {
1 efrain 1762
        global $USER, $COURSE;
1763
        $theme = theme_config::load('universe');
1764
 
1765
        $context = context_course::instance($COURSE->id);
1766
        $roles = get_user_roles($context, $USER->id, true);
1767
 
1768
        if (is_array($roles) && !empty($roles)) {
1769
            foreach ($roles as $role) {
1770
                $this->page->add_body_class('role-' . $role->shortname);
1771
            }
1772
        } else {
1773
            $this->page->add_body_class('role-none');
1774
        }
1775
 
1776
        if ($theme->settings->topbareditmode == '1') {
1777
            $this->page->add_body_class('rui-editmode--top');
1778
        } else {
1779
            $this->page->add_body_class('rui-editmode--footer');
1780
        }
1781
 
1782
        return parent::header();
1783
    }
1784
 
1785
 
1786
    /**
1787
     * See if this is the first view of the current cm in the session if it has fake blocks.
1788
     *
1789
     * (We track up to 100 cms so as not to overflow the session.)
1790
     * This is done for drawer regions containing fake blocks so we can show blocks automatically.
1791
     *
1792
     * @return boolean true if the page has fakeblocks and this is the first visit.
1793
     */
161 ariadna 1794
    public function firstview_fakeblocks(): bool
1795
    {
1 efrain 1796
        global $SESSION;
1797
 
1798
        $firstview = false;
1799
        if ($this->page->cm) {
1800
            if (!$this->page->blocks->region_has_fakeblocks('side-pre')) {
1801
                return false;
1802
            }
1803
            if (!property_exists($SESSION, 'firstview_fakeblocks')) {
1804
                $SESSION->firstview_fakeblocks = [];
1805
            }
1806
            if (array_key_exists($this->page->cm->id, $SESSION->firstview_fakeblocks)) {
1807
                $firstview = false;
1808
            } else {
1809
                $SESSION->firstview_fakeblocks[$this->page->cm->id] = true;
1810
                $firstview = true;
1811
                if (count($SESSION->firstview_fakeblocks) > 100) {
1812
                    array_shift($SESSION->firstview_fakeblocks);
1813
                }
1814
            }
1815
        }
1816
        return $firstview;
1817
    }
1818
 
1819
 
1820
    /**
1821
     * Build the guest access hint HTML code.
1822
     *
1823
     * @param int $courseid The course ID.
1824
     * @return string.
1825
     */
161 ariadna 1826
    public function theme_universe_get_course_guest_access_hint($courseid)
1827
    {
1 efrain 1828
        global $CFG;
1829
        require_once($CFG->dirroot . '/enrol/self/lib.php');
1830
 
1831
        $html = '';
1832
        $instances = enrol_get_instances($courseid, true);
1833
        $plugins = enrol_get_plugins(true);
1834
        foreach ($instances as $instance) {
1835
            if (!isset($plugins[$instance->enrol])) {
1836
                continue;
1837
            }
1838
            $plugin = $plugins[$instance->enrol];
1839
            if ($plugin->show_enrolme_link($instance)) {
1840
                $html = html_writer::tag('div', get_string(
1841
                    'showhintcourseguestaccesssettinglink',
1842
                    'theme_universe',
1843
                    array('url' => $CFG->wwwroot . '/enrol/index.php?id=' . $courseid)
1844
                ));
1845
                break;
1846
            }
1847
        }
1848
 
1849
        return $html;
1850
    }
1851
 
1852
 
1853
    /**
1854
     * Color Customization
1855
     * @return string HTML fragment.
1856
     */
161 ariadna 1857
    public function additional_head_html()
1858
    {
1 efrain 1859
        global $SITE, $DB, $CFG, $COURSE, $PAGE;
1860
 
1861
        $output = null;
1862
 
1863
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
1864
            if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor1'), 'id')) {
1865
                // Get custom field by name
1866
                $customfieldid1 = $DB->get_record('customfield_field', array('shortname' => 'maincolor1'));
1867
                // Get value
1868
                $mainthemecolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid1->id, 'instanceid' => $COURSE->id));
1869
            } else {
1870
                $mainthemecolor = null;
1871
            }
1872
 
1873
            if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor2'), 'id')) {
1874
                $customfieldid2 = $DB->get_record('customfield_field', array('shortname' => 'maincolor2'));
1875
                $mainthemecolor2 = $DB->get_record('customfield_data', array('fieldid' => $customfieldid2->id, 'instanceid' => $COURSE->id));
1876
            }
1877
 
1878
            if ($DB->record_exists('customfield_field', array('shortname' => 'topbarcolor'), 'id')) {
1879
                // Get custom field by name
1880
                $customfieldid3 = $DB->get_record('customfield_field', array('shortname' => 'topbarcolor'));
1881
                // Get value
1882
                $topbarcolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid3->id, 'instanceid' => $COURSE->id));
1883
            }
1884
 
1885
            if ($DB->record_exists('customfield_field', array('shortname' => 'dmtopbarcolor'), 'id')) {
1886
                // Get custom field by name
1887
                $customfieldid3 = $DB->get_record('customfield_field', array('shortname' => 'dmtopbarcolor'));
1888
                // Get value
1889
                $dmtopbarcolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid3->id, 'instanceid' => $COURSE->id));
1890
            } else {
1891
                $dmtopbarcolor = null;
1892
            }
1893
 
1894
 
1895
            if ($DB->record_exists('customfield_field', array('shortname' => 'footerbgcolor'), 'id')) {
1896
                // Get custom field by name
1897
                $customfieldid4 = $DB->get_record('customfield_field', array('shortname' => 'footerbgcolor'));
1898
                // Get value
1899
                $footercolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid4->id, 'instanceid' => $COURSE->id));
1900
            } else {
1901
                $footercolor = null;
1902
            }
1903
 
1904
 
1905
            $css = '';
1906
 
1907
            $css .= ':root { ';
1908
            if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor1'), 'id')) {
1909
                if ($mainthemecolor != null) {
1910
                    $css .= '--main-theme-color: ' . $mainthemecolor->value . '; ';
1911
                    $css .= '--primary-color-100: ' . $mainthemecolor->value . '30; ';
1912
                    $css .= '--primary-color-300: ' . $mainthemecolor->value . '70; ';
1913
                    $css .= '--main-theme-color-gradient: ' . $mainthemecolor->value . '; ';
1914
                    $css .= '--btn-primary-color-bg: ' . $mainthemecolor->value . '; ';
1915
                    $css .= '--btn-primary-color-bg-hover: ' . $mainthemecolor->value . '95; ';
1916
 
1917
                    if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor2'), 'id')) {
1918
                        if ($mainthemecolor2 != null) {
1919
                            $css .= '--main-theme-color-gradient-2: ' . $mainthemecolor2->value . '; ';
1920
                        } else {
1921
                            $css .= '--main-theme-color-gradient-2: ' . $mainthemecolor->value . '30; ';
1922
                        }
1923
                    }
1924
                }
1925
            }
1926
 
1927
            if ($DB->record_exists('customfield_field', array('shortname' => 'topbarcolor'), 'id')) {
1928
                if ($topbarcolor != null) {
1929
                    $css .= '--topbar-color: ' . $topbarcolor->value . '; ';
1930
                    if ($dmtopbarcolor != null) {
1931
                        $css .= '--dm-topbar-color: ' . $dmtopbarcolor->value . '; ';
1932
                    } else {
1933
                        $css .= '--dm-topbar-color: ' . $topbarcolor->value . '; ';
1934
                    }
1935
                }
1936
            }
1937
 
1938
            if ($DB->record_exists('customfield_field', array('shortname' => 'footerbgcolor'), 'id')) {
1939
                if ($footercolor != null) {
1940
                    $css .= '--footer-color: ' . $footercolor->value . '; ';
1941
                }
1942
            }
1943
 
1944
            $css .= '}';
1945
 
1946
            if ($css) {
1947
                $output .= '<style>' . $css . '</style>';
1948
            }
1949
        }
1950
 
1951
        return $output;
1952
    }
1953
 
161 ariadna 1954
    public function custom_course_logo()
1955
    {
1 efrain 1956
        global $DB, $CFG, $COURSE, $PAGE;
1957
 
1958
        $output = null;
1959
 
1960
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
1961
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcourselogo'))) {
1962
                // Get custom field ID
1963
                $customfieldpic = $DB->get_record('customfield_field', array('shortname' => 'customcourselogo'));
1964
                $customfieldpicid = $customfieldpic->id;
1965
                // Get value
1966
                $customlogo = $DB->get_record(
1967
                    'customfield_data',
1968
                    array('fieldid' => $customfieldpicid, 'instanceid' => $COURSE->id)
1969
                );
1970
 
1971
                $customlogoid = $customlogo->id;
1972
                $contextid = $customlogo->contextid;
1973
 
1974
                if ($customfieldpic != null) {
1975
                    $files = get_file_storage()->get_area_files(
1976
                        $contextid,
1977
                        'customfield_picture',
1978
                        'file',
1979
                        $customlogoid,
1980
                        '',
1981
                        false
1982
                    );
1983
 
1984
                    if (empty($files)) {
1985
                        return null;
1986
                    }
1987
 
1988
                    $file = reset($files);
1989
                    $fileurl = moodle_url::make_pluginfile_url(
1990
                        $file->get_contextid(),
1991
                        $file->get_component(),
1992
                        $file->get_filearea(),
1993
                        $file->get_itemid(),
1994
                        $file->get_filepath(),
1995
                        $file->get_filename()
1996
                    );
1997
 
1998
                    $output .= $fileurl;
1999
                }
2000
            }
2001
        }
2002
 
2003
        return $output;
2004
    }
2005
 
161 ariadna 2006
    public function custom_course_dmlogo()
2007
    {
1 efrain 2008
        global $DB, $CFG, $COURSE, $PAGE;
2009
 
2010
        $output = null;
2011
 
2012
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
2013
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcoursedmlogo'))) {
2014
                // Get custom field ID
2015
                $customfieldpic = $DB->get_record('customfield_field', array('shortname' => 'customcoursedmlogo'));
2016
                $customfieldpicid = $customfieldpic->id;
2017
                // Get value
2018
                $customlogo = $DB->get_record(
2019
                    'customfield_data',
2020
                    array('fieldid' => $customfieldpicid, 'instanceid' => $COURSE->id)
2021
                );
2022
 
2023
                $customlogoid = $customlogo->id;
2024
                $contextid = $customlogo->contextid;
2025
 
2026
                if ($customfieldpic != null) {
2027
                    $files = get_file_storage()->get_area_files(
2028
                        $contextid,
2029
                        'customfield_picture',
2030
                        'file',
2031
                        $customlogoid,
2032
                        '',
2033
                        false
2034
                    );
2035
 
2036
                    if (empty($files)) {
2037
                        return null;
2038
                    }
2039
 
2040
                    $file = reset($files);
2041
                    $fileurl = moodle_url::make_pluginfile_url(
2042
                        $file->get_contextid(),
2043
                        $file->get_component(),
2044
                        $file->get_filearea(),
2045
                        $file->get_itemid(),
2046
                        $file->get_filepath(),
2047
                        $file->get_filename()
2048
                    );
2049
 
2050
                    $output .= $fileurl;
2051
                }
2052
            }
2053
        }
2054
 
2055
        return $output;
2056
    }
2057
 
161 ariadna 2058
    public function custom_course_favicon()
2059
    {
1 efrain 2060
        global $DB, $CFG, $COURSE, $PAGE;
2061
 
2062
        $output = null;
2063
 
2064
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
2065
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcoursefavicon'))) {
2066
                // Get custom field ID
2067
                $customfieldpic = $DB->get_record('customfield_field', array('shortname' => 'customcoursefavicon'));
2068
                $customfieldpicid = $customfieldpic->id;
2069
                // Get value
2070
                $customfavicon = $DB->get_record(
2071
                    'customfield_data',
2072
                    array('fieldid' => $customfieldpicid, 'instanceid' => $COURSE->id)
2073
                );
2074
 
2075
                $customfaviconid = $customfavicon->id;
2076
                $contextid = $customfavicon->contextid;
2077
 
2078
                if ($customfieldpic != null) {
2079
                    $files = get_file_storage()->get_area_files(
2080
                        $contextid,
2081
                        'customfield_picture',
2082
                        'file',
2083
                        $customfaviconid,
2084
                        '',
2085
                        false
2086
                    );
2087
 
2088
                    if (empty($files)) {
2089
                        return null;
2090
                    }
2091
 
2092
                    $file = reset($files);
2093
                    $fileurl = moodle_url::make_pluginfile_url(
2094
                        $file->get_contextid(),
2095
                        $file->get_component(),
2096
                        $file->get_filearea(),
2097
                        $file->get_itemid(),
2098
                        $file->get_filepath(),
2099
                        $file->get_filename()
2100
                    );
2101
 
2102
                    $output .= $fileurl;
2103
                }
2104
            }
2105
        }
2106
 
2107
        return $output;
2108
    }
2109
 
161 ariadna 2110
    public function custom_course_name()
2111
    {
1 efrain 2112
        global $DB, $CFG, $COURSE, $PAGE;
2113
 
2114
        $output = null;
2115
 
2116
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
2117
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcoursename'), 'id')) {
2118
                // Get custom field by name
2119
                $customfieldid = $DB->get_record('customfield_field', array('shortname' => 'customcoursename'));
2120
                // Get value
2121
                $customcoursename = $DB->get_record('customfield_data', array('fieldid' => $customfieldid->id, 'instanceid' => $COURSE->id));
2122
                if (!empty($customcoursename)) {
2123
                    $output .= $customcoursename->value;
2124
                }
2125
            } else {
2126
                $customcoursename = null;
2127
            }
2128
        }
2129
 
2130
        return $output;
2131
    }
2132
 
161 ariadna 2133
    /**
1 efrain 2134
     * Get the course pattern datauri to show on a course card.
2135
     *
2136
     * The datauri is an encoded svg that can be passed as a url.
2137
     * @param int $id Id to use when generating the pattern
2138
     * @return string datauri
2139
     */
161 ariadna 2140
    public function get_generated_image_for_id($id)
2141
    {
1 efrain 2142
        global $CFG;
2143
 
2144
        $theme = \theme_config::load('universe');
2145
        // Add custom course cover.
2146
        $customcover = $theme->setting_file_url('defaultcourseimg', 'defaultcourseimg');
2147
 
2148
        if (!empty(($customcover))) {
2149
            $urlreplace = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2150
            $customcover = str_replace($urlreplace, '', $customcover);
2151
            $txt = new moodle_url($customcover);
2152
            return strval($txt);
2153
        } else {
2154
            $color = $this->get_generated_color_for_id($id);
2155
            $pattern = new \core_geopattern();
2156
            $pattern->setColor($color);
2157
            $pattern->patternbyid($id);
2158
            return $pattern->datauri();
2159
        }
2160
    }
161 ariadna 2161
 
2162
    public function moremenu_group_item()
2163
    {
1 efrain 2164
        global $CFG, $COURSE;
2165
 
2166
        $theme = \theme_config::load('universe');
2167
        $courseid = $COURSE->id;
2168
        $sitehomeurl = new moodle_url('/');
2169
 
2170
        if ($this->page->theme->settings->secnavgroupitem == 1) {
2171
            if (has_capability('moodle/course:managegroups', \context_course::instance($COURSE->id))) {
2172
                $html = $sitehomeurl . "group/index.php?id=" . $courseid;
2173
                return $html;
2174
            }
2175
        }
2176
    }
2177
 
161 ariadna 2178
    public function moremenu_custom_items()
2179
    {
1 efrain 2180
        global $CFG, $COURSE, $USER;
2181
 
2182
        $theme = \theme_config::load('universe');
2183
        $html = '';
2184
        $secnavcount = theme_universe_get_setting('secnavitemscount');
2185
 
2186
        // Get current user role ID.
2187
        $context = context_course::instance($COURSE->id);
2188
        $roles = get_user_roles($context, $USER->id, true);
2189
        $role = 999;
2190
        $roleid = 999;
2191
        $role = key($roles);
2192
        if ($role != null) {
2193
            $roleid = $roles[$role]->roleid;
2194
        }
2195
 
2196
        // End.
2197
 
2198
        if ($this->page->theme->settings->secnavitems == 1) {
2199
 
2200
            $secnav = new stdClass();
2201
            for ($i = 1; $i <= $secnavcount; $i++) {
2202
                $secnav->title = theme_universe_get_setting("secnavcustomnavlabel" . $i);
2203
 
2204
                $url = theme_universe_get_setting("secnavcustomnavurl" . $i);
2205
                $courseid = $COURSE->id;
2206
                $newurl = str_replace("{{courseID}}", $courseid, $url);
161 ariadna 2207
 
1 efrain 2208
                // User role restriction.
2209
                $selectrole = theme_universe_get_setting("secnavuserroles" . $i);
161 ariadna 2210
 
2211
                if ($roleid == $selectrole) {
1 efrain 2212
                    $secnav->url = $newurl;
2213
                    $html .= $this->render_from_template('theme_universe/custom_sec_nav_item', $secnav);
161 ariadna 2214
                }
2215
                if ($roleid != $selectrole) {
1 efrain 2216
                    $secnav->url = $newurl;
2217
                }
161 ariadna 2218
                if ($selectrole == 0) {
1 efrain 2219
                    $secnav->url = $newurl;
2220
                    $html .= $this->render_from_template('theme_universe/custom_sec_nav_item', $secnav);
161 ariadna 2221
                }
1 efrain 2222
                // End.
2223
 
2224
            }
2225
        }
2226
        return $html;
2227
    }
2228
}