Proyectos de Subversion Moodle

Rev

Rev 1301 | Rev 1307 | 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.
1306 ariadna 1377
 
1378
     * public function main_content()
1379
     *{
1380
     * This is here because it is the only place we can inject the "main" role over the entire main content area
1381
     * without requiring all theme's to manually do it, and without creating yet another thing people need to
1382
     * remember in the theme.
1383
     * This is an unfortunate hack. DO NO EVER add anything more here.
1384
     * DO NOT add classes.
1385
     * DO NOT add an id.
1386
     *return '<div class="main-content" role="main">' . $this->unique_main_content_token . '</div>';
1387
     *}*/
1388
 
1298 ariadna 1389
    public function main_content()
1390
    {
1306 ariadna 1391
        return '<div class="main-content" role="main">' . $this->page->get_main_content() . '</div>';
1298 ariadna 1392
    }
1393
 
1394
    /**
1395
     * Outputs a heading
1396
     *
1397
     * @param string $text The text of the heading
1398
     * @param int $level The level of importance of the heading. Defaulting to 2
1399
     * @param string $classes A space-separated list of CSS classes. Defaulting to null
1400
     * @param string $id An optional ID
1401
     * @return string the HTML to output.
1402
     */
1403
    public function heading($text, $level = 2, $classes = null, $id = null)
1404
    {
1405
        $level = (int) $level;
1406
        if ($level < 1 || $level > 6) {
1407
            throw new coding_exception('Heading level must be an integer between 1 and 6.');
1408
        }
1409
        return html_writer::tag('div', html_writer::tag('h' .
1410
            $level, $text, array('id' => $id, 'class' => renderer_base::prepare_classes($classes) .
1411
            ' rui-main-content-title rui-main-content-title--h' .
1412
            $level)), array('class' => 'rui-title-container'));
1413
    }
1414
 
1415
 
1416
    public function headingwithavatar($text, $level = 2, $classes = null, $id = null)
1417
    {
1418
        $level = (int) $level;
1419
        if ($level < 1 || $level > 6) {
1420
            throw new coding_exception('Heading level must be an integer between 1 and 6.');
1421
        }
1422
        return html_writer::tag('div', html_writer::tag('h' .
1423
            $level, $text, array('id' => $id, 'class' => renderer_base::prepare_classes($classes) .
1424
            ' rui-main-content-title-with-avatar')), array('class' => 'rui-title-container-with-avatar'));
1425
    }
1426
 
1427
    /**
1428
     * Renders the login form.
1429
     *
1430
     * @param \core_auth\output\login $form The renderable.
1431
     * @return string
1432
     */
1433
    public function render_login(\core_auth\output\login $form)
1434
    {
1435
        global $CFG, $SITE;
1436
 
1437
        $context = $form->export_for_template($this);
1438
 
1439
        // Override because rendering is not supported in template yet.
1440
        if ($CFG->rememberusername == 0) {
1441
            $context->cookieshelpiconformatted = $this->help_icon('cookiesenabledonlysession');
1442
        } else {
1443
            $context->cookieshelpiconformatted = $this->help_icon('cookiesenabled');
1444
        }
1445
        $context->errorformatted = $this->error_text($context->error);
1446
        $url = $this->get_logo_url();
1447
        if ($url) {
1448
            $url = $url->out(false);
1449
        }
1450
        $context->logourl = $url;
1451
        $context->sitename = format_string(
1452
            $SITE->fullname,
1453
            true,
1454
            ['context' => context_course::instance(SITEID), "escape" => false]
1455
        );
1456
 
1457
        if ($this->page->theme->settings->setloginlayout == 1) {
1458
            $context->loginlayout1 = 1;
1459
        } else if ($this->page->theme->settings->setloginlayout == 2) {
1460
            $context->loginlayout2 = 1;
1461
            if (isset($this->page->theme->settings->loginbg)) {
1462
                $context->loginlayoutimg = 1;
1295 ariadna 1463
            }
1298 ariadna 1464
        } else if ($this->page->theme->settings->setloginlayout == 3) {
1465
            $context->loginlayout3 = 1;
1466
            if (isset($this->page->theme->settings->loginbg)) {
1467
                $context->loginlayoutimg = 1;
1468
            }
1469
        } else if ($this->page->theme->settings->setloginlayout == 4) {
1470
            $context->loginlayout4 = 1;
1471
        } else if ($this->page->theme->settings->setloginlayout == 5) {
1472
            $context->loginlayout5 = 1;
1473
        }
1295 ariadna 1474
 
1298 ariadna 1475
        if (isset($this->page->theme->settings->loginlogooutside)) {
1476
            $context->loginlogooutside = $this->page->theme->settings->loginlogooutside;
1477
        }
1295 ariadna 1478
 
1298 ariadna 1479
        if (isset($this->page->theme->settings->customsignupoutside)) {
1480
            $context->customsignupoutside = $this->page->theme->settings->customsignupoutside;
1481
        }
1295 ariadna 1482
 
1298 ariadna 1483
        if (isset($this->page->theme->settings->loginidprovtop)) {
1484
            $context->loginidprovtop = $this->page->theme->settings->loginidprovtop;
1485
        }
1486
 
1487
        if (isset($this->page->theme->settings->stringca)) {
1488
            $context->stringca = format_text(($this->page->theme->settings->stringca),
1489
                FORMAT_HTML,
1490
                array('noclean' => true)
1491
            );
1492
        }
1493
 
1494
        if (isset($this->page->theme->settings->stringca)) {
1495
            $context->stringca = format_text(($this->page->theme->settings->stringca),
1496
                FORMAT_HTML,
1497
                array('noclean' => true)
1498
            );
1499
        }
1500
 
1501
        if (isset($this->page->theme->settings->loginhtmlcontent1)) {
1502
            $context->loginhtmlcontent1 = format_text(($this->page->theme->settings->loginhtmlcontent1),
1503
                FORMAT_HTML,
1504
                array('noclean' => true)
1505
            );
1506
        }
1507
 
1508
        if (isset($this->page->theme->settings->loginhtmlcontent2)) {
1509
            $context->loginhtmlcontent2 = format_text(($this->page->theme->settings->loginhtmlcontent2),
1510
                FORMAT_HTML,
1511
                array('noclean' => true)
1512
            );
1513
        }
1514
 
1515
        if (isset($this->page->theme->settings->loginhtmlcontent3)) {
1516
            $context->loginhtmlcontent3 = format_text(($this->page->theme->settings->loginhtmlcontent3),
1517
                FORMAT_HTML,
1518
                array('noclean' => true)
1519
            );
1520
        }
1521
 
1522
        if (isset($this->page->theme->settings->loginhtmlcontent2)) {
1523
            $context->loginhtmlcontent2 = format_text(($this->page->theme->settings->loginhtmlcontent2),
1524
                FORMAT_HTML,
1525
                array('noclean' => true)
1526
            );
1527
        }
1528
 
1529
        if (isset($this->page->theme->settings->logincustomfooterhtml)) {
1530
            $context->logincustomfooterhtml = format_text(($this->page->theme->settings->logincustomfooterhtml),
1531
                FORMAT_HTML,
1532
                array('noclean' => true)
1533
            );
1534
        }
1535
 
1536
        if (isset($this->page->theme->settings->loginhtmlblockbottom)) {
1537
            $context->loginhtmlblockbottom = format_text(($this->page->theme->settings->loginhtmlblockbottom),
1538
                FORMAT_HTML,
1539
                array('noclean' => true)
1540
            );
1541
        }
1542
 
1543
        if (isset($this->page->theme->settings->loginfootercontent)) {
1544
            $context->loginfootercontent = format_text(($this->page->theme->settings->loginfootercontent),
1545
                FORMAT_HTML,
1546
                array('noclean' => true)
1547
            );
1548
        }
1549
 
1550
        if (isset($this->page->theme->settings->footercopy)) {
1551
            $context->footercopy = format_text(($this->page->theme->settings->footercopy),
1552
                FORMAT_HTML,
1553
                array('noclean' => true)
1554
            );
1555
        }
1556
 
1557
        if (isset($this->page->theme->settings->loginintrotext)) {
1558
            $context->loginintrotext = format_text(($this->page->theme->settings->loginintrotext),
1559
                FORMAT_HTML,
1560
                array('noclean' => true)
1561
            );
1562
        }
1563
 
1564
        if (isset($this->page->theme->settings->loginintrotext)) {
1565
            $context->loginintrotext = format_text(($this->page->theme->settings->loginintrotext),
1566
                FORMAT_HTML,
1567
                array('noclean' => true)
1568
            );
1569
        }
1570
 
1571
        if (isset($this->page->theme->settings->customloginlogo)) {
1572
            $context->customloginlogo = $this->page->theme->setting_file_url('customloginlogo', 'customloginlogo');
1573
        }
1574
 
1575
        if (isset($this->page->theme->settings->loginbg)) {
1576
            $context->loginbg = $this->page->theme->setting_file_url('loginbg', 'loginbg');
1577
        }
1578
 
1579
        if (isset($this->page->theme->settings->hideforgotpassword)) {
1580
            $context->hideforgotpassword = $this->page->theme->settings->hideforgotpassword == 1;
1581
        }
1582
 
1583
        if (isset($this->page->theme->settings->logininfobox)) {
1584
            $context->logininfobox = format_text(($this->page->theme->settings->logininfobox),
1585
                FORMAT_HTML,
1586
                array('noclean' => true)
1587
            );
1588
        }
1589
 
1590
        return $this->render_from_template('core/loginform', $context);
1591
    }
