Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"laminas/laminas-coding-standard": "^2.3",
"laminas/laminas-config": "^3.1",
"phpunit/phpunit": "^9.5",
"psalm/plugin-phpunit": "^0.15.1",
"psalm/plugin-phpunit": "^0.16.0",
"vimeo/psalm": "^4.7"
},
"autoload": {
Expand Down
189 changes: 76 additions & 113 deletions composer.lock

Large diffs are not rendered by default.

50 changes: 0 additions & 50 deletions psalm-baseline.xml

This file was deleted.

21 changes: 3 additions & 18 deletions psalm.xml
Original file line number Diff line number Diff line change
@@ -1,35 +1,20 @@
<?xml version="1.0"?>
<psalm
totallyTyped="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
errorBaseline="psalm-baseline.xml"
errorLevel="1"
findUnusedPsalmSuppress="true"
>
<projectFiles>
<directory name="src"/>
<directory name="test"/>
<ignoreFiles>
<directory name=".github"/>
<directory name="docs"/>
<directory name="vendor"/>
</ignoreFiles>
</projectFiles>

<issueHandlers>
<InternalMethod>
<errorLevel type="suppress">
<referencedMethod name="PHPUnit\Framework\MockObject\Builder\InvocationMocker::method"/>
</errorLevel>
<errorLevel type="suppress">
<referencedMethod name="PHPUnit\Framework\MockObject\Builder\InvocationMocker::willReturn"/>
</errorLevel>
<errorLevel type="suppress">
<referencedMethod name="PHPUnit\Framework\MockObject\Builder\InvocationMocker::with"/>
</errorLevel>
</InternalMethod>
</issueHandlers>
<plugins>
<pluginClass class="Psalm\PhpUnitPlugin\Plugin"/>
</plugins>
</psalm>
</psalm>
13 changes: 11 additions & 2 deletions src/LazyParameterPostProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@

namespace Laminas\ConfigAggregatorParameters;

/**
* @template TParameters of array<string,mixed>
* @psalm-import-type ProcessedConfig from ParameterPostProcessor
*/
final class LazyParameterPostProcessor
{
/** @var callable */
/**
* @var callable():array<string,mixed>
* @psalm-var callable():TParameters
*/
private $parameterProvider;

/**
* @psalm-param callable():array<string,mixed> $parameterProvider
* @param callable():array<string,mixed> $parameterProvider
* @psalm-param callable():TParameters $parameterProvider
*/
public function __construct(callable $parameterProvider)
{
Expand All @@ -20,6 +28,7 @@ public function __construct(callable $parameterProvider)
/**
* @param array<string,mixed> $config
* @return array<string,mixed>
* @psalm-return ProcessedConfig
*/
public function __invoke(array $config): array
{
Expand Down
17 changes: 12 additions & 5 deletions src/ParameterNotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException as BaseException;
use Throwable;

use function sprintf;

Expand All @@ -14,14 +15,20 @@ class ParameterNotFoundException extends InvalidArgumentException
/** @var string */
private $key;

public function __construct(string $message = "", int $code = 0, ?Throwable $previous = null, string $key = '')
{
parent::__construct($message, $code, $previous);
$this->key = $key;
}

public static function fromException(BaseException $e): self
{
$toReturn = new self(sprintf(
$code = (int) $e->getCode();
$key = (string) $e->getKey();
return new self(sprintf(
'Found key "%s" within configuration, but it has no associated parameter defined',
$e->getKey()
), $e->getCode(), $e);
$toReturn->key = $e->getKey();
return $toReturn;
$key
), $code, $e, $key);
}

public function getKey(): string
Expand Down
29 changes: 25 additions & 4 deletions src/ParameterPostProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,45 +11,66 @@
use function is_array;
use function is_numeric;

/**
* @template TParameters of array<string,mixed>
* @psalm-type ProcessedConfig=array<string,mixed>&array{parameters:array<string,mixed>}
*/
class ParameterPostProcessor
{
/** @var array */
/**
* @var array<string,mixed>
* @psalm-var TParameters
*/
private $parameters;

/**
* @param array $parameters
* @param array<string,mixed> $parameters
* @psalm-param TParameters $parameters
*/
public function __construct(array $parameters)
{
$this->parameters = $parameters;
}

/**
* @template TConfig of array<string,mixed>
* @param array<string,mixed> $config
* @return array<string,mixed>
* @psalm-return ProcessedConfig
*/
public function __invoke(array $config): array
{
try {
$parameters = $this->getResolvedParameters();

array_walk_recursive($config, function (&$value) use ($parameters) {
/** @psalm-suppress MissingClosureParamType */
array_walk_recursive($config, static function (&$value) use ($parameters) {
/** @psalm-suppress MixedAssignment */
$value = $parameters->unescapeValue($parameters->resolveValue($value));
});
} catch (SymfonyParameterNotFoundException $exception) {
throw ParameterNotFoundException::fromException($exception);
}

$config['parameters'] = $parameters->all();
/** @var array<string,mixed> $allParameters */
$allParameters = $parameters->all();
$config['parameters'] = $allParameters;

/** @psalm-var ProcessedConfig $config */
return $config;
}

private function resolveNestedParameters(array $values, string $prefix = ''): array
{
$convertedValues = [];
/** @psalm-suppress MixedAssignment */
foreach ($values as $key => $value) {
// Do not provide numeric keys as single parameter
if (is_numeric($key)) {
continue;
}

/** @psalm-suppress MixedAssignment */
$convertedValues[$prefix . $key] = $value;
if (is_array($value)) {
$convertedValues += $this->resolveNestedParameters($value, $prefix . $key . '.');
Expand Down
1 change: 1 addition & 0 deletions test/LazyParameterPostProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public function testParameterProviderNotCalledDuringInstantiation(): void
throw new RuntimeException('Parameter provider must not be called during instantiation!');
};

/** @psalm-suppress MixedArgumentTypeCoercion */
new LazyParameterPostProcessor($callable);

self::assertTrue(true);
Expand Down
23 changes: 18 additions & 5 deletions test/ParameterPostProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ class ParameterPostProcessorTest extends TestCase
{
use ArraySubsetAsserts;

/**
* @psalm-return array<
* non-empty-string,
* array{
* 0: array<string,mixed>,
* 1: array<string,mixed>,
* 2: array<string,mixed>
* }
* >
*/
public function parameterProvider(): array
{
return [
Expand Down Expand Up @@ -57,23 +67,26 @@ public function parameterProvider(): array

/**
* @dataProvider parameterProvider
* @param array<string,mixed> $parameters
* @param array<string,mixed> $configuration
* @param array<string,mixed> $expected
*/
public function testCanApplyParameters(array $parameters, array $configuration, array $expected)
public function testCanApplyParameters(array $parameters, array $configuration, array $expected): void
{
$processor = new ParameterPostProcessor($parameters);
$processed = $processor($configuration);

$this->assertArraySubset($expected, $processed);
self::assertArraySubset($expected, $processed);
}

public function testCanDetectMissingParameter()
public function testCanDetectMissingParameter(): void
{
$processor = new ParameterPostProcessor([]);
$this->expectException(ParameterNotFoundException::class);
$processor(['foo' => '%foo%']);
}

public function testResolvesParameterizedParameters()
public function testResolvesParameterizedParameters(): void
{
$processor = new ParameterPostProcessor([
'foo' => 'bar',
Expand All @@ -97,7 +110,7 @@ public function testResolvesParameterizedParameters()
], $processed);
}

public function testResolvesParameterizedParametersInReversedOrder()
public function testResolvesParameterizedParametersInReversedOrder(): void
{
$processor = new ParameterPostProcessor([
'foo' => '%bar%',
Expand Down