Skip to content

Commit 62b4f70

Browse files
authored
Merge pull request #303 from clue-labs/container-more-types
Support more built-in types for container factory functions
2 parents 575c46b + 4e42238 commit 62b4f70

2 files changed

Lines changed: 147 additions & 2 deletions

File tree

src/Container.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,11 +465,15 @@ private function validateType($value, \ReflectionType $type): bool
465465
\assert($type !== 'null' && $type !== 'mixed');
466466

467467
return (
468-
(\is_object($value) && $value instanceof $type) ||
468+
(\is_object($value) && ($value instanceof $type || $type === 'object')) || // instanceof or object for PHP 7.2+
469469
(\is_string($value) && $type === 'string') ||
470470
(\is_int($value) && $type === 'int') ||
471471
(\is_float($value) && $type === 'float') ||
472-
(\is_bool($value) && $type === 'bool')
472+
(\is_bool($value) && $type === 'bool') ||
473+
(\is_iterable($value) && $type === 'iterable') ||
474+
(\is_callable($value) && $type === 'callable') ||
475+
($value === true && $type === 'true') || // PHP 8.2+ standalone type
476+
($value === false && $type === 'false') // PHP 8.0+ union or PHP 8.2+ standalone
473477
);
474478
}
475479

tests/ContainerTest.php

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,6 +1924,69 @@ public function testGetEnvReturnsStringFromMapFactory(): void
19241924
$this->assertEquals('bar', $container->getEnv('X_FOO'));
19251925
}
19261926

1927+
/**
1928+
* @requires PHP 7.2
1929+
*/
1930+
public function testGetEnvReturnsStringFromFactoryFunctionWithObjectType(): void
1931+
{
1932+
$container = new Container([
1933+
'X_FOO' => function (object $data) { return get_class($data); },
1934+
'data' => new \ArrayObject()
1935+
]);
1936+
1937+
$this->assertEquals('ArrayObject', $container->getEnv('X_FOO'));
1938+
}
1939+
1940+
public function testGetEnvReturnsStringFromFactoryFunctionWithIterableType(): void
1941+
{
1942+
$container = new Container([
1943+
'X_FOO' => function (iterable $items) { $s = ''; foreach ($items as $v) { $s .= $v; } return $s; },
1944+
'items' => new \ArrayIterator([1, 2, 3])
1945+
]);
1946+
1947+
$this->assertEquals('123', $container->getEnv('X_FOO'));
1948+
}
1949+
1950+
public function testGetEnvReturnsStringFromFactoryFunctionWithCallableType(): void
1951+
{
1952+
$container = new Container([
1953+
'X_FOO' => function (callable $fn) { return $fn('alice'); },
1954+
'fn' => 'strtoupper'
1955+
]);
1956+
1957+
$this->assertEquals('ALICE', $container->getEnv('X_FOO'));
1958+
}
1959+
1960+
/**
1961+
* @requires PHP 8.2
1962+
*/
1963+
public function testGetEnvReturnsStringFromFactoryFunctionWithTrueType(): void
1964+
{
1965+
// eval to avoid syntax error on PHP < 8.2
1966+
$fn = eval('return function (true $admin) { return var_export($admin, true); };');
1967+
$container = new Container([
1968+
'X_FOO' => $fn,
1969+
'admin' => true
1970+
]);
1971+
1972+
$this->assertEquals('true', $container->getEnv('X_FOO'));
1973+
}
1974+
1975+
/**
1976+
* @requires PHP 8.2
1977+
*/
1978+
public function testGetEnvReturnsStringFromFactoryFunctionWithFalseType(): void
1979+
{
1980+
// eval to avoid syntax error on PHP < 8.2
1981+
$fn = eval('return function (false $disabled) { return var_export($disabled, true); };');
1982+
$container = new Container([
1983+
'X_FOO' => $fn,
1984+
'disabled' => false
1985+
]);
1986+
1987+
$this->assertEquals('false', $container->getEnv('X_FOO'));
1988+
}
1989+
19271990
/**
19281991
* @requires PHP 8
19291992
*/
@@ -2501,6 +2564,84 @@ public function testGetEnvThrowsWhenFactoryFunctionExpectsNullableIntArgumentBut
25012564
$container->getEnv('X_FOO');
25022565
}
25032566

