Skip to content

Commit 36ae2c0

Browse files
committed
Fix container behavior
1 parent 795abbe commit 36ae2c0

File tree

2 files changed

+53
-34
lines changed

2 files changed

+53
-34
lines changed

src/Container/ConfigContainer.php

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,17 @@
2020
use Psr\Container\ContainerInterface;
2121

2222
/**
23-
* Class ConfigContainer.
23+
* Class ConfigContainer
2424
*
2525
* Provides a PSR-11 compatible container interface for accessing configuration values.
26-
* This container MAY be used in dependency injection systems where configuration keys
27-
* should be resolvable via standard container access.
26+
*
27+
* This container implementation SHALL resolve configuration keys by prefix using the alias "config".
28+
* For example, a request for "config.db.host" will attempt to fetch the key "db.host" from the underlying ConfigInterface.
29+
*
30+
* Identifiers such as 'config', ConfigInterface::class, and the concrete config class MUST return the configuration instance itself.
31+
* Requests for unknown or invalid identifiers MUST result in a ContainerNotFoundException.
32+
*
33+
* @package FastForward\Config\Container
2834
*/
2935
final class ConfigContainer implements ContainerInterface
3036
{
@@ -37,52 +43,68 @@ final class ConfigContainer implements ContainerInterface
3743
* Constructs a new ConfigContainer instance.
3844
*
3945
* This constructor SHALL wrap an existing ConfigInterface instance and expose it
40-
* through PSR-11 `get()` and `has()` methods.
46+
* through PSR-11 `get()` and `has()` methods with namespace-style key resolution.
4147
*
42-
* @param ConfigInterface $config the configuration instance to expose as a container
48+
* @param ConfigInterface $config The configuration instance to expose as a container.
4349
*/
4450
public function __construct(
4551
private ConfigInterface $config,
4652
) {}
4753

4854
/**
49-
* Determines if the container can return an entry for the given identifier.
55+
* Determines whether the container can return an entry for the given identifier.
5056
*
51-
* @param string $id identifier of the entry to look for
57+
* This method SHALL return true if:
58+
* - The identifier matches known internal bindings (alias, interface, or class).
59+
* - The identifier is prefixed with 'config' and corresponds to an existing key in the configuration.
5260
*
53-
* @return bool TRUE if the entry is known or exists in the configuration, FALSE otherwise
61+
* @param string $id Identifier of the entry to look for.
62+
* @return bool True if the entry can be resolved; false otherwise.
5463
*/
5564
public function has(string $id): bool
5665
{
57-
return $this->isResolvedByContainer($id)
58-
|| $this->config->has($id);
66+
if ($this->isResolvedByContainer($id)) {
67+
return true;
68+
}
69+
70+
if (!str_starts_with($id, self::ALIAS)) {
71+
return false;
72+
}
73+
74+
return $this->config->has(mb_substr($id, mb_strlen(self::ALIAS) + 1));
5975
}
6076

6177
/**
6278
* Retrieves an entry of the container by its identifier.
6379
*
64-
* If the ID matches the container itself or the config class, it SHALL return itself.
65-
* Otherwise, it SHALL retrieve the value from the configuration.
66-
* If the key is not found, it MUST throw a ContainerNotFoundException.
67-
*
68-
* @param string $id identifier of the entry to retrieve
80+
* This method SHALL resolve identifiers in the following order:
81+
* - If the identifier matches 'config', ConfigInterface::class, or the concrete config class,
82+
* it SHALL return the ConfigInterface instance itself.
83+
* - If the identifier is prefixed with 'config.', the suffix SHALL be used to query the configuration.
84+
* If the configuration key exists, its value SHALL be returned.
85+
* - If the identifier cannot be resolved, a ContainerNotFoundException MUST be thrown.
6986
*
70-
* @return mixed the value associated with the identifier
87+
* @param string $id Identifier of the entry to retrieve.
88+
* @return mixed The value associated with the identifier.
7189
*
72-
* @throws ContainerNotFoundException if the identifier is not found
90+
* @throws ContainerNotFoundException If the identifier cannot be resolved.
7391
*/
7492
public function get(string $id)
7593
{
76-
if ($id === self::class) {
94+
if (self::class === $id) {
7795
return $this;
7896
}
7997

8098
if ($this->isResolvedByContainer($id)) {
8199
return $this->config;
82100
}
83101

84-
if ($this->config->has($id)) {
85-
return $this->config->get($id);
102+
if (str_starts_with($id, self::ALIAS)) {
103+
$id = mb_substr($id, mb_strlen(self::ALIAS) + 1);
104+
105+
if ($this->config->has($id)) {
106+
return $this->config->get($id);
107+
}
86108
}
87109

88110
throw ContainerNotFoundException::forKey($id);
@@ -91,16 +113,13 @@ public function get(string $id)
91113
/**
92114
* Determines whether the given identifier is resolved internally by the container itself.
93115
*
94-
* This method SHALL be used to check if the requested identifier corresponds to:
95-
* - the container alias (e.g., 'config'),
96-
* - the Config interface (`FastForward\Config\ConfigInterface`),
97-
* - or the concrete configuration key.
98-
*
99-
* If any of these conditions match, the container MUST resolve the request by returning itself.
100-
*
101-
* @param string $id the identifier being checked for internal resolution
116+
* This method SHALL match the identifier against:
117+
* - the alias "config"
118+
* - the ConfigInterface::class string
119+
* - the concrete class of the injected configuration instance
102120
*
103-
* @return bool TRUE if the container SHALL resolve the identifier itself; FALSE otherwise
121+
* @param string $id The identifier to check.
122+
* @return bool True if the identifier is resolved internally; false otherwise.
104123
*/
105124
private function isResolvedByContainer(string $id): bool
106125
{

tests/Container/ConfigContainerTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public function testHasReturnsTrueIfConfigContainsKey(): void
5252
$config = new ArrayConfig([$key => $value]);
5353
$container = new ConfigContainer($config);
5454

55-
self::assertTrue($container->has($key));
55+
self::assertTrue($container->has(ConfigContainer::ALIAS . '.' . $key));
5656
}
5757

5858
#[Test]
@@ -70,9 +70,9 @@ public function testGetReturnsContainerForInternalIdentifiers(): void
7070
$config = new ArrayConfig();
7171
$container = new ConfigContainer($config);
7272

73-
self::assertSame($container, $container->get(ConfigContainer::ALIAS));
74-
self::assertSame($container, $container->get(ConfigInterface::class));
75-
self::assertSame($container, $container->get($config::class));
73+
self::assertSame($config, $container->get(ConfigContainer::ALIAS));
74+
self::assertSame($config, $container->get(ConfigInterface::class));
75+
self::assertSame($config, $container->get($config::class));
7676
}
7777

7878
#[Test]
@@ -84,7 +84,7 @@ public function testGetReturnsConfigValueForKey(): void
8484
$config = new ArrayConfig([$key => $value]);
8585
$container = new ConfigContainer($config);
8686

87-
self::assertSame($value, $container->get($key));
87+
self::assertSame($value, $container->get(ConfigContainer::ALIAS . '.' . $key));
8888
}
8989

9090
#[Test]

0 commit comments

Comments
 (0)