moodle2cc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. data/.gitignore +20 -0
  2. data/Gemfile +4 -0
  3. data/Guardfile +14 -0
  4. data/LICENSE +661 -0
  5. data/README.md +38 -0
  6. data/Rakefile +12 -0
  7. data/bin/moodle2cc +6 -0
  8. data/lib/moodle2cc.rb +60 -0
  9. data/lib/moodle2cc/canvas/.converter.rb.swo +0 -0
  10. data/lib/moodle2cc/canvas/.wiki.rb.swo +0 -0
  11. data/lib/moodle2cc/canvas/assessment.rb +109 -0
  12. data/lib/moodle2cc/canvas/assignment.rb +108 -0
  13. data/lib/moodle2cc/canvas/converter.rb +28 -0
  14. data/lib/moodle2cc/canvas/course.rb +145 -0
  15. data/lib/moodle2cc/canvas/discussion_topic.rb +64 -0
  16. data/lib/moodle2cc/canvas/label.rb +8 -0
  17. data/lib/moodle2cc/canvas/question.rb +468 -0
  18. data/lib/moodle2cc/canvas/question_bank.rb +54 -0
  19. data/lib/moodle2cc/canvas/resource.rb +16 -0
  20. data/lib/moodle2cc/canvas/templates/assignment.html.erb +9 -0
  21. data/lib/moodle2cc/canvas/templates/syllabus.html.erb +9 -0
  22. data/lib/moodle2cc/canvas/templates/wiki_content.html.erb +10 -0
  23. data/lib/moodle2cc/canvas/web_content.rb +10 -0
  24. data/lib/moodle2cc/canvas/web_link.rb +17 -0
  25. data/lib/moodle2cc/canvas/wiki.rb +25 -0
  26. data/lib/moodle2cc/cc/assessment.rb +25 -0
  27. data/lib/moodle2cc/cc/assignment.rb +66 -0
  28. data/lib/moodle2cc/cc/cc_helper.rb +282 -0
  29. data/lib/moodle2cc/cc/converter.rb +136 -0
  30. data/lib/moodle2cc/cc/course.rb +16 -0
  31. data/lib/moodle2cc/cc/discussion_topic.rb +53 -0
  32. data/lib/moodle2cc/cc/label.rb +6 -0
  33. data/lib/moodle2cc/cc/question.rb +23 -0
  34. data/lib/moodle2cc/cc/resource.rb +30 -0
  35. data/lib/moodle2cc/cc/templates/assignment.html.erb +9 -0
  36. data/lib/moodle2cc/cc/templates/syllabus.html.erb +9 -0
  37. data/lib/moodle2cc/cc/templates/wiki_content.html.erb +10 -0
  38. data/lib/moodle2cc/cc/web_content.rb +40 -0
  39. data/lib/moodle2cc/cc/web_link.rb +53 -0
  40. data/lib/moodle2cc/cc/wiki.rb +72 -0
  41. data/lib/moodle2cc/cli.rb +14 -0
  42. data/lib/moodle2cc/error.rb +3 -0
  43. data/lib/moodle2cc/migrator.rb +23 -0
  44. data/lib/moodle2cc/moodle/backup.rb +38 -0
  45. data/lib/moodle2cc/moodle/course.rb +24 -0
  46. data/lib/moodle2cc/moodle/grade_item.rb +24 -0
  47. data/lib/moodle2cc/moodle/info.rb +8 -0
  48. data/lib/moodle2cc/moodle/mod.rb +127 -0
  49. data/lib/moodle2cc/moodle/question.rb +98 -0
  50. data/lib/moodle2cc/moodle/question_category.rb +17 -0
  51. data/lib/moodle2cc/moodle/section.rb +37 -0
  52. data/lib/moodle2cc/resource_factory.rb +32 -0
  53. data/lib/moodle2cc/version.rb +3 -0
  54. data/moodle2cc.gemspec +29 -0
  55. data/test/acceptance/migrator_test.rb +23 -0
  56. data/test/fixtures/cc.imscc +0 -0
  57. data/test/fixtures/moodle_backup/course_files/folder/test.txt +1 -0
  58. data/test/fixtures/moodle_backup/course_files/test.txt +1 -0
  59. data/test/fixtures/moodle_backup/moodle.xml +916 -0
  60. data/test/test_helper.rb +43 -0
  61. data/test/test_question_helper.rb +107 -0
  62. data/test/test_wiki_helper.rb +21 -0
  63. data/test/unit/canvas/assessment_test.rb +218 -0
  64. data/test/unit/canvas/assignment_test.rb +220 -0
  65. data/test/unit/canvas/converter_test.rb +159 -0
  66. data/test/unit/canvas/course_test.rb +176 -0
  67. data/test/unit/canvas/discussion_topic_test.rb +129 -0
  68. data/test/unit/canvas/label_test.rb +32 -0
  69. data/test/unit/canvas/question_bank_test.rb +73 -0
  70. data/test/unit/canvas/question_test.rb +824 -0
  71. data/test/unit/canvas/web_content_test.rb +37 -0
  72. data/test/unit/canvas/web_link_test.rb +48 -0
  73. data/test/unit/canvas/wiki_test.rb +74 -0
  74. data/test/unit/cc/assessment_test.rb +48 -0
  75. data/test/unit/cc/assignment_test.rb +67 -0
  76. data/test/unit/cc/cc_helper_test.rb +19 -0
  77. data/test/unit/cc/converter_test.rb +159 -0
  78. data/test/unit/cc/course_test.rb +36 -0
  79. data/test/unit/cc/discussion_topic_test.rb +83 -0
  80. data/test/unit/cc/label_test.rb +29 -0
  81. data/test/unit/cc/question_test.rb +49 -0
  82. data/test/unit/cc/web_content_test.rb +76 -0
  83. data/test/unit/cc/web_link_test.rb +79 -0
  84. data/test/unit/cc/wiki_test.rb +139 -0
  85. data/test/unit/migrator_test.rb +56 -0
  86. data/test/unit/moodle/backup_test.rb +30 -0
  87. data/test/unit/moodle/course_test.rb +57 -0
  88. data/test/unit/moodle/grade_item_test.rb +72 -0
  89. data/test/unit/moodle/info_test.rb +21 -0
  90. data/test/unit/moodle/mod_test.rb +301 -0
  91. data/test/unit/moodle/question_category_test.rb +34 -0
  92. data/test/unit/moodle/question_test.rb +185 -0
  93. data/test/unit/moodle/section_test.rb +75 -0
  94. data/test/unit/resource_factory_test.rb +119 -0
  95. metadata +342 -0