2567+
/**
2568+
* @requires PHP 7.2
2569+
*/
2570+
public function testGetEnvThrowsWhenFactoryFunctionExpectsObjectTypeButWrongTypeGiven(): void
2571+
{
2572+
$line = __LINE__ + 2;
2573+
$container = new Container([
2574+
'X_FOO' => function (object $data) { return get_class($data); },
2575+
'data' => 'Alice'
2576+
]);
2577+
2578+
$this->expectException(\TypeError::class);
2579+
$this->expectExceptionMessage('Argument #1 ($data) of {closure:' . __FILE__ . ':' . $line . '}() for $X_FOO must be of type object, string given');
2580+
$container->getEnv('X_FOO');
2581+
}
2582+
2583+
public function testGetEnvThrowsWhenFactoryFunctionExpectsIterableTypeButWrongTypeGiven(): void
2584+
{
2585+
$line = __LINE__ + 2;
2586+
$container = new Container([
2587+
'X_FOO' => function (iterable $items) { $s = ''; foreach ($items as $v) { $s .= $v; } return $s; },
2588+
'items' => 'not-iterable'
2589+
]);
2590+
2591+
$this->expectException(\TypeError::class);
2592+
$this->expectExceptionMessage('Argument #1 ($items) of {closure:' . __FILE__ . ':' . $line . '}() for $X_FOO must be of type iterable, string given');
2593+
$container->getEnv('X_FOO');
2594+
}
2595+
2596+
public function testGetEnvThrowsWhenFactoryFunctionExpectsCallableTypeButWrongTypeGiven(): void
2597+
{
2598+
$line = __LINE__ + 2;
2599+
$container = new Container([
2600+
'X_FOO' => function (callable $fn) { return $fn(); },
2601+
'fn' => 42
2602+
]);
2603+
2604+
$this->expectException(\TypeError::class);
2605+
$this->expectExceptionMessage('Argument #1 ($fn) of {closure:' . __FILE__ . ':' . $line . '}() for $X_FOO must be of type callable, int given');
2606+
$container->getEnv('X_FOO');
2607+
}
2608+
2609+
/**
2610+
* @requires PHP 8.2
2611+
*/
2612+
public function testGetEnvThrowsWhenFactoryFunctionExpectsTrueTypeButWrongTypeGiven(): void
2613+
{
2614+
$line = __LINE__ + 2;
2615+
// eval to avoid syntax error on PHP < 8.2
2616+
$fn = eval('return function (true $admin) { return var_export($admin, true); };');
2617+
$container = new Container([
2618+
'X_FOO' => $fn,
2619+
'admin' => false
2620+
]);
2621+
2622+
$this->expectException(\TypeError::class);
2623+
$this->expectExceptionMessage('Argument #1 ($admin) of {closure:' . __FILE__ . '(' . $line . ') : eval()\'d code:1}() for $X_FOO must be of type true, false given');
2624+
$container->getEnv('X_FOO');
2625+
}
2626+
2627+
/**
2628+
* @requires PHP 8.2
2629+
*/
2630+
public function testGetEnvThrowsWhenFactoryFunctionExpectsFalseTypeButWrongTypeGiven(): void
2631+
{
2632+
$line = __LINE__ + 2;
2633+
// eval to avoid syntax error on PHP < 8.2
2634+
$fn = eval('return function (false $disabled) { return var_export($disabled, true); };');
2635+
$container = new Container([
2636+
'X_FOO' => $fn,
2637+
'disabled' => true
2638+
]);
2639+
2640+
$this->expectException(\TypeError::class);
2641+
$this->expectExceptionMessage('Argument #1 ($disabled) of {closure:' . __FILE__ . '(' . $line . ') : eval()\'d code:1}() for $X_FOO must be of type false, true given');
2642+
$container->getEnv('X_FOO');
2643+
}
2644+
25042645
/**
25052646
* @requires PHP 8
25062647
*/

0 commit comments

Comments
 (0)