Skip to content

Commit 959a371

Browse files
authored
Merge pull request #3 from ddrv-fork/ci/add-psalm
add psalm
2 parents af9e42f + 82e1514 commit 959a371

13 files changed

+148
-47
lines changed

.gitattributes

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
*.md text eol=lf
2+
*.json text eol=lf
3+
*.php text eol=lf
4+
*.yml text eol=lf
5+
*.dist text eol=lf
6+
LICENCE text eol=lf
7+
.github/ export-ignore
8+
tests/ export-ignore
9+
stuff/ export-ignore
10+
*.dist export-ignore

.github/workflows/ci.yml

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
name: CI
22

3-
on: [push, pull_request]
3+
on:
4+
pull_request:
5+
branches:
6+
- master
7+
push:
8+
branches:
9+
- master
10+
tags-ignore:
11+
- v*
412

513
jobs:
614
tests:
@@ -29,5 +37,8 @@ jobs:
2937
- name: Check code style
3038
run: vendor/bin/phpcs
3139

40+
- name: Stat Analise
41+
run: vendor/bin/psalm
42+
3243
- name: Run test suite
3344
run: vendor/bin/phpunit

.github/workflows/release.yml

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Create release
2+
3+
on:
4+
push:
5+
tags:
6+
- v*
7+
8+
jobs:
9+
release:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Get version
13+
id: get-version
14+
uses: mad9000/actions-find-and-replace-string@2
15+
with:
16+
source: ${{ github.ref }}
17+
find: 'refs/tags/v'
18+
replace: ''
19+
20+
- name: Create Release
21+
id: create-release
22+
uses: actions/create-release@v1
23+
env:
24+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25+
with:
26+
tag_name: ${{ github.ref }}
27+
release_name: ${{ steps.get-version.outputs.value }}
28+
draft: false
29+
prerelease: false

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ vendor/
22
composer.lock
33
phpcs.xml
44
phpunit.xml
5+
psalm.xml

composer.json

+7-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"nyholm/psr7": "^1.5",
2222
"phpunit/phpunit": "^6.5 || ^7.5 || ^8.5 || ^9.5",
2323
"squizlabs/php_codesniffer": "^3.7",
24-
"webclient/fake-http-client": "^2.0"
24+
"webclient/fake-http-client": "^2.0",
25+
"vimeo/psalm": "^4.30"
2526
},
2627
"provide": {
2728
"psr/http-client-implementation": "1.0"
@@ -39,5 +40,10 @@
3940
"Stuff\\Webclient\\Extension\\Cookie\\": "stuff/",
4041
"Tests\\Webclient\\Extension\\Cookie\\": "tests/"
4142
}
43+
},
44+
"config": {
45+
"allow-plugins": {
46+
"composer/package-versions-deprecated": true
47+
}
4248
}
4349
}

psalm.xml.dist

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0"?>
2+
<psalm
3+
errorLevel="1"
4+
resolveFromConfigFile="true"
5+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6+
xmlns="https://getpsalm.org/schema/config"
7+
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
8+
>
9+
<projectFiles>
10+
<directory name="src" />
11+
<directory name="stuff" />
12+
<ignoreFiles>
13+
<directory name="vendor" />
14+
</ignoreFiles>
15+
</projectFiles>
16+
</psalm>

src/Cookie/ArrayStorage.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
final class ArrayStorage extends Storage
88
{
9-
public function save()
9+
public function save(): void
1010
{
1111
}
1212
}

src/Cookie/NetscapeCookieFile.php

