Proyectos de Subversion Moodle

Rev

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

Rev Autor Línea Nro. Línea
256 ariadna 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
 
1301 ariadna 17
namespace theme_universe_child\output;
256 ariadna 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;
1301 ariadna 34
use core\oauth2\rest;
256 ariadna 35
use pix_icon;
36
use renderer_base;
37
use theme_config;
38
use get_string;
39
use core_course_category;
40
use theme_universe\util\user;
41
use theme_universe\util\course;
1301 ariadna 42
use core_completion\progress;
256 ariadna 43
 
44
require_once($CFG->dirroot . '/cesa/statics_blocks.php'); // Incluimos StaticsBlocks
45
 
46
 
47
/**
48
 * Renderers to align Moodle's HTML with that expected by Bootstrap
49
 *
50
 * @package    theme_universe
51
 * @copyright  2023 Marcin Czaja (https://rosea.io)
52
 * @license    Commercial https://themeforest.net/licenses
53
 */
1298 ariadna 54
class core_renderer extends \core_renderer
1291 ariadna 55
{
56
 
1298 ariadna 57
    public function edit_button(moodle_url $url, string $method = 'post')
1295 ariadna 58
    {
1298 ariadna 59
        if ($this->page->theme->haseditswitch) {
60
            return;
61
        }
62
        $url->param('sesskey', sesskey());
63
        if ($this->page->user_is_editing()) {
64
            $url->param('edit', 'off');
65
            $editstring = get_string('turneditingoff');
66
        } else {
67
            $url->param('edit', 'on');
68
            $editstring = get_string('turneditingon');
69
        }
70
        $button = new \single_button($url, $editstring, 'post', ['class' => 'btn btn-primary']);
71
        return $this->render_single_button($button);
72
    }
1295 ariadna 73
 
1298 ariadna 74
    /**
75
     * The standard tags (meta tags, links to stylesheets and JavaScript, etc.)
76
     * that should be included in the <head> tag. Designed to be called in theme
77
     * layout.php files.
78
     *
79
     * @return string HTML fragment.
80
     */
81
    public function standard_head_html()
82
    {
83
        $output = parent::standard_head_html();
84
        global $USER;
1295 ariadna 85
 
1298 ariadna 86
        $googleanalyticscode = "<script
87
                                    async
88
                                    src='https://www.googletagmanager.com/gtag/js?id=GOOGLE-ANALYTICS-CODE'>
89
                                </script>
90
                                <script>
91
                                    window.dataLayer = window.dataLayer || [];
92
                                    function gtag() {
93
                                        dataLayer.push(arguments);
94
                                    }
95
                                    gtag('js', new Date());
96
                                    gtag('config', 'GOOGLE-ANALYTICS-CODE');
97
                                </script>";
1295 ariadna 98
 
1298 ariadna 99
        $theme = theme_config::load('universe');
1295 ariadna 100
 
1298 ariadna 101
        if (!empty($theme->settings->googleanalytics) && isloggedin()) {
102
            $output .= str_replace(
103
                "GOOGLE-ANALYTICS-CODE",
104
                trim($theme->settings->googleanalytics),
105
                $googleanalyticscode
106
            );
107
        }
1295 ariadna 108
 
1298 ariadna 109
        return $output;
110
    }
1295 ariadna 111
 
112
 
1298 ariadna 113
    /**
114
     *
115
     * Method to load theme element form 'layout/parts' folder
116
     *
117
     */
118
    public function theme_part($name, $vars = array())
119
    {
120
 
121
        global $CFG;
122
 
123
        $element = $name . '.php';
124
        $candidate1 = $this->page->theme->dir . '/layout/parts/' . $element;
125
 
126
        // Require for child theme.
127
        if (file_exists($candidate1)) {
128
            $candidate = $candidate1;
129
        } else {
130
            $candidate = $CFG->dirroot . theme_universe_themedir() . '/universe/layout/parts/' . $element;
131
        }
132
 
133
        if (!is_readable($candidate)) {
134
            debugging("Could not include element $name.");
135
            return;
136
        }
137
 
138
        ob_start();
139
        include($candidate);
140
        $output = ob_get_clean();
141
        return $output;
142
    }
143
 
144
    /**
145
     * Renders the custom menu
146
     *
147
     * @param custom_menu $menu
148
     * @return mixed
149
     */
150
    protected function render_custom_menu(custom_menu $menu)
151
    {
152
        if (!$menu->has_children()) {
1295 ariadna 153
            return '';
154
        }
155
 
1298 ariadna 156
        $content = '';
157
        foreach ($menu->get_children() as $item) {
158
            $context = $item->export_for_template($this);
159
            $content .= $this->render_from_template('core/moremenu_children', $context);
160
        }
1295 ariadna 161
 
1298 ariadna 162
        return $content;
163
    }
164
 
165
    /**
166
     * Outputs the favicon urlbase.
167
     *
168
     * @return string an url
169
     */
170
    public function favicon()
171
    {
172
        global $CFG;
173
        $theme = theme_config::load('universe');
174
        $favicon = $theme->setting_file_url('favicon', 'favicon');
175
 
176
        if (!empty(($favicon))) {
177
            $urlreplace = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
178
            $favicon = str_replace($urlreplace, '', $favicon);
179
 
180
            return new moodle_url($favicon);
1295 ariadna 181
        }
182
 
1298 ariadna 183
        return parent::favicon();
184
    }
1295 ariadna 185
 
1298 ariadna 186
    public function render_lang_menu()
187
    {
188
        $langs = get_string_manager()->get_list_of_translations();
189
        $haslangmenu = $this->lang_menu() != '';
190
        $menu = new custom_menu;
1295 ariadna 191
 
1298 ariadna 192
        if ($haslangmenu) {
193
            $strlang = get_string('language');
194
            $currentlang = current_language();
195
            if (isset($langs[$currentlang])) {
196
                $currentlang = $langs[$currentlang];
197
            } else {
198
                $currentlang = $strlang;
199
            }
200
            $this->language = $menu->add($currentlang, new moodle_url('#'), $strlang, 10000);
201
            foreach ($langs as $langtype => $langname) {
202
                $this->language->add($langname, new moodle_url($this->page->url, array('lang' => $langtype)), $langname);
203
            }
204
            foreach ($menu->get_children() as $item) {
205
                $context = $item->export_for_template($this);
206
            }
1295 ariadna 207
 
1298 ariadna 208
            $context->currentlangname = array_search($currentlang, $langs);
209
 
210
            if (isset($context)) {
211
                return $this->render_from_template('theme_universe/lang_menu', $context);
1295 ariadna 212
            }
213
        }
1298 ariadna 214
    }
1295 ariadna 215
 
1298 ariadna 216
    public function render_lang_menu_login()
217
    {
218
        $langs = get_string_manager()->get_list_of_translations();
219
        $haslangmenu = $this->lang_menu() != '';
220
        $menu = new custom_menu;
1295 ariadna 221
 
1298 ariadna 222
        if ($haslangmenu) {
223
            $strlang = get_string('language');
224
            $currentlang = current_language();
225
            if (isset($langs[$currentlang])) {
226
                $currentlang = $langs[$currentlang];
227
            } else {
228
                $currentlang = $strlang;
229
            }
230
            $this->language = $menu->add($currentlang, new moodle_url('#'), $strlang, 10000);
231
            foreach ($langs as $langtype => $langname) {
232
                $this->language->add($langname, new moodle_url($this->page->url, array('lang' => $langtype)), $langname);
233
            }
234
            foreach ($menu->get_children() as $item) {
235
                $context = $item->export_for_template($this);
236
            }
1295 ariadna 237
 
1298 ariadna 238
            $context->currentlangname = array_search($currentlang, $langs);
1295 ariadna 239
 
1298 ariadna 240
            if (isset($context)) {
241
                return $this->render_from_template('theme_universe/lang_menu_login', $context);
242
            }
243
        }
244
    }
1295 ariadna 245
 
1298 ariadna 246
    public static function get_course_progress_count($course, $userid = 0)
247
    {
248
        global $USER;
1295 ariadna 249
 
1298 ariadna 250
        // Make sure we continue with a valid userid.
251
        if (empty($userid)) {
252
            $userid = $USER->id;
253
        }
1295 ariadna 254
 
1298 ariadna 255
        $completion = new \completion_info($course);
1295 ariadna 256
 
1298 ariadna 257
        // First, let's make sure completion is enabled.
258
        if (!$completion->is_enabled()) {
259
            return null;
260
        }
1295 ariadna 261
 
1298 ariadna 262
        if (!$completion->is_tracked_user($userid)) {
263
            return null;
1295 ariadna 264
        }
265
 
1298 ariadna 266
        // Before we check how many modules have been completed see if the course has.
267
        if ($completion->is_course_complete($userid)) {
268
            return 100;
269
        }
1295 ariadna 270
 
1298 ariadna 271
        // Get the number of modules that support completion.
272
        $modules = $completion->get_activities();
273
        $count = count($modules);
274
        if (!$count) {
275
            return null;
276
        }
1295 ariadna 277
 
1298 ariadna 278
        // Get the number of modules that have been completed.
279
        $completed = 0;
280
        foreach ($modules as $module) {
281
            $data = $completion->get_data($module, true, $userid);
282
            $completed += $data->completionstate == COMPLETION_INCOMPLETE ? 0 : 1;
283
        }
1295 ariadna 284
 
1298 ariadna 285
        return ($completed / $count) * 100;
286
    }
1295 ariadna 287
 
1298 ariadna 288
    /**
289
     *
290
     * Outputs the course progress if course completion is on.
291
     *
292
     * @return string Markup.
293
     */
294
    protected function courseprogress($course)
295
    {
296
        global $USER;
297
        $theme = \theme_config::load('universe');
1295 ariadna 298
 
1298 ariadna 299
        $output = '';
300
        $courseformat = course_get_format($course);
1295 ariadna 301
 
1298 ariadna 302
        if (get_class($courseformat) != 'format_tiles') {
303
            $completion = new \completion_info($course);
1295 ariadna 304
 
1298 ariadna 305
            // Start Course progress count.
306
            // Make sure we continue with a valid userid.
307
            if (empty($userid)) {
308
                $userid = $USER->id;
309
            }
310
            $completion = new \completion_info($course);
1295 ariadna 311
 
1298 ariadna 312
            // Get the number of modules that support completion.
313
            $modules = $completion->get_activities();
314
            $count = count($modules);
315
            if (!$count) {
316
                return null;
317
            }
1295 ariadna 318
 
1298 ariadna 319
            // Get the number of modules that have been completed.
320
            $completed = 0;
321
            foreach ($modules as $module) {
322
                $data = $completion->get_data($module, true, $userid);
323
                $completed += $data->completionstate == COMPLETION_INCOMPLETE ? 0 : 1;
324
            }
325
            $progresscountc = $completed;
326
            $progresscounttotal = $count;
327
            // End progress count.
1295 ariadna 328
 
1298 ariadna 329
            if ($completion->is_enabled()) {
330
                $templatedata = new \stdClass;
331
                $templatedata->progress = \core_completion\progress::get_course_progress_percentage($course);
332
                $templatedata->progresscountc = $progresscountc;
333
                $templatedata->progresscounttotal = $progresscounttotal;
334
 
335
                if (!is_null($templatedata->progress)) {
336
                    $templatedata->progress = floor($templatedata->progress);
337
                } else {
338
                    $templatedata->progress = 0;
1295 ariadna 339
                }
1298 ariadna 340
                if (get_config('theme_universe', 'courseprogressbar') == 1) {
341
                    $progressbar = '<div class="rui-course-progresschart">' .
342
                        $this->render_from_template('theme_universe/progress-chart', $templatedata) .
343
                        '</div>';
344
                    if (has_capability('report/progress:view',  \context_course::instance($course->id))) {
345
                        $courseprogress = new \moodle_url('/report/progress/index.php');
346
                        $courseprogress->param('course', $course->id);
347
                        $courseprogress->param('sesskey', sesskey());
348
                        $output .= html_writer::link($courseprogress, $progressbar, array('class' => 'rui-course-progressbar border rounded px-3 pt-2 mb-3'));
349
                    } else {
350
                        $output .= $progressbar;
351
                    }
352
                }
1295 ariadna 353
            }
1298 ariadna 354
        }
1295 ariadna 355
 
1298 ariadna 356
        return $output;
357
    }
1295 ariadna 358
 
359
 
1298 ariadna 360
    /**
361
     *
362
     * Returns HTML to display course contacts.
363
     *
364
     */
365
    public function course_teachers()
366
    {
367
        global $CFG, $COURSE, $DB;
368
        $course = $DB->get_record('course', ['id' => $COURSE->id]);
369
        $course = new core_course_list_element($course);
370
        $instructors = $course->get_course_contacts();
1295 ariadna 371
 
1298 ariadna 372
        if (!empty($instructors)) {
373
            $content = html_writer::start_div('course-teachers-box');
374
 
375
            foreach ($instructors as $key => $instructor) {
376
                $name = $instructor['username'];
377
                $role = $instructor['rolename'];
378
                $roleshortname = $instructor['role']->shortname;
379
 
380
                if ($instructor['role']->id == '3') {
381
                    $url = $CFG->wwwroot . '/user/profile.php?id=' . $key;
382
                    $user = $instructor['user'];
383
                    $userutil = new user($user->id);
384
                    $picture = $userutil->get_user_picture();
385
 
386
                    $content .= "<div class='course-contact-title-item'>
387
                        <a href='{$url}' 'title='{$name}'
388
                            class='course-contact rui-user-{$roleshortname}'>";
389
                    $content .= "<img src='{$picture}'
390
                        class='course-teacher-avatar' alt='{$name}'
391
                        title='{$name} - {$role}' data-toggle='tooltip'/>";
392
                    $content .= "<div class='course-teacher-content'>
393
                        <span class='course-teacher-role'>{$role}</span>
394
                        <h4 class='course-teacher-name'>{$name}</h4></div>";
395
                    $content .= "</a></div>";
396
                }
1295 ariadna 397
            }
398
 
1298 ariadna 399
            $content .= html_writer::end_div(); // End .teachers-box.
400
            return $content;
401
        }
402
    }
1295 ariadna 403
 
1298 ariadna 404
    public function course_contacts()
405
    {
406
        global $CFG, $COURSE, $DB;
407
        $course = $DB->get_record('course', ['id' => $COURSE->id]);
408
        $course = new core_course_list_element($course);
409
        $instructors = $course->get_course_contacts();
1295 ariadna 410
 
1298 ariadna 411
        if (!empty($instructors)) {
412
            $content = html_writer::start_div('course-teachers-box w-100');
1295 ariadna 413
 
1298 ariadna 414
            foreach ($instructors as $key => $instructor) {
415
                $name = $instructor['username'];
416
                $role = $instructor['rolename'];
417
                $roleshortname = $instructor['role']->shortname;
1295 ariadna 418
 
1298 ariadna 419
                $url = $CFG->wwwroot . '/user/profile.php?id=' . $key;
420
                $user = $instructor['user'];
421
                $userutil = new user($user->id);
422
                $picture = $userutil->get_user_picture(384);
1295 ariadna 423
 
1298 ariadna 424
                $user = $DB->get_record('user', array('id' => $key));
425
                $desc = $user->description;
1295 ariadna 426
 
1298 ariadna 427
                $content .= "<div class='rui-block-team-item text-center text-md-left
428
                    d-inline-flex flex-wrap align-items-start align-items-md-center'>";
429
                $content .= "<div class='rui-card-team--img-smpl'><img src='{$picture}'
430
                    class='rui-card-team--img-smpl mr-3 mr-md-5'
431
                    alt='{$name}, {$role}'/></div>";
432
                $content .= "<div class='rui-course-teacher--item col px-0 text-left'>
433
                    <a href='{$url}' 'title='{$name}'
434
                        class='course-contact rui-user-{$roleshortname}'>
435
                        <h4 class='mb-0'>{$name}</h4></a>
436
                        <span class='rui-block-text--3 rui-block-text--light mb-3'>{$role}</span>";
437
                $content .= "<div class='rui-block-text--2 mt-2'>{$desc}</div></div></div>";
1295 ariadna 438
            }
1298 ariadna 439
            $content .= html_writer::end_div(); // End .teachers-box.
440
            return $content;
1295 ariadna 441
        }
1298 ariadna 442
    }
1295 ariadna 443
 
1298 ariadna 444
    /**
445
     *
446
     * Returns HTML to display course details.
447
     *
448
     */
449
    protected function course_details()
450
    {
451
        global $CFG, $COURSE, $DB;
452
        $course = $DB->get_record('course', ['id' => $COURSE->id]);
453
        $course = new core_course_list_element($course);
454
        $content = '';
455
        $tempcourse = $DB->get_record('course_categories', ['id' => $COURSE->id]);
1295 ariadna 456
 
1298 ariadna 457
        $content .= html_writer::start_div('rui-course-details mt-4');
458
        $content .= html_writer::start_div('rui-custom-field-box rui-course-startdate');
459
        $content .= html_writer::tag('span', get_string('startdate', 'moodle'), ['class' => 'rui-custom-field-name']);
460
        $content .= html_writer::tag('span', date("F j, Y", $COURSE->startdate), ['class' => 'rui-custom-field-value']);
461
        $content .= html_writer::end_div();
1295 ariadna 462
 
1298 ariadna 463
        // Course End date.
464
        $courseenddate = $COURSE->enddate;
465
        if ($courseenddate != '0') {
466
            $content .= html_writer::start_div('rui-custom-field-box rui-course-startdate');
467
            $content .= html_writer::tag('span', get_string('enddate', 'moodle'), ['class' => 'rui-course-enddate-label rui-custom-field-name']);
468
            $content .= html_writer::tag('span', date("F j, Y", $courseenddate), ['class' => 'rui-course-enddate rui-custom-field-value']);
469
            $content .= html_writer::end_div();
470
        }
471
        $content .= html_writer::end_div(); // .rui-course-details.
1295 ariadna 472
 
1298 ariadna 473
        return $content;
474
    }
1295 ariadna 475
 
1298 ariadna 476
    /**
477
     *
478
     * Returns HTML to display course summary.
479
     *
480
     */
481
    protected function course_summary($courseid = 0, $content = '')
482
    {
483
        global $COURSE, $CFG;
484
        $output = '';
1295 ariadna 485
 
1298 ariadna 486
        require_once($CFG->libdir . '/filelib.php');
1295 ariadna 487
 
1298 ariadna 488
        $iscourseid = $courseid ? $courseid : $COURSE->id;
489
        $iscontent = $content ? $content : $COURSE->summary;
490
        $context = context_course::instance($iscourseid);
491
        $desc = file_rewrite_pluginfile_urls($iscontent, 'pluginfile.php', $context->id, 'course', 'summary', null);
492
 
493
        $output .= html_writer::start_div('rui-course-desc');
494
        $output .= format_text($desc, FORMAT_HTML);
495
        $output .= html_writer::end_div();
496
 
497
        return $output;
498
    }
499
 
500
    /**
501
     * Outputs the pix url base
502
     *
503
     * @return string an URL.
504
     */
505
    public function get_pix_image_url_base()
506
    {
507
        global $CFG;
508
 
509
        return $CFG->wwwroot . "/theme/universe/pix";
510
    }
511
 
512
    /**
513
     *
514
     */
515
    public function course_hero_url()
516
    {
517
        global $CFG, $COURSE, $DB;
518
 
519
        $course = $DB->get_record('course', ['id' => $COURSE->id]);
520
 
521
        $course = new core_course_list_element($course);
522
 
523
        $courseimage = '';
524
        $imageindex = 1;
525
        foreach ($course->get_course_overviewfiles() as $file) {
526
            $isimage = $file->is_valid_image();
527
 
528
            $url = new moodle_url("$CFG->wwwroot/pluginfile.php" . '/' .
529
                $file->get_contextid() . '/' . $file->get_component() . '/' .
530
                $file->get_filearea() .
531
                $file->get_filepath() .
532
                $file->get_filename(), ['forcedownload' => !$isimage]);
533
 
534
            if ($isimage) {
535
                $courseimage = $url;
1295 ariadna 536
            }
537
 
1298 ariadna 538
            if ($imageindex == 2) {
539
                break;
540
            }
1295 ariadna 541
 
1298 ariadna 542
            $imageindex++;
543
        }
1295 ariadna 544
 
1298 ariadna 545
        $html = '';
546
        // Create html for header.
547
        if (!empty($courseimage)) {
548
            $html .= $courseimage;
1295 ariadna 549
        }
1298 ariadna 550
        return $html;
551
    }
1295 ariadna 552
 
1298 ariadna 553
    /**
554
     * Returns HTML to display course hero.
555
     *
556
     */
557
    public function course_hero()
558
    {
559
        global $CFG, $COURSE, $DB;
1295 ariadna 560
 
1298 ariadna 561
        $course = $DB->get_record('course', ['id' => $COURSE->id]);
1295 ariadna 562
 
1298 ariadna 563
        $course = new core_course_list_element($course);
1295 ariadna 564
 
1298 ariadna 565
        $courseimage = '';
1295 ariadna 566
 
1298 ariadna 567
        $courseutil = new course($course);
568
        $courseimage = $courseutil->get_summary_image(false); // Remove repeatable pattern on the course page.
1295 ariadna 569
 
1298 ariadna 570
        $html = '';
571
        // Create html for header.
572
        if (!empty($courseimage)) {
573
            $html .= $courseimage;
574
        }
575
        return $html;
576
    }
1295 ariadna 577
 
578
 
579
 
580
 
1298 ariadna 581
    /**
582
     * Breadcrumbs
583
     *
584
     */
585
    public function breadcrumbs()
586
    {
587
        global $USER, $COURSE, $CFG;
1295 ariadna 588
 
1298 ariadna 589
        $header = new stdClass();
590
        $header->hasnavbar = empty($this->page->layout_options['nonavbar']);
591
        $header->navbar = $this->navbar();
592
        $header->courseheader = $this->course_header();
593
        $html = $this->render_from_template('theme_universe/breadcrumbs', $header);
594
 
595
        return $html;
596
    }
597
 
598
 
599
    /**
600
     * Wrapper for header elements.
601
     *
602
     * @return string HTML to display the main header.
603
     */
604
    public function simple_header()
605
    {
606
 
607
        global $USER, $COURSE, $CFG;
608
        $html = null;
609
 
610
        if (
611
            $this->page->include_region_main_settings_in_header_actions() &&
612
            !$this->page->blocks->is_block_present('settings')
613
        ) {
614
            // Only include the region main settings if the page has requested it and it doesn't already have
615
            // the settings block on it. The region main settings are included in the settings block and
616
            // duplicating the content causes behat failures.
617
            $this->page->add_header_action(html_writer::div(
618
                $this->region_main_settings_menu(),
619
                'd-print-none',
620
                ['id' => 'region-main-settings-menu']
621
            ));
1295 ariadna 622
        }
623
 
1298 ariadna 624
        $header = new stdClass();
625
        $header->settingsmenu = $this->context_header_settings_menu();
626
        $header->contextheader = $this->context_header();
627
        $header->hasnavbar = empty($this->page->layout_options['nonavbar']);
628
        $header->navbar = $this->navbar();
629
        $header->pageheadingbutton = $this->page_heading_button();
630
        $header->courseheader = $this->course_header();
631
        $header->headeractions = $this->page->get_header_actions();
1295 ariadna 632
 
1298 ariadna 633
        if ($this->page->pagelayout != 'admin') {
634
            $html .= $this->render_from_template('theme_universe/header', $header);
635
        }
1295 ariadna 636
 
1298 ariadna 637
        if ($this->page->pagelayout == 'admin') {
638
            $html .= $this->render_from_template('theme_universe/header_admin', $header);
639
        }
1295 ariadna 640
 
1298 ariadna 641
        return $html;
642
    }
1295 ariadna 643
 
1298 ariadna 644
    public function display_course_progress()
645
    {
646
        $html = null;
647
        $html .= $this->courseprogress($this->page->course);
648
        return $html;
649
    }
1295 ariadna 650
 
1298 ariadna 651
    /**
652
     * Wrapper for header elements.
653
     *
654
     * @return string HTML to display the main header.
655
     */
656
    public function full_header()
657
    {
658
        global $USER, $COURSE, $CFG;
659
        $theme = \theme_config::load('universe');
660
        $html = null;
661
        $pagetype = $this->page->pagetype;
662
        $homepage = get_home_page();
663
        $homepagetype = null;
664
        // Add a special case since /my/courses is a part of the /my subsystem.
665
        if ($homepage == HOMEPAGE_MY || $homepage == HOMEPAGE_MYCOURSES) {
666
            $homepagetype = 'my-index';
667
        } else if ($homepage == HOMEPAGE_SITE) {
668
            $homepagetype = 'site-index';
669
        }
670
        if (
671
            $this->page->include_region_main_settings_in_header_actions() &&
672
            !$this->page->blocks->is_block_present('settings')
673
        ) {
674
            // Only include the region main settings if the page has requested it and it doesn't already have
675
            // the settings block on it. The region main settings are included in the settings block and
676
            // duplicating the content causes behat failures.
677
            $this->page->add_header_action(html_writer::div(
678
                $this->region_main_settings_menu(),
679
                'd-print-none',
680
                ['id' => 'region-main-settings-menu']
681
            ));
682
        }
683
 
684
        $header = new stdClass();
685
        $header->settingsmenu = $this->context_header_settings_menu();
686
        $header->contextheader = $this->context_header();
687
        $header->hasnavbar = empty($this->page->layout_options['nonavbar']);
688
        $header->navbar = $this->navbar();
689
        $header->pageheadingbutton = $this->page_heading_button();
690
        $header->courseheader = $this->course_header();
691
        $header->headeractions = $this->page->get_header_actions();
692
 
693
        if ($this->page->theme->settings->ipcoursedetails == 1) {
694
            $html .= $this->course_details();
695
        }
696
 
697
        $html .= $this->render_from_template('theme_universe/header', $header);
698
        if ($this->page->theme->settings->ipcoursesummary == 1) {
699
            $html .= $this->course_summary();
700
        }
701
 
702
        $html .= html_writer::start_tag('div', array('class' => 'rui-course-header-color'));
703
        if ($this->page->theme->settings->cccteachers == 1) {
704
            $html .= $this->course_teachers();
705
        }
706
 
707
        $html .= html_writer::end_tag('div'); // End .rui-course-header.
708
 
709
        return $html;
710
    }
711
 
712
 
713
    /**
714
     * Wrapper for header elements.
715
     *
716
     * @return string HTML to display the main header.
717
     */
718
    public function clean_header()
719
    {
720
        global $USER, $COURSE, $CFG;
721
        $theme = \theme_config::load('universe');
722
        $html = null;
723
        $pagetype = $this->page->pagetype;
724
        $homepage = get_home_page();
725
        $homepagetype = null;
726
        // Add a special case since /my/courses is a part of the /my subsystem.
727
        if ($homepage == HOMEPAGE_MY || $homepage == HOMEPAGE_MYCOURSES) {
728
            $homepagetype = 'my-index';
729
        } else if ($homepage == HOMEPAGE_SITE) {
730
            $homepagetype = 'site-index';
731
        }
732
        if (
733
            $this->page->include_region_main_settings_in_header_actions() &&
734
            !$this->page->blocks->is_block_present('settings')
735
        ) {
736
            // Only include the region main settings if the page has requested it and it doesn't already have
737
            // the settings block on it. The region main settings are included in the settings block and
738
            // duplicating the content causes behat failures.
739
            $this->page->add_header_action(html_writer::div(
740
                $this->region_main_settings_menu(),
741
                'd-print-none',
742
                ['id' => 'region-main-settings-menu']
743
            ));
744
        }
745
 
746
        $header = new stdClass();
747
        $header->courseheader = $this->course_header();
748
        $header->headeractions = $this->page->get_header_actions();
749
 
750
        $html .= $this->render_from_template('theme_universe/header', $header);
751
 
752
        return $html;
753
    }
754
 
755
 
756
    /**
757
     * Returns standard navigation between activities in a course.
758
     *
759
     * @return string the navigation HTML.
760
     */
761
    public function activity_navigation()
762
    {
763
        // First we should check if we want to add navigation.
764
        $context = $this->page->context;
765
        if (($this->page->pagelayout !== 'incourse' && $this->page->pagelayout !== 'frametop')
766
            || $context->contextlevel != CONTEXT_MODULE
767
        ) {
768
            return '';
769
        }
770
        // If the activity is in stealth mode, show no links.
771
        if ($this->page->cm->is_stealth()) {
772
            return '';
773
        }
774
        $course = $this->page->cm->get_course();
775
        $courseformat = course_get_format($course);
776
 
777
        // Get a list of all the activities in the course.
778
        $modules = get_fast_modinfo($course->id)->get_cms();
779
        // Put the modules into an array in order by the position they are shown in the course.
780
        $mods = [];
781
        $activitylist = [];
782
        foreach ($modules as $module) {
783
            // Only add activities the user can access, aren't in stealth mode and have a url (eg. mod_label does not).
784
            if (!$module->uservisible || $module->is_stealth() || empty($module->url)) {
1295 ariadna 785
                continue;
786
            }
1298 ariadna 787
            $mods[$module->id] = $module;
788
            // No need to add the current module to the list for the activity dropdown menu.
789
            if ($module->id == $this->page->cm->id) {
790
                continue;
791
            }
792
            // Module name.
793
            $modname = $module->get_formatted_name();
794
            // Display the hidden text if necessary.
795
            if (!$module->visible) {
796
                $modname .= ' ' . get_string('hiddenwithbrackets');
797
            }
798
            // Module URL.
799
            $linkurl = new moodle_url($module->url, array('forceview' => 1));
800
            // Add module URL (as key) and name (as value) to the activity list array.
801
            $activitylist[$linkurl->out(false)] = $modname;
802
        }
803
        $nummods = count($mods);
804
        // If there is only one mod then do nothing.
805
        if ($nummods == 1) {
806
            return '';
807
        }
808
        // Get an array of just the course module ids used to get the cmid value based on their position in the course.
809
        $modids = array_keys($mods);
810
        // Get the position in the array of the course module we are viewing.
811
        $position = array_search($this->page->cm->id, $modids);
812
        $prevmod = null;
813
        $nextmod = null;
814
        // Check if we have a previous mod to show.
815
        if ($position > 0) {
816
            $prevmod = $mods[$modids[$position - 1]];
817
        }
818
        // Check if we have a next mod to show.
819
        if ($position < ($nummods - 1)) {
820
            $nextmod = $mods[$modids[$position + 1]];
821
        }
822
        $activitynav = new \core_course\output\activity_navigation($prevmod, $nextmod, $activitylist);
823
        $renderer = $this->page->get_renderer('core', 'course');
1301 ariadna 824
        if ($this->cesa_navigation_course_completion() == '') {
825
            return $renderer->render($activitynav);
826
        }
827
        return '';
1298 ariadna 828
    }
1295 ariadna 829
 
830
 
1301 ariadna 831
 
1298 ariadna 832
    /**
833
     * This is an optional menu that can be added to a layout by a theme. It contains the
834
     * menu for the course administration, only on the course main page.
835
     *
836
     * @return string
837
     */
838
    public function context_header_settings_menu()
839
    {
840
        $context = $this->page->context;
841
        $menu = new action_menu();
1295 ariadna 842
 
1298 ariadna 843
        $items = $this->page->navbar->get_items();
844
        $currentnode = end($items);
845
 
846
        $showcoursemenu = false;
847
        $showfrontpagemenu = false;
848
        $showusermenu = false;
849
 
850
        // We are on the course home page.
851
        if (($context->contextlevel == CONTEXT_COURSE) &&
852
            !empty($currentnode) &&
853
            ($currentnode->type == navigation_node::TYPE_COURSE || $currentnode->type == navigation_node::TYPE_SECTION)
854
        ) {
855
            $showcoursemenu = true;
856
        }
857
 
858
        $courseformat = course_get_format($this->page->course);
859
        // This is a single activity course format, always show the course menu on the activity main page.
860
        if (
861
            $context->contextlevel == CONTEXT_MODULE &&
862
            !$courseformat->has_view_page()
863
        ) {
864
 
865
            $this->page->navigation->initialise();
866
            $activenode = $this->page->navigation->find_active_node();
867
            // If the settings menu has been forced then show the menu.
868
            if ($this->page->is_settings_menu_forced()) {
869
                $showcoursemenu = true;
870
            } else if (!empty($activenode) && ($activenode->type == navigation_node::TYPE_ACTIVITY ||
871
                $activenode->type == navigation_node::TYPE_RESOURCE)) {
872
 
873
                // We only want to show the menu on the first page of the activity. This means
874
                // the breadcrumb has no additional nodes.
875
                if ($currentnode && ($currentnode->key == $activenode->key && $currentnode->type == $activenode->type)) {
876
                    $showcoursemenu = true;
1295 ariadna 877
                }
1298 ariadna 878
            }
879
        }
1295 ariadna 880
 
1298 ariadna 881
        // This is the site front page.
882
        if (
883
            $context->contextlevel == CONTEXT_COURSE &&
884
            !empty($currentnode) &&
885
            $currentnode->key === 'home'
886
        ) {
887
            $showfrontpagemenu = true;
888
        }
889
 
890
        // This is the user profile page.
891
        if (
892
            $context->contextlevel == CONTEXT_USER &&
893
            !empty($currentnode) &&
894
            ($currentnode->key === 'myprofile')
895
        ) {
896
            $showusermenu = true;
897
        }
898
 
899
        if ($showfrontpagemenu) {
900
            $settingsnode = $this->page->settingsnav->find('frontpage', navigation_node::TYPE_SETTING);
901
            if ($settingsnode) {
902
                // Build an action menu based on the visible nodes from this navigation tree.
903
                $skipped = $this->build_action_menu_from_navigation($menu, $settingsnode, false, true);
904
 
905
                // We only add a list to the full settings menu if we didn't include every node in the short menu.
906
                if ($skipped) {
907
                    $text = get_string('morenavigationlinks');
908
                    $url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
909
                    $link = new action_link($url, $text, null, null, new pix_icon('t/edit', $text));
910
                    $menu->add_secondary_action($link);
1295 ariadna 911
                }
1298 ariadna 912
            }
913
        } else if ($showcoursemenu) {
914
            $settingsnode = $this->page->settingsnav->find('courseadmin', navigation_node::TYPE_COURSE);
915
            if ($settingsnode) {
916
                // Build an action menu based on the visible nodes from this navigation tree.
917
                $skipped = $this->build_action_menu_from_navigation($menu, $settingsnode, false, true);
1295 ariadna 918
 
1298 ariadna 919
                // We only add a list to the full settings menu if we didn't include every node in the short menu.
920
                if ($skipped) {
921
                    $text = get_string('morenavigationlinks');
922
                    $url = new moodle_url('/course/admin.php', array('courseid' => $this->page->course->id));
923
                    $link = new action_link($url, $text, null, null, new pix_icon('t/edit', $text));
924
                    $menu->add_secondary_action($link);
925
                }
926
            }
927
        } else if ($showusermenu) {
928
            // Get the course admin node from the settings navigation.
929
            $settingsnode = $this->page->settingsnav->find('useraccount', navigation_node::TYPE_CONTAINER);
930
            if ($settingsnode) {
931
                // Build an action menu based on the visible nodes from this navigation tree.
932
                $this->build_action_menu_from_navigation($menu, $settingsnode);
933
            }
934
        }
1295 ariadna 935
 
1298 ariadna 936
        return $this->render($menu);
937
    }
1295 ariadna 938
 
1298 ariadna 939
    public function customeditblockbtn()
940
    {
941
        $header = new stdClass();
942
        $header->settingsmenu = $this->context_header_settings_menu();
943
        $header->pageheadingbutton = $this->page_heading_button();
1295 ariadna 944
 
1298 ariadna 945
        $html = $this->render_from_template('theme_universe/header_settings_menu', $header);
1295 ariadna 946
 
1298 ariadna 947
        return $html;
948
    }
1295 ariadna 949
 
1298 ariadna 950
    /**
951
     * Renders the context header for the page.
952
     *
953
     * @param array $headerinfo Heading information.
954
     * @param int $headinglevel What 'h' level to make the heading.
955
     * @return string A rendered context header.
956
     */
957
    public function context_header($headerinfo = null, $headinglevel = 1): string
958
    {
959
        global $DB, $USER, $CFG, $SITE;
960
        require_once($CFG->dirroot . '/user/lib.php');
961
        $context = $this->page->context;
962
        $heading = null;
963
        $imagedata = null;
964
        $subheader = null;
965
        $userbuttons = null;
1295 ariadna 966
 
1298 ariadna 967
        // Make sure to use the heading if it has been set.
968
        if (isset($headerinfo['heading'])) {
969
            $heading = $headerinfo['heading'];
970
        } else {
971
            $heading = $this->page->heading;
972
        }
1295 ariadna 973
 
1298 ariadna 974
        // The user context currently has images and buttons. Other contexts may follow.
975
        if ((isset($headerinfo['user']) || $context->contextlevel == CONTEXT_USER) && $this->page->pagetype !== 'my-index') {
976
            if (isset($headerinfo['user'])) {
977
                $user = $headerinfo['user'];
978
            } else {
979
                // Look up the user information if it is not supplied.
980
                $user = $DB->get_record('user', array('id' => $context->instanceid));
981
            }
1295 ariadna 982
 
1298 ariadna 983
            // If the user context is set, then use that for capability checks.
984
            if (isset($headerinfo['usercontext'])) {
985
                $context = $headerinfo['usercontext'];
986
            }
1295 ariadna 987
 
1298 ariadna 988
            // Only provide user information if the user is the current user, or a user which the current user can view.
989
            // When checking user_can_view_profile(), either:
990
            // If the page context is course, check the course context (from the page object) or;
991
            // If page context is NOT course, then check across all courses.
992
            $course = ($this->page->context->contextlevel == CONTEXT_COURSE) ? $this->page->course : null;
1295 ariadna 993
 
1298 ariadna 994
            if (user_can_view_profile($user, $course)) {
995
                // Use the user's full name if the heading isn't set.
996
                if (empty($heading)) {
997
                    $heading = fullname($user);
998
                }
1295 ariadna 999
 
1298 ariadna 1000
                $imagedata = $this->user_picture($user, array('size' => 100));
1295 ariadna 1001
 
1298 ariadna 1002
                // Check to see if we should be displaying a message button.
1003
                if (!empty($CFG->messaging) && has_capability('moodle/site:sendmessage', $context)) {
1004
                    $userbuttons = array(
1005
                        'messages' => array(
1006
                            'buttontype' => 'message',
1007
                            'title' => get_string('message', 'message'),
1008
                            'url' => new moodle_url('/message/index.php', array('id' => $user->id)),
1009
                            'image' => 'message',
1010
                            'linkattributes' => \core_message\helper::messageuser_link_params($user->id),
1011
                            'page' => $this->page
1012
                        )
1013
                    );
1014
 
1015
                    if ($USER->id != $user->id) {
1016
                        $iscontact = \core_message\api::is_contact($USER->id, $user->id);
1017
                        $contacttitle = $iscontact ? 'removefromyourcontacts' : 'addtoyourcontacts';
1018
                        $contacturlaction = $iscontact ? 'removecontact' : 'addcontact';
1019
                        $contactimage = $iscontact ? 'removecontact' : 'addcontact';
1020
                        $userbuttons['togglecontact'] = array(
1021
                            'buttontype' => 'togglecontact',
1022
                            'title' => get_string($contacttitle, 'message'),
1023
                            'url' => new moodle_url(
1024
                                '/message/index.php',
1025
                                array(
1026
                                    'user1' => $USER->id,
1027
                                    'user2' => $user->id,
1028
                                    $contacturlaction => $user->id,
1029
                                    'sesskey' => sesskey()
1030
                                )
1031
                            ),
1032
                            'image' => $contactimage,
1033
                            'linkattributes' => \core_message\helper::togglecontact_link_params($user, $iscontact),
1034
                            'page' => $this->page
1035
                        );
1295 ariadna 1036
                    }
1298 ariadna 1037
 
1038
                    $this->page->requires->string_for_js('changesmadereallygoaway', 'moodle');
1295 ariadna 1039
                }
1298 ariadna 1040
            } else {
1041
                $heading = null;
1042
            }
1043
        }
1295 ariadna 1044
 
1298 ariadna 1045
        $prefix = null;
1046
        if ($context->contextlevel == CONTEXT_MODULE) {
1047
            if ($this->page->course->format === 'singleactivity') {
1048
                $heading = $this->page->course->fullname;
1049
            } else {
1050
                $heading = $this->page->cm->get_formatted_name();
1051
                $imagedata = $this->pix_icon('monologo', '', $this->page->activityname, ['class' => 'activityicon']);
1052
                $purposeclass = plugin_supports('mod', $this->page->activityname, FEATURE_MOD_PURPOSE);
1053
                $purposeclass .= ' activityiconcontainer';
1054
                $purposeclass .= ' modicon_' . $this->page->activityname;
1055
                $imagedata = html_writer::tag('div', $imagedata, ['class' => $purposeclass]);
1056
                $prefix = get_string('modulename', $this->page->activityname);
1057
            }
1058
        }
1295 ariadna 1059
 
1298 ariadna 1060
        $contextheader = new \context_header($heading, $headinglevel, $imagedata, $userbuttons, $prefix);
1061
        return $this->render_context_header($contextheader);
1062
    }
1295 ariadna 1063
 
1064
 
1298 ariadna 1065
    /**
1066
     * Construct a user menu, returning HTML that can be echoed out by a
1067
     * layout file.
1068
     *
1069
     * @param stdClass $user A user object, usually $USER.
1070
     * @param bool $withlinks true if a dropdown should be built.
1071
     * @return string HTML fragment.
1072
     */
1073
    public function user_menu($user = null, $withlinks = null)
1074
    {
1075
        global $USER, $CFG;
1076
        require_once($CFG->dirroot . '/user/lib.php');
1077
 
1078
        if (is_null($user)) {
1079
            $user = $USER;
1080
        }
1081
 
1082
        // Note: this behaviour is intended to match that of core_renderer::login_info,
1083
        // but should not be considered to be good practice; layout options are
1084
        // intended to be theme-specific. Please don't copy this snippet anywhere else.
1085
        if (is_null($withlinks)) {
1086
            $withlinks = empty($this->page->layout_options['nologinlinks']);
1087
        }
1088
 
1089
        // Add a class for when $withlinks is false.
1090
        $usermenuclasses = 'usermenu';
1091
        if (!$withlinks) {
1092
            $usermenuclasses .= ' withoutlinks';
1093
        }
1094
 
1095
        $returnstr = "";
1096
 
1097
        // If during initial install, return the empty return string.
1098
        if (during_initial_install()) {
1099
            return $returnstr;
1100
        }
1101
 
1102
        $loginpage = $this->is_login_page();
1103
        $loginurl = get_login_url();
1104
        // If not logged in, show the typical not-logged-in string.
1105
        if (!isloggedin()) {
1106
            if (!$loginpage) {
1107
                $returnstr .= "<a class=\"rui-topbar-btn rui-login-btn\" href=\"$loginurl\"><span class=\"rui-login-btn-txt\">" .
1108
                    get_string('login') .
1109
                    '</span>
1110
                <svg class="ml-2" width="20" height="20" fill="none" viewBox="0 0 24 24">
1111
                <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
1112
                d="M9.75 8.75L13.25 12L9.75 15.25"></path>
1113
                <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
1114
                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">
1115
                </path>
1116
                <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 12H4.75"></path>
1117
                </svg></a>';
1118
            }
1119
            return html_writer::div(
1120
                html_writer::span(
1121
                    $returnstr,
1122
                    'login'
1123
                ),
1124
                $usermenuclasses
1125
            );
1126
        }
1127
 
1128
        // If logged in as a guest user, show a string to that effect.
1129
        if (isguestuser()) {
1130
            $icon = '<svg class="mr-2"
1131
                width="24"
1132
                height="24"
1133
                viewBox="0 0 24 24"
1134
                fill="none"
1135
                xmlns="http://www.w3.org/2000/svg">
1136
            <path d="M10 12C10 12.5523 9.55228 13 9 13C8.44772 13 8 12.5523 8
1137
            12C8 11.4477 8.44772 11 9 11C9.55228 11 10 11.4477 10 12Z"
1138
                fill="currentColor"
1139
                />
1140
            <path d="M15 13C15.5523 13 16 12.5523 16 12C16 11.4477 15.5523 11
1141
            15 11C14.4477 11 14 11.4477 14 12C14 12.5523 14.4477 13 15 13Z"
1142
                fill="currentColor"
1143
                />
1144
            <path fill-rule="evenodd"
1145
                clip-rule="evenodd"
1146
                d="M12.0244 2.00003L12 2C6.47715 2 2 6.47715 2 12C2 17.5228
1147
                6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.74235
1148
            17.9425 2.43237 12.788 2.03059L12.7886 2.0282C12.5329 2.00891
1149
            12.278 1.99961 12.0244 2.00003ZM12 20C16.4183 20 20 16.4183 20
1150
            12C20 11.3014 19.9105 10.6237 19.7422
1151
            9.97775C16.1597 10.2313 12.7359 8.52461 10.7605 5.60246C9.31322
1152
            7.07886 7.2982 7.99666 5.06879 8.00253C4.38902 9.17866 4 10.5439 4
1153
            12C4 16.4183 7.58172 20
1154
            12 20ZM11.9785 4.00003L12.0236 4.00003L12 4L11.9785 4.00003Z"
1155
                fill="currentColor"
1156
                /></svg>';
1157
            $returnstr = '<div class="rui-badge-guest">' . $icon . get_string('loggedinasguest') . '</div>';
1158
            if (!$loginpage && $withlinks) {
1159
                $returnstr .= "<a class=\"rui-topbar-btn rui-login-btn\"
1160
                    href=\"$loginurl\"><span class=\"rui-login-btn-txt\">" .
1161
                    get_string('login') .
1162
                    '</span>
1163
                <svg class="ml-2"
1164
                    width="20"
1165
                    height="20"
1166
                    fill="none"
1167
                    viewBox="0 0 24 24">
1168
                <path stroke="currentColor"
1169
                    stroke-linecap="round"
1170
                    stroke-linejoin="round"
1171
                    stroke-width="2"
1172
                    d="M9.75 8.75L13.25 12L9.75 15.25"></path>
1173
                <path stroke="currentColor"
1174
                    stroke-linecap="round"
1175
                    stroke-linejoin="round"
1176
                    stroke-width="2"
1177
                    d="M9.75 4.75H17.25C18.3546 4.75 19.25 5.64543 19.25
1178
                    6.75V17.25C19.25 18.3546 18.3546 19.25 17.25 19.25H9.75"></path>
1179
                    <path stroke="currentColor"
1180
                        stroke-linecap="round"
1181
                        stroke-linejoin="round"
1182
                        stroke-width="2"
1183
                        d="M13 12H4.75"></path></svg></a>';
1184
            }
1185
 
1186
            return html_writer::div(
1187
                html_writer::span(
1188
                    $returnstr,
1189
                    'login'
1190
                ),
1191
                $usermenuclasses
1192
            );
1193
        }
1194
 
1195
        // Get some navigation opts.
1196
        $opts = user_get_user_navigation_info($user, $this->page, array('avatarsize' => 56));
1197
 
1198
        $avatarclasses = "avatars";
1199
        $avatarcontents = html_writer::span($opts->metadata['useravatar'], 'avatar current');
1200
        $usertextcontents = '<span class="rui-fullname">' . $opts->metadata['userfullname'] . '</span>';
1201
        $usertextmail = $user->email;
1202
        $usernick = '<svg class="mr-1"
1203
            width="16"
1204
            height="16"
1205
            fill="none"
1206
            viewBox="0 0 24 24">
1207
        <path stroke="currentColor"
1208
            stroke-linecap="round"
1209
            stroke-linejoin="round"
1210
            stroke-width="2"
1211
            d="M12 13V15"></path>
1212
        <circle cx="12"
1213
            cy="9"
1214
            r="1"
1215
            fill="currentColor"></circle>
1216
        <circle cx="12"
1217
            cy="12"
1218
            r="7.25"
1219
            stroke="currentColor"
1220
            stroke-linecap="round"
1221
            stroke-linejoin="round"
1222
            stroke-width="1.5"></circle>
1223
        </svg>' . $user->username;
1224
 
1225
        // Other user.
1226
        $usermeta = '';
1227
        if (!empty($opts->metadata['asotheruser'])) {
1228
            $avatarcontents .= html_writer::span(
1229
                $opts->metadata['realuseravatar'],
1230
                'avatar realuser'
1231
            );
1232
            $usermeta .= $opts->metadata['realuserfullname'];
1233
            $usermeta .= html_writer::tag(
1234
                'span',
1235
                get_string(
1236
                    'loggedinas',
1237
                    'moodle',
1238
                    html_writer::span(
1239
                        $opts->metadata['userfullname'],
1240
                        'value'
1241
                    )
1242
                ),
1243
                array('class' => 'meta viewingas')
1244
            );
1245
        }
1246
 
1247
        // Role.
1248
        if (!empty($opts->metadata['asotherrole'])) {
1249
            $role = core_text::strtolower(preg_replace('#[ ]+#', '-', trim($opts->metadata['rolename'])));
1250
            $usermeta .= html_writer::span(
1251
                $opts->metadata['rolename'],
1252
                'meta role role-' . $role
1253
            );
1254
        }
1255
 
1256
        // User login failures.
1257
        if (!empty($opts->metadata['userloginfail'])) {
1258
            $usermeta .= html_writer::div(
1259
                '<svg class="mr-1"
1260
                width="16"
1261
                height="16"
1262
                fill="none"
1263
                viewBox="0 0 24 24"><path stroke="currentColor"
1264
                stroke-linecap="round"
1265
                stroke-linejoin="round"
1266
                stroke-width="1.5"
1267
                d="M4.9522 16.3536L10.2152 5.85658C10.9531 4.38481 13.0539
1268
                4.3852 13.7913 5.85723L19.0495 16.3543C19.7156 17.6841 18.7487
1269
                19.25 17.2613 19.25H6.74007C5.25234
1270
                19.25 4.2854 17.6835 4.9522 16.3536Z">
1271
                </path><path stroke="currentColor"
1272
                stroke-linecap="round"
1273
                stroke-linejoin="round"
1274
                stroke-width="2"
1275
                d="M12 10V12"></path>
1276
                <circle cx="12" cy="16" r="1" fill="currentColor"></circle></svg>' .
1277
                    $opts->metadata['userloginfail'],
1278
                'meta loginfailures'
1279
            );
1280
        }
1281
 
1282
        // MNet.
1283
        if (!empty($opts->metadata['asmnetuser'])) {
1284
            $mnet = strtolower(preg_replace('#[ ]+#', '-', trim($opts->metadata['mnetidprovidername'])));
1285
            $usermeta .= html_writer::span(
1286
                $opts->metadata['mnetidprovidername'],
1287
                'meta mnet mnet-' . $mnet
1288
            );
1289
        }
1290
 
1291
        $returnstr .= html_writer::span(
1292
            html_writer::span($avatarcontents, $avatarclasses),
1293
            'userbutton'
1294
        );
1295
 
1296
        // Create a divider (well, a filler).
1297
        $divider = new action_menu_filler();
1298
        $divider->primary = false;
1299
 
1300
        $am = new action_menu();
1301
        $am->set_menu_trigger(
1302
            $returnstr
1303
        );
1304
        $am->set_action_label(get_string('usermenu'));
1305
        $am->set_nowrap_on_items();
1306
 
1307
        if ($CFG->enabledashboard) {
1308
            $dashboardlink = '<div class="dropdown-item-wrapper"><a class="dropdown-item" href="' .
1309
                new moodle_url('/my/') .
1310
                '" data-identifier="dashboard,moodle" title="dashboard,moodle">' .
1311
                get_string('myhome', 'moodle') .
1312
                '</a></div>';
1313
        } else {
1314
            $dashboardlink = null;
1315
        }
1316
 
1317
        $am->add(
1318
            '<div class="dropdown-user-wrapper"><div class="dropdown-user">' . $usertextcontents  . '</div>'
1319
                . '<div class="dropdown-user-mail text-truncate" title="' . $usertextmail . '">' . $usertextmail . '</div>'
1320
                . '<span class="dropdown-user-nick w-100">' . $usernick . '</span>'
1321
                . '<div class="dropdown-user-meta"><span class="badge-xs badge-sq badge-warning flex-wrap">' .
1322
                $usermeta . '</span></div>'
1323
                . '</div><div class="dropdown-divider dropdown-divider-user"></div>' . $dashboardlink
1324
        );
1325
 
1326
        if ($withlinks) {
1327
            $navitemcount = count($opts->navitems);
1328
            $idx = 0;
1329
            foreach ($opts->navitems as $key => $value) {
1330
 
1331
                switch ($value->itemtype) {
1332
                    case 'divider':
1333
                        // If the nav item is a divider, add one and skip link processing.
1334
                        $am->add($divider);
1335
                        break;
1336
 
1337
                    case 'invalid':
1338
                        // Silently skip invalid entries (should we post a notification?).
1339
                        break;
1340
 
1341
                    case 'link':
1342
                        $al = '<a class="dropdown-item" href="' .
1343
                            $value->url .
1344
                            '" data-identifier="' .
1345
                            $value->titleidentifier .
1346
                            '" title="' .
1347
                            $value->titleidentifier .
1348
                            '">' .
1349
                            $value->title . '</a>';
1350
                        $am->add($al);
1351
                        break;
1295 ariadna 1352
                }
1353
 
1298 ariadna 1354
                $idx++;
1295 ariadna 1355
 
1298 ariadna 1356
                // Add dividers after the first item and before the last item.
1357
                if ($idx == 1 || $idx == $navitemcount - 1) {
1358
                    $am->add($divider);
1295 ariadna 1359
                }
1298 ariadna 1360
            }
1361
        }
1295 ariadna 1362
 
1301 ariadna 1363
 
1364
 
1298 ariadna 1365
        return html_writer::div(
1366
            $this->render($am),
1367
            $usermenuclasses
1368
        );
1369
    }
1370
 
1371
 
1372
    /**
1373
     * Returns standard main content placeholder.
1374
     * Designed to be called in theme layout.php files.
1375
     *
1376
     * @return string HTML fragment.
1307 ariadna 1377
     */
1298 ariadna 1378
    public function main_content()
1379
    {
1312 ariadna 1380
        $this->page->set_state(moodle_page::STATE_IN_BODY);
1381
        ob_start();
1382
        $this->page->get_renderer('core')->render_page_content();
1383
        return ob_get_clean();
1298 ariadna 1384
    }
1385
 
1386
    /**
1387
     * Outputs a heading
1388
     *
1389
     * @param string $text The text of the heading
1390
     * @param int $level The level of importance of the heading. Defaulting to 2
1391
     * @param string $classes A space-separated list of CSS classes. Defaulting to null
1392
     * @param string $id An optional ID
1393
     * @return string the HTML to output.
1394
     */
1395
    public function heading($text, $level = 2, $classes = null, $id = null)
1396
    {
1397
        $level = (int) $level;
1398
        if ($level < 1 || $level > 6) {
1399
            throw new coding_exception('Heading level must be an integer between 1 and 6.');
1400
        }
1401
        return html_writer::tag('div', html_writer::tag('h' .
1402
            $level, $text, array('id' => $id, 'class' => renderer_base::prepare_classes($classes) .
1403
            ' rui-main-content-title rui-main-content-title--h' .
1404
            $level)), array('class' => 'rui-title-container'));
1405
    }
1406
 
1407
 
1408
    public function headingwithavatar($text, $level = 2, $classes = null, $id = null)
1409
    {
1410
        $level = (int) $level;
1411
        if ($level < 1 || $level > 6) {
1412
            throw new coding_exception('Heading level must be an integer between 1 and 6.');
1413
        }
1414
        return html_writer::tag('div', html_writer::tag('h' .
1415
            $level, $text, array('id' => $id, 'class' => renderer_base::prepare_classes($classes) .
1416
            ' rui-main-content-title-with-avatar')), array('class' => 'rui-title-container-with-avatar'));
1417
    }
1418
 
1419
    /**
1420
     * Renders the login form.
1421
     *
1422
     * @param \core_auth\output\login $form The renderable.
1423
     * @return string
1424
     */
1425
    public function render_login(\core_auth\output\login $form)
1426
    {
1427
        global $CFG, $SITE;
1428
 
1429
        $context = $form->export_for_template($this);
1430
 
1431
        // Override because rendering is not supported in template yet.
1432
        if ($CFG->rememberusername == 0) {
1433
            $context->cookieshelpiconformatted = $this->help_icon('cookiesenabledonlysession');
1434
        } else {
1435
            $context->cookieshelpiconformatted = $this->help_icon('cookiesenabled');
1436
        }
1437
        $context->errorformatted = $this->error_text($context->error);
1438
        $url = $this->get_logo_url();
1439
        if ($url) {
1440
            $url = $url->out(false);
1441
        }
1442
        $context->logourl = $url;
1443
        $context->sitename = format_string(
1444
            $SITE->fullname,
1445
            true,
1446
            ['context' => context_course::instance(SITEID), "escape" => false]
1447
        );
1448
 
1449
        if ($this->page->theme->settings->setloginlayout == 1) {
1450
            $context->loginlayout1 = 1;
1451
        } else if ($this->page->theme->settings->setloginlayout == 2) {
1452
            $context->loginlayout2 = 1;
1453
            if (isset($this->page->theme->settings->loginbg)) {
1454
                $context->loginlayoutimg = 1;
1295 ariadna 1455
            }
1298 ariadna 1456
        } else if ($this->page->theme->settings->setloginlayout == 3) {
1457
            $context->loginlayout3 = 1;
1458
            if (isset($this->page->theme->settings->loginbg)) {
1459
                $context->loginlayoutimg = 1;
1460
            }
1461
        } else if ($this->page->theme->settings->setloginlayout == 4) {
1462
            $context->loginlayout4 = 1;
1463
        } else if ($this->page->theme->settings->setloginlayout == 5) {
1464
            $context->loginlayout5 = 1;
1465
        }
1295 ariadna 1466
 
1298 ariadna 1467
        if (isset($this->page->theme->settings->loginlogooutside)) {
1468
            $context->loginlogooutside = $this->page->theme->settings->loginlogooutside;
1469
        }
1295 ariadna 1470
 
1298 ariadna 1471
        if (isset($this->page->theme->settings->customsignupoutside)) {
1472
            $context->customsignupoutside = $this->page->theme->settings->customsignupoutside;
1473
        }
1295 ariadna 1474
 
1298 ariadna 1475
        if (isset($this->page->theme->settings->loginidprovtop)) {
1476
            $context->loginidprovtop = $this->page->theme->settings->loginidprovtop;
1477
        }
1478
 
1479
        if (isset($this->page->theme->settings->stringca)) {
1480
            $context->stringca = format_text(($this->page->theme->settings->stringca),
1481
                FORMAT_HTML,
1482
                array('noclean' => true)
1483
            );
1484
        }
1485
 
1486
        if (isset($this->page->theme->settings->stringca)) {
1487
            $context->stringca = format_text(($this->page->theme->settings->stringca),
1488
                FORMAT_HTML,
1489
                array('noclean' => true)
1490
            );
1491
        }
1492
 
1493
        if (isset($this->page->theme->settings->loginhtmlcontent1)) {
1494
            $context->loginhtmlcontent1 = format_text(($this->page->theme->settings->loginhtmlcontent1),
1495
                FORMAT_HTML,
1496
                array('noclean' => true)
1497
            );
1498
        }
1499
 
1500
        if (isset($this->page->theme->settings->loginhtmlcontent2)) {
1501
            $context->loginhtmlcontent2 = format_text(($this->page->theme->settings->loginhtmlcontent2),
1502
                FORMAT_HTML,
1503
                array('noclean' => true)
1504
            );
1505
        }
1506
 
1507
        if (isset($this->page->theme->settings->loginhtmlcontent3)) {
1508
            $context->loginhtmlcontent3 = format_text(($this->page->theme->settings->loginhtmlcontent3),
1509
                FORMAT_HTML,
1510
                array('noclean' => true)
1511
            );
1512
        }
1513
 
1514
        if (isset($this->page->theme->settings->loginhtmlcontent2)) {
1515
            $context->loginhtmlcontent2 = format_text(($this->page->theme->settings->loginhtmlcontent2),
1516
                FORMAT_HTML,
1517
                array('noclean' => true)
1518
            );
1519
        }
1520
 
1521
        if (isset($this->page->theme->settings->logincustomfooterhtml)) {
1522
            $context->logincustomfooterhtml = format_text(($this->page->theme->settings->logincustomfooterhtml),
1523
                FORMAT_HTML,
1524
                array('noclean' => true)
1525
            );
1526
        }
1527
 
1528
        if (isset($this->page->theme->settings->loginhtmlblockbottom)) {
1529
            $context->loginhtmlblockbottom = format_text(($this->page->theme->settings->loginhtmlblockbottom),
1530
                FORMAT_HTML,
1531
                array('noclean' => true)
1532
            );
1533
        }
1534
 
1535
        if (isset($this->page->theme->settings->loginfootercontent)) {
1536
            $context->loginfootercontent = format_text(($this->page->theme->settings->loginfootercontent),
1537
                FORMAT_HTML,
1538
                array('noclean' => true)
1539
            );
1540
        }
1541
 
1542
        if (isset($this->page->theme->settings->footercopy)) {
1543
            $context->footercopy = format_text(($this->page->theme->settings->footercopy),
1544
                FORMAT_HTML,
1545
                array('noclean' => true)
1546
            );
1547
        }
1548
 
1549
        if (isset($this->page->theme->settings->loginintrotext)) {
1550
            $context->loginintrotext = format_text(($this->page->theme->settings->loginintrotext),
1551
                FORMAT_HTML,
1552
                array('noclean' => true)
1553
            );
1554
        }
1555
 
1556
        if (isset($this->page->theme->settings->loginintrotext)) {
1557
            $context->loginintrotext = format_text(($this->page->theme->settings->loginintrotext),
1558
                FORMAT_HTML,
1559
                array('noclean' => true)
1560
            );
1561
        }
1562
 
1563
        if (isset($this->page->theme->settings->customloginlogo)) {
1564
            $context->customloginlogo = $this->page->theme->setting_file_url('customloginlogo', 'customloginlogo');
1565
        }
1566
 
1567
        if (isset($this->page->theme->settings->loginbg)) {
1568
            $context->loginbg = $this->page->theme->setting_file_url('loginbg', 'loginbg');
1569
        }
1570
 
1571
        if (isset($this->page->theme->settings->hideforgotpassword)) {
1572
            $context->hideforgotpassword = $this->page->theme->settings->hideforgotpassword == 1;
1573
        }
1574
 
1575
        if (isset($this->page->theme->settings->logininfobox)) {
1576
            $context->logininfobox = format_text(($this->page->theme->settings->logininfobox),
1577
                FORMAT_HTML,
1578
                array('noclean' => true)
1579
            );
1580
        }
1581
 
1582
        return $this->render_from_template('core/loginform', $context);
1583
    }
1584
 
1585
    /**
1586
     * Render the login signup form into a nice template for the theme.
1587
     *
1588
     * @param mform $form
1589
     * @return string
1590
     */
1591
    public function render_login_signup_form($form)
1592
    {
1593
        global $SITE;
1594
 
1595
        $context = $form->export_for_template($this);
1596
        $url = $this->get_logo_url();
1597
        if ($url) {
1598
            $url = $url->out(false);
1599
        }
1600
        $context['logourl'] = $url;
1601
        $context['sitename'] = format_string(
1602
            $SITE->fullname,
1603
            true,
1604
            ['context' => context_course::instance(SITEID), "escape" => false]
1605
        );
1606
 
1607
        if ($this->page->theme->settings->setloginlayout == 1) {
1608
            $context['loginlayout1'] = 1;
1609
        } else if ($this->page->theme->settings->setloginlayout == 2) {
1610
            $context['loginlayout2'] = 1;
1611
            if (isset($this->page->theme->settings->loginbg)) {
1612
                $context['loginlayoutimg'] = 1;
1613
            }
1614
        } else if ($this->page->theme->settings->setloginlayout == 3) {
1615
            $context['loginlayout3'] = 1;
1616
            if (isset($this->page->theme->settings->loginbg)) {
1617
                $context['loginlayoutimg'] = 1;
1618
            }
1619
        } else if ($this->page->theme->settings->setloginlayout == 4) {
1620
            $context['loginlayout4'] = 1;
1621
        } else if ($this->page->theme->settings->setloginlayout == 5) {
1622
            $context['loginlayout5'] = 1;
1623
        }
1624
 
1625
        if (isset($this->page->theme->settings->loginlogooutside)) {
1626
            $context['loginlogooutside'] = $this->page->theme->settings->loginlogooutside;
1627
        }
1628
 
1629
        if (isset($this->page->theme->settings->stringbacktologin)) {
1630
            $context['stringbacktologin'] = format_text(($this->page->theme->settings->stringbacktologin),
1631
                FORMAT_HTML,
1632
                array('noclean' => true)
1633
            );
1634
        }
1635
        if (isset($this->page->theme->settings->signupintrotext)) {
1636
            $context['signupintrotext'] = format_text(($this->page->theme->settings->signupintrotext),
1637
                FORMAT_HTML,
1638
                array('noclean' => true)
1639
            );
1640
        }
1641
        if (isset($this->page->theme->settings->signuptext)) {
1642
            $context['signuptext'] = format_text(($this->page->theme->settings->signuptext),
1643
                FORMAT_HTML,
1644
                array('noclean' => true)
1645
            );
1646
        }
1647
 
1648
        if (!empty($this->page->theme->settings->customloginlogo)) {
1649
            $url = $this->page->theme->setting_file_url('customloginlogo', 'customloginlogo');
1650
            $context['customloginlogo'] = $url;
1651
        }
1652
 
1653
        if (!empty($this->page->theme->settings->loginbg)) {
1654
            $url = $this->page->theme->setting_file_url('loginbg', 'loginbg');
1655
            $context['loginbg'] = $url;
1656
        }
1657
 
1658
        if (isset($this->page->theme->settings->loginfootercontent)) {
1659
            $context['loginfootercontent'] = format_text(($this->page->theme->settings->loginfootercontent),
1660
                FORMAT_HTML,
1661
                array('noclean' => true)
1662
            );
1663
        }
1664
 
1665
        return $this->render_from_template('core/signup_form_layout', $context);
1666
    }
1667
 
1668
 
1669
    /**
1670
     * Renders the header bar.
1671
     *
1672
     * @param context_header $contextheader Header bar object.
1673
     * @return string HTML for the header bar.
1674
     */
1675
    protected function render_context_header(\context_header $contextheader)
1676
    {
1677
        $heading = null;
1678
        $imagedata = null;
1679
        $html = null;
1680
 
1681
        // Generate the heading first and before everything else as we might have to do an early return.
1682
        if (!isset($contextheader->heading)) {
1683
            $heading = $this->heading($this->page->heading, $contextheader->headinglevel);
1684
        } else {
1685
            $heading = $this->heading($contextheader->heading, $contextheader->headinglevel);
1686
        }
1687
 
1688
        // All the html stuff goes here.
1689
        $html = html_writer::start_div('page-context-header d-flex align-items-center flex-wrap');
1690
 
1691
        // Image data.
1692
        if (isset($contextheader->imagedata)) {
1693
            // Header specific image.
1694
            $html .= html_writer::div($contextheader->imagedata, 'page-header-image');
1695
        }
1696
 
1697
        // Headings.
1698
        if (isset($contextheader->prefix)) {
1699
            $prefix = html_writer::div($contextheader->prefix, 'text-muted text-uppercase small line-height-3');
1700
            $heading = $prefix . $heading;
1701
        }
1702
 
1703
        if (!isset($contextheader->heading)) {
1704
            $html .= html_writer::tag('h3', $heading, array('class' => 'rui-page-title rui-page-title--page'));
1705
        } else if (isset($contextheader->imagedata)) {
1706
            $html .= html_writer::tag(
1707
                'div',
1708
                $this->heading($contextheader->heading, 4),
1709
                array('class' => 'rui-page-title rui-page-title--icon')
1710
            );
1711
        } else {
1712
            $html .= html_writer::tag('h2', $heading, array('class' => 'page-header-headings
1713
                rui-page-title rui-page-title--context'));
1714
        }
1715
 
1716
        // Buttons.
1717
        if (isset($contextheader->additionalbuttons)) {
1718
            $html .= html_writer::start_div('btn-group header-button-group my-2 my-lg-0 ml-lg-4');
1719
            foreach ($contextheader->additionalbuttons as $button) {
1720
                if (!isset($button->page)) {
1721
                    // Include js for messaging.
1722
                    if ($button['buttontype'] === 'togglecontact') {
1723
                        \core_message\helper::togglecontact_requirejs();
1724
                    }
1725
                    if ($button['buttontype'] === 'message') {
1726
                        \core_message\helper::messageuser_requirejs();
1727
                    }
1728
                    $image = $this->pix_icon($button['formattedimage'], $button['title'], 'moodle', array(
1729
                        'class' => 'iconsmall',
1730
                        'role' => 'presentation'
1731
                    ));
1732
                    $image .= html_writer::span($button['title'], 'header-button-title');
1295 ariadna 1733
                } else {
1298 ariadna 1734
                    $image = html_writer::empty_tag('img', array(
1735
                        'src' => $button['formattedimage'],
1736
                        'role' => 'presentation'
1737
                    ));
1295 ariadna 1738
                }
1298 ariadna 1739
                $html .= html_writer::link($button['url'], html_writer::tag('span', $image), $button['linkattributes']);
1740
            }
1741
            $html .= html_writer::end_div();
1742
        }
1743
        $html .= html_writer::end_div();
1295 ariadna 1744
 
1298 ariadna 1745
        return $html;
1746
    }
1295 ariadna 1747
 
1298 ariadna 1748
    public function header()
1749
    {
1750
        global $USER, $COURSE;
1751
        $theme = theme_config::load('universe');
1295 ariadna 1752
 
1301 ariadna 1753
        // Verificar si el curso está definido
1754
        if (!isset($COURSE) || empty($COURSE->id)) {
1755
            debugging('Error: No se pudo obtener el contexto del curso.', DEBUG_DEVELOPER);
1756
            return parent::header();
1757
        }
1758
 
1759
        // Verificar si el usuario está autenticado
1760
        if (!isset($USER->id)) {
1761
            debugging('Error: Usuario no autenticado.', DEBUG_DEVELOPER);
1762
            return parent::header();
1763
        }
1764
 
1765
        // Obtener contexto del curso
1298 ariadna 1766
        $context = context_course::instance($COURSE->id);
1301 ariadna 1767
        $roles = get_user_roles($context, $USER->id, true) ?: [];
1298 ariadna 1768
 
1301 ariadna 1769
        // Agregar clases según los roles del usuario
1770
        if (!empty($roles)) {
1298 ariadna 1771
            foreach ($roles as $role) {
1772
                $this->page->add_body_class('role-' . $role->shortname);
1295 ariadna 1773
            }
1298 ariadna 1774
        } else {
1775
            $this->page->add_body_class('role-none');
1776
        }
1295 ariadna 1777
 
1301 ariadna 1778
        // Verificar configuración de edición
1779
        if (!empty($theme->settings->topbareditmode) && $theme->settings->topbareditmode == '1') {
1298 ariadna 1780
            $this->page->add_body_class('rui-editmode--top');
1781
        } else {
1782
            $this->page->add_body_class('rui-editmode--footer');
1783
        }
1295 ariadna 1784
 
1298 ariadna 1785
        return parent::header();
1786
    }
1787
 
1788
 
1301 ariadna 1789
 
1298 ariadna 1790
    /**
1791
     * See if this is the first view of the current cm in the session if it has fake blocks.
1792
     *
1793
     * (We track up to 100 cms so as not to overflow the session.)
1794
     * This is done for drawer regions containing fake blocks so we can show blocks automatically.
1795
     *
1796
     * @return boolean true if the page has fakeblocks and this is the first visit.
1797
     */
1798
    public function firstview_fakeblocks(): bool
1799
    {
1800
        global $SESSION;
1801
 
1802
        $firstview = false;
1803
        if ($this->page->cm) {
1804
            if (!$this->page->blocks->region_has_fakeblocks('side-pre')) {
1805
                return false;
1806
            }
1807
            if (!property_exists($SESSION, 'firstview_fakeblocks')) {
1808
                $SESSION->firstview_fakeblocks = [];
1809
            }
1810
            if (array_key_exists($this->page->cm->id, $SESSION->firstview_fakeblocks)) {
1811
                $firstview = false;
1812
            } else {
1813
                $SESSION->firstview_fakeblocks[$this->page->cm->id] = true;
1814
                $firstview = true;
1815
                if (count($SESSION->firstview_fakeblocks) > 100) {
1816
                    array_shift($SESSION->firstview_fakeblocks);
1817
                }
1818
            }
1295 ariadna 1819
        }
1298 ariadna 1820
        return $firstview;
1821
    }
1295 ariadna 1822
 
1298 ariadna 1823
 
1824
    /**
1825
     * Build the guest access hint HTML code.
1826
     *
1827
     * @param int $courseid The course ID.
1828
     * @return string.
1829
     */
1830
    public function theme_universe_get_course_guest_access_hint($courseid)
1831
    {
1832
        global $CFG;
1833
        require_once($CFG->dirroot . '/enrol/self/lib.php');
1834
 
1835
        $html = '';
1836
        $instances = enrol_get_instances($courseid, true);
1837
        $plugins = enrol_get_plugins(true);
1838
        foreach ($instances as $instance) {
1839
            if (!isset($plugins[$instance->enrol])) {
1840
                continue;
1841
            }
1842
            $plugin = $plugins[$instance->enrol];
1843
            if ($plugin->show_enrolme_link($instance)) {
1844
                $html = html_writer::tag('div', get_string(
1845
                    'showhintcourseguestaccesssettinglink',
1846
                    'theme_universe',
1847
                    array('url' => $CFG->wwwroot . '/enrol/index.php?id=' . $courseid)
1848
                ));
1849
                break;
1850
            }
1295 ariadna 1851
        }
1852
 
1298 ariadna 1853
        return $html;
1854
    }
1855
 
1301 ariadna 1856
    public function render_statics_blocks($userid = null)
1857
    {
1858
        global $USER;
1298 ariadna 1859
 
1301 ariadna 1860
        if (!$userid) {
1861
            $userid = $USER->id;
1862
        }
1863
 
1864
        // Instanciamos StaticsBlocks para renderizar los bloques
1865
        $statics_blocks = new \StaticsBlocks(
1866
            'side-pre',
1867
            ['messageteacher', 'comments', 'cesa_course_rating', 'cesa_notes']
1868
        );
1869
 
1870
        $blocks = $statics_blocks->renderBlocks();
1871
 
1872
        return $blocks;
1873
    }
1874
 
1875
 
1298 ariadna 1876
    /**
1877
     * Color Customization
1878
     * @return string HTML fragment.
1879
     */
1880
    public function additional_head_html()
1881
    {
1882
        global $SITE, $DB, $CFG, $COURSE, $PAGE;
1883
 
1884
        $output = null;
1885
 
1886
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
1887
            if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor1'), 'id')) {
1888
                // Get custom field by name
1889
                $customfieldid1 = $DB->get_record('customfield_field', array('shortname' => 'maincolor1'));
1890
                // Get value
1891
                $mainthemecolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid1->id, 'instanceid' => $COURSE->id));
1892
            } else {
1893
                $mainthemecolor = null;
1894
            }
1895
 
1896
            if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor2'), 'id')) {
1897
                $customfieldid2 = $DB->get_record('customfield_field', array('shortname' => 'maincolor2'));
1898
                $mainthemecolor2 = $DB->get_record('customfield_data', array('fieldid' => $customfieldid2->id, 'instanceid' => $COURSE->id));
1899
            }
