activesp 0.0.7 → 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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.7
1
+ 0.1.0-pre
@@ -28,6 +28,20 @@ module ActiveSP
28
28
  # @private
29
29
  module Caching
30
30
 
31
+ module InstanceMethods
32
+
33
+ # @private
34
+ def clear_cache_for(name)
35
+ instance_variable_set("@#{name}", nil) # Make sure it is defined first... Dirty, right?
36
+ remove_instance_variable("@#{name}")
37
+ end
38
+
39
+ end
40
+
41
+ def self.extended(o)
42
+ o.send(:include, ActiveSP::Caching::InstanceMethods)
43
+ end
44
+
31
45
  private
32
46
 
33
47
  def cache(name, options = {})
@@ -132,6 +132,32 @@ module ActiveSP
132
132
  end
133
133
  end
134
134
 
135
+ def head(url)
136
+ # TODO: support HTTPS too
137
+ @open_params ||= begin
138
+ u = URL(@root_url)
139
+ [u.host, u.port]
140
+ end
141
+ Net::HTTP.start(*@open_params) do |http|
142
+ request = Net::HTTP::Head.new(URL(url).full_path.gsub(/ /, "%20"))
143
+ if @login
144
+ case auth_type
145
+ when :ntlm
146
+ request.ntlm_auth(@login, @password)
147
+ when :basic
148
+ request.basic_auth(@login, @password)
149
+ else
150
+ raise ArgumentError, "Unknown authentication type #{auth_type.inspect}"
151
+ end
152
+ end
153
+ response = http.request(request)
154
+ # if Net::HTTPFound === response
155
+ # response = fetch(response["location"])
156
+ # end
157
+ # response
158
+ end
159
+ end
160
+
135
161
  end
136
162
 
137
163
  end
@@ -98,6 +98,11 @@ module ActiveSP
98
98
  end
99
99
  cache :fields, :dup => :always
100
100
 
101
+ def fields_by_name
102
+ fields.inject({}) { |h, f| h[decode_field_name(f.StaticName)] = f ; h }
103
+ end
104
+ cache :fields_by_name, :dup => :always
105
+
101
106
  # See {Base#save}
102
107
  # @return [void]
103
108
  def save
@@ -130,12 +135,12 @@ module ActiveSP
130
135
 
131
136
  def internal_attribute_types
