Proyectos de Subversion Moodle

Rev

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

Rev Autor Línea Nro. Línea
4 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
/**
18
 * Point of View block configuration form definition.
19
 *
20
 * @package    block_point_view
21
 * @copyright  2020 Quentin Fombaron, 2021 Astor Bizard
22
 * @author     Quentin Fombaron <q.fombaron@outlook.fr>
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
defined('MOODLE_INTERNAL') || die;
27
 
28
require_once(__DIR__ . '/locallib.php');
29
 
30
/**
31
 * block_point_view_edit_form Class
32
 *
33
 *
34
 * @package    block_point_view
35
 * @copyright  2020 Quentin Fombaron
36
 * @author     Quentin Fombaron <q.fombaron@outlook.fr>
37
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38
 */
39
class block_point_view_edit_form extends block_edit_form {
40
 
41
    /**
6 ariadna 42
     * @var boolean Whether javascript should be added on display (needed since Moodle 4.2 and dynamic forms).
43
     */
44
    protected $addjs = false;
45
 
46
    /**
4 ariadna 47
     * Configuration page
48
     *
49
     * @param MoodleQuickForm $mform
50
     */
51
    protected function specific_definition($mform) {
52
 
53
        global $COURSE, $OUTPUT, $DB;
54
 
55
        if (get_config('block_point_view', 'enable_point_views_admin')) {
56
 
57
            // Add block_point_view class to form element for styling,
58
            // as it is not done for the body element on block edition page.
59
            $mform->updateAttributes([ 'class' => $mform->getAttribute('class') . ' block_point_view' ]);
60
 
61
            $mform->addElement('header', 'general_header', get_string('blocksettings', 'block'));
62
 
63
            // Block content.
64
 
65
            $editoroptions = [ 'maxfiles' => EDITOR_UNLIMITED_FILES, 'noclean' => true, 'context' => $this->block->context ];
66
            $mform->addElement(
67
                'editor',
68
                'config_text',
69
                get_string('contentinputlabel', 'block_point_view'),
70
                null,
71
                $editoroptions
72
            );
73
            $mform->setType('config_text', PARAM_RAW);
74
 
75
            $mform->addHelpButton('config_text', 'contentinputlabel', 'block_point_view');
76
 
77
            // Reaction activation.
78
            $mform->addElement('selectyesno', 'config_enable_point_views',
79
                    get_string('enablepoint_views', 'block_point_view'));
80
 
81
            $this->add_checkbox_with_help($mform, 'config_enable_point_views_new_modules', 'enableforfuturemodules', 1);
82
            $mform->disabledIf('config_enable_point_views_new_modules', 'config_enable_point_views', 'eq', 0);
83
 
84
            $this->add_checkbox_with_help($mform, 'config_show_other_users_reactions', 'showotherreactions', 1);
85
            $mform->disabledIf('config_show_other_users_reactions', 'config_enable_point_views', 'eq', 0);
86
 
87
            $this->add_checkbox_with_help($mform, 'config_highlight_activity_rows', 'highlightactivityrows', 1);
88
            $mform->disabledIf('config_highlight_activity_rows', 'config_enable_point_views', 'eq', 0);
89
 
90
            // Difficulty tracks activation.
91
            $mform->addElement('selectyesno', 'config_enable_difficultytracks',
92
                    get_string('enabledifficulties', 'block_point_view'));
93
 
94
            // Reactions and difficulty tracks configuration by activity.
95
 
96
            $mform->addElement('header', 'activities_header', get_string('header_activities', 'block_point_view'));
97
 
98
            $modinfo = get_fast_modinfo($COURSE->id, -1);
99
            $cms = $modinfo->cms;
100
            $modtypes = array_keys($modinfo->instances);
101
 
102
            if (empty($cms)) {
103
                $this->add_warning_message($mform, get_string('noactivity', 'block_point_view'));
104
            }
105
 
106
            // Enable/Disable by activity module type.
107
            foreach ($modtypes as $type) {
108
                $this->add_enable_disable_buttons($mform, '',
109
                        $type,
110
                        'enable_type', 'disable_type',
111
                        get_string('modulenameplural', $type),
112
                        'enable_disable_type',
113
                        'data-type="' . $type . '"',
114
                        [ 'class' => 'reactions' ]);
115
            }
116
 
117
            $oldsection = '';
118
            $sectionid = 0;
119
            // Enable/Disable by activity or section.
120
            foreach ($cms as $cm) {
121
 
122
                if ($cm->sectionnum != $oldsection) {
123
 
124
                    $sectionid++;
125
                    $sectionname = get_section_name($COURSE, $cm->sectionnum);
126
 
127
                    $this->add_enable_disable_buttons($mform, '<h4>' . $sectionname . '</h4>',
128
                            'sec' . $sectionid,
129
                            'enableall', 'disableall',
130
                            $sectionname,
131
                            'enable_disable_section',
132
                            'data-section="sec' . $sectionid . '"',
133
                            [ 'class' => 'pt-3' ]);
134
 
135
                    $oldsection = $cm->sectionnum;
136
                }
137
 
6 ariadna 138
                $purposeclass = '';
139
                if (defined('FEATURE_MOD_PURPOSE')) {
140
                    $purposeclass = ' ' . plugin_supports('mod', $cm->modname, FEATURE_MOD_PURPOSE, MOD_PURPOSE_OTHER);
141
                }
4 ariadna 142
                $icon = $OUTPUT->pix_icon('icon', $cm->get_module_type_name(), $cm->modname,
143
                        [ 'class' => 'iconlarge activityicon' ]);
6 ariadna 144
                $icon = html_writer::span($icon, 'activityiconcontainer' . $purposeclass);
145
                $name = html_writer::span($cm->get_formatted_name(), 'activity-name');
4 ariadna 146
 
6 ariadna 147
                $this->add_activity_config($mform, $cm->id, $sectionid, $cm->modname, $icon . $name);
4 ariadna 148
            }
149
 
150
            // Emoji configuration.
151
 
152
            $this->add_emoji_selection($mform);
153
 
154
            // Reaction reinitialisation.
155
            $mform->addElement('header', 'reset_header', get_string('resetreactionsheader', 'block_point_view'));
156
 
157
            $buttons = $this->get_action_button('cleanup_reactions', 'warning',
158
                    'cleanupcoursereactions', format_string($COURSE->fullname));
159
            $buttons .= $OUTPUT->help_icon('cleanupreactions', 'block_point_view');
160
            $buttons .= $this->get_action_button('reset_reactions', 'danger',
161
                    'resetcoursereactions', format_string($COURSE->fullname));
162
            $buttons .= $OUTPUT->help_icon('resetreactions', 'block_point_view');
163
 
164
            $mform->addElement('html', html_writer::div($buttons, 'mt-2 mb-3'));
165
 
166
            $cms = get_fast_modinfo($COURSE->id, -1)->cms;
167
            $cmshtml = '';
168
            if (count($cms)) {
169
                $sectionid = -1;
170
                foreach ($cms as $cm) {
171
                    if (!$DB->record_exists('block_point_view', [ 'courseid' => $COURSE->id, 'cmid' => $cm->id ])) {
172
                        continue;
173
                    }
174
                    if ($cm->section != $sectionid) {
175
                        if ($sectionid != -1) {
176
                            $cmshtml .= '</div>'; // Close section.
177
                        }
178
                        $sectionid = $cm->section;
179
                        // Open section.
180
                        $cmshtml .= '<div class="pl-3"><h3>' . get_section_name($COURSE->id, $cm->sectionnum) . '</h3>';
181
                    }
182
                    $icon = $OUTPUT->image_icon('icon', $cm->modfullname, $cm->modname, [ 'class' => 'activityicon' ]);
183
                    $resetbutton = $this->get_action_button('', 'danger', 'resetreactions', null,
184
                            'data-cmid="' . $cm->id    . '" data-role="reset_module"');
185
                    $cmshtml .= html_writer::div($icon . $cm->get_formatted_name() . $resetbutton, 'mb-1');
186
                }
187
            }
188
            if (empty($cmshtml)) {
189
                $cmshtml = get_string('noreactionsyet', 'block_point_view');
190
            } else {
191
                $cmshtml .= '</div>'; // Close section.
192
            }
193
            $mform->addElement('html', html_writer::div(
194
                    html_writer::tag('legend', get_string('resetreactionsbymodule', 'block_point_view')) . $cmshtml, 'ml-3 mb-2'));
195
 
6 ariadna 196
            $this->addjs = true;
197
        } else {
198
            $this->add_warning_message($mform, get_string('blockdisabled', 'block_point_view'));
199
        }
200
    }
201
 
202
    /**
203
     * {@inheritDoc}
204
     * @see moodleform::display()
205
     */
206
    public function display() {
207
        parent::display();
208
        // Javascript needs to be added from display() function, since Moodle 4.2 and dynamic forms.
209
        if ($this->addjs) {
4 ariadna 210
            // Call javascript from a static function in locallib, because Moodle linter won't let us call global $PAGE from here
211
            // (and $this->page actually contains the course page, not the edit form page).
212
            block_point_view_require_edit_form_javascript($this->block->context->id);
213
        }
214
    }
215
 
216
    /**
217
     * Helper function to add an advcheckbox element with a help button to a form.
218
     *
219
     * @param MoodleQuickForm $mform
220
     * @param string $name Checkbox element name.
221
     * @param string $str String identifier for label and help button (in block_point_view component).
222
     * @param mixed $default Default value for the checkbox.
223
     */
224
    protected function add_checkbox_with_help(&$mform, $name, $str, $default = 0) {
225
        $mform->addElement('advcheckbox', $name, get_string($str, 'block_point_view'));
226
        $mform->addHelpButton($name, $str, 'block_point_view');
227
        $mform->setDefault($name, $default);
228
    }
229
 
230
    /**
231
     * Helper function to add two buttons (enable/disable) to a form.
232
     *
233
     * @param MoodleQuickForm $mform
234
     * @param string $grouplabel The label to put before the two buttons.
235
     * @param string $name The name of the buttons (their "id" will be "enableall<$name>" and "disableall<$name>").
236
     * @param string $enablestr String identifier for enable button label (in block_point_view component).
237
     * @param string $disablestr String identifier for disable button label (in block_point_view component).
238
     * @param string $a Additional data to pass to get_string for enable and disable button labels.
239
     * @param string $helpstr String identifier for help button (in block_point_view component).
240
     * @param string $dataattr Data attributes for both buttons.
241
     * @param array $attributes Attributes to be added to the form element containing both buttons.
242
     */
243
    protected function add_enable_disable_buttons(&$mform, $grouplabel, $name,
244
            $enablestr, $disablestr, $a, $helpstr, $dataattr = '', $attributes = []) {
245
 
246
        global $OUTPUT;
247
 
248
        $templatecontext = new stdClass();
249
        $templatecontext->helpbutton = $OUTPUT->help_icon($helpstr, 'block_point_view');
250
        $templatecontext->enablename = 'enableall' . $name;
251
        $templatecontext->enablelabel = get_string($enablestr, 'block_point_view', $a);
252
        $templatecontext->disablename = 'disableall' . $name;
253
        $templatecontext->disablelabel = get_string($disablestr, 'block_point_view', $a);
254
        $templatecontext->dataattr = $dataattr;
255
        $element = &$mform->addElement('static', '', $grouplabel,
256
                $OUTPUT->render_from_template('block_point_view/enabledisable', $templatecontext));
257
        if (!empty($attributes)) {
258
            $element->setAttributes($attributes);
259
        }
260
    }
261
 
262
    /**
263
     * Helper function to create settings for one course module in the form (reactions checkbox and difficulty track select).
264
     *
265
     * @param MoodleQuickForm $mform
266
     * @param int $cmid Course module id.
267
     * @param int $sectionid Section id this module belongs to.
268
     * @param string $type Course module type name.
269
     * @param string $label Label for form elements (likely, course module name and icon).
270
     */
271
    protected function add_activity_config(&$mform, $cmid, $sectionid, $type, $label) {
272
        $group = [];
273
 
274
        // Checkbox for reactions.
275
        $group[] =& $mform->createElement( 'advcheckbox', 'config_moduleselectm' . $cmid,
276
                get_string('reactions', 'block_point_view'), null,
277
                [
278
                        'class' => 'reactions enablemodulereactions cbsec' . $sectionid . ' cb' . $type,
279
                        'data-section' => 'sec' . $sectionid,
280
                        'data-type' => $type,
281
                ],
282
                [ 0, $cmid ]
283
        );
284
 
285
        // Difficulty track.
286
        $group[] =& $mform->createElement( 'html',
287
                '<span id="track_' . $cmid . '" class="block_point_view track selecttrack difficultytracks"></span>' );
288
 
289
        // Difficulty track select.
290
        $group[] =& $mform->createElement( 'select', 'config_difficulty_' . $cmid, '',
291
                [
292
                        get_string('nonetrack', 'block_point_view'),
293
                        get_string('greentrack', 'block_point_view'),
294
                        get_string('bluetrack', 'block_point_view'),
295
                        get_string('redtrack', 'block_point_view'),
296
                        get_string('blacktrack', 'block_point_view'),
297
                ],
298
                [ 'class' => 'difficultytracks moduletrackselect', 'data-id' => $cmid ]
299
        );
300
 
301
        $mform->addGroup( $group, 'config_activity_' . $cmid, $label, '', false );
302
 
303
    }
304
 
305
    /**
306
     * Helper function to add a warning to a form.
307
     * @param MoodleQuickForm $mform
308
     * @param string $message
309
     */
310
    protected function add_warning_message(&$mform, $message) {
311
        $warning = html_writer::tag( 'div', $message, ['class' => 'warning'] );
312
        $mform->addElement('static', '', '', $warning);
313
    }
314
 
315
    /**
316
     * Add all form controls for emoji selection to the form.
317
     * @param MoodleQuickForm $mform
318
     */
319
    protected function add_emoji_selection(&$mform) {
320
        global $CFG;
321
 
322
        $mform->addElement('header', 'images_header', get_string('header_images', 'block_point_view'));
323
 
324
        $pixfiles = [ 'easy', 'better', 'hard' ];
325
 
326
        $adminpixenabled = get_config('block_point_view', 'enable_pix_admin');
327
        $custompixexist = false;
328
 
329
        // List existing pix. Three options:
330
        // - default pix (in blocks/point_view/pix),
331
        // - admin pix (in block administration settings),
332
        // - custom pix (in block configuration).
333
        $pix = [ 'default' => [], 'admin' => [], 'custom' => [] ];
334
        foreach ($pixfiles as $file) {
335
            $defaultsrc = $CFG->wwwroot . '/blocks/point_view/pix/' . $file . '.png';
336
            $pix['default'][$file] = $defaultsrc;
337
 
338
            if ($adminpixenabled) {
339
                $adminsrc = block_point_view_pix_url(1, 'point_views_pix_admin', $file);
340
                if (!$adminsrc) {
341
                    $adminsrc = $defaultsrc;
342
                }
343
                $pix['admin'][$file] = $adminsrc;
344
            }
345
 
346
            $customsrc = block_point_view_pix_url($this->block->context->id, 'point_views_pix', $file);
347
            if ($customsrc) {
348
                $custompixexist = true;
349
            } else {
350
                $customsrc = isset($adminsrc) ? $adminsrc : $defaultsrc;
351
            }
352
            $pix['custom'][$file] = $customsrc;
353
        }
354
 
355
        if ($custompixexist) {
356
            $deletecustombutton = $this->get_action_button('delete_custom_pix', 'warning', 'delete_custom_pix');
357
        } else {
358
            $pix['custom'] = [];
359
            $deletecustombutton = null;
360
        }
361
 
362
        // Create select for the three options.
363
        $pixselect = [];
364
        $pixselect[] = &$mform->createElement('html', '<div class="pixselectgroup">');
365
        $this->create_emoji_radioselect($mform, $pixselect, 'default', $pix);
366
        if ($adminpixenabled) {
367
            $this->create_emoji_radioselect($mform, $pixselect, 'admin', $pix);
368
        }
369
        $this->create_emoji_radioselect($mform, $pixselect, 'custom', $pix, $deletecustombutton);
370
        $pixselect[] = &$mform->createElement('html', '</div>');
371
 
372
        $mform->addGroup($pixselect, 'pixselectgroup', get_string('emojitouse', 'block_point_view'), '', false);
373
        $mform->setDefault('config_pixselect', $adminpixenabled ? 'admin' : 'default');
374
        $mform->addHelpButton('pixselectgroup', 'emojitouse', 'block_point_view');
375
 
376
        // Create file manager for custom emoji.
377
        $mform->addElement(
378
                'filemanager',
379
                'config_point_views_pix',
380
                get_string('customemoji', 'block_point_view'),
381
                null,
382
                [ 'subdirs' => 0, 'maxfiles' => 11, 'accepted_types' => '.png' ]
383
                );
384
 
385
        $mform->addHelpButton('config_point_views_pix', 'customemoji', 'block_point_view');
386
        $mform->disabledIf('config_point_views_pix', 'config_pixselect', 'neq', 'custom');
387
 
388
        // Create fields for custom reaction text.
389
        $current = block_point_view_get_current_pix($this->block, $pixfiles);
390
        foreach ($pixfiles as $file) {
391
 
392
            $elementname = 'config_pix_text_' . $file;
393
            $defaulttext = get_string('defaulttext' . $file, 'block_point_view');
394
 
395
            $mform->addElement('text',
396
                    $elementname,
397
                    html_writer::empty_tag('img', [
398
                            'src' => $current[$file],
399
                            'class' => 'pix-preview currentpix my-1',
400
                            'alt' => $defaulttext,
401
                            'data-reaction' => $file,
402
                    ]) .
403
                    get_string('emojidesc', 'block_point_view')
404
                    );
405
 
406
            $mform->setDefault($elementname, $defaulttext);
407
            $mform->setType($elementname, PARAM_RAW);
408
            $mform->addHelpButton($elementname, 'emojidesc', 'block_point_view');
409
 
410
        }
411
    }
412
 
413
    /**
414
     * Helper function to create a radio select element for emoji and add it to a form.
415
     *
416
     * @param MoodleQuickForm $mform
417
     * @param Html_Common[] $group Array to which the element should be added.
418
     * @param string $value
419
     * @param string[][] $pix Array of pix sources.
420
     * @param string|null $additionallegend Optional html to add after the emoji.
421
     */
422
    protected function create_emoji_radioselect(&$mform, &$group, $value, $pix, $additionallegend = null) {
423
        $group[] = $mform->createElement('radio', 'config_pixselect', '',
424
                get_string($value . 'pix', 'block_point_view'), $value, [ 'class' => 'pr-2 mr-0 w-100 justify-content-start' ]);
425
 
426
        $legend = '<label for="id_config_pixselect_' . $value . '" class="d-inline-block">';
427
        foreach ($pix[$value] as $file => $src) {
428
            $legend .= html_writer::empty_tag('img', [
429
                    'src' => $src,
430
                    'class' => 'pix-preview my-1',
431
                    'data-reaction' => $file,
432
                    'data-source' => $value,
433
            ]);
434
        }
435
        $legend .= '</label>';
436
        if ($additionallegend !== null) {
437
            $legend = '<span>' . $legend . $additionallegend . '</span>';
438
        }
439
        $group[] = $mform->createElement('html', $legend);
440
    }
441
 
442
    /**
443
     * Helper function to create an action button.
444
     *
445
     * @param string $id Button id.
446
     * @param string $type Button outline type (e.g. 'warning', 'danger'...).
447
     * @param string $str String identifier for the button label (in block_point_view component).
448
     * @param string|null $a Additional data to pass to get_string for button label.
449
     * @param string $dataattributes HTML data attributes.
450
     * @return string HTML fragment for the button.
451
     */
452
    protected function get_action_button($id, $type, $str, $a = null, $dataattributes = '') {
453
        return '<button ' . ($id ? 'id="' . $id . '"' : '') . 'class="btn btn-outline-' . $type . ' ml-3 mr-1"
454
                type="button" ' . $dataattributes . '>' .
455
                   get_string($str, 'block_point_view', $a) .
456
               '</button>';
457
    }
458
 
459
    /**
460
     * Validation of filemanager files
461
     *
462
     * @param array $data
463
     * @param array $files
464
     * @return array
465
     */
466
    public function validation($data, $files) {
467
 
468
        global $USER;
469
 
470
        $errors = [];
471
 
472
        if (isset($data['config_pixselect']) && $data['config_pixselect'] == 'custom') {
473
 
474
            $fs = get_file_storage();
475
 
476
            $usercontext = context_user::instance($USER->id);
477
 
478
            $expected = [
479
                'easy',
480
                'better',
481
                'hard',
482
                'group_',
483
                'group_E',
484
                'group_B',
485
                'group_H',
486
                'group_EB',
487
                'group_EH',
488
                'group_BH',
489
                'group_EBH',
490
            ];
491
 
492
            $draftfiles = $fs->get_area_files(
493
                $usercontext->id,
494
                'user',
495
                'draft',
496
                $data['config_point_views_pix'],
497
                'filename',
498
                false
499
                );
500
 
501
            if (empty($draftfiles)) {
502
                $errors['config_point_views_pix'] = get_string('errorfilemanagerempty', 'block_point_view');
503
            }
504
 
505
            foreach ($draftfiles as $file) {
506
 
507
                $pathinfo = pathinfo($file->get_filename());
508
 
509
                if (!in_array($pathinfo['filename'], $expected, true)) {
510
 
511
                    if (!isset($errors['config_point_views_pix'])) {
512
                        $errors['config_point_views_pix'] = '';
513
                    }
514
 
515
                    $errors['config_point_views_pix'] .= get_string(
516
                        'errorfilemanager',
517
                        'block_point_view',
518
                        $pathinfo['filename']
519
                        ) . '<br />';
520
                }
521
            }
522
        }
523
 
524
        return $errors;
525
    }
526
 
527
    /**
528
     * File manager and Editor data
529
     *
530
     * @param array $defaults
531
     */
532
    public function set_data($defaults) {
533
 
534
        $text = '';
535
        if (!empty($this->block->config) && is_object($this->block->config)) {
536
            $text = $this->block->config->text;
537
            $draftideditor = file_get_submitted_draft_itemid('config_text');
538
            if (empty($text)) {
539
                $currenttext = '';
540
            } else {
541
                $currenttext = $text;
542
            }
543
            $defaults->config_text['text'] = file_prepare_draft_area(
544
                $draftideditor,
545
                $this->block->context->id,
546
                'block_point_view',
547
                'content',
548
                0,
549
                [ 'subdirs' => true ],
550
                $currenttext
551
            );
552
            $defaults->config_text['itemid'] = $draftideditor;
553
            $defaults->config_text['format'] = $this->block->config->format;
554
 
555
            $draftidpix = file_get_submitted_draft_itemid('config_point_views_pix');
556
 
557
            file_prepare_draft_area(
558
                $draftidpix,
559
                $this->block->context->id,
560
                'block_point_view',
561
                'point_views_pix',
562
                0,
563
                [
564
                    'subdirs' => 0,
565
                    'maxfiles' => 20,
566
                    'accepted_types' => [ '.png' ],
567
                ]
568
                );
569
 
570
            $defaults->config_point_views_pix = $draftidpix;
571
 
572
            $this->block->config->point_views_pix = $draftidpix;
573
        }
574
 
575
        unset($this->block->config->text);
576
 
577
        if (!get_config('block_point_view', 'enable_pix_admin')
578
                && isset($this->block->config->pixselect)
579
                && $this->block->config->pixselect == 'admin') {
580
            $this->block->config->pixselect = 'default';
581
        }
582
 
583
        parent::set_data($defaults);
584
 
585
        if (!isset($this->block->config)) {
586
            $this->block->config = new stdClass();
587
        }
588
        $this->block->config->text = $text;
589
 
590
    }
591
}