1900
 
1901
            if ($DB->record_exists('customfield_field', array('shortname' => 'topbarcolor'), 'id')) {
1902
                // Get custom field by name
1903
                $customfieldid3 = $DB->get_record('customfield_field', array('shortname' => 'topbarcolor'));
1904
                // Get value
1905
                $topbarcolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid3->id, 'instanceid' => $COURSE->id));
1906
            }
1907
 
1908
            if ($DB->record_exists('customfield_field', array('shortname' => 'dmtopbarcolor'), 'id')) {
1909
                // Get custom field by name
1910
                $customfieldid3 = $DB->get_record('customfield_field', array('shortname' => 'dmtopbarcolor'));
1911
                // Get value
1912
                $dmtopbarcolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid3->id, 'instanceid' => $COURSE->id));
1913
            } else {
1914
                $dmtopbarcolor = null;
1915
            }
1916
 
1917
 
1918
            if ($DB->record_exists('customfield_field', array('shortname' => 'footerbgcolor'), 'id')) {
1919
                // Get custom field by name
1920
                $customfieldid4 = $DB->get_record('customfield_field', array('shortname' => 'footerbgcolor'));
1921
                // Get value
1922
                $footercolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid4->id, 'instanceid' => $COURSE->id));
1923
            } else {
1924
                $footercolor = null;
1925
            }
