Proyectos de Subversion Moodle

Rev

Rev 241 | Rev 256 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

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