Skip to content

Commit 277ac8d

Browse files
authored
Phpstan level7 (#2)
* Simplify array structure * Remove array merges in favor of explicit options * Split allowAll options * Tweak array type * Revert "Tweak array type" This reverts commit 4738baf. * Add explicit cast * Skip check on lowest symfony 4 * Skip check on lowest symfony 4 * Skip check on lowest symfony 4 * SKip * SKip
1 parent 84d0d02 commit 277ac8d

File tree

6 files changed

+55
-82
lines changed

6 files changed

+55
-82
lines changed

.github/workflows/run-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646

4747
- name: Analyse with PHPStan
4848
run: composer analyse
49-
if: matrix.os == 'ubuntu-latest'
49+
if: matrix.os == 'ubuntu-latest' && matrix.symfony != '4.x'
5050

5151
- name: Check PSR-12 Codestyle
5252
run: composer test

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
},
3333
"scripts": {
3434
"test": "phpunit",
35-
"analyse": "phpstan analyse src tests --level=6",
35+
"analyse": "phpstan analyse src tests --level=7",
3636
"check-style": "phpcs -p --standard=PSR12 --exclude=Generic.Files.LineLength --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 src tests",
3737
"fix-style": "phpcbf -p --standard=PSR12 --exclude=Generic.Files.LineLength --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 src tests"
3838
},

src/CorsService.php

Lines changed: 45 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,33 @@
1818

1919
/**
2020
* @phpstan-type CorsInputOptions array{
21-
* 'allowedOrigins'?: array{string}|array{},
22-
* 'allowedOriginsPatterns'?: array{string}|array{},
21+
* 'allowedOrigins'?: string[],
22+
* 'allowedOriginsPatterns'?: string[],
2323
* 'supportsCredentials'?: bool,
24-
* 'allowedHeaders'?: array{string}|array{},
25-
* 'allowedMethods'?: array{string}|array{},
26-
* 'exposedHeaders'?: array{string}|array{},
24+
* 'allowedHeaders'?: string[],
25+
* 'allowedMethods'?: string[],
26+
* 'exposedHeaders'?: string[]|false,
2727
* 'maxAge'?: int|bool|null,
28-
* 'allowed_origins'?: array{string}|array{},
29-
* 'allowed_origins_patterns'?: array{string}|array{},
28+
* 'allowed_origins'?: string[],
29+
* 'allowed_origins_patterns'?: string[],
3030
* 'supports_credentials'?: bool,
31-
* 'allowed_headers'?: array{string}|array{},
32-
* 'allowed_methods'?: array{string}|array{},
33-
* 'exposed_headers'?: array{string}|array{},
31+
* 'allowed_headers'?: string[],
32+
* 'allowed_methods'?: string[],
33+
* 'exposed_headers'?: string[]|false,
3434
* 'max_age'?: int|bool|null
3535
* }
3636
*
3737
* @phpstan-type CorsNormalizedOptions array{
38-
* 'allowedOrigins': array{string}|array{}|true,
39-
* 'allowedOriginsPatterns': array{string}|array{},
38+
* 'allowedOrigins': string[],
39+
* 'allowedOriginsPatterns': string[],
4040
* 'supportsCredentials': bool,
41-
* 'allowedHeaders': array{string}|array{}|bool,
42-
* 'allowedMethods': array{string}|array{}|bool,
43-
* 'exposedHeaders': array{string}|array{},
44-
* 'maxAge': int|bool|null
41+
* 'allowedHeaders': string[],
42+
* 'allowedMethods': string[],
43+
* 'exposedHeaders': string[],
44+
* 'maxAge': int|bool|null,
45+
* 'allowAllOrigins': bool,
46+
* 'allowAllHeaders': bool,
47+
* 'allowAllMethods': bool,
4548
* }
4649
*/
4750
class CorsService
@@ -63,34 +66,18 @@ public function __construct(array $options = [])
6366
*/
6467
private function normalizeOptions(array $options = []): array
6568
{
66-
$aliases = [
67-
'supports_credentials' => 'supportsCredentials',
68-
'allowed_origins' => 'allowedOrigins',
69-
'allowed_origins_patterns' => 'allowedOriginsPatterns',
70-
'allowed_headers' => 'allowedHeaders',
71-
'allowed_methods' => 'allowedMethods',
72-
'exposed_headers' => 'exposedHeaders',
73-
'max_age' => 'maxAge',
74-
];
75-
76-
// Normalize underscores
77-
foreach ($aliases as $alias => $option) {
78-
if (isset($options[$alias])) {
79-
$options[$option] = $options[$alias];
80-
unset($options[$alias]);
81-
}
69+
$options['allowedOrigins'] = $options['allowedOrigins'] ?? $options['allowed_origins'] ?? [];
70+
$options['allowedOriginsPatterns'] =
71+
$options['allowedOriginsPatterns'] ?? $options['allowed_origins_patterns'] ?? [];
72+
$options['allowedMethods'] = $options['allowedMethods'] ?? $options['allowed_methods'] ?? [];
73+
$options['allowedHeaders'] = $options['allowedHeaders'] ?? $options['allowed_headers'] ?? [];
74+
$options['exposedHeaders'] = $options['exposedHeaders'] ?? $options['exposed_headers'] ?? [];
75+
$options['supportsCredentials'] = $options['supportsCredentials'] ?? $options['supports_credentials'] ?? false;
76+
77+
if (!array_key_exists('maxAge', $options)) {
78+
$options['maxAge'] = array_key_exists('max_age', $options) ? $options['max_age'] : 0;
8279
}
8380

84-
$options += [
85-
'allowedOrigins' => [],
86-
'allowedOriginsPatterns' => [],
87-
'supportsCredentials' => false,
88-
'allowedHeaders' => [],
89-
'exposedHeaders' => [],
90-
'allowedMethods' => [],
91-
'maxAge' => 0,
92-
];
93-
9481
if ($options['exposedHeaders'] === false) {
9582
$options['exposedHeaders'] = [];
9683
}
@@ -115,21 +102,14 @@ private function normalizeOptions(array $options = []): array
115102
}
116103
}
117104