1926
 
1927
 
1928
            $css = '';
1929
 
1930
            $css .= ':root { ';
1931
            if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor1'), 'id')) {
1932
                if ($mainthemecolor != null) {
1933
                    $css .= '--main-theme-color: ' . $mainthemecolor->value . '; ';
1934
                    $css .= '--primary-color-100: ' . $mainthemecolor->value . '30; ';
1935
                    $css .= '--primary-color-300: ' . $mainthemecolor->value . '70; ';
1936
                    $css .= '--main-theme-color-gradient: ' . $mainthemecolor->value . '; ';
1937
                    $css .= '--btn-primary-color-bg: ' . $mainthemecolor->value . '; ';
1938
                    $css .= '--btn-primary-color-bg-hover: ' . $mainthemecolor->value . '95; ';
1939
 
1940
                    if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor2'), 'id')) {
1941
                        if ($mainthemecolor2 != null) {
1942
                            $css .= '--main-theme-color-gradient-2: ' . $mainthemecolor2->value . '; ';
1943
                        } else {
1944
                            $css .= '--main-theme-color-gradient-2: ' . $mainthemecolor->value . '30; ';
1945
                        }
1946
                    }
1947
                }
1948
            }
1949
 
1950
            if ($DB->record_exists('customfield_field', array('shortname' => 'topbarcolor'), 'id')) {
1951
                if ($topbarcolor != null) {
1952
                    $css .= '--topbar-color: ' . $topbarcolor->value . '; ';
1953
                    if ($dmtopbarcolor != null) {
1954
                        $css .= '--dm-topbar-color: ' . $dmtopbarcolor->value . '; ';
1955
                    } else {
1956
                        $css .= '--dm-topbar-color: ' . $topbarcolor->value . '; ';
1957
                    }
1958
                }
1959
            }
