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.
- data/CHANGELOG.md +12 -0
- data/LICENSE +8 -0
- data/README.md +148 -0
- data/ROADMAP.md +37 -0
- data/bin/sakai-info +79 -0
- data/lib/sakai-info.rb +62 -0
- data/lib/sakai-info/announcement.rb +170 -0
- data/lib/sakai-info/assignment.rb +281 -0
- data/lib/sakai-info/authz.rb +378 -0
- data/lib/sakai-info/cli.rb +35 -0
- data/lib/sakai-info/cli/help.rb +103 -0
- data/lib/sakai-info/configuration.rb +288 -0
- data/lib/sakai-info/content.rb +300 -0
- data/lib/sakai-info/db.rb +19 -0
- data/lib/sakai-info/gradebook.rb +176 -0
- data/lib/sakai-info/group.rb +119 -0
- data/lib/sakai-info/instance.rb +122 -0
- data/lib/sakai-info/message.rb +122 -0
- data/lib/sakai-info/sakai_object.rb +58 -0
- data/lib/sakai-info/sakai_xml_entity.rb +126 -0
- data/lib/sakai-info/samigo.rb +219 -0
- data/lib/sakai-info/site.rb +752 -0
- data/lib/sakai-info/user.rb +220 -0
- data/lib/sakai-info/version.rb +3 -0
- metadata +90 -0
@@ -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
|