118-
// normalize array('*') to true
119-
if (in_array('*', $options['allowedOrigins'])) {
120-
$options['allowedOrigins'] = true;
121-
}
122-
if (in_array('*', $options['allowedHeaders'])) {
123-
$options['allowedHeaders'] = true;
124-
} else {
125-
$options['allowedHeaders'] = array_map('strtolower', $options['allowedHeaders']);
126-
}
105+
// Normalize case
106+
$options['allowedHeaders'] = array_map('strtolower', $options['allowedHeaders']);
107+
$options['allowedMethods'] = array_map('strtoupper', $options['allowedMethods']);
127108

128-
if (in_array('*', $options['allowedMethods'])) {
129-
$options['allowedMethods'] = true;
130-
} else {
131-
$options['allowedMethods'] = array_map('strtoupper', $options['allowedMethods']);
132-
}
109+
// Normalize ['*'] to true
110+
$options['allowAllOrigins'] = in_array('*', $options['allowedOrigins']);
111+
$options['allowAllHeaders'] = in_array('*', $options['allowedHeaders']);
112+
$options['allowAllMethods'] = in_array('*', $options['allowedMethods']);
133113

134114
return $options;
135115
}
@@ -191,7 +171,7 @@ public function addPreflightRequestHeaders(Response $response, Request $request)
191171

