Skip to content

Commit cbef805

Browse files
committed
Fix static analysis and code style issues
- Add native PHP 8.2+ type hints to all classes - Fix deprecated Nette API usage: - Use Nette\DI\Definitions\ServiceDefinition instead of Nette\DI\ServiceDefinition - Replace deprecated getUser()/getPassword() with Authorization header parsing - Use getMethod() instead of accessing private $methods property - Use IResponse::S401_Unauthorized instead of S401_UNAUTHORIZED - Fix PHPStan errors: - Add proper type narrowing for mixed types - Fix curl_exec result type handling - Fix CodeSniffer errors: - Replace array_walk with pass-by-reference to array_map - Update ruleset.xml to use element syntax for rootNamespaces - Add default 'GET' method for SapiRequestExtension
1 parent a265f8b commit cbef805

File tree

11 files changed

+104
-133
lines changed

11 files changed

+104
-133
lines changed

ruleset.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
<!-- Specific rules -->
77
<rule ref="SlevomatCodingStandard.Files.TypeNameMatchesFileName">
88
<properties>
9-
<property name="rootNamespaces" type="array" value="
10-
src=>Contributte\Http,
11-
tests=>Tests
12-
"/>
9+
<property name="rootNamespaces" type="array">
10+
<element key="src" value="Contributte\Http"/>
11+
<element key="tests" value="Tests"/>
12+
</property>
1313
</properties>
1414
</rule>
1515

src/Auth/BasicAuthenticator.php

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@
99
class BasicAuthenticator
1010
{
1111

12-
/** @var string */
13-
private $title;
12+
private string $title;
1413

15-
/** @var mixed[] */
16-
private $users = [];
14+
/** @var array<string, array{password: string, unsecured: bool}> */
15+
private array $users = [];
1716

1817
public function __construct(string $title)
1918
{
@@ -26,21 +25,21 @@ public function addUser(string $user, string $password, bool $unsecured): self
2625
'password' => $password,
2726
'unsecured' => $unsecured,
2827
];
28+
2929
return $this;
3030
}
3131

