Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Renderer for use with the badges output
19
 *
20
 * @package    core
21
 * @subpackage badges
22
 * @copyright  2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 * @author     Yuliya Bozhko <yuliya.bozhko@totaralms.com>
25
 */
26
 
27
defined('MOODLE_INTERNAL') || die();
28
 
29
require_once($CFG->libdir . '/badgeslib.php');
30
require_once($CFG->libdir . '/tablelib.php');
31
 
32
/**
33
 * Standard HTML output renderer for badges
34
 */
35
class core_badges_renderer extends plugin_renderer_base {
36
 
37
    // Outputs badges list.
38
    public function print_badges_list($badges, $userid, $profile = false, $external = false) {
39
        global $USER, $CFG;
40
        foreach ($badges as $badge) {
41
            if (!$external) {
42
                $context = ($badge->type == BADGE_TYPE_SITE) ? context_system::instance() : context_course::instance($badge->courseid);
43
                $bname = $badge->name;
44
                $imageurl = moodle_url::make_pluginfile_url($context->id, 'badges', 'badgeimage', $badge->id, '/', 'f3', false);
45
            } else {
46
                $bname = '';
47
                $imageurl = '';
48
                if (!empty($badge->name)) {
49
                    $bname = s($badge->name);
50
                }
51
                if (!empty($badge->image)) {
52
                    if (is_object($badge->image)) {
53
                        if (!empty($badge->image->caption)) {
54
                            $badge->imagecaption = $badge->image->caption;
55
                        }
56
                        $imageurl = $badge->image->id;
57
                    } else {
58
                        $imageurl = $badge->image;
59
                    }
60
                }
61
                if (isset($badge->assertion->badge->name)) {
62
                    $bname = s($badge->assertion->badge->name);
63
                }
64
                if (isset($badge->imageUrl)) {
65
                    $imageurl = $badge->imageUrl;
66
                }
67
            }
68
 
69
            $name = html_writer::tag('span', $bname, array('class' => 'badge-name'));
70
 
71
            $imagecaption = $badge->imagecaption ?? '';
72
            $image = html_writer::empty_tag('img', ['src' => $imageurl, 'class' => 'badge-image', 'alt' => $imagecaption]);
73
            if (!empty($badge->dateexpire) && $badge->dateexpire < time()) {
74
                $image .= $this->output->pix_icon('i/expired',
75
                        get_string('expireddate', 'badges', userdate($badge->dateexpire)),
76
                        'moodle',
77
                        array('class' => 'expireimage'));
78
                $name .= '(' . get_string('expired', 'badges') . ')';
79
            }
80
 
81
            $download = $status = $push = '';
82
            if (($userid == $USER->id) && !$profile) {
83
                $params = array(
84
                    'download' => $badge->id,
85
                    'hash' => $badge->uniquehash,
86
                    'sesskey' => sesskey()
87
                );
88
                $url = new moodle_url(
89
                    'mybadges.php',
90
                    $params
91
                );
92
                $notexpiredbadge = (empty($badge->dateexpire) || $badge->dateexpire > time());
93
                $userbackpack = badges_get_user_backpack();
94
                if (!empty($CFG->badges_allowexternalbackpack) && $notexpiredbadge && $userbackpack) {
95
                    $assertion = new moodle_url('/badges/assertion.php', array('b' => $badge->uniquehash));
96
                    $icon = new pix_icon('t/backpack', get_string('addtobackpack', 'badges'));
97
                    if (badges_open_badges_backpack_api($userbackpack->id) == OPEN_BADGES_V2) {
98
                        $addurl = new moodle_url('/badges/backpack-add.php', array('hash' => $badge->uniquehash));
99
                        $push = $this->output->action_icon($addurl, $icon);
100
                    } else if (badges_open_badges_backpack_api($userbackpack->id) == OPEN_BADGES_V2P1) {
101
                        $addurl = new moodle_url('/badges/backpack-export.php', array('hash' => $badge->uniquehash));
102
                        $push = $this->output->action_icon($addurl, $icon);
103
                    }
104
                }
105
 
106
                $download = $this->output->action_icon($url, new pix_icon('t/download', get_string('download')));
107
                if ($badge->visible) {
108
                    $url = new moodle_url('mybadges.php', array('hide' => $badge->issuedid, 'sesskey' => sesskey()));
109
                    $status = $this->output->action_icon($url, new pix_icon('t/hide', get_string('makeprivate', 'badges')));
110
                } else {
111
                    $url = new moodle_url('mybadges.php', array('show' => $badge->issuedid, 'sesskey' => sesskey()));
112
                    $status = $this->output->action_icon($url, new pix_icon('t/show', get_string('makepublic', 'badges')));
113
                }
114
            }
115
 
116
            if (!$profile) {
117
                $url = new moodle_url('badge.php', array('hash' => $badge->uniquehash));
118
            } else {
119
                if (!$external) {
120
                    $url = new moodle_url('/badges/badge.php', array('hash' => $badge->uniquehash));
121
                } else {
122
                    $hash = hash('md5', $badge->hostedUrl);
123
                    $url = new moodle_url('/badges/external.php', array('hash' => $hash, 'user' => $userid));
124
                }
125
            }
126
            $actions = html_writer::tag('div', $push . $download . $status, array('class' => 'badge-actions'));
127
            $items[] = html_writer::link($url, $image . $actions . $name, array('title' => $bname));
128
        }
129
 
130
        return html_writer::alist($items, array('class' => 'badges'));
131
    }
132
 
133
    // Recipients selection form.
134
    public function recipients_selection_form(user_selector_base $existinguc, user_selector_base $potentialuc) {
135
        $output = '';
136
        $formattributes = array();
137
        $formattributes['id'] = 'recipientform';
138
        $formattributes['action'] = $this->page->url;
139
        $formattributes['method'] = 'post';
140
        $output .= html_writer::start_tag('form', $formattributes);
141
        $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
142
 
143
        $existingcell = new html_table_cell();
144
        $existingcell->text = $existinguc->display(true);
145
        $existingcell->attributes['class'] = 'existing';
146
        $actioncell = new html_table_cell();
147
        $actioncell->text  = html_writer::start_tag('div', array());
148
        $actioncell->text .= html_writer::empty_tag('input', array(
149
                    'type' => 'submit',
150
                    'name' => 'award',
151
                    'value' => $this->output->larrow() . ' ' . get_string('award', 'badges'),
152
                    'class' => 'actionbutton btn btn-secondary')
153
                );
1441 ariadna 154
        if (has_capability('moodle/badges:revokebadge', $this->page->context)) {
155
            $actioncell->text .= html_writer::empty_tag(
156
                'input',
157
                [
1 efrain 158
                    'type' => 'submit',
159
                    'name' => 'revoke',
160
                    'value' => get_string('revoke', 'badges') . ' ' . $this->output->rarrow(),
1441 ariadna 161
                    'class' => 'actionbutton btn btn-secondary',
162
                ]
163
            );
164
        }
1 efrain 165
        $actioncell->text .= html_writer::end_tag('div', array());
166
        $actioncell->attributes['class'] = 'actions';
167
        $potentialcell = new html_table_cell();
168
        $potentialcell->text = $potentialuc->display(true);
169
        $potentialcell->attributes['class'] = 'potential';
170
 
171
        $table = new html_table();
172
        $table->attributes['class'] = 'recipienttable boxaligncenter';
173
        $table->data = array(new html_table_row(array($existingcell, $actioncell, $potentialcell)));
174
        $output .= html_writer::table($table);
175
 
176
        $output .= html_writer::end_tag('form');
177
        return $output;
178
    }
179
 
180
    // Prints a badge overview infomation.
181
    public function print_badge_overview($badge, $context) {
182
        $display = "";
183
        $languages = get_string_manager()->get_list_of_languages();
184
 
185
        // Badge details.
186
        $display .= $this->heading(get_string('badgedetails', 'badges'), 3);
187
        $dl = array();
188
        $dl[get_string('name')] = $badge->name;
189
        $dl[get_string('version', 'badges')] = $badge->version;
190
        $dl[get_string('language')] = $languages[$badge->language];
191
        $dl[get_string('description', 'badges')] = $badge->description;
192
        $dl[get_string('createdon', 'search')] = userdate($badge->timecreated);
193
        $dl[get_string('badgeimage', 'badges')] = print_badge_image($badge, $context, 'large');
194
        $dl[get_string('imagecaption', 'badges')] = $badge->imagecaption;
195
        $tags = \core_tag_tag::get_item_tags('core_badges', 'badge', $badge->id);
196
        $dl[get_string('tags', 'badges')] = $this->output->tag_list($tags, '');
197
        $display .= $this->definition_list($dl);
198
 
199
        // Issuer details.
200
        $display .= $this->heading(get_string('issuerdetails', 'badges'), 3);
201
        $dl = array();
202
        $dl[get_string('issuername', 'badges')] = $badge->issuername;
1441 ariadna 203
        $dl[get_string('contact', 'badges')] = '';
204
        if (trim($badge->issuercontact)) {
205
            $dl[get_string('contact', 'badges')] = html_writer::tag(
206
                'a',
207
                $badge->issuercontact,
208
                ['href' => 'mailto:' . $badge->issuercontact],
209
            );
210
        }
211
        $dl[get_string('issuerurl', 'badges')] = '';
212
        if (trim($badge->issuerurl)) {
213
            $dl[get_string('issuerurl', 'badges')] = html_writer::tag(
214
                'a',
215
                $badge->issuerurl,
216
                ['href' => $badge->issuerurl, 'target' => '_blank'],
217
            );
218
        }
1 efrain 219
        $display .= $this->definition_list($dl);
220
 
221
        // Issuance details if any.
222
        $display .= $this->heading(get_string('issuancedetails', 'badges'), 3);
223
        if ($badge->can_expire()) {
224
            if ($badge->expiredate) {
225
                $display .= get_string('expiredate', 'badges', userdate($badge->expiredate));
226
            } else if ($badge->expireperiod) {
227
                if ($badge->expireperiod < 60) {
228
                    $display .= get_string('expireperiods', 'badges', round($badge->expireperiod, 2));
229
                } else if ($badge->expireperiod < 60 * 60) {
230
                    $display .= get_string('expireperiodm', 'badges', round($badge->expireperiod / 60, 2));
231
                } else if ($badge->expireperiod < 60 * 60 * 24) {
232
                    $display .= get_string('expireperiodh', 'badges', round($badge->expireperiod / 60 / 60, 2));
233
                } else {
234
                    $display .= get_string('expireperiod', 'badges', round($badge->expireperiod / 60 / 60 / 24, 2));
235
                }
236
            }
237
        } else {
238
            $display .= get_string('noexpiry', 'badges');
239
        }
240
 
241
        // Criteria details if any.
242
        $display .= $this->heading(get_string('bcriteria', 'badges'), 3);
243
        if ($badge->has_criteria()) {
244
            $display .= self::print_badge_criteria($badge);
245
        } else {
246
            $display .= get_string('nocriteria', 'badges');
247
            if (has_capability('moodle/badges:configurecriteria', $context)) {
248
                $display .= $this->output->single_button(
249
                    new moodle_url('/badges/criteria.php', array('id' => $badge->id)),
250
                    get_string('addcriteria', 'badges'), 'POST', array('class' => 'activatebadge'));
251
            }
252
        }
253
 
254
        // Awards details if any.
255
        if (has_capability('moodle/badges:viewawarded', $context)) {
256
            $display .= $this->heading(get_string('awards', 'badges'), 3);
257
            if ($badge->has_awards()) {
258
                $url = new moodle_url('/badges/recipients.php', array('id' => $badge->id));
259
                $a = new stdClass();
1441 ariadna 260
                $a->badgename = $badge->name;
1 efrain 261
                $a->link = $url->out();
262
                $a->count = count($badge->get_awards());
263
                $display .= get_string('numawards', 'badges', $a);
264
            } else {
265
                $display .= get_string('noawards', 'badges');
266
            }
267
 
268
            if (has_capability('moodle/badges:awardbadge', $context) &&
269
                $badge->has_manual_award_criteria() &&
270
                $badge->is_active()) {
271
                $display .= $this->output->single_button(
272
                        new moodle_url('/badges/award.php', array('id' => $badge->id)),
273
                        get_string('award', 'badges'), 'POST', array('class' => 'activatebadge'));
274
            }
275
        }
276
 
277
        $display .= self::print_badge_endorsement($badge);
278
        $display .= self::print_badge_related($badge);
279
        $display .= self::print_badge_alignments($badge);
280
 
281
        return html_writer::div($display, null, array('id' => 'badge-overview'));
282
    }
283
 
284
    /**
285
     * @deprecated sinde Moodle 4.3
286
     */
1441 ariadna 287
    #[\core\attribute\deprecated(null, reason: 'It is no longer used', since: '4.3', mdl: 'MDL-77061', final: true)]
288
    public function print_badge_table_actions() {
289
        \core\deprecation::emit_deprecation([self::class, __FUNCTION__]);
1 efrain 290
    }
291
 
292
    /**
293
     * Render an issued badge.
294
     *
295
     * @param \core_badges\output\issued_badge $ibadge
296
     * @return string
297
     */
298
    protected function render_issued_badge(\core_badges\output\issued_badge $ibadge) {
299
        $data = $ibadge->export_for_template($this);
300
        return parent::render_from_template('core_badges/issued_badge', $data);
301
    }
302
 
303
    /**
304
     * Render an issued badge.
305
     *
306
     * @param \core_badges\output\badgeclass $badge
307
     * @return string
308
     */
309
    protected function render_badgeclass(\core_badges\output\badgeclass $badge) {
310
        $data = $badge->export_for_template($this);
311
        return parent::render_from_template('core_badges/issued_badge', $data);
312
    }
313
 
314
    /**
315
     * Render an external badge.
316
     *
317
     * @param \core_badges\output\external_badge $ibadge
318
     * @return string
319
     */
320
    protected function render_external_badge(\core_badges\output\external_badge $ibadge) {
321
        $data = $ibadge->export_for_template($this);
322
        return parent::render_from_template('core_badges/issued_badge', $data);
323
    }
324
 
325
    /**
326
     * Render a collection of user badges.
327
     *
328
     * @param \core_badges\output\badge_user_collection $badges
329
     * @return string
330
     */
331
    protected function render_badge_user_collection(\core_badges\output\badge_user_collection $badges) {
332
        global $CFG, $USER, $SITE;
333
        $backpack = $badges->backpack;
334
        $mybackpack = new moodle_url('/badges/mybackpack.php');
335
 
336
        $paging = new paging_bar($badges->totalcount, $badges->page, $badges->perpage, $this->page->url, 'page');
337
        $htmlpagingbar = $this->render($paging);
338
 
339
        // Set backpack connection string.
340
        $backpackconnect = '';
341
        if (!empty($CFG->badges_allowexternalbackpack) && is_null($backpack)) {
342
            $backpackconnect = $this->output->box(get_string('localconnectto', 'badges', $mybackpack->out()), 'noticebox');
343
        }
344
        // Search box.
345
        $searchform = $this->output->box($this->helper_search_form($badges->search), 'boxwidthwide boxaligncenter');
346
 
347
        // Download all button.
348
        $actionhtml = $this->output->single_button(
349
                    new moodle_url('/badges/mybadges.php', array('downloadall' => true, 'sesskey' => sesskey())),
350
                    get_string('downloadall'), 'POST', array('class' => 'activatebadge'));
351
        $downloadall = $this->output->box('', 'col-md-3');
352
        $downloadall .= $this->output->box($actionhtml, 'col-md-9');
1441 ariadna 353
        $downloadall = $this->output->box($downloadall, 'row ms-5');
1 efrain 354
 
355
        // Local badges.
356
        $localhtml = html_writer::start_tag('div', array('id' => 'issued-badge-table', 'class' => 'generalbox'));
357
        $sitename = format_string($SITE->fullname, true, array('context' => context_system::instance()));
358
        $heading = get_string('localbadges', 'badges', $sitename);
359
        $localhtml .= $this->output->heading_with_help($heading, 'localbadgesh', 'badges');
360
        if ($badges->badges) {
361
            $countmessage = $this->output->box(get_string('badgesearned', 'badges', $badges->totalcount));
362
 
363
            $htmllist = $this->print_badges_list($badges->badges, $USER->id);
364
            $localhtml .= $backpackconnect . $countmessage . $searchform;
365
            $localhtml .= $htmlpagingbar . $htmllist . $htmlpagingbar . $downloadall;
366
        } else {
367
            $localhtml .= $searchform . $this->output->notification(get_string('nobadges', 'badges'), 'info');
368
        }
369
        $localhtml .= html_writer::end_tag('div');
370
 
371
        // External badges.
372
        $externalhtml = "";
373
        if (!empty($CFG->badges_allowexternalbackpack)) {
374
            $externalhtml .= html_writer::start_tag('div', array('class' => 'generalbox'));
375
            $externalhtml .= $this->output->heading_with_help(get_string('externalbadges', 'badges'), 'externalbadges', 'badges');
376
            if (!is_null($backpack)) {
377
                if ($backpack->totalcollections == 0) {
378
                    $externalhtml .= get_string('nobackpackcollectionssummary', 'badges', $backpack);
379
                } else {
380
                    if ($backpack->totalbadges == 0) {
381
                        $externalhtml .= get_string('nobackpackbadgessummary', 'badges', $backpack);
382
                    } else {
383
                        $externalhtml .= get_string('backpackbadgessummary', 'badges', $backpack);
384
                        $externalhtml .= '<br/><br/>' . $this->print_badges_list($backpack->badges, $USER->id, true, true);
385
                    }
386
                }
387
            } else {
388
                $externalhtml .= get_string('externalconnectto', 'badges', $mybackpack->out());
389
            }
390
 
391
            $externalhtml .= html_writer::end_tag('div');
392
            $attr = ['class' => 'btn btn-secondary'];
393
            $label = get_string('backpackbadgessettings', 'badges');
394
            $backpacksettings = html_writer::link(new moodle_url('/badges/mybackpack.php'), $label, $attr);
395
            $actionshtml = $this->output->box('', 'col-md-3');
396
            $actionshtml .= $this->output->box($backpacksettings, 'col-md-9');
1441 ariadna 397
            $actionshtml = $this->output->box($actionshtml, 'row ms-5');
1 efrain 398
            $externalhtml .= $actionshtml;
399
        }
400
 
401
        return $localhtml . $externalhtml;
402
    }
403
 
404
    /**
405
     * Render a collection of badges.
406
     *
407
     * @param \core_badges\output\badge_collection $badges
408
     * @return string
409
     *
410
     * @deprecated since Moodle 4.4
411
     * @todo MDL-80455 this will be removed in Moodle 4.8
412
     */
413
    protected function render_badge_collection(\core_badges\output\badge_collection $badges) {
414
        debugging('The method render_badge_collection() has been deprecated', DEBUG_DEVELOPER);
415
        $paging = new paging_bar($badges->totalcount, $badges->page, $badges->perpage, $this->page->url, 'page');
416
        $htmlpagingbar = $this->render($paging);
417
        $table = new html_table();
418
        $table->attributes['class'] = 'table table-bordered table-striped';
419
 
420
        $sortbyname = $this->helper_sortable_heading(get_string('name'),
421
                'name', $badges->sort, $badges->dir);
422
        $sortbyawarded = $this->helper_sortable_heading(get_string('awardedtoyou', 'badges'),
423
                'dateissued', $badges->sort, $badges->dir);
424
        $table->head = array(
425
                    get_string('badgeimage', 'badges'),
426
                    $sortbyname,
427
                    get_string('description', 'badges'),
428
                    get_string('bcriteria', 'badges'),
429
                    $sortbyawarded
430
                );
431
        $table->colclasses = array('badgeimage', 'name', 'description', 'criteria', 'awards');
432
 
433
        foreach ($badges->badges as $badge) {
434
            $badgeimage = print_badge_image($badge, $this->page->context, 'large');
435
            $name = $badge->name;
436
            $description = $badge->description;
437
            $criteria = self::print_badge_criteria($badge);
438
            if ($badge->dateissued) {
439
                $icon = new pix_icon('i/valid',
440
                            get_string('dateearned', 'badges',
441
                                userdate($badge->dateissued, get_string('strftimedatefullshort', 'core_langconfig'))));
442
                $badgeurl = new moodle_url('/badges/badge.php', array('hash' => $badge->uniquehash));
443
                $awarded = $this->output->action_icon($badgeurl, $icon, null, null, true);
444
            } else {
445
                $awarded = "";
446
            }
447
            $row = array($badgeimage, $name, $description, $criteria, $awarded);
448
            $table->data[] = $row;
449
        }
450
 
451
        $htmltable = html_writer::table($table);
452
 
453
        return $htmlpagingbar . $htmltable . $htmlpagingbar;
454
    }
455
 
456
    /**
457
     * @deprecated since Moodle 4.3
458
     */
1441 ariadna 459
    #[\core\attribute\deprecated(null, reason: 'It is no longer used', since: '4.3', mdl: 'MDL-77061', final: true)]
460
    protected function render_badge_management() {
461
        \core\deprecation::emit_deprecation([self::class, __FUNCTION__]);
1 efrain 462
    }
463
 
464
    /**
465
     * Prints badge status box.
466
     *
467
     * @param badge $badge
468
     * @return Either the status box html as a string or null
469
     */
470
    public function print_badge_status_box(badge $badge) {
471
        if (has_capability('moodle/badges:configurecriteria', $badge->get_context())) {
472
 
473
            if (!$badge->has_criteria()) {
474
                $criteriaurl = new moodle_url('/badges/criteria.php', array('id' => $badge->id));
475
                $status = get_string('nocriteria', 'badges');
476
                if ($this->page->url != $criteriaurl) {
477
                    $action = $this->output->single_button(
478
                        $criteriaurl,
479
                        get_string('addcriteria', 'badges'), 'POST', array('class' => 'activatebadge'));
480
                } else {
481
                    $action = '';
482
                }
483
 
484
                $message = $status . $action;
485
            } else {
1441 ariadna 486
                $this->page->requires->js_call_amd('core_badges/actions', 'init');
487
 
1 efrain 488
                $status = get_string('statusmessage_' . $badge->status, 'badges');
489
                if ($badge->is_active()) {
1441 ariadna 490
                    $action = $this->output->single_button(
491
                        new moodle_url('#'),
492
                        get_string('deactivate', 'badges'),
493
                        'POST',
494
                        [
495
                            'class' => 'activatebadge',
496
                            'data-action' => 'disablebadge',
497
                            'data-badgeid' => $badge->id,
498
                            'data-badgename' => $badge->name,
499
                            'data-courseid' => $badge->courseid,
500
                        ],
501
                    );
1 efrain 502
                } else {
1441 ariadna 503
                    $action = $this->output->single_button(
504
                        new moodle_url('#'),
505
                        get_string('activate', 'badges'),
506
                        'POST',
507
                        [
508
                            'class' => 'activatebadge',
509
                            'data-action' => 'enablebadge',
510
                            'data-badgeid' => $badge->id,
511
                            'data-badgename' => $badge->name,
512
                            'data-courseid' => $badge->courseid,
513
                        ]);
1 efrain 514
                }
515
 
516
                $message = $status . $this->output->help_icon('status', 'badges') . $action;
517
 
518
            }
519
 
520
            $style = $badge->is_active() ? 'generalbox statusbox active' : 'generalbox statusbox inactive';
521
            return $this->output->box($message, $style);
522
        }
523
 
524
        return null;
525
    }
526
 
527
    /**
528
     * Returns information about badge criteria in a list form.
529
     *
530
     * @param badge $badge Badge objects
531
     * @param string $short Indicates whether to print full info about this badge
532
     * @return string $output HTML string to output
533
     */
534
    public function print_badge_criteria(badge $badge, $short = '') {
535
        $agg = $badge->get_aggregation_methods();
536
        if (empty($badge->criteria)) {
537
            return get_string('nocriteria', 'badges');
538
        }
539
 
540
        $overalldescr = '';
541
        $overall = $badge->criteria[BADGE_CRITERIA_TYPE_OVERALL];
542
        if (!$short && !empty($overall->description)) {
543
            $overalldescr = $this->output->box(
544
                format_text($overall->description, $overall->descriptionformat, array('context' => $badge->get_context())),
545
                'criteria-description'
546
                );
547
        }
548
 
549
        // Get the condition string.
550
        $condition = '';
551
        if (count($badge->criteria) != 2) {
552
            $condition = get_string('criteria_descr_' . $short . BADGE_CRITERIA_TYPE_OVERALL, 'badges',
553
                                      core_text::strtoupper($agg[$badge->get_aggregation_method()]));
554
        }
555
 
556
        unset($badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]);
557
 
558
        $items = array();
559
        // If only one criterion left, make sure its description goe to the top.
560
        if (count($badge->criteria) == 1) {
561
            $c = reset($badge->criteria);
562
            if (!$short && !empty($c->description)) {
563
                $overalldescr = $this->output->box(
564
                    format_text($c->description, $c->descriptionformat, array('context' => $badge->get_context())),
565
                    'criteria-description'
566
                    );
567
            }
568
            if (count($c->params) == 1) {
569
                $items[] = get_string('criteria_descr_single_' . $short . $c->criteriatype , 'badges') .
570
                           $c->get_details($short);
571
            } else {
572
                $items[] = get_string('criteria_descr_' . $short . $c->criteriatype, 'badges',
573
                        core_text::strtoupper($agg[$badge->get_aggregation_method($c->criteriatype)])) .
574
                        $c->get_details($short);
575
            }
576
        } else {
577
            foreach ($badge->criteria as $type => $c) {
578
                $criteriadescr = '';
579
                if (!$short && !empty($c->description)) {
580
                    $criteriadescr = $this->output->box(
581
                        format_text($c->description, $c->descriptionformat, array('context' => $badge->get_context())),
582
                        'criteria-description'
583
                        );
584
                }
585
                if (count($c->params) == 1) {
586
                    $items[] = get_string('criteria_descr_single_' . $short . $type , 'badges') .
587
                               $c->get_details($short) . $criteriadescr;
588
                } else {
589
                    $items[] = get_string('criteria_descr_' . $short . $type , 'badges',
590
                            core_text::strtoupper($agg[$badge->get_aggregation_method($type)])) .
591
                            $c->get_details($short) .
592
                            $criteriadescr;
593
                }
594
            }
595
        }
596
 
1441 ariadna 597
        $criteriadesc = count($items) > 1 ? html_writer::alist($items, [], 'ul') : reset($items);
598
 
599
        return $overalldescr . $condition . $criteriadesc;
1 efrain 600
    }
