Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 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
 
17
namespace core_courseformat\output\local\content\cm;
18
 
19
use cm_info;
20
use core\context\course as context_course;
21
use core\context\module as context_module;
22
use core\output\action_menu;
23
use core\output\action_menu\link;
24
use core\output\action_menu\link_secondary;
25
use core\output\renderer_base;
26
use core_courseformat\base as course_format;
27
use core_courseformat\output\local\content\basecontrolmenu;
28
use core\output\pix_icon;
29
use core\url;
30
use section_info;
31
 
32
/**
33
 * Base class to render delegated section controls.
34
 *
35
 * @package   core_courseformat
36
 * @copyright 2024 Amaia Anabitarte <amaia@moodle.com>
37
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38
 */
39
class delegatedcontrolmenu extends basecontrolmenu {
40
    /** @var context_module|null modcontext the module context if any */
41
    protected ?context_module $modcontext = null;
42
 
43
    /** @var bool $canmanageactivities Optimization to know if the user can manage activities */
44
    protected bool $canmanageactivities;
45
 
46
    /**
47
     * Constructor.
48
     *
49
     * @param course_format $format the course format
50
     * @param section_info $section the section info
51
     * @param cm_info $mod the module info
52
     */
53
    public function __construct(course_format $format, section_info $section, cm_info $mod) {
54
        parent::__construct($format, $section, $mod, $section->id);
55
 
56
        $this->modcontext = context_module::instance($mod->id);
57
        $this->canmanageactivities = has_capability('moodle/course:manageactivities', $this->modcontext);
58
    }
59
 
60
    /**
61
     * Generate the default delegated section action menu.
62
     *
63
     * This method is public in case some block needs to modify the menu before output it.
64
     *
65
     * @param renderer_base $output typically, the renderer that's calling this function
66
     * @return action_menu|null the action menu
67
     */
68
    public function get_default_action_menu(renderer_base $output): ?action_menu {
69
        $controls = $this->delegated_control_items();
70
        return $this->format_controls($controls);
71
    }
72
 
73
    /**
74
     * Generate the edit control items of a section.
75
     *
76
     * @return array of edit control items
77
     */
78
    public function delegated_control_items() {
79
        // TODO remove this if as part of MDL-83530.
80
        if (!$this->format->supports_components()) {
81
            return $this->delegated_control_items_legacy();
82
        }
83
 
84
        $controls = [];
85
        $controls['view'] = $this->get_section_view_item();
86
        $controls['edit'] = $this->get_section_edit_item();
87
        $controls['visibility'] = $this->get_section_visibility_item();
88
        $controls['movesection'] = $this->get_cm_move_item();
89
        $controls['permalink'] = $this->get_section_permalink_item();
90
        $controls['delete'] = $this->get_cm_delete_item();
91
 
92
        return $controls;
93
    }
94
 
95
    /**
96
     * Retrieves the view item for the section control menu.
97
     *
98
     * @return link|null The menu item if applicable, otherwise null.
99
     */
100
    protected function get_section_view_item(): ?link {
101
        // Only show the view link if we are not already in the section view page.
102
        if ($this->format->get_sectionid() == $this->section->id) {
103
            return null;
104
        }
105
        return new link_secondary(
106
                url: new url('/course/section.php', ['id' => $this->section->id]),
107
                icon: new pix_icon('i/viewsection', ''),
108
                text: get_string('view'),
109
                attributes: ['class' => 'view'],
110
        );
111
    }
112
 
113
    /**
114
     * Retrieves the edit item for the section control menu.
115
     *
116
     * @return link|null The menu item if applicable, otherwise null.
117
     */
118
    protected function get_section_edit_item(): ?link {
119
        if (!has_capability('moodle/course:update', $this->coursecontext)) {
120
            return null;
121
        }
122
 
123
        $url = new url(
124
            '/course/editsection.php',
125
            [
126
                'id' => $this->section->id,
127
                'sr' => $this->section->sectionnum,
128
            ]
129
        );
130
 
131
        return new link_secondary(
132
                url: $url,
133
                icon: new pix_icon('i/settings', ''),
134
                text: get_string('editsection'),
135
                attributes: ['class' => 'edit'],
136
        );
137
    }
138
 
139
 
140
 
141
    /**
142
     * Generates the move item for a course module.
143
     *
144
     * @return link|null The menu item if applicable, otherwise null.
145
     */
146
    protected function get_cm_move_item(): ?link {
147
        // Only show the move link if we are not already in the section view page.
148
        if (
149
            !$this->canmanageactivities
150
            || $this->format->get_sectionid() == $this->section->id
151
        ) {
152
            return null;
153
        }
154
 
155
        // The move action uses visual elements on the course page.
156
        $url = new url('/course/mod.php', ['sesskey' => sesskey()]);
157
 
158
        $sectionnumreturn = $this->format->get_sectionnum();
159
        if ($sectionnumreturn !== null) {
160
            $url->param('sr', $sectionnumreturn);
161
        }
162
 
163
        return new link_secondary(
164
            url: $url,
165
            icon: new pix_icon('i/dragdrop', ''),
166
            text: get_string('move'),
167
            attributes: [
168
                // This tool requires ajax and will appear only when the frontend state is ready.
169
                'class' => 'editing_movecm waitstate',
170
                'data-action' => 'moveCm',
171
                'data-id' => $this->mod->id,
172
            ],
173
        );
174
    }
175
 
176
    /**
177
     * Retrieves the get_section_visibility_menu_item item for the section control menu.
178
     *
179
     * @return link|null The menu item if applicable, otherwise null.
180
     */
181
    protected function get_section_visibility_item(): ?link {
182
        // To avoid exponential complexity, we only allow subsection visibility actions
183
        // when the parent section is visible.
184
        $parentsection = $this->mod->get_section_info();
185
        if (
186
            $this->section->sectionnum == 0
187
            || !$parentsection->visible
188
            || !has_capability('moodle/course:sectionvisibility', $this->coursecontext)
189
            || !has_capability('moodle/course:activityvisibility', $this->modcontext)
190
        ) {
191
            return null;
192
        }
193
 
194
        $sectionreturn = $this->format->get_sectionnum();
195
 
196
        $strhide = get_string('hide');
197
        $strshow = get_string('show');
198
 
199
        if ($this->section->visible) {
200
            $action = 'section_hide';
201
            $icon = 'i/show';
202
            $name = $strhide;
203
            $attributes = [
204
                'class' => 'icon editing_showhide',
205
                'data-sectionreturn' => $sectionreturn,
206
                'data-action' => 'sectionHide',
207
                'data-id' => $this->section->id,
208
                'data-icon' => 'i/show',
209
                'data-swapname' => $strshow,
210
                'data-swapicon' => 'i/hide',
211
            ];
212
        } else {
213
            $action = 'section_show';
214
            $icon = 'i/hide';
215
            $name = $strshow;
216
            $attributes = [
217
                'class' => 'editing_showhide',
218
                'data-sectionreturn' => $sectionreturn,
219
                'data-action' => 'sectionShow',
220
                'data-id' => $this->section->id,
221
                'data-icon' => 'i/hide',
222
                'data-swapname' => $strhide,
223
                'data-swapicon' => 'i/show',
224
            ];
225
        }
226
 
227
        $url = $this->format->get_update_url(
228
            action: $action,
229
            ids: [$this->section->id],
230
            returnurl: $this->baseurl,
231
        );
232
 
233
        return new link_secondary(
234
            url: $url,
235
            icon: new pix_icon($icon, ''),
236
            text: $name,
237
            attributes: $attributes,
238
        );
239
    }
240
 
241
    /**
242
     * Retrieves the permalink item for the section control menu.
243
     *
244
     * @return link|null The menu item if applicable, otherwise null.
245
     */
246
    protected function get_section_permalink_item(): ?link {
247
        if (!has_any_capability(
248
                [
249
                    'moodle/course:movesections',
250
                    'moodle/course:update',
251
                    'moodle/course:sectionvisibility',
252
                ],
253
                $this->coursecontext
254
            )
255
        ) {
256
            return null;
257
        }
258
 
259
        $url = new url(
260
            '/course/section.php',
261
            ['id' => $this->section->id]
262
        );
263
        return new link_secondary(
264
            url: $url,
265
            icon: new pix_icon('i/link', ''),
266
            text: get_string('sectionlink', 'course'),
267
            attributes: [
268
                'class' => 'permalink',
269
                'data-action' => 'permalink',
270
            ],
271
        );
272
    }
273
 
274
    /**
275
     * Generates the delete item for a course module.
276
     *
277
     * @return link|null The menu item if applicable, otherwise null.
278
     */
279
    protected function get_cm_delete_item(): ?link {
280
        if (!$this->canmanageactivities) {
281
            return null;
282
        }
283
 
284
        $url = $this->format->get_update_url(
285
            action: 'cm_delete',
286
            ids: [$this->mod->id],
287
            returnurl: $this->baseurl,
288
        );
289
 
290
        return new link_secondary(
291
            url: $url,
292
            icon: new pix_icon('t/delete', ''),
293
            text: get_string('delete'),
294
            attributes: [
295
                'class' => 'editing_delete text-danger',
296
                'data-action' => 'cmDelete',
297
                'data-sectionreturn' => $this->format->get_sectionnum(),
298
                'data-id' => $this->mod->id,
299
            ],
300
        );
301
    }
302
 
303
    /**
304
     * Generate the edit control items of a section.
305
     *
306
     * It is not clear this kind of controls are still available in 4.0 so, for now, this
307
     * method is almost a clone of the previous section_control_items from the course/renderer.php.
308
     *
309
     * @deprecated since Moodle 5.0
310
     * @todo Remove this method in Moodle 6.0 (MDL-83530).
311
     * @return array of edit control items
312
     */
313
    #[\core\attribute\deprecated(
314
        replacement: 'delegated_control_items',
315
        since: '5.0',
316
        mdl: 'MDL-83527',
317
    )]