3232
public function authenticate(IRequest $request, IResponse $response): void
3333
{
34-
$user = $request->getUrl()->getUser();
35-
$password = $request->getUrl()->getPassword();
34+
[$user, $password] = $this->parseBasicAuth($request);
3635

3736
if (!$this->auth($user, $password)) {
3837
if (class_exists(Debugger::class)) {
3938
Debugger::$productionMode = true;
4039
}
4140

4241
$response->setHeader('WWW-Authenticate', sprintf('Basic realm="%s"', $this->title));
43-
$response->setCode(IResponse::S401_UNAUTHORIZED);
42+
$response->setCode(IResponse::S401_Unauthorized);
4443

4544
echo '<h1>Authentication failed.</h1>';
4645
die;
@@ -49,18 +48,36 @@ public function authenticate(IRequest $request, IResponse $response): void
4948

5049
protected function auth(string $user, string $password): bool
5150
{
52-
if (!isset($this->users[$user])) {
51+
if ($user === '' || !isset($this->users[$user])) {
5352
return false;
5453
}
5554

56-
if (
57-
($this->users[$user]['unsecured'] === true && !hash_equals($password, $this->users[$user]['password'])) ||
58-
($this->users[$user]['unsecured'] === false && !password_verify($password, $this->users[$user]['password']))
59-
) {
55+
$userData = $this->users[$user];
56+
if ($userData['unsecured'] && !hash_equals($password, $userData['password'])) {
6057
return false;
6158
}
6259

63-
return true;
60+
return $userData['unsecured'] || password_verify($password, $userData['password']);
61+
}
62+
63+
/**
64+
* Parse Basic auth credentials from request
65+
*
66+
* @return array{string, string}
67+
*/
68+
private function parseBasicAuth(IRequest $request): array
69+
{
70+
$header = $request->getHeader('Authorization');
71+
if ($header !== null && str_starts_with($header, 'Basic ')) {
72+
$credentials = base64_decode(substr($header, 6), true);
73+
if ($credentials !== false && str_contains($credentials, ':')) {
74+
$parts = explode(':', $credentials, 2);
75+
76+
return [$parts[0], $parts[1]];
77+
}
78+
}
79+
80+
return ['', ''];
6481
}
6582

6683
}

src/Client/FakeClient.php

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,14 @@ class FakeClient implements IClient
1111
{
1212

1313
/** @var Response[] */
14-
private $responses = [];
14+
private array $responses = [];
1515

16-
/** @var Response */
17-
private $defaultResponse;
16+
private Response $defaultResponse;
1817

1918
/** @var Request[] */
20-
private $recordedRequests = [];
19+
private array $recordedRequests = [];
2120

22-
/** @var bool */
23-
private $recordRequests = true;
21+
private bool $recordRequests = true;
2422

2523
public function __construct()
2624
{
@@ -216,10 +214,9 @@ public function get(string $url, array $headers = []): Response
216214
/**
217215
* Convenience method for POST requests
218216
*
219-
* @param mixed $body
220217
* @param string[] $headers
221218
*/
222-
public function post(string $url, $body = null, array $headers = []): Response
219+
public function post(string $url, mixed $body = null, array $headers = []): Response
223220
{
224221
$request = new Request($url, Request::METHOD_POST);
225222
$request->setHeaders($headers);
@@ -231,10 +228,9 @@ public function post(string $url, $body = null, array $headers = []): Response
231228
/**
232229
* Convenience method for PUT requests
233230
*
234-
* @param mixed $body
235231
* @param string[] $headers
236232
*/
237-
public function put(string $url, $body = null, array $headers = []): Response
233+
public function put(string $url, mixed $body = null, array $headers = []): Response
238234
{
239235
$request = new Request($url, Request::METHOD_PUT);
240236
$request->setHeaders($headers);

src/Client/IClient.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,16 @@ public function get(string $url, array $headers = []): Response;
2323
/**
2424
* Convenience method for POST requests
2525
*
26-
* @param mixed $body
2726
* @param string[] $headers
2827
*/
29-
public function post(string $url, $body = null, array $headers = []): Response;
28+
public function post(string $url, mixed $body = null, array $headers = []): Response;
3029

3130
/**
3231
* Convenience method for PUT requests
3332
*
34-
* @param mixed $body
3533
* @param string[] $headers
3634
*/
37-
public function put(string $url, $body = null, array $headers = []): Response;
35+
public function put(string $url, mixed $body = null, array $headers = []): Response;
3836

3937
/**
4038
* Convenience method for DELETE requests

src/Client/Request.php

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,17 @@ class Request
1616
public const METHOD_HEAD = 'HEAD';
1717
public const METHOD_OPTIONS = 'OPTIONS';
1818

19-
/** @var string */
20-
private $url;
19+
private string $url;
2120

22-
/** @var string */
23-
private $method;
21+
private string $method;
2422

2523
/** @var string[] */
26-
private $headers = [];
24+
private array $headers = [];
2725

28-
/** @var mixed */
29-
private $body;
26+
private mixed $body = null;
3027

3128
/** @var mixed[] */
32-
private $options = [];
29+
private array $options = [];
3330

3431
public function __construct(string $url, string $method = self::METHOD_GET)
3532
{
@@ -96,18 +93,12 @@ public function getHeader(string $name): ?string
9693
return $this->headers[$name] ?? null;
9794
}
9895

99-
/**
100-
* @return mixed
101-
*/
102-
public function getBody()
96+
public function getBody(): mixed
10397
{
10498
return $this->body;
10599
}
106100

107-
/**
108-
* @param mixed $body
109-
*/
110-
public function setBody($body): self
101+
public function setBody(mixed $body): self
111102
{
112103
$this->body = $body;
113104

@@ -132,10 +123,7 @@ public function setOptions(array $options): self
132123
return $this;
133124
}
134125

135-
/**
136-
* @param mixed $value
137-
*/
138-
public function setOption(string $key, $value): self
126+
public function setOption(string $key, mixed $value): self
139127
{
140128
$this->options[$key] = $value;
141129

@@ -144,9 +132,8 @@ public function setOption(string $key, $value): self
144132

145133
/**
146134
* @param int $key CURLOPT_* constant
147-
* @param mixed $value
148135
*/
149-
public function setCurlOption(int $key, $value): self
136+
public function setCurlOption(int $key, mixed $value): self
150137
{
151138
$this->options[$key] = $value;
152139

src/Client/Response.php

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,21 @@
88
class Response
99
{
1010

11-
/** @var mixed */
12-
private $body;
11+
private mixed $body;
1312

1413
/** @var string[] */
15-
private $headers;
14+
private array $headers;
1615

1716
/** @var mixed[] */
18-
private $info;
17+
private array $info;
1918

20-
/** @var mixed */
21-
private $error;
19+
private mixed $error = null;
2220

2321
/**
24-
* @param mixed $body
2522
* @param string[] $headers
2623
* @param mixed[] $info
2724
*/
28-
public function __construct($body = null, array $headers = [], array $info = [])
25+
public function __construct(mixed $body = null, array $headers = [], array $info = [])
2926
{
3027
$this->body = $body;
3128
$this->headers = $headers;
@@ -45,10 +42,7 @@ public function hasInfo(string $key): bool
4542
return isset($this->info[$key]);
4643
}
4744

48-
/**
49-
* @return mixed
50-
*/
51-
public function getInfo(string $key)
45+
public function getInfo(string $key): mixed
5246
{
5347
if ($this->hasInfo($key)) {
5448
return $this->info[$key];
@@ -79,10 +73,7 @@ public function getHeader(string $key): ?string
7973
return null;
8074
}
8175

82-
/**
83-
* @return mixed
84-
*/
85-
public function getBody()
76+
public function getBody(): mixed
8677
{
8778
return $this->body;
8879
}
@@ -99,25 +90,32 @@ public function isJson(): bool
9990
$contentType = $this->getHeader('Content-Type');
10091
}
10192

102-
return $contentType !== null && strpos($contentType, 'application/json') !== false;
93+
return is_string($contentType) && str_contains($contentType, 'application/json');
10394
}
10495

105-
/**
106-
* @return mixed
107-
*/
108-
public function getJsonBody()
96+
public function getJsonBody(): mixed
10997
{
11098
$body = $this->getBody();
111-
if ($body === null) {
99+
if (!is_string($body) || $body === '') {
112100
return null;
113101
}
114102

115-
return @json_decode((string) $this->getBody(), true);
103+
return json_decode($body, true);
116104
}
117105

118106
public function getStatusCode(): int
119107
{
120-
return $this->getInfo('http_code') ?? $this->getInfo('status_code') ?? 0;
108+
$httpCode = $this->getInfo('http_code');
109+
if (is_int($httpCode)) {
110+
return $httpCode;
111+
}
112+
113+
$statusCode = $this->getInfo('status_code');
114+
if (is_int($statusCode)) {
115+
return $statusCode;
116+
}
117+
118+
return 0;
121119
}
122120

123121
public function isOk(): bool
@@ -132,18 +130,12 @@ public function isSuccess(): bool
132130
return $code >= 200 && $code < 300;
133131
}
134132

135-
/**
136-
* @return mixed
137-
*/
138-
public function getError()
133+
public function getError(): mixed
139134
{
140135
return $this->error;
141136
}
142137

143-
/**
144-
* @param mixed $error
145-
*/
146-
public function setError($error): void
138+
public function setError(mixed $error): void
147139
{
148140
$this->error = $error;
149141
}

0 commit comments

Comments
 (0)