Completed
Pull Request — develop (#2)
by Sebastian
02:16
created

CurlHttpRunner   C

Complexity

Total Complexity 8

Size/Duplication

Total Lines 145
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 19

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 8
lcom 1
cbo 19
dl 0
loc 145
rs 6.875
c 1
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 1
A addRequest() 0 16 2
A run() 0 7 1
A onSuccess() 0 20 1
A onError() 0 22 1
A convertToHeaderCollection() 0 10 2
1
<?php
2
namespace DjThossi\SmokeTestingPhp\Runner;
3
4
use Curl\CaseInsensitiveArray;
5
use Curl\Curl;
6
use Curl\MultiCurl;
7
use DjThossi\SmokeTestingPhp\Collection\HeaderCollection;
8
use DjThossi\SmokeTestingPhp\Collection\ResultCollection;
9
use DjThossi\SmokeTestingPhp\Options\RequestOptions;
10
use DjThossi\SmokeTestingPhp\Result\ErrorResult;
11
use DjThossi\SmokeTestingPhp\Result\ValidResult;
12
use DjThossi\SmokeTestingPhp\ValueObject\Body;
13
use DjThossi\SmokeTestingPhp\ValueObject\BodyLength;
14
use DjThossi\SmokeTestingPhp\ValueObject\Concurrency;
15
use DjThossi\SmokeTestingPhp\ValueObject\ErrorMessage;
16
use DjThossi\SmokeTestingPhp\ValueObject\Header;
17
use DjThossi\SmokeTestingPhp\ValueObject\HeaderKey;
18
use DjThossi\SmokeTestingPhp\ValueObject\HeaderValue;
19
use DjThossi\SmokeTestingPhp\ValueObject\StatusCode;
20
use DjThossi\SmokeTestingPhp\ValueObject\TimeToFirstByte;
21
use DjThossi\SmokeTestingPhp\ValueObject\Url;
22
23
class CurlHttpRunner implements HttpRunner
24
{
25
    /**
26
     * @var BodyLength
27
     */
28
    private $bodyLength;
29
30
    /**
31
     * @var MultiCurl
32
     */
33
    private $multiCurl;
34
35
    /**
36
     * @var ResultCollection
37
     */
38
    private $results;
39
40
    /**
41
     * @var callable
42
     */
43
    private $successCallback;
44
45
    /**
46
     * @var callable
47
     */
48
    private $errorCallback;
49
50
    /**
51
     * @param Concurrency $concurrency
52
     * @param BodyLength $bodyLength
53
     * @param callable $successCallback
54
     * @param callable $errorCallback
55
     */
56
    public function __construct(
57
        Concurrency $concurrency,
58
        BodyLength $bodyLength,
59
        callable $successCallback,
60
        callable $errorCallback
61
    ) {
62
        $this->multiCurl = new MultiCurl();
63
        $this->multiCurl->setConcurrency($concurrency->asInteger());
64
        $this->multiCurl->success([$this, 'onSuccess']);
65
        $this->multiCurl->error([$this, 'onError']);
66
        $this->bodyLength = $bodyLength;
67
        $this->successCallback = $successCallback;
68
        $this->errorCallback = $errorCallback;
69
    }
70
71
    /**
72
     * @param RequestOptions $requestOptions
73
     */
74
    public function addRequest(RequestOptions $requestOptions)
75
    {
76
        $curl = new Curl();
77
        $curl->setUrl($requestOptions->getUrl()->asString());
78
        $curl->setTimeout($requestOptions->getRequestTimeout()->inSeconds());
79
        $curl->setOpt(CURLOPT_FOLLOWLOCATION, $requestOptions->getFollowRedirect()->asBoolean());
80
81
        if ($requestOptions->needsBasicAuth()) {
82
            $curl->setBasicAuthentication(
83
                $requestOptions->getBasicAuth()->getUsername(),
84
                $requestOptions->getBasicAuth()->getPassword()
85
            );
86
        }
87
88
        $this->multiCurl->addCurl($curl);
89
    }
90
91
    /**
92
     * @return ResultCollection
93
     */
94
    public function run()
95
    {
96
        $this->results = new ResultCollection();
97
        $this->multiCurl->start();
98
99
        return $this->results;
100
    }
101
102
    /**
103
     * @param Curl $curl
104
     */
105
    public function onSuccess(Curl $curl)
106
    {
107
        $curlInfo = $curl->getInfo();
108
        $timeToFirstByte = $curlInfo['starttransfer_time'] - $curlInfo['pretransfer_time'];
109
        $inMilliseconds = (int) round($timeToFirstByte * 1000);
110
111
        $body = substr($curl->response, 0, $this->bodyLength->asInteger());
112
113
        $validResult = new ValidResult(
114
            new Url($curl->url),
115
            $this->convertToHeaderCollection($curl->responseHeaders),
116
            new Body($body),
117
            new TimeToFirstByte($inMilliseconds),
118
            new StatusCode($curl->httpStatusCode)
119
        );
120
121
        call_user_func($this->successCallback, $validResult);
122
123
        $this->results->addResult($validResult);
124
    }
125
126
    /**
127
     * @param Curl $curl
128
     */
129
    public function onError(Curl $curl)
130
    {
131
        $url = new Url($curl->url);
132
133
        $errorMessage = new ErrorMessage(
134
            sprintf(
135
                'Curl Code: %s Error: %s',
136
                $curl->errorCode,
137
                $curl->errorMessage
138
            )
139
        );
140
141
        $errorResult = new ErrorResult(
142
            $url,
143
            $this->convertToHeaderCollection($curl->responseHeaders),
144
            $errorMessage
145
        );
146
147
        call_user_func($this->errorCallback, $errorResult);
148
149
        $this->results->addResult($errorResult);
150
    }
151
152
    /**
153
     * @param CaseInsensitiveArray $headers
154
     *
155
     * @return HeaderCollection
156
     */
157
    private function convertToHeaderCollection(CaseInsensitiveArray $headers)
158
    {
159
        $headerCollection = new HeaderCollection();
160
        foreach ($headers as $key => $value) {
161
            $header = new Header(new HeaderKey($key), new HeaderValue($value));
162
            $headerCollection->addHeader($header);
163
        }
164
165
        return $headerCollection;
166
    }
167
}
168