1592
 
1593
    /**
1594
     * Render the login signup form into a nice template for the theme.
1595
     *
1596
     * @param mform $form
1597
     * @return string
1598
     */
1599
    public function render_login_signup_form($form)
1600
    {
1601
        global $SITE;
1602
 
1603
        $context = $form->export_for_template($this);
1604
        $url = $this->get_logo_url();
1605
        if ($url) {
1606
            $url = $url->out(false);
1607
        }
1608
        $context['logourl'] = $url;
1609
        $context['sitename'] = format_string(
1610
            $SITE->fullname,
1611
            true,
1612
            ['context' => context_course::instance(SITEID), "escape" => false]
1613
        );
1614
 
1615
        if ($this->page->theme->settings->setloginlayout == 1) {
1616
            $context['loginlayout1'] = 1;
1617
        } else if ($this->page->theme->settings->setloginlayout == 2) {
1618
            $context['loginlayout2'] = 1;
1619
            if (isset($this->page->theme->settings->loginbg)) {
1620
                $context['loginlayoutimg'] = 1;
1621
            }
1622
        } else if ($this->page->theme->settings->setloginlayout == 3) {
1623
            $context['loginlayout3'] = 1;
1624
            if (isset($this->page->theme->settings->loginbg)) {
1625
                $context['loginlayoutimg'] = 1;
1626
            }
1627
        } else if ($this->page->theme->settings->setloginlayout == 4) {
1628
            $context['loginlayout4'] = 1;
1629
        } else if ($this->page->theme->settings->setloginlayout == 5) {
1630
            $context['loginlayout5'] = 1;
1631
        }
1632
 
1633
        if (isset($this->page->theme->settings->loginlogooutside)) {
1634
            $context['loginlogooutside'] = $this->page->theme->settings->loginlogooutside;
1635
        }
1636
 
1637
        if (isset($this->page->theme->settings->stringbacktologin)) {
1638
            $context['stringbacktologin'] = format_text(($this->page->theme->settings->stringbacktologin),
1639
                FORMAT_HTML,
1640
                array('noclean' => true)
1641
            );
1642
        }
1643
        if (isset($this->page->theme->settings->signupintrotext)) {
1644
            $context['signupintrotext'] = format_text(($this->page->theme->settings->signupintrotext),
1645
                FORMAT_HTML,
1646
                array('noclean' => true)
1647
            );
1648
        }
1649
        if (isset($this->page->theme->settings->signuptext)) {
1650
            $context['signuptext'] = format_text(($this->page->theme->settings->signuptext),
1651
                FORMAT_HTML,
1652
                array('noclean' => true)
1653
            );
1654
        }
1655
 
1656
        if (!empty($this->page->theme->settings->customloginlogo)) {
1657
            $url = $this->page->theme->setting_file_url('customloginlogo', 'customloginlogo');
1658
            $context['customloginlogo'] = $url;
1659
        }
1660
 
1661
        if (!empty($this->page->theme->settings->loginbg)) {
1662
            $url = $this->page->theme->setting_file_url('loginbg', 'loginbg');
1663
            $context['loginbg'] = $url;
1664
        }
1665
 
1666
        if (isset($this->page->theme->settings->loginfootercontent)) {
1667
            $context['loginfootercontent'] = format_text(($this->page->theme->settings->loginfootercontent),
1668
                FORMAT_HTML,
1669
                array('noclean' => true)
1670
            );
1671
        }
1672
 
1673
        return $this->render_from_template('core/signup_form_layout', $context);
1674
    }
1675
 
1676
 
1677
    /**
1678
     * Renders the header bar.
1679
     *
1680
     * @param context_header $contextheader Header bar object.
1681
     * @return string HTML for the header bar.
1682
     */
1683
    protected function render_context_header(\context_header $contextheader)