601
 
602
    /**
603
     * Prints criteria actions for badge editing.
604
     *
605
     * @param badge $badge
606
     * @return string
607
     */
608
    public function print_criteria_actions(badge $badge) {
609
        $output = '';
610
        if (!$badge->is_active() && !$badge->is_locked()) {
611
            $accepted = $badge->get_accepted_criteria();
612
            $potential = array_diff($accepted, array_keys($badge->criteria));
613
 
614
            if (!empty($potential)) {
615
                foreach ($potential as $p) {
616
                    if ($p != 0) {
617
                        $select[$p] = get_string('criteria_' . $p, 'badges');
618
                    }
619
                }
620
                $output .= $this->output->single_select(
621
                    new moodle_url('/badges/criteria_settings.php', array('badgeid' => $badge->id, 'add' => true)),
622
                    'type',
623
                    $select,
624
                    '',
625
                    array('' => 'choosedots'),
626
                    null,
627
                    array('label' => get_string('addbadgecriteria', 'badges'))
628
                );
629
            } else {
630
                $output .= $this->output->box(get_string('nothingtoadd', 'badges'), 'clearfix');
631
            }
632
        }
633
 
634
        return $output;
635
    }
636
 
637
    /**
638
     * Renders a table with users who have earned the badge.
639
     * Based on stamps collection plugin.
640
     *
641
     * @param \core_badges\output\badge_recipients $recipients
642
     * @return string
643
     *
644
     * @deprecated since Moodle 4.4
645
     * @todo MDL-80455 this will be removed in Moodle 4.8
646
     */
