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
namespace editor_tiny;
18
 
19
use context;
20
 
21
/**
22
 * Tiny Editor Plugin manager.
23
 *
24
 * @package    editor_tiny
25
 * @copyright  2021 Andrew Lyons <andrew@nicols.co.uk>
26
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27
 */
28
class manager {
29
 
30
    /**
31
     * Get the configuration for all plugins.
32
     *
33
     * @param context $context The context that the editor is used within
34
     * @param array $options The options passed in when requesting the editor
35
     * @param array $fpoptions The filepicker options passed in when requesting the editor
36
     * @param  editor $editor The editor instance in which the plugin is initialised
37
     */
38
    public function get_plugin_configuration(
39
        context $context,
40
        array $options = [],
41
        array $fpoptions = [],
42
        ?editor $editor = null
43
    ): array {
44
        // Get the list of plugins.
45
        // Note: Disabled plugins are already removed from this list.
46
        $plugins = $this->get_shipped_plugins();
47
 
48
        // Fetch configuration for Moodle plugins.
49
        $moodleplugins = \core_component::get_plugin_list_with_class('tiny', 'plugininfo');
50
        $enabledplugins = \editor_tiny\plugininfo\tiny::get_enabled_plugins();
51
        foreach ($moodleplugins as $plugin => $classname) {
52
            [, $pluginname] = explode('_', $plugin, 2);
53
            if (!in_array($pluginname, $enabledplugins)) {
54
                // This plugin has been disabled.
55
                continue;
56
            }
57
 
58
            if (!is_a($classname, plugin::class, true)) {
59
                // Skip plugins that do not implement the plugin interface.
60
                debugging("Plugin {$plugin} does not implement the plugin interface", DEBUG_DEVELOPER);
61
                continue;
62
            }
63
 
1441 ariadna 64
            $options['pluginname'] = $pluginname;
65
 
1 efrain 66
            if (!$classname::is_enabled($context, $options, $fpoptions, $editor)) {
67
                // This plugin has disabled itself for some reason.
68
                // This is typical for media plugins where there is no file storage.
69
                continue;
70
            }
71
 
72
            // Get the plugin information, which includes the list of buttons, menu items, and configuration.
73
            $plugininfo = $classname::get_plugin_info(
74
                $context,
75
                $options,
76
                $fpoptions,
77
                $editor
78
            );
79
 
80
            // We suffix the plugin name for Moodle plugins with /plugin to avoid conflicts with Tiny plugins.
81
            $plugins["{$plugin}/plugin"] = $plugininfo;
82
        }
83
 
84
        return $plugins;
85
    }
86
 
87
    /**
1441 ariadna 88
     * Get the configuration for external functions.
89
     *
90
     * @param context $context The context that the editor is used within.
91
     */
92
    public function get_plugin_configuration_for_external(context $context): array {
93
        $plugins = [];
94
 
95
        $moodleplugins = \core_component::get_plugin_list_with_class('tiny', 'plugininfo');
96
        $enabledplugins = \editor_tiny\plugininfo\tiny::get_enabled_plugins();
97
 
98
        foreach ($moodleplugins as $plugin => $classname) {
99
            [, $pluginname] = explode('_', $plugin, 2);
100
            if (!in_array($pluginname, $enabledplugins)) {
101
                // This plugin has been disabled.
102
                continue;
103
            }
104
 
105
            if (!is_a($classname, plugin::class, true)) {
106
                // Skip plugins that do not implement the plugin interface.
107
                debugging("Plugin {$plugin} does not implement the plugin interface", DEBUG_DEVELOPER);
108
                continue;
109
            }
110
 
111
            $options = ['pluginname' => $pluginname];
112
            if (!$classname::is_enabled_for_external($context, $options)) {
113
                // This plugin has disabled itself for some reason.
114
                continue;
115
            }
116
 
117
            // Get the plugin configuration for external functions.
118
            $pluginconfig = [];
119
            if (is_a($classname, plugin_with_configuration_for_external::class, true)) {
120
                $pluginconfig = $classname::get_plugin_configuration_for_external($context);
121
            }
122
 
123
            $plugins[$pluginname] = $pluginconfig;
124
        }
125
 
126
        return $plugins;
127
    }
128
 
129
    /**
1 efrain 130
     * Get a list of the buttons provided by this plugin.
131
     *
132
     * @return string[]
133
     */
134
    protected function get_tinymce_buttons(): array {
135
        // The following list is defined at:
136
        // https://www.tiny.cloud/docs/advanced/available-toolbar-buttons/#thecoretoolbarbuttons.
137
        return [
138
            // These are always available, without requiring additional plugins.
139
            'aligncenter',
140
            'alignjustify',
141
            'alignleft',
142
            'alignnone',
143
            'alignright',
144
            'blockquote',
145
            'backcolor',
146
            'bold',
147
            'copy',
148
            'cut',
149
            'fontselect',
150
            'fontsizeselect',
151
            'forecolor',
152
            'formatselect',
153
            'h1',
154
            'h2',
155
            'h3',
156
            'h4',
157
            'h5',
158
            'h6',
159
            'indent',
160
            'italic',
161
            'language',
162
            'lineheight',
163
            'newdocument',
164
            'outdent',
165
            'paste',
166
            'redo',
167
            'remove',
168
            'removeformat',
169
            'selectall',
170
            'strikethrough',
171
            'styleselect',
172
            'subscript',
173
            'superscript',
174
            'underline',
175
            'undo',
176
            'visualaid',
177
        ];
178
    }
179
 
180
    /**
181
     * Get a list of the menu items provided by this plugin.
182
     *
183
     * @return string[]
184
     */
185
    protected function get_tinymce_menuitems(): array {
186
        // The following list is defined at:
187
        // https://www.tiny.cloud/docs/advanced/available-menu-items/#thecoremenuitems.
188
        return [
189
            'align' => 'format',
190
            'backcolor' => 'format',
191
            'blockformats' => 'format',
192
            'bold' => 'format',
193
            'codeformat' => 'format',
194
            'copy' => 'copy',
195
            'cut' => 'copy',
196
            'forecolor' => 'format',
197
            'formats' => 'format',
198
            'fontformats' => 'format',
199
            'fontsizes' => 'format',
200
            'italic' => 'format',
201
            'language' => 'format',
202
            'lineheight' => 'format',
203
            'newdocument' => 'file',
204
            'paste' => 'copy',
205
            'redo' => 'copy',
206
            'removeformat' => 'format',
207
            'selectall' => 'edit',
208
            'strikethrough' => 'format',
209
            'subscript' => 'format',
210
            'superscript' => 'format',
211
            'underline' => 'format',
212
            'undo' => 'copy',
213
            'visualaid' => 'view',
214
        ];
215
    }
216
 
217
    /**
218
     * Return a list of all available plugins, including both TinyMCE shipped, and Moodle add-onis.
219
     *
220
     * Each plugin is returned as an array element containing:
221
     * - a list of buttons (if applicable); and
222
     * - a list of menuitems (if applicable).
223
     *
224
     * Note: Not all plugins include buttons, and not all plugins include menuitems.
225
     * These array keys are optional.
226
     *
227
     * @return array
228
     */
229
    protected function get_available_plugins(): array {
230
        $plugins = $this->get_shipped_plugins();
231
        $plugins += $this->get_moodle_plugins();
232
 
233
        $disabledplugins = $this->get_disabled_tinymce_plugins();
234
        $plugins = array_filter($plugins, function ($plugin) use ($disabledplugins) {
235
            return !in_array($plugin, $disabledplugins);
236
        }, ARRAY_FILTER_USE_KEY);
237
 
238
        return $plugins;
239
    }
240
 
241
    /**
242
     * Return a list of all available plugins built into TinyMCE and not shipped as separate Moodle plugins.
243
     *
244
     * Each plugin is returned as an array element containing:
245
     * - a list of buttons (if applicable); and
246
     * - a list of menuitems (if applicable).
247
     *
248
     * Note: Not all plugins include buttons, and not all plugins include menuitems.
249
     * These array keys are optional.
250
     *
251
     * @return array
252
     */
253
    protected function get_shipped_plugins(): array {
254
        $plugins = $this->get_tinymce_plugins();
255
        if ($this->premium_plugins_enabled()) {
256
            $plugins += $this->get_premium_plugins();
257
        }
258
 
259
        $disabledplugins = $this->get_disabled_tinymce_plugins();
260
        return array_filter($plugins, function ($plugin) use ($disabledplugins) {
261
            return !in_array($plugin, $disabledplugins);
262
        }, ARRAY_FILTER_USE_KEY);
263
    }
264
 
265
    /**
266
     * Get a list of the core plugins with their button, and menuitem, configuration.
267
     *
268
     * @return array[]
269
     */
270
    protected function get_tinymce_plugins(): array {
271
        // The following list is defined at:
272
        // https://www.tiny.cloud/docs/advanced/available-toolbar-buttons/#thecoretoolbarbuttons.
273
        return [
274
            'anchor' => [
275
                'buttons' => [
276
                    'anchor',
277
                ],
278
                'menuitems' => [
279
                    'anchor' => 'insert',
280
                ],
281
            ],
282
            'autosave' => [
283
                'buttons' => [
284
                    'restoredraft',
285
                ],
286
                'menuitems' => [
287
                    'restoredraft' => 'file',
288
                ],
289
            ],
290
            'charmap' => [
291
                'buttons' => [
292
                    'charmap',
293
                ],
294
                'menuitems' => [
295
                    'charmap' => 'insert',
296
                ],
297
            ],
298
            'code' => [
299
                'buttons' => [
300
                    'code',
301
                ],
302
                'menuitems' => [
303
                    'code' => 'view',
304
                ],
305
            ],
306
            'codesample' => [
307
                'buttons' => [
308
                    'codesample',
309
                ],
310
                'menutiems' => [
311
                    'codesample' => 'insert',
312
                ],
313
            ],
314
            'directionality' => [
315
                'buttons' => [
316
                    'ltr',
317
                    'rtl',
318
                ],
319
            ],
320
            'emoticons' => [
321
                'buttons' => [
322
                    'emoticons',
323
                ],
324
                'menuitems' => [
325
                    'emoticons' => 'insert',
326
                ],
327
            ],
328
            'fullscreen' => [
329
                'buttons' => [
330
                    'fullscreen',
331
                ],
332
                'menuitems' => [
333
                    'fullscreen' => 'view',
334
                ],
335
            ],
336
            'help' => [
337
                'buttons' => [
338
                    'help',
339
                ],
340
                'menuitems' => [
341
                    'help' => 'help',
342
                ],
343
            ],
344
            'image' => [
345
                'buttons' => [
346
                    'image',
347
                ],
348
                'menuitems' => [
349
                    'image' => 'insert',
350
                ],
351
            ],
352
            'insertdatetime' => [
353
                'buttons' => [
354
                    'insertdatetime',
355
                ],
356
                'menuitems' => [
357
                    'insertdatetime' => 'insert',
358
                ],
359
            ],
360
            'link' => [
361
                'buttons' => [
362
                    'link',
363
                    'openlink',
364
                    'unlink',
365
                ],
366
                'menuitems' => [
367
                    'link' => 'insert',
368
                ],
369
            ],
370
            'lists' => [
371
                'buttons' => [
372
                    'bullist',
373
                    'numlist',
374
                ],
375
            ],
376
            'media' => [
377
                'buttons' => [
378
                    'media',
379
                ],
380
                'menuitems' => [
381
                    'media' => 'insert',
382
                ],
383
            ],
384
            'nonbreaking' => [
385
                'buttons' => [
386
                    'nonbreaking',
387
                ],
388
                'menuitems' => [
389
                    'nonbreaking' => 'insert',
390
                ],
391
            ],
392
            'pagebreak' => [
393
                'buttons' => [
394
                    'pagebreak',
395
                ],
396
                'menuitems' => [
397
                    'pagebreak' => 'insert',
398
                ],
399
            ],
400
            'preview' => [
401
                'buttons' => [
402
                    'preview',
403
                ],
404
                'menuitems' => [
405
                    'preview' => 'file',
406
                ],
407
            ],
408
            'quickbars' => [
409
                'buttons' => [
410
                    'quickimage',
411
                    'quicklink',
412
                    'quicktable',
413
                ],
414
            ],
415
            'save' => [
416
                'buttons' => [
417
                    'cancel',
418
                    'save',
419
                ],
420
            ],
421
            'searchreplace' => [
422
                'buttons' => [
423
                    'searchreplace',
424
                ],
425
                'menuitems' => [
426
                    'searchreplace' => 'edit',
427
                ],
428
            ],
429
            'table' => [
430
                'buttons' => [
431
                    'table',
432
                    'tablecellprops',
433
                    'tablecopyrow',
434
                    'tablecutrow',
435
                    'tabledelete',
436
                    'tabledeletecol',
437
                    'tabledeleterow',
438
                    'tableinsertdialog',
439
                    'tableinsertcolafter',
440
                    'tableinsertcolbefore',
441
                    'tableinsertrowafter',
442
                    'tableinsertrowbefore',
443
                    'tablemergecells',
444
                    'tablepasterowafter',
445
                    'tablepasterowbefore',
446
                    'tableprops',
447
                    'tablerowprops',
448
                    'tablesplitcells',
449
                    'tableclass',
450
                    'tablecellclass',
451
                    'tablecellvalign',
452
                    'tablecellborderwidth',
453
                    'tablecellborderstyle',
454
                    'tablecaption',
455
                    'tablecellbackgroundcolor',
456
                    'tablecellbordercolor',
457
                    'tablerowheader',
458
                    'tablecolheader',
459
                ],
460
                'menuitems' => [
461
                    'inserttable' => 'table',
462
                    'tableprops' => 'table',
463
                    'deletetable' => 'table',
464
                    'cell' => 'table',
465
                    'tablemergecells' => 'table',
466
                    'tablesplitcells' => 'table',
467
                    'tablecellprops' => 'table',
468
                    'column' => 'table',
469
                    'tableinsertcolumnbefore' => 'table',
470
                    'tableinsertcolumnafter' => 'table',
471
                    'tablecutcolumn' => 'table',
472
                    'tablecopycolumn' => 'table',
473
                    'tablepastecolumnbefore' => 'table',
474
                    'tablepastecolumnafter' => 'table',
475
                    'tabledeletecolumn' => 'table',
476
                    'row' => 'table',
477
                    'tableinsertrowbefore' => 'table',
478
                    'tableinsertrowafter' => 'table',
479
                    'tablecutrow' => 'table',
480
                    'tablecopyrow' => 'table',
481
                    'tablepasterowbefore' => 'table',
482
                    'tablepasterowafter' => 'table',
483
                    'tablerowprops' => 'table',
484
                    'tabledeleterow' => 'table',
485
                ],
486
            ],
487
            'visualblocks' => [
488
                'buttons' => [
489
                    'visualblocks',
490
                ],
491
                'menuitems' => [
492
                    'visualblocks' => 'view',
493
                ],
494
            ],
495
            'visualchars' => [
496
                'buttons' => [
497
                    'visualchars',
498
                ],
499
                'menuitems' => [
500
                    'visualchars' => 'view',
501
                ],
502
            ],
503
            'wordcount' => [
504
                'buttons' => [
505
                    'wordcount',
506
                ],
507
                'menuitems' => [
508
                    'wordcount' => 'tools',
509
                ],
510
            ],
511
        ];
512
    }
513
 
514
    /**
515
     * Get a list of the built-in TinyMCE plugins which we want to disable.
516
     *
517
     * These are usually disabled because we have replaced them, or they are not compatible with Moodle in some way.
518
     *
519
     * @return string[]
520
     */
521
    protected function get_disabled_tinymce_plugins(): array {
522
        return [
523
            // Disable the image and media plugins.
524
            // These are not generally compatible with Moodle.
525
            'image',
526
            'media',
527
 
528
            // Use the Moodle autosave plugin instead.
529
            'autosave',
530
 
531
            // Disable the preview plugin as it does not support Moodle filters.
532
            'preview',
533
 
534
            // Use the Moodle link plugin instead.
535
            'link',
536
        ];
537
    }
538
 
539
    /**
540
     * Get a list of the Moodle plugins with their button, and menuitem, configuration.
541
     *
542
     * @return array[]
543
     */
544
    protected function get_moodle_plugins(): array {
545
        $plugins = \core_component::get_plugin_list_with_class('tiny', 'plugininfo');
546
 
547
        $pluginconfig = [];
548
        foreach ($plugins as $pluginname => $classname) {
549
            if (!is_a($classname, plugin::class, true)) {
550
                continue;
551
            }
552
            // Module name => [buttons, menuitems].
553
            $pluginconfig["{$pluginname}/plugin"] = $classname::get_plugin_info();
554
        }
555
 
556
        return $pluginconfig;
557
    }
558
 
559
    /**
560
     * Check whether premium plugins are configured and enabled.
561
     *
562
     * @return bool
563
     */
564
    protected function premium_plugins_enabled(): bool {
565
        return false;
566
    }
567
 
568
    /**
569
     * Get a list of the Tiny Premium plugins with their button, and menuitem, configuration.
570
     *
571
     * Note: This only includes _compatible_ premium plugins.
572
     * Some premium plugins *may not* be compatible with Moodle, and some may require additional configuration.
573
     *
574
     * @return array[]
575
     */
576
    protected function get_premium_plugins(): array {
577
        return [
578
            'a11ycheck' => [
579
                'buttons' => [
580
                    'a11ycheck',
581
                ],
582
                'menuitems' => [
583
                    'a11ycheck',
584
                ],
585
            ],
586
            'advcode' => [
587
                'buttons' => [
588
                    'code',
589
                ],
590
                'menuitems' => [
591
                    'code',
592
                ],
593
            ],
594
            'footnotes' => [
595
                'buttons' => [
596
                    'footnotes',
597
                    'footnotesupdate',
598
                ],
599
                'menuitems' => [
600
                    'footnotes',
601
                    'footnotesupdate',
602
                ],
603
            ],
604
            'mergetags' => [
605
                'buttons' => [
606
                    'mergetags',
607
                ],
608
                'menuitems' => [
609
                    'mergetags',
610
                ],
611
            ],
612
            'autocorrect' => [
613
                'menuitems' => [
614
                    'autocorrect',
615
                    'capitalization',
616
                ],
617
            ],
618
        ];
619
    }
620
}