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,19 @@
1
+ # sakai-info/db.rb
2
+ # SakaiInfo::DB library
3
+ #
4
+ # Created 2012-02-16 daveadams@gmail.com
5
+ # Last updated 2012-02-19 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 DB
14
+ def self.connect(instance_name = :default)
15
+ Configuration.get_instance(instance_name).connect
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,176 @@
1
+ # sakai-info/gradebook.rb
2
+ # SakaiInfo::Gradebook 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 Gradebook < SakaiObject
14
+ attr_reader :version, :site, :name
15
+
16
+ def initialize(id, version, site, name)
17
+ @id = id
18
+ @version = version
19
+ @site = site
20
+ @name = name
21
+ end
22
+
23
+ @@cache = {}
24
+ @@cache_by_site_id = {}
25
+ def self.find(id)
26
+ if @@cache[id].nil?
27
+ version = site = name = nil
28
+ DB.connect.exec("select version, gradebook_uid, name " +
29
+ "from gb_gradebook_t " +
30
+ "where id = :id", id) do |row|
31
+ version = row[0].to_i
32
+ site = Site.find(row[1])
33
+ name = row[2]
34
+ end
35
+ if version.nil?
36
+ raise ObjectNotFoundException.new(Gradebook, id)
37
+ end
38
+ @@cache[id] = Gradebook.new(id, version, site, name)
39
+ @@cache_by_site_id[site.id] = @@cache[id]
40
+ end
41
+ @@cache[id]
42
+ end
43
+
44
+ def self.find_by_site_id(site_id)
45
+ if @@cache_by_site_id[site_id].nil?
46
+ id = version = site = name = nil
47
+ DB.connect.exec("select id, version, name " +
48
+ "from gb_gradebook_t " +
49
+ "where gradebook_uid = :site_id", site_id) do |row|
50
+ id = row[0].to_i
51
+ version = row[1].to_i
52
+ name = row[2]
53
+ site = Site.find(site_id)
54
+ end
55
+ if version.nil?
56
+ raise ObjectNotFoundException.new(Gradebook, site_id)
57
+ end
58
+ @@cache[id] = Gradebook.new(id, version, site, name)
59
+ @@cache_by_site_id[site_id] = @@cache[id]
60
+ end
61
+ @@cache_by_site_id[site_id]
62
+ end
63
+
64
+ def items
65
+ @items ||= GradableObject.find_by_gradebook_id(@id)
66
+ end
67
+
68
+ def item_count
69
+ items.length
70
+ end
71
+ end
72
+
73
+ class GradableObject < SakaiObject
74
+ attr_reader :id, :gradebook, :object_type, :version, :name
75
+ attr_reader :points_possible, :due_date, :weight
76
+
77
+ def initialize(id, gradebook, object_type, version, name,
78
+ points_possible, due_date, weight)
79
+ @id = id
80
+ @gradebook = gradebook
81
+ @object_type = object_type
82
+ @version = version
83
+ @name = name
84
+ @points_possible = points_possible
85
+ @due_date = due_date
86
+ @weight = weight
87
+ end
88
+
89
+ @@cache = {}
90
+ def self.find(id)
91
+ if @@cache[id].nil?
92
+ gradebook = object_type = version = name = points_possible = due_date = weight = nil
93
+ DB.connect.exec("select gradebook_id, object_type_id, version, " +
94
+ "name, points_possible, " +
95
+ "to_char(due_date, 'YYYY-MM-DD'), " +
96
+ "assignment_weighting " +
97
+ "from gb_gradable_object_t " +
98
+ "where id = :id", id) do |row|
99
+ gradebook = Gradebook.find(row[0].to_i)
100
+ object_type = row[1].to_i
101
+ version = row[2].to_i
102
+ name = row[3]
103
+ points_possible = row[4].to_f
104
+ due_date = row[5]
105
+ weight = row[6].to_f
106
+ end
107
+ if version.nil?
108
+ raise ObjectNotFoundException.new(GradableObject, id)
109
+ end
110
+ @@cache[id] = GradableObject.new(id, gradebook, object_type,
111
+ version, name, points_possible,
112
+ due_date, weight)
113
+ end
114
+ @@cache[id]
115
+ end
116
+
117
+ @@cache_by_gradebook_id = {}
118
+ def self.find_by_gradebook_id(gradebook_id)
119
+ if @@cache_by_gradebook_id[gradebook_id].nil?
120
+ objects = []
121
+ gradebook = Gradebook.find(gradebook_id)
122
+ DB.connect.exec("select id, object_type_id, version, " +
123
+ "name, points_possible, " +
124
+ "to_char(due_date, 'YYYY-MM-DD'), " +
125
+ "assignment_weighting " +
126
+ "from gb_gradable_object_t " +
127
+ "where gradebook_id = :gradebook_id " +
128
+ "order by due_date asc", gradebook_id) do |row|
129
+ id = row[0].to_i
130
+ object_type = row[1].to_i
131
+ version = row[2].to_i
132
+ name = row[3]
133
+ points_possible = row[4].to_f
134
+ due_date = row[5]
135
+ weight = row[6].to_f
136
+ objects << GradableObject.new(id, gradebook, object_type,
137
+ version, name, points_possible,
138
+ due_date, weight)
139
+
140
+ end
141
+ @@cache_by_gradebook_id[gradebook_id] = objects
142
+ end
143
+ @@cache_by_gradebook_id[gradebook_id]
144
+ end
145
+
146
+ def default_serialization
147
+ result = {
148
+ "id" => self.id,
149
+ "name" => self.name,
150
+ "gradebook_id" => self.gradebook.id,
151
+ "object_type" => self.object_type,
152
+ "version" => self.version,
153
+ "points_possible" => self.points_possible,
154
+ "due_date" => self.due_date,
155
+ "weight" => self.weight
156
+ }
157
+ if self.due_date.nil?
158
+ result.delete("due_date")
159
+ end
160
+ result
161
+ end
162
+
163
+ def summary_serialization
164
+ result = {
165
+ "id" => self.id,
166
+ "name" => self.name,
167
+ "points_possible" => self.points_possible,
168
+ "due_date" => self.due_date
169
+ }
170
+ if self.due_date.nil?
171
+ result.delete("due_date")
172
+ end
173
+ result
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,119 @@
1
+ # sakai-info/group.rb
2
+ # SakaiInfo::Group 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 Group < SakaiObject
14
+ attr_reader :site, :title
15
+
16
+ def initialize(id, site, title)
17
+ @id = id
18
+ if site.is_a? Site
19
+ @site = site
20
+ else
21
+ # assume the string version is a site_id
22
+ @site = Site.find(site.to_s)
23
+ end
24
+ @title = title
25
+ end
26
+
27
+ @@cache = {}
28
+ def self.find(id)
29
+ if @@cache[id].nil?
30
+ site_id = title = nil
31
+ DB.connect.exec("select site_id, title from sakai_site_group " +
32
+ "where group_id = :id", id) do |row|
33
+ site_id = row[0]
34
+ title = row[1]
35
+ @@cache[id] = Group.new(id, site_id, title)
36
+ end
37
+ if site_id.nil? or name.nil?
38
+ raise ObjectNotFoundException.new(Group, id)
39
+ end
40
+ end
41
+ @@cache[id]
42
+ end
43
+
44
+ @@cache_by_site_id = {}
45
+ def self.find_by_site_id(site_id)
46
+ if @@cache_by_site_id[site_id].nil?
47
+ @@cache_by_site_id[site_id] = []
48
+ site = Site.find(site_id)
49
+ DB.connect.exec("select group_id, title " +
50
+ "from sakai_site_group " +
51
+ "where site_id = :site_id", site_id) do |row|
52
+ id = row[0]
53
+ title = row[1]
54
+ @@cache[id] = Group.new(id, site, title)
55
+ @@cache_by_site_id[site_id] << @@cache[id]
56
+ end
57
+ end
58
+ @@cache_by_site_id[site_id]
59
+ end
60
+
61
+ def self.count_by_site_id(site_id)
62
+ count = 0
63
+ DB.connect.exec("select count(*) from sakai_site_group " +
64
+ "where site_id=:site_id", site_id) do |row|
65
+ count = row[0].to_i
66
+ end
67
+ count
68
+ end
69
+
70
+ def properties
71
+ @properties ||= GroupProperty.find_by_group_id(@id)
72
+ end
73
+
74
+ def realm
75
+ @authz_realm ||= AuthzRealm.find_by_site_id_and_group_id(@site.id, @id)
76
+ end
77
+
78
+ # serialization
79
+ def default_serialization
80
+ result = {
81
+ "id" => self.id,
82
+ "title" => self.title,
83
+ "site_id" => self.site.id,
84
+ "members" => self.realm.user_count,
85
+ "properties" => self.properties
86
+ }
87
+ if result["properties"] == {}
88
+ result.delete("properties")
89
+ end
90
+ result
91
+ end
92
+
93
+ def summary_serialization
94
+ {
95
+ "id" => self.id,
96
+ "title" => self.title,
97
+ "members" => self.realm.user_count
98
+ }
99
+ end
100
+ end
101
+
102
+ class GroupProperty
103
+ attr_reader :name, :value
104
+
105
+ def initialize(name, value)
106
+ @name = name
107
+ @value = value
108
+ end
109
+
110
+ def self.find_by_group_id(group_id)
111
+ properties = []
112
+ DB.connect.exec("select name, value from sakai_site_group_property " +
113
+ "where group_id=:group_id", group_id) do |row|
114
+ properties << GroupProperty.new(row[0], row[1].read)
115
+ end
116
+ properties
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,122 @@
1
+ # sakai-info/instance.rb
2
+ # SakaiInfo::Instance library
3
+ #
4
+ # Created 2012-02-19 daveadams@gmail.com
5
+ # Last updated 2012-02-19 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 ConnectionFailureException < SakaiException; end
14
+
15
+ class Instance
16
+ def self.create(config)
17
+ case config["dbtype"].downcase
18
+ when "oracle" then
19
+ OracleInstance.new(config)
20
+ when "mysql" then
21
+ MySqlInstance.new(config)
22
+ else
23
+ raise UnsupportedConfigException.new("Database type '#{config["dbtype"]}' is not supported.")
24
+ end
25
+ end
26
+ end
27
+
28
+ class OracleInstance
29
+ DEFAULT_PORT = 1521
30
+
31
+ def initialize(config)
32
+ # fix NLS_LANG if necessary
33
+ ENV["NLS_LANG"] ||= "AMERICAN_AMERICA.UTF8"
34
+
35
+ # include Oracle driver
36
+ require 'oci8'
37
+
38
+ @username = config["username"]
39
+ @password = config["password"]
40
+ if config["host"].nil? or config["host"] == ""
41
+ @service = config["service"]
42
+ else
43
+ @host = config["host"]
44
+ @port = config["port"].nil? ? DEFAULT_PORT : config["port"].to_i
45
+ @service = "//#{@host}:#{@port}/#{config["service"]}"
46
+ end
47
+
48
+ # close the connection upon exit
49
+ at_exit {
50
+ if @connection
51
+ begin
52
+ if @connection.methods.include? :ping
53
+ @connection.logoff if @connection.ping
54
+ else
55
+ @connection.logoff
56
+ end
57
+ rescue
58
+ # it's ok
59
+ end
60
+ end
61
+ }
62
+ end
63
+
64
+ def dbtype
65
+ "oracle"
66
+ end
67
+
68
+ def alive?
69
+ is_alive = false
70
+ begin
71
+ @connection.exec("select 1 from dual") do |row|
72
+ if row[0] == 1
73
+ is_alive = true
74
+ end
75
+ end
76
+ rescue
77
+ # doesn't matter what the exception is
78
+ @connection = nil
79
+ is_alive = false
80
+ end
81
+
82
+ is_alive
83
+ end
84
+
85
+ def connect
86
+ if @connection and self.alive?
87
+ return @connection
88
+ end
89
+
90
+ begin
91
+ @connection = OCI8.new(@username, @password, @service)
92
+ rescue => e
93
+ @connection = nil
94
+ raise ConnectionFailureException.new("Could not connect: #{e}")
95
+ end
96
+ end
97
+ end
98
+
99
+ class MySqlInstance
100
+ DEFAULT_PORT = 3306
101
+
102
+ def initialize(config)
103
+ @username = config["username"]
104
+ @password = config["password"]
105
+ @dbname = config["dbname"]
106
+ @host = config["host"]
107
+ @port = config["port"].nil? ? 3306 : config["port"].to_i
108
+ end
109
+
110
+ def dbtype
111
+ "mysql"
112
+ end
113
+
114
+ def alive?
115
+ false
116
+ end
117
+
118
+ def connect
119
+ raise UnsupportedConfigException.new("MySQL will be supported in a future release.")
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,122 @@
1
+ # sakai-info/message.rb
2
+ # SakaiInfo::Message 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 MessageTypeUUID
14
+ # TODO: verify whether these are the same in all installs
15
+ PRIVATE_MESSAGE = "d6404db7-7f6e-487a-00fe-baffce45d84c"
16
+ FORUM_POST = "7143223e-355a-4865-00dd-cee9310499e4"
17
+ end
18
+
19
+ class UnknownMessageTypeException < SakaiException; end
20
+ class GenericMessage < SakaiObject
21
+ def self.count_by_date_and_message_type(count_date, message_type)
22
+ date_str = nil
23
+ if count_date.is_a? Time
24
+ date_str = count_date.strftime("%Y-%m-%d")
25
+ elsif count_date.is_a? String
26
+ if count_date =~ /^\d\d\d\d-\d\d-\d\d$/
27
+ date_str = count_date
28
+ else
29
+ raise InvalidDateException
30
+ end
31
+ else
32
+ raise InvalidDateException
33
+ end
34
+
35
+ if not valid_message_type? message_type
36
+ raise UnknownMessageTypeException
37
+ end
38
+
39
+ count = 0
40
+ DB.connect.exec("select count(*) from mfr_message_t " +
41
+ "where message_dtype = :t " +
42
+ "and to_char(created,'YYYY-MM-DD') = :d",
43
+ message_type, date_str) do |row|
44
+ count = row[0].to_i
45
+ end
46
+ count
47
+ end
48
+
49
+ private
50
+ def self.valid_message_type?(s)
51
+ s =="ME" or s =="PM"
52
+ end
53
+ end
54
+
55
+ class PrivateMessage < GenericMessage
56
+ def self.count_by_date(d)
57
+ count_by_date_and_message_type(d, "PM")
58
+ end
59
+ end
60
+
61
+ class ForumPost < GenericMessage
62
+ def self.count_by_date(d)
63
+ count_by_date_and_message_type(d, "ME")
64
+ end
65
+ end
66
+
67
+ class Forum < SakaiObject
68
+ attr_reader :id, :title
69
+
70
+ def initialize(id, title)
71
+ @id = id.to_i
72
+ @title = title
73
+ end
74
+
75
+ @@cache = {}
76
+
77
+ def self.count_by_site_id(site_id)
78
+ count = 0
79
+ DB.connect.exec("select count(*) from mfr_open_forum_t " +
80
+ "where surrogatekey = (select id from mfr_area_t " +
81
+ "where type_uuid = :type_uuid " +
82
+ "and context_id = :site_id)",
83
+ MessageTypeUUID::FORUM_POST, site_id) do |row|
84
+ count = row[0].to_i
85
+ end
86
+ count
87
+ end
88
+
89
+ @@cache_by_site_id = {}
90
+ def self.find_by_site_id(site_id)
91
+ if @@cache_by_site_id[site_id].nil?
92
+ @@cache_by_site_id[site_id] = []
93
+ DB.connect.exec("select id, title from mfr_open_forum_t " +
94
+ "where surrogatekey = (select id from mfr_area_t " +
95
+ "where type_uuid = :type_uuid " +
96
+ "and context_id = :site_id) order by sort_index",
97
+ MessageTypeUUID::FORUM_POST, site_id) do |row|
98
+ id = row[0].to_i.to_s
99
+ title = row[1]
100
+ @@cache[id] = Forum.new(id, title)
101
+ @@cache_by_site_id[site_id] << @@cache[id]
102
+ end
103
+ end
104
+ @@cache_by_site_id[site_id]
105
+ end
106
+
107
+ def default_serialization
108
+ {
109
+ "id" => self.id,
110
+ "title" => self.title
111
+ }
112
+ end
113
+
114
+ def summary_serialization
115
+ {
116
+ "id" => self.id,
117
+ "title" => self.title
118
+ }
119
+ end
120
+ end
121
+ end
122
+