infopark_reactor 1.10.0.beta → 1.11.0.beta2

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.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/app/models/rails_connector/abstract_model.rb +7 -0
  3. data/app/models/rails_connector/abstract_obj.rb +31 -0
  4. data/app/models/rails_connector/attribute.rb +94 -0
  5. data/app/models/rails_connector/blob_mapping.rb +12 -0
  6. data/app/models/rails_connector/channel.rb +41 -0
  7. data/app/models/rails_connector/content.rb +12 -0
  8. data/app/models/rails_connector/meta/eager_loader.rb +41 -0
  9. data/app/models/rails_connector/obj_class.rb +143 -0
  10. data/app/models/rails_connector/object_with_meta_data.rb +18 -0
  11. data/infopark_reactor.gemspec +4 -4
  12. data/lib/generators/cm/migration/USAGE +8 -0
  13. data/lib/generators/cm/migration/migration_generator.rb +16 -0
  14. data/lib/generators/cm/migration/templates/template.rb +8 -0
  15. data/lib/infopark_reactor.rb +35 -1
  16. data/lib/reactor/attributes.rb +2 -4
  17. data/lib/reactor/cm/attribute.rb +91 -0
  18. data/lib/reactor/cm/bridge.rb +50 -0
  19. data/lib/reactor/cm/channel.rb +18 -0
  20. data/lib/reactor/cm/editorial_group.rb +23 -0
  21. data/lib/reactor/cm/group.rb +241 -0
  22. data/lib/reactor/cm/language.rb +57 -0
  23. data/lib/reactor/cm/link.rb +136 -0
  24. data/lib/reactor/cm/live_group.rb +23 -0
  25. data/lib/reactor/cm/log_entry.rb +64 -0
  26. data/lib/reactor/cm/missing_credentials.rb +8 -0
  27. data/lib/reactor/cm/multi_xml_request.rb +102 -0
  28. data/lib/reactor/cm/obj.rb +544 -0
  29. data/lib/reactor/cm/obj_class.rb +187 -0
  30. data/lib/reactor/cm/object_base.rb +165 -0
  31. data/lib/reactor/cm/permissions.rb +44 -0
  32. data/lib/reactor/cm/user.rb +139 -0
  33. data/lib/reactor/cm/workflow.rb +41 -0
  34. data/lib/reactor/cm/xml_attribute.rb +36 -0
  35. data/lib/reactor/cm/xml_markup.rb +86 -0
  36. data/lib/reactor/cm/xml_multi_request_error.rb +10 -0
  37. data/lib/reactor/cm/xml_request.rb +83 -0
  38. data/lib/reactor/cm/xml_request_error.rb +11 -0
  39. data/lib/reactor/cm/xml_response.rb +43 -0
  40. data/lib/reactor/cm/xml_single_request_error.rb +21 -0
  41. data/lib/reactor/configuration.rb +8 -0
  42. data/lib/{engine.rb → reactor/engine.rb} +16 -1
  43. data/lib/reactor/legacy.rb +3 -3
  44. data/lib/reactor/link/temporary_link.rb +8 -4
  45. data/lib/reactor/migration.rb +87 -0
  46. data/lib/reactor/permission.rb +2 -2
  47. data/lib/reactor/persistence.rb +14 -12
  48. data/lib/reactor/plans/common_attribute.rb +33 -0
  49. data/lib/reactor/plans/common_channel.rb +32 -0
  50. data/lib/reactor/plans/common_group.rb +45 -0
  51. data/lib/reactor/plans/common_obj_class.rb +70 -0
  52. data/lib/reactor/plans/create_attribute.rb +33 -0
  53. data/lib/reactor/plans/create_channel.rb +24 -0
  54. data/lib/reactor/plans/create_group.rb +35 -0
  55. data/lib/reactor/plans/create_obj.rb +49 -0
  56. data/lib/reactor/plans/create_obj_class.rb +29 -0
  57. data/lib/reactor/plans/delete_attribute.rb +24 -0
  58. data/lib/reactor/plans/delete_channel.rb +22 -0
  59. data/lib/reactor/plans/delete_group.rb +29 -0
  60. data/lib/reactor/plans/delete_obj.rb +23 -0
  61. data/lib/reactor/plans/delete_obj_class.rb +23 -0
  62. data/lib/reactor/plans/prepared.rb +16 -0
  63. data/lib/reactor/plans/rename_group.rb +33 -0
  64. data/lib/reactor/plans/rename_obj_class.rb +25 -0
  65. data/lib/reactor/plans/update_attribute.rb +24 -0
  66. data/lib/reactor/plans/update_group.rb +31 -0
  67. data/lib/reactor/plans/update_obj.rb +31 -0
  68. data/lib/reactor/plans/update_obj_class.rb +27 -0
  69. data/lib/reactor/rails_connector_meta.rb +144 -0
  70. data/lib/reactor/tools/migrator.rb +136 -0
  71. data/lib/reactor/tools/response_handler/base.rb +23 -0
  72. data/lib/reactor/tools/response_handler/string.rb +20 -0
  73. data/lib/reactor/tools/response_handler/xml_attribute.rb +53 -0
  74. data/lib/reactor/tools/smart_xml_logger.rb +70 -0
  75. data/lib/reactor/tools/sower.rb +90 -0
  76. data/lib/reactor/tools/uploader.rb +134 -0
  77. data/lib/reactor/tools/versioner.rb +121 -0
  78. data/lib/reactor/tools/workflow_generator.rb +1 -1
  79. data/lib/reactor/tools/xml_attributes.rb +71 -0
  80. data/lib/reactor/version.rb +1 -1
  81. data/lib/tasks/cm_migrate.rake +8 -0
  82. data/lib/tasks/cm_seeds.rake +41 -0
  83. metadata +82 -13
  84. data/README.md +0 -186
