google-ads-savon 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/BUILD +7 -0
- data/CONTRIBUTING +24 -0
- data/ChangeLog +3 -0
- data/LICENSE +21 -0
- data/README.md +17 -0
- data/Rakefile +5 -0
- data/google-ads-savon.gemspec +35 -0
- data/lib/ads_savon.rb +23 -0
- data/lib/ads_savon/client.rb +163 -0
- data/lib/ads_savon/config.rb +46 -0
- data/lib/ads_savon/core_ext/string.rb +30 -0
- data/lib/ads_savon/error.rb +6 -0
- data/lib/ads_savon/hooks/group.rb +68 -0
- data/lib/ads_savon/hooks/hook.rb +61 -0
- data/lib/ads_savon/http/error.rb +42 -0
- data/lib/ads_savon/log_message.rb +50 -0
- data/lib/ads_savon/logger.rb +39 -0
- data/lib/ads_savon/model.rb +102 -0
- data/lib/ads_savon/null_logger.rb +10 -0
- data/lib/ads_savon/soap.rb +21 -0
- data/lib/ads_savon/soap/fault.rb +72 -0
- data/lib/ads_savon/soap/invalid_response_error.rb +13 -0
- data/lib/ads_savon/soap/request.rb +86 -0
- data/lib/ads_savon/soap/request_builder.rb +205 -0
- data/lib/ads_savon/soap/response.rb +130 -0
- data/lib/ads_savon/soap/xml.rb +252 -0
- data/lib/ads_savon/version.rb +5 -0
- metadata +224 -0
@@ -0,0 +1,205 @@
|
|
1
|
+
module GoogleAdsSavon
|
2
|
+
module SOAP
|
3
|
+
|
4
|
+
# = GoogleAdsSavon::SOAP::RequestBuilder
|
5
|
+
#
|
6
|
+
# GoogleAdsSavon::SOAP::RequestBuilder builds GoogleAdsSavon::SOAP::Request instances.
|
7
|
+
# The RequestBuilder is configured by the client that instantiates it.
|
8
|
+
# It uses the options set by the client to build an appropriate request.
|
9
|
+
class RequestBuilder
|
10
|
+
|
11
|
+
# Initialize a new +RequestBuilder+ with the given SOAP operation.
|
12
|
+
# The operation may be specified using a symbol or a string.
|
13
|
+
def initialize(operation, options = {})
|
14
|
+
@operation = operation
|
15
|
+
assign_options(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Writer for the <tt>HTTPI::Request</tt> object.
|
19
|
+
attr_writer :http
|
20
|
+
|
21
|
+
# Writer for the <tt>GoogleAdsSavon::SOAP::XML</tt> object.
|
22
|
+
attr_writer :soap
|
23
|
+
|
24
|
+
# Writer for the <tt>Akami::WSSE</tt> object.
|
25
|
+
attr_writer :wsse
|
26
|
+
|
27
|
+
# Writer for the <tt>Wasabi::Document</tt> object.
|
28
|
+
attr_writer :wsdl
|
29
|
+
|
30
|
+
# Writer for the <tt>GoogleAdsSavon::Config</tt> object.
|
31
|
+
attr_writer :config
|
32
|
+
|
33
|
+
# Writer for the attributes of the SOAP input tag. Accepts a Hash.
|
34
|
+
attr_writer :attributes
|
35
|
+
|
36
|
+
# Writer for the namespace identifer of the <tt>GoogleAdsSavon::SOAP::XML</tt>
|
37
|
+
# object.
|
38
|
+
attr_writer :namespace_identifier
|
39
|
+
|
40
|
+
# Writer for the SOAP action of the <tt>GoogleAdsSavon::SOAP::XML</tt> object.
|
41
|
+
attr_writer :soap_action
|
42
|
+
|
43
|
+
# Reader for the operation of the request being built by the request builder.
|
44
|
+
attr_reader :operation
|
45
|
+
|
46
|
+
# Builds and returns a <tt>GoogleAdsSavon::SOAP::Request</tt> object. You may optionally
|
47
|
+
# pass a block to the method that will be run after the initial configuration of
|
48
|
+
# the dependencies. +self+ will be yielded to the block if the block accepts an
|
49
|
+
# argument.
|
50
|
+
def request(&post_configuration_block)
|
51
|
+
configure_dependencies
|
52
|
+
|
53
|
+
if post_configuration_block
|
54
|
+
# Only yield self to the block if our block takes an argument
|
55
|
+
args = [] and (args << self if post_configuration_block.arity == 1)
|
56
|
+
post_configuration_block.call(*args)
|
57
|
+
end
|
58
|
+
|
59
|
+
Request.new(config, http, soap)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the identifier for the default namespace. If an operation namespace
|
63
|
+
# identifier is defined for the current operation in the WSDL document, this
|
64
|
+
# namespace identifier is used. Otherwise, the +@namespace_identifier+ instance
|
65
|
+
# variable is used.
|
66
|
+
def namespace_identifier
|
67
|
+
if operation_namespace_defined_in_wsdl?
|
68
|
+
wsdl.operations[operation][:namespace_identifier].to_sym
|
69
|
+
else
|
70
|
+
@namespace_identifier
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns the namespace identifier to be used for the the SOAP input tag.
|
75
|
+
# If +@namespace_identifier+ is not +nil+, it will be returned. Otherwise, the
|
76
|
+
# default namespace identifier as returned by +namespace_identifier+ will be
|
77
|
+
# returned.
|
78
|
+
def input_namespace_identifier
|
79
|
+
@namespace_identifier || namespace_identifier
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns the default namespace to be used for the SOAP request. If a namespace
|
83
|
+
# is defined for the operation in the WSDL document, this namespace will be
|
84
|
+
# returned. Otherwise, the default WSDL document namespace will be returned.
|
85
|
+
def namespace
|
86
|
+
if operation_namespace_defined_in_wsdl?
|
87
|
+
wsdl.parser.namespaces[namespace_identifier.to_s]
|
88
|
+
else
|
89
|
+
wsdl.namespace
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns true if the operation's namespace is defined within the WSDL
|
94
|
+
# document.
|
95
|
+
def operation_namespace_defined_in_wsdl?
|
96
|
+
return false unless wsdl.document?
|
97
|
+
(operation = wsdl.operations[self.operation]) && operation[:namespace_identifier]
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns the SOAP action. If +@soap_action+ has been defined, this will
|
101
|
+
# be returned. Otherwise, if there is a WSDL document defined, the SOAP
|
102
|
+
# action corresponding to the operation will be returned. Failing this,
|
103
|
+
# the operation name will be used to form the SOAP action.
|
104
|
+
def soap_action
|
105
|
+
return @soap_action if @soap_action
|
106
|
+
|
107
|
+
if wsdl.document?
|
108
|
+
wsdl.soap_action(operation.to_sym)
|
109
|
+
else
|
110
|
+
Gyoku::XMLKey.create(operation).to_sym
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns the SOAP operation input tag. If there is a WSDL document defined,
|
115
|
+
# and the operation's input tag is defined in the document, this will be
|
116
|
+
# returned. Otherwise, the operation name will be used to form the input tag.
|
117
|
+
def soap_input_tag
|
118
|
+
if wsdl.document? && (input = wsdl.soap_input(operation.to_sym))
|
119
|
+
input
|
120
|
+
else
|
121
|
+
Gyoku::XMLKey.create(operation)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Changes the body of the SOAP request to +body+.
|
126
|
+
def body=(body)
|
127
|
+
soap.body = body
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns the body of the SOAP request.
|
131
|
+
def body
|
132
|
+
soap.body
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns the attributes of the SOAP input tag. Defaults to
|
136
|
+
# an empty Hash.
|
137
|
+
def attributes
|
138
|
+
@attributes ||= {}
|
139
|
+
end
|
140
|
+
|
141
|
+
# Returns the <tt>GoogleAdsSavon::Config</tt> object for the request. Defaults
|
142
|
+
# to a clone of <tt>GoogleAdsSavon.config</tt>.
|
143
|
+
def config
|
144
|
+
@config ||= GoogleAdsSavon.config.clone
|
145
|
+
end
|
146
|
+
|
147
|
+
# Returns the <tt>HTTPI::Request</tt> object.
|
148
|
+
def http
|
149
|
+
@http ||= HTTPI::Request.new
|
150
|
+
end
|
151
|
+
|
152
|
+
# Returns the <tt>SOAP::XML</tt> object.
|
153
|
+
def soap
|
154
|
+
@soap ||= XML.new(config)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Returns the <tt>Wasabi::Document</tt> object.
|
158
|
+
def wsdl
|
159
|
+
@wsdl ||= Wasabi::Document.new
|
160
|
+
end
|
161
|
+
|
162
|
+
# Returns the <tt>Akami::WSSE</tt> object.
|
163
|
+
def wsse
|
164
|
+
@wsse ||= Akami.wsse
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
def configure_dependencies
|
170
|
+
soap.endpoint = wsdl.endpoint
|
171
|
+
soap.element_form_default = wsdl.element_form_default
|
172
|
+
soap.wsse = wsse
|
173
|
+
|
174
|
+
soap.namespace = namespace
|
175
|
+
soap.namespace_identifier = namespace_identifier
|
176
|
+
|
177
|
+
add_wsdl_namespaces_to_soap
|
178
|
+
add_wsdl_types_to_soap
|
179
|
+
|
180
|
+
soap.input = [input_namespace_identifier, soap_input_tag.to_sym, attributes]
|
181
|
+
|
182
|
+
http.headers["SOAPAction"] = %{"#{soap_action}"}
|
183
|
+
end
|
184
|
+
|
185
|
+
def add_wsdl_namespaces_to_soap
|
186
|
+
wsdl.type_namespaces.each do |path, uri|
|
187
|
+
soap.use_namespace(path, uri)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def add_wsdl_types_to_soap
|
192
|
+
wsdl.type_definitions.each do |path, type|
|
193
|
+
soap.types[path] = type
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def assign_options(options)
|
198
|
+
options.each do |option, value|
|
199
|
+
send(:"#{option}=", value) if value
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require "ads_savon/soap/xml"
|
2
|
+
require "ads_savon/soap/fault"
|
3
|
+
require "ads_savon/soap/invalid_response_error"
|
4
|
+
require "ads_savon/http/error"
|
5
|
+
|
6
|
+
module GoogleAdsSavon
|
7
|
+
module SOAP
|
8
|
+
|
9
|
+
# = GoogleAdsSavon::SOAP::Response
|
10
|
+
#
|
11
|
+
# Represents the SOAP response and contains the HTTP response.
|
12
|
+
class Response
|
13
|
+
|
14
|
+
# Expects an <tt>HTTPI::Response</tt> and handles errors.
|
15
|
+
def initialize(config, response)
|
16
|
+
self.config = config
|
17
|
+
self.http = response
|
18
|
+
raise_errors if config.raise_errors
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_accessor :http, :config
|
22
|
+
|
23
|
+
# Returns whether the request was successful.
|
24
|
+
def success?
|
25
|
+
!soap_fault? && !http_error?
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns whether there was a SOAP fault.
|
29
|
+
def soap_fault?
|
30
|
+
soap_fault.present?
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the <tt>GoogleAdsSavon::SOAP::Fault</tt>.
|
34
|
+
def soap_fault
|
35
|
+
@soap_fault ||= Fault.new http
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns whether there was an HTTP error.
|
39
|
+
def http_error?
|
40
|
+
http_error.present?
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns the <tt>GoogleAdsSavon::HTTP::Error</tt>.
|
44
|
+
def http_error
|
45
|
+
@http_error ||= HTTP::Error.new http
|
46
|
+
end
|
47
|
+
|
48
|
+
# Shortcut accessor for the SOAP response body Hash.
|
49
|
+
def [](key)
|
50
|
+
body[key]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns the SOAP response header as a Hash.
|
54
|
+
def header
|
55
|
+
if !hash.has_key? :envelope
|
56
|
+
raise GoogleAdsSavon::SOAP::InvalidResponseError, "Unable to parse response body '#{to_xml}'"
|
57
|
+
end
|
58
|
+
hash[:envelope][:header]
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns the SOAP response body as a Hash.
|
62
|
+
def body
|
63
|
+
if !hash.has_key? :envelope
|
64
|
+
raise GoogleAdsSavon::SOAP::InvalidResponseError, "Unable to parse response body '#{to_xml}'"
|
65
|
+
end
|
66
|
+
hash[:envelope][:body]
|
67
|
+
end
|
68
|
+
|
69
|
+
alias to_hash body
|
70
|
+
|
71
|
+
# Traverses the SOAP response body Hash for a given +path+ of Hash keys and returns
|
72
|
+
# the value as an Array. Defaults to return an empty Array in case the path does not
|
73
|
+
# exist or returns nil.
|
74
|
+
def to_array(*path)
|
75
|
+
result = path.inject body do |memo, key|
|
76
|
+
return [] unless memo[key]
|
77
|
+
memo[key]
|
78
|
+
end
|
79
|
+
|
80
|
+
result.kind_of?(Array) ? result.compact : [result].compact
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the complete SOAP response XML without normalization.
|
84
|
+
def hash
|
85
|
+
@hash ||= nori.parse(to_xml)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns the SOAP response XML.
|
89
|
+
def to_xml
|
90
|
+
http.body
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns a <tt>Nokogiri::XML::Document</tt> for the SOAP response XML.
|
94
|
+
def doc
|
95
|
+
@doc ||= Nokogiri::XML(to_xml)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns an Array of <tt>Nokogiri::XML::Node</tt> objects retrieved with the given +path+.
|
99
|
+
# Automatically adds all of the document's namespaces unless a +namespaces+ hash is provided.
|
100
|
+
def xpath(path, namespaces = nil)
|
101
|
+
doc.xpath(path, namespaces || xml_namespaces)
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def raise_errors
|
107
|
+
raise soap_fault if soap_fault?
|
108
|
+
raise http_error if http_error?
|
109
|
+
end
|
110
|
+
|
111
|
+
def xml_namespaces
|
112
|
+
@xml_namespaces ||= doc.collect_namespaces
|
113
|
+
end
|
114
|
+
|
115
|
+
def nori
|
116
|
+
return @nori if @nori
|
117
|
+
|
118
|
+
nori_options = {
|
119
|
+
:strip_namespaces => true,
|
120
|
+
:convert_tags_to => lambda { |tag| tag.snakecase.to_sym },
|
121
|
+
:advanced_typecasting => false
|
122
|
+
}
|
123
|
+
|
124
|
+
non_nil_nori_options = nori_options.reject { |_, value| value.nil? }
|
125
|
+
@nori = Nori.new(non_nil_nori_options)
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,252 @@
|
|
1
|
+
require "builder"
|
2
|
+
require "gyoku"
|
3
|
+
require "rexml/document"
|
4
|
+
require "nori"
|
5
|
+
|
6
|
+
require "ads_savon/soap"
|
7
|
+
|
8
|
+
module GoogleAdsSavon
|
9
|
+
module SOAP
|
10
|
+
|
11
|
+
# = GoogleAdsSavon::SOAP::XML
|
12
|
+
#
|
13
|
+
# Represents the SOAP request XML. Contains various global and per request/instance settings
|
14
|
+
# like the SOAP version, header, body and namespaces.
|
15
|
+
class XML
|
16
|
+
|
17
|
+
# XML Schema Type namespaces.
|
18
|
+
SCHEMA_TYPES = {
|
19
|
+
"xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
|
20
|
+
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance"
|
21
|
+
}
|
22
|
+
|
23
|
+
# Expects a +config+ object.
|
24
|
+
def initialize(config)
|
25
|
+
self.config = config
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_accessor :config
|
29
|
+
|
30
|
+
# Accessor for the SOAP +input+ tag.
|
31
|
+
attr_accessor :input
|
32
|
+
|
33
|
+
# Accessor for the SOAP +endpoint+.
|
34
|
+
attr_accessor :endpoint
|
35
|
+
|
36
|
+
# Sets the SOAP +version+.
|
37
|
+
def version=(version)
|
38
|
+
raise ArgumentError, "Invalid SOAP version: #{version}" unless SOAP::VERSIONS.include? version
|
39
|
+
@version = version
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the SOAP +version+. Defaults to <tt>GoogleAdsSavon.config.soap_version</tt>.
|
43
|
+
def version
|
44
|
+
@version ||= config.soap_version
|
45
|
+
end
|
46
|
+
|
47
|
+
# Sets the SOAP +header+ Hash.
|
48
|
+
attr_writer :header
|
49
|
+
|
50
|
+
# Returns the SOAP +header+. Defaults to an empty Hash.
|
51
|
+
def header
|
52
|
+
@header ||= config.soap_header.nil? ? {} : config.soap_header
|
53
|
+
end
|
54
|
+
|
55
|
+
# Sets the SOAP envelope namespace.
|
56
|
+
attr_writer :env_namespace
|
57
|
+
|
58
|
+
# Returns the SOAP envelope namespace. Uses the global namespace if set Defaults to :env.
|
59
|
+
def env_namespace
|
60
|
+
@env_namespace ||= config.env_namespace.nil? ? :env : config.env_namespace
|
61
|
+
end
|
62
|
+
|
63
|
+
# Sets the +namespaces+ Hash.
|
64
|
+
attr_writer :namespaces
|
65
|
+
|
66
|
+
# Returns the +namespaces+. Defaults to a Hash containing the SOAP envelope namespace.
|
67
|
+
def namespaces
|
68
|
+
@namespaces ||= begin
|
69
|
+
key = ["xmlns"]
|
70
|
+
key << env_namespace if env_namespace && env_namespace != ""
|
71
|
+
{ key.join(":") => SOAP::NAMESPACE[version] }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def namespace_by_uri(uri)
|
76
|
+
namespaces.each do |candidate_identifier, candidate_uri|
|
77
|
+
return candidate_identifier.gsub(/^xmlns:/, '') if candidate_uri == uri
|
78
|
+
end
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def used_namespaces
|
83
|
+
@used_namespaces ||= {}
|
84
|
+
end
|
85
|
+
|
86
|
+
def use_namespace(path, uri)
|
87
|
+
@internal_namespace_count ||= 0
|
88
|
+
|
89
|
+
unless identifier = namespace_by_uri(uri)
|
90
|
+
identifier = "ins#{@internal_namespace_count}"
|
91
|
+
namespaces["xmlns:#{identifier}"] = uri
|
92
|
+
@internal_namespace_count += 1
|
93
|
+
end
|
94
|
+
|
95
|
+
used_namespaces[path] = identifier
|
96
|
+
end
|
97
|
+
|
98
|
+
def types
|
99
|
+
@types ||= {}
|
100
|
+
end
|
101
|
+
|
102
|
+
# Sets the default namespace identifier.
|
103
|
+
attr_writer :namespace_identifier
|
104
|
+
|
105
|
+
# Returns the default namespace identifier.
|
106
|
+
def namespace_identifier
|
107
|
+
@namespace_identifier ||= :wsdl
|
108
|
+
end
|
109
|
+
|
110
|
+
# Accessor for whether all local elements should be namespaced.
|
111
|
+
attr_accessor :element_form_default
|
112
|
+
|
113
|
+
# Accessor for the default namespace URI.
|
114
|
+
attr_accessor :namespace
|
115
|
+
|
116
|
+
# Accessor for the <tt>GoogleAdsSavon::WSSE</tt> object.
|
117
|
+
attr_accessor :wsse
|
118
|
+
|
119
|
+
def signature?
|
120
|
+
wsse.respond_to?(:signature?) && wsse.signature?
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns the SOAP request encoding. Defaults to "UTF-8".
|
124
|
+
def encoding
|
125
|
+
@encoding ||= "UTF-8"
|
126
|
+
end
|
127
|
+
|
128
|
+
# Sets the SOAP request encoding.
|
129
|
+
attr_writer :encoding
|
130
|
+
|
131
|
+
# Accepts a +block+ and yields a <tt>Builder::XmlMarkup</tt> object to let you create
|
132
|
+
# custom body XML.
|
133
|
+
def body
|
134
|
+
@body = yield builder(nil) if block_given?
|
135
|
+
@body
|
136
|
+
end
|
137
|
+
|
138
|
+
# Sets the SOAP +body+. Expected to be a Hash that can be translated to XML via `Gyoku.xml`
|
139
|
+
# or any other Object responding to to_s.
|
140
|
+
attr_writer :body
|
141
|
+
|
142
|
+
# Accepts a +block+ and yields a <tt>Builder::XmlMarkup</tt> object to let you create
|
143
|
+
# a completely custom XML.
|
144
|
+
def xml(directive_tag = :xml, attrs = {})
|
145
|
+
@xml = yield builder(directive_tag, attrs) if block_given?
|
146
|
+
end
|
147
|
+
|
148
|
+
# Accepts an XML String and lets you specify a completely custom request body.
|
149
|
+
attr_writer :xml
|
150
|
+
|
151
|
+
# Returns the XML for a SOAP request.
|
152
|
+
def to_xml(clear_cache = false)
|
153
|
+
if clear_cache
|
154
|
+
@xml = nil
|
155
|
+
@header_for_xml = nil
|
156
|
+
end
|
157
|
+
|
158
|
+
@xml ||= tag(builder, :Envelope, complete_namespaces) do |xml|
|
159
|
+
tag(xml, :Header) { xml << header_for_xml } unless header_for_xml.empty?
|
160
|
+
|
161
|
+
# TODO: Maybe there should be some sort of plugin architecture where
|
162
|
+
# classes like WSSE::Signature can hook into this process.
|
163
|
+
body_attributes = (signature? ? wsse.signature.body_attributes : {})
|
164
|
+
|
165
|
+
if input.nil?
|
166
|
+
tag(xml, :Body, body_attributes)
|
167
|
+
else
|
168
|
+
tag(xml, :Body, body_attributes) { xml.tag!(*add_namespace_to_input) { xml << body_to_xml } }
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
# Returns a new <tt>Builder::XmlMarkup</tt> object.
|
176
|
+
def builder(directive_tag = :xml, attrs = { :encoding => encoding })
|
177
|
+
builder = Builder::XmlMarkup.new
|
178
|
+
builder.instruct!(directive_tag, attrs) if directive_tag
|
179
|
+
builder
|
180
|
+
end
|
181
|
+
|
182
|
+
# Expects a builder +xml+ instance, a tag +name+ and accepts optional +namespaces+
|
183
|
+
# and a block to create an XML tag.
|
184
|
+
def tag(xml, name, namespaces = {}, &block)
|
185
|
+
if env_namespace && env_namespace != ""
|
186
|
+
xml.tag! env_namespace, name, namespaces, &block
|
187
|
+
else
|
188
|
+
xml.tag! name, namespaces, &block
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# Returns the complete Hash of namespaces.
|
193
|
+
def complete_namespaces
|
194
|
+
defaults = SCHEMA_TYPES.dup
|
195
|
+
defaults["xmlns:#{namespace_identifier}"] = namespace if namespace
|
196
|
+
defaults.merge namespaces
|
197
|
+
end
|
198
|
+
|
199
|
+
# Returns the SOAP header as an XML String.
|
200
|
+
def header_for_xml
|
201
|
+
@header_for_xml ||= (Hash === header ? Gyoku.xml(header) : header) + wsse_header
|
202
|
+
end
|
203
|
+
|
204
|
+
# Returns the WSSE header or an empty String in case WSSE was not set.
|
205
|
+
def wsse_header
|
206
|
+
wsse.respond_to?(:to_xml) ? wsse.to_xml : ""
|
207
|
+
end
|
208
|
+
|
209
|
+
# Returns the SOAP body as an XML String.
|
210
|
+
def body_to_xml
|
211
|
+
return body.to_s unless body.kind_of? Hash
|
212
|
+
body_to_xml = element_form_default == :qualified ? add_namespaces_to_body(body) : body
|
213
|
+
Gyoku.xml body_to_xml, :element_form_default => element_form_default, :namespace => namespace_identifier
|
214
|
+
end
|
215
|
+
|
216
|
+
def add_namespaces_to_body(hash, path = [input[1].to_s])
|
217
|
+
return unless hash
|
218
|
+
return hash.map { |value| add_namespaces_to_body(value, path) } if hash.kind_of?(Array)
|
219
|
+
return hash.to_s unless hash.kind_of? Hash
|
220
|
+
|
221
|
+
hash.inject({}) do |newhash, (key, value)|
|
222
|
+
camelcased_key = Gyoku::XMLKey.create(key)
|
223
|
+
newpath = path + [camelcased_key]
|
224
|
+
|
225
|
+
if used_namespaces[newpath]
|
226
|
+
newhash.merge(
|
227
|
+
"#{used_namespaces[newpath]}:#{camelcased_key}" =>
|
228
|
+
add_namespaces_to_body(value, types[newpath] ? [types[newpath]] : newpath)
|
229
|
+
)
|
230
|
+
else
|
231
|
+
add_namespaces_to_values(value, path) if key == :order!
|
232
|
+
newhash.merge(key => value)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def add_namespace_to_input
|
238
|
+
return input.compact unless used_namespaces[[input[1].to_s]]
|
239
|
+
[used_namespaces[[input[1].to_s]], input[1], input[2]]
|
240
|
+
end
|
241
|
+
|
242
|
+
def add_namespaces_to_values(values, path)
|
243
|
+
values.collect! { |value|
|
244
|
+
camelcased_value = Gyoku::XMLKey.create(value)
|
245
|
+
namespace_path = path + [camelcased_value.to_s]
|
246
|
+
namespace = used_namespaces[namespace_path]
|
247
|
+
"#{namespace.blank? ? '' : namespace + ":"}#{camelcased_value}"
|
248
|
+
}
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|