Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 29a47fc

Browse filesBrowse files
committed
add simple decorator support
1 parent a45af9a commit 29a47fc
Copy full SHA for 29a47fc

File tree

9 files changed

+74
-75
lines changed
Filter options

9 files changed

+74
-75
lines changed

‎src/Symfony/Component/Decorator/Attribute/Decorate.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Decorator/Attribute/Decorate.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
class Decorate
2323
{
2424
/**
25-
* @param string $id The decorator service id
25+
* @param string $id The decorator identifier
2626
* @param array<string, mixed> $options The decorator options to pass through
2727
*/
2828
public function __construct(

‎src/Symfony/Component/Decorator/DecoratorChain.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Decorator/DecoratorChain.php
+9-14Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
use Psr\Container\ContainerInterface;
1515
use Symfony\Component\Decorator\Attribute\Decorate;
16-
use Symfony\Contracts\Service\ServiceLocatorTrait;
1716

1817
/**
1918
* @author Yonel Ceruto <open@yceruto.dev>
@@ -23,23 +22,13 @@
2322
class DecoratorChain implements DecoratorInterface
2423
{
2524
/**
26-
* @param ContainerInterface $decorators Locator of decorators, keyed by service id
25+
* @param ContainerInterface $decorators Locator of decorators, keyed by identifier
2726
*/
2827
public function __construct(
29-
private readonly ContainerInterface $decorators,
28+
private readonly ContainerInterface $decorators = new DecoratorLocator([]),
3029
) {
3130
}
3231

33-
/**
34-
* @param array<string, callable(): DecoratorInterface> $decorators
35-
*/
36-
public static function from(array $decorators): self
37-
{
38-
return new self(new class($decorators) implements ContainerInterface {
39-
use ServiceLocatorTrait;
40-
});
41-
}
42-
4332
public function call(callable $callable, mixed ...$args): mixed
4433
{
4534
return $this->decorate($callable(...))(...$args);
@@ -48,7 +37,13 @@ public function call(callable $callable, mixed ...$args): mixed
4837
public function decorate(\Closure $func): \Closure
4938
{
5039
foreach ($this->getAttributes($func) as $attribute) {
51-
$func = $this->decorators->get($attribute->id)->decorate($func, ...$attribute->options);
40+
if ($attribute instanceof DecoratorInterface && !$this->decorators->has($attribute->id)) {
41+
$decorator = $attribute;
42+
} else {
43+
$decorator = $this->decorators->get($attribute->id);
44+
}
45+
46+
$func = $decorator->decorate($func, ...$attribute->options);
5247
}
5348

5449
return $func;

‎src/Symfony/Component/Decorator/DecoratorInterface.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Decorator/DecoratorInterface.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
namespace Symfony\Component\Decorator;
1313

1414
/**
15-
* Decorates the functionality of other function.
15+
* Decorates the functionality of a given function.
1616
*
1717
* @author Yonel Ceruto <open@yceruto.dev>
1818
*
+30Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Decorator;
13+
14+
use Psr\Container\ContainerInterface;
15+
use Symfony\Contracts\Service\ServiceLocatorTrait;
16+
17+
/**
18+
* @author Yonel Ceruto <open@yceruto.dev>
19+
*/
20+
class DecoratorLocator implements ContainerInterface
21+
{
22+
use ServiceLocatorTrait {
23+
get as private doGet;
24+
}
25+
26+
public function get(string $id): DecoratorInterface
27+
{
28+
return $this->doGet($id);
29+
}
30+
}

‎src/Symfony/Component/Decorator/README.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Decorator/README.md
+17-22Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,51 +21,46 @@ use Symfony\Component\Decorator\Attribute\Decorate;
2121
use Symfony\Component\Decorator\DecoratorChain;
2222
use Symfony\Component\Decorator\DecoratorInterface;
2323

24-
class DebugDecorator implements DecoratorInterface
24+
#[\Attribute(\Attribute::TARGET_METHOD)]
25+
class MyDecorator extends Decorate implements DecoratorInterface
2526
{
27+
public function __construct()
28+
{
29+
parent::__construct(self::class);
30+
}
31+
2632
public function decorate(\Closure $func): \Closure
2733
{
28-
return function (mixed ...$args) use ($func): mixed {
34+
return function (mixed ...$args) use ($func): mixed
35+
{
2936
echo "Do something before\n";
3037

3138
$result = $func(...$args);
3239

3340
echo "Do something after\n";
3441

3542
return $result;
36-
}
37-
}
38-
}
39-
40-
$decorator = DecoratorChain::from([
41-
DebugDecorator::class => fn () => new DebugDecorator(),
42-
]);
43-
44-
#[\Attribute(\Attribute::TARGET_METHOD)]
45-
class Debug extends Decorate
46-
{
47-
public function __construct()
48-
{
49-
parent::__construct(DebugDecorator::class);
43+
};
5044
}
5145
}
5246

5347
class Greeting
5448
{
55-
#[Debug]
56-
public function hello(string $name): void
49+
#[MyDecorator]
50+
public function sayHello(string $name): void
5751
{
58-
echo "Hello $name\n"
52+
echo "Hello $name!\n";
5953
}
6054
}
61-
6255
$greeting = new Greeting();
63-
$decorator->call($greeting->hello(...), 'Fabien');
56+
57+
$decorator = new DecoratorChain();
58+
$decorator->call($greeting->sayHello(...), 'Fabien');
6459
```
6560
Output:
6661
```
6762
Do something before
68-
Hello Fabien
63+
Hello Fabien!
6964
Do something after
7065
```
7166

‎src/Symfony/Component/Decorator/Tests/DecoratorChainTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Decorator/Tests/DecoratorChainTest.php
+3-4Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Decorator\DecoratorChain;
16+
use Symfony\Component\Decorator\DecoratorLocator;
1617
use Symfony\Component\Decorator\Tests\Fixtures\Controller\CreateTaskController;
17-
use Symfony\Component\Decorator\Tests\Fixtures\Decorator\JsonDecorator;
1818
use Symfony\Component\Decorator\Tests\Fixtures\Decorator\Logging;
1919
use Symfony\Component\Decorator\Tests\Fixtures\Decorator\LoggingDecorator;
2020
use Symfony\Component\Decorator\Tests\Fixtures\Handler\Message;
@@ -29,10 +29,9 @@ class DecoratorChainTest extends TestCase
2929
protected function setUp(): void
3030
{
3131
$this->logger = new TestLogger();
32-
$this->decorator = DecoratorChain::from([
33-
JsonDecorator::class => fn () => new JsonDecorator(),
32+
$this->decorator = new DecoratorChain(new DecoratorLocator([
3433
LoggingDecorator::class => fn () => new LoggingDecorator($this->logger),
35-
]);
34+
]));
3635
}
3736

3837
public function testTopDecoratedFunc()

‎src/Symfony/Component/Decorator/Tests/DependencyInjection/DecoratorPassTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Decorator/Tests/DependencyInjection/DecoratorPassTest.php
+1-5Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Decorator\DecoratorChain;
1616
use Symfony\Component\Decorator\DependencyInjection\DecoratorsPass;
17-
use Symfony\Component\Decorator\Tests\Fixtures\Decorator\JsonDecorator;
1817
use Symfony\Component\Decorator\Tests\Fixtures\Decorator\LoggingDecorator;
1918
use Symfony\Component\Decorator\Tests\Fixtures\Handler\Message;
2019
use Symfony\Component\Decorator\Tests\Fixtures\Handler\MessageHandler;
@@ -36,7 +35,7 @@ public function testDefinition()
3635
$argument = $container->getDefinition('decorator.chain')->getArgument(0);
3736

3837
$this->assertInstanceOf(ServiceLocatorArgument::class, $argument);
39-
$this->assertSame(['decorator.json', LoggingDecorator::class], array_keys($argument->getValues()));
38+
$this->assertSame([LoggingDecorator::class], array_keys($argument->getValues()));
4039
}
4140

4241
public function testService()
@@ -76,9 +75,6 @@ private function getDefinition(): ContainerBuilder
7675
->addArgument(new AbstractArgument('set in DecoratorPass'))
7776
->setPublic(true);
7877

79-
$container->register('decorator.json', JsonDecorator::class)
80-
->addTag('decorator');
81-
8278
$container->register(TestLogger::class)
8379
->setPublic(true);
8480

‎src/Symfony/Component/Decorator/Tests/Fixtures/Decorator/Json.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Decorator/Tests/Fixtures/Decorator/Json.php
+12-2Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,22 @@
1212
namespace Symfony\Component\Decorator\Tests\Fixtures\Decorator;
1313

1414
use Symfony\Component\Decorator\Attribute\Decorate;
15+
use Symfony\Component\Decorator\DecoratorInterface;
1516

1617
#[\Attribute(\Attribute::TARGET_METHOD)]
17-
final class Json extends Decorate
18+
final class Json extends Decorate implements DecoratorInterface
1819
{
1920
public function __construct()
2021
{
21-
parent::__construct(JsonDecorator::class);
22+
parent::__construct(self::class);
23+
}
24+
25+
public function decorate(\Closure $func): \Closure
26+
{
27+
return static function (mixed ...$args) use ($func): string {
28+
$result = $func(...$args);
29+
30+
return json_encode($result, JSON_THROW_ON_ERROR);
31+
};
2232
}
2333
}

‎src/Symfony/Component/Decorator/Tests/Fixtures/Decorator/JsonDecorator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Decorator/Tests/Fixtures/Decorator/JsonDecorator.php
-26Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.