canvas_link_migrator 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 814327ff4502ff2b1187f0b817659cff573bb272ee7e85ae32685297f985ce55
4
- data.tar.gz: e8fa4255d9200988f052ddc9b6a4087b72709ce5443c9bbff4558279be38c4c6
3
+ metadata.gz: 989d0e7044ece5d052b909fa121de7f205906c733908a8dcf4a26d619cf67caf
4
+ data.tar.gz: a065d7f5ad6ad400cbd7cf448f5d42c5b69d400d9123837d2517950059d4a70e
5
5
  SHA512:
6
- metadata.gz: fc23256c7587decc42dfe9b5677f6299c7ba31cc4aa14e2bda8aca60233ba5ffdc143b205419f4d9fd101b13a52e54a2de896dbd1f038a3d25a44e7d631f54cf
7
- data.tar.gz: fd8ac04adf9829f958297818be79bff39910259cb9e8bb233689b117deb22cbce21df0c875c8d756e9dfa5c4dafb1ab4b5aaba717cfb10aa1a22d8b9574b52a5
6
+ metadata.gz: 50b673e7a91c0f345455c0ef0027b9e05a84c973f35d75f5659d336dfb70a3385d04d3360bead41b16a5101e3f8ee5e054f881cab88ac3f7c3ec0d5387cb7c6c
7
+ data.tar.gz: 8519365222facd8c05af020e7c6734db5c61e386cfd1fd0097f1a0815924c2c622929c217bfa4772d37fcd3acadd118019672cd9958ad76951512acd4bd8c4ba
@@ -18,9 +18,14 @@
18
18
  # with this program. If not, see <http://www.gnu.org/licenses/>.
19
19
 
20
20
  require "active_support/core_ext/object"
21
+ require "rack"
21
22
 
22
23
  module CanvasLinkMigrator
23
24
  class LinkResolver
25
+ attr_accessor :migration_id_converter
26
+
27
+ delegate :context_path, :attachment_path_id_lookup, to: :migration_id_converter
28
+
24
29
  def initialize(migration_id_converter)
25
30
  @migration_id_converter = migration_id_converter
26
31
  end
@@ -35,8 +40,8 @@ module CanvasLinkMigrator
35
40
  end
36
41
  end
37
42
 
38
- def context_path
39
- @migration_id_converter.context_path
43
+ def attachment_path_id_lookup_lower
44
+ @attachment_path_id_lookup_lower ||= attachment_path_id_lookup&.transform_keys(&:downcase)
40
45
  end
41
46
 
42
47
  # finds the :new_value to use to replace the placeholder
@@ -150,13 +155,13 @@ module CanvasLinkMigrator
150
155
  # This is for backward-compatibility: canvas attachment filenames are escaped
151
156
  # with '+' for spaces and older exports have files with that instead of %20
152
157
  alt_rel_path = rel_path.tr("+", " ")
153
- if @migration_id_converter.attachment_path_id_lookup
154
- mig_id ||= @migration_id_converter.attachment_path_id_lookup[rel_path]
155
- mig_id ||= @migration_id_converter.attachment_path_id_lookup[alt_rel_path]
158
+ if attachment_path_id_lookup
159
+ mig_id ||= attachment_path_id_lookup[rel_path]
160
+ mig_id ||= attachment_path_id_lookup[alt_rel_path]
156
161
  end
157
- if !mig_id && @migration_id_converter.attachment_path_id_lookup_lower
158
- mig_id ||= @migration_id_converter.attachment_path_id_lookup_lower[rel_path.downcase]
159
- mig_id ||= @migration_id_converter.attachment_path_id_lookup_lower[alt_rel_path.downcase]
162
+ if !mig_id && attachment_path_id_lookup_lower
163
+ mig_id ||= attachment_path_id_lookup_lower[rel_path.downcase]
164
+ mig_id ||= attachment_path_id_lookup_lower[alt_rel_path.downcase]
160
165
  end
161
166
 
162
167
  # This md5 comparison is here to handle faulty cartridges with the migration_id equivalent of an empty string
@@ -182,7 +187,7 @@ module CanvasLinkMigrator
182
187
  while new_url.nil? && !rel_path_parts.empty?
