activesp 0.0.1

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,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