Proyectos de Subversion Moodle

Rev

| 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
/**
20
 * Tiny Editor.
21
 *
22
 * @package    editor_tiny
23
 * @copyright  2021 Andrew Lyons <andrew@nicols.co.uk>
24
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25
 */
26
class editor extends \texteditor {
27
 
28
    /** @var manager The Tiny Manager instace */
29
    protected $manager;
30
 
31
    /** @var \stdClass|null The default configuration to use if none is provided */
32
    protected static $defaultconfiguration = null;
33
 
34
    /**
35
     * Instantiate the new editor instance.
36
     */
37
    public function __construct() {
38
        $this->manager = new manager();
39
    }
40
 
41
    /**
42
     * Set the default configuration for the editor.
43
     *
44
     * @param manager $manager The editor manager
45
     */
46
    public static function set_default_configuration(manager $manager): void {
47
        global $PAGE;
48
 
49
        if (self::is_default_configuration_set()) {
50
            return;
51
        }
52
 
53
        $context = $PAGE->context;
54
 
55
        $config = (object) [
56
            'css' => $PAGE->theme->editor_css_url()->out(false),
57
            'context' => $context->id,
58
            'plugins' => $manager->get_plugin_configuration($context, [], []),
59
        ];
60
 
61
        $config = json_encode($config);
62
        $inlinejs = <<<EOF
63
            M.util.js_pending('editor_tiny/editor:defaultConfiguration');
64
            require(['editor_tiny/editor'], (Tiny) => {
65
                Tiny.configureDefaultEditor({$config});
66
                M.util.js_complete('editor_tiny/editor:defaultConfiguration');
67
            });
68
        EOF;
69
 
70
        $PAGE->requires->js_amd_inline($inlinejs);
71
 
72
        self::$defaultconfiguration = $config;
73
    }
74
 
75
    /**
76
     * Fetch the current defautl configuration.
77
     *
78
     * @return \stdClass|null The default configuration or null if not set.
79
     */
80
    public static function get_default_configuration(): ?\stdClass {
81
        return self::$defaultconfiguration;
82
    }
83
 
84
    /**
85
     * Reset the default configuration.
86
     */
87
    public static function reset_default_configuration(): void {
88
        self::$defaultconfiguration = null;
89
    }
90
 
91
    /**
92
     * Check if the default configuration is set.
93
     *
94
     * @return bool True if the default configuration is set.
95
     */
96
    public static function is_default_configuration_set(): bool {
97
        return !empty(self::$defaultconfiguration);
98
    }
99
 
100
    /**
101
     * Is the current browser supported by this editor?
102
     *
103
     * @return bool
104
     */
105
    public function supported_by_browser() {
106
        return true;
107
    }
108
 
109
    /**
110
     * List of supported text field formats.
111
     *
112
     * @return array
113
     */
114
    public function get_supported_formats() {
115
        return [
116
            FORMAT_HTML => FORMAT_HTML,
117
        ];
118
    }
119
 
120
    /**
121
     * Returns text format preferred by this editor.
122
     *
123
     * @return int
124
     */
125
    public function get_preferred_format() {
126
        return FORMAT_HTML;
127
    }
128
 
129
    /**
130
     * Does this editor support picking from repositories?
131
     *
132
     * @return bool
133
     */
134
    public function supports_repositories() {
135
        return true;
136
    }
137
 
138
    /**
139
     * Use this editor for given element.
140
     *
141
     * @param string $elementid
142
     * @param array $options
143
     * @param null $fpoptions
144
     */
145
    public function use_editor($elementid, array $options = null, $fpoptions = null) {
146
        global $PAGE;
147
 
148
        // Ensure that the default configuration is set.
149
        self::set_default_configuration($this->manager);
150
 
151
        if ($fpoptions === null) {
152
            $fpoptions = [];
153
        }
154
 
155
        $context = $PAGE->context;
156
 
157
        if (isset($options['context']) && ($options['context'] instanceof \context)) {
158
            // A different context was provided.
159
            // Use that instead.
160
            $context = $options['context'];
161
        }
162
 
163
        // Generate the configuration for this editor.
164
        $siteconfig = get_config('editor_tiny');
165
        $config = (object) [
166
            // The URL to the CSS file for the editor.
167
            'css' => $PAGE->theme->editor_css_url()->out(false),
168
 
169
            // The current context for this page or editor.
170
            'context' => $context->id,
171
 
172
            // File picker options.
173
            'filepicker' => (object) $fpoptions,
174
 
175
            // Default draft item ID.
176
            'draftitemid' => 0,
177
 
178
            'currentLanguage' => current_language(),
179
 
180
            'branding' => property_exists($siteconfig, 'branding') ? !empty($siteconfig->branding) : true,
181
 
182
            // Language options.
183
            'language' => [
184
                'currentlang' => current_language(),
185
                'installed' => get_string_manager()->get_list_of_translations(true),
186
                'available' => get_string_manager()->get_list_of_languages()
187
            ],
188
 
189
            // Placeholder selectors.
190
            // Some contents (Example: placeholder elements) are only shown in the editor, and not to users. It is unrelated to the
191
            // real display. We created a list of placeholder selectors, so we can decide to or not to apply rules, styles... to
192
            // these elements.
193
            // The default of this list will be empty.
194
            // Other plugins can register their placeholder elements to placeholderSelectors list by calling
195
            // editor_tiny/options::registerPlaceholderSelectors.
196
            'placeholderSelectors' => [],
197
 
198
            // Plugin configuration.
199
            'plugins' => $this->manager->get_plugin_configuration($context, $options, $fpoptions, $this),
200
        ];
201
 
202
        if (defined('BEHAT_SITE_RUNNING') && BEHAT_SITE_RUNNING) {
203
            // Add sample selectors for Behat test.
204
            $config->placeholderSelectors = ['.behat-tinymce-placeholder'];
205
        }
206
 
207
        foreach ($fpoptions as $fp) {
208
            // Guess the draftitemid for the editor.
209
            // Note: This is the best we can do at the moment.
210
            if (!empty($fp->itemid)) {
211
                $config->draftitemid = $fp->itemid;
212
                break;
213
            }
214
        }
215
 
216
        $configoptions = json_encode(convert_to_array($config));
217
 
218
        // Note: This is not ideal but the editor does not have control over any HTML output.
219
        // The Editor API only allows you to run JavaScript.
220
        // In the future we will extend the editor API to allow it to generate the textarea, or attributes to use in the
221
        // textarea or its wrapper.
222
        // For now we cannot use the `js_call_amd()` API call because it warns if the parameters passed exceed a
223
        // relatively low character limit.
224
        $config = json_encode($config);
225
        $inlinejs = <<<EOF
226
            M.util.js_pending('editor_tiny/editor');
227
            require(['editor_tiny/editor'], (Tiny) => {
228
                Tiny.setupForElementId({
229
                    elementId: "{$elementid}",
230
                    options: {$configoptions},
231
                });
232
                M.util.js_complete('editor_tiny/editor');
233
            });
234
        EOF;
235
 
236
        $PAGE->requires->js_amd_inline($inlinejs);
237
    }
238
}