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