132
137
  @@internal_attribute_types ||= {
133
- "Description" => GhostField.new("ColName", "Text", false, true),
134
- "FeatureId" => GhostField.new("ColName", "Text", false, true),
135
- "Group" => GhostField.new("ColName", "Text", false, true),
138
+ "Description" => GhostField.new("Description", "Text", false, true),
139
+ "FeatureId" => GhostField.new("FeatureId", "Text", false, true),
140
+ "Group" => GhostField.new("Group", "Text", false, true),
136
141
  "Hidden" => GhostField.new("Hidden", "Bool", false, true),
137
- "ID" => GhostField.new("ColName", "Text", false, true),
138
- "Name" => GhostField.new("ColName", "Text", false, true),
142
+ "ID" => GhostField.new("ID", "Text", false, true),
143
+ "Name" => GhostField.new("Name", "Text", false, true),
139
144
  "ReadOnly" => GhostField.new("ReadOnly", "Bool", false, true),
140
145
  "Sealed" => GhostField.new("Sealed", "Bool", false, true),
141
146
  "V2ListTemplateName" => GhostField.new("V2ListTemplateName", "Text", false, true),
@@ -44,10 +44,19 @@ module ActiveSP
44
44
  @item.list.site.connection.fetch(@url).body
45
45
  end
46
46
 
47
+ def content_type
48
+ head_data["content-type"]
49
+ end
50
+
51
+ def content_size
52
+ head_data["content-length"].to_i
53
+ end
54
+
47
55
  def destroy
48
56
  if @destroyable
49
57
  result = call("Lists", "delete_attachment", "listName" => @item.list.id, "listItemID" => @item.ID, "url" => @url)
50
58
  if delete_result = result.xpath("//sp:DeleteAttachmentResponse", NS).first
59
+ @item.clear_cache_for(:attachment_urls)
51
60
  self
52
61
  else
53
62
  raise "file could not be deleted"
@@ -65,6 +74,12 @@ module ActiveSP
65
74
  # @private
66
75
  alias inspect to_s
67
76
 
77
+ private
78
+
79
+ def head_data
80
+ @head_data ||= @item.list.site.connection.head(@url)
81
+ end
82
+
68
83
  end
69
84
 
70
85
  end
@@ -34,7 +34,7 @@ module ActiveSP
34
34
  end
35
35
 
36
36
  def is_folder?
37
- false
37
+ true
38
38
  end
39
39
 
40
40
  # Returns the list of items in this folder
@@ -68,7 +68,7 @@ module ActiveSP
68
68
  end
69
69
 
70
70
  def create_document(parameters = {})
71
- @list.create_document(parameters.merge(:folder => absolute_url))
71
+ @list.create_document(parameters.merge(:folder => absolute_url, :folder_object => self))
72
72
  end
73
73
 
74
74
  # Returns the item with the given name
@@ -35,11 +35,11 @@ module ActiveSP
35
35
  include Util
36
36
 
37
37
  # @private
38
- attr_reader :Name, :internal_type, :Mult, :ReadOnly
38
+ attr_reader :Name, :internal_type, :Mult, :ReadOnly, :DisplayName, :Required
39
39
 
40
40
  # @private
41
- def initialize(name, type, mult, read_only)
42
- @Name, @internal_type, @Mult, @ReadOnly = name, type, mult, read_only
41
+ def initialize(name, type, mult, read_only, display_name = name)
42
+ @Name, @DisplayName, @internal_type, @Mult, @ReadOnly = name, display_name, type, mult, read_only
43
43
  end
44
44
 
45
45
  # @private
@@ -86,7 +86,7 @@ module ActiveSP
86
86
  def original_attributes
87
87
  @original_attributes ||= {
88
88
  "ColName" => @Name,
89
- "DisplayName" => @Name,
89
+ "DisplayName" => @DisplayName,
90
90
  "Mult" => @Mult,
91
91
  "Name" => @Name,
92
92
  "ReadOnly" => @ReadOnly,
@@ -97,8 +97,8 @@ module ActiveSP
97
97
  "Description" => GhostField.new("Description", "Text", false, true),
98
98
  "ID" => GhostField.new("ID", "Text", false, true),
99
99
  "Name" => GhostField.new("Name", "Text", false, true),
100
- "OwnerID" => GhostField.new("OsnerID", "Integer", false, true),
101
- "OwnerIsUser" => GhostField.new("OwnerIsUser", "Bool", false, true)
100
+ "OwnerID" => GhostField.new("OwnerID", "Integer", false, true, "Owner ID"),
101
+ "OwnerIsUser" => GhostField.new("OwnerIsUser", "Bool", false, true, "Owner Is User?")
102
102
  }
103
103
  end
104
104
 
@@ -258,7 +258,9 @@ module ActiveSP
258
258
  if error_code == 0
259
259
  @ID = nil
260
260
  else
261
- raise "cannot create item, error code = #{error_code}"
261
+ message = create_result.xpath("./sp:ErrorText", NS).first
262
+ message &&= message.text
263
+ raise "cannot destroy item, error code = #{error_code}, error description = #{message}"
262
264
  end
263
265
  self
264
266
  end
@@ -306,19 +308,30 @@ module ActiveSP
306
308
  cache :original_attributes
307
309
 
308
310
  def internal_attribute_types
309
- list.fields_by_name
311
+ # list.fields_by_name
312
+ content_type.fields_by_name
310
313
  end
314
+ cache :internal_attribute_types
311
315
 
312
316
  def update_attributes_internal(attributes)
313
317
  attributes = attributes.dup
314
318
  if file_leaf_ref = attributes.delete("FileLeafRef")
315
319
  base_name = ::File.basename(file_leaf_ref, ".*")
320
+ type = ::File.extname(file_leaf_ref).sub(/\A\./, "")
321
+ if type != original_attributes["File Type"].to_s
322
+ raise ArgumentError, "Cannot change file type of a document"
323
+ end
324
+ file_ref = URI.unescape(original_attributes["EncodedAbsUrl"])
316
325
  end
317
- updates = Builder::XmlMarkup.new.Batch("OnError" => "Continue", "ListVersion" => 1) do |xml|
326
+ updates = Builder::XmlMarkup.new.Batch("OnError" => "Continue", "ListVersion" => @list.attribute("Version")) do |xml|
318
327
  xml.Method("ID" => 1, "Cmd" => "Update") do
319
328
  xml.Field(self.ID, "Name" => "ID")
320
329
  construct_xml_for_update_list_items(xml, @list.fields_by_name, attributes)
321
- xml.Field(base_name, "Name" => "BaseName") if base_name
330
+ if file_ref
331
+ xml.Field(base_name, "Name" => "BaseName")
332
+ xml.Field(file_ref, "Name" => "FileRef")
333
+ end
334
+ xml.Field("1", "Name" => "FSObjType") if is_folder?
322
335
  end
323
336
  end
324
337
  result = call("Lists", "update_list_items", "listName" => @list.id, "updates" => updates)
@@ -329,7 +342,9 @@ module ActiveSP
329
342
  @attributes_before_type_cast = clean_item_attributes(row.attributes)
330
343
  reload
331
344
  else
332
- raise "cannot create item, error code = #{error_code}"
345
+ message = create_result.xpath("./sp:ErrorText", NS).first
346
+ message &&= message.text
347
+ raise "cannot update item, error code = #{error_code}, error description = #{message}"
333
348
  end
334
349
  end
335
350
 
@@ -94,7 +94,8 @@ module ActiveSP
94
94
  folder = options.delete(:folder)
95
95
  # Always include a query because for some reason SP is capable of not finding certain
96
96
  # items otherwise.
97
- query = { "query" => options.delete(:query) || "<Query><Where></Where></Query>" }
97
+ # query = { "query" => options.delete(:query) || "<Query><Where></Where></Query>" }
98
+ query = { "query" => options.delete(:query) || "" }
98
99
  no_preload = options.delete(:no_preload)
99
100
  options.empty? or raise ArgumentError, "unknown options #{options.keys.map { |k| k.inspect }.join(", ")}"
100
101
  query_options = Builder::XmlMarkup.new.QueryOptions do |xml|
@@ -152,6 +153,10 @@ module ActiveSP
152
153
  # Returns the item with the given name or nil if there is no item with the given name
153
154
  # @return [Item]
154
155
  def item(name)
156
+ __item(name)
157
+ end
158
+
159
+ def __item(name, options = {})
155
160
  query = Builder::XmlMarkup.new.Query do |xml|
156
161
  xml.Where do |xml|
157
162
  xml.Eq do |xml|
@@ -160,7 +165,7 @@ module ActiveSP
160
165
  end
161
166
  end
162
167
  end
163
- items(:query => query).first
168
+ items(options.merge(:query => query)).first
164
169
  end
165
170
 
166
171
  alias / item
@@ -189,7 +194,11 @@ module ActiveSP
189
194
  else
190
195
  view_fields = Builder::XmlMarkup.new.ViewFields
191
196
  end
192
- result = call("Lists", "get_list_item_changes_since_token", "listName" => @id, 'queryOptions' => '<queryOptions xmlns:s="http://schemas.microsoft.com/sharepoint/soap/" ><QueryOptions/></queryOptions>', 'changeToken' => token, 'viewFields' => view_fields)
197
+ if token
198
+ result = call("Lists", "get_list_item_changes_since_token", "listName" => @id, 'queryOptions' => '<queryOptions xmlns:s="http://schemas.microsoft.com/sharepoint/soap/" ><QueryOptions/></queryOptions>', 'changeToken' => token, 'viewFields' => view_fields)
199
+ else
200
+ result = call("Lists", "get_list_item_changes_since_token", "listName" => @id, 'queryOptions' => '<queryOptions xmlns:s="http://schemas.microsoft.com/sharepoint/soap/" ><QueryOptions/></queryOptions>', 'viewFields' => view_fields)
201
+ end
193
202
  updates = []
194
203
  result.xpath("//z:row", NS).each do |row|
195
204
  attributes = clean_item_attributes(row.attributes)
@@ -361,66 +370,66 @@ module ActiveSP
361
370
 
362
371
  def internal_attribute_types
363
372
  @@internal_attribute_types ||= {
364
- "AllowAnonymousAccess" => GhostField.new("AllowAnonymousAccess", "Bool", false, true),
365
- "AllowDeletion" => GhostField.new("AllowDeletion", "Bool", false, true),
366
- "AllowMultiResponses" => GhostField.new("AllowMultiResponses", "Bool", false, true),
367
- "AnonymousPermMask" => GhostField.new("AnonymousPermMask", "Integer", false, true),
368
- "AnonymousViewListItems" => GhostField.new("AnonymousViewListItems", "Bool", false, true),
373
+ "AllowAnonymousAccess" => GhostField.new("AllowAnonymousAccess", "Bool", false, true, "Allow Anonymous Access?"),
374
+ "AllowDeletion" => GhostField.new("AllowDeletion", "Bool", false, true, "Allow Deletion?"),
375
+ "AllowMultiResponses" => GhostField.new("AllowMultiResponses", "Bool", false, true, "Allow Multiple Responses?"),
376
+ "AnonymousPermMask" => GhostField.new("AnonymousPermMask", "Integer", false, true, "Anonymous Permission Mask"),
377
+ "AnonymousViewListItems" => GhostField.new("AnonymousViewListItems", "Bool", false, true, "Anonymous Can View List Items?"),
369
378
  "Author" => GhostField.new("Author", "InternalUser", false, true),
370
- "BaseTemplate" => GhostField.new("BaseTemplate", "Text", false, true),
371
- "BaseType" => GhostField.new("BaseType", "Text", false, true),
372
- "Created" => GhostField.new("Created", "StandardDateTime", false, true),
373
- "DefaultViewUrl" => GhostField.new("DefaultViewUrl", "Text", false, true),
379
+ "BaseTemplate" => GhostField.new("BaseTemplate", "Text", false, true, "Base Template"),
380
+ "BaseType" => GhostField.new("BaseType", "Text", false, true, "Base Type"),
381
+ "Created" => GhostField.new("Created", "StandardDateTime", false, true, "Created"),
382
+ "DefaultViewUrl" => GhostField.new("DefaultViewUrl", "Text", false, true, "Default View Url"),
374
383
  "Description" => GhostField.new("Description", "Text", false, false),
375
384
  "Direction" => GhostField.new("Direction", "Text", false, true),
376
- "DocTemplateUrl" => GhostField.new("DocTemplateUrl", "Text", false, true),
377
- "EmailAlias" => GhostField.new("EmailAlias", "Text", false, true),
378
- "EmailInsertsFolder" => GhostField.new("EmailInsertsFolder", "Text", false, true),
379
- "EnableAssignedToEmail" => GhostField.new("EnableAssignedToEmail", "Bool", false, true),
380
- "EnableAttachments" => GhostField.new("EnableAttachments", "Bool", false, true),
381
- "EnableMinorVersion" => GhostField.new("EnableMinorVersion", "Bool", false, true),
382
- "EnableModeration" => GhostField.new("EnableModeration", "Bool", false, true),
383
- "EnableVersioning" => GhostField.new("EnableVersioning", "Bool", false, true),
384
- "EventSinkAssembly" => GhostField.new("EventSinkAssembly", "Text", false, true),
385
- "EventSinkClass" => GhostField.new("EventSinkClass", "Text", false, true),
386
- "EventSinkData" => GhostField.new("EventSinkData", "Text", false, true),
387
- "FeatureId" => GhostField.new("FeatureId", "Text", false, true),
385
+ "DocTemplateUrl" => GhostField.new("DocTemplateUrl", "Text", false, true, "Document Template URL"),
386
+ "EmailAlias" => GhostField.new("EmailAlias", "Text", false, true, "Email Alias"),
387
+ "EmailInsertsFolder" => GhostField.new("EmailInsertsFolder", "Text", false, true, "Email Inserts Folder"),
388
+ "EnableAssignedToEmail" => GhostField.new("EnableAssignedToEmail", "Bool", false, true, "Enable Assign to Email?"),
389
+ "EnableAttachments" => GhostField.new("EnableAttachments", "Bool", false, true, "Enable Attachments?"),
390
+ "EnableMinorVersion" => GhostField.new("EnableMinorVersion", "Bool", false, true, "Enable Minor Versions?"),
391
+ "EnableModeration" => GhostField.new("EnableModeration", "Bool", false, true, "Enable Moderation?"),
392
+ "EnableVersioning" => GhostField.new("EnableVersioning", "Bool", false, true, "Enable Versioning?"),
393
+ "EventSinkAssembly" => GhostField.new("EventSinkAssembly", "Text", false, true, "Event Sink Assembly"),
394
+ "EventSinkClass" => GhostField.new("EventSinkClass", "Text", false, true, "Event Sink Class"),
395
+ "EventSinkData" => GhostField.new("EventSinkData", "Text", false, true, "Event Sink Data"),
396
+ "FeatureId" => GhostField.new("FeatureId", "Text", false, true, "Feature ID"),
388
397
  "Flags" => GhostField.new("Flags", "Integer", false, true),
389
- "HasUniqueScopes" => GhostField.new("HasUniqueScopes", "Bool", false, true),
398
+ "HasUniqueScopes" => GhostField.new("HasUniqueScopes", "Bool", false, true, "Has Unique Scopes?"),
390
399
  "Hidden" => GhostField.new("Hidden", "Bool", false, true),
391
400
  "ID" => GhostField.new("ID", "Text", false, true),
392
- "ImageUrl" => GhostField.new("ImageUrl", "Text", false, true),
393
- "InheritedSecurity" => GhostField.new("InheritedSecurity", "Bool", false, true),
394
- "InternalName" => GhostField.new("InternalName", "Text", false, true),
395
- "ItemCount" => GhostField.new("ItemCount", "Integer", false, true),
396
- "LastDeleted" => GhostField.new("LastDeleted", "StandardDateTime", false, true),
397
- "LastModified" => GhostField.new("LastModified", "XMLDateTime", false, true),
398
- "LastModifiedForceRecrawl" => GhostField.new("LastModifiedForceRecrawl", "XMLDateTime", false, true),
399
- "MajorVersionLimit" => GhostField.new("MajorVersionLimit", "Integer", false, true),
400
- "MajorWithMinorVersionsLimit" => GhostField.new("MajorWithMinorVersionsLimit", "Integer", false, true),
401
- "MobileDefaultViewUrl" => GhostField.new("MobileDefaultViewUrl", "Text", false, true),
401
+ "ImageUrl" => GhostField.new("ImageUrl", "Text", false, true, "Image URL"),
402
+ "InheritedSecurity" => GhostField.new("InheritedSecurity", "Bool", false, true, "Has Inherited Security?"),
403
+ "InternalName" => GhostField.new("InternalName", "Text", false, true, "Internal Name"),
404
+ "ItemCount" => GhostField.new("ItemCount", "Integer", false, true, "Item Count"),
405
+ "LastDeleted" => GhostField.new("LastDeleted", "StandardDateTime", false, true, "Deleted"),
406
+ "LastModified" => GhostField.new("LastModified", "XMLDateTime", false, true, "Modified"),
407
+ "LastModifiedForceRecrawl" => GhostField.new("LastModifiedForceRecrawl", "XMLDateTime", false, true, "Last Modified Force Recrawl"),
408
+ "MajorVersionLimit" => GhostField.new("MajorVersionLimit", "Integer", false, true, "Major Version Limit"),
409
+ "MajorWithMinorVersionsLimit" => GhostField.new("MajorWithMinorVersionsLimit", "Integer", false, true, "Major With Minor Versions Limit"),
410
+ "MobileDefaultViewUrl" => GhostField.new("MobileDefaultViewUrl", "Text", false, true, "Mobile Default View URL"),
402
411
  "Modified" => GhostField.new("Modified", "StandardDateTime", false, true),
403
- "MultipleDataList" => GhostField.new("MultipleDataList", "Bool", false, true),
412
+ "MultipleDataList" => GhostField.new("MultipleDataList", "Bool", false, true, "Is Multiple Data List?"),
404
413
  "Name" => GhostField.new("Name", "Text", false, true),
405
414
  "Ordered" => GhostField.new("Ordered", "Bool", false, true),
406
415
  "Permissions" => GhostField.new("Permissions", "Text", false, true),
407
- "ReadSecurity" => GhostField.new("ReadSecurity", "Integer", false, true),
408
- "RequireCheckout" => GhostField.new("RequireCheckout", "Bool", false, true),
409
- "RootFolder" => GhostField.new("RootFolder", "Text", false, true),
410
- "ScopeId" => GhostField.new("ScopeId", "Text", false, true),
411
- "SendToLocation" => GhostField.new("SendToLocation", "Text", false, true),
412
- "ServerTemplate" => GhostField.new("ServerTemplate", "Text", false, true),
413
- "ShowUser" => GhostField.new("ShowUser", "Bool", false, true),
414
- "ThumbnailSize" => GhostField.new("ThumbnailSize", "Integer", false, true),
416
+ "ReadSecurity" => GhostField.new("ReadSecurity", "Integer", false, true, "Read Security"),
417
+ "RequireCheckout" => GhostField.new("RequireCheckout", "Bool", false, true, "Requires Checkout?"),
418
+ "RootFolder" => GhostField.new("RootFolder", "Text", false, true, "Root Folder"),
419
+ "ScopeId" => GhostField.new("ScopeId", "Text", false, true, "Scope ID"),
420
+ "SendToLocation" => GhostField.new("SendToLocation", "Text", false, true, "Send To Location"),
421
+ "ServerTemplate" => GhostField.new("ServerTemplate", "Text", false, true, "Server Template"),
422
+ "ShowUser" => GhostField.new("ShowUser", "Bool", false, true, "Shows User?"),
423
+ "ThumbnailSize" => GhostField.new("ThumbnailSize", "Integer", false, true, "Thumbnail Size"),
415
424
  "Title" => GhostField.new("Title", "Text", false, true),
416
- "ValidSecurityInfo" => GhostField.new("ValidSecurityInfo", "Bool", false, true),
425
+ "ValidSecurityInfo" => GhostField.new("ValidSecurityInfo", "Bool", false, true, "Has Valid Security Info?"),
417
426
  "Version" => GhostField.new("Version", "Integer", false, true),
418
- "WebFullUrl" => GhostField.new("WebFullUrl", "Text", false, true),
419
- "WebId" => GhostField.new("WebId", "Text", false, true),
420
- "WebImageHeight" => GhostField.new("WebImageHeight", "Integer", false, true),
421
- "WebImageWidth" => GhostField.new("WebImageWidth", "Integer", false, true),
422
- "WorkFlowId" => GhostField.new("WorkFlowId", "Text", false, true),
423
- "WriteSecurity" => GhostField.new("WriteSecurity", "Integer", false, true)
427
+ "WebFullUrl" => GhostField.new("WebFullUrl", "Text", false, true, "Full Web URL"),
428
+ "WebId" => GhostField.new("WebId", "Text", false, true, "Web ID"),
429
+ "WebImageHeight" => GhostField.new("WebImageHeight", "Integer", false, true, "Web Image Height"),
430
+ "WebImageWidth" => GhostField.new("WebImageWidth", "Integer", false, true, "Web Image Width"),
431
+ "WorkFlowId" => GhostField.new("WorkFlowId", "Text", false, true, "Work Flow ID"),
432
+ "WriteSecurity" => GhostField.new("WriteSecurity", "Integer", false, true, "Write Security")
424
433
  }
425
434
  end
426
435
 
@@ -456,9 +465,10 @@ module ActiveSP
456
465
  parameters = parameters.dup
457
466
  content = parameters.delete(:content) or raise ArgumentError, "Specify the content in the :content parameter"
458
467
  folder = parameters.delete(:folder)
468
+ folder_object = parameters.delete(:folder_object)
459
469
  overwrite = parameters.delete(:overwrite)
460
470
  file_name = parameters.delete("FileLeafRef") or raise ArgumentError, "Specify the file name in the 'FileLeafRef' parameter"
461
- raise ArgumentError, "document with file name #{file_name.inspect} already exists" if item(file_name) && !overwrite
471
+ raise ArgumentError, "document with file name #{file_name.inspect} already exists" if __item(file_name, :folder => folder_object) && !overwrite
462
472
  destination_urls = Builder::XmlMarkup.new.wsdl(:string, URI.escape(::File.join(folder || url, file_name)))
463
473
  parameters = type_check_attributes_for_creation(fields_by_name, parameters)
464
474
  attributes = untype_cast_attributes(@site, self, fields_by_name, parameters)
@@ -470,13 +480,14 @@ module ActiveSP
470
480
  if error_code != "Success"
471
481
  raise "#{error_code} : #{copy_result["ErrorMessage"]}"
472
482
  else
473
- item(file_name)
483
+ __item(file_name, :folder => folder_object)
474
484
  end
475
485
  end
476
486
 
477
487
  def create_list_item(parameters)
478
488
  parameters = parameters.dup
479
489
  folder = parameters.delete(:folder)
490
+ folder_object = parameters.delete(:folder_object)
480
491
  folder_name = parameters.delete(:folder_name)
481
492
  parameters = type_check_attributes_for_creation(fields_by_name, parameters)
482
493
  attributes = untype_cast_attributes(@site, self, fields_by_name, parameters)
@@ -246,21 +246,21 @@ module ActiveSP
246
246
 
247
247
  def internal_attribute_types
248
248
  @@internal_attribute_types ||= {
249
- "AllowAnonymousAccess" => GhostField.new("AllowAnonymousAccess", "Bool", false, true),
250
- "AnonymousViewListItems" => GhostField.new("AnonymousViewListItems", "Bool", false, true),
249
+ "AllowAnonymousAccess" => GhostField.new("AllowAnonymousAccess", "Bool", false, true, "Allow Anonymous Access?"),
250
+ "AnonymousViewListItems" => GhostField.new("AnonymousViewListItems", "Bool", false, true, "Anonymous Can View List Items?"),
251
251
  "Author" => GhostField.new("Author", "InternalUser", false, true),
252
252
  "Description" => GhostField.new("Description", "Text", false, true),
253
- "ExternalSecurity" => GhostField.new("ExternalSecurity", "Bool", false, true),
254
- "InheritedSecurity" => GhostField.new("InheritedSecurity", "Bool", false, true),
255
- "IsBucketWeb" => GhostField.new("IsBucketWeb", "Bool", false, true),
253
+ "ExternalSecurity" => GhostField.new("ExternalSecurity", "Bool", false, true, "Has External Security?"),
254
+ "InheritedSecurity" => GhostField.new("InheritedSecurity", "Bool", false, true, "Has Inherited Security?"),
255
+ "IsBucketWeb" => GhostField.new("IsBucketWeb", "Bool", false, true, "Is Bucket Web?"),
256
256
  "Language" => GhostField.new("Language", "Integer", false, true),
257
- "LastModified" => GhostField.new("LastModified", "XMLDateTime", false, true),
258
- "LastModifiedForceRecrawl" => GhostField.new("LastModifiedForceRecrawl", "XMLDateTime", false, true),
257
+ "LastModified" => GhostField.new("LastModified", "XMLDateTime", false, true, "Modified"),
258
+ "LastModifiedForceRecrawl" => GhostField.new("LastModifiedForceRecrawl", "XMLDateTime", false, true, "Last Modified Force Recrawl"),
259
259
  "Permissions" => GhostField.new("Permissions", "Text", false, true),
260
260
  "Title" => GhostField.new("Title", "Text", false, true),
261
- "UsedInAutocat" => GhostField.new("UsedInAutocat", "Bool", false, true),
262
- "ValidSecurityInfo" => GhostField.new("ValidSecurityInfo", "Bool", false, true),
263
- "WebID" => GhostField.new("WebID", "Text", false, true)
261
+ "UsedInAutocat" => GhostField.new("UsedInAutocat", "Bool", false, true, "Used in Autocat?"),
262
+ "ValidSecurityInfo" => GhostField.new("ValidSecurityInfo", "Bool", false, true, "Has Valid Security Info?"),
263
+ "WebID" => GhostField.new("WebID", "Text", false, true, "Web ID")
264
264
  }
265
265
  end
266
266
 
@@ -83,9 +83,9 @@ module ActiveSP
83
83
  @@internal_attribute_types ||= {
84
84
  "Email" => GhostField.new("Email", "Text", false, true),
85
85
  "ID" => GhostField.new("ID", "Text", false, true),
86
- "IsDomainGroup" => GhostField.new("Email", "Bool", false, true),
87
- "IsSiteAdmin" => GhostField.new("IsSiteAdmin", "Bool", false, true),
88
- "LoginName" => GhostField.new("LoginName", "Text", false, true),
86
+ "IsDomainGroup" => GhostField.new("Email", "Bool", false, true, "Is Domain Group?"),
87
+ "IsSiteAdmin" => GhostField.new("IsSiteAdmin", "Bool", false, true, "Is Site Admin?"),
88
+ "LoginName" => GhostField.new("LoginName", "Text", false, true, "Login Name"),
89
89
  "Name" => GhostField.new("Name", "Text", false, true),
90
90
  "Notes" => GhostField.new("Notes", "Text", false, true),
91
91
  "Sid" => GhostField.new("Sid", "Text", false, true)
@@ -53,7 +53,11 @@ module ActiveSP
53
53
  when "DateTime"
54
54
  v = Time.parse(v)
55
55
  when "XMLDateTime"
56
- v = Time.xmlschema(v.sub(/ /, "T"))
56
+ if v == "0001-01-01T00:00:00"
57
+ v = nil
58
+ else
59
+ v = Time.xmlschema(v.sub(/ /, "T"))
60
+ end
57
61
  when "Computed", "Text", "Guid", "ContentTypeId", "URL"
58
62
  when "Integer", "Counter", "Attachments"
59
63
  v = v && v != "" ? Integer(v) : nil
@@ -70,9 +74,9 @@ module ActiveSP
70
74
 
71
75
  when "User"
72
76
  d = split_multi(v)
73
- v = create_user_or_group(site, d[2])
77
+ v = create_user_or_group_by_name(site, d[2])
74
78
  when "InternalUser"
75
- v = create_user_or_group(site, v)
79
+ v = create_user_or_group_by_name(site, v)
76
80
  when "UserMulti"
77
81
  d = split_multi(v)
78
82
  v = (0...(d.length / 4)).map { |i| create_user_or_group(site, d[4 * i + 2]) }
@@ -118,23 +122,43 @@ module ActiveSP
118
122
  end
119
123
 
120
124
  def create_user_or_group(site, entry)
121
- if entry == "System Account"
122
- User.new(site.connection.root, "SHAREPOINT\\system")
123
- elsif entry[/\\/]
125
+ if entry[/\\/]
124
126
  User.new(site.connection.root, entry)
125
127
  else
126
128
  Group.new(site.connection.root, entry)
127
129
  end
128
130
  end
129
131
 
132
+ def create_user_or_group_by_name(site, name)
133
+ if /\A\d+\z/ === name
134
+ create_user_or_group_by_id(site, name)
135
+ else
136
+ if user = site.connection.users.find { |u| u.attribute("Name") === name }
137
+ User.new(site.connection.root, user.attribute("LoginName"))
138
+ elsif group = site.connection.groups.find { |g| g.attribute("Name") === name }
139
+ Group.new(site.connection.root, name)
140
+ end
141
+ end
142
+ end
143
+
144
+ def create_user_or_group_by_id(site, id)
145
+ if user = site.connection.users.find { |u| u.attribute("ID") === id }
146
+ User.new(site.connection.root, user.attribute("LoginName"))
147
+ elsif group = site.connection.groups.find { |g| g.attribute("ID") === id }
148
+ Group.new(site.connection.root, group.attribute("Name"))
149
+ end
150
+ end
151
+
130
152
  def type_check_attribute(field, value)
131
153
  case field.internal_type
132
- when "Text", "File"
154
+ when "Text", "File", "Note", "URL", "Choice"
133
155
  value.to_s
134
156
  when "Bool", "Boolean"
135
157
  !!value
136
158
  when "Integer"
137
- Integer(value)
159
+ Integer(value) if value
160
+ when "Number"
161
+ Float(value) if value
138
162
  when "StandardDateTime", "XMLDateTime"
139
163
  Time === value and value or raise ArgumentError, "wrong type for #{field.Name} attribute"
140
164
  when "InternalUser"
@@ -173,6 +197,8 @@ module ActiveSP
173
197
  if ::ActiveSP::User === value || field.attributes["UserSelectionMode"] == "PeopleAndGroups" && ::ActiveSP::Group === value
174
198
  # TODO: check if the user is in the correct group in case a group is specified
175
199
  value
200
+ elsif value == nil && !field.attributes["Required"]
201
+ nil
176
202
  else
177
203
  raise ArgumentError, "wrong type for #{field.Name} attribute"
178
204
  end
@@ -190,6 +216,8 @@ module ActiveSP
190
216
  raise ArgumentError, "wrong type for #{field.Name} attribute"
191
217
  end
192
218
  end
219
+ when "ContentTypeId"
220
+ value
193
221
  else
194
222
  raise "not yet #{field.Name}:#{field.internal_type}"
195
223
  end
@@ -198,7 +226,7 @@ module ActiveSP
198
226
  def type_check_attributes_for_creation(fields, attributes)
199
227
  attributes.inject({}) do |h, (k, v)|
200
228
  if field = fields[k]
201
- if !field.ReadOnly
229
+ if !field.ReadOnly || field.Name == "ContentType"
202
230
  h[k] = type_check_attribute(field, v)
203
231
  h
204
232
  else
@@ -214,23 +242,26 @@ module ActiveSP
214
242
  attributes.inject({}) do |h, (k, v)|
215
243
  if field = fields[k]
216
244
  case field.internal_type
217
- when "Text", "File"
245
+ when "Text", "File", "Note", "URL", "Choice"
218
246
  when "Bool"
219
247
  v = v ? "TRUE" : "FALSE"
220
248
  when "Boolean"
221
249
  v = v ? "1" : "0"
222
250
  when "Integer"
223
251
  v = v.to_s
252
+ when "Number"
253
+ v = v.to_s
224
254
  when "DateTime"
225
255
  v = v.strftime("%Y-%m-%d %H:%M:%S")
226
256
  when "User"
227
- v = v.ID
257
+ v = v.ID if v
228
258
  when "UserMulti"
229
259
  v = v.map { |ug| ug.ID }.join(";#;#")
230
260
  when "Lookup"
231
- v = v.ID
261
+ v = v.ID if v
232
262
  when "LookupMulti"
233
263
  v = v.map { |i| i.ID }.join(";#;#")
264
+ when "ContentTypeId"
234
265
  else
235
266
  raise "don't know type #{field.internal_type.inspect} for #{k}=#{v.inspect} on self"
236
267
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activesp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 7
10
- version: 0.0.7
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Peter Vanbroekhoven
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-11 00:00:00 +01:00
18
+ date: 2011-05-19 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -24,12 +24,15 @@ dependencies:
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ">="
27
+ - - "="
28
28
  - !ruby/object:Gem::Version
29
- hash: 3
29
+ hash: 113
30
30
  segments:
31
31
  - 0
32
- version: "0"
32
+ - 7
33
+ - 2
34
+ - 7
35
+ version: 0.7.2.7
33
36
  type: :runtime
34
37
  version_requirements: *id001
35
38
  - !ruby/object:Gem::Dependency
@@ -81,7 +84,7 @@ files:
81
84
  - lib/activesp/user.rb
82
85
  - lib/activesp/util.rb
83
86
  - lib/activesp.rb
84
- has_rdoc: false
87
+ has_rdoc: true
85
88
  homepage: http://www.xaop.com/labs/activesp
86
89
  licenses: []
87
90