Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.72% covered (success)
98.72%
77 / 78
91.67% covered (success)
91.67%
11 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
Http
98.72% covered (success)
98.72%
77 / 78
91.67% covered (success)
91.67%
11 / 12
31
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
4
 setUserInfo
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getUserInfo
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 readResponse
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
4
 getAuthorizedRequest
90.91% covered (success)
90.91%
10 / 11
0.00% covered (danger)
0.00%
0 / 1
6.03
 setApiKey
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setWorkflowKey
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 readGetResult
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 readPostResult
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 readDeleteResult
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 readResult
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
5
 createRequest
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace BO\Zmsclient;
4
5use Psr\Http\Message\RequestInterface;
6use Psr\Http\Message\UriInterface;
7use Psr\Http\Client\ClientInterface;
8use Slim\Psr7\Headers;
9
10/**
11 * Adapter & Decorator Class to use the Psr7\Client
12 *
13 * Access api method_exists
14 * @SuppressWarnings(Coupling)
15 */
16class Http
17{
18    /**
19     * @var ClientInterface|null
20     */
21    protected $client = null;
22
23    /**
24     * @var string
25     */
26    protected $http_baseurl = '';
27
28    /**
29     * @var bool
30     * with authentification request if true
31     */
32    public static $authEnabled = true;
33
34    /**
35     * @var Psr7\Uri|null
36     */
37    protected $uri = null;
38
39    /**
40     * @var bool
41     * Log requests and responses if true
42     */
43    public static $logEnabled = true;
44
45    /**
46     * @var array
47     * Contains a list of requests and responses if logging is enabled
48     */
49    public static $log = [];
50
51    /**
52     * @var string|null
53     */
54    protected $apikeyString = null;
55
56    /**
57     * @var string|null
58     */
59    protected $workflowkeyString = null;
60
61    /**
62     * @var int|null
63     */
64    public static $jsonCompressLevel = null;
65
66    /**
67     *
68     * @param ClientInterface $client
69     */
70    public function __construct($baseUrl, ClientInterface $client = null)
71    {
72        $this->http_baseurl = parse_url($baseUrl, PHP_URL_PATH) ?? '';
73        $this->uri = new Psr7\Uri();
74        $this->uri = $this->uri->withScheme(parse_url($baseUrl, PHP_URL_SCHEME) ?? '');
75        $this->uri = $this->uri->withHost(parse_url($baseUrl, PHP_URL_HOST) ?? '');
76        $port = parse_url($baseUrl, PHP_URL_PORT);
77        if ($port) {
78            $this->uri = $this->uri->withPort($port);
79        }
80        $user = parse_url($baseUrl, PHP_URL_USER);
81        $pass = parse_url($baseUrl, PHP_URL_PASS);
82        if ($user) {
83            $this->setUserInfo($user, $pass);
84        }
85        if (null === $client) {
86            $client = new Psr7\Client();
87        }
88        $this->client = $client;
89    }
90
91    public function setUserInfo($user, $pass)
92    {
93        $this->uri = $this->uri->withUserInfo($user, $pass);
94        return $this;
95    }
96
97    public function getUserInfo()
98    {
99        return $this->uri->getUserInfo();
100    }
101
102    /**
103     * Start request and fetch response
104     * The request is extended by auth informations
105     *
106     * @param \Psr\Http\Message\RequestInterface $request
107     *
108     * @return \Psr\Http\Message\ResponseInterface
109     */
110    public function readResponse(RequestInterface $request)
111    {
112        if (static::$authEnabled) {
113            $request = $this->getAuthorizedRequest($request);
114        }
115        if (null !== static::$jsonCompressLevel) {
116            $request = $request->withHeader('X-JsonCompressLevel', static::$jsonCompressLevel);
117        }
118        $startTime = microtime(true);
119        $response = $this->client->readResponse($request);
120        if (self::$logEnabled) {
121            self::$log[] = $request;
122            self::$log[] = $response;
123            $responseSizeKb = round(strlen($response->getBody()->getContents()) / 1024);
124            self::$log[] = "Response ($responseSizeKb kb) time in s: " . round(microtime(true) - $startTime, 3);
125        }
126        return $response;
127    }
128
129    /**
130     * Extend the request by auth informations
131     *
132     * @param \Psr\Http\Message\RequestInterface $request
133     *
134     * @return \Psr\Http\Message\RequestInterface
135     */
136    public function getAuthorizedRequest(RequestInterface $request)
137    {
138        $userInfo = $request->getUri()->getUserInfo();
139        $xAuthKey = Auth::getKey();
140        if (null !== $xAuthKey && ! $userInfo) {
141            $request = $request->withHeader('X-Authkey', $xAuthKey);
142        } elseif ($userInfo) {
143            $request = $request->withHeader('Authorization', 'Basic ' . base64_encode($userInfo));
144        }
145        if (null !== $this->apikeyString) {
146            $request = $request->withHeader('X-Api-Key', $this->apikeyString);
147        }
148        if (null !== $this->workflowkeyString) {
149            $request = $request->withHeader('X-Workflow-Key', $this->workflowkeyString);
150        }
151
152        return $request;
153    }
154
155    public function setApiKey($apikeyString)
156    {
157        $this->apikeyString = $apikeyString;
158        return $this;
159    }
160
161    public function setWorkflowKey($apikeyString)
162    {
163        $this->workflowkeyString = $apikeyString;
164        return $this;
165    }
166
167    /**
168     * Creates a GET-Http-Request and fetches the response
169     *
170     * @param string $relativeUrl
171     * @param array|null $getParameters (optional)
172     *
173     * @return Result
174     */
175    public function readGetResult($relativeUrl, array $getParameters = null, $xToken = null)
176    {
177        $uri = $this->uri->withPath($this->http_baseurl . $relativeUrl);
178        if (null !== $getParameters) {
179            $uri = $uri->withQuery(http_build_query($getParameters));
180        }
181        $request = self::createRequest('GET', $uri);
182
183        if (null !== $xToken) {
184            $request = $request->withHeader('X-Token', $xToken);
185        }
186
187        return $this->readResult($request);
188    }
189
190    /**
191     * Creates a POST-Http-Request and fetches the response
192     *
193     * @param string $relativeUrl
194     * @param \BO\Zmsentities\Schema\Entity $entity
195     * @param array $getParameters (optional)
196     *
197     * @return Result
198     */
199    public function readPostResult($relativeUrl, $entity, array $getParameters = null)
200    {
201        $uri = $this->uri->withPath($this->http_baseurl . $relativeUrl);
202        if (null !== $getParameters) {
203            $uri = $uri->withQuery(http_build_query($getParameters));
204        }
205        $request = self::createRequest('POST', $uri);
206        $body = new Psr7\Stream();
207        $body->write(json_encode($entity));
208        $request = $request->withBody($body);
209
210        return $this->readResult($request);
211    }
212
213    /**
214     * Creates a DELETE-Http-Request and fetches the response
215     *
216     * @param string $relativeUrl
217     * @param array $getParameters (optional)
218     *
219     * @return Result
220     */
221    public function readDeleteResult($relativeUrl, array $getParameters = null)
222    {
223        $uri = $this->uri->withPath($this->http_baseurl . $relativeUrl);
224        if (null !== $getParameters) {
225            $uri = $uri->withQuery(http_build_query($getParameters));
226        }
227        $request = self::createRequest('DELETE', $uri);
228        return $this->readResult($request);
229    }
230
231    protected function readResult(
232        RequestInterface $request = null,
233        $try = 0
234    ) {
235        $response = $this->readResponse($request);
236        $result = new Result($response, $request);
237        if ($response->getStatuscode() == 500) {
238            try {
239                $result->getData();
240            } catch (Exception $exception) {
241                if (
242                    $try < 3 && in_array($exception->template, [
243                    "BO\\Zmsdb\\Exception\\Pdo\\DeadLockFound",
244                    "BO\\Zmsdb\\Exception\\Pdo\\LockTimeout",
245                    ])
246                ) {
247                    usleep(rand(1000000, 3000000));
248                    return $this->readResult($request, $try + 1);
249                }
250            }
251        }
252        return $result;
253    }
254
255    public static function createRequest(string $method, UriInterface $uri): RequestInterface
256    {
257        $request = new Psr7\Request($method, $uri, 'php://memory', new Headers([], []));
258        return $request;
259    }
260}