Skip to content

Commit

Permalink
Merge branch 'master' into lazy-services
Browse files Browse the repository at this point in the history
  • Loading branch information
xepozz authored Mar 3, 2024
2 parents bc7f70e + aeb0856 commit fedff5e
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 42 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/rector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ name: rector
jobs:
rector:
uses: yiisoft/actions/.github/workflows/rector.yml@master
secrets:
token: ${{ secrets.YIISOFT_GITHUB_TOKEN }}
with:
os: >-
['ubuntu-latest']
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## 1.2.2 under development

- no changes in this release.
- Enh #353: Add shortcut for tag reference #333 (@xepozz)

## 1.2.1 December 23, 2022

Expand Down
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
[![static analysis](https://github.com/yiisoft/di/workflows/static%20analysis/badge.svg)](https://github.com/yiisoft/di/actions?query=workflow%3A%22static+analysis%22)
[![type-coverage](https://shepherd.dev/github/yiisoft/di/coverage.svg)](https://shepherd.dev/github/yiisoft/di)

[PSR-11](http:https://www.php-fig.org/psr/psr-11/) compatible
[dependency injection](http:https://en.wikipedia.org/wiki/Dependency_injection) container that's able to instantiate
[PSR-11](https:https://www.php-fig.org/psr/psr-11/) compatible
[dependency injection](https:https://en.wikipedia.org/wiki/Dependency_injection) container that's able to instantiate
and configure classes resolving dependencies.

## Features

- [PSR-11](http:https://www.php-fig.org/psr/psr-11/) compatible.
- [PSR-11](https:https://www.php-fig.org/psr/psr-11/) compatible.
- Supports property injection, constructor injection and method injection.
- Detects circular references.
- Accepts array definitions. You can use it with mergeable configs.
Expand Down Expand Up @@ -315,7 +315,7 @@ $container = new Container($config);
Now you can get tagged services from the container in the following way:

```php
$container->get('tag@car');
$container->get(\Yiisoft\Di\Reference\TagReference::to('car'));
```

The result is an array that has two instances: `BlueCarService` and `RedCarService`.
Expand Down Expand Up @@ -348,7 +348,7 @@ applications with tools like [Swoole](https://www.swoole.co.uk/) or [RoadRunner]
reset the state of such services every request. For this purpose you can use `StateResetter` with resetters callbacks:

```php
$resetter = new StateResetter();
$resetter = new StateResetter($container);
$resetter->setResetters([
MyServiceInterface::class => function () {
$this->reset(); // a method of MyServiceInterface
Expand Down Expand Up @@ -406,8 +406,8 @@ To manually add resetters or in case you use Yii DI composite container with a t
MyServiceInterface::class => function () {
// ...
},
StateResetter::class => function () {
$resetter = new StateResetter();
StateResetter::class => function (ContainerInterface $container) {
$resetter = new StateResetter($container);
$resetter->setResetters([
MyServiceInterface::class => function () {
$this->reset(); // a method of MyServiceInterface
Expand Down Expand Up @@ -497,15 +497,16 @@ $container = new Container($config);

## Further reading

- [Martin Fowler's article](http:https://martinfowler.com/articles/injection.html).
- [Martin Fowler's article](https:https://martinfowler.com/articles/injection.html).


# Benchmarks

To run benchmarks execute the next command

`composer require phpbench/phpbench`
`$ ./vendor/bin/phpbench run`
```shell
./vendor/bin/phpbench run
```

Result example

Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"issues": "https://github.com/yiisoft/di/issues?state=open",
"forum": "https://www.yiiframework.com/forum/",
"wiki": "https://www.yiiframework.com/wiki/",
"irc": "irc:https://irc.freenode.net/yii",
"irc": "ircs:https://irc.libera.chat:6697/yii",
"chat": "https://t.me/yii3en",
"source": "https://github.com/yiisoft/di"
},
Expand All @@ -33,7 +33,7 @@
"friendsofphp/proxy-manager-lts": "^1.0",
"phpbench/phpbench": "^1.2.0",
"phpunit/phpunit": "^9.5",
"rector/rector": "^0.17.0",
"rector/rector": "^1.0.0",
"roave/infection-static-analysis-plugin": "^1.25",
"spatie/phpunit-watcher": "^1.23",
"vimeo/psalm": "^4.30|^5.7",
Expand Down
7 changes: 7 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
use Rector\Config\RectorConfig;
use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector;
use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector;
use Rector\Set\ValueObject\LevelSetList;

return static function (RectorConfig $rectorConfig): void {
Expand All @@ -19,4 +21,9 @@
$rectorConfig->sets([
LevelSetList::UP_TO_PHP_80,
]);

$rectorConfig->skip([
ClosureToArrowFunctionRector::class,
JsonThrowOnErrorRector::class,
]);
};
4 changes: 2 additions & 2 deletions src/CompositeContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use Psr\Container\ContainerInterface;
use RuntimeException;
use Throwable;
use Yiisoft\Di\Helpers\TagHelper;
use Yiisoft\Di\Reference\TagReference;

use function is_string;

Expand Down Expand Up @@ -54,7 +54,7 @@ public function get($id)
return $stateResetter;
}

if (TagHelper::isTagAlias($id)) {
if (TagReference::isTagAlias($id)) {
$tags = [];
foreach ($this->containers as $container) {
if (!$container instanceof Container) {
Expand Down
12 changes: 6 additions & 6 deletions src/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
use Yiisoft\Definitions\LazyDefinition;
use Yiisoft\Di\Helpers\DefinitionNormalizer;
use Yiisoft\Di\Helpers\DefinitionParser;
use Yiisoft\Di\Helpers\TagHelper;
use Yiisoft\Di\Reference\TagReference;

use function array_key_exists;
use function array_keys;
Expand All @@ -31,7 +31,7 @@
use function is_string;

/**
* Container implements a [dependency injection](http:https://en.wikipedia.org/wiki/Dependency_injection) container.
* Container implements a [dependency injection](https:https://en.wikipedia.org/wiki/Dependency_injection) container.
*/
final class Container implements ContainerInterface
{
Expand Down Expand Up @@ -104,8 +104,8 @@ public function __construct(ContainerConfigInterface $config)
*/
public function has(string $id): bool
{
if (TagHelper::isTagAlias($id)) {
$tag = TagHelper::extractTagFromAlias($id);
if (TagReference::isTagAlias($id)) {
$tag = TagReference::extractTagFromAlias($id);
return isset($this->tags[$tag]);
}

Expand Down Expand Up @@ -478,7 +478,7 @@ private function addDefinitionToStorage(string $id, $definition): void
*/
private function build(string $id)
{
if (TagHelper::isTagAlias($id)) {
if (TagReference::isTagAlias($id)) {
return $this->getTaggedServices($id);
}

Expand Down Expand Up @@ -508,7 +508,7 @@ private function build(string $id)

private function getTaggedServices(string $tagAlias): array
{
$tag = TagHelper::extractTagFromAlias($tagAlias);
$tag = TagReference::extractTagFromAlias($tagAlias);
$services = [];
if (isset($this->tags[$tag])) {
foreach ($this->tags[$tag] as $service) {
Expand Down
21 changes: 0 additions & 21 deletions src/Helpers/TagHelper.php

This file was deleted.

38 changes: 38 additions & 0 deletions src/Reference/TagReference.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Di\Reference;

use Yiisoft\Definitions\Reference;

/**
* TagReference is a helper class that is used to specify a reference to a tag.
* For example, `TagReference::to('my-tag')` specifies a reference to all services that are tagged with `tag@my-tag`.
*/
final class TagReference
{
private const PREFIX = 'tag@';

private function __construct()
{
}

public static function to(string $tag): Reference
{
return Reference::to(self::PREFIX . $tag);
}

public static function extractTagFromAlias(string $alias): string
{
if (!str_starts_with($alias, self::PREFIX)) {
throw new \InvalidArgumentException(sprintf('Alias "%s" is not a tag alias.', $alias));
}
return substr($alias, 4);
}

public static function isTagAlias(string $id): bool
{
return str_starts_with($id, self::PREFIX);
}
}
76 changes: 76 additions & 0 deletions tests/Unit/Reference/TagReferenceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Di\Tests\Unit\Reference;

use Error;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Yiisoft\Di\Reference\TagReference;

final class TagReferenceTest extends TestCase
{
public function testConstructorIsPrivate(): void
{
$this->expectException(Error::class);
new TagReference();
}

public function testConstructor(): void
{
$reflection = new \ReflectionClass(TagReference::class);
$reflectionMethod = $reflection->getConstructor();
$this->assertTrue($reflectionMethod->isPrivate());
if (PHP_VERSION_ID < 81000) {
$reflectionMethod->setAccessible(true);
}

$reflectionMethod->invoke($reflection->newInstanceWithoutConstructor());
}

public function testAliases(): void
{
$this->assertFalse(TagReference::isTagAlias('test'));
$this->assertFalse(TagReference::isTagAlias('tag#test'));
$this->assertTrue(TagReference::isTagAlias('tag@test'));
}

public function testExtractTag(): void
{
$this->assertEquals('test', TagReference::extractTagFromAlias('tag@test'));
}

public function testExtractWrongTagDelimiter(): void
{
$this->expectException(InvalidArgumentException::class);
TagReference::extractTagFromAlias('tag#test');
}

public function testExtractWrongTagFormat(): void
{
$this->expectException(InvalidArgumentException::class);
TagReference::extractTagFromAlias('test');
}

public function testReference(): void
{
$reference = TagReference::to('test');
$spyContainer = new class () implements ContainerInterface {
public function get($id)
{
return $id;
}

public function has($id): bool
{
return true;
}
};

$result = $reference->resolve($spyContainer);

$this->assertEquals('tag@test', $result);
}
}

0 comments on commit fedff5e

Please sign in to comment.