647
    protected function render_badge_recipients(\core_badges\output\badge_recipients $recipients) {
648
        debugging('The method render_badge_recipients() has been deprecated', DEBUG_DEVELOPER);
649
        $paging = new paging_bar($recipients->totalcount, $recipients->page, $recipients->perpage, $this->page->url, 'page');
650
        $htmlpagingbar = $this->render($paging);
651
        $table = new html_table();
652
        $table->attributes['class'] = 'generaltable boxaligncenter boxwidthwide';
653
 
654
        $sortbyfirstname = $this->helper_sortable_heading(get_string('firstname'),
655
                'firstname', $recipients->sort, $recipients->dir);
656
        $sortbylastname = $this->helper_sortable_heading(get_string('lastname'),
657
                'lastname', $recipients->sort, $recipients->dir);
658
        if ($this->helper_fullname_format() == 'lf') {
659
            $sortbyname = $sortbylastname . ' / ' . $sortbyfirstname;
660
        } else {
661
            $sortbyname = $sortbyfirstname . ' / ' . $sortbylastname;
662
        }
663
 
664
        $sortbydate = $this->helper_sortable_heading(get_string('dateawarded', 'badges'),
665
                'dateissued', $recipients->sort, $recipients->dir);
666
 
667
        $table->head = array($sortbyname, $sortbydate, '');
668
 
669
        foreach ($recipients->userids as $holder) {
670
            $fullname = fullname($holder);
671
            $fullname = html_writer::link(
672
                            new moodle_url('/user/profile.php', array('id' => $holder->userid)),
673
                            $fullname
674
                        );
675
            $awarded  = userdate($holder->dateissued);
676
            $badgeurl = html_writer::link(
677
                            new moodle_url('/badges/badge.php', array('hash' => $holder->uniquehash)),
678
                            get_string('viewbadge', 'badges')
679
                        );
680
 
681
            $row = array($fullname, $awarded, $badgeurl);
682
            $table->data[] = $row;
683
        }
684
 
685
        $htmltable = html_writer::table($table);
686
 
687
        return $htmlpagingbar . $htmltable . $htmlpagingbar;
688
    }
