diff --git a/lib/tests/weblib_test.php b/lib/tests/weblib_test.php index 87185348148..1cdd34b6db0 100644 --- a/lib/tests/weblib_test.php +++ b/lib/tests/weblib_test.php @@ -492,4 +492,43 @@ class core_weblib_testcase extends advanced_testcase { $this->assertEquals(DEBUG_NONE, $CFG->debug); $this->assertFalse($CFG->debugdeveloper); } + + public function test_strip_pluginfile_content() { + $source = << +External link 2:Moodle +Internal link 1:Moodle +Internal link 2:Moodle +Anchor link 1:Link text +Anchor link 2:Link text +Anchor + ext. img:Moodle +Ext. anchor + img:Moodle +SOURCE; + $expected = << +External link 2:Moodle +Internal link 1: +Internal link 2: +Anchor link 1:Link text +Anchor link 2:Link text +Anchor + ext. img: +Ext. anchor + img:Moodle +EXPECTED; + $this->assertSame($expected, strip_pluginfile_content($source)); + } + } diff --git a/lib/weblib.php b/lib/weblib.php index 680d091de78..ef395228b57 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -1523,6 +1523,25 @@ function format_module_intro($module, $activity, $cmid, $filter=true) { return trim(format_text($intro, $activity->introformat, $options, null)); } +/** + * Removes the usage of Moodle files from a text. + * + * In some rare cases we need to re-use a text that already has embedded links + * to some files hosted within Moodle. But the new area in which we will push + * this content does not support files... therefore we need to remove those files. + * + * @param string $source The text + * @return string The stripped text + */ +function strip_pluginfile_content($source) { + $baseurl = '@@PLUGINFILE@@'; + // Looking for something like < .* "@@pluginfile@@.*" .* > + $pattern = '$<[^<>]+["\']' . $baseurl . '[^"\']*["\'][^<>]*>$'; + $stripped = preg_replace($pattern, '', $source); + // Use purify html to rebalence potentially mismatched tags and generally cleanup. + return purify_html($stripped); +} + /** * Legacy function, used for cleaning of old forum and glossary text only. * diff --git a/mod/assign/feedback/comments/locallib.php b/mod/assign/feedback/comments/locallib.php index 1f043cb5a5a..96dde23d982 100644 --- a/mod/assign/feedback/comments/locallib.php +++ b/mod/assign/feedback/comments/locallib.php @@ -214,23 +214,6 @@ class assign_feedback_comments extends assign_feedback_plugin { $mform->disabledIf('assignfeedback_comments_commentinline', 'assignfeedback_comments_enabled', 'notchecked'); } - /** - * A student submission may contain image tags that refer to images stored - * in the file area for the submission. We cannot allow these links to be copied to - * the feedback text fields, so we must strip them from the content. - * - * @param string $source The submission text - * @return string The stripped text - */ - protected function strip_moodle_content($source) { - $baseurl = '@@PLUGINFILE@@'; - // Looking for something like < .* "@@pluginfile@@.*" .* > - $pattern = '$<[^<>]+["\']' . $baseurl . '[^"\']*["\'][^<>]*>$'; - $stripped = preg_replace($pattern, '', $source); - // Use purify html to rebalence potentially mismatched tags and generally cleanup. - return purify_html($stripped); - } - /** * Convert the text from any submission plugin that has an editor field to * a format suitable for inserting in the feedback text field. @@ -247,7 +230,7 @@ class assign_feedback_comments extends assign_feedback_plugin { $fields = $plugin->get_editor_fields(); if ($plugin->is_enabled() && $plugin->is_visible() && !empty($fields)) { foreach ($fields as $key => $description) { - $rawtext = $this->strip_moodle_content($plugin->get_editor_text($key, $submission->id)); + $rawtext = strip_pluginfile_content($plugin->get_editor_text($key, $submission->id)); $newformat = $plugin->get_editor_format($key, $submission->id); diff --git a/mod/assign/locallib.php b/mod/assign/locallib.php index 71ce279329e..2d5acfdfe37 100644 --- a/mod/assign/locallib.php +++ b/mod/assign/locallib.php @@ -831,30 +831,37 @@ class assign { $event = new stdClass(); $params = array('modulename'=>'assign', 'instance'=>$instance->id); - $event->id = $DB->get_field('event', - 'id', - $params); + $event->id = $DB->get_field('event', 'id', $params); + $event->name = $instance->name; + $event->timestart = $instance->duedate; + + // Convert the links to pluginfile. It is a bit hacky but at this stage the files + // might not have been saved in the module area yet. + $intro = $instance->intro; + if ($draftid = file_get_submitted_draft_itemid('introeditor')) { + $intro = file_rewrite_urls_to_pluginfile($intro, $draftid); + } + + // We need to remove the links to files as the calendar is not ready + // to support module events with file areas. + $intro = strip_pluginfile_content($intro); + $event->description = array( + 'text' => $intro, + 'format' => $instance->introformat + ); if ($event->id) { - $event->name = $instance->name; - $event->description = format_module_intro('assign', $instance, $coursemoduleid); - $event->timestart = $instance->duedate; - $calendarevent = calendar_event::load($event->id); $calendarevent->update($event); } else { - $event = new stdClass(); - $event->name = $instance->name; - $event->description = format_module_intro('assign', $instance, $coursemoduleid); + unset($event->id); $event->courseid = $instance->course; $event->groupid = 0; $event->userid = 0; $event->modulename = 'assign'; $event->instance = $instance->id; $event->eventtype = 'due'; - $event->timestart = $instance->duedate; $event->timeduration = 0; - calendar_event::create($event); } } else { diff --git a/mod/assign/tests/locallib_test.php b/mod/assign/tests/locallib_test.php index 0e703ae6237..77c08975afe 100644 --- a/mod/assign/tests/locallib_test.php +++ b/mod/assign/tests/locallib_test.php @@ -296,15 +296,45 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase { public function test_update_calendar() { global $DB; - $now = time(); $this->setUser($this->editingteachers[0]); - $assign = $this->create_instance(array('duedate'=>$now)); + $userctx = context_user::instance($this->editingteachers[0]->id)->id; + + // Hack to pretend that there was an editor involved. We need both $_POST and $_REQUEST, and a sesskey. + $draftid = file_get_unused_draft_itemid(); + $_REQUEST['introeditor'] = $draftid; + $_POST['introeditor'] = $draftid; + $_POST['sesskey'] = sesskey(); + + // Write links to a draft area. + $fakearealink1 = file_rewrite_pluginfile_urls('link', 'draftfile.php', $userctx, + 'user', 'draft', $draftid); + $fakearealink2 = file_rewrite_pluginfile_urls('new', 'draftfile.php', $userctx, + 'user', 'draft', $draftid); + + // Create a new assignment with links to a draft area. + $now = time(); + $assign = $this->create_instance(array( + 'duedate' => $now, + 'intro' => $fakearealink1, + 'introformat' => FORMAT_HTML + )); // See if there is an event in the calendar. $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id); - $id = $DB->get_field('event', 'id', $params); + $event = $DB->get_record('event', $params); + $this->assertNotEmpty($event); + $this->assertSame('link', $event->description); // The pluginfile links are removed. - $this->assertEquals(false, empty($id)); + // Make sure the same works when updating the assignment. + $instance = $assign->get_instance(); + $instance->instance = $instance->id; + $instance->intro = $fakearealink2; + $instance->introformat = FORMAT_HTML; + $assign->update_instance($instance); + $params = array('modulename' => 'assign', 'instance' => $assign->get_instance()->id); + $event = $DB->get_record('event', $params); + $this->assertNotEmpty($event); + $this->assertSame('new', $event->description); // The pluginfile links are removed. } public function test_update_instance() {