activesp 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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