689
 
690
    ////////////////////////////////////////////////////////////////////////////
691
    // Helper methods
692
    // Reused from stamps collection plugin
693
    ////////////////////////////////////////////////////////////////////////////
694
 
695
    /**
696
     * Renders a text with icons to sort by the given column
697
     *
698
     * This is intended for table headings.
699
     *
700
     * @param string $text    The heading text
701
     * @param string $sortid  The column id used for sorting
702
     * @param string $sortby  Currently sorted by (column id)
703
     * @param string $sorthow Currently sorted how (ASC|DESC)
704
     *
705
     * @return string
706
     */
707
    protected function helper_sortable_heading($text, $sortid = null, $sortby = null, $sorthow = null) {
708
        $out = html_writer::tag('span', $text, array('class' => 'text'));
709
 
710
        if (!is_null($sortid)) {
711
            if ($sortby !== $sortid || $sorthow !== 'ASC') {
712
                $url = new moodle_url($this->page->url);
713
                $url->params(array('sort' => $sortid, 'dir' => 'ASC'));
714
                $out .= $this->output->action_icon($url,
1441 ariadna 715
                        new pix_icon('t/sort_asc', get_string('sortbyx', 'core', s($text)), null));
1 efrain 716
            }
717
            if ($sortby !== $sortid || $sorthow !== 'DESC') {
718
                $url = new moodle_url($this->page->url);
719
                $url->params(array('sort' => $sortid, 'dir' => 'DESC'));
720
                $out .= $this->output->action_icon($url,
1441 ariadna 721
                        new pix_icon('t/sort_desc', get_string('sortbyxreverse', 'core', s($text)), null));
1 efrain 722
            }
723
        }
724
        return $out;
725
    }
