Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for psr/container v2 #188

Merged
merged 1 commit into from
May 2, 2023
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
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"php": "~8.1.0 || ~8.2.0",
"brick/varexporter": "^0.3.8",
"laminas/laminas-stdlib": "^3.2.1",
"psr/container": "^1.1"
"psr/container": "^1.1 || ^2.0"
},
"extra": {
"laminas": {
Expand All @@ -58,7 +58,7 @@
"vimeo/psalm": "^5.10"
},
"provide": {
"psr/container-implementation": "^1.0"
"psr/container-implementation": "^1.0 || ^2.0"
},
"conflict": {
"laminas/laminas-code": "<3.3.1",
Expand Down
43 changes: 25 additions & 18 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@
<code><![CDATA[$config['factories']]]></code>
<code><![CDATA[$config['shared']]]></code>
</MixedOperand>
<ParamNameMismatch>
<code>$name</code>
<code>$name</code>
</ParamNameMismatch>
</file>
<file src="src/Test/CommonPluginManagerTrait.php">
<ArgumentTypeCoercion>
Expand Down
2 changes: 1 addition & 1 deletion src/AbstractPluginManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ public function setService(string $name, mixed $service): void
/**
* {@inheritDoc}
*/
public function get($id): mixed
public function get(string $id): mixed
{
if (! $this->has($id)) {
if (! $this->autoAddInvokableClass || ! class_exists($id)) {
Expand Down
24 changes: 12 additions & 12 deletions src/ServiceManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,35 +204,35 @@ public function __construct(
}

/** {@inheritDoc} */
public function get($name)
public function get(string $id): mixed
{
// We start by checking if we have cached the requested service;
// this is the fastest method.
if (isset($this->services[$name])) {
return $this->services[$name];
if (isset($this->services[$id])) {
return $this->services[$id];
}

// Determine if the service should be shared.
$sharedService = $this->shared[$name] ?? $this->sharedByDefault;
$sharedService = $this->shared[$id] ?? $this->sharedByDefault;

// We achieve better performance if we can let all alias
// considerations out.
if (! $this->aliases) {
/** @psalm-suppress MixedAssignment Yes indeed, service managers can return mixed. */
$service = $this->doCreate($name);
$service = $this->doCreate($id);

// Cache the service for later, if it is supposed to be shared.
if ($sharedService) {
$this->services[$name] = $service;
$this->services[$id] = $service;
}
return $service;
}

// We now deal with requests which may be aliases.
$resolvedName = $this->aliases[$name] ?? $name;
$resolvedName = $this->aliases[$id] ?? $id;

// Update shared service information as we checked if the alias was shared before.
if ($resolvedName !== $name) {
if ($resolvedName !== $id) {
$sharedService = $this->shared[$resolvedName] ?? $sharedService;
}

Expand All @@ -241,7 +241,7 @@ public function get($name)

// If the alias is configured as a shared service, we are done.
if ($sharedAlias) {
$this->services[$name] = $this->services[$resolvedName];
$this->services[$id] = $this->services[$resolvedName];
return $this->services[$resolvedName];
}

Expand All @@ -253,7 +253,7 @@ public function get($name)
// Cache the object for later, if it is supposed to be shared.
if ($sharedService) {
$this->services[$resolvedName] = $service;
$this->services[$name] = $service;
$this->services[$id] = $service;
}

return $service;
Expand All @@ -274,10 +274,10 @@ public function build(string $name, ?array $options = null): mixed
* @param string|class-string $name
* @return bool
*/
public function has($name)
public function has(string $id): bool
{
// Check static services and factories first to speedup the most common requests.
return $this->staticServiceOrFactoryCanCreate($name) || $this->abstractFactoryCanCreate($name);
return $this->staticServiceOrFactoryCanCreate($id) || $this->abstractFactoryCanCreate($id);
}

/**
Expand Down
39 changes: 33 additions & 6 deletions test/Tool/FactoryCreatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
use Psr\Container\ContainerInterface;
use stdClass;

use function array_pop;
use function count;
use function file_get_contents;
use function func_get_args;
use function is_array;
use function preg_match;

use const PHP_EOL;
Expand Down Expand Up @@ -55,9 +59,9 @@ public function testCreateFactoryCreatesForSimpleDependencies(): void
$this->container
->expects(self::atLeastOnce())
->method('has')
->willReturnMap([
->willReturnCallback($this->createReturnMapCallbackWithDefault([
[InvokableObject::class, true],
]);
], false));

self::assertSame($factory, $this->factoryCreator->createFactory($className));
}
Expand All @@ -70,10 +74,10 @@ public function testCreateFactoryCreatesForComplexDependencies(): void
$this->container
->expects(self::atLeastOnce())
->method('has')
->willReturnMap([
->willReturnCallback($this->createReturnMapCallbackWithDefault([
[SimpleDependencyObject::class, true],
[SecondComplexDependencyObject::class, true],
]);
], false));

self::assertSame($factory, $this->factoryCreator->createFactory($className));
}
Expand All @@ -89,10 +93,10 @@ public function testNamespaceGeneration(): void
$this->container
->expects(self::atLeastOnce())
->method('has')
->willReturnMap([
->willReturnCallback($this->createReturnMapCallbackWithDefault([
[SimpleDependencyObject::class, true],
[SecondComplexDependencyObject::class, true],
]);
], false));

foreach ($testClassNames as $testFqcn => $expectedNamespace) {
$generatedFactory = $this->factoryCreator->createFactory($testFqcn);
Expand All @@ -108,4 +112,27 @@ public function testNamespaceGeneration(): void
self::assertSame($expectedNamespace, $namespaceMatch[1]);
}
}

private function createReturnMapCallbackWithDefault(array $values, mixed $default): callable
{
return function () use ($values, $default): mixed {
$args = func_get_args();
$parameterCount = count($args);

foreach ($values as $map) {
if (! is_array($map) || $parameterCount !== count($map) - 1) {
continue;
}

/** @var mixed $return */
$return = array_pop($map);

if ($args === $map) {
return $return;
}
}

return $default;
};
}
}