activesp 0.0.1 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,25 @@
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
+
10
+ Software is furnished to do so, subject to the following
11
+ conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
+
23
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,105 @@
1
+ = ActiveSP Release 0.0.3 "Under Pressure" (Aug 27th 2010)
2
+
3
+ == What?
4
+
5
+ ActiveSP is a library for talking to SharePoint through its web services in an
6
+ object-oriented way.
7
+
8
+ At the moment it only provides read-only access and write access to list items.
9
+ Full write access is on the way!
10
+
11
+ == Why?
12
+
13
+ Because Ruby is great and SharePoint's popularity is a fact of life.
14
+
15
+ == When?
16
+
17
+ This library is pure Ruby and does not need a Ruby VM running on .NET (such as IronRuby).
18
+ Use this library when using IronRuby is not an option, or when it needs to run on more
19
+ than IronRuby.
20
+
21
+ The web services are not fully functional and somewhat slow, so if you can use
22
+ the .NET platform then consider talking to the .NET API's directly instead.
23
+
24
+ == How?
25
+
26
+ Install the gem and its dependencies:
27
+
28
+ gem install activesp
29
+
30
+ Create a file <tt>test.rb</tt> like this:
31
+
32
+ require 'rubygems'
33
+ require 'activesp'
34
+
35
+ def browse(item, indentation = 0)
36
+ puts " " * indentation + "- " + item.class.to_s + " : " + item.url
37
+ case item
38
+ when ActiveSP::Site
39
+ puts " " * indentation + " Title = #{item.Title}, Description = #{item.Description}"
40
+ item.sites.each { |site| browse(site, indentation + 1) }
41
+ item.lists.each { |list| browse(list, indentation + 1) }
42
+ when ActiveSP::List
43
+ puts " " * indentation + " Description = #{item.Description}, Hidden = #{item.Hidden}"
44
+ item.items.each { |item| browse(item, indentation + 1) }
45
+ when ActiveSP::Folder
46
+ item.items.each { |item| browse(item, indentation + 1) }
47
+ when ActiveSP::Item
48
+ item.content_urls.each do |url|
49
+ puts " " * indentation + " Content URL = #{url}"
50
+ end
51
+ end
52
+ end
53
+
54
+ c = ActiveSP::Connection.new(:login => "your login", :password => "your password", :root => "URL of root site")
55
+
56
+ browse(c.root)
57
+
58
+ Run <tt>ruby test.rb</tt> and it will print the structure of your SharePoint site.
59
+
60
+ The examples directory contains this example plus a few others. We will add more along the way.
61
+
62
+ == Support
63
+
64
+ We support read access to sites (webs), lists, items, documents, folders, content type,
65
+ columns (fields), content, users, groups, roles.
66
+
67
+ We support write access to list items (including documents): create, update and delete list items.
68
+
69
+ We do not yet support life cycles, versions, full write support.
70
+
71
+ == Compatibility
72
+
73
+ We have tested ActiveSP with SharePoint 2007 and SharePoint 2010. ActiveSP has been tested
74
+ on Mac OS X with Ruby 1.8.6, but we do not see any reason why it would not work on Linux
75
+ or Windows, or with other Ruby implementations.
76
+
77
+ For release 0.0.3, we have not tested extensively on SharePoint 2007 so we can't guarantee
78
+ compatibility.
79
+
80
+ == Changelog
81
+
82
+ === ActiveSP Release 0.0.3 "Under Pressure" (Aug 27th 2010)
83
+
84
+ * Added write support for list items (including documents): create, update, delete
85
+ * Use association proxies for list items and item attachments
86
+ * Decode field names (e.g., File_x0020_Type becomes File Type)
87
+ * A few bug fixes
88
+ * Added method to ask for list changes since token
89
+
90
+ === ActiveSP Release 0.0.1 "Space Oddity" (Apr 9th 2010)
91
+
92
+ * Initial release
93
+
94
+ == License
95
+
96
+ ActiveSP is released under the MIT license. The usual disclaimers apply, including that we are
97
+ not responsible for inevitable Ruby addiction.
98
+
99
+ See the LICENSE file included in the distribution for further details.
100
+
101
+ == Who?
102
+
103
+ ActiveSP is copyright (c) 2010 XAOP bvba
104
+
105
+ Visit us at http://www.xaop.com.
data/Rakefile CHANGED
@@ -1,5 +1,31 @@
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
+
1
26
  require 'rubygems'