726
    /**
727
     * Tries to guess the fullname format set at the site
728
     *
729
     * @return string fl|lf
730
     */
731
    protected function helper_fullname_format() {
732
        $fake = new stdClass();
733
        $fake->lastname = 'LLLL';
734
        $fake->firstname = 'FFFF';
735
        $fullname = get_string('fullnamedisplay', '', $fake);
736
        if (strpos($fullname, 'LLLL') < strpos($fullname, 'FFFF')) {
737
            return 'lf';
738
        } else {
739
            return 'fl';
740
        }
741
    }
742
    /**
743
     * Renders a search form
744
     *
745
     * @param string $search Search string
746
     * @return string HTML
747
     */
748
    protected function helper_search_form($search) {
749
        global $CFG;
750
        require_once($CFG->libdir . '/formslib.php');
751
 
752
        $mform = new MoodleQuickForm('searchform', 'POST', $this->page->url);
753
 
754
        $mform->addElement('hidden', 'sesskey', sesskey());
755
 
756
        $el[] = $mform->createElement('text', 'search', get_string('search'), array('size' => 20));
757
        $mform->setDefault('search', $search);
758
        $el[] = $mform->createElement('submit', 'submitsearch', get_string('search'));
759
        $el[] = $mform->createElement('submit', 'clearsearch', get_string('clear'));
760
        $mform->addGroup($el, 'searchgroup', get_string('searchname', 'badges'), ' ', false);
761
 
762
        ob_start();
763
        $mform->display();
764
        $out = ob_get_clean();
765
 
766
        return $out;
767
    }