318
    protected function delegated_control_items_legacy(): array {
319
        global $USER;
320
        \core\deprecation::emit_deprecation([self::class, __FUNCTION__]);
321
 
322
        $format = $this->format;
323
        $section = $this->section;
324
        $cm = $this->mod;
325
        $course = $format->get_course();
326
        $sectionreturn = !is_null($format->get_sectionid()) ? $format->get_sectionnum() : null;
327
        $user = $USER;
328
 
329
        $usecomponents = $format->supports_components();
330
        $coursecontext = context_course::instance($course->id);
331
 
332
        $baseurl = course_get_url($course, $sectionreturn);
333
        $baseurl->param('sesskey', sesskey());
334
 
335
        $cmbaseurl = new url('/course/mod.php');
336
        $cmbaseurl->param('sesskey', sesskey());
337
 
338
        $hasmanageactivities = has_capability('moodle/course:manageactivities', $coursecontext);
339
        $isheadersection = $format->get_sectionid() == $section->id;
340
 
341
        $controls = [];
342
 
343
        // Only show the view link if we are not already in the section view page.
344
        if (!$isheadersection) {
345
            $controls['view'] = [
346
                'url'   => new url('/course/section.php', ['id' => $section->id]),
347
                'icon' => 'i/viewsection',
348
                'name' => get_string('view'),
349
                'pixattr' => ['class' => ''],
350
                'attr' => ['class' => 'view'],
351
            ];
352
        }
353
 
354
        if (has_capability('moodle/course:update', $coursecontext, $user)) {
355
            $params = ['id' => $section->id];
356
            $params['sr'] = $section->section;
357
            if (get_string_manager()->string_exists('editsection', 'format_'.$format->get_format())) {
358
                $streditsection = get_string('editsection', 'format_'.$format->get_format());
359
            } else {
360
                $streditsection = get_string('editsection');
361
            }
362
 
363
            // Edit settings goes to section settings form.
364
            $controls['edit'] = [
365
                'url'   => new url('/course/editsection.php', $params),
366
                'icon' => 'i/settings',
367
                'name' => $streditsection,
368
                'pixattr' => ['class' => ''],
369
                'attr' => ['class' => 'edit'],
370
            ];
371
        }
372
 
373
        // Hide/Show uses module functionality.
374
        // Hide/Show options will be available for subsections inside visible sections only.
375
        $parentsection = $cm->get_section_info();
376
        $availablevisibility = has_capability('moodle/course:sectionvisibility', $coursecontext, $user) && $parentsection->visible;
377
        if ($availablevisibility) {
378
            $url = clone($baseurl);
379
            if (!is_null($sectionreturn)) {
380
                $url->param('sr', $format->get_sectionid());
381
            }
382
            $strhidefromothers = get_string('hidefromothers', 'format_' . $course->format);
383
            $strshowfromothers = get_string('showfromothers', 'format_' . $course->format);
384
            if ($section->visible) { // Show the hide/show eye.
385
                $url->param('hide', $section->section);
386
                $controls['visiblity'] = [
387
                    'url' => $url,
388
                    'icon' => 'i/show',
389
                    'name' => $strhidefromothers,
390
                    'pixattr' => ['class' => ''],
391
                    'attr' => [
392
                        'class' => 'editing_showhide',
393
                        'data-sectionreturn' => $sectionreturn,
394
                        'data-action' => ($usecomponents) ? 'sectionHide' : 'hide',
395
                        'data-id' => $section->id,
396
                        'data-swapname' => $strshowfromothers,
397
                        'data-swapicon' => 'i/show',
398
                    ],
399
                ];
400
            } else {
401
                $url->param('show', $section->section);
402
                $controls['visiblity'] = [
403
                    'url' => $url,
404
                    'icon' => 'i/hide',
405
                    'name' => $strshowfromothers,
406
                    'pixattr' => ['class' => ''],
407
                    'attr' => [
408
                        'class' => 'editing_showhide',
409
                        'data-sectionreturn' => $sectionreturn,
410
                        'data-action' => ($usecomponents) ? 'sectionShow' : 'show',
411
                        'data-id' => $section->id,
412
                        'data-swapname' => $strhidefromothers,
413
                        'data-swapicon' => 'i/hide',
414
                    ],
415
                ];
416
            }
417
        }
418
 
419
        // Only show the move link if we are not already in the section view page.
420
        // Move (only for component compatible formats).
421
        if (!$isheadersection && $hasmanageactivities && $usecomponents) {
422
            $controls['move'] = [
423
                'url'   => new url('/course/mod.php', ['copy' => $cm->id]),
424
                'icon' => 'i/dragdrop',
425
                'name' => get_string('move'),
426
                'pixattr' => ['class' => ''],
427
                'attr' => [
428
                    'class' => 'editing_movecm ',
429
                    'data-action' => 'moveCm',
430
                    'data-id' => $cm->id,
431
                ],
432
            ];
433
        }
434
 
435
        // Delete deletes the module.
436
        if ($hasmanageactivities) {
437
            $url = clone($cmbaseurl);
438
            $url->param('delete', $cm->id);
439
            $url->param('sr', $cm->sectionnum);
440
 
441
            $controls['delete'] = [
442
                'url' => $url,
443
                'icon' => 't/delete',
444
                'name' => get_string('delete'),
445
                'pixattr' => ['class' => ''],
446
                'attr' => [
447
                    'class' => 'editing_delete text-danger',
448
                    'data-action' => ($usecomponents) ? 'cmDelete' : 'delete',
449
                    'data-sectionreturn' => $sectionreturn,
450
                    'data-id' => $cm->id,
451
                ],
452
            ];
453
        }
454
 
455
        // Add section page permalink.
456
        if (
457
            has_any_capability([
458
                'moodle/course:movesections',
459
                'moodle/course:update',
460
                'moodle/course:sectionvisibility',
461
            ], $coursecontext)
462
        ) {
463
            $sectionlink = new url(
464
                '/course/section.php',
465
                ['id' => $section->id]
466
            );
467
            $controls['permalink'] = [
468
                'url' => $sectionlink,
469
                'icon' => 'i/link',
470
                'name' => get_string('sectionlink', 'course'),
471
                'pixattr' => ['class' => ''],
472
                'attr' => [
473
                    'data-action' => 'permalink',
474
                ],
475
            ];
476
        }
477
 
478
        return $controls;
479
    }
480
}