183
188
  sub_path = File.join(rel_path_parts)
184
189
  if (file = find_file_in_context(sub_path))
185
- new_url = "#{context_path}/files/#{file.id}"
190
+ new_url = "#{context_path}/files/#{file["id"]}"
186
191
  # support other params in the query string, that were exported from the
187
192
  # original path components and query string. see
188
193
  # CCHelper::file_query_string
@@ -219,13 +224,13 @@ module CanvasLinkMigrator
219
224
 
220
225
  def resolve_media_comment_data(node, rel_path)
221
226
  if (file = find_file_in_context(rel_path[/^[^?]+/])) # strip query string for this search
222
- media_id = (file.media_object&.media_id || file.media_entry_id)
227
+ media_id = file.try(:media_object)&.media_id || file["media_entry_id"]
223
228
  if media_id && media_id != "maybe"
224
229
  if ["iframe", "source"].include?(node.name)
225
230
  node["data-media-id"] = media_id
226
231
  if node["data-is-media-attachment"]
227
232
  node.delete("data-is-media-attachment")
228
- return media_attachment_iframe_url(file.id, node["data-media-type"])
233
+ return media_attachment_iframe_url(file["id"], node["data-media-type"])
229
234
  else
230
235
  return media_iframe_url(media_id, node["data-media-type"])
231
236
  end
@@ -52,9 +52,9 @@ module CanvasLinkMigrator
52
52
  migration_data["destination_hosts"]
53
53
  end
54
54
 
55
- def attachment_path_id_lookup; end
56
-
57
- def attachment_path_id_lookup_lower; end
55
+ def attachment_path_id_lookup
56
+ migration_data["attachment_path_id_lookup"]
57
+ end
58
58
 
59
59
  def root_folder_name
60
60
  migration_data["destination_root_folder"]
@@ -102,5 +102,9 @@ module CanvasLinkMigrator
102
102
  # we'll check both here
103
103
  convert_announcement_migration_id(migration_id) if type == "discussion_topics"
104
104
  end
105
+
106
+ def lookup_attachment_by_migration_id(migration_id)
107
+ resources.dig("files", migration_id, "destination")
108
+ end
105
109
  end
106
110
  end
@@ -56,62 +56,55 @@ describe CanvasLinkMigrator::ImportedHtmlConverter do
56
56
  end
57
57
  end
58
58
 
59
- # it "finds an attachment by migration id" do
60
- # test_string = %{<p>This is an image: <br /><img src="%24CANVAS_OBJECT_REFERENCE%24/attachments/F" alt=":(" /></p>}
61
- # expect(@converter.convert_exported_html(test_string)).to eq([%{<p>This is an image: <br><img src="#{@path}files/6/preview" alt=":("></p>}, nil])
62
- # end
63
-
64
- # it "finds an attachment by path" do
65
- # test_string = %{<p>This is an image: <br /><img src="%24IMS_CC_FILEBASE%24/test.png" alt=":(" /></p>}
66
-
67
- # # if there isn't a path->migration id map it'll be a relative course file path
68
- # expect(@converter.convert_exported_html(test_string)).to eq %{<p>This is an image: <br><img src="#{@path}file_contents/course%20files/test.png" alt=":("></p>}
69
-
70
- # @migration.attachment_path_id_lookup = { "test.png" => att.migration_id }
71
- # expect(@converter.convert_exported_html(test_string)).to eq %{<p>This is an image: <br><img src="#{@path}files/#{att.id}/preview" alt=":("></p>}
72
- # end
59
+ it "finds an attachment by migration id" do
60
+ test_string = %{<p>This is an image: <br /><img src="%24CANVAS_OBJECT_REFERENCE%24/attachments/F" alt=":(" /></p>}
61
+ expect(@converter.convert_exported_html(test_string)).to eq([%{<p>This is an image: <br><img src="#{@path}files/6/preview" alt=":("></p>}, nil])
62
+ end
73
63
 
74
- # it "finds an attachment by a path with a space" do
75
- # att = make_test_att
76
- # @migration.attachment_path_id_lookup = { "subfolder/with a space/test.png" => att.migration_id }
64
+ it "finds an attachment by path" do
65
+ test_string = %{<p>This is an image: <br /><img src="%24IMS_CC_FILEBASE%24/test.png" alt=":(" /></p>}
77
66
 
