From de978747a89fa887a7b853ca2ec00cdeee2840dd Mon Sep 17 00:00:00 2001 From: Nadav Kavalerchik Date: Wed, 24 Jul 2019 10:37:36 +0300 Subject: [PATCH] MDL-61674 usertours: Allow rich text (atto) editing of step content --- .../classes/local/forms/editstep.php | 13 ++++- .../classes/local/table/step_list.php | 7 ++- admin/tool/usertours/classes/output/step.php | 11 +++- admin/tool/usertours/classes/step.php | 56 ++++++++++++++++++- admin/tool/usertours/db/install.xml | 3 +- admin/tool/usertours/db/upgrade.php | 14 +++++ admin/tool/usertours/lib.php | 27 +++++++++ admin/tool/usertours/version.php | 2 +- 8 files changed, 124 insertions(+), 9 deletions(-) diff --git a/admin/tool/usertours/classes/local/forms/editstep.php b/admin/tool/usertours/classes/local/forms/editstep.php index 83d5665a7d8..48ec1f0c2e5 100644 --- a/admin/tool/usertours/classes/local/forms/editstep.php +++ b/admin/tool/usertours/classes/local/forms/editstep.php @@ -56,6 +56,8 @@ class editstep extends \moodleform { * Form definition. */ public function definition() { + global $CFG; + $mform = $this->_form; $mform->addElement('header', 'heading_target', get_string('target_heading', 'tool_usertours')); @@ -79,9 +81,16 @@ class editstep extends \moodleform { $mform->setType('title', PARAM_TEXT); $mform->addHelpButton('title', 'title', 'tool_usertours'); - $mform->addElement('textarea', 'content', get_string('content', 'tool_usertours')); + $editoroptions = [ + 'subdirs' => 1, + 'maxbytes' => $CFG->maxbytes, + 'maxfiles' => EDITOR_UNLIMITED_FILES, + 'changeformat' => 1, + 'trusttext' => true + ]; + $mform->addElement('editor', 'content', get_string('content', 'tool_usertours'), null, $editoroptions); $mform->addRule('content', get_string('required'), 'required', null, 'client'); - $mform->setType('content', PARAM_RAW); + $mform->setType('content', PARAM_RAW); // No XSS prevention here, users must be trusted. $mform->addHelpButton('content', 'content', 'tool_usertours'); // Add the step configuration. diff --git a/admin/tool/usertours/classes/local/table/step_list.php b/admin/tool/usertours/classes/local/table/step_list.php index a37127f112a..8da8be90f8e 100644 --- a/admin/tool/usertours/classes/local/table/step_list.php +++ b/admin/tool/usertours/classes/local/table/step_list.php @@ -96,7 +96,12 @@ class step_list extends \flexible_table { * @return string */ protected function col_content(step $step) { - return format_text(step::get_string_from_input($step->get_content()), FORMAT_HTML); + $content = $step->get_content(); + $systemcontext = \context_system::instance(); + $content = file_rewrite_pluginfile_urls($content, 'pluginfile.php', $systemcontext->id, + 'tool_usertours', 'stepcontent', $step->get_id()); + + return format_text(step::get_string_from_input($content), $step->get_contentformat()); } /** diff --git a/admin/tool/usertours/classes/output/step.php b/admin/tool/usertours/classes/output/step.php index 772edd0b994..8aecf7c06dc 100644 --- a/admin/tool/usertours/classes/output/step.php +++ b/admin/tool/usertours/classes/output/step.php @@ -26,6 +26,8 @@ namespace tool_usertours\output; defined('MOODLE_INTERNAL') || die(); +require_once($CFG->libdir . "/filelib.php"); + use tool_usertours\step as stepsource; /** @@ -60,6 +62,11 @@ class step implements \renderable { global $PAGE; $step = $this->step; + $content = $step->get_content(); + $systemcontext = \context_system::instance(); + $content = file_rewrite_pluginfile_urls($content, 'pluginfile.php', $systemcontext->id, + 'tool_usertours', 'stepcontent', $step->get_id()); + $result = (object) [ 'stepid' => $step->get_id(), 'title' => external_format_text( @@ -69,8 +76,8 @@ class step implements \renderable { 'tool_usertours' )[0], 'content' => external_format_text( - stepsource::get_string_from_input($step->get_content()), - FORMAT_HTML, + stepsource::get_string_from_input($content), + $step->get_contentformat(), $PAGE->context->id, 'tool_usertours' )[0], diff --git a/admin/tool/usertours/classes/step.php b/admin/tool/usertours/classes/step.php index 4819ac08029..754377b0027 100644 --- a/admin/tool/usertours/classes/step.php +++ b/admin/tool/usertours/classes/step.php @@ -59,6 +59,11 @@ class step { */ protected $content; + /** + * @var int $contentformat The content format: FORMAT_MOODLE/FORMAT_HTML/FORMAT_PLAIN/FORMAT_MARKDOWN. + */ + protected $contentformat; + /** * @var int $targettype The type of target. */ @@ -147,6 +152,7 @@ class step { $this->title = $record->title; $this->content = $record->content; } + $this->contentformat = isset($record->contentformat) ? $record->contentformat : 1; $this->targettype = $record->targettype; $this->targetvalue = $record->targetvalue; $this->sortorder = $record->sortorder; @@ -222,6 +228,15 @@ class step { return $this; } + /** + * Get the content format of the step. + * + * @return int + */ + public function get_contentformat(): int { + return $this->contentformat; + } + /** * Get the body content of the step. * @@ -235,10 +250,12 @@ class step { * Set the content value for this step. * * @param string $value The new content to use. + * @param int $format The new format to use: FORMAT_MOODLE/FORMAT_HTML/FORMAT_PLAIN/FORMAT_MARKDOWN. * @return $this */ - public function set_content($value) { + public function set_content($value, $format = FORMAT_HTML) { $this->content = clean_text($value); + $this->contentformat = $format; $this->dirty = true; return $this; @@ -443,6 +460,7 @@ class step { 'tourid' => $this->tourid, 'title' => $this->title, 'content' => $this->content, + 'contentformat' => $this->contentformat, 'targettype' => $this->targettype, 'targetvalue' => $this->targetvalue, 'sortorder' => $this->sortorder, @@ -486,6 +504,23 @@ class step { $this->get_tour()->reset_step_sortorder(); } + $systemcontext = \context_system::instance(); + if ($draftid = file_get_submitted_draft_itemid('content')) { + // Take any files added to the stepcontent draft file area and + // convert them into the proper event description file area. Also + // parse the content text and replace the URLs to the draft files + // with the @@PLUGIN_FILE@@ placeholder to be persisted in the DB. + $this->content = file_save_draft_area_files( + $draftid, + $systemcontext->id, + 'tool_usertours', + 'stepcontent', + $this->id, + ['subdirs' => true], + $this->content + ); + $DB->set_field('tool_usertours_steps', 'content', $this->content, ['id' => $this->id]); + } $this->reload(); // Notify of a change to the step configuration. @@ -613,6 +648,23 @@ class step { $this->get_target()->prepare_data_for_form($data); } + // Prepare content for editing in a form 'editor' field type. + $draftitemid = file_get_submitted_draft_itemid('tool_usertours'); + $systemcontext = \context_system::instance(); + $data->content = [ + 'format' => $data->contentformat, + 'itemid' => $draftitemid, + 'text' => file_prepare_draft_area( + $draftitemid, + $systemcontext->id, + 'tool_usertours', + 'stepcontent', + $this->id, + ['subdirs' => true], + $data->content + ), + ]; + return $data; } @@ -625,7 +677,7 @@ class step { */ public function handle_form_submission(local\forms\editstep &$mform, \stdClass $data) { $this->set_title($data->title); - $this->set_content($data->content); + $this->set_content($data->content['text'], $data->content['format']); $this->set_targettype($data->targettype); $this->set_targetvalue($this->get_target()->get_value_from_form($data)); diff --git a/admin/tool/usertours/db/install.xml b/admin/tool/usertours/db/install.xml index 72401e3db92..25f2de6faa6 100644 --- a/admin/tool/usertours/db/install.xml +++ b/admin/tool/usertours/db/install.xml @@ -1,5 +1,5 @@ - @@ -26,6 +26,7 @@ + diff --git a/admin/tool/usertours/db/upgrade.php b/admin/tool/usertours/db/upgrade.php index 40d814e75fe..b1873c8cd7e 100644 --- a/admin/tool/usertours/db/upgrade.php +++ b/admin/tool/usertours/db/upgrade.php @@ -114,5 +114,19 @@ function xmldb_tool_usertours_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2021100700, 'tool', 'usertours'); } + if ($oldversion < 2021101300) { + // Define field contentformat to be added to tool_usertours_steps. + $table = new xmldb_table('tool_usertours_steps'); + $field = new xmldb_field('contentformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '1', 'content'); + + // Conditionally launch add field contentformat. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Usertours savepoint reached. + upgrade_plugin_savepoint(true, 2021101300, 'tool', 'usertours'); + } + return true; } diff --git a/admin/tool/usertours/lib.php b/admin/tool/usertours/lib.php index 9c4c0777cf7..9d017968564 100644 --- a/admin/tool/usertours/lib.php +++ b/admin/tool/usertours/lib.php @@ -85,3 +85,30 @@ function tool_usertours_get_fontawesome_icon_map() { 'tool_usertours:t/filler' => 'fa-spacer', ]; } + + +/** + * Serves any files associated with the user tour content. + * + * @param stdClass $course Course object + * @param stdClass $cm Course module object + * @param context $context Context + * @param string $filearea File area for data privacy + * @param array $args Arguments + * @param bool $forcedownload If we are forcing the download + * @param array $options More options + * @return bool Returns false if we don't find a file. + */ +function tool_usertours_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = []): bool { + if ($context->contextlevel != CONTEXT_SYSTEM) { + return false; + } + + $fs = get_file_storage(); + $file = $fs->get_file($context->id, 'tool_usertours', $filearea, $args[0], '/', $args[1]); + if (!$file) { + return false; // No such file. + } + send_stored_file($file, null, 0, $forcedownload, $options); + return true; +} diff --git a/admin/tool/usertours/version.php b/admin/tool/usertours/version.php index cf35e046cc6..6c49cf6373e 100644 --- a/admin/tool/usertours/version.php +++ b/admin/tool/usertours/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021100700; // The current module version (Date: YYYYMMDDXX). +$plugin->version = 2021101300; // The current module version (Date: YYYYMMDDXX). $plugin->requires = 2021052500; // Requires this Moodle version. $plugin->component = 'tool_usertours'; // Full name of the plugin (used for diagnostics).