768
 
769
    /**
770
     * Renders a definition list
771
     *
772
     * @param array $items the list of items to define
773
     * @param array
774
     */
775
    protected function definition_list(array $items, array $attributes = array()) {
776
        $output = html_writer::start_tag('dl', $attributes);
777
        foreach ($items as $label => $value) {
778
            $output .= html_writer::tag('dt', $label);
779
            $output .= html_writer::tag('dd', $value);
780
        }
781
        $output .= html_writer::end_tag('dl');
782
        return $output;
783
    }
784
 
785
    /**
786
     * Outputs list en badges.
787
     *
788
     * @param badge $badge Badge object.
789
     * @return string $output content endorsement to output.
790
     */
791
    protected function print_badge_endorsement(badge $badge) {
792
        $output = '';
793
        $endorsement = $badge->get_endorsement();
794
        $dl = array();
795
        $output .= $this->heading(get_string('endorsement', 'badges'), 3);
796
        if (!empty($endorsement)) {
797
            $dl[get_string('issuername', 'badges')] = $endorsement->issuername;
798
            $dl[get_string('issueremail', 'badges')] =
799
                html_writer::tag('a', $endorsement->issueremail, array('href' => 'mailto:' . $endorsement->issueremail));
800
            $dl[get_string('issuerurl', 'badges')] = html_writer::link($endorsement->issuerurl, $endorsement->issuerurl,
801
                array('target' => '_blank'));
802
            $dl[get_string('dateawarded', 'badges')] = userdate($endorsement->dateissued);
803
            $dl[get_string('claimid', 'badges')] = html_writer::link($endorsement->claimid, $endorsement->claimid,
804
            array('target' => '_blank'));
805
            $dl[get_string('claimcomment', 'badges')] = $endorsement->claimcomment;
806
            $output .= $this->definition_list($dl);
807
        } else {
808
            $output .= get_string('noendorsement', 'badges');
809
        }
810
        return $output;
811
    }