@@ -0,0 +1,102 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'net/http'
3
+ require 'reactor/cm/xml_response'
4
+ require 'reactor/cm/xml_multi_request_error'
5
+ require 'reactor/cm/xml_markup'
6
+ require 'nokogiri'
7
+
8
+ module Reactor
9
+ module Cm
10
+
11
+ class MultiXmlRequest
12
+
13
+ def self.token(login, instance_secret)
14
+ Digest::MD5.hexdigest(login + instance_secret)
15
+ end
16
+
17
+ def self.execute
18
+ access = Configuration::xml_access
19
+ sanity_check(access)
20
+ xml = XmlMarkup.new
21
+ xml2 = nil
22
+ ret = nil
23
+ xml.instruct!
24
+ req = nil
25
+ ret = xml.tag!('cm-payload', 'payload-id' =>'abcabc', 'timestamp' => Time.now.getutc.strftime('%Y%m%d%H%M%S'), 'version' => '6.7.3') do
26
+ xml.tag!('cm-header') do
27
+ xml.tag!('cm-sender', 'sender-id' => access[:id], 'name' => "ruby-simple-client")
28
+ xml.tag!('cm-authentication', 'login' => access[:username], 'token' => token(access[:username],access[:secret]))
29
+ end
30
+ req = self.new(xml).tap do |instance|
31
+ yield instance
32
+ end
33
+ end
34
+ req.execute!(ret)
35
+ end
36
+
37
+ def mandatory(&block)
38
+ req_id = self.class.generate_id
39
+ @mandatory << req_id
40
+ @builder.tag!('cm-request', 'request-id' => req_id, 'preclusive' => 'true') do |xml2|
41
+ yield xml2
42
+ end
43
+ end
44
+
45
+ def optional(&block)
46
+ req_id = self.class.generate_id
47
+ @optional << req_id
48
+ @builder.tag!('cm-request', 'request-id' => req_id, 'preclusive' => 'false') do |xml2|
49
+ yield xml2
50
+ end
51
+ end
52
+
53
+ def execute!(xml)
54
+ access = Configuration::xml_access
55
+ payload = xml
56
+
57
+ res = Net::HTTP.new(access[:host], access[:port]).start do |http|
58
+ req = Net::HTTP::Post.new('/xml')
59
+ req.body = payload
60
+ http.request(req)
61
+ end
62
+
63
+ result = MultiXmlResponse.new(res.body, @mandatory, @optional)
64
+ end
65
+
66
+ class << self
67
+
68
+ def generate_id
69
+ rand(10000)
70
+ end
71
+
72
+ protected
73
+
74
+ def sanity_check(access)
75
+ raise Reactor::Cm::MissingCredentials if access[:username].nil? || access[:username].empty?
76
+ end
77
+ end
78
+
79
+ protected
80
+
81
+ def initialize(builder)
82
+ @builder = builder
83
+ @mandatory = []
84
+ @optional = []
85
+ end
86
+
87
+ class MultiXmlResponse
88
+ def initialize(xml, mandatory, optional)
89
+ @xml, @mandatory, @optional = xml, mandatory, optional
90
+ @n = Nokogiri::XML.parse(@xml)
91
+ end
92
+
93
+ def assert_success
94
+ first_failed = nil
95
+ @mandatory.any? do |mandatory_id|
96
+ @n.xpath("//cm-response[@request-id='#{mandatory_id}']//cm-code[@numeric='200']").empty? && (first_failed = mandatory_id)
97
+ end && raise(XmlMultiRequestError, @n.xpath("//cm-response[@request-id='#{first_failed}']//cm-code//error/phrase/text()").map(&:to_s).join("\n"))
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,544 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'reactor/cm/multi_xml_request'
3
+
4
+ module Reactor
5
+ module Cm
6
+ class Obj
7
+ attr_reader :obj_id
8
+ OBJ_ATTRS = [:permalink, :objClass, :workflowName, :name, :suppressExport, :parent]
9
+ ATTR_LENGTH_CONSTRAINT = {:name => 250, :title => 250}
10
+
11
+ def self.create(name, parent, objClass)
12
+ obj = Obj.new(name)
13
+ obj.send(:create, parent, objClass)
14
+ obj
15
+ end
16
+
17
+ def self.exists?(path_or_id)
18
+ obj = Obj.new
19
+ begin
20
+ obj.send(:load, path_or_id).ok?
21
+ rescue
22
+ return false
23
+ end
24
+ end
25
+
26
+ def self.load(id)
27
+ obj = Obj.new
28
+ obj.instance_variable_set('@obj_id', id)
29
+ obj
30
+ end
31
+
32
+ def self.get(path_or_id)
33
+ obj = Obj.new
34
+ obj.send(:load, path_or_id)
35
+ obj
36
+ end
37
+
38
+ def self.delete_where(conditions)
39
+ request = XmlRequest.prepare do |xml|
40
+
41
+ xml.tag!('obj-where') do
42
+ conditions.each do |key, value|
43
+ xml.tag!(key, value)
44
+ end
45
+ end
46
+ xml.tag!("obj-delete")
47
+ end
48
+ request.execute!
49
+ end
50
+
51
+ def upload(data_or_io, extension)
52
+ data = (data_or_io.kind_of?IO) ? data_or_io.read : data_or_io
53
+ base64_data = Base64.encode64(data)
54
+
55
+ set(:contentType, extension)
56
+ set(:blob, {base64_data=>{:encoding=>'base64'}})
57
+ end
58
+
59
+ def get(key)
60
+ request = XmlRequest.prepare do |xml|
61
+ xml.where_key_tag!(base_name, 'id', @obj_id)
62
+ xml.get_key_tag!(base_name, key)
63
+ end
64
+ response = request.execute!
65
+ result = response.xpath("//#{key}")
66
+ if result.children.map {|i| i.respond_to?(:name) && (i.name == "listitem") }.reduce(:&)
67
+ result.children.map {|i| i.text.to_s }
68
+ else
69
+ result = result.text unless result.is_a? Array
70
+ result
71
+ end
72
+ end
73
+
74
+ def set(key, value, options={})
75
+ key = key.to_sym
76
+ value = value[0, ATTR_LENGTH_CONSTRAINT[key]] if ATTR_LENGTH_CONSTRAINT[key] && value
77
+ if OBJ_ATTRS.include?(key) then @obj_attrs[key] = value
78
+ else
79
+ @attrs[key] = value
80
+ end
81
+ @attr_options[key] = options
82
+ end
83
+
84
+ def permission_granted_to(user, permission)
85
+ request = XmlRequest.prepare do |xml|
86
+ xml.where_key_tag!(base_name, 'id', @obj_id)
87
+ xml.get_tag!(base_name) do
88
+ xml.tag!('permissionGrantedTo', :permission => permission, :user => user)
89
+ end
90
+ end
91
+ response = request.execute!
92
+ response.xpath("//permissionGrantedTo/text()") == "1"
93
+ end
94
+
95
+ def permission_set(permission, groups)
96
+ request = XmlRequest.prepare do |xml|
97
+ xml.where_key_tag!(base_name, :id, @obj_id)
98
+
99
+ options = {
100
+ :permission => permission,
101
+ :type => :list,
102
+ }
103
+
104
+ xml.set_key_tag!(base_name, :permission, groups, options)
105
+ end
106
+
107
+ request.execute!
108
+ end
109
+
110
+ def permission_grant(permission, groups)
111
+ self.permission_command('GrantTo', permission, groups)
112
+ end
113
+
114
+ def permission_revoke(permission, groups)
115
+ self.permission_command('RevokeFrom', permission, groups)
116
+ end
117
+
118
+ def permission_clear(permission)
119
+ self.permission_set(permission, [])
120
+ end
121
+
122
+ def get_links(attr)
123
+ get_link_ids(attr).map {|id| Link.get(id)}
124
+ end
125
+
126
+ def set_links(attr, new_links_as_hashes)
127
+ get_links(attr).map(&:delete!)
128
+ new_links_as_hashes.each do |link_hash|
129
+ Link.create_inside(self, attr, link_hash[:destination_url], link_hash[:title], link_hash[:target])
130
+ end
131
+ end
132
+
133
+ def set_link(attr, path)
134
+ old_links = get_links(attr)
135
+ if old_links.length == 1
136
+ old_link = old_links.first
137
+ old_link.dest_url = path
138
+ @links[attr] = [old_link]
139
+ else
140
+ @removed_links = old_links
141
+ @links[attr] = [Link.create_inside(self, attr, path)]
142
+ end
143
+ end
144
+
145
+ def set_mutiple(attrs)
146
+ attrs.each {|a,(v,o)| set(a,v,o||{}) }
147
+ end
148
+
149
+ def composite_save(attrs, links_to_add, links_to_remove, links_to_set, links_modified=false)
150
+ set_mutiple(attrs)
151
+
152
+ skip_version_creation = @attrs.empty? && links_to_remove.empty? && links_to_set.empty? && !links_modified
153
+
154
+ resp = MultiXmlRequest.execute do |reqs|
155
+ reqs.optional {|xml| SimpleCommandRequest.build(xml, @obj_id, 'take') } unless skip_version_creation
156
+ reqs.optional {|xml| SimpleCommandRequest.build(xml, @obj_id, 'edit') } unless skip_version_creation
157
+
158
+
159
+ reqs.mandatory {|xml| ObjSetRequest.build(xml, @obj_id, @obj_attrs) } unless @obj_attrs.empty? #important! requires different permissions
160
+ reqs.mandatory {|xml| ContentSetRequest.build(xml, @obj_id, @attrs, @attr_options) } unless skip_version_creation
161
+ end
162
+
163
+ resp.assert_success
164
+
165
+ yield(attrs, links_to_add, links_to_remove, links_to_set) if block_given?
166
+
167
+ resp = MultiXmlRequest.execute do |reqs|
168
+ links_to_remove.each do |link_id|
169
+ reqs.mandatory {|xml| LinkDeleteRequest.build(xml, link_id) }
170
+ end
171
+ links_to_add.each do |(attr, link)|
172
+
173
+ reqs.mandatory {|xml| LinkAddRequest.build(xml, @obj_id, attr, link) }
174
+ end
175
+
176
+ links_to_set.each do |(link_id, link)|
177
+ reqs.mandatory {|xml| LinkSetRequest.build(xml, link_id, link) }
178
+ end
179
+
180
+ reqs.optional {|xml| ResolveRefsRequest.build(xml, @obj_id) }
181
+ end unless skip_version_creation
182
+
183
+ resp.assert_success
184
+ end
185
+
186
+ def save!
187
+ links_to_remove = @removed_links.map {|l| l.link_id}
188
+ links_to_add = @links.map do |attr, links|
189
+ links.map do |link|
190
+ [attr, {:destination_url => link.dest_url, :title => link.title, :target => link.target, :position => link.position}]
191
+ end.flatten
192
+ end
193
+ composite_save([], links_to_add, links_to_remove, [])
194
+ end
195
+
196
+
197
+ def release!(msg=nil)
198
+ simple_command("release",msg)
199
+ end
200
+
201
+ def edit!(msg=nil)
202
+ simple_command("edit",msg)
203
+ end
204
+
205
+ def take!(msg=nil)
206
+ simple_command("take",msg)
207
+ end
208
+
209
+ def forward!(msg=nil)
210
+ simple_command("forward",msg)
211
+ end
212
+
213
+ def commit!(msg=nil)
214
+ simple_command("commit",msg)
215
+ end
216
+
217
+ def reject!(msg=nil)
218
+ simple_command("reject",msg)
219
+ end
220
+
221
+ def revert!(msg=nil)
222
+ simple_command("revert",msg)
223
+ end
224
+
225
+ def sign!(msg=nil)
226
+ simple_command("sign",msg)
227
+ end
228
+
229
+ def valid_actions
230
+ vcak = get('validControlActionKeys')
231
+ (vcak || []).map(&:to_s)
232
+ end
233
+
234
+ def copy(new_parent, recursive = false, new_name = nil)
235
+ request = XmlRequest.prepare do |xml|
236
+ xml.tag!('obj-where') do
237
+ xml.tag!("id", @obj_id)
238
+ end
239
+ xml.tag!("obj-copy") do
240
+ xml.tag!("parent", new_parent)
241
+ xml.tag!("name", new_name) if new_name
242
+ xml.tag!("recursive", "1") if recursive
243
+ end
244
+ end
245
+ response = request.execute!
246
+ response.xpath("//obj/id").text
247
+ end
248
+
249
+ def delete!
250
+ simple_command("delete")
251
+ end
252
+
253
+ def remove_active_contents!
254
+ simple_command("removeActiveContents")
255
+ end
256
+
257
+ def remove_archived_contents!
258
+ simple_command("removeArchivedContents")
259
+ end
260
+
261
+ def resolve_refs!
262
+ request = XmlRequest.prepare do |xml|
263
+ xml.tag!('content-where') do
264
+ xml.tag!('objectId', @obj_id)
265
+ xml.tag!('state', 'edited')
266
+ end
267
+ xml.tag!('content-resolveRefs')
268
+ end
269
+ response = request.execute!
270
+ end
271
+
272
+ def path
273
+ request = XmlRequest.prepare do |xml|
274
+ xml.where_key_tag!(base_name, 'id', @obj_id)
275
+ xml.get_key_tag!(base_name, 'path')
276
+ end
277
+ response = request.execute!
278
+ response.xpath("//obj/path").text
279
+ end
280
+
281
+ def edited?
282
+ request = XmlRequest.prepare do |xml|
283
+ xml.where_key_tag!(base_name, 'id', @obj_id)
284
+ xml.get_key_tag!(base_name, 'isEdited')
285
+ end
286
+ response = request.execute!
287
+ response.xpath("//isEdited").text == "1"
288
+ end
289
+
290
+ def reasons_for_incomplete_state
291
+ request = XmlRequest.prepare do |xml|
292
+ xml.tag!('content-where') do
293
+ xml.tag!('objectId', @obj_id)
294
+ xml.tag!('state', 'edited')
295
+ end
296
+ xml.get_key_tag!('content', 'reasonsForIncompleteState')
297
+ end
298
+ response = request.execute!
299
+ result = response.xpath('//reasonsForIncompleteState/*')
300
+ result.kind_of?(Array) ? result.map(&:text).map(&:to_s) : [result.to_s]
301
+ end
302
+
303
+ def workflow_comment
304
+ request = XmlRequest.prepare do |xml|
305
+ xml.tag!('content-where') do
306
+ xml.tag!('objectId', @obj_id)
307
+ xml.tag!('state', 'released')
308
+ end
309
+ xml.get_key_tag!('content', 'workflowComment')
310
+ end
311
+ response = request.execute!
312
+ result = response.xpath('//workflowComment/*').map {|x| x.text.to_s}.first
313
+ end
314
+
315
+ def editor
316
+ request = XmlRequest.prepare do |xml|
317
+ xml.tag!('content-where') do
318
+ xml.tag!('objectId', @obj_id)
319
+ xml.tag!('state', 'edited')
320
+ end
321
+ xml.get_key_tag!('content', 'editor')
322
+ end
323
+ response = request.execute!
324
+ response.xpath('//editor').text
325
+ end
326
+
327
+ def edited_content
328
+ request = XmlRequest.prepare do |xml|
329
+ xml.where_key_tag!(base_name, 'id', @obj_id)
330
+ xml.get_key_tag!(base_name, 'editedContent')
331
+ end
332
+ response = request.execute!
333
+ response.xpath("//editedContent").text
334
+ end
335
+
336
+ protected
337
+ def simple_command(cmd_name, comment=nil)
338
+ @request = XmlRequest.prepare do |xml|
339
+ xml.where_key_tag!(base_name, 'id', @obj_id)
340
+ if comment
341
+ xml.tag!("#{base_name}-#{cmd_name}") do
342
+ xml.tag!('comment', comment)
343
+ end
344
+ else
345
+ xml.tag!("#{base_name}-#{cmd_name}")
346
+ end
347
+ end
348
+ response = @request.execute!
349
+ end
350
+
351
+ def base_name
352
+ 'obj'
353
+ end
354
+
355
+ def get_content_attr_text(attr)
356
+ content = edited_content
357
+ request = XmlRequest.prepare do |xml|
358
+ xml.where_key_tag!('content', 'id', content)
359
+ xml.get_tag!('content') do
360
+ xml.tag!(attr.to_s)
361
+ end
362
+ end
363
+ response = request.execute!
364
+ txt = response.xpath("//#{attr}/text()")
365
+ txt.class.unnormalize(txt.to_s)
366
+ end
367
+
368
+ def get_link_ids(attr)
369
+ content = edited_content
370
+ request = XmlRequest.prepare do |xml|
371
+ xml.where_key_tag!('content', 'id', content)
372
+ xml.get_key_tag!('content', attr.to_s)
373
+ end
374
+ response = request.execute!
375
+ result = response.xpath("//listitem/text()")
376
+ result.kind_of?(Array) ? result : [result]
377
+ rescue XmlRequestError
378
+ []
379
+ end
380
+
381
+ def self.extract_id(response)
382
+ response.xpath("//obj/id").text
383
+ end
384
+
385
+ def initialize(name=nil)
386
+ @name = name
387
+ @attrs = {}
388
+ @obj_attrs = {}
389
+ @links = {}
390
+ @removed_links = []
391
+ @attr_options = {}
392
+ end
393
+
394
+ def create(parent, objClass)
395
+ @request = XmlRequest.prepare do |xml|
396
+ xml.where_key_tag!(base_name, 'path', parent)
397
+ xml.create_tag!(base_name) do
398
+ xml.tag!('objClass') do
399
+ xml.text!(objClass)
400
+ end
401
+ xml.tag!('name') do
402
+ xml.text!(@name)
403
+ end
404
+ end
405
+ end
406
+ response = @request.execute!
407
+ @obj_id = self.class.extract_id(response)
408
+ response
409
+ end
410
+
411
+ def load(path_or_id)
412
+ key = (/^\// =~ path_or_id.to_s) ? 'path' : 'id'
413
+ value = path_or_id
414
+
415
+ @request = XmlRequest.prepare do |xml|
416
+ xml.where_key_tag!(base_name, key.to_s, value.to_s)
417
+ xml.get_key_tag!(base_name, 'id')
418
+ end
419
+ response = @request.execute!
420
+ @obj_id = self.class.extract_id(response)
421
+ response
422
+ end
423
+
424
+ def permission_command(type, permission, groups)
425
+ request = XmlRequest.prepare do |xml|
426
+ xml.where_key_tag!(base_name, 'id', @obj_id)
427
+
428
+ xml.tag!("#{base_name}-permission#{type}", :permission => permission) do
429
+ groups.each do |name|
430
+ xml.tag!(:group, name)
431
+ end
432
+ end
433
+ end
434
+
435
+ request.execute!
436
+ end
437
+
438
+ class Request
439
+ attr_reader :xml
440
+
441
+ def initialize(xml)
442
+ @xml = xml
443
+ end
444
+
445
+ def self.build(xml, *args)
446
+ self.new(xml).build(*args)
447
+ end
448
+ end
449
+
450
+ class SimpleCommandRequest < Request
451
+ def build(obj_id, cmd_name, comment = nil)
452
+ xml.where_key_tag!('obj', 'id', obj_id)
453
+ if comment
454
+ xml.tag!("obj-#{cmd_name}") do
455
+ xml.tag!('comment', comment)
456
+ end
457
+ else
458
+ xml.tag!("obj-#{cmd_name}")
459
+ end
460
+ end
461
+ end
462
+
463
+ class ObjSetRequest < Request
464
+ def build(obj_id, obj_attrs)
465
+ xml.where_key_tag!('obj', 'id', obj_id)
466
+ xml.set_tag!('obj') do
467
+ obj_attrs.each do |key, value|
468
+ xml.value_tag!(key, value)
469
+ end
470
+ end
471
+ end
472
+ end
473
+
474
+ class ContentSetRequest < Request
475
+ def build(id, attrs, attr_options)
476
+ xml.tag!('content-where') do
477
+ xml.tag!('objectId', id.to_s)
478
+ xml.tag!('state', 'edited')
479
+ end
480
+ xml.tag!("content-set") do
481
+ attrs.each do |key, value|
482
+ if (attr_options[key] || {})[:cdata]
483
+ xml.tag!(key.to_s) do
484
+ xml.cdata!(value)
485
+ end
486
+ else
487
+ xml.value_tag!(key.to_s, value)
488
+ end
489
+ end
490
+ end
491
+ end
492
+ end
493
+
494
+ class LinkDeleteRequest < Request
495
+ def build(link_id)
496
+ xml.where_key_tag!('link', 'id', link_id)
497
+ xml.tag!("link-delete")
498
+ end
499
+ end
500
+
501
+ class LinkAddRequest < Request
502
+ def build(obj_id, attr, link_data)
503
+ title = link_data[:title]
504
+ target = link_data[:target]
505
+ xml.tag!('content-where') do
506
+ xml.tag!('objectId', obj_id.to_s)
507
+ xml.tag!('state', 'edited')
508
+ end
509
+ xml.tag!('content-addLinkTo') do
510
+ xml.tag!('attribute', attr.to_s)
511
+ xml.tag!('destinationUrl', link_data[:destination_url].to_s)
512
+ xml.tag!('title', title.to_s) if title
513
+ xml.tag!('target', target.to_s) if target
514
+ end
515
+ end
516
+ end
517
+
518
+ class LinkSetRequest < Request
519
+ def build(link_id, link_data)
520
+ title = link_data[:title]
521
+ target = link_data[:target]
522
+ xml.tag!('link-where') do
523
+ xml.tag!('id', link_id)
524
+ end
525
+ xml.tag!('link-set') do
526
+ xml.tag!('destinationUrl', link_data[:destination_url].to_s)
527
+ xml.tag!('title', title.to_s) if title
528
+ xml.tag!('target', target.to_s) if target
529
+ end
530
+ end
531
+ end
532
+
533
+ class ResolveRefsRequest < Request
534
+ def build(obj_id)
535
+ xml.tag!('content-where') do
536
+ xml.tag!('objectId', obj_id.to_s)
537
+ xml.tag!('state', 'edited')
538
+ end
539
+ xml.tag!('content-resolveRefs')
540
+ end
541
+ end
542
+ end
543
+ end
544
+ end