192172
public function isOriginAllowed(Request $request): bool
193173
{
194-
if ($this->options['allowedOrigins'] === true) {
174+
if ($this->options['allowAllOrigins'] === true) {
195175
return true;
196176
}
197177

@@ -205,6 +185,7 @@ public function isOriginAllowed(Request $request): bool
205185
return true;
206186
}
207187

188+
/** @var string $pattern */
208189
foreach ($this->options['allowedOriginsPatterns'] as $pattern) {
209190
if (preg_match($pattern, $origin)) {
210191
return true;
@@ -229,7 +210,7 @@ public function addActualRequestHeaders(Response $response, Request $request): R
229210

230211
private function configureAllowedOrigin(Response $response, Request $request): void
231212
{
232-
if ($this->options['allowedOrigins'] === true && !$this->options['supportsCredentials']) {
213+
if ($this->options['allowAllOrigins'] === true && !$this->options['supportsCredentials']) {
233214
// Safe+cacheable, allow everything
234215
$response->headers->set('Access-Control-Allow-Origin', '*');
235216
} elseif ($this->isSingleOriginAllowed()) {
@@ -247,7 +228,7 @@ private function configureAllowedOrigin(Response $response, Request $request): v
247228

248229
private function isSingleOriginAllowed(): bool
249230
{
250-
if ($this->options['allowedOrigins'] === true || count($this->options['allowedOriginsPatterns']) > 0) {
231+
if ($this->options['allowAllOrigins'] === true || count($this->options['allowedOriginsPatterns']) > 0) {
251232
return false;
252233
}
253234

@@ -256,8 +237,8 @@ private function isSingleOriginAllowed(): bool
256237

257238
private function configureAllowedMethods(Response $response, Request $request): void
258239
{
259-
if ($this->options['allowedMethods'] === true) {
260-
$allowMethods = strtoupper($request->headers->get('Access-Control-Request-Method'));
240+
if ($this->options['allowAllMethods'] === true) {
241+
$allowMethods = strtoupper((string) $request->headers->get('Access-Control-Request-Method'));
261242
$this->varyHeader($response, 'Access-Control-Request-Method');
262243
} else {
263244
$allowMethods = implode(', ', $this->options['allowedMethods']);
@@ -268,7 +249,7 @@ private function configureAllowedMethods(Response $response, Request $request):
268249

269250
private function configureAllowedHeaders(Response $response, Request $request): void
270251
{
271-
if ($this->options['allowedHeaders'] === true) {
252+
if ($this->options['allowAllHeaders'] === true) {
272253
$allowHeaders = $request->headers->get('Access-Control-Request-Headers');
273254
$this->varyHeader($response, 'Access-Control-Request-Headers');
274255
} else {
@@ -302,8 +283,8 @@ public function varyHeader(Response $response, string $header): Response
302283
{
303284
if (!$response->headers->has('Vary')) {
304285
$response->headers->set('Vary', $header);
305-
} elseif (!in_array($header, explode(', ', $response->headers->get('Vary')))) {
306-
$response->headers->set('Vary', $response->headers->get('Vary') . ', ' . $header);
286+
} elseif (!in_array($header, explode(', ', (string) $response->headers->get('Vary')))) {
287+
$response->headers->set('Vary', ((string) $response->headers->get('Vary')) . ', ' . $header);
307288
}
308289

309290
return $response;

tests/CorsServiceTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public function itNormalizesWildcardOrigins(): void
8383
$service = new CorsService(['allowedOrigins' => $origins]);
8484
$this->assertInstanceOf(CorsService::class, $service);
8585

86-
$this->assertEquals(true, $this->getOptionsFromService($service)['allowedOrigins']);
86+
$this->assertTrue($this->getOptionsFromService($service)['allowAllOrigins']);
8787
}
8888

8989
/**

tests/CorsTest.php

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -555,23 +555,15 @@ private function createValidPreflightRequest(): Request
555555

556556
/**
557557
* @param CorsInputOptions $options
558-
* @param array{'Vary'?: string} $responseHeaders
558+
* @param string[] $responseHeaders
559559
* @return MockApp
560560
*/
561561
private function createStackedApp(array $options = array(), array $responseHeaders = array()): MockApp
562562
{
563-
$passedOptions = array_merge(
564-
array(
565-
'allowedHeaders' => array('x-allowed-header', 'x-other-allowed-header'),
566-
'allowedMethods' => array('delete', 'get', 'post', 'put'),
567-
'allowedOrigins' => array('http://localhost'),
568-
'exposedHeaders' => false,
569-
'maxAge' => false,
570-
'supportsCredentials' => false,
571-
),
572-
$options
573-
);
563+
$options['allowedHeaders'] = $options['allowedHeaders'] ?? ['x-allowed-header', 'x-other-allowed-header'];
564+
$options['allowedMethods'] = $options['allowedMethods'] ?? ['delete', 'get', 'post', 'put'];
565+
$options['allowedOrigins'] = $options['allowedOrigins'] ?? ['http://localhost'];
574566

575-
return new MockApp($responseHeaders, $passedOptions);
567+
return new MockApp($responseHeaders, $options);
576568
}
577569
}

tests/MockApp.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
*/
2222
class MockApp
2323
{
24-
/** @var array{'Vary'?: string} */
24+
/** @var string[] */
2525
private $responseHeaders;
2626

2727
/**
@@ -30,7 +30,7 @@ class MockApp
3030
private $cors;
3131

3232
/**
33-
* @param array{'Vary'?: string} $responseHeaders
33+
* @param string[] $responseHeaders
3434
* @param CorsInputOptions $options
3535
*/
3636
public function __construct(array $responseHeaders, array $options = [])

0 commit comments

Comments
 (0)