812
 
813
    /**
814
     * Print list badges related.
815
     *
816
     * @param badge $badge Badge objects.
817
     * @return string $output List related badges to output.
818
     */
819
    protected function print_badge_related(badge $badge) {
820
        $output = '';
821
        $relatedbadges = $badge->get_related_badges();
822
        $output .= $this->heading(get_string('relatedbages', 'badges'), 3);
823
        if (!empty($relatedbadges)) {
824
            $items = array();
825
            foreach ($relatedbadges as $related) {
826
                $relatedurl = new moodle_url('/badges/overview.php', array('id' => $related->id));
827
                $items[] = html_writer::link($relatedurl->out(), $related->name, array('target' => '_blank'));
828
            }
829
            $output .= html_writer::alist($items, array(), 'ul');
830
        } else {
831
            $output .= get_string('norelated', 'badges');
832
        }
833
        return $output;
834
    }
835
 
836
    /**
837
     * Print list badge alignments.
838
     *
839
     * @param badge $badge Badge objects.
840
     * @return string $output List alignments to output.
841
     */
842
    protected function print_badge_alignments(badge $badge) {
843
        $output = '';
844
        $output .= $this->heading(get_string('alignment', 'badges'), 3);
845
        $alignments = $badge->get_alignments();
846
        if (!empty($alignments)) {
847
            $items = array();
848
            foreach ($alignments as $alignment) {
849
                $urlaligment = new moodle_url('alignment.php',
850
                    array('id' => $badge->id, 'alignmentid' => $alignment->id)
851
                );
852
                $items[] = html_writer::link($urlaligment, $alignment->targetname, array('target' => '_blank'));
853
            }
854
            $output .= html_writer::alist($items, array(), 'ul');
855
        } else {
856
            $output .= get_string('noalignment', 'badges');
857
        }
858
        return $output;
859
    }
860
 
861
    /**
862
     * Renders a table for related badges.
863
     *
864
     * @param \core_badges\output\badge_related $related list related badges.
865
     * @return string list related badges to output.
866
     */
