diff --git a/lib/cc/new_quizzes_links_replacer.rb b/lib/cc/new_quizzes_links_replacer.rb new file mode 100644 index 00000000000..defc67ae14a --- /dev/null +++ b/lib/cc/new_quizzes_links_replacer.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +# +# Copyright (C) 2011 - present Instructure, Inc. +# +# This file is part of Canvas. +# +# Canvas is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, version 3 of the License. +# +# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along +# with this program. If not, see . +# + +require "nokogiri" + +module CC + class NewQuizzesLinksReplacer + def initialize(manifest) + @course = manifest.exporter.course + @user = manifest.exporter.user + @manifest = manifest + end + + def replace_links(xml) + doc = Nokogiri::XML(xml || "") + doc.search("*").each do |node| + next unless node.node_name == "mattext" && node["texttype"] == "text/html" + + node.content = html_exporter.html_content(node.content) + end + + doc.to_xml + end + + def html_exporter + @html_exporter ||= CCHelper::HtmlContentExporter.new(@course, + @user, + for_course_copy: false, + key_generator: @manifest) + end + end +end diff --git a/lib/cc/qti/new_quizzes_generator.rb b/lib/cc/qti/new_quizzes_generator.rb index fb4b83a8c5c..24210f59411 100644 --- a/lib/cc/qti/new_quizzes_generator.rb +++ b/lib/cc/qti/new_quizzes_generator.rb @@ -43,7 +43,13 @@ module CC dest_dir = File.join(export_dir, file_dir) FileUtils.mkdir_p(dest_dir) - File.binwrite(File.join(dest_dir, file_name), File.read(f)) + file_content = File.read(f) + + if file_name.end_with?(".xml", ".qti") + file_content = links_replacer.replace_links(file_content) + end + + File.binwrite(File.join(dest_dir, file_name), file_content) file_path end end @@ -98,6 +104,10 @@ module CC private + def links_replacer + @links_replacer ||= CC::NewQuizzesLinksReplacer.new(@manifest) + end + def uploaded_media_resources(file_paths) file_paths.each do |file_path| file_uuid = file_path.split("/").last diff --git a/spec/lib/cc/new_quizzes_links_replacer_spec.rb b/spec/lib/cc/new_quizzes_links_replacer_spec.rb new file mode 100644 index 00000000000..32c93b8b260 --- /dev/null +++ b/spec/lib/cc/new_quizzes_links_replacer_spec.rb @@ -0,0 +1,178 @@ +# frozen_string_literal: true + +# Copyright (C) 2011 - present Instructure, Inc. +# +# This file is part of Canvas. +# +# Canvas is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, version 3 of the License. +# +# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along +# with this program. If not, see . + +require "nokogiri" + +describe CC::NewQuizzesLinksReplacer do + describe "#replace_links" do + subject { described_class.new(@manifest) } + + before do + @course = course_model + @content_export = @course.content_exports.build(global_identifiers: true, + export_type: ContentExport::COMMON_CARTRIDGE, + user: @user) + @exporter = CC::CCExporter.new(@content_export, course: @course, user: @user) + @manifest = CC::Manifest.new(@exporter) + end + + context "when the xml contains file links" do + before do + folder = folder_model(name: "Uploaded Media", context: @course) + @attachment = attachment_model(display_name: "aws_opensearch-2.png", + context: @course, + folder:, + uploaded_data: stub_file_data("aws_opensearch-2.png", "...", "image/png")) + end + + let(:xml) do + <<~XML + + + +
+ + + + <div><p>insert question here</p> + <p><img src="/courses/#{@course.id}/files/#{@attachment.id}/preview" alt="aws_opensearch-2.png"></p></div> + + + +
+
+
+ XML + end + + it "replaces course file links" do + expected_xml = <<~XML + + + +
+ + + + <div><p>insert question here</p> + <p><img src="$IMS-CC-FILEBASE$/Uploaded%20Media/aws_opensearch-2.png" alt="aws_opensearch-2.png"></p></div> + + + +
+
+
+ XML + + expect(subject.replace_links(xml)).to eq(expected_xml) + end + end + + context "when the xml contains wiki page links" do + before do + @page = @course.wiki_pages.create(title: "My wiki page") + end + + let(:xml) do + <<~XML + + + +
+ + + + <div><p><a title="My wiki page" href="/courses/#{@course.id}/pages/my-wiki-page" data-course-type="wikiPages" data-published="false">My wiki page</a></p></div> + + + +
+
+
+ XML + end + + it "replaces wiki page links" do + expected_xml = <<~XML + + + +
+ + + + <div><p><a title="My wiki page" href="$WIKI_REFERENCE$/pages/#{CC::CCHelper.create_key(@page, global: true)}" data-course-type="wikiPages" data-published="false">My wiki page</a></p></div> + + + +
+
+
+ XML + + expect(subject.replace_links(xml)).to eq(expected_xml) + end + + context "when the xml contains internal links" do + before do + @assignment = @course.assignments.create!(name: "my quiz") + end + + let(:xml) do + <<~XML + + + +
+ + + + <div><p><a title="my quiz" href="/courses/#{@course.id}/assignments/#{@assignment.id}" data-course-type="assignments" data-published="false">my quiz</a></p></div> + + + +
+
+
+ XML + end + + it "replaces internal links" do + expected_xml = <<~XML + + + +
+ + + + <div><p><a title="my quiz" href="$CANVAS_OBJECT_REFERENCE$/assignments/#{CC::CCHelper.create_key(@assignment, global: true)}" data-course-type="assignments" data-published="false">my quiz</a></p></div> + + + +
+
+
+ XML + + expect(subject.replace_links(xml)).to eq(expected_xml) + end + end + end + end +end