infopark_reactor 1.10.0.beta → 1.11.0.beta2

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