867
    protected function render_badge_related(\core_badges\output\badge_related $related) {
868
        $currentbadge = new badge($related->currentbadgeid);
869
        $languages = get_string_manager()->get_list_of_languages();
870
        $paging = new paging_bar($related->totalcount, $related->page, $related->perpage, $this->page->url, 'page');
871
        $htmlpagingbar = $this->render($paging);
872
        $table = new html_table();
873
        $table->attributes['class'] = 'generaltable boxaligncenter boxwidthwide';
874
        $table->head = array(
875
            get_string('name'),
876
            get_string('version', 'badges'),
877
            get_string('language', 'badges'),
878
            get_string('type', 'badges')
879
        );
880
        if (!$currentbadge->is_active() && !$currentbadge->is_locked()) {
881
            array_push($table->head, '');
882
        }
883
 
884
        foreach ($related->badges as $badge) {
885
            $badgeobject = new badge($badge->id);
886
            $style = array('title' => $badgeobject->name);
887
            if (!$badgeobject->is_active()) {
888
                $style['class'] = 'dimmed';
889
            }
890
            $context = ($badgeobject->type == BADGE_TYPE_SITE) ?
891
                context_system::instance() : context_course::instance($badgeobject->courseid);
892
            $forlink = print_badge_image($badgeobject, $context) . ' ' .
893
                html_writer::start_tag('span') . $badgeobject->name . html_writer::end_tag('span');
894
            $name = html_writer::link(new moodle_url('/badges/overview.php', array('id' => $badgeobject->id)), $forlink, $style);
895
 
896
            $row = array(
897
                $name,
898
                $badge->version,
899
                $badge->language ? $languages[$badge->language] : '',
900
                $badge->type == BADGE_TYPE_COURSE ? get_string('badgesview', 'badges') : get_string('sitebadges', 'badges')
901
            );
902
            if (!$currentbadge->is_active() && !$currentbadge->is_locked()) {
903
                $action = $this->output->action_icon(
904
                    new moodle_url('/badges/related_action.php', [
905
                        'badgeid' => $related->currentbadgeid,
906
                        'relatedid' => $badge->id,
907
                        'sesskey' => sesskey(),
908
                        'action' => 'remove'
909
                    ]),
910
                    new pix_icon('t/delete', get_string('delete')));
911
                $actions = html_writer::tag('div', $action, array('class' => 'badge-actions'));
912
                array_push($row, $actions);
913
            }
914
            $table->data[] = $row;
915
        }
916
        $htmltable = html_writer::table($table);
917
 
918
        return $htmlpagingbar . $htmltable . $htmlpagingbar;
919
    }
920
 
921
    /**
922
     * Renders a table with alignment.
923
     *
924
     * @param core_badges\output\badge_alignments $alignments List alignments.
925
     * @return string List alignment to output.
926
     */
927
    protected function render_badge_alignments(\core_badges\output\badge_alignments $alignments) {
928
        $currentbadge = new badge($alignments->currentbadgeid);
929
        $paging = new paging_bar($alignments->totalcount, $alignments->page, $alignments->perpage, $this->page->url, 'page');
930
        $htmlpagingbar = $this->render($paging);
931
        $table = new html_table();
932
        $table->attributes['class'] = 'generaltable boxaligncenter boxwidthwide';
933
        $table->head = array('Name', 'URL', '');
934
 
935
        foreach ($alignments->alignments as $item) {
936
            $urlaligment = new moodle_url('alignment.php',
937
                array(
938
                    'id' => $currentbadge->id,
939
                    'alignmentid' => $item->id,
940
                )
941
            );
942
            $row = array(
943
                html_writer::link($urlaligment, $item->targetname),
944
                html_writer::link($item->targeturl, $item->targeturl, array('target' => '_blank'))
945
            );
946
            if (!$currentbadge->is_active() && !$currentbadge->is_locked()) {
947
                $delete = $this->output->action_icon(
948
                    new moodle_url('/badges/alignment_action.php', [
949
                        'id' => $currentbadge->id,
950
                        'alignmentid' => $item->id,
951
                        'sesskey' => sesskey(),
952
                        'action' => 'remove'
953
                    ]),
954
                    new pix_icon('t/delete', get_string('delete'))
955
                );
956
                $edit = $this->output->action_icon(
957
                    new moodle_url('alignment.php',
958
                        array(
959
                            'id' => $currentbadge->id,
960
                            'alignmentid' => $item->id,
961
                            'action' => 'edit'
962
                        )
963
                    ), new pix_icon('t/edit', get_string('edit')));
964
                $actions = html_writer::tag('div', $edit . $delete, array('class' => 'badge-actions'));
965
                array_push($row, $actions);
966
            }
967
            $table->data[] = $row;
968
        }
969
        $htmltable = html_writer::table($table);
970
 
971
        return $htmlpagingbar . $htmltable . $htmlpagingbar;
972
    }
973
 
974
    /**
975
     * Defer to template.
976
     *
977
     * @param \core_badges\output\external_backpacks_page $page
978
     * @return bool|string
979
     */
980
    public function render_external_backpacks_page(\core_badges\output\external_backpacks_page $page) {
981
        $data = $page->export_for_template($this);
982
        return parent::render_from_template('core_badges/external_backpacks_page', $data);
983
    }
984
 
985
    /**
986
     * Get the result of a backpack validation with its settings. It returns:
987
     * - A informative message if the backpack version is different from OBv2.
988
     * - A warning with the error if it's not possible to connect to this backpack.
989
     * - A successful message if the connection has worked.
990
     *
991
     * @param  int    $backpackid The backpack identifier.
992
     * @return string A message with the validation result.
993
     */
994
    public function render_test_backpack_result(int $backpackid): string {
995
        // Get the backpack.
996
        $backpack = badges_get_site_backpack($backpackid);
997
 
998
        // Add the header to the result.
999
        $result = $this->heading(get_string('testbackpack', 'badges', $backpack->backpackweburl));
1000
 
1001
        if ($backpack->apiversion != OPEN_BADGES_V2) {
1002
            // Only OBv2 supports this validation.
1003
            $result .= get_string('backpackconnectionnottested', 'badges');
1004
        } else {
1005
            $message = badges_verify_backpack($backpackid);
1006
            if (empty($message)) {
1007
                $result .= get_string('backpackconnectionok', 'badges');
1008
            } else {
1009
                $result .= $message;
1010
            }
1011
        }
1012
 
1013
        return $result;
1014
    }
1015
 
1016
    /**
1017
     * Render the tertiary navigation for the page.
1018
     *
1019
     * @param \core_badges\output\base_action_bar $actionbar
1020
     * @return bool|string
1021
     */
1022
    public function render_tertiary_navigation(\core_badges\output\base_action_bar $actionbar) {
1023
        return $this->render_from_template($actionbar->get_template(), $actionbar->export_for_template($this));
1024
    }
1025
}