78
- # test_string = %(<img src="subfolder/with%20a%20space/test.png" alt="nope" />)
79
- # expect(@converter.convert_exported_html(test_string)).to eq %(<img src="#{@path}files/#{att.id}/preview" alt="nope">)
67
+ # if there isn't a path->migration id map it'll be a relative course file path
68
+ expect(@converter.link_resolver).to receive(:attachment_path_id_lookup).exactly(4).times.and_return({})
69
+ html, bad_links = @converter.convert_exported_html(test_string)
70
+ expect(html).to eq %{<p>This is an image: <br><img src="#{@path}file_contents/course%20files/test.png" alt=":("></p>}
71
+ expect(bad_links[0]).to include({ link_type: :file, missing_url: "/courses/2/file_contents/course%20files/test.png" })
80
72
 
81
- # test_string = %(<img src="subfolder/with+a+space/test.png" alt="nope" />)
82
- # expect(@converter.convert_exported_html(test_string)).to eq %(<img src="#{@path}files/#{att.id}/preview" alt="nope">)
83
- # end
73
+ expect(@converter.link_resolver).to receive(:attachment_path_id_lookup).twice.and_call_original
74
+ expect(@converter.convert_exported_html(test_string)).to eq([%{<p>This is an image: <br><img src="#{@path}files/5/preview" alt=":("></p>}, nil])
75
+ end
84
76
 
85
- # it "finds an attachment even if the link has an extraneous folder" do
86
- # att = make_test_att
87
- # @migration.attachment_path_id_lookup = { "subfolder/test.png" => att.migration_id }
77
+ it "finds an attachment by a path with a space" do
78
+ test_string = %(<img src="subfolder/with%20a%20space/test.png" alt="nope" />)
79
+ expect(@converter.convert_exported_html(test_string)).to eq([%(<img src="#{@path}files/6/preview" alt="nope">), nil])
88
80
 
89
- # test_string = %(<img src="anotherfolder/subfolder/test.png" alt="nope" />)
90
- # expect(@converter.convert_exported_html(test_string)).to eq %(<img src="#{@path}files/#{att.id}/preview" alt="nope">)
91
- # end
81
+ test_string = %(<img src="subfolder/with+a+space/test.png" alt="nope" />)
82
+ expect(@converter.convert_exported_html(test_string)).to eq([%(<img src="#{@path}files/6/preview" alt="nope">), nil])
83
+ end
92
84
 
93
- # it "finds an attachment by path if capitalization is different" do
94
- # att = make_test_att
95
- # @migration.attachment_path_id_lookup = { "subfolder/withCapital/test.png" => "wrong!" }
96
- # @migration.attachment_path_id_lookup_lower = { "subfolder/withcapital/test.png" => att.migration_id }
85
+ it "finds an attachment even if the link has an extraneous folder" do
86
+ test_string = %(<img src="anotherfolder/subfolder/test.png" alt="nope" />)
87
+ expect(@converter.convert_exported_html(test_string)).to eq([%(<img src="#{@path}files/7/preview" alt="nope">), nil])
88
+ end
97
89
 
98
- # test_string = %(<img src="subfolder/WithCapital/TEST.png" alt="nope" />)
99
- # expect(@converter.convert_exported_html(test_string)).to eq %(<img src="#{@path}files/#{att.id}/preview" alt="nope">)
100
- # end
90
+ it "finds an attachment by path if capitalization is different" do
91
+ expect(@converter.link_resolver).to receive(:attachment_path_id_lookup).twice.and_return({ "subfolder/withCapital/test.png" => "wrong!" })
92
+ expect(@converter.link_resolver).to receive(:attachment_path_id_lookup).twice.and_return({ "subfolder/withcapital/test.png" => "F" })
101
93
 
102
- # it "finds an attachment with query params" do
103
- # att = make_test_att
104
- # @migration.attachment_path_id_lookup = { "test.png" => att.migration_id }
94
+ test_string = %(<img src="subfolder/WithCapital/TEST.png" alt="nope" />)
95
+ expect(@converter.convert_exported_html(test_string)).to eq([%(<img src="#{@path}files/6/preview" alt="nope">), nil])
96
+ end
105
97
 