1684
    {
1685
        $heading = null;
1686
        $imagedata = null;
1687
        $html = null;
1688
 
1689
        // Generate the heading first and before everything else as we might have to do an early return.
1690
        if (!isset($contextheader->heading)) {
1691
            $heading = $this->heading($this->page->heading, $contextheader->headinglevel);
1692
        } else {
1693
            $heading = $this->heading($contextheader->heading, $contextheader->headinglevel);
1694
        }
1695
 
1696
        // All the html stuff goes here.
1697
        $html = html_writer::start_div('page-context-header d-flex align-items-center flex-wrap');
1698
 
1699
        // Image data.
1700
        if (isset($contextheader->imagedata)) {
1701
            // Header specific image.
1702
            $html .= html_writer::div($contextheader->imagedata, 'page-header-image');
1703
        }
1704
 
1705
        // Headings.
1706
        if (isset($contextheader->prefix)) {
1707
            $prefix = html_writer::div($contextheader->prefix, 'text-muted text-uppercase small line-height-3');
1708
            $heading = $prefix . $heading;
1709
        }
1710
 
1711
        if (!isset($contextheader->heading)) {
1712
            $html .= html_writer::tag('h3', $heading, array('class' => 'rui-page-title rui-page-title--page'));
1713
        } else if (isset($contextheader->imagedata)) {
1714
            $html .= html_writer::tag(
1715
                'div',
1716
                $this->heading($contextheader->heading, 4),
1717
                array('class' => 'rui-page-title rui-page-title--icon')
1718
            );
1719
        } else {
1720
            $html .= html_writer::tag('h2', $heading, array('class' => 'page-header-headings
1721
                rui-page-title rui-page-title--context'));
1722
        }
1723
 
1724
        // Buttons.
1725
        if (isset($contextheader->additionalbuttons)) {
1726
            $html .= html_writer::start_div('btn-group header-button-group my-2 my-lg-0 ml-lg-4');
1727
            foreach ($contextheader->additionalbuttons as $button) {
1728
                if (!isset($button->page)) {
1729
                    // Include js for messaging.
1730
                    if ($button['buttontype'] === 'togglecontact') {
1731
                        \core_message\helper::togglecontact_requirejs();
1732
                    }
1733
                    if ($button['buttontype'] === 'message') {
1734
                        \core_message\helper::messageuser_requirejs();
1735
                    }
1736
                    $image = $this->pix_icon($button['formattedimage'], $button['title'], 'moodle', array(
1737
                        'class' => 'iconsmall',
1738
                        'role' => 'presentation'
1739
                    ));
1740
                    $image .= html_writer::span($button['title'], 'header-button-title');
1295 ariadna 1741
                } else {
1298 ariadna 1742
                    $image = html_writer::empty_tag('img', array(
1743
                        'src' => $button['formattedimage'],
1744
                        'role' => 'presentation'
1745
                    ));
1295 ariadna 1746
                }
1298 ariadna 1747
                $html .= html_writer::link($button['url'], html_writer::tag('span', $image), $button['linkattributes']);
1748
            }
1749
            $html .= html_writer::end_div();
1750
        }
1751
        $html .= html_writer::end_div();
1295 ariadna 1752
 
1298 ariadna 1753
        return $html;
1754
    }
1295 ariadna 1755
 
1298 ariadna 1756
    public function header()
1757
    {
1758
        global $USER, $COURSE;
1759
        $theme = theme_config::load('universe');
1295 ariadna 1760
 
1301 ariadna 1761
        // Verificar si el curso está definido
1762
        if (!isset($COURSE) || empty($COURSE->id)) {
1763
            debugging('Error: No se pudo obtener el contexto del curso.', DEBUG_DEVELOPER);
1764
            return parent::header();
1765
        }
1766
 
1767
        // Verificar si el usuario está autenticado
1768
        if (!isset($USER->id)) {
1769
            debugging('Error: Usuario no autenticado.', DEBUG_DEVELOPER);
1770
            return parent::header();
1771
        }
1772
 
1773
        // Obtener contexto del curso
1298 ariadna 1774
        $context = context_course::instance($COURSE->id);
1301 ariadna 1775
        $roles = get_user_roles($context, $USER->id, true) ?: [];
1298 ariadna 1776
 
1301 ariadna 1777
        // Agregar clases según los roles del usuario
1778
        if (!empty($roles)) {
1298 ariadna 1779
            foreach ($roles as $role) {
1780
                $this->page->add_body_class('role-' . $role->shortname);
1295 ariadna 1781
            }
1298 ariadna 1782
        } else {
1783
            $this->page->add_body_class('role-none');
1784
        }
1295 ariadna 1785
 
1301 ariadna 1786
        // Verificar configuración de edición
1787
        if (!empty($theme->settings->topbareditmode) && $theme->settings->topbareditmode == '1') {
1298 ariadna 1788
            $this->page->add_body_class('rui-editmode--top');
1789
        } else {
1790
            $this->page->add_body_class('rui-editmode--footer');
1791
        }
1295 ariadna 1792
 
1298 ariadna 1793
        return parent::header();
1794
    }
1795
 
1796
 
1301 ariadna 1797
 
1298 ariadna 1798
    /**
1799
     * See if this is the first view of the current cm in the session if it has fake blocks.
1800
     *
1801
     * (We track up to 100 cms so as not to overflow the session.)
1802
     * This is done for drawer regions containing fake blocks so we can show blocks automatically.
1803
     *
1804
     * @return boolean true if the page has fakeblocks and this is the first visit.
1805
     */
1806
    public function firstview_fakeblocks(): bool
1807
    {
1808
        global $SESSION;
1809
 
1810
        $firstview = false;
1811
        if ($this->page->cm) {
1812
            if (!$this->page->blocks->region_has_fakeblocks('side-pre')) {
1813
                return false;
1814
            }
1815
            if (!property_exists($SESSION, 'firstview_fakeblocks')) {
1816
                $SESSION->firstview_fakeblocks = [];
1817
            }
1818
            if (array_key_exists($this->page->cm->id, $SESSION->firstview_fakeblocks)) {
1819
                $firstview = false;
1820
            } else {
1821
                $SESSION->firstview_fakeblocks[$this->page->cm->id] = true;
1822
                $firstview = true;
1823
                if (count($SESSION->firstview_fakeblocks) > 100) {
1824
                    array_shift($SESSION->firstview_fakeblocks);
1825
                }
1826
            }
1295 ariadna 1827
        }
1298 ariadna 1828
        return $firstview;
1829
    }
1295 ariadna 1830
 
1298 ariadna 1831
 
1832
    /**
1833
     * Build the guest access hint HTML code.
1834
     *
1835
     * @param int $courseid The course ID.
1836
     * @return string.
1837
     */
1838
    public function theme_universe_get_course_guest_access_hint($courseid)
1839
    {
1840
        global $CFG;
1841
        require_once($CFG->dirroot . '/enrol/self/lib.php');
1842
 
1843
        $html = '';
1844
        $instances = enrol_get_instances($courseid, true);
1845
        $plugins = enrol_get_plugins(true);
1846
        foreach ($instances as $instance) {
1847
            if (!isset($plugins[$instance->enrol])) {
1848
                continue;
1849
            }
1850
            $plugin = $plugins[$instance->enrol];
1851
            if ($plugin->show_enrolme_link($instance)) {
1852
                $html = html_writer::tag('div', get_string(
1853
                    'showhintcourseguestaccesssettinglink',
1854
                    'theme_universe',
1855
                    array('url' => $CFG->wwwroot . '/enrol/index.php?id=' . $courseid)
1856
                ));
1857
                break;
1858
            }
1295 ariadna 1859
        }
1860
 
1298 ariadna 1861
        return $html;
1862
    }
1863
 
1301 ariadna 1864
    public function render_statics_blocks($userid = null)
1865
    {
1866
        global $USER;
1298 ariadna 1867
 
1301 ariadna 1868
        if (!$userid) {
1869
            $userid = $USER->id;
1870
        }
1871
 
1872
        // Instanciamos StaticsBlocks para renderizar los bloques
1873
        $statics_blocks = new \StaticsBlocks(
1874
            'side-pre',
1875
            ['messageteacher', 'comments', 'cesa_course_rating', 'cesa_notes']
1876
        );
1877
 
1878
        $blocks = $statics_blocks->renderBlocks();
1879
 
1880
        return $blocks;
1881
    }
1882
 
1883
 
1298 ariadna 1884
    /**
1885
     * Color Customization
1886
     * @return string HTML fragment.
1887
     */
1888
    public function additional_head_html()
1889
    {
1890
        global $SITE, $DB, $CFG, $COURSE, $PAGE;
1891
 
1892
        $output = null;
1893
 
1894
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
1895
            if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor1'), 'id')) {
1896
                // Get custom field by name
1897
                $customfieldid1 = $DB->get_record('customfield_field', array('shortname' => 'maincolor1'));
1898
                // Get value
1899
                $mainthemecolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid1->id, 'instanceid' => $COURSE->id));
1900
            } else {
1901
                $mainthemecolor = null;
1902
            }
1903
 
1904
            if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor2'), 'id')) {
1905
                $customfieldid2 = $DB->get_record('customfield_field', array('shortname' => 'maincolor2'));
1906
                $mainthemecolor2 = $DB->get_record('customfield_data', array('fieldid' => $customfieldid2->id, 'instanceid' => $COURSE->id));
1907
            }
1908
 
