Completed
Push — master ( c74de3...47070b )
by Meng
22s queued 10s
created

RequestBuilder::setSoapMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Meng\Soap\HttpBinding;
4
5
use Psr\Http\Message\RequestFactoryInterface;
6
use Psr\Http\Message\RequestInterface;
7
use Psr\Http\Message\StreamFactoryInterface;
8
use Psr\Http\Message\StreamInterface;
9
10
/**
11
 * This class create PSR HTTP requests that embed SOAP messages.
12
 */
13
class RequestBuilder
14
{
15
    const SOAP11 = '1.1';
16
    const SOAP12 = '1.2';
17
18
    /**
19
     * @var string
20
     */
21
    private $endpoint;
22
    /**
23
     * @var string
24
     */
25
    private $soapVersion = self::SOAP11;
26
    /**
27
     * @var string
28
     */
29
    private $soapAction = '';
30
    /**
31
     * @var StreamInterface
32
     */
33
    private $soapMessage;
34
    /**
35
     * @var bool
36
     */
37
    private $hasSoapMessage = false;
38
    /**
39
     * @var string
40
     */
41
    private $httpMethod = 'POST';
42
    /**
43
     * @var StreamFactoryInterface
44
     */
45
    private $streamFactory;
46
    /**
47
     * @var RequestFactoryInterface
48
     */
49
    private $requestFactory;
50
51
    public function __construct(StreamFactoryInterface $streamFactory, RequestFactoryInterface $requestFactory)
52
    {
53
        $this->streamFactory = $streamFactory;
54
        $this->requestFactory = $requestFactory;
55
    }
56
57
    /**
58
     * @return RequestInterface
59
     * @throws RequestException
60
     */
61
    public function getSoapHttpRequest()
62
    {
63
        $this->validate();
64
        $headers = $this->prepareHeaders();
65
        $message = $this->prepareMessage();
66
        $request = $this->requestFactory->createRequest($this->httpMethod, $this->endpoint);
67
        foreach ($headers as $key => $value) {
68
            $request = $request->withHeader($key, $value);
69
        }
70
        $request = $request->withBody($message);
71
        $this->unsetAll();
72
        return $request;
73
    }
74
75
    /**
76
     * @param string $endpoint
77
     * @return self
78
     */
79
    public function setEndpoint($endpoint)
80
    {
81
        $this->endpoint = $endpoint;
82
        return $this;
83
    }
84
85
    /**
86
     * @return self
87
     */
88
    public function isSOAP11()
89
    {
90
        $this->soapVersion = self::SOAP11;
91
        return $this;
92
    }
93
94
    public function isSOAP12()
95
    {
96
        $this->soapVersion = self::SOAP12;
97
        return $this;
98
    }
99
100
101
    /**
102
     * @param string $soapAction
103
     * @return self
104
     */
105
    public function setSoapAction($soapAction)
106
    {
107
        $this->soapAction = $soapAction;
108
        return $this;
109
    }
110
111
    /**
112
     * @param StreamInterface $message
113
     * @return self
114
     */
115
    public function setSoapMessage(StreamInterface $message)
116
    {
117
        $this->soapMessage = $message;
118
        $this->hasSoapMessage = true;
119
        return $this;
120
    }
121
122
    /**
123
     * @param string $method
124
     * @return self
125
     */
126
    public function setHttpMethod($method)
127
    {
128
        $this->httpMethod = $method;
129
        return $this;
130
    }
131
132
    private function validate()
133
    {
134
        $isValid = true;
135
136
        if (!$this->endpoint) {
137
            $isValid = false;
138
        }
139
140
        if (!$this->hasSoapMessage && $this->httpMethod == 'POST') {
141
            $isValid = false;
142
        }
143
144
        /**
145
         * SOAP 1.1 only defines HTTP binding with POST method.
146
         * @link https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383527
147
         */
148
        if ($this->soapVersion == self::SOAP11 && $this->httpMethod != 'POST') {
149
            $isValid = false;
150
        }
151
152
        /**
153
         * SOAP 1.2 only defines HTTP binding with POST and GET methods.
154
         * @link https://www.w3.org/TR/2007/REC-soap12-part0-20070427/#L10309
155
         */
156
        if ($this->soapVersion == self::SOAP12 && !in_array($this->httpMethod, ['GET', 'POST'])) {
157
            $isValid = false;
158
        }
159
160
        if (!$isValid) {
161
            $this->unsetAll();
162
            throw new RequestException;
163
        }
164
    }
165
166
    /**
167
     * @return array
168
     */
169
    private function prepareHeaders()
170
    {
171
        if ($this->soapVersion == self::SOAP11) {
172
            return $this->prepareSoap11Headers();
173
        } else {
174
            return $this->prepareSoap12Headers();
175
        }
176
    }
177
178
    /**
179
     * @link https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383526
180
     * @return array
181
     */
182
    private function prepareSoap11Headers()
183
    {
184
        $headers = [];
185
        $headers['Content-Length'] = $this->soapMessage->getSize();
186
        $headers['SOAPAction'] = $this->soapAction;
187
        $headers['Content-Type'] = 'text/xml; charset="utf-8"';
188
        return $headers;
189
    }
190
191
    /**
192
     * SOSPAction header is removed in SOAP 1.2 and now expressed as a value of
193
     * an (optional) "action" parameter of the "application/soap+xml" media type.
194
     * @link https://www.w3.org/TR/soap12-part0/#L4697
195
     * @return array
196
     */
197
    private function prepareSoap12Headers()
198
    {
199
        $headers = [];
200
        if ($this->httpMethod == 'POST') {
201
            $headers['Content-Length'] = $this->soapMessage->getSize();
202
            $headers['Content-Type'] = 'application/soap+xml; charset="utf-8"' . '; action="' . $this->soapAction . '"';
203
        } else {
204
            $headers['Accept'] = 'application/soap+xml';
205
        }
206
        return $headers;
207
    }
208
209
    /**
210
     * @return StreamInterface
211
     */
212
    private function prepareMessage()
213
    {
214
        if ($this->httpMethod == 'POST') {
215
            return $this->soapMessage;
216
        } else {
217
            return $this->streamFactory->createStream();
218
        }
219
    }
220
221
    private function unsetAll()
222
    {
223
        $this->endpoint = null;
224
        if ($this->hasSoapMessage) {
225
            $this->soapMessage = null;
226
            $this->hasSoapMessage = false;
227
        }
228
        $this->soapAction = '';
229
        $this->soapVersion = self::SOAP11;
230
        $this->httpMethod = 'POST';
231
    }
232
}
233