sakai-info 0.1.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,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