1909
            if ($DB->record_exists('customfield_field', array('shortname' => 'topbarcolor'), 'id')) {
1910
                // Get custom field by name
1911
                $customfieldid3 = $DB->get_record('customfield_field', array('shortname' => 'topbarcolor'));
1912
                // Get value
1913
                $topbarcolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid3->id, 'instanceid' => $COURSE->id));
1914
            }
1915
 
1916
            if ($DB->record_exists('customfield_field', array('shortname' => 'dmtopbarcolor'), 'id')) {
1917
                // Get custom field by name
1918
                $customfieldid3 = $DB->get_record('customfield_field', array('shortname' => 'dmtopbarcolor'));
1919
                // Get value
1920
                $dmtopbarcolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid3->id, 'instanceid' => $COURSE->id));
1921
            } else {
1922
                $dmtopbarcolor = null;
1923
            }
1924
 
1925
 
1926
            if ($DB->record_exists('customfield_field', array('shortname' => 'footerbgcolor'), 'id')) {
1927
                // Get custom field by name
1928
                $customfieldid4 = $DB->get_record('customfield_field', array('shortname' => 'footerbgcolor'));
1929
                // Get value
1930
                $footercolor = $DB->get_record('customfield_data', array('fieldid' => $customfieldid4->id, 'instanceid' => $COURSE->id));
1931
            } else {
1932
                $footercolor = null;
1933
            }
1934
 
1935
 
1936
            $css = '';
1937
 
1938
            $css .= ':root { ';
1939
            if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor1'), 'id')) {
1940
                if ($mainthemecolor != null) {
1941
                    $css .= '--main-theme-color: ' . $mainthemecolor->value . '; ';
1942
                    $css .= '--primary-color-100: ' . $mainthemecolor->value . '30; ';
1943
                    $css .= '--primary-color-300: ' . $mainthemecolor->value . '70; ';
1944
                    $css .= '--main-theme-color-gradient: ' . $mainthemecolor->value . '; ';
1945
                    $css .= '--btn-primary-color-bg: ' . $mainthemecolor->value . '; ';
1946
                    $css .= '--btn-primary-color-bg-hover: ' . $mainthemecolor->value . '95; ';
1947
 
1948
                    if ($DB->record_exists('customfield_field', array('shortname' => 'maincolor2'), 'id')) {
1949
                        if ($mainthemecolor2 != null) {
1950
                            $css .= '--main-theme-color-gradient-2: ' . $mainthemecolor2->value . '; ';
1951
                        } else {
1952
                            $css .= '--main-theme-color-gradient-2: ' . $mainthemecolor->value . '30; ';
1953
                        }
1954
                    }
1955
                }
1956
            }
1957
 
1958
            if ($DB->record_exists('customfield_field', array('shortname' => 'topbarcolor'), 'id')) {
1959
                if ($topbarcolor != null) {
1960
                    $css .= '--topbar-color: ' . $topbarcolor->value . '; ';
1961
                    if ($dmtopbarcolor != null) {
1962
                        $css .= '--dm-topbar-color: ' . $dmtopbarcolor->value . '; ';
1963
                    } else {
1964
                        $css .= '--dm-topbar-color: ' . $topbarcolor->value . '; ';
1965
                    }
1966
                }
1967
            }
1968
 
1969
            if ($DB->record_exists('customfield_field', array('shortname' => 'footerbgcolor'), 'id')) {
1970
                if ($footercolor != null) {
1971
                    $css .= '--footer-color: ' . $footercolor->value . '; ';
1972
                }
1973
            }
1974
 
1975
            $css .= '}';
1976
 
1977
            if ($css) {
1978
                $output .= '<style>' . $css . '</style>';
1979
            }
1295 ariadna 1980
        }
1981
 
1298 ariadna 1982
        return $output;
1983
    }
1295 ariadna 1984
 
1298 ariadna 1985
    public function custom_course_logo()
1986
    {
1987
        global $DB, $CFG, $COURSE, $PAGE;
1295 ariadna 1988
 
1298 ariadna 1989
        $output = null;
1295 ariadna 1990
 
1298 ariadna 1991
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
1992
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcourselogo'))) {
1993
                // Get custom field ID
1994
                $customfieldpic = $DB->get_record('customfield_field', array('shortname' => 'customcourselogo'));
1995
                $customfieldpicid = $customfieldpic->id;
1996
                // Get value
1997
                $customlogo = $DB->get_record(
1998
                    'customfield_data',
1999
                    array('fieldid' => $customfieldpicid, 'instanceid' => $COURSE->id)
2000
                );
1295 ariadna 2001
 
1298 ariadna 2002
                $customlogoid = $customlogo->id;
2003
                $contextid = $customlogo->contextid;
2004
 
2005
                if ($customfieldpic != null) {
2006
                    $files = get_file_storage()->get_area_files(
2007
                        $contextid,
2008
                        'customfield_picture',
2009
                        'file',
2010
                        $customlogoid,
2011
                        '',
2012
                        false
2013
                    );
2014
 
2015
                    if (empty($files)) {
2016
                        return null;
2017
                    }
2018
 
2019
                    $file = reset($files);
2020
                    $fileurl = moodle_url::make_pluginfile_url(
2021
                        $file->get_contextid(),
2022
                        $file->get_component(),
2023
                        $file->get_filearea(),
2024
                        $file->get_itemid(),
2025
                        $file->get_filepath(),
2026
                        $file->get_filename()
2027
                    );
2028
 
2029
                    $output .= $fileurl;
2030
                }
2031
            }
2032
        }
2033
 
2034
        return $output;
1295 ariadna 2035
    }
2036
 
1298 ariadna 2037
    public function custom_course_dmlogo()
1294 ariadna 2038
    {
1298 ariadna 2039
        global $DB, $CFG, $COURSE, $PAGE;
1294 ariadna 2040
 
1298 ariadna 2041
        $output = null;
2042
 
2043
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
2044
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcoursedmlogo'))) {
2045
                // Get custom field ID
2046
                $customfieldpic = $DB->get_record('customfield_field', array('shortname' => 'customcoursedmlogo'));
2047
                $customfieldpicid = $customfieldpic->id;
2048
                // Get value
2049
                $customlogo = $DB->get_record(
2050
                    'customfield_data',
2051
                    array('fieldid' => $customfieldpicid, 'instanceid' => $COURSE->id)
2052
                );
2053
 
2054
                $customlogoid = $customlogo->id;
2055
                $contextid = $customlogo->contextid;
2056
 
2057
                if ($customfieldpic != null) {
2058
                    $files = get_file_storage()->get_area_files(
2059
                        $contextid,
2060
                        'customfield_picture',
2061
                        'file',
2062
                        $customlogoid,
2063
                        '',
2064
                        false
2065
                    );
2066
 
2067
                    if (empty($files)) {
2068
                        return null;
2069
                    }
2070
 
2071
                    $file = reset($files);
2072
                    $fileurl = moodle_url::make_pluginfile_url(
2073
                        $file->get_contextid(),
2074
                        $file->get_component(),
2075
                        $file->get_filearea(),
2076
                        $file->get_itemid(),
2077
                        $file->get_filepath(),
2078
                        $file->get_filename()
2079
                    );
2080
 
2081
                    $output .= $fileurl;
2082
                }
2083
            }
1294 ariadna 2084
        }
2085
 
1298 ariadna 2086
        return $output;
2087
    }
1294 ariadna 2088
 
1298 ariadna 2089
    public function custom_course_favicon()
