pyu-activesp 0.0.4.1.2

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,107 @@
1
+ # Copyright (c) 2010 XAOP bvba
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ #
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ #
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ module ActiveSP
27
+
28
+ class Group < Base
29
+
30
+ extend Caching
31
+ extend PersistentCaching
32
+ include Util
33
+ include InSite
34
+
35
+ persistent { |site, name, *a| [site.connection, [:group, name]] }
36
+ # @private
37
+ def initialize(site, name)
38
+ @site, @name = site, name
39
+ end
40
+
41
+ # See {Base#key}
42
+ # @return [String]
43
+ def key
44
+ encode_key("G", [@name])
45
+ end
46
+
47
+ # Returns the list of users in this group
48
+ # @return [User]
49
+ def users
50
+ call("UserGroup", "get_user_collection_from_group", "groupName" => @name).xpath("//spdir:User", NS).map do |row|
51
+ attributes = clean_attributes(row.attributes)
52
+ User.new(@site, attributes["LoginName"])
53
+ end
54
+ end
55
+ cache :users, :dup => :always
56
+
57
+ # Returns false. The same method is present on {Role} where it returns true. Roles and groups can generally be
58
+ # duck-typed, and this method is there for the rare case where you do need to make the distinction
59
+ # @return [Boolean]
60
+ def is_role?
61
+ false
62
+ end
63
+
64
+ # See {Base#save}
65
+ # @return [void]
66
+ def save
67
+ p untype_cast_attributes(@site, nil, internal_attribute_types, changed_attributes)
68
+ end
69
+
70
+ # @private
71
+ def to_s
72
+ "#<ActiveSP::Group name=#{@name}>"
73
+ end
74
+
75
+ # @private
76
+ alias inspect to_s
77
+
78
+ private
79
+
80
+ def data
81
+ call("UserGroup", "get_group_info", "groupName" => @name).xpath("//spdir:Group", NS).first
82
+ end
83
+ cache :data
84
+
85
+ def attributes_before_type_cast
86
+ clean_attributes(data.attributes)
87
+ end
88
+ cache :attributes_before_type_cast
89
+
90
+ def original_attributes
91
+ type_cast_attributes(@site, nil, internal_attribute_types, attributes_before_type_cast)
92
+ end
93
+ cache :original_attributes
94
+
95
+ def internal_attribute_types
96
+ @@internal_attribute_types ||= {
97
+ "Description" => GhostField.new("Description", "Text", false, true),
98
+ "ID" => GhostField.new("ID", "Text", false, true),
99
+ "Name" => GhostField.new("Name", "Text", false, true),
100
+ "OwnerID" => GhostField.new("OsnerID", "Integer", false, true),
101
+ "OwnerIsUser" => GhostField.new("OwnerIsUser", "Bool", false, true)
102
+ }
103
+ end
104
+
105
+ end
106
+
107
+ end
@@ -0,0 +1,338 @@
1
+ # Copyright (c) 2010 XAOP bvba
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ #
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ #
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ module ActiveSP
27
+
28
+ class Item < Base
29
+
30
+ include InSite
31
+ extend Caching
32
+ include Util
33
+
34
+ # Returns the list in which the item is located
35
+ # @return [List]
36
+ attr_reader :list
37
+
38
+ # @private
39
+ def initialize(list, id, folder = :unset, uid = nil, url = nil, attributes_before_type_cast = nil)
40
+ @list, @id = list, id
41
+ @folder = folder if folder != :unset # We have to allow for nil
42
+ @uid = uid if uid
43
+ @site = list.site
44
+ @url = url if url
45
+ @attributes_before_type_cast = attributes_before_type_cast if attributes_before_type_cast
46
+ end
47
+
48
+ def ID
49
+ @id
50
+ end
51
+
52
+ def is_folder?
53
+ false
54
+ end
55
+
56
+ # Returns the folder, if any, that this item is located in.
57
+ # @return [Folder, nil]
58
+ def folder
59
+ query = Builder::XmlMarkup.new.Query do |xml|
60
+ xml.Where do |xml|
61
+ xml.Eq do |xml|
62
+ xml.FieldRef(:Name => "FileRef")
63
+ xml.Value(::File.dirname(url).sub(/\A\//, ""), :Type => "Text")
64
+ end
65
+ xml.Eq do |xml|
66
+ xml.FieldRef(:Name => "FSObjType")
67
+ xml.Value(1, :Type => "Text")
68
+ end
69
+ end
70
+ end
71
+ @list.items(:folder => :all, :query => query).first
72
+ end
73
+ cache :folder
74
+
75
+ # Returns the parent of this item.
76
+ # @return [Folder, List]
77
+ def parent
78
+ folder || @list
79
+ end
80
+
81
+ # @private
82
+ def id
83
+ uid
84
+ end
85
+
86
+ # @private
87
+ def uid
88
+ attributes["UniqueID"]
89
+ end
90
+ cache :uid
91
+
92
+ # The URL of this item
93
+ # @return [String]
94
+ def url
95
+ # URL(@list.url).join(attributes["ServerUrl"]).to_s
96
+ attributes["ServerUrl"]
97
+ end
98
+ cache :url
99
+
100
+ def absolute_url
101
+ URL(@list.url).join(attributes["ServerUrl"]).to_s
102
+ end
103
+ cache :absolute_url
104
+
105
+ # See {Base#key}
106
+ # @return [String]
107
+ def key
108
+ encode_key("I", [@list.key, @id])
109
+ end
110
+
111
+ # Returns a list of the URLs of the attachments of this item. Note that for items in a document
112
+ # library, this returns an empty list
113
+ # @return [Array<String>]
114
+ def attachment_urls
115
+ @list.when_list do
116
+ result = call("Lists", "get_attachment_collection", "listName" => @list.id, "listItemID" => @id)
117
+ return result.xpath("//sp:Attachment", NS).map { |att| att.text }
118
+ end
119
+ @list.when_document_library { raise TypeError, "a document library does not support attachments" }
120
+ @list.raise_on_unknown_type
121
+ end
122
+ cache :attachment_urls, :dup => :always
123
+
124
+ # Yields each attachment as a ActiveSP::File object.
125
+ #
126
+ def each_attachment
127
+ attachment_urls.each { |url| yield ActiveSP::File.new(self, url, true) }
128
+ end
129
+
130
+ def add_attachment(parameters = {})
131
+ @list.when_list do
132
+ parameters = parameters.dup
133
+ content = parameters.delete(:content) or raise ArgumentError, "Specify the content in the :content parameter"
134
+ file_name = parameters.delete(:file_name) or raise ArgumentError, "Specify the file name in the :file_name parameter"
135
+ result = call("Lists", "add_attachment", "listName" => @list.ID, "listItemID" => self.ID, "fileName" => file_name, "attachment" => Base64.encode64(content.to_s))
136
+ add_result = result.xpath("//sp:AddAttachmentResult", NS).first
137
+ if add_result
138
+ clear_cache_for(:attachment_urls)
139
+ return ActiveSP::File.new(self, add_result.text, true)
140
+ else
141
+ raise "cannot add attachment"
142
+ end
143
+ end
144
+ @list.when_document_library { raise TypeError, "a document library does not support attachments" }
145
+ @list.raise_on_unknown_type
146
+ end
147
+
148
+ association :attachments do
149
+ def create(parameters = {})
150
+ @object.add_attachment(parameters)
151
+ end
152
+ end
153
+
154
+ def content
155
+ @list.when_list { raise TypeError, "a list has attachments" }
156
+ @list.when_document_library { return ActiveSP::File.new(self, url, false) }
157
+ @list.raise_on_unknown_type
158
+ end
159
+
160
+ def content=(data)
161
+ @list.when_list { raise TypeError, "a list has attachments" }
162
+ @list.when_document_library { @list.create_document(:overwrite => true, :content => data, "FileLeafRef" => original_attributes["FileLeafRef"]) }
163
+ @list.raise_on_unknown_type
164
+ end
165
+
166
+ # Returns a list of the content URLs for this item. For items in document libraries, this
167
+ # returns the url, for other items this returns the attachments. These URLs can be used
168
+ # to download all contents. See {Connection#fetch}
169
+ # @return [Array<String>]
170
+ def content_urls
171
+ @list.when_list { return attachment_urls }
172
+ @list.when_document_library { return is_folder? ? [] : [url] }
173
+ @list.raise_on_unknown_type
174
+ end
175
+ cache :content_urls, :dup => :always
176
+
177
+ # Returns the content type of this item
178
+ # @return [ContentType]
179
+ def content_type
180
+ ContentType.new(@site, @list, attributes["ContentTypeId"])
181
+ end
182
+ cache :content_type
183
+
184
+ # def versions
185
+ # call("Versions", "get_versions", "fileName" => attributes["ServerUrl"])
186
+ # end
187
+
188
+ # See {Base#save}
189
+ # @return [self]
190
+ def save
191
+ update_attributes_internal(untype_cast_attributes(@site, nil, internal_attribute_types, changed_attributes))
192
+ self
193
+ end
194
+
195
+ def check_out
196
+ @list.when_list { raise TypeError, "cannot check out list items; they would disappear" }
197
+ @list.raise_on_unknown_type
198
+ result = call("Lists", "check_out_file", "pageUrl" => absolute_url, "checkoutToLocal" => false)
199
+ checkout_result = result.xpath("//sp:CheckOutFileResult", NS).first.text
200
+ if checkout_result == "true"
201
+ self
202
+ else
203
+ raise "cannot check out this item"
204
+ end
205
+ end
206
+
207
+ def check_in(options = {})
208
+ options = options.dup
209
+ type = options.delete(:type) or raise ArgumentError, ":type parameter not specified"
210
+ comment = options.delete(:comment)
211
+ options.empty? or raise ArgumentError, "unsupported options #{options.keys.map { |k| k.inspect }.join(", ")}"
212
+ @list.when_list { raise TypeError, "cannot check in list items because you can't check them out" }
213
+ @list.raise_on_unknown_type
214
+ if checkin_type = { :minor => 0, :major => 1, :overwrite => 2 }[type]
215
+ if type == :minor && !@list.attribute("EnableMinorVersion")
216
+ raise TypeError, "this list does not support minor versions"
217
+ end
218
+ result = call("Lists", "check_in_file", "pageUrl" => absolute_url, "comment" => comment, "CheckinType" => checkin_type)
219
+ checkin_result = result.xpath("//sp:CheckInFileResult", NS).first.text
220
+ if checkin_result == "true"
221
+ self
222
+ else
223
+ raise "cannot check in this item"
224
+ end
225
+ else
226
+ raise ArgumentError, "invalid checkin type #{type.inspect}, valid values are :minor, :major and :overwrite"
227
+ end
228
+ end
229
+
230
+ def cancel_checkout
231
+ @list.when_list { raise TypeError, "cannot undo check-out for list items because you can't check them out" }
232
+ @list.raise_on_unknown_type
233
+ result = call("Lists", "undo_check_out", "pageUrl" => absolute_url)
234
+ cancel_result = result.xpath("//sp:UndoCheckOutResult", NS).first.text
235
+ if cancel_result == "true"
236
+ self
237
+ else
238
+ raise "cannot cancel check-out for this item"
239
+ end
240
+ end
241
+
242
+ def update_attributes(attributes)
243
+ attributes.each do |k, v|
244
+ set_attribute(k, v)
245
+ end
246
+ save
247
+ end
248
+
249
+ def destroy
250
+ updates = Builder::XmlMarkup.new.Batch("OnError" => "Continue", "ListVersion" => 1) do |xml|
251
+ xml.Method("ID" => 1, "Cmd" => "Delete") do
252
+ xml.Field(self.ID, "Name" => "ID")
253
+ end
254
+ end
255
+ result = call("Lists", "update_list_items", "listName" => @list.id, "updates" => updates)
256
+ create_result = result.xpath("//sp:Result", NS).first
257
+ error_code = create_result.xpath("./sp:ErrorCode", NS).first.text.to_i(0)
258
+ if error_code == 0
259
+ @ID = nil
260
+ else
261
+ raise "cannot create item, error code = #{error_code}"
262
+ end
263
+ self
264
+ end
265
+
266
+ # @private
267
+ def to_s
268
+ "#<ActiveSP::Item url=#{url}>"
269
+ end
270
+
271
+ # @private
272
+ alias inspect to_s
273
+
274
+ def ==(object)
275
+ ::ActiveSP::List === object && self.ID == object.ID
276
+ end
277
+
278
+ private
279
+
280
+ def raw_attributes
281
+ query_options = Builder::XmlMarkup.new.QueryOptions do |xml|
282
+ xml.Folder
283
+ end
284
+ query = Builder::XmlMarkup.new.Query do |xml|
285
+ xml.Where do |xml|
286
+ xml.Eq do |xml|
287
+ xml.FieldRef(:Name => "ID")
288
+ xml.Value(@id, :Type => "Counter")
289
+ end
290
+ end
291
+ end
292
+ @list.__each_item(query_options, "query" => query) do |attributes|
293
+ return attributes
294
+ end
295
+ end
296
+ cache :raw_attributes
297
+
298
+ def attributes_before_type_cast
299
+ clean_item_attributes(raw_attributes)
300
+ end
301
+ cache :attributes_before_type_cast
302
+
303
+ def original_attributes
304
+ type_cast_attributes(@site, @list, @list.fields_by_name, attributes_before_type_cast)
305
+ end
306
+ cache :original_attributes
307
+
308
+ def internal_attribute_types
309
+ list.fields_by_name
310
+ end
311
+
312
+ def update_attributes_internal(attributes)
313
+ attributes = attributes.dup
314
+ if file_leaf_ref = attributes.delete("FileLeafRef")
315
+ base_name = ::File.basename(file_leaf_ref, ".*")
316
+ end
317
+ updates = Builder::XmlMarkup.new.Batch("OnError" => "Continue", "ListVersion" => 1) do |xml|
318
+ xml.Method("ID" => 1, "Cmd" => "Update") do
319
+ xml.Field(self.ID, "Name" => "ID")
320
+ construct_xml_for_update_list_items(xml, @list.fields_by_name, attributes)
321
+ xml.Field(base_name, "Name" => "BaseName") if base_name
322
+ end
323
+ end
324
+ result = call("Lists", "update_list_items", "listName" => @list.id, "updates" => updates)
325
+ create_result = result.xpath("//sp:Result", NS).first
326
+ error_code = create_result.xpath("./sp:ErrorCode", NS).first.text.to_i(0)
327
+ if error_code == 0
328
+ row = result.xpath("//z:row", NS).first
329
+ @attributes_before_type_cast = clean_item_attributes(row.attributes)
330
+ reload
331
+ else
332
+ raise "cannot create item, error code = #{error_code}"
333
+ end
334
+ end
335
+
336
+ end
337
+
338
+ end