Differences Between: [Versions 401 and 402] [Versions 402 and 403]
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' => $fpoptions, 174 175 'currentLanguage' => current_language(), 176 177 'branding' => property_exists($siteconfig, 'branding') ? !empty($siteconfig->branding) : true, 178 179 // Language options. 180 'language' => [ 181 'currentlang' => current_language(), 182 'installed' => get_string_manager()->get_list_of_translations(true), 183 'available' => get_string_manager()->get_list_of_languages() 184 ], 185 186 // Placeholder selectors. 187 // Some contents (Example: placeholder elements) are only shown in the editor, and not to users. It is unrelated to the 188 // real display. We created a list of placeholder selectors, so we can decide to or not to apply rules, styles... to 189 // these elements. 190 // The default of this list will be empty. 191 // Other plugins can register their placeholder elements to placeholderSelectors list by calling 192 // editor_tiny/options::registerPlaceholderSelectors. 193 'placeholderSelectors' => [], 194 195 // Plugin configuration. 196 'plugins' => $this->manager->get_plugin_configuration($context, $options, $fpoptions, $this), 197 198 // Nest menu inside parent DOM. 199 'nestedmenu' => true, 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body