Proyectos de Subversion Moodle

Rev

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