sfmc-fuelsdk-ruby 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +28 -28
  3. data/Gemfile +3 -3
  4. data/Gemfile.lock +92 -90
  5. data/Guardfile +8 -8
  6. data/LICENSE.md +13 -13
  7. data/README.md +166 -143
  8. data/Rakefile +1 -1
  9. data/lib/marketingcloudsdk.rb +74 -74
  10. data/lib/marketingcloudsdk/client.rb +348 -296
  11. data/lib/marketingcloudsdk/http_request.rb +118 -118
  12. data/lib/marketingcloudsdk/objects.rb +757 -757
  13. data/lib/marketingcloudsdk/rest.rb +118 -118
  14. data/lib/marketingcloudsdk/soap.rb +296 -282
  15. data/lib/marketingcloudsdk/targeting.rb +99 -99
  16. data/lib/marketingcloudsdk/utils.rb +47 -47
  17. data/lib/marketingcloudsdk/version.rb +39 -39
  18. data/lib/new.rb +1240 -1240
  19. data/marketingcloudsdk.gemspec +30 -30
  20. data/samples/sample-AddSubscriberToList.rb +56 -56
  21. data/samples/sample-CreateAndStartDataExtensionImport.rb +29 -29
  22. data/samples/sample-CreateAndStartListImport.rb +27 -27
  23. data/samples/sample-CreateContentAreas.rb +48 -48
  24. data/samples/sample-CreateDataExtensions.rb +54 -54
  25. data/samples/sample-CreateProfileAttributes.rb +48 -48
  26. data/samples/sample-SendEmailToDataExtension.rb +23 -23
  27. data/samples/sample-SendEmailToList.rb +23 -23
  28. data/samples/sample-SendTriggeredSends.rb +30 -30
  29. data/samples/sample-bounceevent.rb +70 -70
  30. data/samples/sample-campaign.rb +211 -211
  31. data/samples/sample-clickevent.rb +71 -71
  32. data/samples/sample-contentarea.rb +122 -122
  33. data/samples/sample-dataextension.rb +209 -209
  34. data/samples/sample-directverb.rb +54 -54
  35. data/samples/sample-email.rb +122 -122
  36. data/samples/sample-email.senddefinition.rb +134 -134
  37. data/samples/sample-folder.rb +143 -143
  38. data/samples/sample-import.rb +103 -103
  39. data/samples/sample-list.rb +105 -105
  40. data/samples/sample-list.subscriber.rb +97 -97
  41. data/samples/sample-openevent.rb +70 -70
  42. data/samples/sample-profileattribute.rb +56 -56
  43. data/samples/sample-sentevent.rb +70 -70
  44. data/samples/sample-subscriber.rb +135 -135
  45. data/samples/sample-triggeredsend.rb +129 -129
  46. data/samples/sample-unsubevent.rb +72 -72
  47. data/samples/sample_helper.rb.template +10 -10
  48. data/spec/client_spec.rb +218 -218
  49. data/spec/default_values_fallback_spec.rb +30 -30
  50. data/spec/helper_funcs_spec.rb +11 -11
  51. data/spec/http_request_spec.rb +61 -61
  52. data/spec/objects_helper_spec.rb +32 -32
  53. data/spec/objects_spec.rb +484 -484
  54. data/spec/rest_spec.rb +48 -48
  55. data/spec/soap_spec.rb +140 -140
  56. data/spec/spec_helper.rb +14 -14
  57. data/spec/targeting_spec.rb +44 -44
  58. metadata +9 -9