1960
 
1961
            if ($DB->record_exists('customfield_field', array('shortname' => 'footerbgcolor'), 'id')) {
1962
                if ($footercolor != null) {
1963
                    $css .= '--footer-color: ' . $footercolor->value . '; ';
1964
                }
1965
            }
1966
 
1967
            $css .= '}';
1968
 
1969
            if ($css) {
1970
                $output .= '<style>' . $css . '</style>';
1971
            }
1295 ariadna 1972
        }
1973
 
1298 ariadna 1974
        return $output;
1975
    }
1295 ariadna 1976
 
1298 ariadna 1977
    public function custom_course_logo()
1978
    {
1979
        global $DB, $CFG, $COURSE, $PAGE;
1295 ariadna 1980
 
1298 ariadna 1981
        $output = null;
1295 ariadna 1982
 
1298 ariadna 1983
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
1984
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcourselogo'))) {
1985
                // Get custom field ID
1986
                $customfieldpic = $DB->get_record('customfield_field', array('shortname' => 'customcourselogo'));
1987
                $customfieldpicid = $customfieldpic->id;
1988
                // Get value
1989
                $customlogo = $DB->get_record(
1990
                    'customfield_data',
1991
                    array('fieldid' => $customfieldpicid, 'instanceid' => $COURSE->id)
1992
                );
1295 ariadna 1993
 
1298 ariadna 1994
                $customlogoid = $customlogo->id;
1995
                $contextid = $customlogo->contextid;
1996
 
1997
                if ($customfieldpic != null) {
1998
                    $files = get_file_storage()->get_area_files(
1999
                        $contextid,
2000
                        'customfield_picture',
2001
                        'file',
2002
                        $customlogoid,
2003
                        '',
2004
                        false
2005
                    );
2006
 
2007
                    if (empty($files)) {
2008
                        return null;
2009
                    }
2010
 
2011
                    $file = reset($files);
2012
                    $fileurl = moodle_url::make_pluginfile_url(
2013
                        $file->get_contextid(),
2014
                        $file->get_component(),
2015
                        $file->get_filearea(),
2016
                        $file->get_itemid(),
2017
                        $file->get_filepath(),
2018
                        $file->get_filename()
2019
                    );
2020
 
2021
                    $output .= $fileurl;
2022
                }
2023
            }
