Proyectos de Subversion Moodle

Rev

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

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