sakai-info 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +11 -0
- data/README.md +2 -2
- data/ROADMAP.md +17 -5
- data/bin/sakai-info +2 -2
- data/lib/sakai-info.rb +1 -1
- data/lib/sakai-info/assignment.rb +89 -86
- data/lib/sakai-info/cli.rb +6 -1
- data/lib/sakai-info/cli/help.rb +83 -7
- data/lib/sakai-info/mod_props.rb +11 -2
- data/lib/sakai-info/quiz.rb +327 -8
- data/lib/sakai-info/sakai_object.rb +9 -1
- data/lib/sakai-info/sakai_xml_entity.rb +44 -39
- data/lib/sakai-info/site.rb +3 -3
- data/lib/sakai-info/version.rb +1 -1
- metadata +4 -4
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# sakai-info Change History #
|
2
2
|
|
3
|
+
## 0.3.1 ##
|
4
|
+
|
5
|
+
*Released 2012-02-29*
|
6
|
+
|
7
|
+
* New objects: quiz-attempt, quiz-attempt-item, quiz-attempt-item-attachment
|
8
|
+
* More new objects: assignment, assignment-submission
|
9
|
+
* SakaiXMLEntity base class supports ModProps
|
10
|
+
* New standard CL arguments: --dbrow-only and --mod-details
|
11
|
+
* First steps towards a sqlite test infrastructure: schema creation
|
12
|
+
* First steps towards better Sakai DB docs: graphviz file for quiz tables
|
13
|
+
|
3
14
|
## 0.3.0 ##
|
4
15
|
|
5
16
|
*Released 2012-02-26*
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ tool or the libraries.
|
|
10
10
|
|
11
11
|
## Meta ##
|
12
12
|
|
13
|
-
last updated: 2012-02-
|
13
|
+
last updated: 2012-02-29
|
14
14
|
author: David Adams (daveadams@gmail.com)
|
15
15
|
github url: https://github.com/daveadams/sakai-info
|
16
16
|
|
@@ -26,7 +26,7 @@ Use `rake` to test and build the gem:
|
|
26
26
|
$ rake gem:build
|
27
27
|
|
28
28
|
The resulting gem will be saved to the working directory as
|
29
|
-
`sakai-info-0.3.
|
29
|
+
`sakai-info-0.3.1.gem`.
|
30
30
|
|
31
31
|
Cleanup built gems using:
|
32
32
|
|
data/ROADMAP.md
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
# sakai-info Roadmap #
|
2
2
|
|
3
|
-
*Last updated 2012-02-
|
4
|
-
|
5
|
-
### 0.3.1 ###
|
6
|
-
|
7
|
-
* CLI access to assignments
|
3
|
+
*Last updated 2012-02-29*
|
8
4
|
|
9
5
|
### 0.3.2 ###
|
10
6
|
|
@@ -18,6 +14,22 @@
|
|
18
14
|
|
19
15
|
* CLI access to forums
|
20
16
|
|
17
|
+
### 0.3.5 ###
|
18
|
+
|
19
|
+
* CLI access to gradebook
|
20
|
+
|
21
|
+
### 0.3.6 ###
|
22
|
+
|
23
|
+
* CLI access to announcements
|
24
|
+
|
25
|
+
### 0.3.7 ###
|
26
|
+
|
27
|
+
* CLI access to content
|
28
|
+
|
29
|
+
### 0.3.8 ###
|
30
|
+
|
31
|
+
* CLI access to authz (realms, roles, functions)
|
32
|
+
|
21
33
|
### 0.4 ###
|
22
34
|
|
23
35
|
* Standardized abstraction for user and site to support --mod and --dbrow
|
data/bin/sakai-info
CHANGED
@@ -140,9 +140,9 @@ if flags.include? "--all"
|
|
140
140
|
serials = CLI::ObjectModes[mode].all_serializations
|
141
141
|
elsif
|
142
142
|
flags.include? "--dbrow-only"
|
143
|
-
serials = [:
|
143
|
+
serials = [:dbrow_only]
|
144
144
|
else
|
145
|
-
serials = [:default] + flags.collect{|flag|flag.gsub(/^--/,'').to_sym}
|
145
|
+
serials = [:default] + flags.collect{|flag|flag.gsub(/^--/,'').gsub("-","_").to_sym}
|
146
146
|
end
|
147
147
|
begin
|
148
148
|
puts CLI::ObjectModes[mode].find(id).to_yaml(serials)
|
data/lib/sakai-info.rb
CHANGED
@@ -73,9 +73,9 @@ end
|
|
73
73
|
require 'sakai-info/database'
|
74
74
|
|
75
75
|
# base objects
|
76
|
+
require 'sakai-info/mod_props'
|
76
77
|
require 'sakai-info/sakai_object'
|
77
78
|
require 'sakai-info/sakai_xml_entity'
|
78
|
-
require 'sakai-info/mod_props'
|
79
79
|
|
80
80
|
# sakai object classes
|
81
81
|
require 'sakai-info/user'
|
@@ -2,7 +2,7 @@
|
|
2
2
|
# SakaiInfo::Assignment library
|
3
3
|
#
|
4
4
|
# Created 2012-02-17 daveadams@gmail.com
|
5
|
-
# Last updated 2012-02-
|
5
|
+
# Last updated 2012-02-29 daveadams@gmail.com
|
6
6
|
#
|
7
7
|
# https://github.com/daveadams/sakai-info
|
8
8
|
#
|
@@ -11,46 +11,43 @@
|
|
11
11
|
|
12
12
|
module SakaiInfo
|
13
13
|
class Assignment < SakaiXMLEntity
|
14
|
-
attr_reader :
|
14
|
+
attr_reader :dbrow, :site_id
|
15
15
|
|
16
16
|
@@cache = {}
|
17
17
|
def self.find(id)
|
18
18
|
if @@cache[id].nil?
|
19
19
|
xml = ""
|
20
|
-
row = DB.connect[:
|
20
|
+
row = DB.connect[:assignment_assignment].where(:assignment_id => id).first
|
21
21
|
if row.nil?
|
22
22
|
raise ObjectNotFoundException.new(Assignment, id)
|
23
23
|
end
|
24
|
-
|
25
|
-
REXML::Document.new(row[:xml].read).write(xml, 2)
|
26
|
-
@@cache[id] = Assignment.new(id, site, xml)
|
24
|
+
@@cache[id] = Assignment.new(row)
|
27
25
|
end
|
28
26
|
@@cache[id]
|
29
27
|
end
|
30
28
|
|
31
29
|
# raw data constructor
|
32
|
-
def initialize(
|
33
|
-
@
|
34
|
-
|
35
|
-
@
|
30
|
+
def initialize(dbrow)
|
31
|
+
@dbrow = dbrow
|
32
|
+
|
33
|
+
@id = dbrow[:assignment_id]
|
34
|
+
@site_id = dbrow[:context]
|
35
|
+
|
36
36
|
parse_xml
|
37
37
|
end
|
38
38
|
|
39
39
|
# set lookup
|
40
|
+
def self.query_by_site_id(site_id)
|
41
|
+
DB.connect[:assignment_assignment].where(:context => site_id)
|
42
|
+
end
|
43
|
+
|
40
44
|
def self.find_by_site_id(site_id)
|
41
|
-
|
42
|
-
|
43
|
-
DB.connect[:assignment_assignment].filter(:context => site_id).all.each do |row|
|
44
|
-
id = row[:assignment_id]
|
45
|
-
xml = ""
|
46
|
-
REXML::Document.new(row[:xml].read).write(xml, 2)
|
47
|
-
assignments << Assignment.new(id, site, xml)
|
48
|
-
end
|
49
|
-
return assignments
|
45
|
+
Assignment.query_by_site_id(site_id).
|
46
|
+
all.collect { |row| Assignment.new(row) }
|
50
47
|
end
|
51
48
|
|
52
49
|
def self.count_by_site_id(site_id)
|
53
|
-
|
50
|
+
Assignment.query_by_site_id(site_id).count
|
54
51
|
end
|
55
52
|
|
56
53
|
# getters
|
@@ -58,12 +55,16 @@ module SakaiInfo
|
|
58
55
|
@attributes["title"]
|
59
56
|
end
|
60
57
|
|
58
|
+
def site
|
59
|
+
@site ||= Site.find(self.site_id)
|
60
|
+
end
|
61
|
+
|
61
62
|
def submissions
|
62
|
-
@submissions ||= AssignmentSubmission.find_by_assignment_id(
|
63
|
+
@submissions ||= AssignmentSubmission.find_by_assignment_id(self.id)
|
63
64
|
end
|
64
65
|
|
65
66
|
def submission_count
|
66
|
-
@submission_count ||= AssignmentSubmission.count_by_assignment_id(
|
67
|
+
@submission_count ||= AssignmentSubmission.count_by_assignment_id(self.id)
|
67
68
|
end
|
68
69
|
|
69
70
|
# yaml/json serialization
|
@@ -72,9 +73,7 @@ module SakaiInfo
|
|
72
73
|
"id" => self.id,
|
73
74
|
"title" => self.title,
|
74
75
|
"site" => self.site.serialize(:summary),
|
75
|
-
"
|
76
|
-
"created_at" => self.created_at,
|
77
|
-
"submissions" => self.submission_count
|
76
|
+
"submission_count" => self.submission_count
|
78
77
|
}
|
79
78
|
end
|
80
79
|
|
@@ -82,118 +81,122 @@ module SakaiInfo
|
|
82
81
|
{
|
83
82
|
"id" => self.id,
|
84
83
|
"title" => self.title,
|
85
|
-
"
|
86
|
-
|
84
|
+
"submission_count" => self.submission_count
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
def submissions_serialization
|
89
|
+
{
|
90
|
+
"submissions" => self.submissions.collect{|s|s.serialize(:assignment_summary)}
|
87
91
|
}
|
88
92
|
end
|
89
93
|
end
|
90
94
|
|
91
95
|
class AssignmentSubmission < SakaiXMLEntity
|
92
|
-
attr_reader :
|
96
|
+
attr_reader :dbrow, :assignment_id, :submitter_id
|
97
|
+
|
98
|
+
def initialize(dbrow)
|
99
|
+
@dbrow = dbrow
|
100
|
+
|
101
|
+
@id = dbrow[:submission_id]
|
102
|
+
@assignment_id = dbrow[:context]
|
103
|
+
@submitter_id = dbrow[:submitter_id]
|
104
|
+
@is_submitted = (dbrow[:submitted] == "true")
|
105
|
+
@is_graded = (dbrow[:graded] == "true")
|
93
106
|
|
94
|
-
def initialize(id, assignment, xml, submitter, submitted, graded)
|
95
|
-
@id = id
|
96
|
-
@assignment = assignment
|
97
|
-
@xml = xml
|
98
|
-
@submitter = submitter
|
99
|
-
@submitted = submitted
|
100
|
-
@graded = graded
|
101
107
|
parse_xml
|
102
108
|
end
|
103
109
|
|
104
110
|
@@cache = {}
|
105
111
|
def self.find(id)
|
106
112
|
if @@cache[id].nil?
|
107
|
-
|
108
|
-
xml = ""
|
109
|
-
row = DB.connect[:assignment_submission].filter(:submission_id => id).first
|
113
|
+
row = DB.connect[:assignment_submission].where(:submission_id => id).first
|
110
114
|
if row.nil?
|
111
115
|
raise ObjectNotFoundException.new(AssignmentSubmission, id)
|
112
116
|
end
|
113
117
|
|
114
|
-
|
115
|
-
REXML::Document.new(row[:xml].read).write(xml, 2)
|
116
|
-
submitter = User.find(row[:submitter_id])
|
117
|
-
submitted = (row[:submitted] == "true")
|
118
|
-
graded = (row[:graded] == "true")
|
119
|
-
|
120
|
-
@@cache[id] = AssignmentSubmission.new(id, assignment, xml, submitter, submitted, graded)
|
118
|
+
@@cache[id] = AssignmentSubmission.new(row)
|
121
119
|
end
|
122
120
|
@@cache[id]
|
123
121
|
end
|
124
122
|
|
123
|
+
def submitter
|
124
|
+
@submitter ||= User.find(self.submitter_id)
|
125
|
+
end
|
126
|
+
|
127
|
+
def assignment
|
128
|
+
@assignment ||= Assignment.find(self.assignment_id)
|
129
|
+
end
|
130
|
+
|
125
131
|
def submitted?
|
126
|
-
(
|
132
|
+
( self.created_by_id == self.submitter_id && @is_submitted ) || false
|
127
133
|
end
|
128
134
|
|
129
135
|
def graded?
|
130
|
-
@
|
136
|
+
@is_graded || false
|
131
137
|
end
|
132
138
|
|
133
139
|
def submitted_at
|
134
140
|
@submitted_at ||= format_entity_date(@attributes["datesubmitted"])
|
135
141
|
end
|
136
142
|
|
143
|
+
def self.query_by_assignment_id(assignment_id)
|
144
|
+
DB.connect[:assignment_submission].where(:context => assignment_id)
|
145
|
+
end
|
146
|
+
|
137
147
|
def self.find_by_assignment_id(assignment_id)
|
138
|
-
|
139
|
-
|
140
|
-
DB.connect[:assignment_submission].filter(:context => assignment_id).all.each do |row|
|
141
|
-
id = row[:submission_id]
|
142
|
-
xml = ""
|
143
|
-
REXML::Document.new(row[:xml].read).write(xml, 2)
|
144
|
-
submitter = User.find(row[:submitter_id])
|
145
|
-
submitted = (row[:submitted] == "true")
|
146
|
-
graded = (row[:graded] == "true")
|
147
|
-
submissions << AssignmentSubmission.new(id, assignment, xml, submitter, submitted, graded)
|
148
|
-
end
|
149
|
-
return submissions
|
148
|
+
AssignmentSubmission.query_by_assignment_id(assignment_id).
|
149
|
+
all.collect { |row| AssignmentSubmission.new(row) }
|
150
150
|
end
|
151
151
|
|
152
152
|
def self.count_by_assignment_id(assignment_id)
|
153
|
-
|
153
|
+
AssignmentSubmission.query_by_assignment_id(assignment_id).count
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.query_by_user_id(user_id)
|
157
|
+
DB.connect[:assignment_submission].where(:submitter_id => user_id)
|
154
158
|
end
|
155
159
|
|
156
160
|
def self.find_by_user_id(user_id)
|
157
|
-
|
158
|
-
|
159
|
-
DB.connect[:assignment_submission].filter(:submitter_id => user_id).all.each do |row|
|
160
|
-
id = row[:submission_id]
|
161
|
-
assignment = Assignment.find(row[:context])
|
162
|
-
xml = ""
|
163
|
-
REXML::Document.new(row[:xml].read).write(xml, 2)
|
164
|
-
submitted = (row[:submitted] == "true")
|
165
|
-
graded = (row[:graded] == "true")
|
166
|
-
submissions << AssignmentSubmission.new(id, assignment, xml, submitter, submitted, graded)
|
167
|
-
end
|
168
|
-
return submissions
|
161
|
+
AssignmentSubmission.query_by_user_id(user_id).
|
162
|
+
all.collect { |row| AssignmentSubmission.new(row) }
|
169
163
|
end
|
170
164
|
|
171
165
|
def self.count_by_user_id(user_id)
|
172
|
-
|
166
|
+
AssignmentSubmission.query_by_user_id(user_id).count
|
173
167
|
end
|
174
168
|
|
175
169
|
# yaml/json serialization
|
176
170
|
def default_serialization
|
177
|
-
{
|
171
|
+
result = {
|
178
172
|
"id" => self.id,
|
179
173
|
"assignment" => self.assignment.serialize(:summary),
|
180
174
|
"submitter" => self.submitter.serialize(:summary),
|
181
|
-
"
|
175
|
+
"is_submitted" => self.submitted?,
|
182
176
|
"submitted_at" => self.submitted_at,
|
183
|
-
"
|
184
|
-
"created_by" => self.created_by.eid,
|
185
|
-
"created_at" => self.created_at,
|
186
|
-
"modified_by" => self.modified_by.eid,
|
187
|
-
"modified_at" => self.modified_at
|
177
|
+
"is_graded" => self.graded?,
|
188
178
|
}
|
179
|
+
if not self.submitted?
|
180
|
+
result.delete("submitted_at")
|
181
|
+
result.delete("is_graded")
|
182
|
+
end
|
183
|
+
result
|
189
184
|
end
|
190
185
|
|
191
186
|
def summary_serialization
|
192
187
|
{
|
193
188
|
"id" => self.id,
|
194
|
-
"assignment_id" => self.
|
195
|
-
"submitter" => self.
|
196
|
-
"
|
189
|
+
"assignment_id" => self.assignment_id,
|
190
|
+
"submitter" => User.get_eid(self.submitter_id),
|
191
|
+
"is_submitted" => self.submitted?
|
192
|
+
}
|
193
|
+
end
|
194
|
+
|
195
|
+
def assignment_summary_serialization
|
196
|
+
{
|
197
|
+
"id" => self.id,
|
198
|
+
"submitter" => User.get_eid(self.submitter_id),
|
199
|
+
"is_submitted" => self.submitted?
|
197
200
|
}
|
198
201
|
end
|
199
202
|
end
|
@@ -211,7 +214,7 @@ module SakaiInfo
|
|
211
214
|
@@cache = {}
|
212
215
|
def self.find(id)
|
213
216
|
if @@cache[id].nil?
|
214
|
-
row = DB.connect[:assignment_content].
|
217
|
+
row = DB.connect[:assignment_content].where(:content_id => id).first
|
215
218
|
if row.nil?
|
216
219
|
raise ObjectNotFoundException.new(AssignmentContent, id)
|
217
220
|
end
|
@@ -224,7 +227,7 @@ module SakaiInfo
|
|
224
227
|
|
225
228
|
def self.find_by_user_id(user_id)
|
226
229
|
contents = []
|
227
|
-
DB.connect[:assignment_content].
|
230
|
+
DB.connect[:assignment_content].where(:context => user_id).all.each do |row|
|
228
231
|
id = row[:content_id]
|
229
232
|
context = row[:context]
|
230
233
|
xml = ""
|
@@ -235,7 +238,7 @@ module SakaiInfo
|
|
235
238
|
end
|
236
239
|
|
237
240
|
def self.count_by_user_id(user_id)
|
238
|
-
DB.connect[:assignment_content].
|
241
|
+
DB.connect[:assignment_content].where(:context => user_id).count
|
239
242
|
end
|
240
243
|
|
241
244
|
# getters
|
data/lib/sakai-info/cli.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# - sakai-info command line tool support
|
3
3
|
#
|
4
4
|
# Created 2012-02-19 daveadams@gmail.com
|
5
|
-
# Last updated 2012-02-
|
5
|
+
# Last updated 2012-02-29 daveadams@gmail.com
|
6
6
|
#
|
7
7
|
# https://github.com/daveadams/sakai-info
|
8
8
|
#
|
@@ -19,8 +19,13 @@ module SakaiInfo
|
|
19
19
|
"quiz" => Quiz,
|
20
20
|
"quiz-section" => QuizSection,
|
21
21
|
"quiz-item" => QuizItem,
|
22
|
+
"quiz-attempt" => QuizAttempt,
|
23
|
+
"quiz-attempt-item" => QuizAttemptItem,
|
24
|
+
"quiz-attempt-item-attachment" => QuizAttemptItemAttachment,
|
22
25
|
"qpool" => QuestionPool,
|
23
26
|
"question-pool" => QuestionPool,
|
27
|
+
"assignment" => Assignment,
|
28
|
+
"assignment-submission" => AssignmentSubmission,
|
24
29
|
}
|
25
30
|
end
|
26
31
|
end
|
data/lib/sakai-info/cli/help.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# - sakai-info command line help
|
3
3
|
#
|
4
4
|
# Created 2012-02-19 daveadams@gmail.com
|
5
|
-
# Last updated 2012-02-
|
5
|
+
# Last updated 2012-02-29 daveadams@gmail.com
|
6
6
|
#
|
7
7
|
# https://github.com/daveadams/sakai-info
|
8
8
|
#
|
@@ -21,11 +21,22 @@ sakai-info #{VERSION}
|
|
21
21
|
Object commands:
|
22
22
|
user User information
|
23
23
|
site Site information
|
24
|
+
|
24
25
|
quiz Quiz aka Assessment information, pending or published
|
25
26
|
quiz-section Quiz section information, pending or published
|
26
27
|
quiz-item Quiz item information, pending or published
|
28
|
+
quiz-attempt Quiz attempt information
|
29
|
+
quiz-attempt-item
|
30
|
+
Information on attempted quiz items
|
31
|
+
quiz-attempt-item-attachment
|
32
|
+
Information on file attachments to attempted quiz items
|
33
|
+
|
27
34
|
question-pool Question Pool information
|
28
35
|
|
36
|
+
assignment Assignment information
|
37
|
+
assignment-submission
|
38
|
+
Assignment submission information
|
39
|
+
|
29
40
|
Misc commands:
|
30
41
|
test Tests configured database connections
|
31
42
|
help Prints general help
|
@@ -45,11 +56,17 @@ sakai-info #{VERSION}
|
|
45
56
|
trace log to STDOUT.
|
46
57
|
|
47
58
|
Options that work on most object types:
|
59
|
+
--dbrow
|
60
|
+
Print the raw database fields in addition to the usual summary.
|
61
|
+
|
48
62
|
--dbrow-only
|
49
63
|
Print only the raw database fields for the object requested.
|
50
64
|
|
51
65
|
--mod
|
52
|
-
Print creation and modification
|
66
|
+
Print creation and modification user EIDs and timestamps.
|
67
|
+
|
68
|
+
--mod-details
|
69
|
+
Print creation and modification user details and timestamps.
|
53
70
|
|
54
71
|
--all
|
55
72
|
Print all possible information (other than dbrow)
|
@@ -126,13 +143,12 @@ sakai-info quiz
|
|
126
143
|
include additional information:
|
127
144
|
|
128
145
|
--sections Print section summary list
|
146
|
+
--attempts Print summary of user quiz attempts
|
129
147
|
--mod Print creation/modification info
|
130
148
|
--all Print all possible details
|
131
|
-
--dbrow Print the raw database fields
|
132
149
|
|
133
150
|
Not yet implemented:
|
134
151
|
--items Print summary of items on the quiz
|
135
|
-
--attempts Print summary of user quiz attempts (for published quizzes)
|
136
152
|
EOF
|
137
153
|
|
138
154
|
"quiz-section" => <<EOF,
|
@@ -147,7 +163,6 @@ sakai-info quiz-section
|
|
147
163
|
--items Print summary of items in the section
|
148
164
|
--mod Print creation/modification info
|
149
165
|
--all Print all possible details
|
150
|
-
--dbrow Print the raw database fields
|
151
166
|
EOF
|
152
167
|
|
153
168
|
"quiz-item" => <<EOF,
|
@@ -161,7 +176,6 @@ sakai-info quiz-item
|
|
161
176
|
|
162
177
|
--mod Print creation/modification info
|
163
178
|
--all Print all possible details
|
164
|
-
--dbrow Print the raw database fields
|
165
179
|
EOF
|
166
180
|
|
167
181
|
"question-pool" => <<EOF,
|
@@ -174,7 +188,6 @@ sakai-info question-pool
|
|
174
188
|
may be passed to include additional information:
|
175
189
|
|
176
190
|
--mod Print creation/modification info
|
177
|
-
--dbrow Print the raw database fields
|
178
191
|
|
179
192
|
Not yet implemented:
|
180
193
|
--items Print summary of items in the pool
|
@@ -182,6 +195,69 @@ sakai-info question-pool
|
|
182
195
|
--all Print all possible details
|
183
196
|
EOF
|
184
197
|
|
198
|
+
"quiz-attempt" => <<EOF,
|
199
|
+
sakai-info quiz-attempt
|
200
|
+
|
201
|
+
Usage: sakai-info quiz-attempt <id> [<options>]
|
202
|
+
|
203
|
+
Prints information about the quiz attempt ID specified. Additional options
|
204
|
+
may be passed to include additional information:
|
205
|
+
|
206
|
+
--items Print list of attempted items
|
207
|
+
--all Print all possible details
|
208
|
+
EOF
|
209
|
+
|
210
|
+
|
211
|
+
"quiz-attempt-item" => <<EOF,
|
212
|
+
sakai-info quiz-attempt-item
|
213
|
+
|
214
|
+
Usage: sakai-info quiz-attempt-item <id> [<options>]
|
215
|
+
|
216
|
+
Prints information about the quiz attempt item ID specified. Additional
|
217
|
+
options may be passed to include additional information:
|
218
|
+
|
219
|
+
--attachments Print a list of file attachments, if any
|
220
|
+
--all Print all possible details
|
221
|
+
EOF
|
222
|
+
|
223
|
+
"quiz-attempt-item-attachment" => <<EOF,
|
224
|
+
sakai-info quiz-attempt-item-attachment
|
225
|
+
|
226
|
+
Usage: sakai-info quiz-attempt-item-attachment <id> [<options>]
|
227
|
+
|
228
|
+
Prints information about the quiz attempt item attachment ID specified.
|
229
|
+
Additional options may be passed to include additional information:
|
230
|
+
|
231
|
+
--mod Print creation/modification info
|
232
|
+
--all Print all possible details
|
233
|
+
EOF
|
234
|
+
|
235
|
+
"assignment" => <<EOF,
|
236
|
+
sakai-info assignment
|
237
|
+
|
238
|
+
Usage: sakai-info assignment <id> [<options>]
|
239
|
+
|
240
|
+
Prints information about the assignment ID specified. Additional options
|
241
|
+
may be passed to include additional information:
|
242
|
+
|
243
|
+
--submissions Print summary of all submissions
|
244
|
+
--xml Print the raw XML
|
245
|
+
--mod Print creation/modification info
|
246
|
+
--all Print all possible details
|
247
|
+
EOF
|
248
|
+
|
249
|
+
"assignment-submission" => <<EOF,
|
250
|
+
sakai-info assignment-submission
|
251
|
+
|
252
|
+
Usage: sakai-info assignment-submission <id> [<options>]
|
253
|
+
|
254
|
+
Prints information about the assignment submission ID specified. Additional
|
255
|
+
options may be passed to include additional information:
|
256
|
+
|
257
|
+
--xml Print the raw XML
|
258
|
+
--mod Print creation/modification info
|
259
|
+
--all Print all possible details
|
260
|
+
EOF
|
185
261
|
}
|
186
262
|
|
187
263
|
def self.help(topic = :default, io = STDOUT)
|
data/lib/sakai-info/mod_props.rb
CHANGED
@@ -61,10 +61,19 @@ module SakaiInfo
|
|
61
61
|
|
62
62
|
def mod_serialization
|
63
63
|
{
|
64
|
+
"created_at" => self.created_at,
|
65
|
+
"created_by" => User.get_eid(self.created_by_id),
|
66
|
+
"modified_at" => self.modified_at,
|
67
|
+
"modified_by" => User.get_eid(self.modified_by_id),
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def mod_details_serialization
|
72
|
+
{
|
73
|
+
"created_at" => self.created_at,
|
64
74
|
"created_by" => self.created_by.serialize(:summary),
|
65
|
-
"
|
75
|
+
"modified_at" => self.modified_at,
|
66
76
|
"modified_by" => self.modified_by.serialize(:summary),
|
67
|
-
"modified_at" => self.modified_at.strftime("%Y-%m-%d %H:%M:%S")
|
68
77
|
}
|
69
78
|
end
|
70
79
|
}
|
data/lib/sakai-info/quiz.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# SakaiInfo::Quiz library
|
3
3
|
#
|
4
4
|
# Created 2012-02-17 daveadams@gmail.com
|
5
|
-
# Last updated 2012-02-
|
5
|
+
# Last updated 2012-02-28 daveadams@gmail.com
|
6
6
|
#
|
7
7
|
# https://github.com/daveadams/sakai-info
|
8
8
|
#
|
@@ -107,11 +107,17 @@ module SakaiInfo
|
|
107
107
|
"title" => self.title,
|
108
108
|
"site" => nil,
|
109
109
|
"type" => self.quiz_type,
|
110
|
-
"section_count" => self.section_count
|
110
|
+
"section_count" => self.section_count,
|
111
|
+
"attempt_count" => nil
|
111
112
|
}
|
112
113
|
if not self.site.nil?
|
113
114
|
result["site"] = self.site.serialize(:summary)
|
114
115
|
end
|
116
|
+
if self.respond_to? :attempt_count
|
117
|
+
result["attempt_count"] = self.attempt_count
|
118
|
+
else
|
119
|
+
result.delete("attempt_count")
|
120
|
+
end
|
115
121
|
result
|
116
122
|
end
|
117
123
|
|
@@ -140,6 +146,10 @@ module SakaiInfo
|
|
140
146
|
"sections" => self.sections.collect{|s|s.serialize(:quiz_summary)}
|
141
147
|
}
|
142
148
|
end
|
149
|
+
|
150
|
+
def self.all_serializations
|
151
|
+
[:default, :sections]
|
152
|
+
end
|
143
153
|
end
|
144
154
|
|
145
155
|
class PendingQuiz < Quiz
|
@@ -223,6 +233,24 @@ module SakaiInfo
|
|
223
233
|
def quiz_type
|
224
234
|
"published"
|
225
235
|
end
|
236
|
+
|
237
|
+
def attempt_count
|
238
|
+
@attempt_count ||= QuizAttempt.count_by_quiz_id(self.id)
|
239
|
+
end
|
240
|
+
|
241
|
+
def attempts
|
242
|
+
@attempts ||= QuizAttempt.find_by_quiz_id(self.id)
|
243
|
+
end
|
244
|
+
|
245
|
+
def attempts_serialization
|
246
|
+
{
|
247
|
+
"attempts" => self.attempts.collect { |a| a.serialize(:quiz_summary) }
|
248
|
+
}
|
249
|
+
end
|
250
|
+
|
251
|
+
def self.all_serializations
|
252
|
+
[:default, :sections, :attempts]
|
253
|
+
end
|
226
254
|
end
|
227
255
|
|
228
256
|
class QuizSection < SakaiObject
|
@@ -256,7 +284,7 @@ module SakaiInfo
|
|
256
284
|
begin
|
257
285
|
@@cache[id] = PublishedQuizSection.find(id)
|
258
286
|
rescue ObjectNotFoundException
|
259
|
-
raise ObjectNotFoundException(QuizSection, id)
|
287
|
+
raise ObjectNotFoundException.new(QuizSection, id)
|
260
288
|
end
|
261
289
|
end
|
262
290
|
end
|
@@ -347,7 +375,7 @@ module SakaiInfo
|
|
347
375
|
if @@cache[id].nil?
|
348
376
|
row = DB.connect[:sam_section_t].where(:sectionid => id).first
|
349
377
|
if row.nil?
|
350
|
-
raise ObjectNotFoundException(PendingQuizSection, id)
|
378
|
+
raise ObjectNotFoundException.new(PendingQuizSection, id)
|
351
379
|
end
|
352
380
|
|
353
381
|
@@cache[id] = PendingQuizSection.new(row)
|
@@ -367,7 +395,7 @@ module SakaiInfo
|
|
367
395
|
if @@cache[id].nil?
|
368
396
|
row = DB.connect[:sam_publishedsection_t].where(:sectionid => id).first
|
369
397
|
if row.nil?
|
370
|
-
raise ObjectNotFoundException(PublishedQuizSection, id)
|
398
|
+
raise ObjectNotFoundException.new(PublishedQuizSection, id)
|
371
399
|
end
|
372
400
|
|
373
401
|
@@cache[id] = PublishedQuizSection.new(row)
|
@@ -409,7 +437,7 @@ module SakaiInfo
|
|
409
437
|
begin
|
410
438
|
@@cache[id] = PublishedQuizItem.find(id)
|
411
439
|
rescue ObjectNotFoundException
|
412
|
-
raise ObjectNotFoundException(QuizItem, id)
|
440
|
+
raise ObjectNotFoundException.new(QuizItem, id)
|
413
441
|
end
|
414
442
|
end
|
415
443
|
end
|
@@ -500,7 +528,7 @@ module SakaiInfo
|
|
500
528
|
if @@cache[id].nil?
|
501
529
|
row = DB.connect[:sam_item_t].where(:itemid => id).first
|
502
530
|
if row.nil?
|
503
|
-
raise ObjectNotFoundException(PendingQuizItem, id)
|
531
|
+
raise ObjectNotFoundException.new(PendingQuizItem, id)
|
504
532
|
end
|
505
533
|
|
506
534
|
@@cache[id] = PendingQuizItem.new(row)
|
@@ -520,7 +548,7 @@ module SakaiInfo
|
|
520
548
|
if @@cache[id].nil?
|
521
549
|
row = DB.connect[:sam_publisheditem_t].where(:itemid => id).first
|
522
550
|
if row.nil?
|
523
|
-
raise ObjectNotFoundException(PublishedQuizItem, id)
|
551
|
+
raise ObjectNotFoundException.new(PublishedQuizItem, id)
|
524
552
|
end
|
525
553
|
|
526
554
|
@@cache[id] = PublishedQuizItem.new(row)
|
@@ -532,4 +560,295 @@ module SakaiInfo
|
|
532
560
|
"published"
|
533
561
|
end
|
534
562
|
end
|
563
|
+
|
564
|
+
# class QuizItemAttachment < SakaiObject
|
565
|
+
# end
|
566
|
+
|
567
|
+
# class PendingQuizItemAttachment < QuizItemAttachment
|
568
|
+
# end
|
569
|
+
|
570
|
+
# class PublishedQuizItemAttachment < QuizItemAttachment
|
571
|
+
# end
|
572
|
+
|
573
|
+
class QuizAttempt < SakaiObject
|
574
|
+
attr_reader :dbrow, :submitted_at, :total_auto_score, :status, :attempted_at
|
575
|
+
attr_reader :time_elapsed, :comments, :user_id, :quiz_id
|
576
|
+
|
577
|
+
def initialize(dbrow)
|
578
|
+
@dbrow = dbrow
|
579
|
+
|
580
|
+
@id = dbrow[:assessmentgradingid]
|
581
|
+
@submitted_at = dbrow[:submitteddate]
|
582
|
+
@user_id = dbrow[:agentid]
|
583
|
+
@quiz_id = dbrow[:publishedassessmentid]
|
584
|
+
@total_auto_score = dbrow[:totalautoscore]
|
585
|
+
@status = dbrow[:status]
|
586
|
+
@attempted_at = dbrow[:attempted_at]
|
587
|
+
@time_elapsed = dbrow[:timeelapsed]
|
588
|
+
@is_auto_submitted = dbrow[:is_auto_submitted]
|
589
|
+
@is_late = dbrow[:islate]
|
590
|
+
@comments = dbrow[:comments]
|
591
|
+
end
|
592
|
+
|
593
|
+
@@cache = {}
|
594
|
+
def self.find(id)
|
595
|
+
id = id.to_s
|
596
|
+
if @@cache[id].nil?
|
597
|
+
row = DB.connect[:sam_assessmentgrading_t].where(:assessmentgradingid => id).first
|
598
|
+
if row.nil?
|
599
|
+
raise ObjectNotFoundException.new(QuizAttempt, id)
|
600
|
+
end
|
601
|
+
|
602
|
+
@@cache[id] = QuizAttempt.new(row)
|
603
|
+
end
|
604
|
+
@@cache[id]
|
605
|
+
end
|
606
|
+
|
607
|
+
def self.query_by_quiz_id(quiz_id)
|
608
|
+
DB.connect[:sam_assessmentgrading_t].where(:publishedassessmentid => quiz_id)
|
609
|
+
end
|
610
|
+
|
611
|
+
def self.count_by_quiz_id(quiz_id)
|
612
|
+
QuizAttempt.query_by_quiz_id(quiz_id).count
|
613
|
+
end
|
614
|
+
|
615
|
+
def self.find_by_quiz_id(quiz_id)
|
616
|
+
QuizAttempt.query_by_quiz_id(quiz_id).
|
617
|
+
all.collect { |row| QuizAttempt.new(row) }
|
618
|
+
end
|
619
|
+
|
620
|
+
def items
|
621
|
+
@items ||= QuizAttemptItem.find_by_attempt_id(self.id)
|
622
|
+
end
|
623
|
+
|
624
|
+
def item_count
|
625
|
+
@item_count ||= QuizAttemptItem.count_by_attempt_id(self.id)
|
626
|
+
end
|
627
|
+
|
628
|
+
def user
|
629
|
+
@user ||= User.find(@user_id)
|
630
|
+
end
|
631
|
+
|
632
|
+
def quiz
|
633
|
+
@quiz ||= PublishedQuiz.find(@quiz_id)
|
634
|
+
end
|
635
|
+
|
636
|
+
def auto_submitted?
|
637
|
+
@is_auto_submitted == 1
|
638
|
+
end
|
639
|
+
|
640
|
+
def late?
|
641
|
+
@is_late == 1
|
642
|
+
end
|
643
|
+
|
644
|
+
def default_serialization
|
645
|
+
{
|
646
|
+
"id" => self.id,
|
647
|
+
"user" => self.user.serialize(:summary),
|
648
|
+
"quiz" => self.quiz.serialize(:summary),
|
649
|
+
"item_count" => self.item_count,
|
650
|
+
"submitted_at" => self.submitted_at,
|
651
|
+
"is_auto_submitted" => self.auto_submitted?,
|
652
|
+
"is_late" => self.late?,
|
653
|
+
"status" => self.status,
|
654
|
+
"total_auto_score" => self.total_auto_score
|
655
|
+
}
|
656
|
+
end
|
657
|
+
|
658
|
+
def summary_serialization
|
659
|
+
{
|
660
|
+
"id" => self.id,
|
661
|
+
"eid" => User.get_eid(self.user_id),
|
662
|
+
"quiz_id" => self.quiz_id,
|
663
|
+
"status" => self.status
|
664
|
+
}
|
665
|
+
end
|
666
|
+
|
667
|
+
def quiz_summary_serialization
|
668
|
+
{
|
669
|
+
"id" => self.id,
|
670
|
+
"eid" => User.get_eid(self.user_id),
|
671
|
+
"status" => self.status
|
672
|
+
}
|
673
|
+
end
|
674
|
+
|
675
|
+
def items_serialization
|
676
|
+
{
|
677
|
+
"items" => self.items.collect { |i| i.serialize(:attempt_summary) }
|
678
|
+
}
|
679
|
+
end
|
680
|
+
|
681
|
+
def self.all_serializations
|
682
|
+
[:default, :items]
|
683
|
+
end
|
684
|
+
end
|
685
|
+
|
686
|
+
class QuizAttemptItem < SakaiObject
|
687
|
+
attr_reader :dbrow, :submitted_at, :answer, :user_id, :item_id, :attempt_id
|
688
|
+
|
689
|
+
def initialize(dbrow)
|
690
|
+
@dbrow = dbrow
|
691
|
+
|
692
|
+
@id = dbrow[:itemgradingid]
|
693
|
+
@submitted_at = dbrow[:submitteddate]
|
694
|
+
@user_id = dbrow[:agentid]
|
695
|
+
@attempt_id = dbrow[:assessmentgradingid]
|
696
|
+
@item_id = dbrow[:publisheditemid]
|
697
|
+
@answer = dbrow[:answertext]
|
698
|
+
end
|
699
|
+
|
700
|
+
def user
|
701
|
+
@user ||= User.find(@user_id)
|
702
|
+
end
|
703
|
+
|
704
|
+
def attempt
|
705
|
+
@attempt ||= QuizAttempt.find(@attempt_id)
|
706
|
+
end
|
707
|
+
|
708
|
+
def item
|
709
|
+
@item ||= PublishedQuizItem.find(@item_id)
|
710
|
+
end
|
711
|
+
|
712
|
+
@@cache = {}
|
713
|
+
def self.find(id)
|
714
|
+
id = id.to_s
|
715
|
+
if @@cache[id].nil?
|
716
|
+
row = DB.connect[:sam_itemgrading_t].where(:itemgradingid => id).first
|
717
|
+
if row.nil?
|
718
|
+
raise ObjectNotFoundException.new(QuizAttemptItem, id)
|
719
|
+
end
|
720
|
+
|
721
|
+
@@cache[id] = QuizAttemptItem.new(row)
|
722
|
+
end
|
723
|
+
@@cache[id]
|
724
|
+
end
|
725
|
+
|
726
|
+
def self.query_by_attempt_id(attempt_id)
|
727
|
+
DB.connect[:sam_itemgrading_t].where(:assessmentgradingid => attempt_id)
|
728
|
+
end
|
729
|
+
|
730
|
+
def self.count_by_attempt_id(attempt_id)
|
731
|
+
QuizAttemptItem.query_by_attempt_id(attempt_id).count
|
732
|
+
end
|
733
|
+
|
734
|
+
def self.find_by_attempt_id(attempt_id)
|
735
|
+
QuizAttemptItem.query_by_attempt_id(attempt_id).
|
736
|
+
all.collect { |row| QuizAttemptItem.new(row) }
|
737
|
+
end
|
738
|
+
|
739
|
+
def attachments
|
740
|
+
@attachments ||=
|
741
|
+
QuizAttemptItemAttachment.find_by_quiz_attempt_item_id(self.id)
|
742
|
+
end
|
743
|
+
|
744
|
+
def default_serialization
|
745
|
+
{
|
746
|
+
"id" => self.id,
|
747
|
+
"user" => self.user.serialize(:summary),
|
748
|
+
"attempt" => self.attempt.serialize(:summary),
|
749
|
+
"item" => self.item.serialize(:summary),
|
750
|
+
"answer" => self.answer,
|
751
|
+
"attachment_count" => self.attachments.length
|
752
|
+
}
|
753
|
+
end
|
754
|
+
|
755
|
+
def summary_serialization
|
756
|
+
{
|
757
|
+
"id" => self.id,
|
758
|
+
"eid" => User.get_eid(self.user_id),
|
759
|
+
"attempt_id" => self.attempt_id,
|
760
|
+
"item_id" => self.item_id
|
761
|
+
}
|
762
|
+
end
|
763
|
+
|
764
|
+
def attempt_summary_serialization
|
765
|
+
{
|
766
|
+
"id" => self.id,
|
767
|
+
"item_id" => self.item_id
|
768
|
+
}
|
769
|
+
end
|
770
|
+
|
771
|
+
def attachments_serialization
|
772
|
+
{
|
773
|
+
"attachments" => self.attachments.collect{|a|a.serialize(:attempt_item_summary)}
|
774
|
+
}
|
775
|
+
end
|
776
|
+
|
777
|
+
def self.all_serializations
|
778
|
+
[:default, :attachments]
|
779
|
+
end
|
780
|
+
end
|
781
|
+
|
782
|
+
class QuizAttemptItemAttachment < SakaiObject
|
783
|
+
attr_reader :dbrow, :status, :filepath, :filename, :filesize, :mimetype
|
784
|
+
attr_reader :description, :quiz_attempt_item_id
|
785
|
+
|
786
|
+
include ModProps
|
787
|
+
created_by_key :createdby
|
788
|
+
created_at_key :createddate
|
789
|
+
modified_by_key :lastmodifiedby
|
790
|
+
modified_at_key :lastmodifieddate
|
791
|
+
|
792
|
+
def initialize(dbrow)
|
793
|
+
@dbrow = dbrow
|
794
|
+
|
795
|
+
@id = dbrow[:mediaid]
|
796
|
+
@quiz_attempt_item_id = dbrow[:itemgradingid]
|
797
|
+
@status = dbrow[:status]
|
798
|
+
@filepath = dbrow[:location]
|
799
|
+
@filename = dbrow[:filename]
|
800
|
+
@filesize = dbrow[:filesize]
|
801
|
+
@mimetype = dbrow[:mimetype]
|
802
|
+
@description = dbrow[:description]
|
803
|
+
end
|
804
|
+
|
805
|
+
def quiz_attempt_item
|
806
|
+
@quiz_attempt_item ||= QuizAttemptItem.find(@quiz_attempt_item_id)
|
807
|
+
end
|
808
|
+
|
809
|
+
def self.find_by_quiz_attempt_item_id(quiz_attempt_item_id)
|
810
|
+
DB.connect[:sam_media_t].where(:itemgradingid => quiz_attempt_item_id).
|
811
|
+
all.collect { |row| QuizAttemptItemAttachment.new(row) }
|
812
|
+
end
|
813
|
+
|
814
|
+
@@cache = {}
|
815
|
+
def self.find(id)
|
816
|
+
id = id.to_s
|
817
|
+
if @@cache[id].nil?
|
818
|
+
row = DB.connect[:sam_media_t].where(:mediaid => id).first
|
819
|
+
if row.nil?
|
820
|
+
raise ObjectNotFoundException.new(QuizAttemptItemAttachment, id)
|
821
|
+
end
|
822
|
+
|
823
|
+
@@cache[id] = QuizAttemptItemAttachment.new(row)
|
824
|
+
end
|
825
|
+
@@cache[id]
|
826
|
+
end
|
827
|
+
|
828
|
+
def default_serialization
|
829
|
+
{
|
830
|
+
"id" => self.id,
|
831
|
+
"filename" => self.filename,
|
832
|
+
"mimetype" => self.mimetype,
|
833
|
+
"filesize" => self.filesize,
|
834
|
+
"status" => self.status,
|
835
|
+
"quiz_attempt_item" => self.quiz_attempt_item.serialize(:summary)
|
836
|
+
}
|
837
|
+
end
|
838
|
+
|
839
|
+
def summary_serialization
|
840
|
+
{
|
841
|
+
"id" => self.id,
|
842
|
+
"filename" => self.filename,
|
843
|
+
"quiz_attempt_item_id" => self.quiz_attempt_item_id
|
844
|
+
}
|
845
|
+
end
|
846
|
+
|
847
|
+
def attempt_item_summary_serialization
|
848
|
+
{
|
849
|
+
"id" => self.id,
|
850
|
+
"filename" => self.filename
|
851
|
+
}
|
852
|
+
end
|
853
|
+
end
|
535
854
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
# SakaiInfo::SakaiObject
|
3
3
|
#
|
4
4
|
# Created 2012-02-15 daveadams@gmail.com
|
5
|
-
# Last updated 2012-02-
|
5
|
+
# Last updated 2012-02-29 daveadams@gmail.com
|
6
6
|
#
|
7
7
|
# https://github.com/daveadams/sakai-info
|
8
8
|
#
|
@@ -50,6 +50,14 @@ module SakaiInfo
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
+
def dbrow_only_serialization
|
54
|
+
if not self.dbrow_serialization["dbrow"].nil?
|
55
|
+
self.dbrow_serialization["dbrow"]
|
56
|
+
else
|
57
|
+
{}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
53
61
|
def default_serialization
|
54
62
|
object_type_serialization
|
55
63
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
# SakaiInfo::SakaiXMLEntity
|
3
3
|
#
|
4
4
|
# Created 2012-02-16 daveadams@gmail.com
|
5
|
-
# Last updated 2012-02-
|
5
|
+
# Last updated 2012-02-29 daveadams@gmail.com
|
6
6
|
#
|
7
7
|
# https://github.com/daveadams/sakai-info
|
8
8
|
#
|
@@ -39,12 +39,22 @@ module SakaiInfo
|
|
39
39
|
class SakaiXMLEntity < SakaiObject
|
40
40
|
attr_reader :xml, :xmldoc, :attributes, :properties
|
41
41
|
|
42
|
-
|
42
|
+
include ModProps
|
43
|
+
created_by_key :_xml_entity_created_by
|
44
|
+
created_at_key :_xml_entity_created_at
|
45
|
+
modified_by_key :_xml_entity_modified_by
|
46
|
+
modified_at_key :_xml_entity_modified_at
|
47
|
+
|
43
48
|
# this method parses the universal XML field for all entities
|
44
49
|
# down to two collections: attributes (XML attributes defined in the
|
45
50
|
# top-level tag) and properties (<property> tags inside the top-level
|
46
51
|
# tag). Properties are generally base64 encoded
|
47
52
|
def parse_xml
|
53
|
+
if @xml.nil?
|
54
|
+
@xml = ""
|
55
|
+
REXML::Document.new(@dbrow[:xml].read).write(@xml, 2)
|
56
|
+
end
|
57
|
+
|
48
58
|
@xmldoc = REXML::Document.new(@xml)
|
49
59
|
@attributes = {}
|
50
60
|
@xmldoc.root.attributes.keys.each do |att_name|
|
@@ -60,67 +70,62 @@ module SakaiInfo
|
|
60
70
|
if prop_encoding == "BASE64"
|
61
71
|
prop_value = Base64.decode64(prop_value)
|
62
72
|
else
|
63
|
-
raise UnrecognizedPropertyEncodingException(prop_name, prop_encoding, prop_value)
|
73
|
+
raise UnrecognizedPropertyEncodingException.new(prop_name, prop_encoding, prop_value)
|
64
74
|
end
|
65
75
|
@properties[prop_name] = prop_value
|
66
76
|
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def format_entity_date(raw)
|
70
|
-
raw.gsub(/^(....)(..)(..)(..)(..)(..).*$/, '\1-\2-\3 \4:\5:\6')
|
71
|
-
end
|
72
|
-
|
73
|
-
public
|
74
|
-
# standard property for all entities
|
75
|
-
def created_by
|
76
|
-
@created_by ||= User.find(@properties["CHEF:creator"])
|
77
|
-
end
|
78
|
-
|
79
|
-
# standard property for all entities
|
80
|
-
def modified_by
|
81
|
-
@modified_by ||= User.find(@properties["CHEF:modifiedby"])
|
82
|
-
end
|
83
|
-
|
84
|
-
# standard property for all entities
|
85
|
-
def created_at
|
86
|
-
format_entity_date(@properties["DAV:creationdate"])
|
87
|
-
end
|
88
77
|
|
89
|
-
|
90
|
-
|
91
|
-
format_entity_date(@properties["DAV:
|
78
|
+
@dbrow[:_xml_entity_created_by] = @properties["CHEF:creator"]
|
79
|
+
@dbrow[:_xml_entity_modified_by] = @properties["CHEF:modifiedby"]
|
80
|
+
@dbrow[:_xml_entity_created_at] = format_entity_date(@properties["DAV:creationdate"])
|
81
|
+
@dbrow[:_xml_entity_modified_at] = format_entity_date(@properties["DAV:getlastmodified"])
|
92
82
|
end
|
93
83
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
"created_at" => self.created_at,
|
100
|
-
"modified_by" => self.modified_by,
|
101
|
-
"modified_at" => self.modified_at
|
102
|
-
}
|
84
|
+
def format_entity_date(raw)
|
85
|
+
if raw =~ /^(....)(..)(..)(..)(..)(..).*$/
|
86
|
+
# I believe these are usually in UTC
|
87
|
+
Time.utc($1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i).getlocal
|
88
|
+
end
|
103
89
|
end
|
104
90
|
|
105
91
|
# serialize all attributes
|
106
92
|
def attributes_serialization
|
107
93
|
{
|
108
|
-
"attributes" =>
|
94
|
+
"attributes" => self.attributes
|
109
95
|
}
|
110
96
|
end
|
111
97
|
|
112
98
|
# serialize all properties
|
113
99
|
def properties_serialization
|
114
100
|
{
|
115
|
-
"properties" =>
|
101
|
+
"properties" => self.properties
|
116
102
|
}
|
117
103
|
end
|
118
104
|
|
119
105
|
# xml dump serialization option
|
120
106
|
def xml_serialization
|
121
107
|
{
|
122
|
-
"xml" => xml
|
108
|
+
"xml" => self.xml
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
# tweak the dbrow out since we hacked dbrow for other purposes
|
113
|
+
# and since the xml field doesn't display typically
|
114
|
+
def dbrow_serialization
|
115
|
+
dbrow = super["dbrow"]
|
116
|
+
dbrow[:xml] = self.xml
|
117
|
+
dbrow.delete(:_xml_entity_created_by)
|
118
|
+
dbrow.delete(:_xml_entity_created_at)
|
119
|
+
dbrow.delete(:_xml_entity_modified_by)
|
120
|
+
dbrow.delete(:_xml_entity_modified_at)
|
121
|
+
|
122
|
+
{
|
123
|
+
"dbrow" => dbrow
|
123
124
|
}
|
124
125
|
end
|
126
|
+
|
127
|
+
def self.all_serializations
|
128
|
+
[ :default, :attributes, :properties, :xml ]
|
129
|
+
end
|
125
130
|
end
|
126
131
|
end
|
data/lib/sakai-info/site.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# SakaiInfo::Site library
|
3
3
|
#
|
4
4
|
# Created 2012-02-17 daveadams@gmail.com
|
5
|
-
# Last updated 2012-02-
|
5
|
+
# Last updated 2012-02-28 daveadams@gmail.com
|
6
6
|
#
|
7
7
|
# https://github.com/daveadams/sakai-info
|
8
8
|
#
|
@@ -273,7 +273,7 @@ module SakaiInfo
|
|
273
273
|
"pending_quiz_count" => self.pending_quiz_count,
|
274
274
|
"published_quiz_count" => self.published_quiz_count,
|
275
275
|
"assignment_count" => self.assignment_count,
|
276
|
-
"announcement_count" => self.announcement_count,
|
276
|
+
# "announcement_count" => self.announcement_count,
|
277
277
|
"gradebook_item_count" => (self.gradebook.nil? ? 0 : self.gradebook.item_count),
|
278
278
|
"forum_count" => self.forum_count
|
279
279
|
}
|
@@ -445,7 +445,7 @@ module SakaiInfo
|
|
445
445
|
if @@cache[id].nil?
|
446
446
|
row = DB.connect[:sakai_site_page].where(:page_id => id).first
|
447
447
|
if row.nil?
|
448
|
-
raise ObjectNotFoundException(Page, id)
|
448
|
+
raise ObjectNotFoundException.new(Page, id)
|
449
449
|
end
|
450
450
|
|
451
451
|
site = Site.find(row[:site_id])
|
data/lib/sakai-info/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sakai-info
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 1
|
10
|
+
version: 0.3.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- David Adams
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-02-
|
18
|
+
date: 2012-02-29 00:00:00 -06:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|