2024
        }
2025
 
2026
        return $output;
1295 ariadna 2027
    }
2028
 
1298 ariadna 2029
    public function custom_course_dmlogo()
1294 ariadna 2030
    {
1298 ariadna 2031
        global $DB, $CFG, $COURSE, $PAGE;
1294 ariadna 2032
 
1298 ariadna 2033
        $output = null;
2034
 
2035
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
2036
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcoursedmlogo'))) {
2037
                // Get custom field ID
2038
                $customfieldpic = $DB->get_record('customfield_field', array('shortname' => 'customcoursedmlogo'));
2039
                $customfieldpicid = $customfieldpic->id;
2040
                // Get value
2041
                $customlogo = $DB->get_record(
2042
                    'customfield_data',
2043
                    array('fieldid' => $customfieldpicid, 'instanceid' => $COURSE->id)
2044
                );
2045
 
2046
                $customlogoid = $customlogo->id;
2047
                $contextid = $customlogo->contextid;
2048
 
2049
                if ($customfieldpic != null) {
2050
                    $files = get_file_storage()->get_area_files(
2051
                        $contextid,
2052
                        'customfield_picture',
2053
                        'file',
2054
                        $customlogoid,
2055
                        '',
2056
                        false
2057
                    );
2058
 
2059
                    if (empty($files)) {
2060
                        return null;
2061
                    }
2062
 
2063
                    $file = reset($files);
2064
                    $fileurl = moodle_url::make_pluginfile_url(
2065
                        $file->get_contextid(),
2066
                        $file->get_component(),
2067
                        $file->get_filearea(),
2068
                        $file->get_itemid(),
2069
                        $file->get_filepath(),
2070
                        $file->get_filename()
2071
                    );
2072
 
2073
                    $output .= $fileurl;
2074
                }
2075
            }