2090
    {
2091
        global $DB, $CFG, $COURSE, $PAGE;
1294 ariadna 2092
 
1298 ariadna 2093
        $output = null;
2094
 
2095
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
2096
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcoursefavicon'))) {
2097
                // Get custom field ID
2098
                $customfieldpic = $DB->get_record('customfield_field', array('shortname' => 'customcoursefavicon'));
2099
                $customfieldpicid = $customfieldpic->id;
2100
                // Get value
2101
                $customfavicon = $DB->get_record(
2102
                    'customfield_data',
2103
                    array('fieldid' => $customfieldpicid, 'instanceid' => $COURSE->id)
2104
                );
2105
 
2106
                $customfaviconid = $customfavicon->id;
2107
                $contextid = $customfavicon->contextid;
2108
 
2109
                if ($customfieldpic != null) {
2110
                    $files = get_file_storage()->get_area_files(
2111
                        $contextid,
2112
                        'customfield_picture',
2113
                        'file',
2114
                        $customfaviconid,
2115
                        '',
2116
                        false
2117
                    );
2118
 
2119
                    if (empty($files)) {
2120
                        return null;
2121
                    }
2122
 
2123
                    $file = reset($files);
2124
                    $fileurl = moodle_url::make_pluginfile_url(
2125
                        $file->get_contextid(),
2126
                        $file->get_component(),
2127
                        $file->get_filearea(),
2128
                        $file->get_itemid(),
2129
                        $file->get_filepath(),
2130
                        $file->get_filename()
2131
                    );
2132
 
2133
                    $output .= $fileurl;
2134
                }
2135
            }
2136
        }
2137
 
2138
        return $output;
1294 ariadna 2139
    }
1297 ariadna 2140
 
1298 ariadna 2141
    public function custom_course_name()
1297 ariadna 2142
    {
1298 ariadna 2143
        global $DB, $CFG, $COURSE, $PAGE;
1297 ariadna 2144
 
1298 ariadna 2145
        $output = null;
2146
 
2147
        if ($PAGE->pagelayout == 'course' || $PAGE->pagelayout == 'incourse') {
2148
            if ($DB->record_exists('customfield_field', array('shortname' => 'customcoursename'), 'id')) {
2149
                // Get custom field by name
2150
                $customfieldid = $DB->get_record('customfield_field', array('shortname' => 'customcoursename'));
2151
                // Get value
2152
                $customcoursename = $DB->get_record('customfield_data', array('fieldid' => $customfieldid->id, 'instanceid' => $COURSE->id));
2153
                if (!empty($customcoursename)) {
2154
                    $output .= $customcoursename->value;
2155
                }
2156
            } else {
2157
                $customcoursename = null;
2158
            }
1297 ariadna 2159
        }
2160
 
1298 ariadna 2161
        return $output;
2162
    }
2163
 
2164
    /**
2165
     * Get the course pattern datauri to show on a course card.
2166
     *
2167
     * The datauri is an encoded svg that can be passed as a url.
2168
     * @param int $id Id to use when generating the pattern
2169
     * @return string datauri
2170
     */
2171
    public function get_generated_image_for_id($id)
2172
    {
2173
        global $CFG;
2174
 
2175
        $theme = \theme_config::load('universe');
2176
        // Add custom course cover.
2177
        $customcover = $theme->setting_file_url('defaultcourseimg', 'defaultcourseimg');
2178
 
2179
        if (!empty(($customcover))) {
2180
            $urlreplace = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2181
            $customcover = str_replace($urlreplace, '', $customcover);
2182
            $txt = new moodle_url($customcover);
2183
            return strval($txt);
2184
        } else {
2185
            $color = $this->get_generated_color_for_id($id);
2186
            $pattern = new \core_geopattern();
2187
            $pattern->setColor($color);
2188
            $pattern->patternbyid($id);
2189
            return $pattern->datauri();
1297 ariadna 2190
        }
1298 ariadna 2191
    }
1297 ariadna 2192
 
1298 ariadna 2193
    public function moremenu_group_item()
2194
    {
2195
        global $CFG, $COURSE;
2196
 
2197
        $theme = \theme_config::load('universe');
2198
        $courseid = $COURSE->id;
2199
        $sitehomeurl = new moodle_url('/');
2200
 
2201
        if ($this->page->theme->settings->secnavgroupitem == 1) {
2202
            if (has_capability('moodle/course:managegroups', \context_course::instance($COURSE->id))) {
2203
                $html = $sitehomeurl . "group/index.php?id=" . $courseid;
2204
                return $html;
2205
            }
1297 ariadna 2206
        }
1298 ariadna 2207
    }
1297 ariadna 2208
 
1301 ariadna 2209
 
2210
    public function cesa_navigation_course_completion()
2211
    {
2212
        global $COURSE, $PAGE, $USER, $CFG;
2213
 
2214
        if (empty($PAGE->cm->id) || empty($COURSE->enablecompletion)) {
2215
            return '';
2216
        }
2217
 
2218
        $course_context = context_course::instance($COURSE->id);
2219
        $roles = get_user_roles($course_context, $USER->id, true);
2220
 
2221
        $completion_visible = true;
2222
        foreach ($roles as $role) {
2223
            if ($role->shortname != 'student') {
2224
                $completion_visible  = false;
2225
            }
2226
        }
2227
 
2228
        if (!$completion_visible) {
2229
            return '';
2230
        }
2231
        $PAGE->requires->js(new \moodle_url($CFG->wwwroot . '/local/cesanavigation/javascript/terminacion.js'));
2232
 
2233
        $page_context = $PAGE->cm;
2234
 
2235
        $modules = get_fast_modinfo($COURSE->id)->get_cms();
2236
 
2237
        $mods = [];
2238
        foreach ($modules as $module) {
2239
            if (!$module->uservisible || $module->is_stealth() || empty($module->url)) {
2240
                continue;
2241
            }
2242
            $mods[$module->id] = $module;
2243
        }
2244
 
2245
 
2246
 
2247
        $nummods = count($mods);
2248
 
2249
        // If there is only one mod then do nothing.
2250
        if ($nummods == 1) {
2251
            return '';
2252
        }
2253
 
2254
        $modids = array_keys($mods);
2255
        $position = array_search($page_context->id, $modids);   //array_search($this->page->cm->id, $modids);
2256
 
2257
        $currentmod = $mods[$modids[$position]];
2258
 
2259
        /*if(!$currentmod->completion) {
2260
            return '';
2261
        }*/
2262
 
2263
        $completioninfo = new \completion_info($COURSE);
2264
        $completiondata = $completioninfo->get_data($currentmod, true);
2265
        if ($completiondata->completionstate != COMPLETION_COMPLETE && $completiondata->completionstate != COMPLETION_COMPLETE_PASS) {
2266
            $url = new \moodle_url($CFG->wwwroot . '/local/cesanavigation/terminacion.php', ['courseid' => $COURSE->id, 'modid' =>  $currentmod->id]);
2267
 
2268
 
2269
            return '<div class="containerr">
2270
                        <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">
2271
                    </div>';
2272
        }
2273
 
2274
        return '';
2275
    }
2276
 
1298 ariadna 2277
    public function moremenu_custom_items()
