PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/form/editor.php

https://github.com/raymanuk/moodle
PHP | 447 lines | 224 code | 56 blank | 167 comment | 27 complexity | 24e335b2e9a8ca2ff1034e948dd6f503 MD5 | raw file
  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. * Editor input element
  18. *
  19. * Contains class to create preffered editor form element
  20. *
  21. * @package core_form
  22. * @copyright 2009 Petr Skoda {@link http://skodak.org}
  23. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24. */
  25. global $CFG;
  26. require_once('HTML/QuickForm/element.php');
  27. require_once($CFG->dirroot.'/lib/filelib.php');
  28. require_once($CFG->dirroot.'/repository/lib.php');
  29. /**
  30. * Editor element
  31. *
  32. * It creates preffered editor (textbox/TinyMce) form element for the format (Text/HTML) selected.
  33. *
  34. * @package core_form
  35. * @category form
  36. * @copyright 2009 Petr Skoda {@link http://skodak.org}
  37. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38. * @todo MDL-29421 element Freezing
  39. * @todo MDL-29426 ajax format conversion
  40. */
  41. class MoodleQuickForm_editor extends HTML_QuickForm_element {
  42. /** @var string html for help button, if empty then no help will icon will be dispalyed. */
  43. public $_helpbutton = '';
  44. /** @var string defines the type of editor */
  45. public $_type = 'editor';
  46. /** @var array options provided to initalize filepicker */
  47. protected $_options = array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 0, 'changeformat' => 0,
  48. 'areamaxbytes' => FILE_AREA_MAX_BYTES_UNLIMITED, 'context' => null, 'noclean' => 0, 'trusttext' => 0,
  49. 'return_types' => 7);
  50. // $_options['return_types'] = FILE_INTERNAL | FILE_EXTERNAL | FILE_REFERENCE
  51. /** @var array values for editor */
  52. protected $_values = array('text'=>null, 'format'=>null, 'itemid'=>null);
  53. /**
  54. * Constructor
  55. *
  56. * @param string $elementName (optional) name of the editor
  57. * @param string $elementLabel (optional) editor label
  58. * @param array $attributes (optional) Either a typical HTML attribute string
  59. * or an associative array
  60. * @param array $options set of options to initalize filepicker
  61. */
  62. function MoodleQuickForm_editor($elementName=null, $elementLabel=null, $attributes=null, $options=null) {
  63. global $CFG, $PAGE;
  64. $options = (array)$options;
  65. foreach ($options as $name=>$value) {
  66. if (array_key_exists($name, $this->_options)) {
  67. $this->_options[$name] = $value;
  68. }
  69. }
  70. if (!empty($options['maxbytes'])) {
  71. $this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $options['maxbytes']);
  72. }
  73. if (!$this->_options['context']) {
  74. // trying to set context to the current page context to make legacy files show in filepicker (e.g. forum post)
  75. if (!empty($PAGE->context->id)) {
  76. $this->_options['context'] = $PAGE->context;
  77. } else {
  78. $this->_options['context'] = context_system::instance();
  79. }
  80. }
  81. $this->_options['trusted'] = trusttext_trusted($this->_options['context']);
  82. parent::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
  83. // Note: for some reason the code using this setting does not like bools.
  84. $this->_options['subdirs'] = (int)($this->_options['subdirs'] == 1);
  85. editors_head_setup();
  86. }
  87. /**
  88. * Called by HTML_QuickForm whenever form event is made on this element
  89. *
  90. * @param string $event Name of event
  91. * @param mixed $arg event arguments
  92. * @param object $caller calling object
  93. * @return bool
  94. */
  95. function onQuickFormEvent($event, $arg, &$caller)
  96. {
  97. switch ($event) {
  98. case 'createElement':
  99. $caller->setType($arg[0] . '[format]', PARAM_ALPHANUM);
  100. $caller->setType($arg[0] . '[itemid]', PARAM_INT);
  101. break;
  102. }
  103. return parent::onQuickFormEvent($event, $arg, $caller);
  104. }
  105. /**
  106. * Sets name of editor
  107. *
  108. * @param string $name name of the editor
  109. */
  110. function setName($name) {
  111. $this->updateAttributes(array('name'=>$name));
  112. }
  113. /**
  114. * Returns name of element
  115. *
  116. * @return string
  117. */
  118. function getName() {
  119. return $this->getAttribute('name');
  120. }
  121. /**
  122. * Updates editor values, if part of $_values
  123. *
  124. * @param array $values associative array of values to set
  125. */
  126. function setValue($values) {
  127. $values = (array)$values;
  128. foreach ($values as $name=>$value) {
  129. if (array_key_exists($name, $this->_values)) {
  130. $this->_values[$name] = $value;
  131. }
  132. }
  133. }
  134. /**
  135. * Returns editor values
  136. *
  137. * @return array
  138. */
  139. function getValue() {
  140. return $this->_values;
  141. }
  142. /**
  143. * Returns maximum file size which can be uploaded
  144. *
  145. * @return int
  146. */
  147. function getMaxbytes() {
  148. return $this->_options['maxbytes'];
  149. }
  150. /**
  151. * Sets maximum file size which can be uploaded
  152. *
  153. * @param int $maxbytes file size
  154. */
  155. function setMaxbytes($maxbytes) {
  156. global $CFG;
  157. $this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $maxbytes);
  158. }
  159. /**
  160. * Returns the maximum size of the area.
  161. *
  162. * @return int
  163. */
  164. function getAreamaxbytes() {
  165. return $this->_options['areamaxbytes'];
  166. }
  167. /**
  168. * Sets the maximum size of the area.
  169. *
  170. * @param int $areamaxbytes size limit
  171. */
  172. function setAreamaxbytes($areamaxbytes) {
  173. $this->_options['areamaxbytes'] = $areamaxbytes;
  174. }
  175. /**
  176. * Returns maximum number of files which can be uploaded
  177. *
  178. * @return int
  179. */
  180. function getMaxfiles() {
  181. return $this->_options['maxfiles'];
  182. }
  183. /**
  184. * Sets maximum number of files which can be uploaded.
  185. *
  186. * @param int $num number of files
  187. */
  188. function setMaxfiles($num) {
  189. $this->_options['maxfiles'] = $num;
  190. }
  191. /**
  192. * Returns true if subdirectoy can be created, else false
  193. *
  194. * @return bool
  195. */
  196. function getSubdirs() {
  197. return $this->_options['subdirs'];
  198. }
  199. /**
  200. * Set option to create sub directory, while uploading file
  201. *
  202. * @param bool $allow true if sub directory can be created.
  203. */
  204. function setSubdirs($allow) {
  205. $this->_options['subdirs'] = (int)($allow == 1);
  206. }
  207. /**
  208. * Returns editor format
  209. *
  210. * @return int.
  211. */
  212. function getFormat() {
  213. return $this->_values['format'];
  214. }
  215. /**
  216. * Checks if editor used is a required field
  217. *
  218. * @return bool true if required field.
  219. */
  220. function isRequired() {
  221. return (isset($this->_options['required']) && $this->_options['required']);
  222. }
  223. /**
  224. * @deprecated since Moodle 2.0
  225. */
  226. function setHelpButton($_helpbuttonargs, $function='_helpbutton') {
  227. throw new coding_exception('setHelpButton() can not be used any more, please see MoodleQuickForm::addHelpButton().');
  228. }
  229. /**
  230. * Returns html for help button.
  231. *
  232. * @return string html for help button
  233. */
  234. function getHelpButton() {
  235. return $this->_helpbutton;
  236. }
  237. /**
  238. * Returns type of editor element
  239. *
  240. * @return string
  241. */
  242. function getElementTemplateType() {
  243. if ($this->_flagFrozen){
  244. return 'nodisplay';
  245. } else {
  246. return 'default';
  247. }
  248. }
  249. /**
  250. * Returns HTML for editor form element.
  251. *
  252. * @return string
  253. */
  254. function toHtml() {
  255. global $CFG, $PAGE;
  256. require_once($CFG->dirroot.'/repository/lib.php');
  257. if ($this->_flagFrozen) {
  258. return $this->getFrozenHtml();
  259. }
  260. $ctx = $this->_options['context'];
  261. $id = $this->_attributes['id'];
  262. $elname = $this->_attributes['name'];
  263. $subdirs = $this->_options['subdirs'];
  264. $maxbytes = $this->_options['maxbytes'];
  265. $areamaxbytes = $this->_options['areamaxbytes'];
  266. $maxfiles = $this->_options['maxfiles'];
  267. $changeformat = $this->_options['changeformat']; // TO DO: implement as ajax calls
  268. $text = $this->_values['text'];
  269. $format = $this->_values['format'];
  270. $draftitemid = $this->_values['itemid'];
  271. // security - never ever allow guest/not logged in user to upload anything
  272. if (isguestuser() or !isloggedin()) {
  273. $maxfiles = 0;
  274. }
  275. $str = $this->_getTabs();
  276. $str .= '<div>';
  277. $editor = editors_get_preferred_editor($format);
  278. $strformats = format_text_menu();
  279. $formats = $editor->get_supported_formats();
  280. foreach ($formats as $fid) {
  281. $formats[$fid] = $strformats[$fid];
  282. }
  283. // get filepicker info
  284. //
  285. $fpoptions = array();
  286. if ($maxfiles != 0 ) {
  287. if (empty($draftitemid)) {
  288. // no existing area info provided - let's use fresh new draft area
  289. require_once("$CFG->libdir/filelib.php");
  290. $this->setValue(array('itemid'=>file_get_unused_draft_itemid()));
  291. $draftitemid = $this->_values['itemid'];
  292. }
  293. $args = new stdClass();
  294. // need these three to filter repositories list
  295. $args->accepted_types = array('web_image');
  296. $args->return_types = $this->_options['return_types'];
  297. $args->context = $ctx;
  298. $args->env = 'filepicker';
  299. // advimage plugin
  300. $image_options = initialise_filepicker($args);
  301. $image_options->context = $ctx;
  302. $image_options->client_id = uniqid();
  303. $image_options->maxbytes = $this->_options['maxbytes'];
  304. $image_options->areamaxbytes = $this->_options['areamaxbytes'];
  305. $image_options->env = 'editor';
  306. $image_options->itemid = $draftitemid;
  307. // moodlemedia plugin
  308. $args->accepted_types = array('video', 'audio');
  309. $media_options = initialise_filepicker($args);
  310. $media_options->context = $ctx;
  311. $media_options->client_id = uniqid();
  312. $media_options->maxbytes = $this->_options['maxbytes'];
  313. $media_options->areamaxbytes = $this->_options['areamaxbytes'];
  314. $media_options->env = 'editor';
  315. $media_options->itemid = $draftitemid;
  316. // advlink plugin
  317. $args->accepted_types = '*';
  318. $link_options = initialise_filepicker($args);
  319. $link_options->context = $ctx;
  320. $link_options->client_id = uniqid();
  321. $link_options->maxbytes = $this->_options['maxbytes'];
  322. $link_options->areamaxbytes = $this->_options['areamaxbytes'];
  323. $link_options->env = 'editor';
  324. $link_options->itemid = $draftitemid;
  325. $fpoptions['image'] = $image_options;
  326. $fpoptions['media'] = $media_options;
  327. $fpoptions['link'] = $link_options;
  328. }
  329. //If editor is required and tinymce, then set required_tinymce option to initalize tinymce validation.
  330. if (($editor instanceof tinymce_texteditor) && !is_null($this->getAttribute('onchange'))) {
  331. $this->_options['required'] = true;
  332. }
  333. // print text area - TODO: add on-the-fly switching, size configuration, etc.
  334. $editor->use_editor($id, $this->_options, $fpoptions);
  335. $rows = empty($this->_attributes['rows']) ? 15 : $this->_attributes['rows'];
  336. $cols = empty($this->_attributes['cols']) ? 80 : $this->_attributes['cols'];
  337. //Apply editor validation if required field
  338. $editorrules = '';
  339. if (!is_null($this->getAttribute('onblur')) && !is_null($this->getAttribute('onchange'))) {
  340. $editorrules = ' onblur="'.htmlspecialchars($this->getAttribute('onblur')).'" onchange="'.htmlspecialchars($this->getAttribute('onchange')).'"';
  341. }
  342. $str .= '<div><textarea id="'.$id.'" name="'.$elname.'[text]" rows="'.$rows.'" cols="'.$cols.'" spellcheck="true"'.$editorrules.'>';
  343. $str .= s($text);
  344. $str .= '</textarea></div>';
  345. $str .= '<div>';
  346. if (count($formats)>1) {
  347. $str .= html_writer::label(get_string('format'), 'menu'. $elname. 'format', false, array('class' => 'accesshide'));
  348. $str .= html_writer::select($formats, $elname.'[format]', $format, false, array('id' => 'menu'. $elname. 'format'));
  349. } else {
  350. $keys = array_keys($formats);
  351. $str .= html_writer::empty_tag('input',
  352. array('name'=>$elname.'[format]', 'type'=> 'hidden', 'value' => array_pop($keys)));
  353. }
  354. $str .= '</div>';
  355. // during moodle installation, user area doesn't exist
  356. // so we need to disable filepicker here.
  357. if (!during_initial_install() && empty($CFG->adminsetuppending)) {
  358. // 0 means no files, -1 unlimited
  359. if ($maxfiles != 0 ) {
  360. $str .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $elname.'[itemid]',
  361. 'value' => $draftitemid));
  362. // used by non js editor only
  363. $editorurl = new moodle_url("$CFG->wwwroot/repository/draftfiles_manager.php", array(
  364. 'action'=>'browse',
  365. 'env'=>'editor',
  366. 'itemid'=>$draftitemid,
  367. 'subdirs'=>$subdirs,
  368. 'maxbytes'=>$maxbytes,
  369. 'areamaxbytes' => $areamaxbytes,
  370. 'maxfiles'=>$maxfiles,
  371. 'ctx_id'=>$ctx->id,
  372. 'course'=>$PAGE->course->id,
  373. 'sesskey'=>sesskey(),
  374. ));
  375. $str .= '<noscript>';
  376. $str .= "<div><object type='text/html' data='$editorurl' height='160' width='600' style='border:1px solid #000'></object></div>";
  377. $str .= '</noscript>';
  378. }
  379. }
  380. $str .= '</div>';
  381. return $str;
  382. }
  383. /**
  384. * What to display when element is frozen.
  385. *
  386. * @return empty string
  387. */
  388. function getFrozenHtml() {
  389. return '';
  390. }
  391. }