2
27
  require 'rake/gempackagetask'
28
+ require 'yard'
3
29
 
4
30
  ACTIVESP_VERSION = File.readlines("VERSION")[0][/[\d.]*/]
5
31
 
@@ -9,18 +35,17 @@ spec = Gem::Specification.new do |s|
9
35
  s.version = ACTIVESP_VERSION
10
36
  s.author = "Peter Vanbroekhoven"
11
37
  s.email = "peter@xaop.com"
12
- #s.homepage = "http://www.xaop.com/pages/dctmruby"
38
+ s.homepage = "http://www.xaop.com/labs/activesp"
13
39
  s.summary = "Interface to SharePoint"
14
- s.description = s.summary
15
- #s.rubyforge_project = s.name
16
- s.files += %w(VERSION Rakefile)
40
+ s.description = "An object-oriented interface to SharePoint that uses the web services provided by SharePoint to connect to it. Supports SharePoint 2007 and 2010."
41
+ s.files += %w(VERSION LICENSE README.rdoc Rakefile)
17
42
  s.files += Dir['lib/**/*.rb']
18
43
  # s.bindir = "bin"
19
- # s.executables.push(*(Dir['bin/*.rb'] - ["bin/encrypt-dmcl.rb"]).map { |f| File.basename(f) })
44
+ # s.executables.push(*(Dir['bin/*.rb']))
20
45
  s.add_dependency('savon-xaop')
21
46
  s.add_dependency('nokogiri')
22
47
  # s.rdoc_options << '--exclude' << 'ext' << '--main' << 'README'
23
- # s.extra_rdoc_files = ["README", "docs/README.html"]
48
+ # s.extra_rdoc_files = ["README"]
24
49
  s.has_rdoc = false
25
50
  s.require_paths << 'lib'
26
51
  # s.autorequire = 'mysql'
@@ -32,3 +57,7 @@ Rake::GemPackageTask.new(spec) do |pkg|
32
57
  pkg.need_zip = true
33
58
  pkg.need_tar = true
34
59
  end
60
+
61
+ YARD::Rake::YardocTask.new do |t|
62
+ t.options = ['--no-private', '--readme', 'README.rdoc']
63
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.4
data/lib/activesp.rb CHANGED
@@ -1,3 +1,28 @@
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
+
1
26
  require 'nokogiri'
2
27
  require 'time'
3
28
 
@@ -6,6 +31,7 @@ end
6
31
 
7
32
  require 'activesp/util'
8
33
  require 'activesp/caching'
34
+ require 'activesp/associations'
9
35
  require 'activesp/persistent_caching'
10
36
 
11
37
  require 'activesp/base'
@@ -24,3 +50,4 @@ require 'activesp/user'
24
50
  require 'activesp/group'
25
51
  require 'activesp/role'
26
52
  require 'activesp/permission_set'
53
+ require 'activesp/file'
@@ -0,0 +1,76 @@
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
+ # @private
29
+ module Associations
30
+
31
+ class AssociationProxy
32
+
33
+ include Enumerable
34
+
35
+ def initialize(object, &element_getter)
36
+ @object = object
37
+ @element_getter = element_getter
38
+ end
39
+
40
+ def each(&blk)
41
+ @element_getter.call(blk)
42
+ end
43
+
44
+ def first
45
+ each { |element| return element }
46
+ nil
47
+ end
48
+
49
+ def last
50
+ inject { |_, element| element }
51
+ end
52
+
53
+ def count
54
+ inject(0) { |cnt, _| cnt + 1 }
55
+ end
56
+
57
+ end
58
+
59
+ private
60
+
61
+ def association(name, each_method = ("each_" + name.to_s.sub(/s\z/, "")).to_sym, &blk)
62
+ proxy = Class.new(AssociationProxy) do
63
+ class_eval(&blk) if blk
64
+ define_method(:to_s) { "#{@object.to_s}.#{name}" }
65
+ define_method(:inspect) { "#{@object.inspect}.#{name}" }
66
+ end
67
+ define_method(name) do |*a|
68
+ proxy.new(self) do |blk|
69
+ send(each_method, *a, &blk)
70
+ end
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ end
data/lib/activesp/base.rb CHANGED
@@ -1,35 +1,99 @@
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
+
1
26
  module ActiveSP
2
27
 
28
+ # The base class for all objects stored in SharePoint
3
29
  class Base
4
30
 
5
31
  extend Caching
32
+ extend Associations
6
33
 