2278
    {
2279
        global $CFG, $COURSE, $USER;
2280
 
2281
        $theme = \theme_config::load('universe');
2282
        $html = '';
2283
        $secnavcount = theme_universe_get_setting('secnavitemscount');
2284
 
2285
        // Get current user role ID.
2286
        $context = context_course::instance($COURSE->id);
2287
        $roles = get_user_roles($context, $USER->id, true);
2288
        $role = 999;
2289
        $roleid = 999;
2290
        $role = key($roles);
2291
        if ($role != null) {
2292
            $roleid = $roles[$role]->roleid;
1297 ariadna 2293
        }
2294
 
1298 ariadna 2295
        // End.
2296
 
2297
        if ($this->page->theme->settings->secnavitems == 1) {
2298
 
2299
            $secnav = new stdClass();
2300
            for ($i = 1; $i <= $secnavcount; $i++) {
2301
                $secnav->title = theme_universe_get_setting("secnavcustomnavlabel" . $i);
2302
 
2303
                $url = theme_universe_get_setting("secnavcustomnavurl" . $i);
2304
                $courseid = $COURSE->id;
2305
                $newurl = str_replace("{{courseID}}", $courseid, $url);
2306
 
2307
                // User role restriction.
2308
                $selectrole = theme_universe_get_setting("secnavuserroles" . $i);
2309
 
2310
                if ($roleid == $selectrole) {
2311
                    $secnav->url = $newurl;
2312
                    $html .= $this->render_from_template('theme_universe/custom_sec_nav_item', $secnav);
2313
                }
2314
                if ($roleid != $selectrole) {
2315
                    $secnav->url = $newurl;
2316
                }
2317
                if ($selectrole == 0) {
2318
                    $secnav->url = $newurl;
2319
                    $html .= $this->render_from_template('theme_universe/custom_sec_nav_item', $secnav);
2320
                }
2321
                // End.
2322
 
2323
            }
2324
        }
2325
        return $html;
1297 ariadna 2326
    }
1299 ariadna 2327
 
1301 ariadna 2328
    public function get_navbar_image_courses()
1299 ariadna 2329
    {
1301 ariadna 2330
        global $CFG;
1299 ariadna 2331
 
1301 ariadna 2332
        if (!empty($this->page->theme->settings->navbar_icon_courses)) {
2333
            $url = $this->page->theme->setting_file_url('navbar_icon_courses', 'navbar_icon_courses');
2334
            // Get a URL suitable for moodle_url.
2335
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2336
            $url = str_replace($relativebaseurl, '', $url);
2337
            return new moodle_url($url);
1299 ariadna 2338
        }
2339
 
2340
 
1301 ariadna 2341
        return $CFG->wwwroot . '/theme/universe_child/pix/icon-catalog-white.png';
2342
    }
1299 ariadna 2343
 
1301 ariadna 2344
    public function get_navbar_image_progress()
2345
    {
2346
        global $CFG;
2347
 
2348
        if (!empty($this->page->theme->settings->navbar_icon_progress)) {
2349
            $url = $this->page->theme->setting_file_url('navbar_icon_progress', 'navbar_icon_progress');
2350
            // Get a URL suitable for moodle_url.
2351
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2352
            $url = str_replace($relativebaseurl, '', $url);
2353
            return new moodle_url($url);
2354
        }
2355
 
2356
 
2357
 
2358
        return $CFG->wwwroot . '/theme/universe_child/pix/icon-progress-white.png';
1299 ariadna 2359
    }
1300 ariadna 2360
 
1301 ariadna 2361
    public function get_navbar_image_forums()
2362
    {
2363
        global $CFG;
2364
 
2365
 
2366
        if (!empty($this->page->theme->settings->navbar_icon_forums)) {
2367
            $url = $this->page->theme->setting_file_url('navbar_icon_forums', 'navbar_icon_forums');
2368
            // Get a URL suitable for moodle_url.
2369
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2370
            $url = str_replace($relativebaseurl, '', $url);
2371
            return new moodle_url($url);
2372
        }
2373
 
2374
        return $CFG->wwwroot . '/theme/universe_child/pix/icon-forum-white.png';
2375
    }
2376
 
2377
    public function get_navbar_image_calendar()
2378
    {
2379
        global $CFG;
2380
 
2381
 
2382
        if (!empty($this->page->theme->settings->navbar_icon_calendar)) {
2383
            $url = $this->page->theme->setting_file_url('navbar_icon_calendar', 'navbar_icon_calendar');
2384
            // Get a URL suitable for moodle_url.
2385
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2386
            $url = str_replace($relativebaseurl, '', $url);
2387
            return new moodle_url($url);
2388
        }
2389
 
2390
        return $CFG->wwwroot . '/theme/universe_child/pix/icon-calendar-white.png';
2391
    }
2392
 
2393
    public function get_theme_image_login_bg()
2394
    {
2395
        global  $DB, $CFG;
2396
 
2397
        if (!empty($this->page->theme->settings->loginimagebackground)) {
2398
            $url = $this->page->theme->setting_file_url('loginimagebackground', 'loginimagebackground');
2399
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2400
            $url = str_replace($relativebaseurl, '', $url);
2401
            return new moodle_url($url);
2402
        }
2403
 
2404
        return '';
2405
    }
2406
 
2407
    public function get_navbar_image_personal_area()
2408
    {
2409
        global $CFG;
2410
 
2411
 
2412
        if (!empty($this->page->theme->settings->navbar_icon_calendar)) {
2413
            $url = $this->page->theme->setting_file_url('navbar_icon_personal_area', 'navbar_icon_personal_area');
2414
            // Get a URL suitable for moodle_url.
2415
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2416
            $url = str_replace($relativebaseurl, '', $url);
2417
            return new moodle_url($url);
2418
        }
2419
 
2420
        return $CFG->wwwroot . '/theme/universe_child/pix/icon-personal-area-white.png';
2421
    }
2422
 
2423
    public function get_navbar_image_messages()
2424
    {
2425
        global $CFG;
2426
 
2427
 
2428
        if (!empty($this->page->theme->settings->navbar_icon_calendar)) {
2429
            $url = $this->page->theme->setting_file_url('navbar_icon_messages', 'navbar_icon_messages');
2430
            // Get a URL suitable for moodle_url.
2431
            $relativebaseurl = preg_replace('|^https?://|i', '//', $CFG->wwwroot);
2432
            $url = str_replace($relativebaseurl, '', $url);
2433
            return new moodle_url($url);
2434
        }
2435
 
2436
        return $CFG->wwwroot . '/theme/universe_child/pix/icon-messages-white.png';
2437
    }
2438
 
2439
    private function extractDurationFromVideo($record, $filename)
2440
    {
2441
        global $DB;
2442
 
2443
        $duration = 0;
2444
 
2445
        if (empty($record->duration)) {
2446
            $fs = get_file_storage();
2447
            $file = $fs->get_file($record->contextid, $record->component, $record->filearea, $record->itemid, $record->filepath, $record->filename);
2448
            if ($file) {
2449
 
2450
                $data = $file->get_content();
2451
 
2452
                $path_temp = __DIR__ . DIRECTORY_SEPARATOR . 'tmp';
2453
                if (!file_exists($path_temp)) {
2454
                    mkdir($path_temp, 0755);
2455
                }
2456
 
2457
                $full_filename = $path_temp . DIRECTORY_SEPARATOR . uniqid() . '_' . $filename;
2458
                file_put_contents($full_filename, $data);
2459
 
2460
                if (file_exists($full_filename)) {
2461
                    $cmd = "/usr/bin/ffprobe -i $full_filename -show_entries format=duration -v quiet -of csv=\"p=0\" ";
2462
                    $response = trim(shell_exec($cmd));
2463
                    @unlink($full_filename);
2464
 
2465
 
2466
                    $duration = $response;
2467
 
2468
 
2469
                    if ($response) {
2470
                        $response = floatval($response);
2471
 
2472
                        if ($response > 60) {
2473
 
2474
                            //echo 'response = ' . $response . '<br>';
2475
 
2476
                            $minutes = intval($response / 60);
2477
                            //echo 'minutes = ' . $minutes . '<br>';
2478
 
2479
                            $seconds = round(($response - ($minutes * 60)));
2480
                            //echo 'seconds = ' . $seconds . '<br>';
2481
 
2482
 
2483
                            if ($minutes < 10) {
2484
                                $duration = '0' . $minutes;
2485
                            } else {
2486
                                $duration = $minutes;
2487
                            }
2488
 
2489
                            if ($seconds) {
2490
                                if ($seconds < 10) {
2491
                                    $duration = $duration . ':0' . $seconds;
2492
                                } else {
2493
                                    $duration = $duration . ':' . $seconds;
2494
                                }
2495
                            } else {
2496
                                $duration = $duration . ':00';
2497
                            }
2498
                        } else {
2499
                            $duration = '00:' . intval($response);
2500
                        }
2501
 
2502
 
2503
 
2504
                        $dataobject = new \stdClass();
2505
                        $dataobject->id = $record->id;
2506
                        $dataobject->duration = $duration;
2507
 
2508
 
2509
 
2510
                        $DB->update_record('files', $dataobject);
2511
                    }
2512
                }
2513
            }
2514
        }
2515
        return $duration;
2516
    }