1294 ariadna 2076
        }
2077
 
1298 ariadna 2078
        return $output;
2079
    }
1294 ariadna 2080
 
1298 ariadna 2081
    public function custom_course_favicon()
2082
    {
2083
        global $DB, $CFG, $COURSE, $PAGE;
1294 ariadna 2084
 
1298 ariadna 2085
        $output = null;
2086
 
2087
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
2088
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcoursefavicon'))) {
2089
                // Get custom field ID
2090
                $customfieldpic = $DB->get_record('customfield_field', array('shortname' => 'customcoursefavicon'));
2091
                $customfieldpicid = $customfieldpic->id;
2092
                // Get value
2093
                $customfavicon = $DB->get_record(
2094
                    'customfield_data',
2095
                    array('fieldid' => $customfieldpicid, 'instanceid' => $COURSE->id)
2096
                );
2097
 
2098
                $customfaviconid = $customfavicon->id;
2099
                $contextid = $customfavicon->contextid;
2100
 
2101
                if ($customfieldpic != null) {
2102
                    $files = get_file_storage()->get_area_files(
2103
                        $contextid,
2104
                        'customfield_picture',
2105
                        'file',
2106
                        $customfaviconid,
2107
                        '',
2108
                        false
2109
                    );
2110
 
2111
                    if (empty($files)) {
2112
                        return null;
2113
                    }
2114
 
2115
                    $file = reset($files);
2116
                    $fileurl = moodle_url::make_pluginfile_url(
2117
                        $file->get_contextid(),
2118
                        $file->get_component(),
2119
                        $file->get_filearea(),
2120
                        $file->get_itemid(),
2121
                        $file->get_filepath(),
2122
                        $file->get_filename()
2123
                    );
2124
 
2125
                    $output .= $fileurl;
2126
                }
2127
            }
2128
        }
2129
 
2130
        return $output;
1294 ariadna 2131
    }
1297 ariadna 2132
 
1298 ariadna 2133
    public function custom_course_name()
