Completed
Push — master ( ba8d7f...08dee8 )
by Meng
02:59
created

RequestBuilder::validate()   C

Complexity

Conditions 11
Paths 64

Size

Total Lines 37
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 37
rs 5.2653
cc 11
eloc 15
nc 64
nop 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Meng\Soap\HttpBinding;
4
5
use Psr\Http\Message\RequestInterface;
6
use Psr\Http\Message\StreamInterface;
7
use Zend\Diactoros\Request;
8
use Zend\Diactoros\Stream;
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
    /**
44
     * @return RequestInterface
45
     */
46
    public function getSoapHttpRequest()
47
    {
48
        $this->validate();
49
        $headers = $this->prepareHeaders();
50
        $message = $this->prepareMessage();
51
        $request = new Request(
52
            $this->endpoint,
53
            $this->httpMethod,
54
            $message,
55
            $headers
56
        );
57
        $this->unsetAll();
58
        return $request;
59
    }
60
61
    /**
62
     * @param string $endpoint
63
     * @return self
64
     */
65
    public function setEndpoint($endpoint)
66
    {
67
        $this->endpoint = $endpoint;
68
        return $this;
69
    }
70
71
    /**
72
     * @return self
73
     */
74
    public function isSOAP11()
75
    {
76
        $this->soapVersion = self::SOAP11;
77
        return $this;
78
    }
79
80
    public function isSOAP12()
81
    {
82
        $this->soapVersion = self::SOAP12;
83
        return $this;
84
    }
85
86
87
    /**
88
     * @param string $soapAction
89
     * @return self
90
     */
91
    public function setSoapAction($soapAction)
92
    {
93
        $this->soapAction = $soapAction;
94
        return $this;
95
    }
96
97
    /**
98
     * @param StreamInterface $message
99
     * @return self
100
     */
101
    public function setSoapMessage($message)
102
    {
103
        $this->soapMessage = $message;
104
        $this->hasSoapMessage = true;
105
        return $this;
106
    }
107
108
    /**
109
     * @param string $method
110
     * @return self
111
     */
112
    public function setHttpMethod($method)
113
    {
114
        $this->httpMethod = $method;
115
        return $this;
116
    }
117
118
    private function validate()
119
    {
120
        $isValid = true;
121
122
        if (!$this->endpoint) {
123
            $isValid = false;
124
        }
125
126
        if (!$this->hasSoapMessage && $this->httpMethod == 'POST') {
127
            $isValid = false;
128
        }
129
130
        if ($this->hasSoapMessage && !$this->soapMessage instanceof StreamInterface) {
131
            $isValid = false;
132
        }
133
134
        /**
135
         * SOAP 1.1 only defines HTTP binding with POST method.
136
         * @link https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383527
137
         */
138
        if ($this->soapVersion == self::SOAP11 && $this->httpMethod != 'POST') {
139
            $isValid = false;
140
        }
141
142
        /**
143
         * SOAP 1.2 only defines HTTP binding with POST and GET methods.
144
         * @link https://www.w3.org/TR/2007/REC-soap12-part0-20070427/#L10309
145
         */
146
        if ($this->soapVersion == self::SOAP12 && !in_array($this->httpMethod, ['GET', 'POST'])) {
147
            $isValid = false;
148
        }
149
150
        if (!$isValid) {
151
            $this->unsetAll();
152
            throw new RequestException;
153
        }
154
    }
155
156
    /**
157
     * @return array
158
     */
159
    private function prepareHeaders()
160
    {
161
        if ($this->soapVersion == self::SOAP11) {
162
            return $this->prepareSoap11Headers();
163
        } else {
164
            return $this->prepareSoap12Headers();
165
        }
166
    }
167
168
    /**
169
     * @link https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383526
170
     * @return array
171
     */
172
    private function prepareSoap11Headers()
173
    {
174
        $headers = [];
175
        $headers['Content-Length'] = strlen($this->soapMessage->getContents());
176
        $headers['SOAPAction'] = $this->soapAction;
177
        $headers['Content-Type'] = 'text/xml; charset="utf-8"';
178
        return $headers;
179
    }
180
181
    /**
182
     * SOSPAction header is removed in SOAP 1.2 and now expressed as a value of
183
     * an (optional) "action" parameter of the "application/soap+xml" media type.
184
     * @link https://www.w3.org/TR/soap12-part0/#L4697
185
     * @return array
186
     */
187
    private function prepareSoap12Headers()
188
    {
189
        $headers = [];
190
        if ($this->httpMethod == 'POST') {
191
            $headers['Content-Length'] = strlen($this->soapMessage->getContents());
192
            $headers['Content-Type'] = 'application/soap+xml; charset="utf-8"' . '; action="' . $this->soapAction . '"';
193
        } else {
194
            $headers['Accept'] = 'application/soap+xml';
195
        }
196
        return $headers;
197
    }
198
199
    /**
200
     * @return StreamInterface
201
     */
202
    private function prepareMessage()
203
    {
204
        if ($this->httpMethod == 'POST') {
205
            return $this->soapMessage;
206
        } else {
207
            return new Stream(fopen('php://temp', 'r'));
208
        }
209
    }
210
211
    private function unsetAll()
212
    {
213
        $this->endpoint = null;
214
        if ($this->hasSoapMessage) {
215
            $this->soapMessage = null;
216
            $this->hasSoapMessage = false;
217
        }
218
        $this->soapAction = '';
219
        $this->soapVersion = self::SOAP11;
220
        $this->httpMethod = 'POST';
221
    }
222
}