Skip to content

Commit 8bc567f

Browse files
committed
🚨 Fix PHPStan's issues
1 parent 4b08045 commit 8bc567f

File tree

3 files changed

+83
-11
lines changed

3 files changed

+83
-11
lines changed

phpstan.neon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
includes:
2+
- phar://phpstan.phar/conf/bleedingEdge.neon
3+
14
parameters:
25
level: max
36
excludePaths:

phpunit-tests/ApplicationTest.php

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,33 @@ public function testConfigEmptyFilesSolution(): void
8181
$this->assertStringContainsString('.meta/config.json: `files.solution` key is empty', $display);
8282
}
8383

84-
public function testConfigInvalidFilesSolutionValue(): void
84+
public function testConfigInvalidFilesValueNotArray(): void
85+
{
86+
$this->expectException(RuntimeException::class);
87+
$this->expectExceptionMessageMatches('#^\.meta/config\.json: missing or invalid `files\.solution` key$#');
88+
$input = new InMemoryFilesystemAdapter();
89+
$inputFs = new Filesystem($input);
90+
$inputFs->write('.meta/config.json', '{"files":true}');
91+
$output = new InMemoryFilesystemAdapter();
92+
93+
$application = new Application();
94+
$application->represent($inputFs, new Filesystem($output), new NullLogger());
95+
}
96+
97+
public function testConfigInvalidFilesMissingSolution(): void
98+
{
99+
$this->expectException(RuntimeException::class);
100+
$this->expectExceptionMessageMatches('#^\.meta/config\.json: missing or invalid `files\.solution` key$#');
101+
$input = new InMemoryFilesystemAdapter();
102+
$inputFs = new Filesystem($input);
103+
$inputFs->write('.meta/config.json', '{"files":{}}');
104+
$output = new InMemoryFilesystemAdapter();
105+
106+
$application = new Application();
107+
$application->represent($inputFs, new Filesystem($output), new NullLogger());
108+
}
109+
110+
public function testConfigInvalidFilesSolutionValueNotArray(): void
85111
{
86112
$this->expectException(RuntimeException::class);
87113
$this->expectExceptionMessageMatches('#^\.meta/config\.json: missing or invalid `files\.solution` key$#');
@@ -94,6 +120,19 @@ public function testConfigInvalidFilesSolutionValue(): void
94120
$application->represent($inputFs, new Filesystem($output), new NullLogger());
95121
}
96122

123+
public function testConfigInvalidFilesSolutionValueNotArrayOfString(): void
124+
{
125+
$this->expectException(RuntimeException::class);
126+
$this->expectExceptionMessageMatches('#^\.meta/config\.json: missing or invalid `files\.solution` key$#');
127+
$input = new InMemoryFilesystemAdapter();
128+
$inputFs = new Filesystem($input);
129+
$inputFs->write('.meta/config.json', '{"files":{"solution":[true]}}');
130+
$output = new InMemoryFilesystemAdapter();
131+
132+
$application = new Application();
133+
$application->represent($inputFs, new Filesystem($output), new NullLogger());
134+
}
135+
97136
public function testConfigMissingFilesSolution(): void
98137
{
99138
$this->expectException(RuntimeException::class);

src/DirectoryRepresenter.php

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use function assert;
1212
use function implode;
1313
use function is_array;
14+
use function is_string;
1415
use function json_decode;
1516

1617
use const JSON_THROW_ON_ERROR;
@@ -32,16 +33,7 @@ public function __construct(
3233
public function represent(): Result
3334
{
3435
$configJson = $this->solutionDir->read('/.meta/config.json');
35-
36-
$config = json_decode($configJson, true, flags: JSON_THROW_ON_ERROR);
37-
assert(is_array($config), 'json_decode(..., true) should return an array');
38-
39-
if (! isset($config['files']['solution']) || ! is_array($config['files']['solution'])) {
40-
throw new RuntimeException('.meta/config.json: missing or invalid `files.solution` key');
41-
}
42-
43-
$solutions = $config['files']['solution'];
44-
$this->logger->info('.meta/config.json: Solutions files: ' . implode(', ', $solutions));
36+
$solutions = $this->parseSolutions($configJson);
4537

4638
$mapping = new Mapping();
4739
$representer = new FilesRepresenter($mapping, $this->logger);
@@ -66,4 +58,42 @@ public function represent(): Result
6658
$mapping->toJson(),
6759
);
6860
}
61+
62+
/** @return string[] */
63+
private function parseSolutions(string $configJson): array
64+
{
65+
$config = json_decode($configJson, true, flags: JSON_THROW_ON_ERROR);
66+
assert(is_array($config), 'json_decode(..., true) should return an array');
67+
if (
68+
! isset($config['files'])
69+
|| ! is_array($config['files'])
70+
|| ! isset($config['files']['solution'])
71+
|| ! is_array($config['files']['solution'])
72+
|| ! $this->isArrayOfString($config['files']['solution'])
73+
) {
74+
throw new RuntimeException('.meta/config.json: missing or invalid `files.solution` key');
75+
}
76+
77+
$solutions = $config['files']['solution'];
78+
79+
$this->logger->info('.meta/config.json: Solutions files: ' . implode(', ', $solutions));
80+
81+
return $solutions;
82+
}
83+
84+
/**
85+
* @param mixed[] $array
86+
*
87+
* @phpstan-assert-if-true string[] $array
88+
*/
89+
private function isArrayOfString(array $array): bool
90+
{
91+
foreach ($array as $element) {
92+
if (! is_string($element)) {
93+
return false;
94+
}
95+
}
96+
97+
return true;
98+
}
6999
}

0 commit comments

Comments
 (0)