@@ -1,118 +1,118 @@
1
- =begin
2
- Copyright (c) 2013 ExactTarget, Inc.
3
-
4
- All rights reserved.
5
-
6
- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
7
-
8
- following conditions are met:
9
-
10
- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
11
-
12
- following disclaimer.
13
-
14
- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
15
-
16
- following disclaimer in the documentation and/or other materials provided with the distribution.
17
-
18
- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
19
-
20
- products derived from this software without specific prior written permission.
21
-
22
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
23
-
24
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
-
26
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
-
28
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29
-
30
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31
-
32
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
33
-
34
- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
- =end
36
-
37
- require 'open-uri'
38
- require 'net/https'
39
- require 'json'
40
- require 'marketingcloudsdk/version'
41
-
42
- module MarketingCloudSDK
43
-
44
- class HTTPResponse < MarketingCloudSDK::Response
45
- def initialize raw, client, request
46
- super raw, client
47
- @request = request
48
- end
49
-
50
- def continue
51
- rsp = nil
52
- if more?
53
- @request['options']['page'] = @results['page'].to_i + 1
54
- rsp = unpack @client.rest_get(@request['url'], @request['options'])
55
- else
56
- puts 'No more data'
57
- end
58
-
59
- rsp
60
- end
61
-
62
- def [] key
63
- @results[key]
64
- end
65
-
66
- private
67
- def unpack raw
68
- @code = raw.code.to_i
69
- @message = raw.message
70
- @body = JSON.parse(raw.body) rescue {}
71
- @results = @body
72
- @more = ((@results['count'] || @results['totalCount']) > @results['page'] * @results['pageSize']) rescue false
73
- @success = @message == 'OK'
74
- end
75
-
76
- # by default try everything against results
77
- def method_missing method, *args, &block
78
- @results.send(method, *args, &block)
79
- end
80
- end
81
-
82
- module HTTPRequest
83
- request_methods = ['get', 'post', 'patch', 'delete']
84
- request_methods.each do |method|
85
- class_eval <<-EOT, __FILE__, __LINE__ + 1
86
- def #{method}(url, options={}) # def post(url, options)
87
- request Net::HTTP::#{method.capitalize}, url, options # request Net::HTTP::Post, url, options
88
- end # end
89
- EOT
90
- end
91
-
92
- def generate_uri(url, params=nil)
93
- uri = URI.parse(url)
94
- uri.query = URI.encode_www_form(params) if params
95
- uri
96
- end
97
-
98
- def request(method, url, options={})
99
- uri = generate_uri url, options['params']
100
- http = Net::HTTP.new(uri.host, uri.port)
101
- http.use_ssl = true
102
-
103
- data = options['data']
104
- _request = method.new uri.request_uri
105
- _request.body = data.to_json if data
106
- _request.content_type = options['content_type'] if options['content_type']
107
- _request.add_field('User-Agent', 'FuelSDK-Ruby-v' + MarketingCloudSDK::VERSION)
108
-
109
- # Add Authorization header if we have an access token
110
- if options['access_token']
111
- _request.add_field('Authorization', 'Bearer ' + options['access_token'])
112
- end
113
-
114
- response = http.request(_request)
115
- HTTPResponse.new(response, self, :url => url, :options => options)
116
- end
117
- end
118
- end
1
+ =begin
2
+ Copyright (c) 2013 ExactTarget, Inc.
3
+
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
7
+
8
+ following conditions are met:
9
+
10
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
11
+
12
+ following disclaimer.
13
+
14
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
15
+
16
+ following disclaimer in the documentation and/or other materials provided with the distribution.
17
+
18
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
19
+
20
+ products derived from this software without specific prior written permission.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
23
+
24
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
+
26
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
+
28
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29
+
30
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31
+
32
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
33
+
34
+ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
+ =end
36
+
37
+ require 'open-uri'
38
+ require 'net/https'
39
+ require 'json'
40
+ require 'marketingcloudsdk/version'
41
+
42
+ module MarketingCloudSDK
43
+
44
+ class HTTPResponse < MarketingCloudSDK::Response
45
+ def initialize raw, client, request
46
+ super raw, client
47
+ @request = request
48
+ end
49
+
50
+ def continue
51
+ rsp = nil
52
+ if more?
53
+ @request['options']['page'] = @results['page'].to_i + 1
54
+ rsp = unpack @client.rest_get(@request['url'], @request['options'])
55
+ else
56
+ puts 'No more data'
57
+ end
58
+
59
+ rsp
60
+ end
61
+
62
+ def [] key
63
+ @results[key]
64
+ end
65
+
66
+ private
67
+ def unpack raw
68
+ @code = raw.code.to_i
69
+ @message = raw.message
70
+ @body = JSON.parse(raw.body) rescue {}
71
+ @results = @body
72
+ @more = ((@results['count'] || @results['totalCount']) > @results['page'] * @results['pageSize']) rescue false
73
+ @success = @message == 'OK'
74
+ end
75
+
76
+ # by default try everything against results
77
+ def method_missing method, *args, &block
78
+ @results.send(method, *args, &block)
79
+ end
80
+ end
81
+
82
+ module HTTPRequest
83
+ request_methods = ['get', 'post', 'patch', 'delete']
84
+ request_methods.each do |method|
85
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
86
+ def #{method}(url, options={}) # def post(url, options)
87
+ request Net::HTTP::#{method.capitalize}, url, options # request Net::HTTP::Post, url, options
88
+ end # end
89
+ EOT
90
+ end
91
+
92
+ def generate_uri(url, params=nil)
93
+ uri = URI.parse(url)
94
+ uri.query = URI.encode_www_form(params) if params
95
+ uri
96
+ end
97
+
98
+ def request(method, url, options={})
99
+ uri = generate_uri url, options['params']
100
+ http = Net::HTTP.new(uri.host, uri.port)
101
+ http.use_ssl = true
102
+
103
+ data = options['data']
104
+ _request = method.new uri.request_uri
105
+ _request.body = data.to_json if data
106
+ _request.content_type = options['content_type'] if options['content_type']
107
+ _request.add_field('User-Agent', 'FuelSDK-Ruby-v' + MarketingCloudSDK::VERSION)
108
+
109
+ # Add Authorization header if we have an access token
110
+ if options['access_token']
111
+ _request.add_field('Authorization', 'Bearer ' + options['access_token'])
112
+ end
113
+
114
+ response = http.request(_request)
115
+ HTTPResponse.new(response, self, :url => url, :options => options)
116
+ end
117
+ end
118
+ end
@@ -1,757 +1,757 @@
1
- =begin
2
- Copyright (c) 2013 ExactTarget, Inc.
3
-
4
- All rights reserved.
5
-
6
- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
7
-
8
- following conditions are met:
9
-
10
- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
11
-
12
- following disclaimer.
13
-
14
- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
15
-
16
- following disclaimer in the documentation and/or other materials provided with the distribution.
17
-
18
- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
19
-
20
- products derived from this software without specific prior written permission.
21
-
22
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
23
-
24
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
-
26
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
-
28
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29
-
30
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31
-
32
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
33
-
34
- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
- =end
36
-
37
- module MarketingCloudSDK
38
- module Objects
39
- module Soap
40
- module Read
41
- attr_accessor :filter
42
- def get _id=nil
43
- client.soap_get _id||id, properties, filter
44
- end
45
-
46
- def info
47
- client.soap_describe id
48
- end
49
- end
50
-
51
- module CUD #create, update, delete
52
- def post
53
- if self.respond_to?('folder_property') && !self.folder_id.nil?
54
- properties[self.folder_property] = self.folder_id
55
- elsif self.respond_to?('folder_property') && !self.folder_property.nil? && !client.package_name.nil? then
56
- if client.package_folders.nil? then
57
- getPackageFolder = ET_Folder.new
58
- getPackageFolder.authStub = client
59
- getPackageFolder.properties = ["ID", "ContentType"]
60
- getPackageFolder.filter = {"Property" => "Name", "SimpleOperator" => "equals", "Value" => client.package_name}
61
- resultPackageFolder = getPackageFolder.get
62
- if resultPackageFolder.status then
63
- client.package_folders = {}
64
- resultPackageFolder.results.each do |value|
65
- client.package_folders[value[:content_type]] = value[:id]
66
- end
67
- else
68
- raise "Unable to retrieve folders from account due to: #{resultPackageFolder.message}"
69
- end
70
- end
71
-
72
- if !client.package_folders.has_key?(self.folder_media_type) then
73
- if client.parentFolders.nil? then
74
- parentFolders = ET_Folder.new
75
- parentFolders.authStub = client
76
- parentFolders.properties = ["ID", "ContentType"]
77
- parentFolders.filter = {"Property" => "ParentFolder.ID", "SimpleOperator" => "equals", "Value" => "0"}
78
- resultParentFolders = parentFolders.get
79
- if resultParentFolders.status then
80
- client.parent_folders = {}
81
- resultParentFolders.results.each do |value|
82
- client.parent_folders[value[:content_type]] = value[:id]
83
- end
84
- else
85
- raise "Unable to retrieve folders from account due to: #{resultParentFolders.message}"
86
- end
87
- end
88
-
89
- newFolder = ET_Folder.new
90
- newFolder.authStub = client
91
- newFolder.properties = {"Name" => client.package_name, "Description" => client.package_name, "ContentType"=> self.folder_media_type, "IsEditable"=>"true", "ParentFolder" => {"ID" => client.parentFolders[self.folder_media_type]}}
92
- folderResult = newFolder.post
93
- if folderResult.status then
94
- client.package_folders[self.folder_media_type] = folderResult.results[0][:new_id]
95
- else
96
- raise "Unable to create folder for Post due to: #{folderResult.message}"
97
- end
98
-
99
- end
100
- properties[self.folder_property] = client.package_folders[self.folder_media_type]
101
- end
102
- client.soap_post id, properties
103
- end
104
-
105
- def patch
106
- client.soap_patch id, properties
107
- end
108
-
109
- def delete
110
- client.soap_delete id, properties
111
- end
112
- end
113
-
114
- module Upsert
115
- def put
116
- client.soap_put id, properties
117
- end
118
- end
119
-
120
- end
121
-
122
- module Rest
123
- module Read
124
- def get
125
- client.rest_get id, properties
126
- end
127
- end
128
-
129
- module CUD
130
- def post
131
- client.rest_post id, properties
132
- end
133
-
134
- def patch
135
- client.rest_patch id, properties
136
- end
137
-
138
- def delete
139
- client.rest_delete id, properties
140
- end
141
- end
142
-
143
- end
144
-
145
- class Base
146
- attr_accessor :properties, :client
147
- attr_reader :id
148
-
149
- alias props= properties= # backward compatibility
150
- alias authStub= client= # backward compatibility
151
-
152
- def properties
153
- #@properties = [@properties].compact unless @properties.kind_of? Array
154
- @properties
155
- end
156
-
157
- #Backwards compatibility
158
- def props
159
- @properties
160
- end
161
-
162
- def id
163
- self.class.id
164
- end
165
-
166
- class << self
167
- def id
168
- self.name.split('::').pop
169
- end
170
- end
171
- end
172
- end
173
-
174
- class BounceEvent < Objects::Base
175
- attr_accessor :get_since_last_batch
176
- include Objects::Soap::Read
177
- end
178
-
179
- class ClickEvent < Objects::Base
180
- attr_accessor :get_since_last_batch
181
- include Objects::Soap::Read
182
- end
183
-
184
- class ContentArea < Objects::Base
185
- include Objects::Soap::Read
186
- include Objects::Soap::CUD
187
- attr_accessor :folder_id
188
-
189
- def folder_property
190
- 'CategoryID'
191
- end
192
-
193
- def folder_media_type
194
- 'content'
195
- end
196
- end
197
-
198
- class DataFolder < Objects::Base
199
- include Objects::Soap::Read
200
- include Objects::Soap::CUD
201
- end
202
-
203
- class Folder < DataFolder
204
- class << self
205
- def id
206
- DataFolder.id
207
- end
208
- end
209
- end
210
-
211
- class Email < Objects::Base
212
- include Objects::Soap::Read
213
- include Objects::Soap::CUD
214
- attr_accessor :folder_id
215
-
216
- def folder_property
217
- 'CategoryID'
218
- end
219
-
220
- def folder_media_type
221
- 'email'
222
- end
223
-
224
- class SendDefinition < Objects::Base
225
- include Objects::Soap::Read
226
- include Objects::Soap::CUD
227
- attr_accessor :folder_id
228
-
229
- def id
230
- 'EmailSendDefinition'
231
- end
232
-
233
- def folder_property
234
- 'CategoryID'
235
- end
236
-
237
- def folder_media_type
238
- 'userinitiatedsends'
239
- end
240
-
241
-
242
- def send
243
- perform_response = client.soap_perform id, 'start' , properties
244
- if perform_response.status then
245
- @last_task_id = perform_response.results[0][:result][:task][:id]
246
- end
247
- perform_response
248
- end
249
-
250
- def status
251
- client.soap_get "Send", ['ID','CreatedDate', 'ModifiedDate', 'Client.ID', 'Email.ID', 'SendDate','FromAddress','FromName','Duplicates','InvalidAddresses','ExistingUndeliverables','ExistingUnsubscribes','HardBounces','SoftBounces','OtherBounces','ForwardedEmails','UniqueClicks','UniqueOpens','NumberSent','NumberDelivered','NumberTargeted','NumberErrored','NumberExcluded','Unsubscribes','MissingAddresses','Subject','PreviewURL','SentDate','EmailName','Status','IsMultipart','SendLimit','SendWindowOpen','SendWindowClose','BCCEmail','EmailSendDefinition.ObjectID','EmailSendDefinition.CustomerKey'], {'Property' => 'ID','SimpleOperator' => 'equals','Value' => @last_task_id}
252
- end
253
-
254
- private
255
- attr_accessor :last_task_id
256
-
257
- end
258
- end
259
-
260
-
261
-
262
- class Import < Objects::Base
263
- include Objects::Soap::Read
264
- include Objects::Soap::CUD
265
-
266
-
267
- def id
268
- 'ImportDefinition'
269
- end
270
-
271
- def post
272
- originalProp = properties
273
- cleanProps
274
- obj = super
275
- properties = originalProp
276
- return obj
277
- end
278
-
279
- def patch
280
- originalProp = properties
281
- cleanProps
282
- obj = super
283
- properties = originalProp
284
- return obj
285
- end
286
-
287
- def start
288
- perform_response = client.soap_perform id, 'start' , properties
289
- if perform_response.status then
290
- @last_task_id = perform_response.results[0][:result][:task][:id]
291
- end
292
- perform_response
293
- end
294
-
295
- def status
296
- client.soap_get "ImportResultsSummary", ['ImportDefinitionCustomerKey','TaskResultID','ImportStatus','StartDate','EndDate','DestinationID','NumberSuccessful','NumberDuplicated','NumberErrors','TotalRows','ImportType'], {'Property' => 'TaskResultID','SimpleOperator' => 'equals','Value' => @last_task_id}
297
- end
298
-
299
- private
300
- attr_accessor :last_task_id
301
-
302
- def cleanProps
303
- # If the ID property is specified for the destination then it must be a list import
304
- if properties.has_key?('DestinationObject') then
305
- if properties['DestinationObject'].has_key?('ID') then
306
- properties[:attributes!] = { 'DestinationObject' => { 'xsi:type' => 'tns:List'}}
307
- end
308
- end
309
- end
310
- end
311
-
312
-
313
- class List < Objects::Base
314
- include Objects::Soap::Read
315
- include Objects::Soap::CUD
316
- attr_accessor :folder_id
317
-
318
- def folder_property
319
- 'Category'
320
- end
321
-
322
- def folder_media_type
323
- 'list'
324
- end
325
-
326
- class Subscriber < Objects::Base
327
- include Objects::Soap::Read
328
- def id
329
- 'ListSubscriber'
330
- end
331
- end
332
- end
333
-
334
- class OpenEvent < Objects::Base
335
- attr_accessor :get_since_last_batch
336
- include Objects::Soap::Read
337
- end
338
-
339
- class SentEvent < Objects::Base
340
- attr_accessor :get_since_last_batch
341
- include Objects::Soap::Read
342
- end
343
-
344
- class Subscriber < Objects::Base
345
- include Objects::Soap::Read
346
- include Objects::Soap::CUD
347
- include Objects::Soap::Upsert
348
- end
349
-
350
- class UnsubEvent < Objects::Base
351
- attr_accessor :get_since_last_batch
352
- include Objects::Soap::Read
353
- end
354
-
355
- class ProfileAttribute < Objects::Base
356
- def get
357
- client.soap_describe "Subscriber"
358
- end
359
-
360
- def post
361
- client.soap_configure "PropertyDefinition","create", properties
362
- end
363
-
364
- def delete
365
- client.soap_configure "PropertyDefinition","delete", properties
366
- end
367
-
368
- def patch
369
- client.soap_configure "PropertyDefinition","update", properties
370
- end
371
- end
372
-
373
- class TriggeredSend < Objects::Base
374
- include Objects::Soap::Read
375
- include Objects::Soap::CUD
376
- attr_accessor :folder_id, :subscribers, :attributes
377
- def id
378
- 'TriggeredSendDefinition'
379
- end
380
-
381
- def folder_property
382
- 'CategoryID'
383
- end
384
-
385
- def folder_media_type
386
- 'triggered_send'
387
- end
388
-
389
- def send
390
- if self.properties.is_a? Array then
391
- tscall = []
392
- self.properties.each{ |p|
393
- tscall.push({"TriggeredSendDefinition" => {"CustomerKey" => p["CustomerKey"]}, "Subscribers" => p["Subscribers"], "Attributes" => p["Attributes"]})
394
- }
395
- else
396
- tscall = {"TriggeredSendDefinition" => self.properties, "Subscribers" => @subscribers, "Attributes" => @attributes }
397
- end
398
- client.soap_post 'TriggeredSend', tscall
399
- end
400
- end
401
-
402
- class DataExtension < Objects::Base
403
- include Objects::Soap::Read
404
- include Objects::Soap::CUD
405
- attr_accessor :fields, :folder_id
406
-
407
- def folder_property
408
- 'CategoryID'
409
- end
410
-
411
- def folder_media_type
412
- 'dataextension'
413
- end
414
-
415
- alias columns= fields= # backward compatibility
416
-
417
- def post
418
- munge_fields self.properties
419
- super
420
- end
421
-
422
- def patch
423
- munge_fields self.properties
424
- super
425
- end
426
-
427
- class Column < Objects::Base
428
- include Objects::Soap::Read
429
- def id
430
- 'DataExtensionField'
431
- end
432
- def get
433
- if filter and filter.kind_of? Hash and \
434
- filter.include? 'Property' and filter['Property'] == 'CustomerKey'
435
- filter['Property'] = 'DataExtension.CustomerKey'
436
- end
437
- super
438
- end
439
- end
440
-
441
- class Row < Objects::Base
442
- include Objects::Soap::Read
443
- include Objects::Soap::CUD
444
- include Objects::Soap::Upsert
445
-
446
- attr_accessor :name, :customer_key
447
-
448
- # backward compatibility
449
- alias Name= name=
450
- alias CustomerKey= customer_key=
451
-
452
- def id
453
- 'DataExtensionObject'
454
- end
455
-
456
- def get
457
- super "#{id}[#{name}]"
458
- end
459
-
460
- def name
461
- unless @name
462
- retrieve_required
463
- end
464
- @name
465
- end
466
-
467
- def customer_key
468
- unless @customer_key
469
- retrieve_required
470
- end
471
- @customer_key
472
- end
473
-
474
- def post
475
- munge_properties self.properties
476
- super
477
- end
478
-
479
- def patch
480
- munge_properties self.properties
481
- super
482
- end
483
-
484
- def put
485
- munge_properties self.properties
486
- super
487
- end
488
-
489
- def delete
490
- munge_keys self.properties
491
- super
492
- end
493
-
494
- private
495
- #::TODO::
496
- # opportunity for meta programming here... but need to get this out the door
497
- def munge_keys d
498
- if d.kind_of? Array
499
- d.each do |o|
500
-
501
- next if explicit_keys(o) && explicit_customer_key(o)
502
-
503
- formatted = []
504
- o['CustomerKey'] = customer_key unless explicit_customer_key o
505
- unless explicit_properties(o)
506
- o.each do |k, v|
507
- next if k == 'CustomerKey'
508
- formatted.concat MarketingCloudSDK.format_name_value_pairs k => v
509
- o.delete k
510
- end
511
- o['Keys'] = {'Key' => formatted }
512
- end
513
- end
514
- else
515
- formatted = []
516
- d.each do |k, v|
517
- next if k == 'CustomerKey'
518
- formatted.concat MarketingCloudSDK.format_name_value_pairs k => v
519
- d.delete k
520
- end
521
- d['CustomerKey'] = customer_key
522
- d['Keys'] = {'Key' => formatted }
523
- end
524
- end
525
-
526
- def explicit_keys h
527
- h['Keys'] and h['Keys']['Key']
528
- end
529
-
530
- def munge_properties d
531
- if d.kind_of? Array
532
- d.each do |o|
533
- next if explicit_properties(o) && explicit_customer_key(o)
534
-
535
- formatted = []
536
- o['CustomerKey'] = customer_key unless explicit_customer_key o
537
- unless explicit_properties(o)
538
- o.each do |k, v|
539
- next if k == 'CustomerKey'
540
- formatted.concat MarketingCloudSDK.format_name_value_pairs k => v
541
- o.delete k
542
- end
543
- o['Properties'] = {'Property' => formatted }
544
- end
545
- end
546
- else
547
- formatted = []
548
- d.each do |k, v|
549
- formatted.concat MarketingCloudSDK.format_name_value_pairs k => v
550
- d.delete k
551
- end
552
- d['CustomerKey'] = customer_key
553
- d['Properties'] = {'Property' => formatted }
554
- end
555
- end
556
-
557
- def explicit_properties h
558
- h['Properties'] and h['Properties']['Property']
559
- end
560
-
561
- def explicit_customer_key h
562
- h['CustomerKey']
563
- end
564
-
565
- def retrieve_required
566
- # have to use instance variables so we don't recursivelly retrieve_required
567
- if !@name && !@customer_key
568
- raise 'Unable to process DataExtension::Row ' \
569
- 'request due to missing CustomerKey and Name'
570
- end
571
- if !@name || !@customer_key
572
- filter = {
573
- 'Property' => @name.nil? ? 'CustomerKey' : 'Name',
574
- 'SimpleOperator' => 'equals',
575
- 'Value' => @customer_key || @name
576
- }
577
- rsp = client.soap_get 'DataExtension', ['Name', 'CustomerKey'], filter
578
- if rsp.success? && rsp.results.count == 1
579
- self.name = rsp.results.first[:name]
580
- self.customer_key = rsp.results.first[:customer_key]
581
- else
582
- raise 'Unable to process DataExtension::Row'
583
- end
584
- end
585
- end
586
- end
587
-
588
- private
589
-
590
- def munge_fields d
591
- # maybe one day will make it smart enough to zip properties and fields if count is same?
592
- if d.kind_of? Array and d.count > 1 and (fields and !fields.empty?)
593
- # we could map the field to all DataExtensions, but lets make user be explicit.
594
- # if they are going to use fields attribute properties should
595
- # be a single DataExtension Defined in a Hash
596
- raise 'Unable to handle muliple DataExtension definitions and a field definition'
597
- end
598
-
599
- if d.kind_of? Array
600
- d.each do |de|
601
- if (explicit_fields(de) and (de['columns'] || de['fields'] || has_fields)) or
602
- (de['columns'] and (de['fields'] || has_fields)) or
603
- (de['fields'] and has_fields)
604
- raise 'Fields are defined in too many ways. Please only define once.' # ahhh what, to do...
605
- end
606
-
607
- # let users who chose, to define fields explicitly within the hash definition
608
- next if explicit_fields de
609
-
610
- de['Fields'] = {'Field' => de['columns'] || de['fields'] || fields}
611
- # sanitize
612
-
613
- raise 'DataExtension needs atleast one field.' unless de['Fields']['Field']
614
- end
615
- else
616
- self.properties['Fields'] = {'Field' => self.properties['columns'] || self.properties['fields'] || fields}
617
- raise 'DataExtension needs atleast one field.' unless self.properties['Fields']['Field']
618
- self.properties.delete 'columns'
619
- self.properties.delete 'fields'
620
- end
621
- end
622
-
623
- def explicit_fields h
624
- h['Fields'] and h['Fields']['Field']
625
- end
626
-
627
- def has_fields
628
- fields and !fields.empty?
629
- end
630
- end
631
-
632
- class Campaign < Objects::Base
633
- include Objects::Rest::Read
634
- include Objects::Rest::CUD
635
-
636
- def properties
637
- @properties ||= {}
638
- @properties.merge! 'id' => '' unless @properties.include? 'id'
639
- @properties
640
- end
641
-
642
- def id
643
- self.client.base_api_url + '/hub/v1/campaigns/%{id}'
644
- end
645
-
646
- class Asset < Objects::Base
647
- include Objects::Rest::Read
648
- include Objects::Rest::CUD
649
-
650
- def properties
651
- @properties ||= {}
652
- @properties.merge! 'assetId' => '' unless @properties.include? 'assetId'
653
- @properties
654
- end
655
-
656
- def id
657
- self.client.base_api_url + '/hub/v1/campaigns/%{id}/assets/%{assetId}'
658
- end
659
- end
660
- end
661
-
662
- # Direct Verb Access Section
663
-
664
- class Get < Objects::Base
665
- include Objects::Soap::Read
666
- attr_accessor :id
667
-
668
- def initialize client, id, properties, filter
669
- self.properties = properties
670
- self.filter = filter
671
- self.client = client
672
- self.id = id
673
- end
674
-
675
- def get
676
- super id
677
- end
678
-
679
- class << self
680
- def new client, id, properties=nil, filter=nil
681
- o = self.allocate
682
- o.send :initialize, client, id, properties, filter
683
- return o.get
684
- end
685
- end
686
- end
687
-
688
- class Post < Objects::Base
689
- include Objects::Soap::CUD
690
- attr_accessor :id
691
-
692
- def initialize client, id, properties
693
- self.properties = properties
694
- self.client = client
695
- self.id = id
696
- end
697
-
698
- def post
699
- super
700
- end
701
-
702
- class << self
703
- def new client, id, properties=nil
704
- o = self.allocate
705
- o.send :initialize, client, id, properties
706
- return o.post
707
- end
708
- end
709
- end
710
-
711
- class Delete < Objects::Base
712
- include Objects::Soap::CUD
713
- attr_accessor :id
714
-
715
- def initialize client, id, properties
716
- self.properties = properties
717
- self.client = client
718
- self.id = id
719
- end
720
-
721
- def delete
722
- super
723
- end
724
-
725
- class << self
726
- def new client, id, properties=nil
727
- o = self.allocate
728
- o.send :initialize, client, id, properties
729
- return o.delete
730
- end
731
- end
732
- end
733
-
734
- class Patch < Objects::Base
735
- include Objects::Soap::CUD
736
- attr_accessor :id
737
-
738
- def initialize client, id, properties
739
- self.properties = properties
740
- self.client = client
741
- self.id = id
742
- end
743
-
744
- def patch
745
- super
746
- end
747
-
748
- class << self
749
- def new client, id, properties=nil
750
- o = self.allocate
751
- o.send :initialize, client, id, properties
752
- return o.patch
753
- end
754
- end
755
- end
756
-
757
- end
1
+ =begin
2
+ Copyright (c) 2013 ExactTarget, Inc.
3
+
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
7
+
8
+ following conditions are met:
9
+
10
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
11
+
12
+ following disclaimer.
13
+
14
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
15
+
16
+ following disclaimer in the documentation and/or other materials provided with the distribution.
17
+
18
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
19
+
20
+ products derived from this software without specific prior written permission.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
23
+
24
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
+
26
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
+
28
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29
+
30
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31
+
32
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
33
+
34
+ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
+ =end
36
+
37
+ module MarketingCloudSDK
38
+ module Objects
39
+ module Soap
40
+ module Read
41
+ attr_accessor :filter
42
+ def get _id=nil
43
+ client.soap_get _id||id, properties, filter
44
+ end
45
+
46
+ def info
47
+ client.soap_describe id
48
+ end
49
+ end
50
+
51
+ module CUD #create, update, delete
52
+ def post
53
+ if self.respond_to?('folder_property') && !self.folder_id.nil?
54
+ properties[self.folder_property] = self.folder_id
55
+ elsif self.respond_to?('folder_property') && !self.folder_property.nil? && !client.package_name.nil? then
56
+ if client.package_folders.nil? then
57
+ getPackageFolder = ET_Folder.new
58
+ getPackageFolder.authStub = client
59
+ getPackageFolder.properties = ["ID", "ContentType"]
60
+ getPackageFolder.filter = {"Property" => "Name", "SimpleOperator" => "equals", "Value" => client.package_name}
61
+ resultPackageFolder = getPackageFolder.get
62
+ if resultPackageFolder.status then
63
+ client.package_folders = {}
64
+ resultPackageFolder.results.each do |value|
65
+ client.package_folders[value[:content_type]] = value[:id]
66
+ end
67
+ else
68
+ raise "Unable to retrieve folders from account due to: #{resultPackageFolder.message}"
69
+ end
70
+ end
71
+
72
+ if !client.package_folders.has_key?(self.folder_media_type) then
73
+ if client.parentFolders.nil? then
74
+ parentFolders = ET_Folder.new
75
+ parentFolders.authStub = client
76
+ parentFolders.properties = ["ID", "ContentType"]
77
+ parentFolders.filter = {"Property" => "ParentFolder.ID", "SimpleOperator" => "equals", "Value" => "0"}
78
+ resultParentFolders = parentFolders.get
79
+ if resultParentFolders.status then
80
+ client.parent_folders = {}
81
+ resultParentFolders.results.each do |value|
82
+ client.parent_folders[value[:content_type]] = value[:id]
83
+ end
84
+ else
85
+ raise "Unable to retrieve folders from account due to: #{resultParentFolders.message}"
86
+ end
87
+ end
88
+
89
+ newFolder = ET_Folder.new
90
+ newFolder.authStub = client
91
+ newFolder.properties = {"Name" => client.package_name, "Description" => client.package_name, "ContentType"=> self.folder_media_type, "IsEditable"=>"true", "ParentFolder" => {"ID" => client.parentFolders[self.folder_media_type]}}
92
+ folderResult = newFolder.post
93
+ if folderResult.status then
94
+ client.package_folders[self.folder_media_type] = folderResult.results[0][:new_id]
95
+ else
96
+ raise "Unable to create folder for Post due to: #{folderResult.message}"
97
+ end
98
+
99
+ end
100
+ properties[self.folder_property] = client.package_folders[self.folder_media_type]
101
+ end
102
+ client.soap_post id, properties
103
+ end
104
+
105
+ def patch
106
+ client.soap_patch id, properties
107
+ end
108
+
109
+ def delete
110
+ client.soap_delete id, properties
111
+ end
112
+ end
113
+
114
+ module Upsert
115
+ def put
116
+ client.soap_put id, properties
117
+ end
118
+ end
119
+
120
+ end
121
+
122
+ module Rest
123
+ module Read
124
+ def get
125
+ client.rest_get id, properties
126
+ end
127
+ end
128
+
129
+ module CUD
130
+ def post
131
+ client.rest_post id, properties
132
+ end
133
+
134
+ def patch
135
+ client.rest_patch id, properties
136
+ end
137
+
138
+ def delete
139
+ client.rest_delete id, properties
140
+ end
141
+ end
142
+
143
+ end
144
+
145
+ class Base
146
+ attr_accessor :properties, :client
147
+ attr_reader :id
148
+
149
+ alias props= properties= # backward compatibility
150
+ alias authStub= client= # backward compatibility
151
+
152
+ def properties
153
+ #@properties = [@properties].compact unless @properties.kind_of? Array
154
+ @properties
155
+ end
156
+
157
+ #Backwards compatibility
158
+ def props
159
+ @properties
160
+ end
161
+
162
+ def id
163
+ self.class.id
164
+ end
165
+
166
+ class << self
167
+ def id
168
+ self.name.split('::').pop
169
+ end
170
+ end
171
+ end
172
+ end
173
+
174
+ class BounceEvent < Objects::Base
175
+ attr_accessor :get_since_last_batch
176
+ include Objects::Soap::Read
177
+ end
178
+
179
+ class ClickEvent < Objects::Base
180
+ attr_accessor :get_since_last_batch
181
+ include Objects::Soap::Read
182
+ end
183
+
184
+ class ContentArea < Objects::Base
185
+ include Objects::Soap::Read
186
+ include Objects::Soap::CUD
187
+ attr_accessor :folder_id
188
+
189
+ def folder_property
190
+ 'CategoryID'
191
+ end
192
+
193
+ def folder_media_type
194
+ 'content'
195
+ end
196
+ end
197
+
198
+ class DataFolder < Objects::Base
199
+ include Objects::Soap::Read
200
+ include Objects::Soap::CUD
201
+ end
202
+
203
+ class Folder < DataFolder
204
+ class << self
205
+ def id
206
+ DataFolder.id
207
+ end
208
+ end
209
+ end
210
+
211
+ class Email < Objects::Base
212
+ include Objects::Soap::Read
213
+ include Objects::Soap::CUD
214
+ attr_accessor :folder_id
215
+
216
+ def folder_property
217
+ 'CategoryID'
218
+ end
219
+
220
+ def folder_media_type
221
+ 'email'
222
+ end
223
+
224
+ class SendDefinition < Objects::Base
225
+ include Objects::Soap::Read
226
+ include Objects::Soap::CUD
227
+ attr_accessor :folder_id
228
+
229
+ def id
230
+ 'EmailSendDefinition'
231
+ end
232
+
233
+ def folder_property
234
+ 'CategoryID'
235
+ end
236
+
237
+ def folder_media_type
238
+ 'userinitiatedsends'
239
+ end
240
+
241
+
242
+ def send
243
+ perform_response = client.soap_perform id, 'start' , properties
244
+ if perform_response.status then
245
+ @last_task_id = perform_response.results[0][:result][:task][:id]
246
+ end
247
+ perform_response
248
+ end
249
+
250
+ def status
251
+ client.soap_get "Send", ['ID','CreatedDate', 'ModifiedDate', 'Client.ID', 'Email.ID', 'SendDate','FromAddress','FromName','Duplicates','InvalidAddresses','ExistingUndeliverables','ExistingUnsubscribes','HardBounces','SoftBounces','OtherBounces','ForwardedEmails','UniqueClicks','UniqueOpens','NumberSent','NumberDelivered','NumberTargeted','NumberErrored','NumberExcluded','Unsubscribes','MissingAddresses','Subject','PreviewURL','SentDate','EmailName','Status','IsMultipart','SendLimit','SendWindowOpen','SendWindowClose','BCCEmail','EmailSendDefinition.ObjectID','EmailSendDefinition.CustomerKey'], {'Property' => 'ID','SimpleOperator' => 'equals','Value' => @last_task_id}
252
+ end
253
+
254
+ private
255
+ attr_accessor :last_task_id
256
+
257
+ end
258
+ end
259
+
260
+
261
+
262
+ class Import < Objects::Base
263
+ include Objects::Soap::Read
264
+ include Objects::Soap::CUD
265
+
266
+
267
+ def id
268
+ 'ImportDefinition'
269
+ end
270
+
271
+ def post
272
+ originalProp = properties
273
+ cleanProps
274
+ obj = super
275
+ properties = originalProp
276
+ return obj
277
+ end
278
+
279
+ def patch
280
+ originalProp = properties
281
+ cleanProps
282
+ obj = super
283
+ properties = originalProp
284
+ return obj
285
+ end
286
+
287
+ def start
288
+ perform_response = client.soap_perform id, 'start' , properties
289
+ if perform_response.status then
290
+ @last_task_id = perform_response.results[0][:result][:task][:id]
291
+ end
292
+ perform_response
293
+ end
294
+
295
+ def status
296
+ client.soap_get "ImportResultsSummary", ['ImportDefinitionCustomerKey','TaskResultID','ImportStatus','StartDate','EndDate','DestinationID','NumberSuccessful','NumberDuplicated','NumberErrors','TotalRows','ImportType'], {'Property' => 'TaskResultID','SimpleOperator' => 'equals','Value' => @last_task_id}
297
+ end
298
+
299
+ private
300
+ attr_accessor :last_task_id
301
+
302
+ def cleanProps
303
+ # If the ID property is specified for the destination then it must be a list import
304
+ if properties.has_key?('DestinationObject') then
305
+ if properties['DestinationObject'].has_key?('ID') then
306
+ properties[:attributes!] = { 'DestinationObject' => { 'xsi:type' => 'tns:List'}}
307
+ end
308
+ end
309
+ end
310
+ end
311
+
312
+
313
+ class List < Objects::Base
314
+ include Objects::Soap::Read
315
+ include Objects::Soap::CUD
316
+ attr_accessor :folder_id
317
+
318
+ def folder_property
319
+ 'Category'
320
+ end
321
+
322
+ def folder_media_type
323
+ 'list'
324
+ end
325
+
326
+ class Subscriber < Objects::Base
327
+ include Objects::Soap::Read
328
+ def id
329
+ 'ListSubscriber'
330
+ end
331
+ end
332
+ end
333
+
334
+ class OpenEvent < Objects::Base
335
+ attr_accessor :get_since_last_batch
336
+ include Objects::Soap::Read
337
+ end
338
+
339
+ class SentEvent < Objects::Base
340
+ attr_accessor :get_since_last_batch
341
+ include Objects::Soap::Read
342
+ end
343
+
344
+ class Subscriber < Objects::Base
345
+ include Objects::Soap::Read
346
+ include Objects::Soap::CUD
347
+ include Objects::Soap::Upsert
348
+ end
349
+
350
+ class UnsubEvent < Objects::Base
351
+ attr_accessor :get_since_last_batch
352
+ include Objects::Soap::Read
353
+ end
354
+
355
+ class ProfileAttribute < Objects::Base
356
+ def get
357
+ client.soap_describe "Subscriber"
358
+ end
359
+
360
+ def post
361
+ client.soap_configure "PropertyDefinition","create", properties
362
+ end
363
+
364
+ def delete
365
+ client.soap_configure "PropertyDefinition","delete", properties
366
+ end
367
+
368
+ def patch
369
+ client.soap_configure "PropertyDefinition","update", properties
370
+ end
371
+ end
372
+
373
+ class TriggeredSend < Objects::Base
374
+ include Objects::Soap::Read
375
+ include Objects::Soap::CUD
376
+ attr_accessor :folder_id, :subscribers, :attributes
377
+ def id
378
+ 'TriggeredSendDefinition'
379
+ end
380
+
381
+ def folder_property
382
+ 'CategoryID'
383
+ end
384
+
385
+ def folder_media_type
386
+ 'triggered_send'
387
+ end
388
+
389
+ def send
390
+ if self.properties.is_a? Array then
391
+ tscall = []
392
+ self.properties.each{ |p|
393
+ tscall.push({"TriggeredSendDefinition" => {"CustomerKey" => p["CustomerKey"]}, "Subscribers" => p["Subscribers"], "Attributes" => p["Attributes"]})
394
+ }
395
+ else
396
+ tscall = {"TriggeredSendDefinition" => self.properties, "Subscribers" => @subscribers, "Attributes" => @attributes }
397
+ end
398
+ client.soap_post 'TriggeredSend', tscall
399
+ end
400
+ end
401
+
402
+ class DataExtension < Objects::Base
403
+ include Objects::Soap::Read
404
+ include Objects::Soap::CUD
405
+ attr_accessor :fields, :folder_id
406
+
407
+ def folder_property
408
+ 'CategoryID'
409
+ end
410
+
411
+ def folder_media_type
412
+ 'dataextension'
413
+ end
414
+
415
+ alias columns= fields= # backward compatibility
416
+
417
+ def post
418
+ munge_fields self.properties
419
+ super
420
+ end
421
+
422
+ def patch
423
+ munge_fields self.properties
424
+ super
425
+ end
426
+
427
+ class Column < Objects::Base
428
+ include Objects::Soap::Read
429
+ def id
430
+ 'DataExtensionField'
431
+ end
432
+ def get
433
+ if filter and filter.kind_of? Hash and \
434
+ filter.include? 'Property' and filter['Property'] == 'CustomerKey'
435
+ filter['Property'] = 'DataExtension.CustomerKey'
436
+ end
437
+ super
438
+ end
439
+ end
440
+
441
+ class Row < Objects::Base
442
+ include Objects::Soap::Read
443
+ include Objects::Soap::CUD
444
+ include Objects::Soap::Upsert
445
+
446
+ attr_accessor :name, :customer_key
447
+
448
+ # backward compatibility
449
+ alias Name= name=
450
+ alias CustomerKey= customer_key=
451
+
452
+ def id
453
+ 'DataExtensionObject'
454
+ end
455
+
456
+ def get
457
+ super "#{id}[#{name}]"
458
+ end
459
+
460
+ def name
461
+ unless @name
462
+ retrieve_required
463
+ end
464
+ @name
465
+ end
466
+
467
+ def customer_key
468
+ unless @customer_key
469
+ retrieve_required
470
+ end
471
+ @customer_key
472
+ end
473
+
474
+ def post
475
+ munge_properties self.properties
476
+ super
477
+ end
478
+
479
+ def patch
480
+ munge_properties self.properties
481
+ super
482
+ end
483
+
484
+ def put
485
+ munge_properties self.properties
486
+ super
487
+ end
488
+
489
+ def delete
490
+ munge_keys self.properties
491
+ super
492
+ end
493
+
494
+ private
495
+ #::TODO::
496
+ # opportunity for meta programming here... but need to get this out the door
497
+ def munge_keys d
498
+ if d.kind_of? Array
499
+ d.each do |o|
500
+
501
+ next if explicit_keys(o) && explicit_customer_key(o)
502
+
503
+ formatted = []
504
+ o['CustomerKey'] = customer_key unless explicit_customer_key o
505
+ unless explicit_properties(o)
506
+ o.each do |k, v|
507
+ next if k == 'CustomerKey'
508
+ formatted.concat MarketingCloudSDK.format_name_value_pairs k => v
509
+ o.delete k
510
+ end
511
+ o['Keys'] = {'Key' => formatted }
512
+ end
513
+ end
514
+ else
515
+ formatted = []
516
+ d.each do |k, v|
517
+ next if k == 'CustomerKey'
518
+ formatted.concat MarketingCloudSDK.format_name_value_pairs k => v
519
+ d.delete k
520
+ end
521
+ d['CustomerKey'] = customer_key
522
+ d['Keys'] = {'Key' => formatted }
523
+ end
524
+ end
525
+
526
+ def explicit_keys h
527
+ h['Keys'] and h['Keys']['Key']
528
+ end
529
+
530
+ def munge_properties d
531
+ if d.kind_of? Array
532
+ d.each do |o|
533
+ next if explicit_properties(o) && explicit_customer_key(o)
534
+
535
+ formatted = []
536
+ o['CustomerKey'] = customer_key unless explicit_customer_key o
537
+ unless explicit_properties(o)
538
+ o.each do |k, v|
539
+ next if k == 'CustomerKey'
540
+ formatted.concat MarketingCloudSDK.format_name_value_pairs k => v
541
+ o.delete k
542
+ end
543
+ o['Properties'] = {'Property' => formatted }
544
+ end
545
+ end
546
+ else
547
+ formatted = []
548
+ d.each do |k, v|
549
+ formatted.concat MarketingCloudSDK.format_name_value_pairs k => v
550
+ d.delete k
551
+ end
552
+ d['CustomerKey'] = customer_key
553
+ d['Properties'] = {'Property' => formatted }
554
+ end
555
+ end
556
+
557
+ def explicit_properties h
558
+ h['Properties'] and h['Properties']['Property']
559
+ end
560
+
561
+ def explicit_customer_key h
562
+ h['CustomerKey']
563
+ end
564
+
565
+ def retrieve_required
566
+ # have to use instance variables so we don't recursivelly retrieve_required
567
+ if !@name && !@customer_key
568
+ raise 'Unable to process DataExtension::Row ' \
569
+ 'request due to missing CustomerKey and Name'
570
+ end
571
+ if !@name || !@customer_key
572
+ filter = {
573
+ 'Property' => @name.nil? ? 'CustomerKey' : 'Name',
574
+ 'SimpleOperator' => 'equals',
575
+ 'Value' => @customer_key || @name
576
+ }
577
+ rsp = client.soap_get 'DataExtension', ['Name', 'CustomerKey'], filter
578
+ if rsp.success? && rsp.results.count == 1
579
+ self.name = rsp.results.first[:name]
580
+ self.customer_key = rsp.results.first[:customer_key]
581
+ else
582
+ raise 'Unable to process DataExtension::Row'
583
+ end
584
+ end
585
+ end
586
+ end
587
+
588
+ private
589
+
590
+ def munge_fields d
591
+ # maybe one day will make it smart enough to zip properties and fields if count is same?
592
+ if d.kind_of? Array and d.count > 1 and (fields and !fields.empty?)
593
+ # we could map the field to all DataExtensions, but lets make user be explicit.
594
+ # if they are going to use fields attribute properties should
595
+ # be a single DataExtension Defined in a Hash
596
+ raise 'Unable to handle muliple DataExtension definitions and a field definition'
597
+ end
598
+
599
+ if d.kind_of? Array
600
+ d.each do |de|
601
+ if (explicit_fields(de) and (de['columns'] || de['fields'] || has_fields)) or
602
+ (de['columns'] and (de['fields'] || has_fields)) or
603
+ (de['fields'] and has_fields)
604
+ raise 'Fields are defined in too many ways. Please only define once.' # ahhh what, to do...
605
+ end
606
+
607
+ # let users who chose, to define fields explicitly within the hash definition
608
+ next if explicit_fields de
609
+
610
+ de['Fields'] = {'Field' => de['columns'] || de['fields'] || fields}
611
+ # sanitize
612
+
613
+ raise 'DataExtension needs atleast one field.' unless de['Fields']['Field']
614
+ end
615
+ else
616
+ self.properties['Fields'] = {'Field' => self.properties['columns'] || self.properties['fields'] || fields}
617
+ raise 'DataExtension needs atleast one field.' unless self.properties['Fields']['Field']
618
+ self.properties.delete 'columns'
619
+ self.properties.delete 'fields'
620
+ end
621
+ end
622
+
623
+ def explicit_fields h
624
+ h['Fields'] and h['Fields']['Field']
625
+ end
626
+
627
+ def has_fields
628
+ fields and !fields.empty?
629
+ end
630
+ end
631
+
632
+ class Campaign < Objects::Base
633
+ include Objects::Rest::Read
634
+ include Objects::Rest::CUD
635
+
636
+ def properties
637
+ @properties ||= {}
638
+ @properties.merge! 'id' => '' unless @properties.include? 'id'
639
+ @properties
640
+ end
641
+
642
+ def id
643
+ self.client.base_api_url + '/hub/v1/campaigns/%{id}'
644
+ end
645
+
646
+ class Asset < Objects::Base
647
+ include Objects::Rest::Read
648
+ include Objects::Rest::CUD
649
+
650
+ def properties
651
+ @properties ||= {}
652
+ @properties.merge! 'assetId' => '' unless @properties.include? 'assetId'
653
+ @properties
654
+ end
655
+
656
+ def id
657
+ self.client.base_api_url + '/hub/v1/campaigns/%{id}/assets/%{assetId}'
658
+ end
659
+ end
660
+ end
661
+
662
+ # Direct Verb Access Section
663
+
664
+ class Get < Objects::Base
665
+ include Objects::Soap::Read
666
+ attr_accessor :id
667
+
668
+ def initialize client, id, properties, filter
669
+ self.properties = properties
670
+ self.filter = filter
671
+ self.client = client
672
+ self.id = id
673
+ end
674
+
675
+ def get
676
+ super id
677
+ end
678
+
679
+ class << self
680
+ def new client, id, properties=nil, filter=nil
681
+ o = self.allocate
682
+ o.send :initialize, client, id, properties, filter
683
+ return o.get
684
+ end
685
+ end
686
+ end
687
+
688
+ class Post < Objects::Base
689
+ include Objects::Soap::CUD
690
+ attr_accessor :id
691
+
692
+ def initialize client, id, properties
693
+ self.properties = properties
694
+ self.client = client
695
+ self.id = id
696
+ end
697
+
698
+ def post
699
+ super
700
+ end
701
+
702
+ class << self
703
+ def new client, id, properties=nil
704
+ o = self.allocate
705
+ o.send :initialize, client, id, properties
706
+ return o.post
707
+ end
708
+ end
709
+ end
710
+
711
+ class Delete < Objects::Base
712
+ include Objects::Soap::CUD
713
+ attr_accessor :id
714
+
715
+ def initialize client, id, properties
716
+ self.properties = properties
717
+ self.client = client
718
+ self.id = id
719
+ end
720
+
721
+ def delete
722
+ super
723
+ end
724
+
725
+ class << self
726
+ def new client, id, properties=nil
727
+ o = self.allocate
728
+ o.send :initialize, client, id, properties
729
+ return o.delete
730
+ end
731
+ end
732
+ end
733
+
734
+ class Patch < Objects::Base
735
+ include Objects::Soap::CUD
736
+ attr_accessor :id
737
+
738
+ def initialize client, id, properties
739
+ self.properties = properties
740
+ self.client = client
741
+ self.id = id
742
+ end
743
+
744
+ def patch
745
+ super
746
+ end
747
+
748
+ class << self
749
+ def new client, id, properties=nil
750
+ o = self.allocate
751
+ o.send :initialize, client, id, properties
752
+ return o.patch
753
+ end
754
+ end
755
+ end
756
+
757
+ end