Proyectos de Subversion Moodle

Rev

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