1297 ariadna 2134
    {
1298 ariadna 2135
        global $DB, $CFG, $COURSE, $PAGE;
1297 ariadna 2136
 
1298 ariadna 2137
        $output = null;
2138
 
2139
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
2140
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcoursename'), 'id')) {
2141
                // Get custom field by name
2142
                $customfieldid = $DB->get_record('customfield_field', array('shortname' => 'customcoursename'));
2143
                // Get value
2144
                $customcoursename = $DB->get_record('customfield_data', array('fieldid' => $customfieldid->id, 'instanceid' => $COURSE->id));
2145
                if (!empty($customcoursename)) {
2146
                    $output .= $customcoursename->value;
2147
                }
2148
            } else {
2149
                $customcoursename = null;
2150
            }
1297 ariadna 2151
        }
2152
 
1298 ariadna 2153
        return $output;
2154
    }
2155
 
2156
    /**
2157
     * Get the course pattern datauri to show on a course card.
2158
     *
2159
     * The datauri is an encoded svg that can be passed as a url.
2160
     * @param int $id Id to use when generating the pattern
2161
     * @return string datauri
2162
     */
2163
    public function get_generated_image_for_id($id)
2164
    {
2165
        global $CFG;
2166
 
2167
        $theme = \theme_config::load('universe');
2168
        // Add custom course cover.
2169
        $customcover = $theme->setting_file_url('defaultcourseimg', 'defaultcourseimg');
2170
 
2171
        if (!empty(($customcover))) {
2172
            $urlreplace = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2173
            $customcover = str_replace($urlreplace, '', $customcover);
2174
            $txt = new moodle_url($customcover);
2175
            return strval($txt);
2176
        } else {
2177
            $color = $this->get_generated_color_for_id($id);
2178
            $pattern = new \core_geopattern();
2179
            $pattern->setColor($color);
2180
            $pattern->patternbyid($id);
2181
            return $pattern->datauri();
1297 ariadna 2182
        }
1298 ariadna 2183
    }
1297 ariadna 2184
 
1298 ariadna 2185
    public function moremenu_group_item()
2186
    {
2187
        global $CFG, $COURSE;
2188
 
2189
        $theme = \theme_config::load('universe');
2190
        $courseid = $COURSE->id;
2191
        $sitehomeurl = new moodle_url('/');
2192
 
2193
        if ($this->page->theme->settings->secnavgroupitem == 1) {
2194
            if (has_capability('moodle/course:managegroups', \context_course::instance($COURSE->id))) {
2195
                $html = $sitehomeurl . "group/index.php?id=" . $courseid;
2196
                return $html;
2197
            }
1297 ariadna 2198
        }
1298 ariadna 2199
    }
1297 ariadna 2200
 
1301 ariadna 2201
 
2202
    public function cesa_navigation_course_completion()
2203
    {
2204
        global $COURSE, $PAGE, $USER, $CFG;
2205
 
2206
        if (empty($PAGE->cm->id) || empty($COURSE->enablecompletion)) {
2207
            return '';
2208
        }
2209
 
2210
        $course_context = context_course::instance($COURSE->id);
2211
        $roles = get_user_roles($course_context, $USER->id, true);
2212
 
2213
        $completion_visible = true;
2214
        foreach ($roles as $role) {
2215
            if ($role->shortname != 'student') {
2216
                $completion_visible  = false;
2217
            }
2218
        }
2219
 
2220
        if (!$completion_visible) {
2221
            return '';
2222
        }
2223
        $PAGE->requires->js(new \moodle_url($CFG->wwwroot . '/local/cesanavigation/javascript/terminacion.js'));
2224
 
2225
        $page_context = $PAGE->cm;
2226
 
2227
        $modules = get_fast_modinfo($COURSE->id)->get_cms();
2228
 
2229
        $mods = [];
2230
        foreach ($modules as $module) {
2231
            if (!$module->uservisible || $module->is_stealth() || empty($module->url)) {
2232
                continue;
2233
            }
2234
            $mods[$module->id] = $module;
2235
        }
2236
 
2237
 
2238
 
2239
        $nummods = count($mods);
2240
 
2241
        // If there is only one mod then do nothing.
2242
        if ($nummods == 1) {
2243
            return '';
2244
        }
2245
 
2246
        $modids = array_keys($mods);
2247
        $position = array_search($page_context->id, $modids);   //array_search($this->page->cm->id, $modids);
2248
 
2249
        $currentmod = $mods[$modids[$position]];
2250
 
2251
        /*if(!$currentmod->completion) {
2252
            return '';
2253
        }*/
2254
 
2255
        $completioninfo = new \completion_info($COURSE);
2256
        $completiondata = $completioninfo->get_data($currentmod, true);
2257
        if ($completiondata->completionstate != COMPLETION_COMPLETE && $completiondata->completionstate != COMPLETION_COMPLETE_PASS) {
2258
            $url = new \moodle_url($CFG->wwwroot . '/local/cesanavigation/terminacion.php', ['courseid' => $COURSE->id, 'modid' =>  $currentmod->id]);
2259
 
2260
 
2261
            return '<div class="containerr">
2262
                        <input type="button" class="btn btn-primary d-block mx-auto btn-cesa-course-completion button-cesa vertical-center center" data-url="' . $url . '" value="Completar y continuar">
2263
                    </div>';
2264
        }
2265
 
2266
        return '';
2267
    }
2268
 
1298 ariadna 2269
    public function moremenu_custom_items()
2270
    {
2271
        global $CFG, $COURSE, $USER;
2272
 
2273
        $theme = \theme_config::load('universe');
2274
        $html = '';
2275
        $secnavcount = theme_universe_get_setting('secnavitemscount');
2276
 
2277
        // Get current user role ID.
2278
        $context = context_course::instance($COURSE->id);
2279
        $roles = get_user_roles($context, $USER->id, true);
2280
        $role = 999;
2281
        $roleid = 999;
2282
        $role = key($roles);
2283
        if ($role != null) {
2284
            $roleid = $roles[$role]->roleid;
1297 ariadna 2285
        }
2286
 
1298 ariadna 2287
        // End.
2288
 
2289
        if ($this->page->theme->settings->secnavitems == 1) {
2290
 
2291
            $secnav = new stdClass();
2292
            for ($i = 1; $i <= $secnavcount; $i++) {
2293
                $secnav->title = theme_universe_get_setting("secnavcustomnavlabel" . $i);
2294
 
2295
                $url = theme_universe_get_setting("secnavcustomnavurl" . $i);
2296
                $courseid = $COURSE->id;
2297
                $newurl = str_replace("{{courseID}}", $courseid, $url);
2298
 
2299
                // User role restriction.
2300
                $selectrole = theme_universe_get_setting("secnavuserroles" . $i);
2301
 
2302
                if ($roleid == $selectrole) {
2303
                    $secnav->url = $newurl;
2304
                    $html .= $this->render_from_template('theme_universe/custom_sec_nav_item', $secnav);
2305
                }
2306
                if ($roleid != $selectrole) {
2307
                    $secnav->url = $newurl;
2308
                }
2309
                if ($selectrole == 0) {
2310
                    $secnav->url = $newurl;
2311
                    $html .= $this->render_from_template('theme_universe/custom_sec_nav_item', $secnav);
2312
                }
2313
                // End.
2314
 
2315
            }
2316
        }
2317
        return $html;
1297 ariadna 2318
    }
1299 ariadna 2319
 
1301 ariadna 2320
    public function get_navbar_image_courses()
1299 ariadna 2321
    {
1301 ariadna 2322
        global $CFG;
1299 ariadna 2323
 
1301 ariadna 2324
        if (!empty($this->page->theme->settings->navbar_icon_courses)) {
2325
            $url = $this->page->theme->setting_file_url('navbar_icon_courses', 'navbar_icon_courses');
2326
            // Get a URL suitable for moodle_url.
2327
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2328
            $url = str_replace($relativebaseurl, '', $url);
2329
            return new moodle_url($url);
1299 ariadna 2330
        }
2331
 
2332
 
1301 ariadna 2333
        return $CFG->wwwroot . '/theme/universe_child/pix/icon-catalog-white.png';
2334
    }
1299 ariadna 2335
 
1301 ariadna 2336
    public function get_navbar_image_progress()
2337
    {
2338
        global $CFG;
2339
 
2340
        if (!empty($this->page->theme->settings->navbar_icon_progress)) {
2341
            $url = $this->page->theme->setting_file_url('navbar_icon_progress', 'navbar_icon_progress');
2342
            // Get a URL suitable for moodle_url.
2343
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2344
            $url = str_replace($relativebaseurl, '', $url);
2345
            return new moodle_url($url);
2346
        }
2347
 
2348
 
2349
 
2350
        return $CFG->wwwroot . '/theme/universe_child/pix/icon-progress-white.png';
1299 ariadna 2351
    }
1300 ariadna 2352
 
1301 ariadna 2353
    public function get_navbar_image_forums()
2354
    {
2355
        global $CFG;
2356
 
2357
 
2358
        if (!empty($this->page->theme->settings->navbar_icon_forums)) {
2359
            $url = $this->page->theme->setting_file_url('navbar_icon_forums', 'navbar_icon_forums');
2360
            // Get a URL suitable for moodle_url.
2361
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2362
            $url = str_replace($relativebaseurl, '', $url);
2363
            return new moodle_url($url);
2364
        }
2365
 
2366
        return $CFG->wwwroot . '/theme/universe_child/pix/icon-forum-white.png';
2367
    }
2368
 
2369
    public function get_navbar_image_calendar()
2370
    {
2371
        global $CFG;
2372
 
2373
 
2374
        if (!empty($this->page->theme->settings->navbar_icon_calendar)) {
2375
            $url = $this->page->theme->setting_file_url('navbar_icon_calendar', 'navbar_icon_calendar');
2376
            // Get a URL suitable for moodle_url.
2377
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2378
            $url = str_replace($relativebaseurl, '', $url);
2379
            return new moodle_url($url);
2380
        }
2381
 
2382
        return $CFG->wwwroot . '/theme/universe_child/pix/icon-calendar-white.png';
2383
    }
2384
 
2385
    public function get_theme_image_login_bg()
2386
    {
2387
        global  $DB, $CFG;
2388
 
2389
        if (!empty($this->page->theme->settings->loginimagebackground)) {
2390
            $url = $this->page->theme->setting_file_url('loginimagebackground', 'loginimagebackground');
2391
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2392
            $url = str_replace($relativebaseurl, '', $url);
2393
            return new moodle_url($url);
2394
        }
2395
 
2396
        return '';
2397
    }
2398
 
2399
    public function get_navbar_image_personal_area()
2400
    {
2401
        global $CFG;
2402
 
2403
 
2404
        if (!empty($this->page->theme->settings->navbar_icon_calendar)) {
2405
            $url = $this->page->theme->setting_file_url('navbar_icon_personal_area', 'navbar_icon_personal_area');
2406
            // Get a URL suitable for moodle_url.
2407
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2408
            $url = str_replace($relativebaseurl, '', $url);
2409
            return new moodle_url($url);
2410
        }
2411
 
2412
        return $CFG->wwwroot . '/theme/universe_child/pix/icon-personal-area-white.png';
2413
    }
2414
 
2415
    public function get_navbar_image_messages()
2416
    {
2417
        global $CFG;
2418
 
2419
 
2420
        if (!empty($this->page->theme->settings->navbar_icon_calendar)) {
2421
            $url = $this->page->theme->setting_file_url('navbar_icon_messages', 'navbar_icon_messages');
2422
            // Get a URL suitable for moodle_url.
2423
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2424
            $url = str_replace($relativebaseurl, '', $url);
2425
            return new moodle_url($url);
2426
        }
2427
 
2428
        return $CFG->wwwroot . '/theme/universe_child/pix/icon-messages-white.png';
2429
    }
2430
 
2431
    private function extractDurationFromVideo($record, $filename)
2432
    {
2433
        global $DB;
2434
 
2435
        $duration = 0;
2436
 
2437
        if (empty($record->duration)) {
2438
            $fs = get_file_storage();
2439
            $file = $fs->get_file($record->contextid, $record->component, $record->filearea, $record->itemid, $record->filepath, $record->filename);
2440
            if ($file) {
2441
 
2442
                $data = $file->get_content();
2443
 
2444
                $path_temp = __DIR__ . DIRECTORY_SEPARATOR . 'tmp';
2445
                if (!file_exists($path_temp)) {
2446
                    mkdir($path_temp, 0755);
2447
                }
2448
 
2449
                $full_filename = $path_temp . DIRECTORY_SEPARATOR . uniqid() . '_' . $filename;
2450
                file_put_contents($full_filename, $data);
2451
 
2452
                if (file_exists($full_filename)) {
2453
                    $cmd = "/usr/bin/ffprobe -i $full_filename -show_entries format=duration -v quiet -of csv=\"p=0\" ";
2454
                    $response = trim(shell_exec($cmd));
2455
                    @unlink($full_filename);
2456
 
2457
 
2458
                    $duration = $response;
2459
 
2460
 
2461
                    if ($response) {
2462
                        $response = floatval($response);
2463
 
2464
                        if ($response > 60) {
2465
 
2466
                            //echo 'response = ' . $response . '<br>';
2467
 
2468
                            $minutes = intval($response / 60);
2469
                            //echo 'minutes = ' . $minutes . '<br>';
2470
 
2471
                            $seconds = round(($response - ($minutes * 60)));
2472
                            //echo 'seconds = ' . $seconds . '<br>';
2473
 
2474
 
2475
                            if ($minutes < 10) {
2476
                                $duration = '0' . $minutes;
2477
                            } else {
2478
                                $duration = $minutes;
2479
                            }
2480
 
2481
                            if ($seconds) {
2482
                                if ($seconds < 10) {
2483
                                    $duration = $duration . ':0' . $seconds;
2484
                                } else {
2485
                                    $duration = $duration . ':' . $seconds;
2486
                                }
2487
                            } else {
2488
                                $duration = $duration . ':00';
2489
                            }
2490
                        } else {
2491
                            $duration = '00:' . intval($response);
2492
                        }
2493
 
2494
 
2495
 
2496
                        $dataobject = new \stdClass();
2497
                        $dataobject->id = $record->id;
2498
                        $dataobject->duration = $duration;
2499
 
2500
 
2501
 
2502
                        $DB->update_record('files', $dataobject);
2503
                    }
2504
                }
2505
            }
2506
        }
2507
        return $duration;
2508
    }
2509
 
2510
    private function substr_cesa_navigation_course_menu_name($s, $l = 50)