@@ -0,0 +1,136 @@
1
+ module Moodle2CC::CC
2
+ class Converter
3
+ include CCHelper
4
+
5
+ def initialize(moodle_backup, destination_dir)
6
+ @resource_factory = Moodle2CC::ResourceFactory.new Moodle2CC::CC
7
+ @moodle_backup = moodle_backup
8
+ @export_dir = Dir.mktmpdir
9
+ @destination_dir = destination_dir
10
+ end
11
+
12
+ def imscc_file_name
13
+ "#{file_slug(@moodle_backup.course.fullname)}.imscc"
14
+ end
15
+
16
+ def imscc_path
17
+ @imscc_path ||= File.join(@destination_dir, imscc_file_name)
18
+ end
19
+
20
+ def imscc_tmp_path
21
+ @imscc_tmp_path ||= File.join(@export_dir, imscc_file_name)
22
+ end
23
+
24
+ def convert
25
+ File.open(File.join(@export_dir, MANIFEST), 'w') do |file|
26
+ @document = Builder::XmlMarkup.new(:target => file, :indent => 2)
27
+ @document.instruct!
28
+ create_manifest
29
+ end
30
+ create_web_resources
31
+ Zip::ZipFile.open(imscc_tmp_path, Zip::ZipFile::CREATE) do |zipfile|
32
+ Dir["#{@export_dir}/**/*"].each do |file|
33
+ zipfile.add(file.sub(@export_dir + '/', ''), file)
34
+ end
35
+ end
36
+ FileUtils.mv imscc_tmp_path, imscc_path
37
+ FileUtils.rm_r @export_dir
38
+ end
39
+
40
+ def create_manifest
41
+ @document.manifest(
42
+ "identifier" => create_key(@moodle_backup.course.id, "common_cartridge_"),
43
+ "xmlns" => "http://www.imsglobal.org/xsd/imsccv1p1/imscp_v1p1",
44
+ "xmlns:lom" => "http://ltsc.ieee.org/xsd/imsccv1p1/LOM/resource",
45
+ "xmlns:lomimscc" => "http://ltsc.ieee.org/xsd/imsccv1p1/LOM/manifest",
46
+ "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
47
+ "xsi:schemaLocation" => "http://www.imsglobal.org/xsd/imsccv1p1/imscp_v1p1 http://www.imsglobal.org/profile/cc/ccv1p1/ccv1p1_imscp_v1p2_v1p0.xsd http://ltsc.ieee.org/xsd/imsccv1p1/LOM/resource http://www.imsglobal.org/profile/cc/ccv1p1/LOM/ccv1p1_lomresource_v1p0.xsd http://ltsc.ieee.org/xsd/imsccv1p1/LOM/manifest http://www.imsglobal.org/profile/cc/ccv1p1/LOM/ccv1p1_lommanifest_v1p0.xsd"
48
+ ) do |manifest_node|
49
+ @manifest_node = manifest_node
50
+ @manifest_node.metadata do |md|
51
+ md.schema "IMS Common Cartridge"
52
+ md.schemaversion "1.1.0"
53
+ md.lomimscc :lom do |lom|
54
+ lom.lomimscc :general do |general|
55
+ general.lomimscc :title do |title|
56
+ title.lomimscc :string, @moodle_backup.course.fullname
57
+ end
58
+ end
59
+ lom.lomimscc :lifeCycle do |lifecycle|
60
+ lifecycle.lomimscc :contribute do |contribute|
61
+ contribute.lomimscc :date do |date|
62
+ date.lomimscc :dateTime, ims_date
63
+ end
64
+ end
65
+ end
66
+ lom.lomimscc :rights do |rights|
67
+ rights.lomimscc :copyrightAndOtherRestrictions do |node|
68
+ node.lomimscc :value, 'yes'
69
+ end
70
+ rights.lomimscc :description do |desc|
71
+ desc.lomimscc :string, 'Private (Copyrighted) - http://en.wikipedia.org/wiki/Copyright'
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ create_organizations
78
+
79
+ @manifest_node.resources do |resources_node|
80
+ create_resources(resources_node)
81
+ end
82
+ end
83
+ end
84
+
85
+ def create_organizations
86
+ course = Course.new(@moodle_backup.course)
87
+ @manifest_node.organizations do |orgs|
88
+ orgs.organization(
89
+ :identifier => 'org_1',
90
+ :structure => 'rooted-hierarchy'
91
+ ) do |org|
92
+ org.item(:identifier => "LearningModules") do |root_item|
93
+ @moodle_backup.course.sections.each do |section|
94
+ next unless section.visible
95
+ root_item.item(:identifier => create_key(section.id, "section_")) do |item_node|
96
+ item_node.title "#{course.format} #{section.number}"
97
+ section.mods.each do |mod|
98
+ resource = @resource_factory.get_resource_from_mod(mod.instance)
99
+ resource.create_organization_item_node(item_node) if resource
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ def create_resources(resources_node)
109
+ @moodle_backup.course.mods.each_with_index do |mod, index|
110
+ resource = @resource_factory.get_resource_from_mod(mod, index)
111
+ if resource
112
+ resource.create_resource_node(resources_node)
113
+ resource.create_files(@export_dir)
114
+ end
115
+ end
116
+
117
+ @moodle_backup.files.each do |file|
118
+ href = File.join(WEB_RESOURCES_FOLDER, file)
119
+ resources_node.resource(
120
+ :type => WEBCONTENT,
121
+ :identifier => create_key(href, 'resource_'),
122
+ :href => href
123
+ ) do |resource_node|
124
+ resource_node.file(:href => href)
125
+ end
126
+ end
127
+ end
128
+
129
+ def create_web_resources
130
+ web_resources_folder = File.join(@export_dir, WEB_RESOURCES_FOLDER)
131
+ FileUtils.mkdir(web_resources_folder)
132
+ @moodle_backup.copy_files_to(web_resources_folder)
133
+ end
134
+
135
+ end
136
+ end
@@ -0,0 +1,16 @@
1
+ module Moodle2CC::CC
2
+ class Course
3
+ include CCHelper
4
+
5
+ attr_accessor :format
6
+
7
+ def initialize(course)
8
+ @format = case course.format
9
+ when 'weeks', 'weekscss'
10
+ 'Week'
11
+ else
12
+ 'Topic'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,53 @@
1
+ module Moodle2CC
2
+ module CC
3
+ class DiscussionTopic
4
+ include CCHelper
5
+ include Resource
6
+
7
+ attr_accessor :text
8
+
9
+ def initialize(mod, position=0)
10
+ super
11
+ @text = convert_file_path_tokens(mod.intro)
12
+ end
13
+
14
+ def identifierref
15
+ create_key(id, 'topic_meta_')
16
+ end
17
+
18
+ def create_resource_node(resources_node)
19
+ resources_node.resource(
20
+ :type => DISCUSSION_TOPIC,
21
+ :identifier => identifier
22
+ ) do |resource_node|
23
+ resource_node.file(:href => "#{identifier}.xml")
24
+ create_resource_sub_nodes(resource_node)
25
+ end
26
+ end
27
+
28
+ def create_resource_sub_nodes(resource_node)
29
+ end
30
+
31
+ def create_files(export_dir)
32
+ create_topic_xml(export_dir)
33
+ end
34
+
35
+ def create_topic_xml(export_dir)
36
+ path = File.join(export_dir, "#{identifier}.xml")
37
+ File.open(path, 'w') do |file|
38
+ document = Builder::XmlMarkup.new(:target => file, :indent => 2)
39
+ document.instruct!
40
+ document.topicMeta(
41
+ :identifier => identifierref,
42
+ 'xsi:schemaLocation' => "http://www.imsglobal.org/xsd/imsccv1p1/imsdt_v1p1 http://www.imsglobal.org/profile/cc/ccv1p1/ccv1p1_imsdt_v1p1.xsd",
43
+ 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
44
+ 'xmlns' => "http://www.imsglobal.org/xsd/imsccv1p1/imsdt_v1p1"
45
+ ) do |topic|
46
+ topic.title @title
47
+ topic.text @text, :texttype => 'text/html'
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,6 @@
1
+ module Moodle2CC::CC
2
+ class Label
3
+ include CCHelper
4
+ include Resource
5
+ end
6
+ end
@@ -0,0 +1,23 @@
1
+ module Moodle2CC::CC
2
+ class Question
3
+ include CCHelper
4
+
5
+ attr_accessor :id, :title, :identifier
6
+
7
+ def initialize(question, assessment=nil)
8
+ @id = question.id
9
+ @title = (question.name || '').gsub('$@NULL@$', '')
10
+ @identifier_prefix = "#{assessment.mod.mod_type}_" if assessment
11
+
12
+ if question.instance_id
13
+ @identifier = create_key(question.instance_id, "#{@identifier_prefix}question_instance_")
14
+ else
15
+ @identifier = create_key(question.id, "#{@identifier_prefix}question_")
16
+ end
17
+ end
18
+
19
+ def create_item_xml(section_node)
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,30 @@
1
+ module Moodle2CC::CC
2
+ module Resource
3
+ def self.included(klass)
4
+ klass.class_eval do
5
+ attr_accessor :mod, :identifier, :id, :title, :indent
6
+ end
7
+ end
8
+
9
+ def initialize(mod, *args)
10
+ @mod = mod
11
+ @id = mod.id
12
+ @title = mod.name
13
+ @indent = mod.section_mod.nil? ? 0 : mod.section_mod.indent
14
+ @identifier = create_resource_key(mod)
15
+ end
16
+
17
+ def create_files(export_dir)
18
+ end
19
+
20
+ def create_resource_node(resources_node)
21
+ end
22
+
23
+ def create_organization_item_node(item_node)
24
+ item_node.item(:identifier => create_mod_key(@mod), :identifierref => @identifier) do |sub_item|
25
+ sub_item.title @title
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,9 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4
+ <title>Assignment: <%= title %></title>
5
+ </head>
6
+ <body>
7
+ <%= body %>
8
+ </body>
9
+ </html>
@@ -0,0 +1,9 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4
+ <title>Syllabus</title>
5
+ </head>
6
+ <body>
7
+ <%= syllabus_body %>
8
+ </body>
9
+ </html>
@@ -0,0 +1,10 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4
+ <title><%= title %></title>
5
+ <meta name="identifier" content="<%= identifier %>"/>
6
+ </head>
7
+ <body>
8
+ <%= body %>
9
+ </body>
10
+ </html>
@@ -0,0 +1,40 @@
1
+ module Moodle2CC::CC
2
+ class WebContent
3
+ include CCHelper
4
+ include Resource
5
+
6
+ attr_accessor :body
7
+
8
+ def initialize(mod)
9
+ super
10
+ body = mod.alltext
11
+ body = mod.content || '' if body.nil? || body.length == 0
12
+ @body = convert_file_path_tokens(body)
13
+ end
14
+
15
+ def create_resource_node(resources_node)
16
+ href = File.join(WIKI_FOLDER, "#{file_slug(@title)}.html")
17
+ resources_node.resource(
18
+ :type => WEBCONTENT,
19
+ :identifier => identifier,
20
+ :href => href
21
+ ) do |resource_node|
22
+ resource_node.file(:href => href)
23
+ end
24
+ end
25
+
26
+ def create_files(export_dir)
27
+ create_html(export_dir)
28
+ end
29
+
30
+ def create_html(export_dir)
31
+ template = File.expand_path('../templates/wiki_content.html.erb', __FILE__)
32
+ path = File.join(export_dir, 'wiki_content', "#{file_slug(title)}.html")
33
+ FileUtils.mkdir_p(File.dirname(path))
34
+ File.open(path, 'w') do |file|
35
+ erb = ERB.new(File.read(template))
36
+ file.write(erb.result(binding))
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,53 @@
1
+ module Moodle2CC::CC
2
+ class WebLink
3
+ include CCHelper
4
+ include Resource
5
+
6
+ attr_accessor :url
7
+
8
+ def initialize(mod)
9
+ super
10
+ @url = mod.reference
11
+ end
12
+
13
+ def self.create_resource_key(mod)
14
+ if !URI.parse(mod.reference).scheme
15
+ create_key(File.join(WEB_RESOURCES_FOLDER, mod.reference), 'resource_')
16
+ else
17
+ super
18
+ end
19
+ end
20
+
21
+ def create_resource_node(resources_node)
22
+ resources_node.resource(
23
+ :type => WEB_LINK,
24
+ :identifier => identifier
25
+ ) do |resource_node|
26
+ resource_node.file(:href => "#{identifier}.xml")
27
+ end
28
+ end
29
+
30
+ def create_files(export_dir)
31
+ create_xml(export_dir)
32
+ end
33
+
34
+ def create_xml(export_dir)
35
+ path = File.join(export_dir, "#{identifier}.xml")
36
+ FileUtils.mkdir_p(File.dirname(path))
37
+ File.open(path, 'w') do |file|
38
+ settings_node = Builder::XmlMarkup.new(:target => file, :indent => 2)
39
+ settings_node.instruct!
40
+ settings_node.webLink(
41
+ :identifier => identifier,
42
+ 'xsi:schemaLocation' => "http://www.imsglobal.org/xsd/imsccv1p1/imswl_v1p1 http://www.imsglobal.org/profile/cc/ccv1p1/ccv1p1_imswl_v1p1.xsd",
43
+ 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
44
+ 'xmlns' => "http://www.imsglobal.org/xsd/imsccv1p1/imswl_v1p1"
45
+ ) do |web_link_node|
46
+ web_link_node.title @title
47
+ web_link_node.url(:href => @url)
48
+ end
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,72 @@
1
+ module Moodle2CC::CC
2
+ class Wiki
3
+ include CCHelper
4
+ include Resource
5
+
6
+ attr_accessor :pages
7
+
8
+ def initialize(mod)
9
+ super
10
+ page_versions = mod.pages.inject({}) do |result, page|
11
+ version = result[page.page_name]
12
+ result[page.page_name] = page.version if version.nil? || page.version > version
13
+ result
14
+ end
15
+
16
+ @pages = mod.pages.map do |page|
17
+ if page.version == page_versions[page.page_name]
18
+ title_slug = file_slug(@title)
19
+ body = page.content
20
+ slug = [title_slug, file_slug(page.page_name)].join('-')
21
+ href = "#{WIKI_FOLDER}/#{slug}.html"
22
+ Moodle2CC::OpenStruct.new(:title => page.page_name, :body => body, :href => href, :identifier => create_key(href))
23
+ end
24
+ end.compact
25
+
26
+ if @pages.empty?
27
+ slug = file_slug(@title)
28
+ href = File.join(WIKI_FOLDER, "#{slug}.html")
29
+ @pages = [Moodle2CC::OpenStruct.new(:title => @title, :body => mod.summary, :href => href, :identifier => create_key(href))]
30
+ end
31
+
32
+ @identifier = root_page.identifier
33
+ end
34
+
35
+ def self.create_resource_key(mod)
36
+ Wiki.new(mod).identifer
37
+ end
38
+
39
+ def root_page
40
+ @pages.find { |page| page.title == @title }
41
+ end
42
+
43
+ def create_resource_node(resources_node)
44
+ @pages.each do |page|
45
+ href = page.href
46
+ resources_node.resource(
47
+ :href => href,
48
+ :type => WEBCONTENT,
49
+ :identifier => create_key(href)
50
+ ) do |resource_node|
51
+ resource_node.file(:href => href)
52
+ end
53
+ end
54
+ end
55
+
56
+ def create_files(export_dir)
57
+ create_html(export_dir)
58
+ end
59
+
60
+ def create_html(export_dir)
61
+ template = File.expand_path('../templates/wiki_content.html.erb', __FILE__)
62
+ @pages.each do |page|
63
+ path = File.join(export_dir, page.href)
64
+ FileUtils.mkdir_p(File.dirname(path))
65
+ File.open(path, 'w') do |file|
66
+ erb = ERB.new(File.read(template))
67
+ file.write(erb.result(page.instance_eval { binding }))
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end