2517
 
2518
    private function substr_cesa_navigation_course_menu_name($s, $l = 50)
2519
    {
2520
        $s = trim($s);
2521
        if (strlen($s) > $l) {
2522
            $s = substr($s, 0, $l) . '...';
2523
        }
2524
        return $s;
2525
    }
2526
 
2527
    public function cesa_navigation_course_menu_lateral_output()
2528
    {
2529
 
2530
 
2531
 
2532
        global $CFG, $COURSE, $PAGE, $DB, $OUTPUT;
2533
 
2534
 
2535
 
2536
 
2537
        if (!$COURSE->id) {
2538
            return '';
2539
        }
2540
 
2541
        $course_id = $COURSE->id;
2542
 
2543
        $parent = optional_param('parent', 0, PARAM_INT); // Course module id
2544
        if (!$parent) {
2545
            $parent = optional_param('amp;parent', 0, PARAM_INT); // Course module id
2546
        }
2547
 
2548
        //$PAGE->requires->js('/theme/edumynew/javascript/menu-lateral.js');
2549
 
2550
 
2551
        if ($parent) {
2552
            $sql  = ' SELECT * FROM {subcourse} WHERE course = ' . $parent;
2553
            $sql .= ' AND refcourse = ' . $course_id;
2554
 
2555
            $recordParentRefCourse  = $DB->get_record_sql($sql);
2556
            if ($recordParentRefCourse) {
2557
                $course_id = $recordParentRefCourse->course;
2558
            }
2559
        }
2560
 
2561
 
2562
 
2563
        $course = get_course($course_id);
2564
        $course_context = context_course::instance($course->id);
2565
        $completioninfo = new \completion_info($course);
2566
 
2567
        // $course_context = !empty($PAGE->cm->id)  ? $PAGE->cm : \context_course::instance($COURSE->id);
2568
        // First we should check if we want to add navigation.
2569
        // Get a list of all the activities in the course.
2570
 
2571
 
2572
 
2573
        $menu = [];
2574
 
2575
        $currentServerLink = strtolower(trim($_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']));
2576
        $currentServerLink = html_entity_decode($currentServerLink);
2577
        $currentServerLink = htmlentities($currentServerLink);
2578
 
2579
        $parts = explode('&', $currentServerLink);
2580
        if (count($parts) > 1) {
2581
            $currentServerLink = $parts[0];
2582
        }
2583
 
2584
 
2585
 
2586
 
2587
        $modules = get_fast_modinfo($course->id)->get_cms();
2588
 
2589
        $prevmod = null;
2590
        $nextmod = null;
2591
        $currentmod = new stdClass();
2592
        $currentmod->name = "Sin Módulos";
2593
        $mods = [];
2594
        $menu = [];
2595
        $numberOfTemary = 1;
2596
        $prevlink = new \StdClass();
2597
        $nextlink = new \StdClass();
2598
        $prevlink->url = "#";
2599
        $nextlink->url = "#";
2600
 
2601
        $isACoursePage = $course->id !== "1" ? true : false;
2602
 
2603
 
2604
 
2605
 
2606
        $modules = get_fast_modinfo($COURSE->id)->get_cms();
2607
        /*
2608
            echo '<pre>';
2609
            print_r($modules);
2610
            echo '</pre>';
2611
            */
2612
 
2613
        if (!empty($modules)) {
2614
            // Put the modules into an array in order by the position they are shown in the course.
2615
            foreach ($modules as $module) {
2616
                if (!$module->uservisible || $module->is_stealth() || empty($module->url)) {
2617
                    continue;
2618
                }
2619
                $mods[$module->id] = $module;
2620
            }
2621
 
2622
 
2623
            $nummods = count($mods);
2624
 
2625
 
2626
            // If there is only one mod then do nothing.
2627
            if ($nummods == 1) {
2628
            }
2629
 
2630
            // Get an array of just the course module ids used to get the cmid value based on their position in the course.
2631
            $modids = array_keys($mods);
2632
 
2633
            // Get the position in the array of the course module we are viewing.
2634
            $position = array_search($course_context->id, $modids);   //array_search($this->page->cm->id, $modids);
2635
 
2636
            $currentmod = $mods[$modids[$position]];
2637
 
2638
 
2639
 
2640
            // Check if we have a previous mod to show.
2641
            if ($position > 0) {
2642
                $prevmod = $mods[$modids[$position - 1]];
2643
            }
2644
 
2645
            // Check if we have a next mod to show.
2646
            if ($position < ($nummods - 1)) {
2647
                $nextmod = $mods[$modids[$position + 1]];
2648
            }
2649
        }
2650
 
2651
 
2652
        //$sections = $DB->get_records('course_sections', ['course' => $COURSE->id], 'section ASC', 'id,name,section,sequence,visible');
2653
 
2654
 
2655
 
2656
 
2657
        $modinfo = get_fast_modinfo($course);
2658
        $records  =  $modinfo->get_section_info_all();
2659
        $sections = [];
2660
 
2661
        foreach ($records as $record) {
2662
            if (!$record->visible) {
2663
                continue;
2664
            }
2665
 
2666
            $section = new \stdClass();
2667
            $section->id = $record->id;
2668
            $section->section = $record->section;
2669
            $section->name = $record->name;
2670
            $section->parent = $record->parent;
2671
            $section->visible = 1;
2672
 
2673
 
2674
            array_push($sections, $section);
2675
        }
2676
 
2677
 
2678
 
2679
        $openParent = 0;
2680
        $maxSections = count($sections);
2681
        for ($i = 0; $i < $maxSections; $i++) {
2682
 
2683
 
2684
 
2685
            $j = $i + 1;
2686
            if ($j < $maxSections) {
2687
 
2688
                if ($sections[$j]->parent) {
2689
                    $openParent = true;
2690
                    $sections[$i]->close_section_parent = 0;
2691
                    $sections[$i]->close_section = 0;
2692
                } else {
2693
                    $sections[$i]->close_section_parent = $openParent ? 1 : 0;
2694
 
2695
                    $sections[$i]->close_section = 1;
2696
                }
2697
            } else {
2698
                $sections[$i]->close_section_parent = $openParent ? 1 : 0;
2699
                $sections[$i]->close_section = 1;
2700
            }
2701
 
2702
            // print_r($section);
2703
 
2704
 
2705
        }
2706
 
2707
        /*
2708
             echo '<pre>';
2709
           print_r($sections);
2710
           echo '</pre>';
2711
 
2712
      */
2713
 
2714
 
2715
 
2716
 
2717
        foreach ($sections as $key =>  $section) {
2718
 
2719
            if (!$section->visible) {
2720
                continue;
2721
            }
2722
 
2723
            $activities = [];
2724
            $section_active = false;
2725
 
2726
            foreach ($modules as $module) {
2727
 
2728
                if ($module->section  != $section->id) {
2729
                    continue;
2730
                }
2731
 
2732
                if (!$module->uservisible || $module->is_stealth()) {
2733
                    // if (!$module->uservisible || $module->is_stealth() || empty($module->url)) {
2734
                    continue;
2735
                }
2736
 
2737
                $mods[$module->id] = $module;
2738
 
2739
                $duration = '';
2740
                $type = '';
2741
                $filepath = '';
2742
 
2743
                $sql = 'SELECT md.name, cm.instance  FROM {modules} md  ' .
2744
                    ' JOIN {course_modules} cm ON cm.module = md.id ' .
2745
                    ' WHERE cm.id = '  . $module->id . ' LIMIT 1 ';
2746
 
2747
                $record = $DB->get_record_sql($sql);
2748
                if ($record) {
2749
 
2750
                    /*
2751
                        echo '<pre>';
2752
                        print_r($record);
2753
                        echo '<pre>';
2754
                        */
2755
 
2756
                    $type = $record->name;
2757
 
2758
                    if ($type == 'hvp') {
2759
                        $instance   = $record->instance;
2760
 
2761
                        $sql = 'SELECT json_content FROM {hvp} WHERE id = ' . $instance . ' LIMIT 1';
2762
                        $record = $DB->get_record_sql($sql);
2763
 
2764
                        if ($record) {
2765
                            $json_content = json_decode($record->json_content);
2766
 
2767
                            if (!empty($json_content->interactiveVideo->video->files[0]->path)) {
2768
                                $filepath = trim($json_content->interactiveVideo->video->files[0]->path);
2769
                                $filepath = trim(str_replace('#tmp', '', $filepath));
2770
 
2771
 
2772
                                $arr = explode('/', $filepath);
2773
                                if (count($arr) > 1) {
2774
                                    $filename = $arr[count($arr) - 1];
2775
                                } else {
2776
                                    $filename = $arr[0];
2777
                                }
2778
 
2779
                                $record = $DB->get_record('files', ['filename' => $filename]);
2780
                                if ($record) {
2781
                                    $duration = $this->extractDurationFromVideo($record, $filename);
2782
                                }
2783
                            }
2784
                        }
2785
                    }
2786
                }
2787
 
2788
                $modname = $module->get_formatted_name();
2789
                $modcontent = $module->get_formatted_content();
2790
 
2791
                if (empty($module->url)) {
2792
                    $linkurl = '';
2793
                    $currentLink = '';
2794
                } else {
2795
 
2796
                    $linkurl = new moodle_url($module->url, array('forceview' => 1));
2797
                    $linkurl = strtolower(trim($linkurl->__toString()));
2798
 
2799
                    $parts = explode('&', $linkurl);
2800
                    if (count($parts) > 1) {
2801
                        $currentLink = $parts[0];
2802
                    } else {
2803
                        $currentLink = $linkurl;
2804
                    }
2805
                }
2806
 
2807
                $completiondata = $completioninfo->get_data($module, true);
2808
 
2809
                if (strcasecmp($currentLink,  $currentServerLink) == 0) {
2810
                    $active = true;
2811
                    $section_active = true;
2812
                } else {
2813
                    $active = false;
2814
                }
2815
 
2816
                array_push($activities, [
2817
                    'active' => $active,
2818
                    'indexElement' => $key,
2819
                    'numberOfTemary' => $numberOfTemary,
2820
                    'activity' => true,
2821
                    'blank' => !empty($section->section),
2822
                    'name' => $this->substr_cesa_navigation_course_menu_name($modname),
2823
                    'content' => $modcontent,
2824
                    'duration' => $duration,
2825
                    'type' =>  $type,
2826
                    'completed' => $completiondata->completionstate == COMPLETION_COMPLETE || $completiondata->completionstate == COMPLETION_COMPLETE_PASS,
2827
                    'failed' => $completiondata->completionstate == COMPLETION_COMPLETE_FAIL,
2828
                    'url' => $linkurl
2829
                ]);
2830
            }
2831
 
2832
 
2833
            if ($activities) {
2834
 
2835
                if ($section->section) {
2836
                    $sectionname = trim($section->name);
2837
                    $sectionname = $sectionname ? $sectionname : ' Tema ' . $section->section;
2838
                } else {
2839
                    $sectionname = 'Recursos';
2840
                }
2841
 
2842
                array_push($menu, [
2843
                    'active' => $section_active,
2844
                    'indexElement' => $key,
2845
                    'id' => $section->id,
2846
                    'numberOfTemary' => $numberOfTemary,
2847
                    'section' => true,
2848
                    'name' => $this->substr_cesa_navigation_course_menu_name($sectionname),
2849
                    'close_section_parent' => $section->close_section_parent,
2850
                    'close_section' => $section->close_section,
2851
                    'completed' => false,
2852
                    'url' => false,
2853
                    'activities' => $activities,
2854
 
2855
 
2856
                ]);
2857
            }
2858
 
2859
 
2860
            $numberOfTemary = ++$numberOfTemary;
2861
        }
2862
 
2863
        // Check if there is a previous module to display.
2864
        if ($prevmod) {
2865
            $linkurl = new \moodle_url($prevmod->url, array('forceview' => 1));
2866
            $attributes = [];
2867
            $prevlink = new \action_link($linkurl, $OUTPUT->larrow(), null, $attributes);
2868
        }
2869
 
2870
        // Check if there is a next module to display.
2871
        if ($nextmod) {
2872
            $linkurl = new \moodle_url($nextmod->url, array('forceview' => 1));
2873
            $attributes = [];
2874
            $nextlink = new \action_link($linkurl, $OUTPUT->rarrow(), null, $attributes);
2875
        }
2876
 
2877
 
2878
        //  echo '<pre>';
2879
        // print_r($activities);
2880
        // echo '</pre>';
2881
        // exit;
2882
 
2883
 
2884
        $progreso = number_format(progress::get_course_progress_percentage($course), 2); // Progreso por curso
2885
 
2886
        $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);
2887
        return $course_navigation->export_for_template($OUTPUT);
2888
    }
2889
 
1300 ariadna 2890
    function universe_child_course_drawer(): string
2891
    {
2892
        global $PAGE;
2893
 
2894
        // If the course index is explicitly set and if it should be hidden.
2895
        if ($PAGE->get_show_course_index() === false) {
2896
            return '';
2897
        }
2898
 
2899
        // Only add course index on non-site course pages.
2900
        if (!$PAGE->course || $PAGE->course->id == SITEID) {
2901
            return '';
2902
        }
2903
 
2904
        // Show course index to users can access the course only.
2905
        if (!can_access_course($PAGE->course, null, '', true)) {
2906
            return '';
2907
        }
2908
 
2909
        $format = course_get_format($PAGE->course);
2910
        $renderer = $format->get_renderer($PAGE);
2911
        if (method_exists($renderer, 'course_index_drawer')) {
2912
            return $this->render_from_template('theme_universe_child/courseindex/drawer', []);
2913
        }
2914
 
2915
        return '';
2916
    }
1301 ariadna 2917
 
2918
    /*
2919
    *
2920
    * Method to get reference to $CFG->themedir variable
2921
    *
2922
    */
2923
    function theme_universe_themedir()
2924
    {
2925
        global $CFG;
2926
 
2927
        $teme_dir = '/theme';
2928
 
2929
        if (isset($CFG->themedir)) {
2930
            $teme_dir = $CFG->themedir;
2931
            $teme_dir = str_replace($CFG->dirroot, '', $CFG->themedir);
2932
        }
2933
 
2934
        return $teme_dir;
2935
    }
1291 ariadna 2936
}