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

Service definition #78

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
121 changes: 121 additions & 0 deletions src/ServiceDefinition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Definitions;

use Psr\Container\ContainerInterface;
use Yiisoft\Definitions\Contract\DefinitionInterface;
use Yiisoft\Definitions\Helpers\ArrayDefinitionHelper;

final class ServiceDefinition implements DefinitionInterface
{
/**
* @psalm-var array<string, mixed>
*/
private array $calls = [];

private function __construct(
/**
* @psalm-var class-string
*/
private string $class,
private array $constructor = [],
) {
}

/**
* @psalm-param class-string $class
*/
public static function for(string $class, array $constructor = []): self
{
return new self($class, $constructor);
}

public function constructor(array $arguments): self
{
$this->constructor = $arguments;
return $this;
}

public function call(string $method, array $arguments = []): self
{
$this->calls[$method . '()'] = $arguments;
return $this;
}

/**
* @psalm-param array<string, array> $methods
*/
public function calls(array $methods): self
{
foreach ($methods as $method => $arguments) {
$this->call($method, $arguments);
}
return $this;
}

public function set(string $property, mixed $value): self
{
$this->calls['$' . $property] = $value;
return $this;
}

/**
* @psalm-param array<string, mixed> $properties
*/
public function sets(array $properties): self
{
foreach ($properties as $property => $value) {
$this->set($property, $value);
}
return $this;
}

public function resolve(ContainerInterface $container): mixed
{
$config = array_merge($this->calls, [
ArrayDefinition::CLASS_NAME => $this->class,
ArrayDefinition::CONSTRUCTOR => $this->constructor,
]);
return ArrayDefinition::fromConfig($config)->resolve($container);
}

public function merge(self $other): self
{
$new = clone $this;
$new->class = $other->class;
$new->constructor = ArrayDefinitionHelper::mergeArguments($this->constructor, $other->constructor);

$calls = $this->calls;
foreach ($other->calls as $key => $item) {
if (str_starts_with($key, '$')) {
$calls[$key] = $item;
} elseif (str_ends_with($key, '()')) {
/** @psalm-suppress MixedArgument */
$arguments = isset($calls[$key])
? ArrayDefinitionHelper::mergeArguments($calls[$key], $item)
: $item;
$calls[$key] = $arguments;
}
}
$new->calls = $calls;

return $new;
}

public function getClass(): string
{
return $this->class;
}

public function getConstructor(): array
{
return $this->constructor;
}

public function getCalls(): array
{
return $this->calls;
}
}
2 changes: 1 addition & 1 deletion tests/Unit/Helpers/DefinitionResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function testEnsureResolvableDefinition(): void
$this->expectException(InvalidConfigException::class);
$this->expectExceptionMessage(
'Only references are allowed in constructor arguments, a definition object was provided: ' .
ValueDefinition::class
var_export(new ValueDefinition(7), true),
);
DefinitionResolver::ensureResolvable(new ValueDefinition(7));
}
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/Helpers/DefinitionValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ public function testDefinitionInArguments(): void
$this->expectException(InvalidConfigException::class);
$this->expectExceptionMessage(
'Only references are allowed in constructor arguments, a definition object was provided: ' .
ValueDefinition::class
var_export(new ValueDefinition(56), true),
);
DefinitionValidator::validate([
'class' => GearBox::class,
Expand Down
Loading