2511
    {
2512
        $s = trim($s);
2513
        if (strlen($s) > $l) {
2514
            $s = substr($s, 0, $l) . '...';
2515
        }
2516
        return $s;
2517
    }
2518
 
2519
    public function cesa_navigation_course_menu_lateral_output()
2520
    {
2521
 
2522
 
2523
 
2524
        global $CFG, $COURSE, $PAGE, $DB, $OUTPUT;
2525
 
2526
 
2527
 
2528
 
2529
        if (!$COURSE->id) {
2530
            return '';
2531
        }
2532
 
2533
        $course_id = $COURSE->id;
2534
 
2535
        $parent = optional_param('parent', 0, PARAM_INT); // Course module id
2536
        if (!$parent) {
2537
            $parent = optional_param('amp;parent', 0, PARAM_INT); // Course module id
2538
        }
2539
 
2540
        //$PAGE->requires->js('/theme/edumynew/javascript/menu-lateral.js');
2541
 
2542
 
2543
        if ($parent) {
2544
            $sql  = ' SELECT * FROM {subcourse} WHERE course = ' . $parent;
2545
            $sql .= ' AND refcourse = ' . $course_id;
2546
 
2547
            $recordParentRefCourse  = $DB->get_record_sql($sql);
2548
            if ($recordParentRefCourse) {
2549
                $course_id = $recordParentRefCourse->course;
2550
            }
2551
        }
2552
 
2553
 
2554
 
2555
        $course = get_course($course_id);
2556
        $course_context = context_course::instance($course->id);
2557
        $completioninfo = new \completion_info($course);
2558
 
2559
        // $course_context = !empty($PAGE->cm->id)  ? $PAGE->cm : \context_course::instance($COURSE->id);
2560
        // First we should check if we want to add navigation.
2561
        // Get a list of all the activities in the course.
2562
 
2563
 
2564
 
2565
        $menu = [];
2566
 
2567
        $currentServerLink = strtolower(trim($_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']));
2568
        $currentServerLink = html_entity_decode($currentServerLink);
2569
        $currentServerLink = htmlentities($currentServerLink);
2570
 
2571
        $parts = explode('&', $currentServerLink);
2572
        if (count($parts) > 1) {
2573
            $currentServerLink = $parts[0];
2574
        }
2575
 
2576
 
2577
 
2578
 
2579
        $modules = get_fast_modinfo($course->id)->get_cms();
2580
 
2581
        $prevmod = null;
2582
        $nextmod = null;
2583
        $currentmod = new stdClass();
2584
        $currentmod->name = "Sin Módulos";
2585
        $mods = [];
2586
        $menu = [];
2587
        $numberOfTemary = 1;
2588
        $prevlink = new \StdClass();
2589
        $nextlink = new \StdClass();
2590
        $prevlink->url = "#";
2591
        $nextlink->url = "#";
2592
 
2593
        $isACoursePage = $course->id !== "1" ? true : false;
2594
 
2595
 
2596
 
2597
 
2598
        $modules = get_fast_modinfo($COURSE->id)->get_cms();
2599
        /*
2600
            echo '<pre>';
2601
            print_r($modules);
2602
            echo '</pre>';
2603
            */
2604
 
2605
        if (!empty($modules)) {
2606
            // Put the modules into an array in order by the position they are shown in the course.
2607
            foreach ($modules as $module) {
2608
                if (!$module->uservisible || $module->is_stealth() || empty($module->url)) {
2609
                    continue;
2610
                }
2611
                $mods[$module->id] = $module;
2612
            }
2613
 
2614
 
2615
            $nummods = count($mods);
2616
 
2617
 
2618
            // If there is only one mod then do nothing.
2619
            if ($nummods == 1) {
2620
            }
2621
 
2622
            // Get an array of just the course module ids used to get the cmid value based on their position in the course.
2623
            $modids = array_keys($mods);
2624
 
2625
            // Get the position in the array of the course module we are viewing.
2626
            $position = array_search($course_context->id, $modids);   //array_search($this->page->cm->id, $modids);
2627
 
2628
            $currentmod = $mods[$modids[$position]];
2629
 
2630
 
2631
 
2632
            // Check if we have a previous mod to show.
2633
            if ($position > 0) {
2634
                $prevmod = $mods[$modids[$position - 1]];
2635
            }
2636
 
2637
            // Check if we have a next mod to show.
2638
            if ($position < ($nummods - 1)) {
2639
                $nextmod = $mods[$modids[$position + 1]];
2640
            }
2641
        }
2642
 
2643
 
2644
        //$sections = $DB->get_records('course_sections', ['course' => $COURSE->id], 'section ASC', 'id,name,section,sequence,visible');
2645
 
2646
 
2647
 
2648
 
2649
        $modinfo = get_fast_modinfo($course);
2650
        $records  =  $modinfo->get_section_info_all();
2651
        $sections = [];
2652
 
2653
        foreach ($records as $record) {
2654
            if (!$record->visible) {
2655
                continue;
2656
            }
2657
 
2658
            $section = new \stdClass();
2659
            $section->id = $record->id;
2660
            $section->section = $record->section;
2661
            $section->name = $record->name;
2662
            $section->parent = $record->parent;
2663
            $section->visible = 1;
2664
 
2665
 
2666
            array_push($sections, $section);
2667
        }
2668
 
2669
 
2670
 
2671
        $openParent = 0;
2672
        $maxSections = count($sections);
2673
        for ($i = 0; $i < $maxSections; $i++) {
2674
 
2675
 
2676
 
2677
            $j = $i + 1;
2678
            if ($j < $maxSections) {
2679
 
2680
                if ($sections[$j]->parent) {
2681
                    $openParent = true;
2682
                    $sections[$i]->close_section_parent = 0;
2683
                    $sections[$i]->close_section = 0;
2684
                } else {
2685
                    $sections[$i]->close_section_parent = $openParent ? 1 : 0;
2686
 
2687
                    $sections[$i]->close_section = 1;
2688
                }
2689
            } else {
2690
                $sections[$i]->close_section_parent = $openParent ? 1 : 0;
2691
                $sections[$i]->close_section = 1;
2692
            }
2693
 
2694
            // print_r($section);
2695
 
2696
 
2697
        }
2698
 
2699
        /*
2700
             echo '<pre>';
2701
           print_r($sections);
2702
           echo '</pre>';
2703
 
2704
      */
2705
 
2706
 
2707
 
2708
 
2709
        foreach ($sections as $key =>  $section) {
2710
 
2711
            if (!$section->visible) {
2712
                continue;
2713
            }
2714
 
2715
            $activities = [];
2716
            $section_active = false;
2717
 
2718
            foreach ($modules as $module) {
2719
 
2720
                if ($module->section  != $section->id) {
2721
                    continue;
2722
                }
2723
 
2724
                if (!$module->uservisible || $module->is_stealth()) {
2725
                    // if (!$module->uservisible || $module->is_stealth() || empty($module->url)) {
2726
                    continue;
2727
                }
2728
 
2729
                $mods[$module->id] = $module;
2730
 
2731
                $duration = '';
2732
                $type = '';
2733
                $filepath = '';
2734
 
2735
                $sql = 'SELECT md.name, cm.instance  FROM {modules} md  ' .
2736
                    ' JOIN {course_modules} cm ON cm.module = md.id ' .
2737
                    ' WHERE cm.id = '  . $module->id . ' LIMIT 1 ';
2738
 
2739
                $record = $DB->get_record_sql($sql);
2740
                if ($record) {
2741
 
2742
                    /*
2743
                        echo '<pre>';
2744
                        print_r($record);
2745
                        echo '<pre>';
2746
                        */
2747
 
2748
                    $type = $record->name;
2749
 
2750
                    if ($type == 'hvp') {
2751
                        $instance   = $record->instance;
2752
 
2753
                        $sql = 'SELECT json_content FROM {hvp} WHERE id = ' . $instance . ' LIMIT 1';
2754
                        $record = $DB->get_record_sql($sql);
2755
 
2756
                        if ($record) {
2757
                            $json_content = json_decode($record->json_content);
2758
 
2759
                            if (!empty($json_content->interactiveVideo->video->files[0]->path)) {
2760
                                $filepath = trim($json_content->interactiveVideo->video->files[0]->path);
2761
                                $filepath = trim(str_replace('#tmp', '', $filepath));
2762
 
2763
 
2764
                                $arr = explode('/', $filepath);
2765
                                if (count($arr) > 1) {
2766
                                    $filename = $arr[count($arr) - 1];
2767
                                } else {
2768
                                    $filename = $arr[0];
2769
                                }
2770
 
2771
                                $record = $DB->get_record('files', ['filename' => $filename]);
2772
                                if ($record) {
2773
                                    $duration = $this->extractDurationFromVideo($record, $filename);
2774
                                }
2775
                            }
2776
                        }
2777
                    }
2778
                }
2779
 
2780
                $modname = $module->get_formatted_name();
2781
                $modcontent = $module->get_formatted_content();
2782
 
2783
                if (empty($module->url)) {
2784
                    $linkurl = '';
2785
                    $currentLink = '';
2786
                } else {
2787
 
2788
                    $linkurl = new moodle_url($module->url, array('forceview' => 1));
2789
                    $linkurl = strtolower(trim($linkurl->__toString()));
2790
 
2791
                    $parts = explode('&', $linkurl);
2792
                    if (count($parts) > 1) {
2793
                        $currentLink = $parts[0];
2794
                    } else {
2795
                        $currentLink = $linkurl;
2796
                    }
2797
                }
2798
 
2799
                $completiondata = $completioninfo->get_data($module, true);
2800
 
2801
                if (strcasecmp($currentLink,  $currentServerLink) == 0) {
2802
                    $active = true;
2803
                    $section_active = true;
2804
                } else {
2805
                    $active = false;
2806
                }
2807
 
2808
                array_push($activities, [
2809
                    'active' => $active,
2810
                    'indexElement' => $key,
2811
                    'numberOfTemary' => $numberOfTemary,
2812
                    'activity' => true,
2813
                    'blank' => !empty($section->section),
2814
                    'name' => $this->substr_cesa_navigation_course_menu_name($modname),
2815
                    'content' => $modcontent,
2816
                    'duration' => $duration,
2817
                    'type' =>  $type,
2818
                    'completed' => $completiondata->completionstate == COMPLETION_COMPLETE || $completiondata->completionstate == COMPLETION_COMPLETE_PASS,
2819
                    'failed' => $completiondata->completionstate == COMPLETION_COMPLETE_FAIL,
2820
                    'url' => $linkurl
2821
                ]);
2822
            }
2823
 
2824
 
2825
            if ($activities) {
2826
 
2827
                if ($section->section) {
2828
                    $sectionname = trim($section->name);
2829
                    $sectionname = $sectionname ? $sectionname : ' Tema ' . $section->section;
2830
                } else {
2831
                    $sectionname = 'Recursos';
2832
                }
2833
 
2834
                array_push($menu, [
2835
                    'active' => $section_active,
2836
                    'indexElement' => $key,
2837
                    'id' => $section->id,
2838
                    'numberOfTemary' => $numberOfTemary,
2839
                    'section' => true,
2840
                    'name' => $this->substr_cesa_navigation_course_menu_name($sectionname),
2841
                    'close_section_parent' => $section->close_section_parent,
2842
                    'close_section' => $section->close_section,
2843
                    'completed' => false,
2844
                    'url' => false,
2845
                    'activities' => $activities,
2846
 
2847
 
2848
                ]);
2849
            }
2850
 
2851
 
2852
            $numberOfTemary = ++$numberOfTemary;
2853
        }
2854
 
2855
        // Check if there is a previous module to display.
2856
        if ($prevmod) {
2857
            $linkurl = new \moodle_url($prevmod->url, array('forceview' => 1));
2858
            $attributes = [];
2859
            $prevlink = new \action_link($linkurl, $OUTPUT->larrow(), null, $attributes);
2860
        }
2861
 
2862
        // Check if there is a next module to display.
2863
        if ($nextmod) {
2864
            $linkurl = new \moodle_url($nextmod->url, array('forceview' => 1));
2865
            $attributes = [];
2866
            $nextlink = new \action_link($linkurl, $OUTPUT->rarrow(), null, $attributes);
2867
        }
2868
 
2869
 
2870
        //  echo '<pre>';
2871
        // print_r($activities);
2872
        // echo '</pre>';
2873
        // exit;
2874
 
2875
 
2876
        $progreso = number_format(progress::get_course_progress_percentage($course), 2); // Progreso por curso
2877
 
2878
        $course_navigation = new \theme_universe_child\output\custom_drawer($prevlink->url, $nextlink->url, $menu, $this->substr_cesa_navigation_course_menu_name($currentmod->name, 10), false, $isACoursePage,  $COURSE->summary, $progreso);
2879
        return $course_navigation->export_for_template($OUTPUT);
2880
    }
2881
 
1300 ariadna 2882
    function universe_child_course_drawer(): string
2883
    {
2884
        global $PAGE;
2885
 
2886
        // If the course index is explicitly set and if it should be hidden.
2887
        if ($PAGE->get_show_course_index() === false) {
2888
            return '';
2889
        }
2890
 
2891
        // Only add course index on non-site course pages.
2892
        if (!$PAGE->course || $PAGE->course->id == SITEID) {
2893
            return '';
2894
        }
2895
 
2896
        // Show course index to users can access the course only.
2897
        if (!can_access_course($PAGE->course, null, '', true)) {
2898
            return '';
2899
        }
2900
 
2901
        $format = course_get_format($PAGE->course);
2902
        $renderer = $format->get_renderer($PAGE);
2903
        if (method_exists($renderer, 'course_index_drawer')) {
2904
            return $this->render_from_template('theme_universe_child/courseindex/drawer', []);
2905
        }
2906
 
2907
        return '';
2908
    }
1301 ariadna 2909
 
2910
    /*
2911
    *
2912
    * Method to get reference to $CFG->themedir variable
2913
    *
2914
    */
2915
    function theme_universe_themedir()
2916
    {
2917
        global $CFG;
2918
 
2919
        $teme_dir = '/theme';
2920
 
2921
        if (isset($CFG->themedir)) {
2922
            $teme_dir = $CFG->themedir;
2923
            $teme_dir = str_replace($CFG->dirroot, '', $CFG->themedir);
2924
        }
2925
 
2926
        return $teme_dir;
2927
    }
1291 ariadna 2928
}