+9-9
Original file line numberDiff line numberDiff line change
@@ -51,24 +51,24 @@ public function __construct(string $file)
5151
throw new InvalidArgumentException('Can not read file ' . $file, 1, $exception);
5252
}
5353
$lines = preg_split('/\r(\n)?/ui', $contents);
54-
foreach ($lines as $num => $line) {
54+
foreach ($lines as $line) {
5555
$line = trim($line);
5656
if (!$line || mb_substr($line, 0, 1) === '#') {
5757
continue;
5858
}
59-
$row = array_replace([null, 'FALSE', '/', 'FALSE', 0, null, null], str_getcsv($line, "\t"));
60-
$name = trim((string)$row[5]);
61-
$value = trim((string)$row[6]);
59+
$row = array_replace(['', 'FALSE', '/', 'FALSE', '0', '', ''], str_getcsv($line, "\t"));
60+
$name = trim($row[5]);
61+
$value = trim($row[6]);
6262
if (!$name || !$value) {
6363
continue;
6464
}
65-
$domain = trim((string)$row[0]);
65+
$domain = trim($row[0]);
6666
$domain = ltrim($domain, '.');
67-
if (mb_strtoupper(trim((string)$row[1])) === 'TRUE') {
67+
if (mb_strtoupper(trim($row[1])) === 'TRUE') {
6868
$domain = '.' . $domain;
6969
}
70-
$secure = mb_strtoupper(trim((string)$row[3])) === 'TRUE';
71-
$path = trim((string)$row[2]);
70+
$secure = mb_strtoupper(trim($row[3])) === 'TRUE';
71+
$path = trim($row[2]);
7272
$expired = (int)$row[4];
7373
if ($expired < 0) {
7474
$expired = 0;
@@ -77,7 +77,7 @@ public function __construct(string $file)
7777
}
7878
}
7979

80-
public function save()
80+
public function save(): void
8181
{
8282
$contents = '';
8383
foreach ($this->all() as $scheme => $domains) {

src/Cookie/Storage.php

+14-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,15 @@
88

99
abstract class Storage
1010
{
11+
/**
12+
* @var array<string, array<string, array<string, array{value: string, expired: int, path: string}>>>
13+
*/
1114
private array $cookies = [];
1215

16+
/**
17+
* @param UriInterface $uri
18+
* @return array<string, string>
19+
*/
1320
final public function get(UriInterface $uri): array
1421
{
1522
$cookies = [];
@@ -49,9 +56,9 @@ final public function set(
4956
string $value,
5057
string $domain,
5158
string $path = '/',
52-
$expire = 0,
53-
$secure = false
54-
) {
59+
int $expire = 0,
60+
bool $secure = false
61+
): void {
5562
$scheme = 'http' . ($secure ? 's' : '');
5663
$name = trim($name);
5764
if (!$name) {
@@ -81,8 +88,11 @@ final public function set(
8188
];
8289
}
8390

84-
abstract public function save();
91+
abstract public function save(): void;
8592

93+
/**
94+
* @return array<string, array<string, array<string, array{value: string, expired: int, path: string}>>>
95+
*/
8696
protected function all(): array
8797
{
8898
return $this->cookies;

src/CookieClientDecorator.php

+10-11
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,13 @@ public function sendRequest(RequestInterface $request): ResponseInterface
3030
if ($cookies) {
3131
if ($request->hasHeader('Cookie')) {
3232
foreach (explode(',', $request->getHeaderLine('Cookie')) as $line) {
33-
$line = trim($line);
34-
list($name, $value) = array_replace([null, null], explode('=', $line, 2));
35-
$name = trim($name);
36-
$value = trim($value);
37-
if (!$name || !$value) {
33+
[$headerCookieName, $headerCookieValue] = array_replace(['', ''], explode('=', trim($line), 2));
34+
$headerCookieName = trim($headerCookieName);
35+
$headerCookieValue = trim($headerCookieValue);
36+
if ($headerCookieName === '' || $headerCookieValue === '') {
3837
continue;
3938
}
40-
$cookies[$name] = $value;
39+
$cookies[$headerCookieName] = $headerCookieValue;
4140
}
4241
}
4342
foreach ($cookies as $cookie => $value) {
@@ -62,18 +61,18 @@ public function __destruct()
6261
* @param string $header
6362
* @param string $domain
6463
*/
65-
private function setCookieFromHeader(string $header, string $domain)
64+
private function setCookieFromHeader(string $header, string $domain): void
6665
{
6766
$arr = explode(';', $header);
6867
$cookies = [];
6968
$path = '/';
7069
$expires = 0;
7170
$secure = false;
7271
foreach ($arr as $item) {
73-
list($key, $value) = array_replace(['', ''], explode('=', $item, 2));
74-
$key = trim($key);
75-
$value = trim($value);
76-
switch (strtolower($key)) {
72+
$keyValue = explode('=', $item, 2);
73+
$key = strtolower(trim($keyValue[0]));
74+
$value = trim($keyValue[1] ?? '');
75+
switch ($key) {
7776
case 'domain':
7877
if ($value) {
7978
$domain = $value;

stuff/Handler.php

+19-13
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ public function handle(ServerRequestInterface $request): ResponseInterface
3232
if (!$path) {
3333
$path = '/';
3434
}
35-
foreach ($query['cookie'] as $name => $item) {
35+
36+
/** @var array<string, string> $queryCookies */
37+
$queryCookies = $query['cookie'];
38+
foreach ($queryCookies as $name => $item) {
3639
$cookies[$name]['value'] = $name . '=' . $item;
3740
$cookies[$name]['domain'] = 'Domain=' . $host;
3841
$cookies[$name]['path'] = 'Path=' . $path;
@@ -42,22 +45,25 @@ public function handle(ServerRequestInterface $request): ResponseInterface
4245
$cookies[$name]['secure'] = 'Secure';
4346
}
4447
}
45-
if (array_key_exists('subdomain', $query) && is_array($query['subdomain'])) {
46-
foreach ($query['subdomain'] as $name) {
47-
if (!array_key_exists($name, $cookies)) {
48-
continue;
49-
}
50-
$cookies[$name]['domain'] = 'Domain=.' . $host;
48+
49+
/** @var string[] $querySubdomain */
50+
$querySubdomain = (array)($query['subdomain'] ?? []);
51+
foreach ($querySubdomain as $name) {
52+
if (!array_key_exists($name, $cookies)) {
53+
continue;
5154
}
55+
$cookies[$name]['domain'] = 'Domain=.' . $host;
5256
}
53-
if (array_key_exists('temp', $query) && is_array($query['temp'])) {
54-
foreach ($query['temp'] as $name) {
55-
if (!array_key_exists($name, $cookies)) {
56-
continue;
57-
}
58-
unset($cookies[$name]['expired']);
57+
58+
/** @var string[] $queryTemp */
59+
$queryTemp = (array)($query['temp'] ?? []);
60+
foreach ($queryTemp as $name) {
61+
if (!array_key_exists($name, $cookies)) {
62+
continue;
5963
}
64+
unset($cookies[$name]['expired']);
6065
}
66+
6167
foreach ($cookies as $cookie) {
6268
$response = $response->withAddedHeader('Set-Cookie', implode('; ', $cookie));
6369
}

stuff/Storage.php

+11-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@
88

99
class Storage extends BaseStorage
1010
{
11+
/**
12+
* @return array<string, array{
13+
* value: string,
14+
* domain: string,
15+
* path: string,
16+
* httpOnly: bool,
17+
* secure: bool,
18+
* expired: int,
19+
* }>
20+
*/
1121
public function getItems(): array
1222
{
1323
$result = [];
@@ -28,7 +38,7 @@ public function getItems(): array
2838
return $result;
2939
}
3040

31-
public function save()
41+
public function save(): void
3242
{
3343
}
3444
}

tests/CookieClientTest.php

+9-6
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ class CookieClientTest extends TestCase
2323
*
2424
* @throws ClientExceptionInterface
2525
*/
26-
public function testSetToStorage(bool $secure, string $host, string $path)
26+
public function testSetToStorage(bool $secure, string $host, string $path): void
2727
{
28-
2928
$storage = new Storage();
3029

3130
$client = new CookieClientDecorator(new FakeHttpClient(new Handler()), $storage);
@@ -57,13 +56,13 @@ public function testSetToStorage(bool $secure, string $host, string $path)
5756

5857
/**
5958
* @param string $uri
60-
* @param array $expected
59+
* @param array<string, string> $expected
6160
*
6261
* @dataProvider provideGetFromStorage
6362
*
6463
* @throws ClientExceptionInterface
6564
*/
66-
public function testGetFromStorage(string $uri, array $expected)
65+
public function testGetFromStorage(string $uri, array $expected): void
6766
{
6867
$set = [
6968
[
@@ -134,11 +133,12 @@ public function testGetFromStorage(string $uri, array $expected)
134133
$request = new Request('GET', $uri, ['Accept' => 'text/plain']);
135134
$response = $client->sendRequest($request);
136135
$json = $response->getBody()->__toString();
136+
/** @var array<string, string> $cookies */
137137
$cookies = json_decode($json, true);
138138
$this->assertCount(count($expected), $cookies);
139139
foreach ($expected as $name => $value) {
140140
$this->assertArrayHasKey($name, $cookies);
141-
$this->assertSame($value, $cookies[$name]);
141+
$this->assertSame($value, $cookies[$name] ?? null);
142142
}
143143
}
144144

@@ -150,6 +150,9 @@ public function provideSetToStorage(): array
150150
];
151151
}
152152

153+
/**
154+
* @return array{0: string, 1: array<string, string>}[]
155+
*/
153156
public function provideGetFromStorage(): array
154157
{
155158
return [
@@ -169,7 +172,7 @@ private function assertStoredCookie(
169172
string $path,
170173
bool $secure,
171174
bool $temporary
172-
) {
175+
): void {
173176
$this->assertSame($value, $cookie['value']);
174177
$this->assertSame($domain, $cookie['domain']);
175178
$this->assertSame($path, $cookie['path']);

0 commit comments

Comments
 (0)