diff options
Diffstat (limited to 'vendor/symfony/service-contracts')
15 files changed, 711 insertions, 0 deletions
diff --git a/vendor/symfony/service-contracts/Attribute/Required.php b/vendor/symfony/service-contracts/Attribute/Required.php new file mode 100644 index 0000000..9df8511 --- /dev/null +++ b/vendor/symfony/service-contracts/Attribute/Required.php | |||
@@ -0,0 +1,25 @@ | |||
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\Contracts\Service\Attribute; | ||
13 | |||
14 | /** | ||
15 | * A required dependency. | ||
16 | * | ||
17 | * This attribute indicates that a property holds a required dependency. The annotated property or method should be | ||
18 | * considered during the instantiation process of the containing class. | ||
19 | * | ||
20 | * @author Alexander M. Turek <me@derrabus.de> | ||
21 | */ | ||
22 | #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] | ||
23 | final class Required | ||
24 | { | ||
25 | } | ||
diff --git a/vendor/symfony/service-contracts/Attribute/SubscribedService.php b/vendor/symfony/service-contracts/Attribute/SubscribedService.php new file mode 100644 index 0000000..f850b84 --- /dev/null +++ b/vendor/symfony/service-contracts/Attribute/SubscribedService.php | |||
@@ -0,0 +1,47 @@ | |||
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\Contracts\Service\Attribute; | ||
13 | |||
14 | use Symfony\Contracts\Service\ServiceMethodsSubscriberTrait; | ||
15 | use Symfony\Contracts\Service\ServiceSubscriberInterface; | ||
16 | |||
17 | /** | ||
18 | * For use as the return value for {@see ServiceSubscriberInterface}. | ||
19 | * | ||
20 | * @example new SubscribedService('http_client', HttpClientInterface::class, false, new Target('githubApi')) | ||
21 | * | ||
22 | * Use with {@see ServiceMethodsSubscriberTrait} to mark a method's return type | ||
23 | * as a subscribed service. | ||
24 | * | ||
25 | * @author Kevin Bond <kevinbond@gmail.com> | ||
26 | */ | ||
27 | #[\Attribute(\Attribute::TARGET_METHOD)] | ||
28 | final class SubscribedService | ||
29 | { | ||
30 | /** @var object[] */ | ||
31 | public array $attributes; | ||
32 | |||
33 | /** | ||
34 | * @param string|null $key The key to use for the service | ||
35 | * @param class-string|null $type The service class | ||
36 | * @param bool $nullable Whether the service is optional | ||
37 | * @param object|object[] $attributes One or more dependency injection attributes to use | ||
38 | */ | ||
39 | public function __construct( | ||
40 | public ?string $key = null, | ||
41 | public ?string $type = null, | ||
42 | public bool $nullable = false, | ||
43 | array|object $attributes = [], | ||
44 | ) { | ||
45 | $this->attributes = \is_array($attributes) ? $attributes : [$attributes]; | ||
46 | } | ||
47 | } | ||
diff --git a/vendor/symfony/service-contracts/CHANGELOG.md b/vendor/symfony/service-contracts/CHANGELOG.md new file mode 100644 index 0000000..7932e26 --- /dev/null +++ b/vendor/symfony/service-contracts/CHANGELOG.md | |||
@@ -0,0 +1,5 @@ | |||
1 | CHANGELOG | ||
2 | ========= | ||
3 | |||
4 | The changelog is maintained for all Symfony contracts at the following URL: | ||
5 | https://github.com/symfony/contracts/blob/main/CHANGELOG.md | ||
diff --git a/vendor/symfony/service-contracts/LICENSE b/vendor/symfony/service-contracts/LICENSE new file mode 100644 index 0000000..7536cae --- /dev/null +++ b/vendor/symfony/service-contracts/LICENSE | |||
@@ -0,0 +1,19 @@ | |||
1 | Copyright (c) 2018-present Fabien Potencier | ||
2 | |||
3 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
4 | of this software and associated documentation files (the "Software"), to deal | ||
5 | in the Software without restriction, including without limitation the rights | ||
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
7 | copies of the Software, and to permit persons to whom the Software is furnished | ||
8 | to do so, subject to the following conditions: | ||
9 | |||
10 | The above copyright notice and this permission notice shall be included in all | ||
11 | copies or substantial portions of the Software. | ||
12 | |||
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
19 | THE SOFTWARE. | ||
diff --git a/vendor/symfony/service-contracts/README.md b/vendor/symfony/service-contracts/README.md new file mode 100644 index 0000000..42841a5 --- /dev/null +++ b/vendor/symfony/service-contracts/README.md | |||
@@ -0,0 +1,9 @@ | |||
1 | Symfony Service Contracts | ||
2 | ========================= | ||
3 | |||
4 | A set of abstractions extracted out of the Symfony components. | ||
5 | |||
6 | Can be used to build on semantics that the Symfony components proved useful and | ||
7 | that already have battle tested implementations. | ||
8 | |||
9 | See https://github.com/symfony/contracts/blob/main/README.md for more information. | ||
diff --git a/vendor/symfony/service-contracts/ResetInterface.php b/vendor/symfony/service-contracts/ResetInterface.php new file mode 100644 index 0000000..a4f389b --- /dev/null +++ b/vendor/symfony/service-contracts/ResetInterface.php | |||
@@ -0,0 +1,33 @@ | |||
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\Contracts\Service; | ||
13 | |||
14 | /** | ||
15 | * Provides a way to reset an object to its initial state. | ||
16 | * | ||
17 | * When calling the "reset()" method on an object, it should be put back to its | ||
18 | * initial state. This usually means clearing any internal buffers and forwarding | ||
19 | * the call to internal dependencies. All properties of the object should be put | ||
20 | * back to the same state it had when it was first ready to use. | ||
21 | * | ||
22 | * This method could be called, for example, to recycle objects that are used as | ||
23 | * services, so that they can be used to handle several requests in the same | ||
24 | * process loop (note that we advise making your services stateless instead of | ||
25 | * implementing this interface when possible.) | ||
26 | */ | ||
27 | interface ResetInterface | ||
28 | { | ||
29 | /** | ||
30 | * @return void | ||
31 | */ | ||
32 | public function reset(); | ||
33 | } | ||
diff --git a/vendor/symfony/service-contracts/ServiceCollectionInterface.php b/vendor/symfony/service-contracts/ServiceCollectionInterface.php new file mode 100644 index 0000000..2333139 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceCollectionInterface.php | |||
@@ -0,0 +1,26 @@ | |||
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\Contracts\Service; | ||
13 | |||
14 | /** | ||
15 | * A ServiceProviderInterface that is also countable and iterable. | ||
16 | * | ||
17 | * @author Kevin Bond <kevinbond@gmail.com> | ||
18 | * | ||
19 | * @template-covariant T of mixed | ||
20 | * | ||
21 | * @extends ServiceProviderInterface<T> | ||
22 | * @extends \IteratorAggregate<string, T> | ||
23 | */ | ||
24 | interface ServiceCollectionInterface extends ServiceProviderInterface, \Countable, \IteratorAggregate | ||
25 | { | ||
26 | } | ||
diff --git a/vendor/symfony/service-contracts/ServiceLocatorTrait.php b/vendor/symfony/service-contracts/ServiceLocatorTrait.php new file mode 100644 index 0000000..b62ec3e --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceLocatorTrait.php | |||
@@ -0,0 +1,115 @@ | |||
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\Contracts\Service; | ||
13 | |||
14 | use Psr\Container\ContainerExceptionInterface; | ||
15 | use Psr\Container\NotFoundExceptionInterface; | ||
16 | |||
17 | // Help opcache.preload discover always-needed symbols | ||
18 | class_exists(ContainerExceptionInterface::class); | ||
19 | class_exists(NotFoundExceptionInterface::class); | ||
20 | |||
21 | /** | ||
22 | * A trait to help implement ServiceProviderInterface. | ||
23 | * | ||
24 | * @author Robin Chalas <robin.chalas@gmail.com> | ||
25 | * @author Nicolas Grekas <p@tchwork.com> | ||
26 | */ | ||
27 | trait ServiceLocatorTrait | ||
28 | { | ||
29 | private array $factories; | ||
30 | private array $loading = []; | ||
31 | private array $providedTypes; | ||
32 | |||
33 | /** | ||
34 | * @param array<string, callable> $factories | ||
35 | */ | ||
36 | public function __construct(array $factories) | ||
37 | { | ||
38 | $this->factories = $factories; | ||
39 | } | ||
40 | |||
41 | public function has(string $id): bool | ||
42 | { | ||
43 | return isset($this->factories[$id]); | ||
44 | } | ||
45 | |||
46 | public function get(string $id): mixed | ||
47 | { | ||
48 | if (!isset($this->factories[$id])) { | ||
49 | throw $this->createNotFoundException($id); | ||
50 | } | ||
51 | |||
52 | if (isset($this->loading[$id])) { | ||
53 | $ids = array_values($this->loading); | ||
54 | $ids = \array_slice($this->loading, array_search($id, $ids)); | ||
55 | $ids[] = $id; | ||
56 | |||
57 | throw $this->createCircularReferenceException($id, $ids); | ||
58 | } | ||
59 | |||
60 | $this->loading[$id] = $id; | ||
61 | try { | ||
62 | return $this->factories[$id]($this); | ||
63 | } finally { | ||
64 | unset($this->loading[$id]); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | public function getProvidedServices(): array | ||
69 | { | ||
70 | if (!isset($this->providedTypes)) { | ||
71 | $this->providedTypes = []; | ||
72 | |||
73 | foreach ($this->factories as $name => $factory) { | ||
74 | if (!\is_callable($factory)) { | ||
75 | $this->providedTypes[$name] = '?'; | ||
76 | } else { | ||
77 | $type = (new \ReflectionFunction($factory))->getReturnType(); | ||
78 | |||
79 | $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '').($type instanceof \ReflectionNamedType ? $type->getName() : $type) : '?'; | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | |||
84 | return $this->providedTypes; | ||
85 | } | ||
86 | |||
87 | private function createNotFoundException(string $id): NotFoundExceptionInterface | ||
88 | { | ||
89 | if (!$alternatives = array_keys($this->factories)) { | ||
90 | $message = 'is empty...'; | ||
91 | } else { | ||
92 | $last = array_pop($alternatives); | ||
93 | if ($alternatives) { | ||
94 | $message = sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last); | ||
95 | } else { | ||
96 | $message = sprintf('only knows about the "%s" service.', $last); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | if ($this->loading) { | ||
101 | $message = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message); | ||
102 | } else { | ||
103 | $message = sprintf('Service "%s" not found: the current service locator %s', $id, $message); | ||
104 | } | ||
105 | |||
106 | return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface { | ||
107 | }; | ||
108 | } | ||
109 | |||
110 | private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface | ||
111 | { | ||
112 | return new class(sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface { | ||
113 | }; | ||
114 | } | ||
115 | } | ||
diff --git a/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php b/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php new file mode 100644 index 0000000..0d89d9f --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php | |||
@@ -0,0 +1,80 @@ | |||
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\Contracts\Service; | ||
13 | |||
14 | use Psr\Container\ContainerInterface; | ||
15 | use Symfony\Contracts\Service\Attribute\Required; | ||
16 | use Symfony\Contracts\Service\Attribute\SubscribedService; | ||
17 | |||
18 | /** | ||
19 | * Implementation of ServiceSubscriberInterface that determines subscribed services | ||
20 | * from methods that have the #[SubscribedService] attribute. | ||
21 | * | ||
22 | * Service ids are available as "ClassName::methodName" so that the implementation | ||
23 | * of subscriber methods can be just `return $this->container->get(__METHOD__);`. | ||
24 | * | ||
25 | * @author Kevin Bond <kevinbond@gmail.com> | ||
26 | */ | ||
27 | trait ServiceMethodsSubscriberTrait | ||
28 | { | ||
29 | protected ContainerInterface $container; | ||
30 | |||
31 | public static function getSubscribedServices(): array | ||
32 | { | ||
33 | $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; | ||
34 | |||
35 | foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { | ||
36 | if (self::class !== $method->getDeclaringClass()->name) { | ||
37 | continue; | ||
38 | } | ||
39 | |||
40 | if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { | ||
41 | continue; | ||
42 | } | ||
43 | |||
44 | if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { | ||
45 | throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); | ||
46 | } | ||
47 | |||
48 | if (!$returnType = $method->getReturnType()) { | ||
49 | throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); | ||
50 | } | ||
51 | |||
52 | /* @var SubscribedService $attribute */ | ||
53 | $attribute = $attribute->newInstance(); | ||
54 | $attribute->key ??= self::class.'::'.$method->name; | ||
55 | $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; | ||
56 | $attribute->nullable = $returnType->allowsNull(); | ||
57 | |||
58 | if ($attribute->attributes) { | ||
59 | $services[] = $attribute; | ||
60 | } else { | ||
61 | $services[$attribute->key] = ($attribute->nullable ? '?' : '').$attribute->type; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | return $services; | ||
66 | } | ||
67 | |||
68 | #[Required] | ||
69 | public function setContainer(ContainerInterface $container): ?ContainerInterface | ||
70 | { | ||
71 | $ret = null; | ||
72 | if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { | ||
73 | $ret = parent::setContainer($container); | ||
74 | } | ||
75 | |||
76 | $this->container = $container; | ||
77 | |||
78 | return $ret; | ||
79 | } | ||
80 | } | ||
diff --git a/vendor/symfony/service-contracts/ServiceProviderInterface.php b/vendor/symfony/service-contracts/ServiceProviderInterface.php new file mode 100644 index 0000000..2e71f00 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceProviderInterface.php | |||
@@ -0,0 +1,45 @@ | |||
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\Contracts\Service; | ||
13 | |||
14 | use Psr\Container\ContainerInterface; | ||
15 | |||
16 | /** | ||
17 | * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container. | ||
18 | * | ||
19 | * @author Nicolas Grekas <p@tchwork.com> | ||
20 | * @author Mateusz Sip <mateusz.sip@gmail.com> | ||
21 | * | ||
22 | * @template-covariant T of mixed | ||
23 | */ | ||
24 | interface ServiceProviderInterface extends ContainerInterface | ||
25 | { | ||
26 | /** | ||
27 | * @return T | ||
28 | */ | ||
29 | public function get(string $id): mixed; | ||
30 | |||
31 | public function has(string $id): bool; | ||
32 | |||
33 | /** | ||
34 | * Returns an associative array of service types keyed by the identifiers provided by the current container. | ||
35 | * | ||
36 | * Examples: | ||
37 | * | ||
38 | * * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface | ||
39 | * * ['foo' => '?'] means the container provides service name "foo" of unspecified type | ||
40 | * * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null | ||
41 | * | ||
42 | * @return array<string, string> The provided service types, keyed by service names | ||
43 | */ | ||
44 | public function getProvidedServices(): array; | ||
45 | } | ||
diff --git a/vendor/symfony/service-contracts/ServiceSubscriberInterface.php b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php new file mode 100644 index 0000000..3da1916 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php | |||
@@ -0,0 +1,62 @@ | |||
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\Contracts\Service; | ||
13 | |||
14 | use Symfony\Contracts\Service\Attribute\SubscribedService; | ||
15 | |||
16 | /** | ||
17 | * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. | ||
18 | * | ||
19 | * The getSubscribedServices method returns an array of service types required by such instances, | ||
20 | * optionally keyed by the service names used internally. Service types that start with an interrogation | ||
21 | * mark "?" are optional, while the other ones are mandatory service dependencies. | ||
22 | * | ||
23 | * The injected service locators SHOULD NOT allow access to any other services not specified by the method. | ||
24 | * | ||
25 | * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally. | ||
26 | * This interface does not dictate any injection method for these service locators, although constructor | ||
27 | * injection is recommended. | ||
28 | * | ||
29 | * @author Nicolas Grekas <p@tchwork.com> | ||
30 | */ | ||
31 | interface ServiceSubscriberInterface | ||
32 | { | ||
33 | /** | ||
34 | * Returns an array of service types (or {@see SubscribedService} objects) required | ||
35 | * by such instances, optionally keyed by the service names used internally. | ||
36 | * | ||
37 | * For mandatory dependencies: | ||
38 | * | ||
39 | * * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name | ||
40 | * internally to fetch a service which must implement Psr\Log\LoggerInterface. | ||
41 | * * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name | ||
42 | * internally to fetch an iterable of Psr\Log\LoggerInterface instances. | ||
43 | * * ['Psr\Log\LoggerInterface'] is a shortcut for | ||
44 | * * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface'] | ||
45 | * | ||
46 | * otherwise: | ||
47 | * | ||
48 | * * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency | ||
49 | * * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency | ||
50 | * * ['?Psr\Log\LoggerInterface'] is a shortcut for | ||
51 | * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface'] | ||
52 | * | ||
53 | * additionally, an array of {@see SubscribedService}'s can be returned: | ||
54 | * | ||
55 | * * [new SubscribedService('logger', Psr\Log\LoggerInterface::class)] | ||
56 | * * [new SubscribedService(type: Psr\Log\LoggerInterface::class, nullable: true)] | ||
57 | * * [new SubscribedService('http_client', HttpClientInterface::class, attributes: new Target('githubApi'))] | ||
58 | * | ||
59 | * @return string[]|SubscribedService[] The required service types, optionally keyed by service names | ||
60 | */ | ||
61 | public static function getSubscribedServices(): array; | ||
62 | } | ||
diff --git a/vendor/symfony/service-contracts/ServiceSubscriberTrait.php b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php new file mode 100644 index 0000000..cc3bc32 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php | |||
@@ -0,0 +1,84 @@ | |||
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\Contracts\Service; | ||
13 | |||
14 | use Psr\Container\ContainerInterface; | ||
15 | use Symfony\Contracts\Service\Attribute\Required; | ||
16 | use Symfony\Contracts\Service\Attribute\SubscribedService; | ||
17 | |||
18 | trigger_deprecation('symfony/contracts', 'v3.5', '"%s" is deprecated, use "ServiceMethodsSubscriberTrait" instead.', ServiceSubscriberTrait::class); | ||
19 | |||
20 | /** | ||
21 | * Implementation of ServiceSubscriberInterface that determines subscribed services | ||
22 | * from methods that have the #[SubscribedService] attribute. | ||
23 | * | ||
24 | * Service ids are available as "ClassName::methodName" so that the implementation | ||
25 | * of subscriber methods can be just `return $this->container->get(__METHOD__);`. | ||
26 | * | ||
27 | * @property ContainerInterface $container | ||
28 | * | ||
29 | * @author Kevin Bond <kevinbond@gmail.com> | ||
30 | * | ||
31 | * @deprecated since symfony/contracts v3.5, use ServiceMethodsSubscriberTrait instead | ||
32 | */ | ||
33 | trait ServiceSubscriberTrait | ||
34 | { | ||
35 | public static function getSubscribedServices(): array | ||
36 | { | ||
37 | $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; | ||
38 | |||
39 | foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { | ||
40 | if (self::class !== $method->getDeclaringClass()->name) { | ||
41 | continue; | ||
42 | } | ||
43 | |||
44 | if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { | ||
45 | continue; | ||
46 | } | ||
47 | |||
48 | if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { | ||
49 | throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); | ||
50 | } | ||
51 | |||
52 | if (!$returnType = $method->getReturnType()) { | ||
53 | throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); | ||
54 | } | ||
55 | |||
56 | /* @var SubscribedService $attribute */ | ||
57 | $attribute = $attribute->newInstance(); | ||
58 | $attribute->key ??= self::class.'::'.$method->name; | ||
59 | $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; | ||
60 | $attribute->nullable = $returnType->allowsNull(); | ||
61 | |||
62 | if ($attribute->attributes) { | ||
63 | $services[] = $attribute; | ||
64 | } else { | ||
65 | $services[$attribute->key] = ($attribute->nullable ? '?' : '').$attribute->type; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | return $services; | ||
70 | } | ||
71 | |||
72 | #[Required] | ||
73 | public function setContainer(ContainerInterface $container): ?ContainerInterface | ||
74 | { | ||
75 | $ret = null; | ||
76 | if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { | ||
77 | $ret = parent::setContainer($container); | ||
78 | } | ||
79 | |||
80 | $this->container = $container; | ||
81 | |||
82 | return $ret; | ||
83 | } | ||
84 | } | ||
diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php new file mode 100644 index 0000000..07d12b4 --- /dev/null +++ b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php | |||
@@ -0,0 +1,23 @@ | |||
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\Contracts\Service\Test; | ||
13 | |||
14 | class_alias(ServiceLocatorTestCase::class, ServiceLocatorTest::class); | ||
15 | |||
16 | if (false) { | ||
17 | /** | ||
18 | * @deprecated since PHPUnit 9.6 | ||
19 | */ | ||
20 | class ServiceLocatorTest | ||
21 | { | ||
22 | } | ||
23 | } | ||
diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php new file mode 100644 index 0000000..65a3fe3 --- /dev/null +++ b/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php | |||
@@ -0,0 +1,96 @@ | |||
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\Contracts\Service\Test; | ||
13 | |||
14 | use PHPUnit\Framework\TestCase; | ||
15 | use Psr\Container\ContainerExceptionInterface; | ||
16 | use Psr\Container\ContainerInterface; | ||
17 | use Psr\Container\NotFoundExceptionInterface; | ||
18 | use Symfony\Contracts\Service\ServiceLocatorTrait; | ||
19 | |||
20 | abstract class ServiceLocatorTestCase extends TestCase | ||
21 | { | ||
22 | protected function getServiceLocator(array $factories): ContainerInterface | ||
23 | { | ||
24 | return new class($factories) implements ContainerInterface { | ||
25 | use ServiceLocatorTrait; | ||
26 | }; | ||
27 | } | ||
28 | |||
29 | public function testHas() | ||
30 | { | ||
31 | $locator = $this->getServiceLocator([ | ||
32 | 'foo' => fn () => 'bar', | ||
33 | 'bar' => fn () => 'baz', | ||
34 | fn () => 'dummy', | ||
35 | ]); | ||
36 | |||
37 | $this->assertTrue($locator->has('foo')); | ||
38 | $this->assertTrue($locator->has('bar')); | ||
39 | $this->assertFalse($locator->has('dummy')); | ||
40 | } | ||
41 | |||
42 | public function testGet() | ||
43 | { | ||
44 | $locator = $this->getServiceLocator([ | ||
45 | 'foo' => fn () => 'bar', | ||
46 | 'bar' => fn () => 'baz', | ||
47 | ]); | ||
48 | |||
49 | $this->assertSame('bar', $locator->get('foo')); | ||
50 | $this->assertSame('baz', $locator->get('bar')); | ||
51 | } | ||
52 | |||
53 | public function testGetDoesNotMemoize() | ||
54 | { | ||
55 | $i = 0; | ||
56 | $locator = $this->getServiceLocator([ | ||
57 | 'foo' => function () use (&$i) { | ||
58 | ++$i; | ||
59 | |||
60 | return 'bar'; | ||
61 | }, | ||
62 | ]); | ||
63 | |||
64 | $this->assertSame('bar', $locator->get('foo')); | ||
65 | $this->assertSame('bar', $locator->get('foo')); | ||
66 | $this->assertSame(2, $i); | ||
67 | } | ||
68 | |||
69 | public function testThrowsOnUndefinedInternalService() | ||
70 | { | ||
71 | $locator = $this->getServiceLocator([ | ||
72 | 'foo' => function () use (&$locator) { return $locator->get('bar'); }, | ||
73 | ]); | ||
74 | |||
75 | if (!$this->getExpectedException()) { | ||
76 | $this->expectException(NotFoundExceptionInterface::class); | ||
77 | $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); | ||
78 | } | ||
79 | |||
80 | $locator->get('foo'); | ||
81 | } | ||
82 | |||
83 | public function testThrowsOnCircularReference() | ||
84 | { | ||
85 | $locator = $this->getServiceLocator([ | ||
86 | 'foo' => function () use (&$locator) { return $locator->get('bar'); }, | ||
87 | 'bar' => function () use (&$locator) { return $locator->get('baz'); }, | ||
88 | 'baz' => function () use (&$locator) { return $locator->get('bar'); }, | ||
89 | ]); | ||
90 | |||
91 | $this->expectException(ContainerExceptionInterface::class); | ||
92 | $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); | ||
93 | |||
94 | $locator->get('foo'); | ||
95 | } | ||
96 | } | ||
diff --git a/vendor/symfony/service-contracts/composer.json b/vendor/symfony/service-contracts/composer.json new file mode 100644 index 0000000..fc8674a --- /dev/null +++ b/vendor/symfony/service-contracts/composer.json | |||
@@ -0,0 +1,42 @@ | |||
1 | { | ||
2 | "name": "symfony/service-contracts", | ||
3 | "type": "library", | ||
4 | "description": "Generic abstractions related to writing services", | ||
5 | "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], | ||
6 | "homepage": "https://symfony.com", | ||
7 | "license": "MIT", | ||
8 | "authors": [ | ||
9 | { | ||
10 | "name": "Nicolas Grekas", | ||
11 | "email": "p@tchwork.com" | ||
12 | }, | ||
13 | { | ||
14 | "name": "Symfony Community", | ||
15 | "homepage": "https://symfony.com/contributors" | ||
16 | } | ||
17 | ], | ||
18 | "require": { | ||
19 | "php": ">=8.1", | ||
20 | "psr/container": "^1.1|^2.0", | ||
21 | "symfony/deprecation-contracts": "^2.5|^3" | ||
22 | }, | ||
23 | "conflict": { | ||
24 | "ext-psr": "<1.1|>=2" | ||
25 | }, | ||
26 | "autoload": { | ||
27 | "psr-4": { "Symfony\\Contracts\\Service\\": "" }, | ||
28 | "exclude-from-classmap": [ | ||
29 | "/Test/" | ||
30 | ] | ||
31 | }, | ||
32 | "minimum-stability": "dev", | ||
33 | "extra": { | ||
34 | "branch-alias": { | ||
35 | "dev-main": "3.5-dev" | ||
36 | }, | ||
37 | "thanks": { | ||
38 | "name": "symfony/contracts", | ||
39 | "url": "https://github.com/symfony/contracts" | ||
40 | } | ||
41 | } | ||
42 | } | ||