moodle2cc 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/Guardfile +14 -0
- data/LICENSE +661 -0
- data/README.md +38 -0
- data/Rakefile +12 -0
- data/bin/moodle2cc +6 -0
- data/lib/moodle2cc.rb +60 -0
- data/lib/moodle2cc/canvas/.converter.rb.swo +0 -0
- data/lib/moodle2cc/canvas/.wiki.rb.swo +0 -0
- data/lib/moodle2cc/canvas/assessment.rb +109 -0
- data/lib/moodle2cc/canvas/assignment.rb +108 -0
- data/lib/moodle2cc/canvas/converter.rb +28 -0
- data/lib/moodle2cc/canvas/course.rb +145 -0
- data/lib/moodle2cc/canvas/discussion_topic.rb +64 -0
- data/lib/moodle2cc/canvas/label.rb +8 -0
- data/lib/moodle2cc/canvas/question.rb +468 -0
- data/lib/moodle2cc/canvas/question_bank.rb +54 -0
- data/lib/moodle2cc/canvas/resource.rb +16 -0
- data/lib/moodle2cc/canvas/templates/assignment.html.erb +9 -0
- data/lib/moodle2cc/canvas/templates/syllabus.html.erb +9 -0
- data/lib/moodle2cc/canvas/templates/wiki_content.html.erb +10 -0
- data/lib/moodle2cc/canvas/web_content.rb +10 -0
- data/lib/moodle2cc/canvas/web_link.rb +17 -0
- data/lib/moodle2cc/canvas/wiki.rb +25 -0
- data/lib/moodle2cc/cc/assessment.rb +25 -0
- data/lib/moodle2cc/cc/assignment.rb +66 -0
- data/lib/moodle2cc/cc/cc_helper.rb +282 -0
- data/lib/moodle2cc/cc/converter.rb +136 -0
- data/lib/moodle2cc/cc/course.rb +16 -0
- data/lib/moodle2cc/cc/discussion_topic.rb +53 -0
- data/lib/moodle2cc/cc/label.rb +6 -0
- data/lib/moodle2cc/cc/question.rb +23 -0
- data/lib/moodle2cc/cc/resource.rb +30 -0
- data/lib/moodle2cc/cc/templates/assignment.html.erb +9 -0
- data/lib/moodle2cc/cc/templates/syllabus.html.erb +9 -0
- data/lib/moodle2cc/cc/templates/wiki_content.html.erb +10 -0
- data/lib/moodle2cc/cc/web_content.rb +40 -0
- data/lib/moodle2cc/cc/web_link.rb +53 -0
- data/lib/moodle2cc/cc/wiki.rb +72 -0
- data/lib/moodle2cc/cli.rb +14 -0
- data/lib/moodle2cc/error.rb +3 -0
- data/lib/moodle2cc/migrator.rb +23 -0
- data/lib/moodle2cc/moodle/backup.rb +38 -0
- data/lib/moodle2cc/moodle/course.rb +24 -0
- data/lib/moodle2cc/moodle/grade_item.rb +24 -0
- data/lib/moodle2cc/moodle/info.rb +8 -0
- data/lib/moodle2cc/moodle/mod.rb +127 -0
- data/lib/moodle2cc/moodle/question.rb +98 -0
- data/lib/moodle2cc/moodle/question_category.rb +17 -0
- data/lib/moodle2cc/moodle/section.rb +37 -0
- data/lib/moodle2cc/resource_factory.rb +32 -0
- data/lib/moodle2cc/version.rb +3 -0
- data/moodle2cc.gemspec +29 -0
- data/test/acceptance/migrator_test.rb +23 -0
- data/test/fixtures/cc.imscc +0 -0
- data/test/fixtures/moodle_backup/course_files/folder/test.txt +1 -0
- data/test/fixtures/moodle_backup/course_files/test.txt +1 -0
- data/test/fixtures/moodle_backup/moodle.xml +916 -0
- data/test/test_helper.rb +43 -0
- data/test/test_question_helper.rb +107 -0
- data/test/test_wiki_helper.rb +21 -0
- data/test/unit/canvas/assessment_test.rb +218 -0
- data/test/unit/canvas/assignment_test.rb +220 -0
- data/test/unit/canvas/converter_test.rb +159 -0
- data/test/unit/canvas/course_test.rb +176 -0
- data/test/unit/canvas/discussion_topic_test.rb +129 -0
- data/test/unit/canvas/label_test.rb +32 -0
- data/test/unit/canvas/question_bank_test.rb +73 -0
- data/test/unit/canvas/question_test.rb +824 -0
- data/test/unit/canvas/web_content_test.rb +37 -0
- data/test/unit/canvas/web_link_test.rb +48 -0
- data/test/unit/canvas/wiki_test.rb +74 -0
- data/test/unit/cc/assessment_test.rb +48 -0
- data/test/unit/cc/assignment_test.rb +67 -0
- data/test/unit/cc/cc_helper_test.rb +19 -0
- data/test/unit/cc/converter_test.rb +159 -0
- data/test/unit/cc/course_test.rb +36 -0
- data/test/unit/cc/discussion_topic_test.rb +83 -0
- data/test/unit/cc/label_test.rb +29 -0
- data/test/unit/cc/question_test.rb +49 -0
- data/test/unit/cc/web_content_test.rb +76 -0
- data/test/unit/cc/web_link_test.rb +79 -0
- data/test/unit/cc/wiki_test.rb +139 -0
- data/test/unit/migrator_test.rb +56 -0
- data/test/unit/moodle/backup_test.rb +30 -0
- data/test/unit/moodle/course_test.rb +57 -0
- data/test/unit/moodle/grade_item_test.rb +72 -0
- data/test/unit/moodle/info_test.rb +21 -0
- data/test/unit/moodle/mod_test.rb +301 -0
- data/test/unit/moodle/question_category_test.rb +34 -0
- data/test/unit/moodle/question_test.rb +185 -0
- data/test/unit/moodle/section_test.rb +75 -0
- data/test/unit/resource_factory_test.rb +119 -0
- metadata +342 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module Moodle2CC
|
4
|
+
class CLI < Thor
|
5
|
+
desc "migrate MOODLE_BACKUP_ZIP EXPORT_DIR", "Migrates Moodle backup ZIP to IMS Common Cartridge package"
|
6
|
+
method_option :format, :default => 'cc'
|
7
|
+
method_options :format => :string
|
8
|
+
def migrate(source, destination)
|
9
|
+
migrator = Moodle2CC::Migrator.new source, destination, options
|
10
|
+
migrator.migrate
|
11
|
+
puts "#{source} converted to #{migrator.imscc_path}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Moodle2CC
|
2
|
+
class Migrator
|
3
|
+
def initialize(source, destination, options={})
|
4
|
+
@source = source
|
5
|
+
@destination = destination
|
6
|
+
@format = options['format'] || 'cc'
|
7
|
+
raise(Moodle2CC::Error, "'#{@source}' does not exist") unless File.exists?(@source)
|
8
|
+
raise(Moodle2CC::Error, "'#{@destination}' is not a directory") unless File.directory?(@destination)
|
9
|
+
raise(Moodle2CC::Error, "'#{@format}' is not a valid format. Please use 'cc' or 'canvas'.") unless ['cc', 'canvas'].include?(@format)
|
10
|
+
@converter_class = @format == 'cc' ? Moodle2CC::CC::Converter : Moodle2CC::Canvas::Converter
|
11
|
+
end
|
12
|
+
|
13
|
+
def migrate
|
14
|
+
backup = Moodle2CC::Moodle::Backup.read @source
|
15
|
+
@converter = @converter_class.new backup, @destination
|
16
|
+
@converter.convert
|
17
|
+
end
|
18
|
+
|
19
|
+
def imscc_path
|
20
|
+
@converter.imscc_path
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'zip/zipfilesystem'
|
2
|
+
|
3
|
+
module Moodle2CC::Moodle
|
4
|
+
class Backup
|
5
|
+
include HappyMapper
|
6
|
+
|
7
|
+
attr_accessor :backup_file, :files
|
8
|
+
|
9
|
+
tag 'MOODLE_BACKUP'
|
10
|
+
has_one :info, Info
|
11
|
+
has_one :course, Course
|
12
|
+
|
13
|
+
def self.read(backup_file)
|
14
|
+
Zip::ZipFile.open(backup_file) do |zipfile|
|
15
|
+
xml = zipfile.file.read("moodle.xml")
|
16
|
+
backup = parse xml
|
17
|
+
backup.backup_file = backup_file
|
18
|
+
backup.files = zipfile.entries.select { |e| e.name =~ /^course_files/ && !e.directory? }.
|
19
|
+
map { |e| e.name.sub('course_files/', '') }.sort
|
20
|
+
backup
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def copy_files_to(dir)
|
25
|
+
Zip::ZipFile.open(@backup_file) do |zipfile|
|
26
|
+
@files.each do |file|
|
27
|
+
zipfile.file.open("course_files/#{file}") do |zip|
|
28
|
+
destination_file = File.join(dir, file)
|
29
|
+
FileUtils.mkdir_p(File.dirname(destination_file))
|
30
|
+
File.open(destination_file, 'w') do |f|
|
31
|
+
f.write zip.read
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Moodle2CC::Moodle
|
2
|
+
class Course
|
3
|
+
include HappyMapper
|
4
|
+
|
5
|
+
tag 'COURSE'
|
6
|
+
element :id, Integer, :tag => 'HEADER/ID'
|
7
|
+
element :fullname, String, :tag => 'HEADER/FULLNAME'
|
8
|
+
element :shortname, String, :tag => 'HEADER/SHORTNAME'
|
9
|
+
element :startdate, Integer, :tag => 'HEADER/STARTDATE'
|
10
|
+
element :format, String, :tag => 'HEADER/FORMAT'
|
11
|
+
element :visible, Boolean, :tag => 'HEADER/VISIBLE'
|
12
|
+
has_many :sections, Section
|
13
|
+
has_many :mods, Mod
|
14
|
+
has_many :grade_items, GradeItem
|
15
|
+
has_many :question_categories, QuestionCategory
|
16
|
+
|
17
|
+
after_parse do |course|
|
18
|
+
course.sections.each { |section| section.course = course }
|
19
|
+
course.mods.each { |mod| mod.course = course }
|
20
|
+
course.grade_items.each { |grade_item| grade_item.course = course }
|
21
|
+
course.question_categories.each { |question_category| question_category.course = course }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Moodle2CC::Moodle
|
2
|
+
class GradeItem
|
3
|
+
include HappyMapper
|
4
|
+
|
5
|
+
attr_accessor :course
|
6
|
+
|
7
|
+
tag 'GRADEBOOK/GRADE_ITEMS/GRADE_ITEM'
|
8
|
+
element :id, Integer, :tag => 'ID'
|
9
|
+
element :category_id, Integer, :tag => 'CATEGORYID'
|
10
|
+
element :item_name, String, :tag => 'ITEMNAME'
|
11
|
+
element :item_type, String, :tag => 'ITEMTYPE'
|
12
|
+
element :item_module, String, :tag => 'ITEMMODULE'
|
13
|
+
element :item_instance, Integer, :tag => 'ITEMINSTANCE'
|
14
|
+
element :item_number, Integer, :tag => 'ITEMNUMBER'
|
15
|
+
element :grade_type, Integer, :tag => 'GRADETYPE'
|
16
|
+
element :grade_max, Float, :tag => 'GRADEMAX'
|
17
|
+
element :grade_min, Float, :tag => 'GRADEMIN'
|
18
|
+
element :scale_id, Integer, :tag => 'SCALEID'
|
19
|
+
|
20
|
+
def instance
|
21
|
+
course.mods.find { |mod| mod.id == item_instance }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module Moodle2CC::Moodle
|
2
|
+
class Mod
|
3
|
+
include HappyMapper
|
4
|
+
|
5
|
+
attr_accessor :course
|
6
|
+
|
7
|
+
class QuestionInstance
|
8
|
+
include HappyMapper
|
9
|
+
|
10
|
+
attr_accessor :mod
|
11
|
+
|
12
|
+
tag 'QUESTION_INSTANCES/QUESTION_INSTANCE'
|
13
|
+
element :id, Integer, :tag => 'ID'
|
14
|
+
element :question_id, Integer, :tag => 'QUESTION'
|
15
|
+
element :grade, Integer, :tag => 'GRADE'
|
16
|
+
|
17
|
+
def question
|
18
|
+
mod.course.question_categories.map do |qc|
|
19
|
+
qc.questions.find { |q| q.id == question_id }
|
20
|
+
end.compact.first
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Page
|
25
|
+
include HappyMapper
|
26
|
+
|
27
|
+
tag 'ENTRIES/ENTRY/PAGES/PAGE'
|
28
|
+
element :page_name, String, :tag => 'PAGENAME'
|
29
|
+
element :version, Integer, :tag => 'VERSION'
|
30
|
+
element :content, String, :tag => 'CONTENT'
|
31
|
+
end
|
32
|
+
|
33
|
+
class Option
|
34
|
+
include HappyMapper
|
35
|
+
|
36
|
+
tag 'OPTIONS/OPTION'
|
37
|
+
element :id, Integer, :tag => 'ID'
|
38
|
+
element :text, String, :tag => 'TEXT'
|
39
|
+
end
|
40
|
+
|
41
|
+
tag 'MODULES/MOD'
|
42
|
+
element :id, Integer, :tag => 'ID'
|
43
|
+
element :var1, Integer, :tag => 'VAR1'
|
44
|
+
element :var2, Integer, :tag => 'VAR2'
|
45
|
+
element :var3, Integer, :tag => 'VAR3'
|
46
|
+
element :var4, Integer, :tag => 'VAR4'
|
47
|
+
element :var5, Integer, :tag => 'VAR5'
|
48
|
+
element :mod_type, String, :tag => 'MODTYPE'
|
49
|
+
element :type, String, :tag => 'TYPE'
|
50
|
+
element :name, String, :tag => 'NAME'
|
51
|
+
element :description, String, :tag => 'DESCRIPTION'
|
52
|
+
element :summary, String, :tag => 'SUMMARY'
|
53
|
+
element :alltext, String, :tag => 'ALLTEXT'
|
54
|
+
element :text, String, :tag => 'TEXT'
|
55
|
+
element :content, String, :tag => 'CONTENT'
|
56
|
+
element :assignment_type, String, :tag => 'ASSIGNMENTTYPE'
|
57
|
+
element :reference, String, :tag => 'REFERENCE'
|
58
|
+
element :intro, String, :tag => 'INTRO'
|
59
|
+
element :resubmit, Boolean, :tag => 'RESUBMIT'
|
60
|
+
element :prevent_late, Boolean, :tag => 'PREVENTLATE'
|
61
|
+
element :grade, Integer, :tag => 'GRADE'
|
62
|
+
element :number_of_attachments, Integer, :tag => 'NATTACHMENTS'
|
63
|
+
element :number_of_student_assessments, Integer, :tag => 'NSASSESSMENTS'
|
64
|
+
element :anonymous, Boolean, :tag => 'ANONYMOUS'
|
65
|
+
element :submission_start, Integer, :tag => 'SUBMISSIONSTART'
|
66
|
+
element :submission_end, Integer, :tag => 'SUBMISSIONEND'
|
67
|
+
element :assessment_start, Integer, :tag => 'ASSESSMENTSTART'
|
68
|
+
element :assessment_end, Integer, :tag => 'ASSESSMENTEND'
|
69
|
+
element :time_due, Integer, :tag => 'TIMEDUE'
|
70
|
+
element :time_available, Integer, :tag => 'TIMEAVAILABLE'
|
71
|
+
element :time_open, Integer, :tag => 'TIMEOPEN'
|
72
|
+
element :time_close, Integer, :tag => 'TIMECLOSE'
|
73
|
+
element :time_limit, Integer, :tag => 'TIMELIMIT'
|
74
|
+
element :attempts_number, Integer, :tag => 'ATTEMPTS_NUMBER'
|
75
|
+
element :grade_method, Integer, :tag => 'GRADEMETHOD'
|
76
|
+
element :password, String, :tag => 'PASSWORD'
|
77
|
+
element :subnet, String, :tag => 'SUBNET'
|
78
|
+
element :shuffle_answers, Boolean, :tag => 'SHUFFLEANSWERS'
|
79
|
+
element :page_name, String, :tag => 'PAGENAME'
|
80
|
+
has_many :question_instances, QuestionInstance
|
81
|
+
has_many :questions, Question
|
82
|
+
has_many :pages, Page
|
83
|
+
has_many :options, Option
|
84
|
+
|
85
|
+
after_parse do |mod|
|
86
|
+
mod.question_instances.each { |question_instance| question_instance.mod = mod }
|
87
|
+
end
|
88
|
+
|
89
|
+
def section_mod
|
90
|
+
course.sections.map { |section| section.mods.find { |mod| mod.instance_id == id && mod.mod_type == mod_type } }.compact.first
|
91
|
+
end
|
92
|
+
|
93
|
+
def grade_item
|
94
|
+
course.grade_items.find { |grade_item| grade_item.item_instance == id }
|
95
|
+
end
|
96
|
+
|
97
|
+
def questions
|
98
|
+
if mod_type == 'questionnaire'
|
99
|
+
@questions.sort! { |a,b| a.position <=> b.position }
|
100
|
+
return @questions
|
101
|
+
end
|
102
|
+
if mod_type == 'choice'
|
103
|
+
question = Question.new
|
104
|
+
question.id = "choice_question_#{@id}"
|
105
|
+
question.name = @name
|
106
|
+
question.text = @text
|
107
|
+
question.type = @mod_type
|
108
|
+
question.grade = 1
|
109
|
+
question.answers = []
|
110
|
+
@options.each do |option|
|
111
|
+
answer = Question::Answer.new
|
112
|
+
answer.id = option.id
|
113
|
+
answer.text = option.text
|
114
|
+
question.answers << answer
|
115
|
+
end
|
116
|
+
@questions = [question]
|
117
|
+
else
|
118
|
+
@questions = question_instances.map do |qi|
|
119
|
+
question = qi.question
|
120
|
+
question.grade = qi.grade
|
121
|
+
question.instance_id = qi.id
|
122
|
+
question
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Moodle2CC::Moodle
|
2
|
+
class Question
|
3
|
+
include HappyMapper
|
4
|
+
|
5
|
+
attr_accessor :question_category, :grade, :instance_id
|
6
|
+
|
7
|
+
class Answer
|
8
|
+
include HappyMapper
|
9
|
+
|
10
|
+
tag 'ANSWERS/ANSWER'
|
11
|
+
element :id, Integer, :tag => 'ID'
|
12
|
+
element :text, String, :tag => 'ANSWER_TEXT'
|
13
|
+
element :fraction, Float, :tag => 'FRACTION'
|
14
|
+
element :feedback, String, :tag => 'FEEDBACK'
|
15
|
+
end
|
16
|
+
|
17
|
+
class Calculation
|
18
|
+
include HappyMapper
|
19
|
+
|
20
|
+
class DatasetDefinition
|
21
|
+
include HappyMapper
|
22
|
+
|
23
|
+
class DatasetItem
|
24
|
+
include HappyMapper
|
25
|
+
|
26
|
+
tag 'DATASET_ITEMS/DATASET_ITEM'
|
27
|
+
element :number, Integer, :tag => 'NUMBER'
|
28
|
+
element :value, Float, :tag => 'VALUE'
|
29
|
+
end
|
30
|
+
|
31
|
+
tag 'DATASET_DEFINITIONS/DATASET_DEFINITION'
|
32
|
+
element :name, String, :tag => 'NAME'
|
33
|
+
element :options, String, :tag => 'OPTIONS'
|
34
|
+
has_many :dataset_items, DatasetItem
|
35
|
+
end
|
36
|
+
|
37
|
+
tag 'CALCULATED'
|
38
|
+
element :answer_id, Integer, :tag => 'ANSWER'
|
39
|
+
element :tolerance, Float, :tag => 'TOLERANCE'
|
40
|
+
element :correct_answer_length, Integer, :tag => 'CORRECTANSWERLENGTH'
|
41
|
+
element :correct_answer_format, Integer, :tag => 'CORRECTANSWERFORMAT'
|
42
|
+
has_many :dataset_definitions, DatasetDefinition
|
43
|
+
end
|
44
|
+
|
45
|
+
class Match
|
46
|
+
include HappyMapper
|
47
|
+
|
48
|
+
tag 'MATCHS/MATCH'
|
49
|
+
element :id, Integer, :tag => 'ID'
|
50
|
+
element :code, Integer, :tag => 'CODE'
|
51
|
+
element :question_text, String, :tag => 'QUESTIONTEXT'
|
52
|
+
element :answer_text, String, :tag => 'ANSWERTEXT'
|
53
|
+
end
|
54
|
+
|
55
|
+
class Numerical
|
56
|
+
include HappyMapper
|
57
|
+
|
58
|
+
tag 'NUMERICAL'
|
59
|
+
element :answer_id, Integer, :tag => 'ANSWER'
|
60
|
+
element :tolerance, Integer, :tag => 'TOLERANCE'
|
61
|
+
end
|
62
|
+
|
63
|
+
class Choice
|
64
|
+
include HappyMapper
|
65
|
+
|
66
|
+
tag 'QUESTION_CHOICE'
|
67
|
+
element :id, Integer, :tag => 'ID'
|
68
|
+
element :content, String, :tag => 'CONTENT'
|
69
|
+
end
|
70
|
+
|
71
|
+
tag 'QUESTION'
|
72
|
+
element :id, Integer, :tag => 'ID'
|
73
|
+
element :name, String, :tag => 'NAME'
|
74
|
+
element :text, String, :tag => 'QUESTIONTEXT'
|
75
|
+
element :content, String, :tag => 'CONTENT'
|
76
|
+
element :length, Integer, :tag => 'LENGTH'
|
77
|
+
element :general_feedback, String, :tag => 'GENERALFEEDBACK'
|
78
|
+
element :default_grade, Integer, :tag => 'DEFAULTGRADE'
|
79
|
+
element :position, Integer, :tag => 'POSITION'
|
80
|
+
element :type, String, :tag => 'QTYPE'
|
81
|
+
element :type_id, Integer, :tag => 'TYPE_ID'
|
82
|
+
has_many :numericals, Numerical
|
83
|
+
has_many :answers, Answer
|
84
|
+
has_many :calculations, Calculation
|
85
|
+
has_many :matches, Match
|
86
|
+
has_many :choices, Choice
|
87
|
+
|
88
|
+
def instance
|
89
|
+
question_category.course.mods.select do |mod|
|
90
|
+
mod.mod_type == 'quiz'
|
91
|
+
end.map do |mod|
|
92
|
+
mod.question_instances.find do |qi|
|
93
|
+
qi.question_id == id
|
94
|
+
end
|
95
|
+
end.compact.first
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Moodle2CC::Moodle
|
2
|
+
class QuestionCategory
|
3
|
+
include HappyMapper
|
4
|
+
|
5
|
+
attr_accessor :course
|
6
|
+
|
7
|
+
tag 'QUESTION_CATEGORIES/QUESTION_CATEGORY'
|
8
|
+
element :id, Integer, :tag => 'ID'
|
9
|
+
element :name, String, :tag => 'NAME'
|
10
|
+
element :info, String, :tag => 'INFO'
|
11
|
+
has_many :questions, Question
|
12
|
+
|
13
|
+
after_parse do |qc|
|
14
|
+
qc.questions.each { |q| q.question_category = qc }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Moodle2CC::Moodle
|
2
|
+
class Section
|
3
|
+
include HappyMapper
|
4
|
+
|
5
|
+
attr_accessor :course
|
6
|
+
|
7
|
+
class Mod
|
8
|
+
include HappyMapper
|
9
|
+
|
10
|
+
attr_accessor :section
|
11
|
+
|
12
|
+
tag 'MODS/MOD'
|
13
|
+
|
14
|
+
element :id, Integer, :tag => 'ID'
|
15
|
+
element :mod_type, String, :tag => 'TYPE'
|
16
|
+
element :instance_id, Integer, :tag => 'INSTANCE'
|
17
|
+
element :added, Integer, :tag => 'ADDED'
|
18
|
+
element :indent, Integer, :tag => 'INDENT'
|
19
|
+
element :visible, Boolean, :tag => 'VISIBLE'
|
20
|
+
|
21
|
+
def instance
|
22
|
+
section.course.mods.find { |mod| mod.id == instance_id && mod.mod_type == mod_type }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
tag 'SECTIONS/SECTION'
|
27
|
+
element :id, Integer, :tag => 'ID'
|
28
|
+
element :number, Integer, :tag => 'NUMBER'
|
29
|
+
element :summary, String, :tag => 'SUMMARY'
|
30
|
+
element :visible, Boolean, :tag => 'VISIBLE'
|
31
|
+
has_many :mods, Mod
|
32
|
+
|
33
|
+
after_parse do |section|
|
34
|
+
section.mods.each { |mod| mod.section = section }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Moodle2CC::ResourceFactory
|
2
|
+
|
3
|
+
def initialize(namespace)
|
4
|
+
@namespace = namespace
|
5
|
+
end
|
6
|
+
|
7
|
+
def get_resource_from_mod(mod, position=0)
|
8
|
+
case mod.mod_type
|
9
|
+
when 'assignment', 'workshop'
|
10
|
+
@namespace.const_get(:Assignment).new(mod, position)
|
11
|
+
when 'resource'
|
12
|
+
if mod.type == 'file'
|
13
|
+
@namespace.const_get(:WebLink).new(mod)
|
14
|
+
elsif mod.type == 'html'
|
15
|
+
@namespace.const_get(:WebContent).new(mod)
|
16
|
+
end
|
17
|
+
when 'forum'
|
18
|
+
@namespace.const_get(:DiscussionTopic).new(mod, position)
|
19
|
+
when 'quiz', 'questionnaire', 'choice'
|
20
|
+
@namespace.const_get(:Assessment).new(mod, position)
|
21
|
+
when 'wiki'
|
22
|
+
@namespace.const_get(:Wiki).new(mod)
|
23
|
+
when 'label'
|
24
|
+
html = Nokogiri::HTML(mod.content)
|
25
|
+
if html.text == mod.content && mod.content.length < 50 # label doesn't contain HTML
|
26
|
+
@namespace.const_get(:Label).new(mod)
|
27
|
+
else
|
28
|
+
@namespace.const_get(:WebContent).new(mod)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|