[DI] leverage Contracts\Service
This commit is contained in:
parent
25ca59d5e7
commit
87392ab30d
@ -50,7 +50,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
@ -102,6 +101,7 @@ use Symfony\Component\Workflow\WorkflowInterface;
|
||||
use Symfony\Component\Yaml\Command\LintCommand as BaseYamlLintCommand;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Symfony\Contracts\Service\ResetInterface;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
|
||||
/**
|
||||
* FrameworkExtension.
|
||||
|
@ -13,8 +13,8 @@ namespace Symfony\Bundle\FrameworkBundle\Test;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\ResettableContainerInterface;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Contracts\Service\ResetInterface;
|
||||
|
||||
/**
|
||||
* KernelTestCase is the base class for tests needing a Kernel.
|
||||
@ -119,7 +119,7 @@ abstract class KernelTestCase extends TestCase
|
||||
if (null !== static::$kernel) {
|
||||
$container = static::$kernel->getContainer();
|
||||
static::$kernel->shutdown();
|
||||
if ($container instanceof ResettableContainerInterface) {
|
||||
if ($container instanceof ResetInterface) {
|
||||
$container->reset();
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,9 @@
|
||||
|
||||
namespace Symfony\Component\Config\Resource;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
|
||||
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface as LegacyServiceSubscriberInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
@ -157,7 +158,10 @@ class ReflectionClassResource implements SelfCheckingResourceInterface, \Seriali
|
||||
yield print_r(\call_user_func(array($class->name, 'getSubscribedEvents')), true);
|
||||
}
|
||||
|
||||
if (interface_exists(ServiceSubscriberInterface::class, false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) {
|
||||
if (interface_exists(LegacyServiceSubscriberInterface::class, false) && $class->isSubclassOf(LegacyServiceSubscriberInterface::class)) {
|
||||
yield LegacyServiceSubscriberInterface::class;
|
||||
yield print_r(\call_user_func(array($class->name, 'getSubscribedServices')), true);
|
||||
} elseif (interface_exists(ServiceSubscriberInterface::class, false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) {
|
||||
yield ServiceSubscriberInterface::class;
|
||||
yield print_r(\call_user_func(array($class->name, 'getSubscribedServices')), true);
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ CHANGELOG
|
||||
* added `ServiceLocatorArgument` and `!service_locator` config tag for creating optimized service-locators
|
||||
* added support for autoconfiguring bindings
|
||||
* added `%env(key:...)%` processor to fetch a specific key from an array
|
||||
* deprecated `ServiceSubscriberInterface`, use the same interface from the `Symfony\Contracts\Service` namespace instead
|
||||
* deprecated `ResettableContainerInterface`, use `Symfony\Contracts\Service\ResetInterface` instead
|
||||
|
||||
4.1.0
|
||||
-----
|
||||
|
@ -15,8 +15,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
|
||||
use Symfony\Component\DependencyInjection\TypedReference;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Compiler pass to register tagged services that require a service locator.
|
||||
|
@ -19,6 +19,8 @@ use Symfony\Contracts\Service\ResetInterface;
|
||||
* not needed anymore.
|
||||
*
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
*
|
||||
* @deprecated since Symfony 4.2, use "Symfony\Contracts\Service\ResetInterface" instead.
|
||||
*/
|
||||
interface ResettableContainerInterface extends ContainerInterface, ResetInterface
|
||||
{
|
||||
|
@ -11,10 +11,14 @@
|
||||
|
||||
namespace Symfony\Component\DependencyInjection;
|
||||
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\ContainerInterface as PsrContainerInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
|
||||
use Symfony\Contracts\Service\ServiceLocatorTrait;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
|
||||
/**
|
||||
* @author Robin Chalas <robin.chalas@gmail.com>
|
||||
@ -22,51 +26,22 @@ use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
|
||||
*/
|
||||
class ServiceLocator implements PsrContainerInterface
|
||||
{
|
||||
private $factories;
|
||||
private $loading = array();
|
||||
use ServiceLocatorTrait {
|
||||
get as private doGet;
|
||||
}
|
||||
|
||||
private $externalId;
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* @param callable[] $factories
|
||||
*/
|
||||
public function __construct(array $factories)
|
||||
{
|
||||
$this->factories = $factories;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function has($id)
|
||||
{
|
||||
return isset($this->factories[$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($id)
|
||||
{
|
||||
if (!isset($this->factories[$id])) {
|
||||
throw new ServiceNotFoundException($id, end($this->loading) ?: null, null, array(), $this->createServiceNotFoundMessage($id));
|
||||
if (!$this->externalId) {
|
||||
return $this->doGet($id);
|
||||
}
|
||||
|
||||
if (isset($this->loading[$id])) {
|
||||
$ids = array_values($this->loading);
|
||||
$ids = \array_slice($this->loading, array_search($id, $ids));
|
||||
$ids[] = $id;
|
||||
|
||||
throw new ServiceCircularReferenceException($id, $ids);
|
||||
}
|
||||
|
||||
$this->loading[$id] = $id;
|
||||
try {
|
||||
return $this->factories[$id]();
|
||||
return $this->doGet($id);
|
||||
} catch (RuntimeException $e) {
|
||||
if (!$this->externalId) {
|
||||
throw $e;
|
||||
}
|
||||
$what = sprintf('service "%s" required by "%s"', $id, $this->externalId);
|
||||
$message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage());
|
||||
|
||||
@ -79,8 +54,6 @@ class ServiceLocator implements PsrContainerInterface
|
||||
$r->setValue($e, $message);
|
||||
|
||||
throw $e;
|
||||
} finally {
|
||||
unset($this->loading[$id]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,14 +74,16 @@ class ServiceLocator implements PsrContainerInterface
|
||||
return $locator;
|
||||
}
|
||||
|
||||
private function createServiceNotFoundMessage($id)
|
||||
private function createNotFoundException(string $id): NotFoundExceptionInterface
|
||||
{
|
||||
if ($this->loading) {
|
||||
return sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $this->formatAlternatives());
|
||||
$msg = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $this->formatAlternatives());
|
||||
|
||||
return new ServiceNotFoundException($id, end($this->loading) ?: null, null, array(), $msg);
|
||||
}
|
||||
|
||||
$class = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, 3);
|
||||
$class = isset($class[2]['object']) ? \get_class($class[2]['object']) : null;
|
||||
$class = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, 4);
|
||||
$class = isset($class[3]['object']) ? \get_class($class[3]['object']) : null;
|
||||
$externalId = $this->externalId ?: $class;
|
||||
|
||||
$msg = sprintf('Service "%s" not found: ', $id);
|
||||
@ -143,7 +118,12 @@ class ServiceLocator implements PsrContainerInterface
|
||||
$msg .= 'Try using dependency injection instead.';
|
||||
}
|
||||
|
||||
return $msg;
|
||||
return new ServiceNotFoundException($id, end($this->loading) ?: null, null, array(), $msg);
|
||||
}
|
||||
|
||||
private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface
|
||||
{
|
||||
return new ServiceCircularReferenceException($id, $path);
|
||||
}
|
||||
|
||||
private function formatAlternatives(array $alternatives = null, $separator = 'and')
|
||||
|
@ -11,40 +11,13 @@
|
||||
|
||||
namespace Symfony\Component\DependencyInjection;
|
||||
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface as BaseServiceSubscriberInterface;
|
||||
|
||||
/**
|
||||
* A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method.
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* The getSubscribedServices method returns an array of service types required by such instances,
|
||||
* optionally keyed by the service names used internally. Service types that start with an interrogation
|
||||
* mark "?" are optional, while the other ones are mandatory service dependencies.
|
||||
*
|
||||
* The injected service locators SHOULD NOT allow access to any other services not specified by the method.
|
||||
*
|
||||
* It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally.
|
||||
* This interface does not dictate any injection method for these service locators, although constructor
|
||||
* injection is recommended.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
* @deprecated since Symfony 4.2, use Symfony\Contracts\Service\ServiceSubscriberInterface instead.
|
||||
*/
|
||||
interface ServiceSubscriberInterface
|
||||
interface ServiceSubscriberInterface extends BaseServiceSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Returns an array of service types required by such instances, optionally keyed by the service names used internally.
|
||||
*
|
||||
* For mandatory dependencies:
|
||||
*
|
||||
* * array('logger' => 'Psr\Log\LoggerInterface') means the objects use the "logger" name
|
||||
* internally to fetch a service which must implement Psr\Log\LoggerInterface.
|
||||
* * array('Psr\Log\LoggerInterface') is a shortcut for
|
||||
* * array('Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface')
|
||||
*
|
||||
* otherwise:
|
||||
*
|
||||
* * array('logger' => '?Psr\Log\LoggerInterface') denotes an optional dependency
|
||||
* * array('?Psr\Log\LoggerInterface') is a shortcut for
|
||||
* * array('Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface')
|
||||
*
|
||||
* @return array The required service types, optionally keyed by service names
|
||||
*/
|
||||
public static function getSubscribedServices();
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ class RegisterServiceSubscribersPassTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
||||
* @expectedExceptionMessage Service "foo" must implement interface "Symfony\Component\DependencyInjection\ServiceSubscriberInterface".
|
||||
* @expectedExceptionMessage Service "foo" must implement interface "Symfony\Contracts\Service\ServiceSubscriberInterface".
|
||||
*/
|
||||
public function testInvalidClass()
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
|
||||
class TestServiceSubscriber implements ServiceSubscriberInterface
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberTrait;
|
||||
|
||||
class TestServiceSubscriberParent implements ServiceSubscriberInterface
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper;
|
||||
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
|
||||
function sc_configure($instance)
|
||||
{
|
||||
|
@ -13,7 +13,7 @@ namespace Symfony\Component\DependencyInjection\Tests;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
use Symfony\Contracts\Tests\Service\ServiceLocatorTest as BaseServiceLocatorTest;
|
||||
|
||||
class ServiceLocatorTest extends BaseServiceLocatorTest
|
||||
@ -74,7 +74,7 @@ class ServiceLocatorTest extends BaseServiceLocatorTest
|
||||
}
|
||||
}
|
||||
|
||||
class SomeServiceSubscriber implements ServiceSubscriberinterface
|
||||
class SomeServiceSubscriber implements ServiceSubscriberInterface
|
||||
{
|
||||
public $container;
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
namespace Symfony\Component\HttpKernel\Tests\EventListener;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
@ -144,15 +143,6 @@ class TestSessionListenerTest extends TestCase
|
||||
$this->filterResponse(new Request());
|
||||
}
|
||||
|
||||
public function testDoesNotImplementServiceSubscriberInterface()
|
||||
{
|
||||
$this->assertTrue(interface_exists(ServiceSubscriberInterface::class));
|
||||
$this->assertTrue(class_exists(SessionListener::class));
|
||||
$this->assertTrue(class_exists(TestSessionListener::class));
|
||||
$this->assertFalse(is_subclass_of(SessionListener::class, ServiceSubscriberInterface::class), 'Implementing ServiceSubscriberInterface would create a dep on the DI component, which eg Silex cannot afford');
|
||||
$this->assertFalse(is_subclass_of(TestSessionListener::class, ServiceSubscriberInterface::class, 'Implementing ServiceSubscriberInterface would create a dep on the DI component, which eg Silex cannot afford'));
|
||||
}
|
||||
|
||||
public function testDoesNotThrowIfRequestDoesNotHaveASession()
|
||||
{
|
||||
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
|
||||
|
Reference in New Issue
Block a user