106
- # test_string = %(<img src="%24IMS_CC_FILEBASE%24/test.png?canvas_customaction=1&canvas_qs_customparam=1" alt="nope" />)
107
- # expect(@converter.convert_exported_html(test_string)).to eq %(<img src="#{@path}files/#{att.id}/customaction?customparam=1" alt="nope">)
98
+ it "finds an attachment with query params" do
99
+ test_string = %(<img src="%24IMS_CC_FILEBASE%24/test.png?canvas_customaction=1&canvas_qs_customparam=1" alt="nope" />)
100
+ expect(@converter.convert_exported_html(test_string)).to eq([%(<img src="#{@path}files/5/customaction?customparam=1" alt="nope">), nil])
108
101
 
109
- # test_string = %(<img src="%24IMS_CC_FILEBASE%24/test.png?canvas_qs_customparam2=3" alt="nope" />)
110
- # expect(@converter.convert_exported_html(test_string)).to eq %(<img src="#{@path}files/#{att.id}/preview?customparam2=3" alt="nope">)
102
+ test_string = %(<img src="%24IMS_CC_FILEBASE%24/test.png?canvas_qs_customparam2=3" alt="nope" />)
103
+ expect(@converter.convert_exported_html(test_string)).to eq([%(<img src="#{@path}files/5/preview?customparam2=3" alt="nope">), nil])
111
104
 
112
- # test_string = %(<img src="%24IMS_CC_FILEBASE%24/test.png?notarelevantparam" alt="nope" />)
113
- # expect(@converter.convert_exported_html(test_string)).to eq %(<img src="#{@path}files/#{att.id}/preview" alt="nope">)
114
- # end
105
+ test_string = %(<img src="%24IMS_CC_FILEBASE%24/test.png?notarelevantparam" alt="nope" />)
106
+ expect(@converter.convert_exported_html(test_string)).to eq([%(<img src="#{@path}files/5/preview" alt="nope">), nil])
107
+ end
115
108
  end
116
109
 
117
110
  it "converts picture source srcsets" do
@@ -81,4 +81,10 @@ describe CanvasLinkMigrator::LinkResolver do
81
81
  expect(link[:new_value]).to eq("/courses/2/assignments/12#fie")
82
82
  end
83
83
  end
84
+
85
+ describe "attachment_path_id_lookup_lower" do
86
+ it "shows correct lowercase paths" do
87
+ expect(resolver.attachment_path_id_lookup_lower).to include({ "subfolder/withcapital/test.png" => "migration_id!" })
88
+ end
89
+ end
84
90
  end
@@ -1,4 +1,10 @@
1
1
  {
2
+ "attachment_path_id_lookup": {
3
+ "subfolder/test.png": "G",
4
+ "subfolder/with a space/test.png": "F",
5
+ "subfolder/withCapital/test.png": "migration_id!",
6
+ "test.png": "E"
7
+ },
2
8
  "contains_migration_ids": true,
3
9
  "destination_course": "2",
4
10
  "destination_hosts": [
@@ -57,6 +63,16 @@
57
63
  "id": "4",
58
64
  "media_entry_id": "m-stuff"
59
65
  }
66
+ },
67
+ "G": {
68
+ "destination": {
69
+ "id": "7",
70
+ "media_entry_id": "m-stuff"
71
+ },
72
+ "source": {
73
+ "id": "2",
74
+ "media_entry_id": "m-stuff"
75
+ }
60
76
  }
61
77
  },
62
78
  "module_items": {
@@ -92,12 +108,6 @@
92
108
  }
93
109
  }
94
110
  },
95
- "file_tree": {
96
- "folder 1": {
97
- "id": "1",
98
- "sub_folders": {}
99
- }
100
- },
101
111
  "source_course": "1",
102
112
  "source_host": "pineapple.edu"
103
- }
113
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canvas_link_migrator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mysti Lilla
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-07-31 00:00:00.000000000 Z
12
+ date: 2023-08-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -39,6 +39,20 @@ dependencies:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rack
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
42
56
  - !ruby/object:Gem::Dependency
43
57
  name: bundler
44
58
  requirement: !ruby/object:Gem::Requirement