viewpoint-spws 0.5.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.
@@ -0,0 +1,107 @@
1
+ =begin
2
+ This file is part of ViewpointSPWS; the Ruby library for Microsoft Sharepoint Web Services.
3
+
4
+ Copyright © 2011 Dan Wanek <dan.wanek@gmail.com>
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ # This class is the glue between the Models and the Web Service.
20
+ class Viewpoint::SPWSClient
21
+ include Viewpoint::SPWS
22
+
23
+ # Initialize the SPWSClient instance.
24
+ # @param [String] endpoint The SPWS endpoint we will be connecting to
25
+ # @param [String] user The user to authenticate as. If you are using
26
+ # NTLM or Negotiate authentication you do not need to pass this parameter.
27
+ # @param [String] pass The user password. If you are using NTLM or
28
+ # Negotiate authentication you do not need to pass this parameter.
29
+ def initialize(endpoint, user = nil, pass = nil)
30
+ @con = Connection.new(endpoint)
31
+ @con.set_auth(user,pass) if(user && pass)
32
+ end
33
+
34
+ def copy_ws
35
+ @copyws ||= Websvc::Copy.new(@con)
36
+ end
37
+
38
+ def lists_ws
39
+ @listsws ||= Websvc::Lists.new(@con)
40
+ end
41
+
42
+ def usergroup_ws
43
+ @usergroupws ||= Websvc::UserGroup.new(@con)
44
+ end
45
+
46
+
47
+ # ========= List Accessor Proxy Methods =========
48
+
49
+ # Available list types that can be used for #add_list
50
+ LIST_TYPES = {
51
+ :custom_list => 100,
52
+ :document_library => 101,
53
+ :survey => 102,
54
+ :links => 103,
55
+ :announcements => 104,
56
+ :contacts => 105,
57
+ :events => 106,
58
+ :tasks => 107,
59
+ :discussion_board => 108,
60
+ :picture_library => 109,
61
+ :datasources => 110,
62
+ :form_library => 115,
63
+ :issues => 1100,
64
+ :custom_list_for_datasheet => 120,
65
+ }
66
+
67
+ # Retrieve all of the viewable lists for this site.
68
+ def get_lists
69
+ lists_ws.get_list_collection
70
+ end
71
+
72
+ # Retrieve a List object
73
+ # @param [String] list title or the GUID for the list
74
+ def get_list(list)
75
+ lists_ws.get_list(list)
76
+ end
77
+
78
+ # Add a List to this site
79
+ # @param [String] name A name for the List
80
+ # @param [String] desc A description of the List
81
+ # @param [Integer] list_type The list template id. Use the LIST_TYPES Hash.
82
+ def add_list(name, desc, list_type)
83
+ lists_ws.add_list(name, desc, list_type)
84
+ end
85
+
86
+ # Delete a list from this site.
87
+ # @param [String] list title or the GUID for the list
88
+ def delete_list(list)
89
+ lists_ws.delete_list(list)
90
+ end
91
+
92
+ # ========= UserGroup Accessor Proxy Methods =========
93
+
94
+ # Retrieve a user by e-mail
95
+ # @param [String] user either in e-mail form or DOMAIN\login form. If you
96
+ # specify an e-mail there is an additional web service call that needs
97
+ # to be made so if you're worried about performance use the DOMAIN\login
98
+ # form.
99
+ # @return [Viewpoint::SPWS::Types::User]
100
+ def get_user(user)
101
+ if user =~ /@/
102
+ ulh = usergroup_ws.get_user_login_from_email [user]
103
+ user = ulh[user]
104
+ end
105
+ usergroup_ws.get_user_info user
106
+ end
107
+ end
@@ -0,0 +1,27 @@
1
+ =begin
2
+ This file is part of ViewpointSPWS; the Ruby library for Microsoft Sharepoint Web Services.
3
+
4
+ Copyright © 2011 Dan Wanek <dan.wanek@gmail.com>
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ module Viewpoint::SPWS
20
+ module Types
21
+ PRIORITY = {:high => '(1) High', :normal => '(2) Normal', :low => '(3) Low'}.freeze
22
+
23
+ STATUS = {:not_started => 'Not Started', :in_progress => 'In Progress',
24
+ :completed => 'Completed', :deferred => 'Deferred',
25
+ :waiting => 'Waiting on someone else'}.freeze
26
+ end
27
+ end
@@ -0,0 +1,41 @@
1
+ =begin
2
+ This file is part of ViewpointSPWS; the Ruby library for Microsoft Sharepoint Web Services.
3
+
4
+ Copyright © 2011 Dan Wanek <dan.wanek@gmail.com>
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ # This class represents a Sharepoint List returned from the Lists Web Service with a
20
+ # ServerTemplate id of 101 (DocumentLibrary).
21
+ # @see http://msdn.microsoft.com/en-us/library/ms774810(v=office.12).aspx
22
+ class Viewpoint::SPWS::Types::DocumentLibrary < Viewpoint::SPWS::Types::List
23
+ include Viewpoint::SPWS::Types
24
+
25
+ # @param [Viewpoint::SPWS::Websvc::List] ws The webservice instance this List spawned from
26
+ # @param [Nokogiri::XML::Element] xml the List element we are building from
27
+ def initialize(ws, xml)
28
+ @copy_ws = Viewpoint::SPWS::Websvc::Copy.new(ws.spcon)
29
+ super
30
+ end
31
+
32
+ # Add a Document to this List
33
+ # @param [Hash] opts parameters for this Document
34
+ # @option opts [String] :file Path to the file to upload
35
+ # @return [Viewpoint::SPWS::Types::ListItem] The newly added Task
36
+ def add_file!(opts)
37
+ raise "Valid file argument required" unless(opts[:file] && File.exists?(opts[:file]))
38
+ fqpath = "#{self.path}/#{File.basename(opts[:file])}"
39
+ @copy_ws.copy_into_items(opts[:file], [fqpath])
40
+ end
41
+ end
@@ -0,0 +1,107 @@
1
+ =begin
2
+ This file is part of ViewpointSPWS; the Ruby library for Microsoft Sharepoint Web Services.
3
+
4
+ Copyright © 2011 Dan Wanek <dan.wanek@gmail.com>
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ # This class represents a Sharepoint List returned from the Lists Web Service
20
+ # @see http://msdn.microsoft.com/en-us/library/ms774810(v=office.12).aspx
21
+ class Viewpoint::SPWS::Types::List
22
+ include Viewpoint::SPWS::Types
23
+
24
+ attr_reader :guid, :title, :description, :created, :modified, :server_template,
25
+ :feature_id, :root_folder
26
+
27
+ # @param [Viewpoint::SPWS::Websvc::List] ws The webservice instance this List spawned from
28
+ # @param [Nokogiri::XML::Element] xml the List element we are building from
29
+ def initialize(ws, xml)
30
+ @ws = ws
31
+ @guid = xml['ID']
32
+ @title = xml['Title']
33
+ @description = xml['Description']
34
+ @hidden = (xml['Hidden'] == 'True')
35
+ @created = DateTime.parse(xml['Created'])
36
+ @modified = DateTime.parse(xml['Modified'])
37
+ @last_deleted = DateTime.parse(xml['LastDeleted'])
38
+ @item_count = xml['ItemCount']
39
+ @server_template= xml['ServerTemplate'].to_i
40
+ @feature_id = xml['FeatureId']
41
+ @root_folder = xml['RootFolder']
42
+ #@xmldoc = xml
43
+ @list_path = nil
44
+ end
45
+
46
+ # Return the full-qualified path of this List
47
+ def path
48
+ return @list_path if @list_path
49
+ site = @ws.spcon.site_base
50
+ @list_path = "#{site.scheme}://#{site.host}"
51
+ @list_path << ":#{site.port}" unless(site.port == 80 || site.port == 443)
52
+ @list_path << @root_folder
53
+ end
54
+
55
+ # Add a ListItem
56
+ # @param [Hash] opts options for List creation.
57
+ def add_item!(opts)
58
+ op = { :command => 'New', :id => 'New' }
59
+ opts.keys.each do |k|
60
+ case k
61
+ when :priority
62
+ op[k] = PRIORITY[opts[:priority]]
63
+ when :status
64
+ op[k] = STATUS[opts[:status]]
65
+ when :percent_complete
66
+ op[k] = opts[k] * 0.01
67
+ else
68
+ op[k] = opts[k]
69
+ end
70
+ end
71
+
72
+ resp = @ws.update_list_items(@guid, :item_updates => [op])
73
+ resp[:new].first
74
+ end
75
+
76
+ # Delete this List
77
+ def delete!
78
+ @ws.delete_list(@guid)
79
+ end
80
+
81
+ # Return the items in this List
82
+ def items
83
+ @ws.get_list_items(@guid)
84
+ end
85
+
86
+ # @param [String] item_id The item id for the item you want to retrieve
87
+ def get_item(item_id)
88
+ addl_fields = %w{LinkTitle Body AssignedTo Status Priority DueDate PercentComplete}
89
+
90
+ i = @ws.get_list_items(@guid, :recursive => true, :view_fields => addl_fields) do |b|
91
+ b.Query {
92
+ b.Where {
93
+ b.Eq {
94
+ b.FieldRef(:Name => 'ID')
95
+ b.Value(item_id, :Type => 'Counter')
96
+ }
97
+ }
98
+ }
99
+ end
100
+ raise "Returned more than one item for #get_item" if(i.length > 1)
101
+ i.first
102
+ end
103
+
104
+ def hidden?
105
+ @hidden
106
+ end
107
+ end
@@ -0,0 +1,248 @@
1
+ =begin
2
+ This file is part of ViewpointSPWS; the Ruby library for Microsoft Sharepoint Web Services.
3
+
4
+ Copyright © 2011 Dan Wanek <dan.wanek@gmail.com>
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ # This class represents a Sharepoint ListItem returned from the Lists Web Service
20
+ # @see
21
+ class Viewpoint::SPWS::Types::ListItem
22
+ include Viewpoint::SPWS::Types
23
+
24
+ attr_reader :id, :body, :file_name, :file_ref, :editor, :guid, :object_type
25
+ attr_reader :created_date, :modified_date, :due_date
26
+ attr_reader :title, :link_title, :status, :priority, :percent_complete
27
+
28
+ # @param [Viewpoint::SPWS::Websvc::List] ws The webservice instance this ListItem spawned from
29
+ # @param [String] list_id The list id that this item belongs to
30
+ # @param [Nokogiri::XML::Element] xml the List element we are building from
31
+ def initialize(ws, list_id, xml)
32
+ @ws = ws
33
+ @list_id = list_id
34
+ @pending_updates = [] # a place to store updates before #save! is called
35
+ @update_keys = {} # the variables to update after #save!
36
+ parse_xml_fields(xml)
37
+ end
38
+
39
+ # Save any pending changes
40
+ def save!
41
+ return true if @pending_updates.empty?
42
+ resp = @ws.update_list_items(@list_id, :item_updates => @pending_updates)
43
+ # @todo check for success before emptying Arry
44
+ update_local_vars resp[:update][0]
45
+ @pending_updates.clear
46
+ true
47
+ resp
48
+ end
49
+
50
+ # Pass a block of updates that will be committed in one transaction
51
+ # @example
52
+ # li.update! do |l|
53
+ # l.rename 'New Name'
54
+ # l.set_priority :low
55
+ # l.set_status :waiting
56
+ # end
57
+ def update!
58
+ yield self if block_given?
59
+ save!
60
+ end
61
+
62
+ # Delete this ListItem
63
+ def delete!
64
+ del = [{ :id => @id, :command => 'Delete',
65
+ :file_ref => full_file_ref }]
66
+ @ws.update_list_items(@list_id, :item_updates => del)
67
+ end
68
+
69
+
70
+ # Set a new title for this Item
71
+ # @param [String] title The new title
72
+ def rename(title)
73
+ raise "There is already a pending rename" if @update_keys[:@title]
74
+ upd = { :id => @id, :command => 'Update',
75
+ :title => title,
76
+ }
77
+ @pending_updates << upd
78
+ @update_keys[:@title] = 'ows_Title'
79
+ @update_keys[:@link_title] = 'ows_LinkTitle'
80
+ title
81
+ end
82
+
83
+ # Set a new title for this Item
84
+ # @see #rename
85
+ def rename!(title)
86
+ rename(title)
87
+ save!
88
+ end
89
+
90
+ # Set the priority of this Item
91
+ # @param [Symbol] priority The new priority. It must be one of these values:
92
+ # :high, :normal, :low
93
+ def set_priority(priority)
94
+ raise "Invalid priority it must be one of: #{PRIORITY.keys.join(', ')}" unless PRIORITY[priority]
95
+ raise "There is already a pending priority change" if @update_keys[:@priority]
96
+ upd = { :id => @id, :command => 'Update',
97
+ :priority => PRIORITY[priority],
98
+ }
99
+ @pending_updates << upd
100
+ @update_keys[:@priority] = 'ows_Priority'
101
+ priority
102
+ end
103
+
104
+ # Set the priority of this Item
105
+ # @see #set_priority
106
+ def set_priority!(priority)
107
+ set_priority priority
108
+ save!
109
+ end
110
+
111
+ # Set the status of this Item
112
+ # @param [Symbol] status The new status. It must be one of these values:
113
+ # :not_started, :in_progress, :completed, :deferred, :waiting
114
+ def set_status(status)
115
+ raise "Invalid status it must be one of: #{STATUS.keys.join(', ')}" unless STATUS[status]
116
+ raise "There is already a pending status change" if @update_keys[:@status]
117
+ upd = { :id => @id, :command => 'Update',
118
+ :status => STATUS[status],
119
+ }
120
+ @pending_updates << upd
121
+ @update_keys[:@status] = 'ows_Status'
122
+ status
123
+ end
124
+
125
+ # Set the status of this Item
126
+ # @see #set_status
127
+ def set_status!(status)
128
+ set_status(status)
129
+ save!
130
+ end
131
+
132
+ # Set the percentage complete of this item.
133
+ # @param [Fixnum] pct the percent complete of this item
134
+ def set_percent_complete(pct)
135
+ if(!(0..100).include?(pct))
136
+ raise "Invalid :percent_complete #{topts[:percent_complete]}"
137
+ end
138
+ raise "There is already a pending percent complete change" if @update_keys[:@percent_complete]
139
+
140
+ upd = { :id => @id, :command => 'Update',
141
+ :percent_complete => pct,
142
+ }
143
+ @pending_updates << upd
144
+ @update_keys[:@percent_complete] = 'ows_PercentComplete'
145
+ pct
146
+ end
147
+
148
+ # Set the percentage complete of this item.
149
+ # @see #set_percent_complete
150
+ def set_percent_complete!(pct)
151
+ set_percent_complete pct
152
+ save!
153
+ end
154
+
155
+ # Assign this item to a user
156
+ # @param [Viewpoint::SPWS::Types::User] user The user to assign this ListItem
157
+ # @todo should I return the String representation of the user or the Types::User?
158
+ def assign(user)
159
+ raise "There is already a pending assignment" if @update_keys[:@assigned_to]
160
+ upd = { :id => @id, :command => 'Update',
161
+ :AssignedTo => "#{user.id};##{user.login_name}",
162
+ }
163
+ @pending_updates << upd
164
+ @update_keys[:@assigned_to] = 'ows_AssignedTo'
165
+ user
166
+ end
167
+
168
+ # Assign this item to a user
169
+ # @see #assign
170
+ def assign!(user)
171
+ assign(user)
172
+ save!
173
+ end
174
+
175
+ private
176
+
177
+ # Return the full FileRef with the site URL attatched
178
+ def full_file_ref
179
+ uri = @ws.spcon.site_base
180
+ url = "#{uri.scheme}://#{uri.host}"
181
+ url << ":#{uri.port}" unless (uri.port == 80 || uri.port == 443)
182
+ url << "/#{@file_ref}"
183
+ end
184
+
185
+ # update the local variables after a #save!.
186
+ # Changed variables are tracked in @update_keys
187
+ # @param [Hash] resp The response Hash from a #save!
188
+ def update_local_vars(resp)
189
+ @update_keys.each_pair do |k,v|
190
+ set_field k, v, resp
191
+ end
192
+ @update_keys.clear
193
+ end
194
+
195
+ # Parse the fields out of the passed XML document.
196
+ # @param[Nokogiri::XML::Element] xml
197
+ def parse_xml_fields(xml)
198
+ @xmldoc = xml
199
+ set_field :@id, 'ows_ID'
200
+ set_field :@file_name, 'ows_LinkFilename'
201
+ set_field :@meta_info, 'ows_MetaInfo'
202
+ set_field :@link_title, 'ows_LinkTitle'
203
+ set_field :@body, 'ows_Body'
204
+ set_field :@title, 'ows_Title'
205
+ set_field :@status, 'ows_Status'
206
+ set_field :@priority, 'ows_Priority'
207
+ set_field :@percent_complete, 'ows_PercentComplete'
208
+ set_field :@due_date, 'ows_DueDate'
209
+ set_field :@assigned_to, 'ows_AssignedTo'
210
+ set_field :@file_ref, 'ows_FileRef'
211
+ set_field :@editor, 'ows_Editor'
212
+ set_field :@guid, 'ows_UniqueId'
213
+ set_field :@object_type, 'ows_FSObjType'
214
+ set_field :@created_date, 'ows_Created'
215
+ set_field :@modified_date, 'ows_Modified'
216
+ set_field :@created_date, 'ows_Created_x0020_Date' unless @created_date
217
+ set_field :@modified_date, 'ows_Last_x0020_Modified' unless @modified_date
218
+ @xmldoc = nil
219
+ end
220
+
221
+ # Parse a Sharepoint field or managed field
222
+ # @param [Symbol] vname The instance variable we will set the value to if it exists
223
+ # @param [String] fname The field name to check for
224
+ # @param [#[]] mapsrc A dictionary or Hash like item that contains variable data.
225
+ def set_field(vname, fname, mapsrc = @xmldoc)
226
+ newvar = nil
227
+ field = mapsrc[fname]
228
+ if field
229
+ if(field =~ /;#/)
230
+ newvar = mapsrc[fname].split(';#').last
231
+ else
232
+ newvar = field
233
+ end
234
+ newvar = transform(newvar)
235
+ end
236
+ instance_variable_set vname, newvar
237
+ end
238
+
239
+ # Run misc transforms on data
240
+ def transform(newvar)
241
+ case newvar
242
+ when /[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}/ # Transform DateTime
243
+ return DateTime.parse(newvar)
244
+ else
245
+ return newvar
246
+ end
247
+ end
248
+ end