activesp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,40 @@
1
+ module ActiveSP
2
+
3
+ class Folder < Item
4
+
5
+ def key
6
+ encode_key("F", [parent.key, @id])
7
+ end
8
+
9
+ def items(options = {})
10
+ @list.items(options.merge(:folder => self))
11
+ end
12
+
13
+ def item(name)
14
+ query = Builder::XmlMarkup.new.Query do |xml|
15
+ xml.Where do |xml|
16
+ xml.Eq do |xml|
17
+ xml.FieldRef(:Name => "FileLeafRef")
18
+ xml.Value(name, :Type => "String")
19
+ end
20
+ end
21
+ end
22
+ items(:query => query).first
23
+ end
24
+
25
+ def /(name)
26
+ item(name)
27
+ end
28
+
29
+ undef attachments
30
+ undef content_urls
31
+
32
+ def to_s
33
+ "#<ActiveSP::Folder url=#{url}>"
34
+ end
35
+
36
+ alias inspect to_s
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,31 @@
1
+ module ActiveSP
2
+
3
+ class GhostField
4
+
5
+ include Util
6
+
7
+ attr_reader :Name, :internal_type, :Mult, :ReadOnly
8
+
9
+ def initialize(name, type, mult, read_only)
10
+ @Name, @internal_type, @Mult, @ReadOnly = name, type, mult, read_only
11
+ end
12
+
13
+ def Type
14
+ translate_internal_type(self)
15
+ end
16
+
17
+ def attributes
18
+ @attributes ||= {
19
+ "ColName" => @Name,
20
+ "DisplayName" => @Name,
21
+ "Mult" => @Mult,
22
+ "Name" => @Name,
23
+ "ReadOnly" => @ReadOnly,
24
+ "StaticName" => @Name,
25
+ "Type" => self.Type
26
+ }
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,68 @@
1
+ module ActiveSP
2
+
3
+ class Group < Base
4
+
5
+ extend Caching
6
+ extend PersistentCaching
7
+ include Util
8
+ include InSite
9
+
10
+ # attr_reader :name
11
+
12
+ persistent { |site, name, *a| [site.connection, [:group, name]] }
13
+ def initialize(site, name)
14
+ @site, @name = site, name
15
+ end
16
+
17
+ def key
18
+ encode_key("G", [@name])
19
+ end
20
+
21
+ def users
22
+ call("UserGroup", "get_user_collection_from_group", "groupName" => @name).xpath("//spdir:User", NS).map do |row|
23
+ attributes = clean_attributes(row.attributes)
24
+ User.new(@site, attributes["LoginName"])
25
+ end
26
+ end
27
+ cache :users, :dup => true
28
+
29
+ def to_s
30
+ "#<ActiveSP::Group name=#{@name}>"
31
+ end
32
+
33
+ alias inspect to_s
34
+
35
+ def is_role?
36
+ false
37
+ end
38
+
39
+ private
40
+
41
+ def data
42
+ call("UserGroup", "get_group_info", "groupName" => @name).xpath("//spdir:Group", NS).first
43
+ end
44
+ cache :data
45
+
46
+ def attributes_before_type_cast
47
+ clean_attributes(data.attributes)
48
+ end
49
+ cache :attributes_before_type_cast
50
+
51
+ def original_attributes
52
+ type_cast_attributes(@site, nil, internal_attribute_types, attributes_before_type_cast)
53
+ end
54
+ cache :original_attributes
55
+
56
+ def internal_attribute_types
57
+ @@internal_attribute_types ||= {
58
+ "Description" => GhostField.new("Description", "Text", false, true),
59
+ "ID" => GhostField.new("ID", "Text", false, true),
60
+ "Name" => GhostField.new("Name", "Text", false, true),
61
+ "OwnerID" => GhostField.new("OsnerID", "Integer", false, true),
62
+ "OwnerIsUser" => GhostField.new("OwnerIsUser", "Bool", false, true)
63
+ }
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,109 @@
1
+ module ActiveSP
2
+
3
+ class Item < Base
4
+
5
+ include InSite
6
+ extend Caching
7
+ include Util
8
+
9
+ attr_reader :list
10
+
11
+ def initialize(list, id, folder, uid = nil, url = nil, attributes_before_type_cast = nil)
12
+ @list, @id, @folder = list, id, folder
13
+ @uid = uid if uid
14
+ @site = list.site
15
+ @url = url if url
16
+ @attributes_before_type_cast = attributes_before_type_cast if attributes_before_type_cast
17
+ end
18
+
19
+ def parent
20
+ @folder || @list
21
+ end
22
+
23
+ def id
24
+ uid
25
+ end
26
+
27
+ def uid
28
+ attributes["UniqueID"]
29
+ end
30
+ cache :uid
31
+
32
+ def url
33
+ URL(@list.url).join(attributes["ServerUrl"]).to_s
34
+ end
35
+ cache :url
36
+
37
+ def key
38
+ encode_key("I", [parent.key, @id])
39
+ end
40
+
41
+ def attachments
42
+ result = call("Lists", "get_attachment_collection", "listName" => @list.id, "listItemID" => @id)
43
+ result.xpath("//sp:Attachment", NS).map { |att| att.text }
44
+ end
45
+ cache :attachments, :dup => true
46
+
47
+ def content_urls
48
+ case @list.attributes["BaseType"]
49
+ when "0", "5"
50
+ attachments
51
+ when "1"
52
+ [url]
53
+ else
54
+ raise "not yet BaseType = #{@list.attributes["BaseType"].inspect}"
55
+ end
56
+ end
57
+ cache :content_urls, :dup => true
58
+
59
+ def content_type
60
+ ContentType.new(@site, @list, attributes["ContentTypeId"])
61
+ end
62
+ cache :content_type
63
+
64
+ # def versions
65
+ # call("Versions", "get_versions", "fileName" => attributes["ServerUrl"])
66
+ # end
67
+
68
+ def to_s
69
+ "#<ActiveSP::Item url=#{url}>"
70
+ end
71
+
72
+ alias inspect to_s
73
+
74
+ private
75
+
76
+ def data
77
+ query_options = Builder::XmlMarkup.new.QueryOptions do |xml|
78
+ xml.Folder
79
+ end
80
+ query = Builder::XmlMarkup.new.Query do |xml|
81
+ xml.Where do |xml|
82
+ xml.Eq do |xml|
83
+ xml.FieldRef(:Name => "ID")
84
+ xml.Value(@id, :Type => "Counter")
85
+ end
86
+ end
87
+ end
88
+ result = call("Lists", "get_list_items", "listName" => @list.id, "viewFields" => "<ViewFields></ViewFields>", "queryOptions" => query_options, "query" => query)
89
+ result.xpath("//z:row", NS).first
90
+ end
91
+ cache :data
92
+
93
+ def attributes_before_type_cast
94
+ clean_item_attributes(data.attributes)
95
+ end
96
+ cache :attributes_before_type_cast
97
+
98
+ def original_attributes
99
+ type_cast_attributes(@site, @list, @list.fields_by_name, attributes_before_type_cast)
100
+ end
101
+ cache :original_attributes
102
+
103
+ def internal_attribute_types
104
+ list.fields_by_name
105
+ end
106
+
107
+ end
108
+
109
+ end
@@ -0,0 +1,302 @@
1
+ module ActiveSP
2
+
3
+ class List < Base
4
+
5
+ include InSite
6
+ extend Caching
7
+ extend PersistentCaching
8
+ include Util
9
+
10
+ attr_reader :site, :id
11
+
12
+ persistent { |site, id, *a| [site.connection, [:list, id]] }
13
+ def initialize(site, id, title = nil, attributes_before_type_cast1 = nil, attributes_before_type_cast2 = nil)
14
+ @site, @id = site, id
15
+ @Title = title if title
16
+ @attributes_before_type_cast1 = attributes_before_type_cast1 if attributes_before_type_cast1
17
+ @attributes_before_type_cast2 = attributes_before_type_cast2 if attributes_before_type_cast2
18
+ end
19
+
20
+ def url
21
+ view_url = File.dirname(attributes["DefaultViewUrl"])
22
+ result = URL(@site.url).join(view_url).to_s
23
+ if File.basename(result) == "Forms" and dir = File.dirname(result) and dir.length > @site.url.length
24
+ result = dir
25
+ end
26
+ result
27
+ end
28
+ cache :url
29
+
30
+ def relative_url
31
+ @site.relative_url(url)
32
+ end
33
+
34
+ def key
35
+ encode_key("L", [@site.key, @id])
36
+ end
37
+
38
+ def Title
39
+ data1["Title"].to_s
40
+ end
41
+ cache :Title
42
+
43
+ def items(options = {})
44
+ folder = options.delete(:folder)
45
+ query = options.delete(:query)
46
+ query = query ? { "query" => query } : {}
47
+ no_preload = options.delete(:no_preload)
48
+ options.empty? or raise ArgumentError, "unknown options #{options.keys.map { |k| k.inspect }.join(", ")}"
49
+ query_options = Builder::XmlMarkup.new.QueryOptions do |xml|
50
+ xml.Folder(folder.url) if folder
51
+ end
52
+ if no_preload
53
+ view_fields = Builder::XmlMarkup.new.ViewFields do |xml|
54
+ %w[FSObjType ID UniqueId ServerUrl].each { |f| xml.FieldRef("Name" => f) }
55
+ end
56
+ result = call("Lists", "get_list_items", { "listName" => @id, "viewFields" => viewFields, "queryOptions" => query_options }.merge(query))
57
+ result.xpath("//z:row", NS).map do |row|
58
+ attributes = clean_item_attributes(row.attributes)
59
+ (attributes["FSObjType"][/1$/] ? Folder : Item).new(
60
+ self,
61
+ attributes["ID"],
62
+ folder,
63
+ attributes["UniqueId"],
64
+ attributes["ServerUrl"]
65
+ )
66
+ end
67
+ else
68
+ begin
69
+ result = call("Lists", "get_list_items", { "listName" => @id, "viewFields" => "<ViewFields></ViewFields>", "queryOptions" => query_options }.merge(query))
70
+ result.xpath("//z:row", NS).map do |row|
71
+ attributes = clean_item_attributes(row.attributes)
72
+ (attributes["FSObjType"][/1$/] ? Folder : Item).new(
73
+ self,
74
+ attributes["ID"],
75
+ folder,
76
+ attributes["UniqueId"],
77
+ attributes["ServerUrl"],
78
+ attributes
79
+ )
80
+ end
81
+ rescue Savon::SOAPFault => e
82
+ if e.message[/lookup column threshold/]
83
+ fields = self.fields.map { |f| f.name }
84
+ split_factor = 2
85
+ begin
86
+ split_size = (fields.length + split_factor - 1) / split_factor
87
+ parts = []
88
+ split_factor.times do |i|
89
+ lo = i * split_size
90
+ hi = [(i + 1) * split_size, fields.length].min - 1
91
+ view_fields = Builder::XmlMarkup.new.ViewFields do |xml|
92
+ fields[lo..hi].each { |f| xml.FieldRef("Name" => f) }
93
+ end
94
+ by_id = {}
95
+ result = call("Lists", "get_list_items", { "listName" => @id, "viewFields" => view_fields, "queryOptions" => query_options }.merge(query))
96
+ result.xpath("//z:row", NS).map do |row|
97
+ attributes = clean_item_attributes(row.attributes)
98
+ by_id[attributes["ID"]] = attributes
99
+ end
100
+ parts << by_id
101
+ end
102
+ parts[0].map do |id, attrs|
103
+ parts[1..-1].each do |part|
104
+ attrs.merge!(part[id])
105
+ end
106
+ (attrs["FSObjType"][/1$/] ? Folder : Item).new(
107
+ self,
108
+ attrs["ID"],
109
+ folder,
110
+ attrs["UniqueId"],
111
+ attrs["ServerUrl"],
112
+ attrs
113
+ )
114
+ end
115
+ rescue Savon::SOAPFault => e
116
+ if e.message[/lookup column threshold/]
117
+ split_factor += 1
118
+ retry
119
+ else
120
+ raise
121
+ end
122
+ end
123
+ else
124
+ raise
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ def item(name)
131
+ query = Builder::XmlMarkup.new.Query do |xml|
132
+ xml.Where do |xml|
133
+ xml.Eq do |xml|
134
+ xml.FieldRef(:Name => "FileLeafRef")
135
+ xml.Value(name, :Type => "String")
136
+ end
137
+ end
138
+ end
139
+ items(:query => query).first
140
+ end
141
+
142
+ def /(name)
143
+ item(name)
144
+ end
145
+
146
+ def fields
147
+ data1.xpath("//sp:Field", NS).map do |field|
148
+ attributes = clean_attributes(field.attributes)
149
+ if attributes["ID"] && attributes["StaticName"]
150
+ Field.new(self, attributes["ID"].downcase, attributes["StaticName"], attributes["Type"], @site.field(attributes["ID"].downcase), attributes)
151
+ end
152
+ end.compact
153
+ end
154
+ cache :fields, :dup => true
155
+
156
+ def fields_by_name
157
+ fields.inject({}) { |h, f| h[f.attributes["StaticName"]] = f ; h }
158
+ end
159
+ cache :fields_by_name, :dup => true
160
+
161
+ def field(id)
162
+ fields.find { |f| f.ID == id }
163
+ end
164
+
165
+ def content_types
166
+ result = call("Lists", "get_list_content_types", "listName" => @id)
167
+ result.xpath("//sp:ContentType", NS).map do |content_type|
168
+ ContentType.new(@site, self, content_type["ID"], content_type["Name"], content_type["Description"], content_type["Version"], content_type["Group"])
169
+ end
170
+ end
171
+ cache :content_types, :dup => true
172
+
173
+ def content_type(id)
174
+ content_types.find { |t| t.id == id }
175
+ end
176
+
177
+ def permission_set
178
+ if attributes["InheritedSecurity"]
179
+ @site.permission_set
180
+ else
181
+ PermissionSet.new(self)
182
+ end
183
+ end
184
+ cache :permission_set
185
+
186
+ def to_s
187
+ "#<ActiveSP::List Title=#{self.Title}>"
188
+ end
189
+
190
+ alias inspect to_s
191
+
192
+ private
193
+
194
+ def data1
195
+ call("Lists", "get_list", "listName" => @id).xpath("//sp:List", NS).first
196
+ end
197
+ cache :data1
198
+
199
+ def attributes_before_type_cast1
200
+ clean_attributes(data1.attributes)
201
+ end
202
+ cache :attributes_before_type_cast1
203
+
204
+ def data2
205
+ call("SiteData", "get_list", "strListName" => @id)
206
+ end
207
+ cache :data2
208
+
209
+ def attributes_before_type_cast2
210
+ element = data2.xpath("//sp:sListMetadata", NS).first
211
+ result = {}
212
+ element.children.each do |ch|
213
+ result[ch.name] = ch.inner_text
214
+ end
215
+ result
216
+ end
217
+ cache :attributes_before_type_cast2
218
+
219
+ def original_attributes
220
+ attrs = attributes_before_type_cast1.merge(attributes_before_type_cast2).merge("BaseType" => attributes_before_type_cast1["BaseType"])
221
+ type_cast_attributes(@site, nil, internal_attribute_types, attrs)
222
+ end
223
+ cache :original_attributes
224
+
225
+ def internal_attribute_types
226
+ @@internal_attribute_types ||= {
227
+ "AllowAnonymousAccess" => GhostField.new("AllowAnonymousAccess", "Bool", false, true),
228
+ "AllowDeletion" => GhostField.new("AllowDeletion", "Bool", false, true),
229
+ "AllowMultiResponses" => GhostField.new("AllowMultiResponses", "Bool", false, true),
230
+ "AnonymousPermMask" => GhostField.new("AnonymousPermMask", "Integer", false, true),
231
+ "AnonymousViewListItems" => GhostField.new("AnonymousViewListItems", "Bool", false, true),
232
+ "Author" => GhostField.new("Author", "InternalUser", false, true),
233
+ "BaseTemplate" => GhostField.new("BaseTemplate", "Text", false, true),
234
+ "BaseType" => GhostField.new("BaseType", "Text", false, true),
235
+ "Created" => GhostField.new("Created", "StandardDateTime", false, true),
236
+ "DefaultViewUrl" => GhostField.new("DefaultViewUrl", "Text", false, true),
237
+ "Description" => GhostField.new("Description", "Text", false, false),
238
+ "Direction" => GhostField.new("Direction", "Text", false, true),
239
+ "DocTemplateUrl" => GhostField.new("DocTemplateUrl", "Text", false, true),
240
+ "EmailAlias" => GhostField.new("EmailAlias", "Text", false, true),
241
+ "EmailInsertsFolder" => GhostField.new("EmailInsertsFolder", "Text", false, true),
242
+ "EnableAssignedToEmail" => GhostField.new("EnableAssignedToEmail", "Bool", false, true),
243
+ "EnableAttachments" => GhostField.new("EnableAttachments", "Bool", false, true),
244
+ "EnableMinorVersion" => GhostField.new("EnableMinorVersion", "Bool", false, true),
245
+ "EnableModeration" => GhostField.new("EnableModeration", "Bool", false, true),
246
+ "EnableVersioning" => GhostField.new("EnableVersioning", "Bool", false, true),
247
+ "EventSinkAssembly" => GhostField.new("EventSinkAssembly", "Text", false, true),
248
+ "EventSinkClass" => GhostField.new("EventSinkClass", "Text", false, true),
249
+ "EventSinkData" => GhostField.new("EventSinkData", "Text", false, true),
250
+ "FeatureId" => GhostField.new("FeatureId", "Text", false, true),
251
+ "Flags" => GhostField.new("Flags", "Integer", false, true),
252
+ "HasUniqueScopes" => GhostField.new("HasUniqueScopes", "Bool", false, true),
253
+ "Hidden" => GhostField.new("Hidden", "Bool", false, true),
254
+ "ID" => GhostField.new("ID", "Text", false, true),
255
+ "ImageUrl" => GhostField.new("ImageUrl", "Text", false, true),
256
+ "InheritedSecurity" => GhostField.new("InheritedSecurity", "Bool", false, true),
257
+ "InternalName" => GhostField.new("InternalName", "Text", false, true),
258
+ "ItemCount" => GhostField.new("ItemCount", "Integer", false, true),
259
+ "LastDeleted" => GhostField.new("LastDeleted", "StandardDateTime", false, true),
260
+ "LastModified" => GhostField.new("LastModified", "XMLDateTime", false, true),
261
+ "LastModifiedForceRecrawl" => GhostField.new("LastModifiedForceRecrawl", "XMLDateTime", false, true),
262
+ "MajorVersionLimit" => GhostField.new("MajorVersionLimit", "Integer", false, true),
263
+ "MajorWithMinorVersionsLimit" => GhostField.new("MajorWithMinorVersionsLimit", "Integer", false, true),
264
+ "MobileDefaultViewUrl" => GhostField.new("MobileDefaultViewUrl", "Text", false, true),
265
+ "Modified" => GhostField.new("Modified", "StandardDateTime", false, true),
266
+ "MultipleDataList" => GhostField.new("MultipleDataList", "Bool", false, true),
267
+ "Name" => GhostField.new("Name", "Text", false, true),
268
+ "Ordered" => GhostField.new("Ordered", "Bool", false, true),
269
+ "Permissions" => GhostField.new("Permissions", "Text", false, true),
270
+ "ReadSecurity" => GhostField.new("ReadSecurity", "Integer", false, true),
271
+ "RequireCheckout" => GhostField.new("RequireCheckout", "Bool", false, true),
272
+ "RootFolder" => GhostField.new("RootFolder", "Text", false, true),
273
+ "ScopeId" => GhostField.new("ScopeId", "Text", false, true),
274
+ "SendToLocation" => GhostField.new("SendToLocation", "Text", false, true),
275
+ "ServerTemplate" => GhostField.new("ServerTemplate", "Text", false, true),
276
+ "ShowUser" => GhostField.new("ShowUser", "Bool", false, true),
277
+ "ThumbnailSize" => GhostField.new("ThumbnailSize", "Integer", false, true),
278
+ "Title" => GhostField.new("Title", "Text", false, true),
279
+ "ValidSecurityInfo" => GhostField.new("ValidSecurityInfo", "Bool", false, true),
280
+ "Version" => GhostField.new("Version", "Integer", false, true),
281
+ "WebFullUrl" => GhostField.new("WebFullUrl", "Text", false, true),
282
+ "WebId" => GhostField.new("WebId", "Text", false, true),
283
+ "WebImageHeight" => GhostField.new("WebImageHeight", "Integer", false, true),
284
+ "WebImageWidth" => GhostField.new("WebImageWidth", "Integer", false, true),
285
+ "WorkFlowId" => GhostField.new("WorkFlowId", "Text", false, true),
286
+ "WriteSecurity" => GhostField.new("WriteSecurity", "Integer", false, true)
287
+ }
288
+ end
289
+
290
+ def permissions
291
+ result = call("Permissions", "get_permission_collection", "objectName" => @id, "objectType" => "List")
292
+ rootsite = @site.rootsite
293
+ result.xpath("//spdir:Permission", NS).map do |row|
294
+ accessor = row["MemberIsUser"][/true/i] ? User.new(rootsite, row["UserLogin"]) : Group.new(rootsite, row["GroupName"])
295
+ { :mask => Integer(row["Mask"]), :accessor => accessor }
296
+ end
297
+ end
298
+ cache :permissions, :dup => true
299
+
300
+ end
301
+
302
+ end