sakai-info 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,109 @@
1
+ # sakai-info/question_pool.rb
2
+ # SakaiInfo::QuestionPool library
3
+ #
4
+ # Created 2012-02-26 daveadams@gmail.com
5
+ # Last updated 2012-02-26 daveadams@gmail.com
6
+ #
7
+ # https://github.com/daveadams/sakai-info
8
+ #
9
+ # This software is public domain.
10
+ #
11
+
12
+ module SakaiInfo
13
+ class QuestionPool < SakaiObject
14
+ attr_reader :title, :owner, :description, :parent_pool_id, :dbrow
15
+
16
+ include ModProps
17
+ created_at_key :datecreated
18
+ created_by_key :ownerid
19
+ modified_at_key :lastmodifieddate
20
+ modified_by_key :lastmodifiedby
21
+
22
+ def initialize(dbrow)
23
+ @dbrow = dbrow
24
+
25
+ @id = dbrow[:questionpoolid]
26
+ @title = dbrow[:title]
27
+ @description = dbrow[:description]
28
+ @owner = User.find(dbrow[:ownerid])
29
+ @parent_pool_id = dbrow[:parentpoolid]
30
+ @parent_pool_id = nil if @parent_pool_id == 0
31
+ end
32
+
33
+ @@cache = {}
34
+ def self.find(id)
35
+ if @@cache[id].nil?
36
+ row = DB.connect[:sam_questionpool_t].filter(:questionpoolid => id).first
37
+ if row.nil?
38
+ raise ObjectNotFoundException.new(QuestionPool, id)
39
+ end
40
+ @@cache[id] = QuestionPool.new(row)
41
+ end
42
+ @@cache[id]
43
+ end
44
+
45
+ def self.find_by_user_id(user_id)
46
+ results = []
47
+ DB.connect[:sam_questionpool_t].filter(:ownerid => user_id).all.each do |row|
48
+ id = row[:questionpoolid]
49
+ @@cache[id] = QuestionPool.new(row)
50
+ results << @@cache[id]
51
+ end
52
+ results
53
+ end
54
+
55
+ def self.count_by_user_id(user_id)
56
+ DB.connect[:sam_questionpool_t].filter(:ownerid => user_id).count
57
+ end
58
+
59
+ def item_count
60
+ @item_count ||=
61
+ DB.connect[:sam_questionpoolitem_t].filter(:questionpoolid => @id).count
62
+ end
63
+
64
+ def parent
65
+ if not @parent_pool_id.nil?
66
+ @parent ||= QuestionPool.find(@parent_pool_id)
67
+ end
68
+ end
69
+
70
+ # serialization
71
+ def default_serialization
72
+ result = {
73
+ "id" => self.id,
74
+ "title" => self.title,
75
+ "owner" => self.owner.serialize(:summary),
76
+ "parent" => nil,
77
+ "item_count" => self.item_count
78
+ }
79
+ if not self.parent.nil?
80
+ result["parent"] = self.parent.serialize(:summary)
81
+ else
82
+ result.delete("parent")
83
+ end
84
+ result
85
+ end
86
+
87
+ def summary_serialization
88
+ result = {
89
+ "id" => self.id,
90
+ "title" => self.title,
91
+ "owner_eid" => self.owner.eid,
92
+ "parent_pool_id" => self.parent_pool_id,
93
+ "item_count" => self.item_count
94
+ }
95
+ if result["parent_pool_id"].nil?
96
+ result.delete("parent_pool_id")
97
+ end
98
+ result
99
+ end
100
+
101
+ def user_summary_serialization
102
+ {
103
+ "id" => self.id,
104
+ "title" => self.title,
105
+ "item_count" => self.item_count
106
+ }
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,535 @@
1
+ # sakai-info/quiz.rb
2
+ # SakaiInfo::Quiz library
3
+ #
4
+ # Created 2012-02-17 daveadams@gmail.com
5
+ # Last updated 2012-02-26 daveadams@gmail.com
6
+ #
7
+ # https://github.com/daveadams/sakai-info
8
+ #
9
+ # This software is public domain.
10
+ #
11
+
12
+ module SakaiInfo
13
+ class Quiz < SakaiObject
14
+ attr_reader :title, :site, :dbrow
15
+
16
+ include ModProps
17
+ created_by_key :createdby
18
+ created_at_key :createddate
19
+ modified_by_key :lastmodifiedby
20
+ modified_at_key :lastmodifieddate
21
+
22
+ # a note about quizzes:
23
+ # they do not link directly back to sites
24
+ # instead, they link back only via the sam_authzdata_t table
25
+ def initialize(dbrow, site = nil)
26
+ @site = nil
27
+ if site.is_a? String
28
+ begin
29
+ @site = Site.find(site)
30
+ rescue ObjectNotFoundException
31
+ @site = nil
32
+ end
33
+ elsif site.is_a? Site
34
+ @site = site
35
+ end
36
+
37
+ @id = dbrow[:id]
38
+ @title = dbrow[:title]
39
+ @dbrow = dbrow
40
+
41
+ if @site.nil?
42
+ # published quizzes map to site_id via the OWN_PUBLISHED_ASSESSMENT function
43
+ # pending quizzes map to site_id via the EDIT_ASSESSMENT function
44
+ DB.connect[:sam_authzdata_t].select(:distinct.sql_function(:agentid)).
45
+ where(:qualifierid => @id).
46
+ where(:functionid => ["OWN_PUBLISHED_ASSESSMENT","EDIT_ASSESSMENT"]).
47
+ all.each do |row|
48
+ begin
49
+ site = Site.find(row[:agentid])
50
+ @site = site
51
+ rescue ObjectNotFoundException
52
+ @site = nil
53
+ end
54
+ break if not @site.nil?
55
+ end
56
+ end
57
+ end
58
+
59
+ @@cache = {}
60
+ def self.find(id)
61
+ id = id.to_s
62
+ if @@cache[id].nil?
63
+ quiz = nil
64
+ begin
65
+ quiz = PendingQuiz.find(id)
66
+ rescue ObjectNotFoundException
67
+ begin
68
+ quiz = PublishedQuiz.find(id)
69
+ rescue ObjectNotFoundException
70
+ raise ObjectNotFoundException.new(Quiz, id)
71
+ end
72
+ end
73
+ @@cache[id] = quiz
74
+ end
75
+ @@cache[id]
76
+ end
77
+
78
+ def self.find_by_site_id(site_id)
79
+ {
80
+ "pending" => PendingQuiz.find_by_site_id(site_id),
81
+ "published" => PublishedQuiz.find_by_site_id(site_id)
82
+ }
83
+ end
84
+
85
+ def self.count_by_site_id(site_id)
86
+ {
87
+ "pending_count" => PendingQuiz.count_by_site_id(site_id),
88
+ "published_count" => PublishedQuiz.count_by_site_id(site_id)
89
+ }
90
+ end
91
+
92
+ def quiz_type
93
+ nil
94
+ end
95
+
96
+ def section_count
97
+ @section_count ||= QuizSection.count_by_quiz_id(@id)
98
+ end
99
+
100
+ def sections
101
+ @sections ||= QuizSection.find_by_quiz_id(@id)
102
+ end
103
+
104
+ def default_serialization
105
+ result = {
106
+ "id" => self.id,
107
+ "title" => self.title,
108
+ "site" => nil,
109
+ "type" => self.quiz_type,
110
+ "section_count" => self.section_count
111
+ }
112
+ if not self.site.nil?
113
+ result["site"] = self.site.serialize(:summary)
114
+ end
115
+ result
116
+ end
117
+
118
+ def summary_serialization
119
+ result = {
120
+ "id" => self.id,
121
+ "title" => self.title,
122
+ "site_id" => nil,
123
+ "type" => self.quiz_type
124
+ }
125
+ if not self.site.nil?
126
+ result["site_id"] = self.site.id
127
+ end
128
+ result
129
+ end
130
+
131
+ def site_summary_serialization
132
+ {
133
+ "id" => self.id,
134
+ "title" => self.title
135
+ }
136
+ end
137
+
138
+ def sections_serialization
139
+ {
140
+ "sections" => self.sections.collect{|s|s.serialize(:quiz_summary)}
141
+ }
142
+ end
143
+ end
144
+
145
+ class PendingQuiz < Quiz
146
+ @@cache = {}
147
+ def self.find(id)
148
+ id = id.to_s
149
+ if @@cache[id].nil?
150
+ row = DB.connect[:sam_assessmentbase_t].filter(:id => id.to_i).first
151
+ if row.nil?
152
+ raise ObjectNotFoundException.new(PendingQuiz, id)
153
+ end
154
+ @@cache[id] = PendingQuiz.new(row)
155
+ end
156
+ @@cache[id]
157
+ end
158
+
159
+ def self.query_by_site_id(site_id)
160
+ db = DB.connect
161
+ db[:sam_assessmentbase_t].
162
+ where(:id =>
163
+ db[:sam_authzdata_t].select(:qualifierid).
164
+ where(:agentid => site_id,
165
+ :functionid => "EDIT_ASSESSMENT"))
166
+ end
167
+
168
+ def self.find_by_site_id(site_id)
169
+ results = []
170
+ PendingQuiz.query_by_site_id(site_id).all.each do |row|
171
+ @@cache[row[:id]] = PendingQuiz.new(row, site_id)
172
+ results << @@cache[row[:id]]
173
+ end
174
+ results
175
+ end
176
+
177
+ def self.count_by_site_id(site_id)
178
+ PendingQuiz.query_by_site_id(site_id).count
179
+ end
180
+
181
+ def quiz_type
182
+ "pending"
183
+ end
184
+ end
185
+
186
+ class PublishedQuiz < Quiz
187
+ @@cache = {}
188
+ def self.find(id)
189
+ id = id.to_s
190
+ if @@cache[id].nil?
191
+ row = DB.connect[:sam_publishedassessment_t].filter(:id => id.to_i).first
192
+ if row.nil?
193
+ raise ObjectNotFoundException.new(PublishedQuiz, id)
194
+ end
195
+
196
+ @@cache[id] = PublishedQuiz.new(row)
197
+ end
198
+ @@cache[id]
199
+ end
200
+
201
+ def self.query_by_site_id(site_id)
202
+ db = DB.connect
203
+ db[:sam_publishedassessment_t].
204
+ where(:id =>
205
+ db[:sam_authzdata_t].select(:qualifierid).
206
+ where(:agentid => site_id,
207
+ :functionid => "OWN_PUBLISHED_ASSESSMENT"))
208
+ end
209
+
210
+ def self.find_by_site_id(site_id)
211
+ results = []
212
+ PublishedQuiz.query_by_site_id(site_id).all.each do |row|
213
+ @@cache[row[:id]] = PublishedQuiz.new(row, site_id)
214
+ results << @@cache[row[:id]]
215
+ end
216
+ results
217
+ end
218
+
219
+ def self.count_by_site_id(site_id)
220
+ PublishedQuiz.query_by_site_id(site_id).count
221
+ end
222
+
223
+ def quiz_type
224
+ "published"
225
+ end
226
+ end
227
+
228
+ class QuizSection < SakaiObject
229
+ attr_reader :dbrow, :quiz, :sequence, :title, :description, :typeid, :status
230
+
231
+ include ModProps
232
+ created_by_key :createdby
233
+ created_at_key :createddate
234
+ modified_by_key :lastmodifiedby
235
+ modified_at_key :lastmodifieddate
236
+
237
+ def initialize(dbrow)
238
+ @dbrow = dbrow
239
+
240
+ @id = dbrow[:sectionid]
241
+ @quiz = Quiz.find(dbrow[:assessmentid])
242
+ @sequence = dbrow[:sequence]
243
+ @title = dbrow[:title]
244
+ @description = dbrow[:description]
245
+ @typeid = dbrow[:typeid]
246
+ @status = dbrow[:status]
247
+ end
248
+
249
+ @@cache = {}
250
+ def self.find(id)
251
+ id = id.to_s
252
+ if @@cache[id].nil?
253
+ begin
254
+ @@cache[id] = PendingQuizSection.find(id)
255
+ rescue ObjectNotFoundException
256
+ begin
257
+ @@cache[id] = PublishedQuizSection.find(id)
258
+ rescue ObjectNotFoundException
259
+ raise ObjectNotFoundException(QuizSection, id)
260
+ end
261
+ end
262
+ end
263
+ @@cache[id]
264
+ end
265
+
266
+ def self.query_by_quiz_id(quiz_id)
267
+ table = if Quiz.find(quiz_id).quiz_type == "pending"
268
+ :sam_section_t
269
+ else
270
+ :sam_publishedsection_t
271
+ end
272
+ DB.connect[table].where(:assessmentid => quiz_id).order(:sequence)
273
+ end
274
+
275
+ def self.find_by_quiz_id(quiz_id)
276
+ section_class = if Quiz.find(quiz_id).quiz_type == "pending"
277
+ PendingQuizSection
278
+ else
279
+ PublishedQuizSection
280
+ end
281
+
282
+ QuizSection.query_by_quiz_id(quiz_id).all.collect do |row|
283
+ section_class.new(row)
284
+ end
285
+ end
286
+
287
+ def self.count_by_quiz_id(quiz_id)
288
+ QuizSection.query_by_quiz_id(quiz_id).count
289
+ end
290
+
291
+ def section_type
292
+ nil
293
+ end
294
+
295
+ def item_count
296
+ @item_count ||= QuizItem.count_by_section_id(@id)
297
+ end
298
+
299
+ def items
300
+ @items ||= QuizItem.find_by_section_id(@id)
301
+ end
302
+
303
+ def default_serialization
304
+ {
305
+ "id" => self.id,
306
+ "title" => self.title,
307
+ "quiz" => self.quiz.serialize(:summary),
308
+ "sequence" => self.sequence,
309
+ "item_count" => self.item_count,
310
+ "description" => self.description,
311
+ "type" => self.section_type,
312
+ "typeid" => self.typeid,
313
+ "status" => self.status
314
+ }
315
+ end
316
+
317
+ def summary_serialization
318
+ {
319
+ "id" => self.id,
320
+ "title" => self.title,
321
+ "quiz_id" => self.quiz.id,
322
+ "sequence" => self.sequence
323
+ }
324
+ end
325
+
326
+ def quiz_summary_serialization
327
+ result = summary_serialization
328
+ result.delete("quiz_id")
329
+ result
330
+ end
331
+
332
+ def items_serialization
333
+ {
334
+ "items" => self.items.collect{|i|i.serialize(:summary)}
335
+ }
336
+ end
337
+
338
+ def self.all_serializations
339
+ [:default, :items, :mod]
340
+ end
341
+ end
342
+
343
+ class PendingQuizSection < QuizSection
344
+ @@cache = {}
345
+ def self.find(id)
346
+ id = id.to_s
347
+ if @@cache[id].nil?
348
+ row = DB.connect[:sam_section_t].where(:sectionid => id).first
349
+ if row.nil?
350
+ raise ObjectNotFoundException(PendingQuizSection, id)
351
+ end
352
+
353
+ @@cache[id] = PendingQuizSection.new(row)
354
+ end
355
+ @@cache[id]
356
+ end
357
+
358
+ def section_type
359
+ "pending"
360
+ end
361
+ end
362
+
363
+ class PublishedQuizSection < QuizSection
364
+ @@cache = {}
365
+ def self.find(id)
366
+ id = id.to_s
367
+ if @@cache[id].nil?
368
+ row = DB.connect[:sam_publishedsection_t].where(:sectionid => id).first
369
+ if row.nil?
370
+ raise ObjectNotFoundException(PublishedQuizSection, id)
371
+ end
372
+
373
+ @@cache[id] = PublishedQuizSection.new(row)
374
+ end
375
+ @@cache[id]
376
+ end
377
+
378
+ def section_type
379
+ "published"
380
+ end
381
+ end
382
+
383
+ class QuizItem < SakaiObject
384
+ attr_reader :dbrow, :section, :quiz, :sequence, :typeid
385
+
386
+ include ModProps
387
+ created_by_key :createdby
388
+ created_at_key :createddate
389
+ modified_by_key :lastmodifiedby
390
+ modified_at_key :lastmodifieddate
391
+
392
+ def initialize(dbrow)
393
+ @dbrow = dbrow
394
+
395
+ @id = dbrow[:itemid]
396
+ @section = QuizSection.find(dbrow[:sectionid])
397
+ @quiz = @section.quiz
398
+ @sequence = dbrow[:sequence]
399
+ @typeid = dbrow[:typeid]
400
+ end
401
+
402
+ @@cache = {}
403
+ def self.find(id)
404
+ id = id.to_s
405
+ if @@cache[id].nil?
406
+ begin
407
+ @@cache[id] = PendingQuizItem.find(id)
408
+ rescue ObjectNotFoundException
409
+ begin
410
+ @@cache[id] = PublishedQuizItem.find(id)
411
+ rescue ObjectNotFoundException
412
+ raise ObjectNotFoundException(QuizItem, id)
413
+ end
414
+ end
415
+ end
416
+ @@cache[id]
417
+ end
418
+
419
+ def self.table_name_for_type(type)
420
+ if type == "pending"
421
+ :sam_item_t
422
+ else
423
+ :sam_publisheditem_t
424
+ end
425
+ end
426
+
427
+ def self.class_for_type(type)
428
+ if type == "pending"
429
+ PendingQuizItem
430
+ else
431
+ PublishedQuizItem
432
+ end
433
+ end
434
+
435
+ def self.query_by_section_id(section_id)
436
+ table = QuizItem.table_name_for_type(QuizSection.find(section_id).section_type)
437
+ DB.connect[table].where(:sectionid => section_id).order(:sequence)
438
+ end
439
+
440
+ def self.count_by_section_id(section_id)
441
+ QuizItem.query_by_section_id(section_id).count
442
+ end
443
+
444
+ def self.find_by_section_id(section_id)
445
+ item_class = QuizItem.class_for_type(QuizSection.find(section_id).section_type)
446
+ QuizItem.query_by_section_id(section_id).all.collect do |row|
447
+ item_class.new(row)
448
+ end
449
+ end
450
+
451
+ def self.query_by_quiz_id(quiz_id)
452
+ table = QuizItem.table_name_for_type(Quiz.find(quiz_id).quiz_type)
453
+ DB.connect[table].
454
+ where(:sectionid => Quiz.find(quiz_id).sections.collect{|s|s.id})
455
+ end
456
+
457
+ def self.count_by_quiz_id(quiz_id)
458
+ QuizItem.query_by_quiz_id(quiz_id).count
459
+ end
460
+
461
+ def self.find_by_quiz_id(quiz_id)
462
+ item_class = QuizItem.class_for_type(Quiz.find(quiz_id).quiz_type)
463
+ QuizItem.query_by_quiz_id(quiz_id).all.collect do |row|
464
+ item_class.new(row)
465
+ end
466
+ end
467
+
468
+ def item_type
469
+ nil
470
+ end
471
+
472
+ def default_serialization
473
+ {
474
+ "id" => self.id,
475
+ "quiz" => self.quiz.serialize(:summary),
476
+ "section" => self.section.serialize(:summary),
477
+ "sequence" => self.sequence,
478
+ "type" => self.item_type,
479
+ "typeid" => self.typeid
480
+ }
481
+ end
482
+
483
+ def summary_serialization
484
+ {
485
+ "id" => self.id,
486
+ "quiz_id" => self.quiz.id,
487
+ "section_id" => self.section.id
488
+ }
489
+ end
490
+
491
+ def self.all_serializations
492
+ [:default, :mod]
493
+ end
494
+ end
495
+
496
+ class PendingQuizItem < QuizItem
497
+ @@cache = {}
498
+ def self.find(id)
499
+ id = id.to_s
500
+ if @@cache[id].nil?
501
+ row = DB.connect[:sam_item_t].where(:itemid => id).first
502
+ if row.nil?
503
+ raise ObjectNotFoundException(PendingQuizItem, id)
504
+ end
505
+
506
+ @@cache[id] = PendingQuizItem.new(row)
507
+ end
508
+ @@cache[id]
509
+ end
510
+
511
+ def item_type
512
+ "pending"
513
+ end
514
+ end
515
+
516
+ class PublishedQuizItem < QuizItem
517
+ @@cache = {}
518
+ def self.find(id)
519
+ id = id.to_s
520
+ if @@cache[id].nil?
521
+ row = DB.connect[:sam_publisheditem_t].where(:itemid => id).first
522
+ if row.nil?
523
+ raise ObjectNotFoundException(PublishedQuizItem, id)
524
+ end
525
+
526
+ @@cache[id] = PublishedQuizItem.new(row)
527
+ end
528
+ @@cache[id]
529
+ end
530
+
531
+ def item_type
532
+ "published"
533
+ end
534
+ end
535
+ end