sakai-info 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,58 @@
1
+ # sakai_object.rb
2
+ # SakaiInfo::SakaiObject
3
+ #
4
+ # Created 2012-02-15 daveadams@gmail.com
5
+ # Last updated 2012-02-18 daveadams@gmail.com
6
+ #
7
+ # https://github.com/daveadams/sakai-info
8
+ #
9
+ # This software is public domain.
10
+ #
11
+
12
+ module SakaiInfo
13
+ # this class forms the basis of all other Sakai object abstractions
14
+ class SakaiObject
15
+ # most objects will have unique IDs
16
+ # (perhaps the rest should generate their own?)
17
+ attr_reader :id
18
+
19
+ def serialize(*q)
20
+ q.flatten!
21
+
22
+ if q.length == 0
23
+ q = [:default]
24
+ end
25
+
26
+ serialization = {}
27
+ q.each do |sub|
28
+ sub_method_name = (sub.to_s + "_serialization").to_sym
29
+ begin
30
+ sub_method = self.method(sub_method_name)
31
+ serialization = serialization.merge(sub_method.call)
32
+ rescue NameError
33
+ # ignore any missing serialization patterns
34
+ end
35
+ end
36
+
37
+ serialization
38
+ end
39
+
40
+ def object_type_serialization
41
+ {
42
+ "sakai_object_type" => self.class
43
+ }
44
+ end
45
+
46
+ def default_serialization
47
+ object_type_serialization
48
+ end
49
+
50
+ def to_yaml
51
+ serialize.to_yaml
52
+ end
53
+
54
+ def to_json
55
+ serialize.to_json
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,126 @@
1
+ # sakai_xml_entity.rb
2
+ # SakaiInfo::SakaiXMLEntity
3
+ #
4
+ # Created 2012-02-16 daveadams@gmail.com
5
+ # Last updated 2012-02-18 daveadams@gmail.com
6
+ #
7
+ # https://github.com/daveadams/sakai-info
8
+ #
9
+ # This software is public domain.
10
+ #
11
+
12
+ module SakaiInfo
13
+ # exception class for unrecognized property encodings
14
+ class UnrecognizedPropertyEncodingException < SakaiException
15
+ attr_reader :name, :encoding, :value
16
+
17
+ def initialize(name, encoding, value)
18
+ @name = name
19
+ @encoding = encoding
20
+ @value = value
21
+
22
+ super("Unrecognized property encoding '#{@encoding}' for property '#{@name}'")
23
+ end
24
+ end
25
+
26
+ # This class is the base for Sakai XML-based entities, which are many of the
27
+ # earliest data types in the Sakai database. Most properties of these objects
28
+ # are stored in a large XML clob/text field, and some are base64-encoded as
29
+ # well. Thus each record must be deserialized to read the various properties.
30
+ #
31
+ # Most XML entities consist of a top-level tag representing the entity with
32
+ # a number of attributes attached representing some of the properties of the
33
+ # entity. And then there are "property" tags inside the top-level tag
34
+ # which represent some other properties, including some defaults recording
35
+ # the creator and modifier and the times of those accesses.
36
+ #
37
+ # This class extends SakaiObject and implements some additional
38
+ # serialization methods to reflect the common elements of XML entities.
39
+ class SakaiXMLEntity < SakaiObject
40
+ attr_reader :xml, :xmldoc, :attributes, :properties
41
+
42
+ private
43
+ # this method parses the universal XML field for all entities
44
+ # down to two collections: attributes (XML attributes defined in the
45
+ # top-level tag) and properties (<property> tags inside the top-level
46
+ # tag). Properties are generally base64 encoded
47
+ def parse_xml
48
+ @xmldoc = REXML::Document.new(@xml)
49
+ @attributes = {}
50
+ @xmldoc.root.attributes.keys.each do |att_name|
51
+ @attributes[att_name] = @xmldoc.root.attributes[att_name]
52
+ end
53
+
54
+ @properties = {}
55
+ REXML::XPath.each(@xmldoc, "//property") do |prop_node|
56
+ prop_name = prop_node.attributes["name"]
57
+ prop_encoding = prop_node.attributes["enc"]
58
+ prop_value = prop_node.attributes["value"]
59
+
60
+ if prop_encoding == "BASE64"
61
+ prop_value = Base64.decode64(prop_value)
62
+ else
63
+ raise UnrecognizedPropertyEncodingException(prop_name, prop_encoding, prop_value)
64
+ end
65
+ @properties[prop_name] = prop_value
66
+ 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
+
89
+ # standard property for all entities
90
+ def modified_at
91
+ format_entity_date(@properties["DAV:getlastmodified"])
92
+ end
93
+
94
+ # by default, serialize all the common properties
95
+ def default_serialization
96
+ {
97
+ "id" => self.id,
98
+ "created_by" => self.created_by,
99
+ "created_at" => self.created_at,
100
+ "modified_by" => self.modified_by,
101
+ "modified_at" => self.modified_at
102
+ }
103
+ end
104
+
105
+ # serialize all attributes
106
+ def attributes_serialization
107
+ {
108
+ "attributes" => @attributes
109
+ }
110
+ end
111
+
112
+ # serialize all properties
113
+ def properties_serialization
114
+ {
115
+ "properties" => @properties
116
+ }
117
+ end
118
+
119
+ # xml dump serialization option
120
+ def xml_serialization
121
+ {
122
+ "xml" => xml
123
+ }
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,219 @@
1
+ # sakai-info/samigo.rb
2
+ # SakaiInfo::Samigo library
3
+ #
4
+ # Created 2012-02-17 daveadams@gmail.com
5
+ # Last updated 2012-02-18 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 PendingQuiz < SakaiObject
14
+ attr_reader :title, :site
15
+
16
+ def initialize(id, title, site)
17
+ @id = id
18
+ @title = title
19
+ @site = site
20
+ end
21
+
22
+ @@cache = {}
23
+ def self.find(id)
24
+ if @@cache[id].nil?
25
+ DB.connect.exec("select title, agent_id from sam_assessmentbase_t " +
26
+ "where id=:quizid", id) do |row|
27
+ @@cache[id] = PendingQuiz.new(id, row[0], Site.find(row[1]))
28
+ end
29
+ if @@cache[id].nil?
30
+ raise ObjectNotFoundException.new(PendingQuiz, id)
31
+ end
32
+ end
33
+ @@cache[id]
34
+ end
35
+
36
+ def self.find_by_site_id(site_id)
37
+ results = []
38
+ site = Site.find(site_id)
39
+ DB.connect.exec("select id, title from sam_assessmentbase_t " +
40
+ "where id in (select qualifierid from sam_authzdata_t " +
41
+ "where agentid=:site_id and " +
42
+ "functionid='EDIT_ASSESSMENT')", site_id) do |row|
43
+ @@cache[row[0]] = PendingQuiz.new(row[0].to_i, row[1], site)
44
+ results << @@cache[row[0]]
45
+ end
46
+ results
47
+ end
48
+
49
+ def self.count_by_site_id(site_id)
50
+ count = 0
51
+ DB.connect.exec("select count(*) from sam_publishedassessment_t " +
52
+ "where id in (select qualifierid from sam_authzdata_t " +
53
+ "where agentid=:site_id and " +
54
+ "functionid='EDIT_ASSESSMENT')", site_id) do |row|
55
+ count = row[0].to_i
56
+ end
57
+ count
58
+ end
59
+
60
+ def default_serialization
61
+ {
62
+ "id" => self.id,
63
+ "title" => self.title,
64
+ "site_id" => self.site.id
65
+ }
66
+ end
67
+
68
+ def summary_serialization
69
+ {
70
+ "id" => self.id,
71
+ "title" => self.title
72
+ }
73
+ end
74
+ end
75
+
76
+ class PublishedQuiz < SakaiObject
77
+ attr_reader :title, :site
78
+
79
+ def initialize(id, title, site)
80
+ @id = id
81
+ @title = title
82
+ @site = site
83
+ end
84
+
85
+ @@cache = {}
86
+ def self.find(id)
87
+ if @@cache[id].nil?
88
+ DB.connect.exec("select title, agent_id from sam_publishedassessment_t " +
89
+ "where id=:quizid", id) do |row|
90
+ @@cache[id] = PublishedQuiz.new(id, row[0], Site.find(row[1]))
91
+ end
92
+ if @@cache[id].nil?
93
+ raise ObjectNotFoundException.new(PublishedQuiz, id)
94
+ end
95
+ end
96
+ @@cache[id]
97
+ end
98
+
99
+ def self.find_by_site_id(site_id)
100
+ results = []
101
+ site = Site.find(site_id)
102
+ DB.connect.exec("select id, title from sam_publishedassessment_t " +
103
+ "where id in (select qualifierid from sam_authzdata_t " +
104
+ "where agentid=:site_id and " +
105
+ "functionid='OWN_PUBLISHED_ASSESSMENT')", site_id) do |row|
106
+ @@cache[row[0]] = PublishedQuiz.new(row[0].to_i, row[1], site)
107
+ results << @@cache[row[0]]
108
+ end
109
+ results
110
+ end
111
+
112
+ def self.count_by_site_id(site_id)
113
+ count = 0
114
+ DB.connect.exec("select count(*) from sam_publishedassessment_t " +
115
+ "where id in (select qualifierid from sam_authzdata_t " +
116
+ "where agentid=:site_id " +
117
+ "and functionid='OWN_PUBLISHED_ASSESSMENT')", site_id) do |row|
118
+ count = row[0].to_i
119
+ end
120
+ count
121
+ end
122
+
123
+ def default_serialization
124
+ {
125
+ "id" => self.id,
126
+ "title" => self.title,
127
+ "site_id" => self.site.id
128
+ }
129
+ end
130
+
131
+ def summary_serialization
132
+ {
133
+ "id" => self.id,
134
+ "title" => self.title
135
+ }
136
+ end
137
+ end
138
+
139
+ class QuestionPool < SakaiObject
140
+ attr_reader :title, :owner
141
+
142
+ def initialize(id, title, owner)
143
+ @id = id
144
+ @title = title
145
+ @owner = owner
146
+ end
147
+
148
+ @@cache = {}
149
+ def self.find(id)
150
+ if @@cache[id].nil?
151
+ DB.connect.exec("select title, ownerid from sam_questionpool_t " +
152
+ "where questionpoolid=:id", id) do |row|
153
+ @@cache[id] = QuestionPool.new(id, row[0], User.find(row[1]))
154
+ end
155
+ if @@cache[id].nil?
156
+ raise ObjectNotFoundException.new(QuestionPool, id)
157
+ end
158
+ end
159
+ @@cache[id]
160
+ end
161
+
162
+ def self.find_by_user_id(user_id)
163
+ results = []
164
+ user = User.find(user_id)
165
+ DB.connect.exec("select questionpoolid, title from sam_questionpool_t " +
166
+ "where ownerid=:userid", user_id) do |row|
167
+ @@cache[row[0]] = QuestionPool.new(row[0].to_i, row[1], user)
168
+ results << @@cache[row[0]]
169
+ end
170
+ results
171
+ end
172
+
173
+ def self.count_by_user_id(user_id)
174
+ count = 0
175
+ DB.connect.exec("select count(*) from sam_questionpool_t " +
176
+ "where ownerid=:userid", user_id) do |row|
177
+ count = row[0].to_i
178
+ end
179
+ count
180
+ end
181
+
182
+ def item_count
183
+ if @item_count.nil?
184
+ DB.connect.exec("select count(*) from sam_questionpoolitem_t " +
185
+ "where questionpoolid=:id", @id) do |row|
186
+ @item_count = row[0].to_i
187
+ end
188
+ end
189
+ @item_count
190
+ end
191
+
192
+ # serialization
193
+ def default_serialization
194
+ {
195
+ "id" => self.id,
196
+ "title" => self.title,
197
+ "owner" => self.owner.serialize(:summary),
198
+ "item_count" => self.item_count
199
+ }
200
+ end
201
+
202
+ def summary_serialization
203
+ {
204
+ "id" => self.id,
205
+ "title" => self.title,
206
+ "owner_eid" => self.owner.eid,
207
+ "item_count" => self.item_count
208
+ }
209
+ end
210
+
211
+ def user_summary_serialization
212
+ {
213
+ "id" => self.id,
214
+ "title" => self.title,
215
+ "item_count" => self.item_count
216
+ }
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,752 @@
1
+ # sakai-info/site.rb
2
+ # SakaiInfo::Site library
3
+ #
4
+ # Created 2012-02-17 daveadams@gmail.com
5
+ # Last updated 2012-02-17 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 Site < SakaiObject
14
+ attr_reader :title, :type
15
+ attr_reader :created_at, :modified_at
16
+
17
+ @@cache = {}
18
+ def self.find(id)
19
+ if @@cache[id].nil?
20
+ site_id = title = type = created_at = created_by_user_id =
21
+ modified_at = modified_by_user_id = joinable = join_role = nil
22
+ DB.connect.exec("select site_id, title, type, " +
23
+ "createdby, to_char(createdon,'YYYY-MM-DD HH24:MI:SS'), " +
24
+ "modifiedby, to_char(modifiedon,'YYYY-MM-DD HH24:MI:SS'), " +
25
+ "joinable, join_role " +
26
+ "from sakai_site where site_id = :site_id", id) do |row|
27
+ site_id, title, type, created_by_user_id, created_at, modified_by_user_id, modified_at, joinable_n, join_role = *row
28
+ if joinable_n.to_i == 1
29
+ joinable = true
30
+ else
31
+ joinable = false
32
+ end
33
+ end
34
+ if site_id.nil?
35
+ raise ObjectNotFoundException.new(Site, id)
36
+ end
37
+ @@cache[id] = Site.new(id, title, type, created_by_user_id, created_at, modified_by_user_id, modified_at, joinable, join_role)
38
+ end
39
+ @@cache[id]
40
+ end
41
+
42
+ def initialize(id, title, type, created_by_user_id, created_at, modified_by_user_id, modified_at, joinable, join_role)
43
+ @id = id
44
+ @title = title
45
+ @type = type
46
+ @created_by_user_id = created_by_user_id
47
+ @created_at = created_at
48
+ @modified_by_user_id = modified_by_user_id
49
+ @modified_at = modified_at
50
+ @joinable = joinable
51
+ @join_role_string = join_role.to_s
52
+ end
53
+
54
+ def joinable?
55
+ @joinable
56
+ end
57
+
58
+ def join_role
59
+ @join_role_string
60
+ end
61
+
62
+ def properties
63
+ @properties ||= SiteProperty.find_by_site_id(@id)
64
+ end
65
+
66
+ def membership
67
+ @membership ||= SiteMembership.find_by_site_id(@id)
68
+ end
69
+
70
+ def pages
71
+ @pages ||= Page.find_by_site_id(@id)
72
+ end
73
+
74
+ def assignments
75
+ @assignments ||= Assignment.find_by_site_id(@id)
76
+ end
77
+
78
+ def created_by
79
+ @created_by ||= User.find(@created_by_user_id)
80
+ end
81
+
82
+ def modified_by
83
+ @modified_by ||= User.find(@modified_by_user_id)
84
+ end
85
+
86
+ def user_count
87
+ if @user_count.nil?
88
+ DB.connect.exec("select count(*) from sakai_site_user " +
89
+ "where site_id=:siteid", @id) do |row|
90
+ @user_count = row[0].to_i
91
+ end
92
+ end
93
+ @user_count
94
+ end
95
+
96
+ def page_count
97
+ if @page_count.nil?
98
+ DB.connect.exec("select count(*) from sakai_site_page " +
99
+ "where site_id=:siteid", @id) do |row|
100
+ @page_count = row[0].to_i
101
+ end
102
+ end
103
+ @page_count
104
+ end
105
+
106
+ def assignment_count
107
+ @assignment_count ||= Assignment.count_by_site_id(@id)
108
+ end
109
+
110
+ # authz/realm properties
111
+ def realm
112
+ @authz_realm ||= AuthzRealm.find_by_site_id(@id)
113
+ end
114
+
115
+ def join_role
116
+ @join_role ||= AuthzRole.find_by_name(@join_role_string)
117
+ end
118
+
119
+ # group properties
120
+ def group_count
121
+ @group_count ||= Group.count_by_site_id(@id)
122
+ end
123
+
124
+ def groups
125
+ @groups ||= Group.find_by_site_id(@id)
126
+ end
127
+
128
+ # announcement properties
129
+ def announcements
130
+ @announcements ||= AnnouncementChannel.find_by_site_id(@id).announcements
131
+ end
132
+
133
+ def announcement_count
134
+ @announcement_count ||= AnnouncementChannel.find_by_site_id(@id).announcement_count
135
+ end
136
+
137
+ # samigo quiz properties
138
+ def published_quiz_count
139
+ @published_quiz_count ||= PublishedQuiz.count_by_site_id(@id)
140
+ end
141
+
142
+ def pending_quiz_count
143
+ @pending_quiz_count ||= PendingQuiz.count_by_site_id(@id)
144
+ end
145
+
146
+ def published_quizzes
147
+ @published_quizzes ||= PublishedQuiz.find_by_site_id(@id)
148
+ end
149
+
150
+ def pending_quizzes
151
+ @pending_quizzes ||= PendingQuiz.find_by_site_id(@id)
152
+ end
153
+
154
+ # gradebook properties
155
+ def gradebook
156
+ @gradebook ||= Gradebook.find_by_site_id(@id)
157
+ rescue ObjectNotFoundException
158
+ # not all sites have a gradebook, don't panic
159
+ nil
160
+ end
161
+
162
+ # forum properties
163
+ def forum_count
164
+ @forum_count ||= Forum.count_by_site_id(@id)
165
+ end
166
+
167
+ def forums
168
+ @forums ||= Forum.find_by_site_id(@id)
169
+ end
170
+
171
+ # content properties
172
+ def resource_storage
173
+ resource_collection_id = "/group/#{@id}/"
174
+ if @type == "myworkspace" or @type == "guestworkspace"
175
+ resource_collection_id = "/user/#{@id.sub(/^~/,'')}"
176
+ end
177
+ @resource_storage ||= ContentCollection.find!(resource_collection_id)
178
+ end
179
+
180
+ def attachment_storage
181
+ attachment_collection_id = "/attachment/#{@id}/"
182
+ @attachment_storage ||= ContentCollection.find!(attachment_collection_id)
183
+ end
184
+
185
+ def melete_storage
186
+ melete_collection_id = "/private/meleteDocs/#{@id}/"
187
+ @melete_storage ||= ContentCollection.find!(melete_collection_id)
188
+ end
189
+
190
+ def dropbox_storage
191
+ dropbox_collection_id = "/group-user/#{@id}/"
192
+ @dropbox_storage ||= ContentCollection.find!(dropbox_collection_id)
193
+ end
194
+
195
+ def total_disk_usage
196
+ resource_storage.size_on_disk + attachment_storage.size_on_disk + melete_storage.size_on_disk + dropbox_storage.size_on_disk
197
+ end
198
+
199
+ # generate a CSV line for disk usage reporting
200
+ def disk_usage_csv
201
+ "#{@id},#{@type},#{resource_storage.size_on_disk},#{attachment_storage.size_on_disk},#{melete_storage.size_on_disk},#{dropbox_storage.size_on_disk},#{total_disk_usage}"
202
+ end
203
+
204
+ # finders/counters
205
+ @@total_site_count = nil
206
+ def self.count
207
+ if @@total_site_count.nil?
208
+ @@total_site_count = 0
209
+ DB.connect.exec("select count(*) from sakai_site") do |row|
210
+ @@total_site_count = row[0].to_i
211
+ end
212
+ end
213
+ @@total_site_count
214
+ end
215
+
216
+ def self.count_by_user_id(user_id)
217
+ user_count = 0
218
+ DB.connect.exec("select count(*) from sakai_site_user " +
219
+ "where user_id=:user_id", user_id) do |row|
220
+ user_count = row[0].to_i
221
+ end
222
+ user_count
223
+ end
224
+
225
+ def self.count_by_type(type)
226
+ type_count = 0
227
+ DB.connect.exec("select count(*) from sakai_site " +
228
+ "where type=:type", type) do |row|
229
+ type_count = row[0].to_i
230
+ end
231
+ type_count
232
+ end
233
+
234
+ def self.count_by_semester(term_eid)
235
+ prop_name = "term_eid"
236
+ sem_count = 0
237
+ DB.connect.exec("select count(*) from sakai_site_property " +
238
+ "where name=:name and to_char(value)=:term_eid",
239
+ prop_name, term_eid) do |row|
240
+ sem_count = row[0].to_i
241
+ end
242
+ sem_count
243
+ end
244
+
245
+ def self.find_all_ids
246
+ ids = []
247
+ DB.connect.exec("select site_id from sakai_site") do |row|
248
+ ids << row[0]
249
+ end
250
+ ids
251
+ end
252
+
253
+ def self.find_all_workspace_ids
254
+ ids = []
255
+ DB.connect.exec("select site_id from sakai_site where site_id like '~%'") do |row|
256
+ ids << row[0]
257
+ end
258
+ ids
259
+ end
260
+
261
+ def self.find_all_non_workspace_ids
262
+ ids = []
263
+ DB.connect.exec("select site_id from sakai_site where site_id not like '~%'") do |row|
264
+ ids << row[0]
265
+ end
266
+ ids
267
+ end
268
+
269
+ def self.find_ids_by_type(type)
270
+ ids = []
271
+ DB.connect.exec("select site_id from sakai_site where type=:type", type) do |row|
272
+ ids << row[0]
273
+ end
274
+ ids
275
+ end
276
+
277
+ def self.find_by_type(type)
278
+ sites = []
279
+ DB.connect.exec("select site_id, title, type, " +
280
+ "createdby, to_char(createdon,'YYYY-MM-DD HH24:MI:SS'), " +
281
+ "modifiedby, to_char(modifiedon,'YYYY-MM-DD HH24:MI:SS'), " +
282
+ "joinable, join_role " +
283
+ "from sakai_site where type = :type", type) do |row|
284
+ joinable = false
285
+ site_id, title, type, created_by_user_id, created_at,
286
+ modified_by_user_id, modified_at, joinable_n, join_role = *row
287
+ if joinable_n.to_i == 1
288
+ joinable = true
289
+ end
290
+ @@cache[site_id] = Site.new(site_id, title, type, created_by_user_id, created_at, modified_by_user_id, modified_at, joinable, join_role)
291
+ sites << @@cache[site_id]
292
+ end
293
+ sites
294
+ end
295
+
296
+ def self.find_ids_by_property(property_name, property_value)
297
+ SiteProperty.find_site_ids_by_property(property_name, property_value)
298
+ end
299
+
300
+ def self.find_ids_by_semester(term_eid)
301
+ find_ids_by_property("term_eid", term_eid)
302
+ end
303
+
304
+ # serialization methods
305
+ def default_serialization
306
+ result = {
307
+ "id" => self.id,
308
+ "title" => self.title,
309
+ "type" => self.type,
310
+ "created_at" => self.created_at,
311
+ "created_by" => self.created_by.serialize(:summary),
312
+ "site_properties" => self.properties,
313
+ "providers" => self.realm.providers,
314
+ "joinable" => self.joinable?,
315
+ "join_role" => (self.joinable? ? self.join_role : nil),
316
+ "user_count" => self.user_count,
317
+ "group_count" => self.group_count,
318
+ "page_count" => self.page_count,
319
+ "pending_quiz_count" => self.pending_quiz_count,
320
+ "published_quiz_count" => self.published_quiz_count,
321
+ "assignment_count" => self.assignment_count,
322
+ "announcement_count" => self.announcement_count,
323
+ "gradebook_item_count" => (self.gradebook.nil? ? 0 : self.gradebook.item_count),
324
+ "forum_count" => self.forum_count
325
+ }
326
+ if result["providers"].nil? or result["providers"] == ""
327
+ result.delete("providers")
328
+ end
329
+ if result["joinable"] == false
330
+ result.delete("join_role")
331
+ end
332
+ if self.gradebook.nil?
333
+ result.delete("gradebook_item_count")
334
+ end
335
+ result
336
+ end
337
+
338
+ def summary_serialization
339
+ {
340
+ "id" => self.id,
341
+ "title" => self.title,
342
+ "type" => self.type,
343
+ "created_by" => self.created_by.eid
344
+ }
345
+ end
346
+
347
+ def users_serialization
348
+ {
349
+ "users" => self.membership.collect { |sm| sm.serialize(:site_summary) }
350
+ }
351
+ end
352
+
353
+ def pages_serialization
354
+ {
355
+ "pages" => self.pages.collect { |pg| pg.serialize(:summary) }
356
+ }
357
+ end
358
+
359
+ def groups_serialization
360
+ {
361
+ "groups" => self.groups.collect { |grp| grp.serialize(:summary) }
362
+ }
363
+ end
364
+
365
+ def quizzes_serialization
366
+ result = {}
367
+ if self.pending_quiz_count > 0 or self.published_quiz_count > 0
368
+ result["quizzes"] = {}
369
+ end
370
+ if self.pending_quiz_count > 0
371
+ result["quizzes"]["pending"] =
372
+ self.pending_quizzes.collect { |pq| pq.serialize(:summary) }
373
+ end
374
+ if self.published_quiz_count > 0
375
+ result["quizzes"]["published"] =
376
+ self.pending_quizzes.collect { |pq| pq.serialize(:summary) }
377
+ end
378
+ result
379
+ end
380
+
381
+ def disk_serialization
382
+ {
383
+ "disk_usage" => {
384
+ "resources" => self.resource_storage.size_on_disk,
385
+ "attachments" => self.attachment_storage.size_on_disk,
386
+ "melete" => self.melete_storage.size_on_disk,
387
+ "dropbox" => self.dropbox_storage.size_on_disk,
388
+ "total" => (self.resource_storage.size_on_disk +
389
+ self.attachment_storage.size_on_disk +
390
+ self.melete_storage.size_on_disk +
391
+ self.dropbox_storage.size_on_disk)
392
+ }
393
+ }
394
+ end
395
+
396
+ def disk_formatted_serialization
397
+ result = disk_serialization["disk_usage"]
398
+ result.keys.each do |key|
399
+ result[key] = format_filesize(result[key])
400
+ end
401
+ {
402
+ "disk_usage" => result
403
+ }
404
+ end
405
+
406
+ def assignments_serialization
407
+ if self.assignment_count > 0
408
+ {
409
+ "assignments" => self.assignments.collect { |asn| asn.serialize(:summary) }
410
+ }
411
+ else
412
+ {}
413
+ end
414
+ end
415
+
416
+ def announcements_serialization
417
+ if self.announcement_count > 0
418
+ {
419
+ "announcements" => self.announcements.collect { |annc| annc.serialize(:summary) }
420
+ }
421
+ else
422
+ {}
423
+ end
424
+ end
425
+
426
+ def gradebook_serialization
427
+ if self.gradebook and self.gradebook.item_count > 0
428
+ {
429
+ "gradebook_items" => self.gradebook.items.collect { |item| item.serialize(:summary) }
430
+ }
431
+ else
432
+ {}
433
+ end
434
+ end
435
+
436
+ def realm_roles_serialization
437
+ {
438
+ "realm_roles" => self.realm.realm_roles.collect { |rr| rr.serialize(:summary) }
439
+ }
440
+ end
441
+
442
+ def forums_serialization
443
+ if self.forum_count > 0
444
+ {
445
+ "forums" => self.forums.collect { |fr| fr.serialize(:summary) }
446
+ }
447
+ else
448
+ {}
449
+ end
450
+ end
451
+ end
452
+
453
+ class SiteProperty
454
+ def self.get(site_id, property_name)
455
+ value = nil
456
+ DB.connect.exec("select value from sakai_site_property " +
457
+ "where site_id=:site_id and name=:name",
458
+ site_id, property_name) do |row|
459
+ value = row[0].read
460
+ end
461
+ return value
462
+ end
463
+
464
+ def self.find_by_site_id(site_id)
465
+ properties = {}
466
+ DB.connect.exec("select name, value from sakai_site_property " +
467
+ "where site_id=:site_id", site_id) do |row|
468
+ name = row[0]
469
+ value = row[1].read
470
+ properties[name] = value
471
+ end
472
+ return properties
473
+ end
474
+
475
+ def self.find_site_ids_by_property(name, value)
476
+ ids = []
477
+ DB.connect.exec("select distinct(site_id) from sakai_site_property " +
478
+ "where name=:name " +
479
+ "and to_char(value)=:value",
480
+ name, value) do |row|
481
+ ids << row[0]
482
+ end
483
+ ids
484
+ end
485
+ end
486
+
487
+ class Page < SakaiObject
488
+ attr_reader :title, :order, :layout, :site
489
+
490
+ @@cache = {}
491
+ def self.find(id)
492
+ if @@cache[id].nil?
493
+ title = order = layout = site = nil
494
+ DB.connect.exec("select title, site_order, layout, site_id " +
495
+ "from sakai_site_page where page_id = :page_id", id) do |row|
496
+ title = row[0]
497
+ order = row[1].to_i
498
+ layout = row[2]
499
+ site = Site.find(row[3])
500
+ end
501
+ if title.nil?
502
+ raise ObjectNotFoundException(Page, id)
503
+ end
504
+ @@cache[id] = Page.new(id, title, order, layout, site)
505
+ end
506
+ @@cache[id]
507
+ end
508
+
509
+ def self.find_by_site_id(site_id)
510
+ results = []
511
+ site = Site.find(site_id)
512
+ DB.connect.exec("select page_id, title, site_order, layout " +
513
+ "from sakai_site_page where site_id = :site_id " +
514
+ "order by site_order", site_id) do |row|
515
+ @@cache[row[0]] = Page.new(row[0], row[1], row[2].to_i, row[3], site)
516
+ results << @@cache[row[0]]
517
+ end
518
+ results
519
+ end
520
+
521
+ def initialize(id, title, order, layout, site)
522
+ @id = id
523
+ @title = title
524
+ @order = order
525
+ @layout = layout
526
+ @site = site
527
+ end
528
+
529
+ def properties
530
+ @properties ||= PageProperty.find_by_page_id(@id)
531
+ end
532
+
533
+ def tools
534
+ @tools ||= Tool.find_by_page_id(@id)
535
+ end
536
+
537
+ # serialization
538
+ def default_serialization
539
+ {
540
+ "id" => self.id,
541
+ "title" => self.title,
542
+ "order" => self.order,
543
+ "tools" => self.tools.collect { |tool| tool.serialize(:summary) },
544
+ "properties" => self.properties,
545
+ "site_id" => self.site.id
546
+ }.delete_if do |k,v|
547
+ k == "properties" && v == {}
548
+ end
549
+ end
550
+
551
+ def summary_serialization
552
+ default_serialization.delete_if do |k,v|
553
+ k == "site_id"
554
+ end
555
+ end
556
+ end
557
+
558
+ class PageProperty
559
+ def self.get(page_id, property_name)
560
+ value = nil
561
+ DB.connect.exec("select value from sakai_site_page_property " +
562
+ "where page_id=:page_id and name=:name", page_id, property_name) do |row|
563
+ value = row[0].read
564
+ end
565
+ return value
566
+ end
567
+
568
+ def self.find_by_page_id(page_id)
569
+ properties = {}
570
+ DB.connect.exec("select name, value from sakai_site_page_property " +
571
+ "where page_id=:page_id", page_id) do |row|
572
+ name = row[0]
573
+ value = row[1].read
574
+ properties[name] = value
575
+ end
576
+ return properties
577
+ end
578
+ end
579
+
580
+ class Tool < SakaiObject
581
+ attr_reader :title, :registration, :order, :layout, :page, :site
582
+
583
+ @@cache = {}
584
+ def self.find(id)
585
+ if @@cache[id].nil?
586
+ tool_id = title = registration = page_order = layout_hints = page = nil
587
+ DB.connect.exec("select tool_id, title, registration, page_order, " +
588
+ "layout_hints, page_id " +
589
+ "from sakai_site_tool where tool_id = :tool_id", id) do |row|
590
+ tool_id, title, registration, page_order_s, layout_hints, page_id = *row
591
+ page_order = page_order_s.to_i
592
+ page = Page.find(page_id)
593
+ end
594
+ if tool_id.nil?
595
+ raise ObjectNotFoundException.new(Tool, id)
596
+ end
597
+ @@cache[id] = Tool.new(tool_id, title, registration, page_order, layout_hints, page)
598
+ end
599
+ @@cache[id]
600
+ end
601
+
602
+ def self.find_by_page_id(page_id)
603
+ results = []
604
+ page = Page.find(page_id)
605
+ DB.connect.exec("select tool_id, title, registration, page_order, layout_hints " +
606
+ "from sakai_site_tool where page_id = :page_id " +
607
+ "order by page_order", page_id) do |row|
608
+ @@cache[row[0]] = Tool.new(row[0], row[1], row[2], row[3].to_i, row[4], page)
609
+ results << @@cache[row[0]]
610
+ end
611
+ results
612
+ end
613
+
614
+ def initialize(id, title, registration, order, layout, page)
615
+ @id = id
616
+ @title = title
617
+ @registration = registration
618
+ @order = order
619
+ @layout = layout
620
+ @page = page
621
+ @site = page.site
622
+ end
623
+
624
+ def properties
625
+ @properties ||= ToolProperty.find_by_tool_id(@id)
626
+ end
627
+
628
+ # serialization
629
+ def default_serialization
630
+ result = {
631
+ "id" => self.id,
632
+ "registration" => self.registration,
633
+ "title" => self.title,
634
+ "site" => self.site.serialize(:summary),
635
+ "page_id" => self.page.id,
636
+ "order" => self.order,
637
+ "layout" => self.layout,
638
+ "properties" => self.properties
639
+ }
640
+ if result["properties"] == {}
641
+ result.delete("properties")
642
+ end
643
+ if result["layout"].nil?
644
+ result.delete("layout")
645
+ end
646
+ result
647
+ end
648
+
649
+ def summary_serialization
650
+ {
651
+ "id" => self.id,
652
+ "registration" => self.registration,
653
+ "title" => self.title
654
+ }
655
+ end
656
+ end
657
+
658
+ class ToolProperty
659
+ def self.get(tool_id, property_name)
660
+ value = nil
661
+ DB.connect.exec("select value from sakai_site_tool_property " +
662
+ "where tool_id=:tool_id and name=:name",
663
+ tool_id, property_name) do |row|
664
+ value = row[0].read
665
+ end
666
+ return value
667
+ end
668
+
669
+ def self.find_by_tool_id(tool_id)
670
+ properties = {}
671
+ DB.connect.exec("select name, value from sakai_site_tool_property " +
672
+ "where tool_id=:tool_id", tool_id) do |row|
673
+ name = row[0]
674
+ value = row[1].read
675
+ properties[name] = value
676
+ end
677
+ return properties
678
+ end
679
+ end
680
+
681
+ class SiteMembership < SakaiObject
682
+ attr_reader :site, :user, :role
683
+
684
+ def initialize(site_id, user_id, role)
685
+ @site = Site.find(site_id)
686
+ @user = User.find(user_id)
687
+ @role = AuthzRole.find(role)
688
+ end
689
+
690
+ def self.find_by_site_id(site_id)
691
+ results = []
692
+ DB.connect.exec("select srrg.user_id, srr.role_name " +
693
+ "from sakai_realm_rl_gr srrg, sakai_realm_role srr, sakai_realm sr " +
694
+ "where srrg.role_key = srr.role_key " +
695
+ "and srrg.realm_key = sr.realm_key " +
696
+ "and sr.realm_id = '/site/'||:site_id", site_id) do |row|
697
+ results << SiteMembership.new(site_id, row[0], row[1])
698
+ end
699
+ results
700
+ end
701
+
702
+ def self.find_by_user_id(user_id)
703
+ results = []
704
+ DB.connect.exec("select substr(sr.realm_id,7), srr.role_name " +
705
+ "from sakai_realm_rl_gr srrg, sakai_realm_role srr, sakai_realm sr " +
706
+ "where srrg.role_key = srr.role_key " +
707
+ "and srrg.realm_key = sr.realm_key " +
708
+ "and srrg.user_id = :1 " +
709
+ "and sr.realm_id like '/site/%' " +
710
+ "and sr.realm_id not like '%/group/%'", user_id) do |row|
711
+ results << SiteMembership.new(row[0], user_id, row[1])
712
+ end
713
+ results
714
+ end
715
+
716
+ def default_serialization
717
+ {
718
+ "site" => self.site.serialize(:summary),
719
+ "user" => self.user.serialize(:summary),
720
+ "role" => self.role.name
721
+ }
722
+ end
723
+
724
+ def summary_serialization
725
+ {
726
+ "site_id" => self.site.id,
727
+ "site_title" => self.site.title,
728
+ "user_id" => self.user.id,
729
+ "user_eid" => self.user.eid,
730
+ "user_type" => self.user.type,
731
+ "role" => self.role.name
732
+ }
733
+ end
734
+
735
+ def user_summary_serialization
736
+ {
737
+ "site_id" => self.site.id,
738
+ "site_title" => self.site.title,
739
+ "role" => self.role.name
740
+ }
741
+ end
742
+
743
+ def site_summary_serialization
744
+ {
745
+ "user_id" => self.user.id,
746
+ "user_eid" => self.user.eid,
747
+ "user_type" => self.user.type,
748
+ "role" => self.role.name
749
+ }
750
+ end
751
+ end
752
+ end