Request::execute()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 9.568
c 0
b 0
f 0
cc 1
nc 1
nop 4
1
<?php
2
/**
3
 * @author: stev leibelt <[email protected]>
4
 * @since: 2015-12-09
5
 */
6
7
namespace Net\Bazzline\Component\Curl\Request;
8
9
use Net\Bazzline\Component\Curl\Dispatcher\DispatcherInterface;
10
use Net\Bazzline\Component\Curl\HeaderLine\HeaderLineInterface;
11
use Net\Bazzline\Component\Curl\Option\OptionInterface;
12
use Net\Bazzline\Component\Curl\Response\Response;
13
use Net\Bazzline\Component\Toolbox\HashMap\Merge;
14
15
class Request
16
{
17
    //@see: http://developer.sugarcrm.com/2013/08/30/doing-put-and-delete-with-curl-in-php/
18
    const HTTP_METHOD_DELETE    = 'DELETE';
19
    const HTTP_METHOD_GET       = 'GET';
20
    const HTTP_METHOD_PATCH     = 'PATCH';
21
    const HTTP_METHOD_POST      = 'POST';
22
    const HTTP_METHOD_PUT       = 'PUT';
23
24
    /** @var array */
25
    private $defaultHeaderLines = [];
26
27
    /** @var array */
28
    private $defaultOptions = [];
29
30
    /** @var DispatcherInterface */
31
    private $dispatcher;
32
33
    /** @var array */
34
    private $headerLines = [];
35
36
    /** @var Merge */
37
    private $merge;
38
39
    /** @var array */
40
    private $options = [];
41
42
    /**
43
     * @param DispatcherInterface $dispatcher
44
     * @param Merge $merge
45
     * @param array $defaultHeaderLines
46
     *  <int> => <value>
47
     * @param array $defaultOptions
48
     *  either:
49
     *      <int> => <value>
50
     *  or:
51
     *      <identifier> => <value>
52
     */
53
    public function __construct(DispatcherInterface $dispatcher, Merge $merge, array $defaultHeaderLines = [], array $defaultOptions = [])
54
    {
55
        $this->defaultHeaderLines   = $defaultHeaderLines;
56
        $this->defaultOptions       = $defaultOptions;
57
        $this->dispatcher           = $dispatcher;
58
        $this->merge                = $merge;
59
    }
60
61
    /**
62
     * @return Request
63
     */
64
    public function __clone()
65
    {
66
        return new self(
67
            $this->dispatcher,
68
            $this->merge,
69
            $this->defaultHeaderLines,
70
            $this->defaultOptions
71
        );
72
    }
73
74
    /**
75
     * @param HeaderLineInterface $line
76
     */
77
    public function addHeaderLine(HeaderLineInterface $line)
78
    {
79
        $this->headerLines[] = $line->line();
80
    }
81
82
    /**
83
     * @param OptionInterface $option
84
     */
85
    public function addOption(OptionInterface $option)
86
    {
87
        $this->options[$option->identifier()] = $option->value();
88
    }
89
90
    /**
91
     * @param string $line - CURLOPT_* - see: http://php.net/manual/en/function.curl-setopt.php
92
     */
93
    public function addRawHeaderLine($line)
94
    {
95
        $this->headerLines[] = $line;
96
    }
97
98
    /**
99
     * @param string $key - CURLOPT_* - see: http://php.net/manual/en/function.curl-setopt.php
100
     * @param mixed $value
101
     */
102
    public function addRawOption($key, $value)
103
    {
104
        $this->options[$key] = $value;
105
    }
106
107
    /**
108
     * @param string $url
109
     * @param array $parameters
110
     * @return Response
111
     */
112
    public function get($url, array $parameters = [])
113
    {
114
        return $this->execute(
115
            $url,
116
            self::HTTP_METHOD_GET,
117
            $parameters,
118
            []
119
        );
120
    }
121
122
    /**
123
     * @param string $url
124
     * @param array $parameters
125
     * @param null|string|array $data
126
     * @return Response
127
     */
128
    public function post($url, array $parameters = [], $data = null)
129
    {
130
        return $this->execute(
131
            $url,
132
            self::HTTP_METHOD_POST,
133
            $parameters,
134
            $data
135
        );
136
    }
137
138
    /**
139
     * @param string $url
140
     * @param array $parameters
141
     * @param null|string|array $data
142
     * @return Response
143
     */
144
    public function put($url, array $parameters = [], $data = null)
145
    {
146
        return $this->execute(
147
            $url,
148
            self::HTTP_METHOD_PUT,
149
            $parameters,
150
            $data
151
        );
152
    }
153
154
    /**
155
     * @param string $url
156
     * @param array $parameters
157
     * @param null|string|array $data
158
     * @return Response
159
     */
160
    public function patch($url, array $parameters = [], $data = null)
161
    {
162
        return $this->execute(
163
            $url,
164
            self::HTTP_METHOD_PATCH,
165
            $parameters,
166
            $data
167
        );
168
    }
169
170
    /**
171
     * @param string $url
172
     * @param array $parameters
173
     * @param null|string|array $data
174
     * @return Response
175
     */
176
    public function delete($url, array $parameters = [], $data = null)
177
    {
178
        return $this->execute(
179
            $url,
180
            self::HTTP_METHOD_DELETE,
181
            $parameters,
182
            $data
183
        );
184
    }
185
186
    /**
187
     * @see: https://de.wikipedia.org/wiki/Representational_State_Transfer
188
    public function head($url)
189
    {
190
    }
191
    public function options($url)
192
    {
193
    }
194
    public function trace($url)
195
    {
196
    }
197
     */
198
199
    /**
200
     * @param bool|false $alsoTheDefaults
201
     */
202
    public function reset($alsoTheDefaults = false)
203
    {
204
        $this->headerLines  = [];
205
        $this->options      = [];
206
207
        if ($alsoTheDefaults) {
208
            $this->defaultHeaderLines   = [];
209
            $this->defaultOptions       = [];
210
        }
211
    }
212
213
    /**
214
     * @param array $options
215
     * @param mixed $data
216
     * @return array
217
     */
218
    private function addDataToTheOptionsIfDataIsValid(array $options, $data)
219
    {
220
        $isDataProvided = (!is_null($data));
221
222
        if ($isDataProvided) {
223
            $dataIsNotFromTypeScalar   = (!is_scalar($data));
224
225
            if ($dataIsNotFromTypeScalar) {
226
                $data = http_build_query($data);
227
            }
228
229
            $dataStringContainsContent = (strlen($data) > 0);
230
231
            if ($dataStringContainsContent) {
232
                $options[CURLOPT_POSTFIELDS] = $data; //@see: http://www.lornajane.net/posts/2009/putting-data-fields-with-php-curl
233
            }
234
        }
235
236
        return $options;
237
    }
238
239
    /**
240
     * @param array $parameters
241
     * @param string $url
242
     * @return string
243
     */
244
    private function addParametersToTheUrlIfParametersAreProvided(array $parameters, $url)
245
    {
246
        $areParametersProvided = (!empty($parameters));
247
248
        if ($areParametersProvided) {
249
            $parametersAsString     = http_build_query($parameters);
250
            $isParameterStringValid = (strlen($parametersAsString) > 0);
251
252
            if ($isParameterStringValid) {
253
                $urlWithParameters = $url . '?' . http_build_query($parameters);
254
            } else {
255
                $urlWithParameters = $url;
256
            }
257
        } else {
258
            $urlWithParameters = $url;
259
        }
260
261
        return $urlWithParameters;
262
    }
263
264
    /**
265
     * @param string $url
266
     * @param string $method
267
     * @param null|array $parameters
268
     * @param null|string|array $data
269
     * @return Response
270
     */
271
    private function execute($url, $method, array $parameters = [], $data = null)
272
    {
273
        //begin of dependencies
274
        $dispatcher             = $this->dispatcher;
275
        $merge                  = $this->merge;
276
        $headerLines            = $merge($this->headerLines, $this->defaultHeaderLines);
277
        $options                = $merge($this->options, $this->defaultOptions);
278
        $headerLines[]          = 'X-HTTP-Method-Override: ' . $method; //@see: http://tr.php.net/curl_setopt#109634
279
        //end of dependencies
280
281
        //begin of business logic
282
        $options[CURLOPT_CUSTOMREQUEST] = $method; //@see: http://tr.php.net/curl_setopt#109634
283
        $options[CURLOPT_HTTPHEADER]    = $headerLines;
284
        //@todo what about binary transfer?
285
286
        $options            = $this->addDataToTheOptionsIfDataIsValid($options, $data);
287
        $urlWithParameters  = $this->addParametersToTheUrlIfParametersAreProvided($parameters, $url);
288
        $response           = $dispatcher->dispatch($urlWithParameters, $options);
289
        //end of business logic
290
291
        return $response;
292
    }
293
}
294