Proyectos de Subversion Moodle

Rev

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