34
+ # Returns a key that can be used to retrieve this object later on using {Connection#find_by_key}
35
+ # @return [String]
36
+ def key
37
+ raise "This is here for documentation purposes only"
38
+ end
39
+
40
+ # Returns the attributes of this object as a Hash
41
+ # @return [Hash{String => Integer, Float, String, Time, Boolean, Base}]
7
42
  def attributes
8
43
  current_attributes
9
44
  end
10
- cache :attributes, :dup => true
45
+ cache :attributes, :dup => :always
11
46
 
47
+ # Returns the types of the attributes of this object as a Hash
48
+ # @return [Hash{String => Field}]
12
49
  def attribute_types
13
50
  internal_attribute_types
14
51
  end
15
- cache :attribute_types, :dup => true
52
+ cache :attribute_types, :dup => :always
16
53
 
54
+ # Returns whether or not this object has an attribute with the given name
55
+ # @param [String] name The name of the attribute
56
+ # @return [Boolean]
17
57
  def has_attribute?(name)
18
- attributes.has_key?(name)
58
+ current_attributes.has_key?(name)
19
59
  end
20
60
 
61
+ # Returns whether or not this object has an attribute with the given name that can be assigned to
62
+ # @param [String] name The name of the attribute
63
+ # @return [Boolean]
21
64
  def has_writable_attribute?(name)
22
- has_attribute?(name) && !attribute_types[name].ReadOnly
65
+ has_attribute?(name) and attr = internal_attribute_types[name] and !attr.ReadOnly
23
66
  end
24
67
 
68
+ # Returns the value of the attribute of the given name, or nil if this object does not have an attribute by the given name
69
+ # @param [String] name The name of the attribute
70
+ # @return [Integer, Float, String, Time, Boolean, Base]
25
71
  def attribute(name)
26
- attributes[name]
72
+ current_attributes[name]
73
+ end
74
+
75
+ # Returns the type of the attribute by the given name, or nil if this object does not have an attribute by the given name
76
+ # @param [String] name The name of the attribute
77
+ # @return [Field]
78
+ def attribute_type(name)
79
+ internal_attribute_types[name]
27
80
  end
28
81
 
82
+ # Sets the attribute with the given name to the given value
83
+ # @param [String] name The name of the attribute
84
+ # @param [Integer, Float, String, Time, Boolean, Base] value The value to assign
85
+ # @return [Integer, Float, String, Time, Boolean, Base] The assigned value
86
+ # @raise [ArgumentError] Raised when this object does not have an attribute by the given name or if the attribute by the given name is read-only
29
87
  def set_attribute(name, value)
30
- current_attributes[name] = value
88
+ has_attribute?(name) and field = attribute_type(name) and internal_attribute_types[name] or raise ArgumentError, "#{self} has no field by the name #{name}"
89
+ !field.ReadOnly or raise ArgumentError, "field #{name} of #{self} is read-only"
90
+ current_attributes[name] = type_check_attribute(field, value)
31
91
  end
32
92
 
93
+ # Provides convenient getters and setters for attributes. Note that no name mangling
94
+ # is done, so an attribute such as Title is accessed as obj.Title. The main rationale
95
+ # behind this is that name mangling is usually not lossless (e.g., both <tt>Title</tt>
96
+ # and <tt>title</tt> could map to the more Rubyish <tt>title</tt>) and imperfect.
33
97
  def method_missing(m, *a, &b)
34
98
  ms = m.to_s
35
99
  if a.length == 0 && has_attribute?(ms)
@@ -41,13 +105,35 @@ module ActiveSP
41
105
  end
42
106
  end
43
107
 
108
+ # Reloads the object from the server
109
+ # @return [void]
110
+ def reload
111
+ end
112
+
113
+ # Saves the object to the server. Raises an exception when the save fails
114
+ # @return [void]
115
+ def save
116
+ end
117
+
44
118
  private
45
119
 
46
120
  def current_attributes
47
- original_attributes
121
+ original_attributes.inject({}) { |h, (k, v)| h[k] = ::Array === v ? v.dup.freeze : v ; h }
48
122
  end
49
123
  cache :current_attributes
50
124
 
125
+ def changed_attributes
126
+ before = original_attributes
127
+ after = current_attributes
128
+ changes = {}
129
+ after.each do |name, value|
130
+ if before[name] != value
131
+ changes[name] = value
132
+ end
133
+ end
134
+ changes
135
+ end
136
+
51
137
  end
52
138
 
53
139
  end