From b5b33c686b1d5b3ac2f94deab3c993a798346aec Mon Sep 17 00:00:00 2001 From: Nicolas Mugnier <6680190+NicolasMugnier@users.noreply.github.com> Date: Thu, 7 Dec 2023 16:27:57 +0100 Subject: [PATCH 1/2] feat(service-proxy-pass): Lazy load proxy method instances --- .../Symfony/Config/services.php | 2 +- .../Compiler/ServiceProxyPass.php | 15 ++++++++ .../Subscriber/ServiceProxySubscriber.php | 38 ++----------------- src/Model/Request/Instance.php | 19 ++++++++++ src/Model/Request/Method.php | 2 +- 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/FrameworkBridge/Symfony/Config/services.php b/src/FrameworkBridge/Symfony/Config/services.php index 7568201..4176d14 100644 --- a/src/FrameworkBridge/Symfony/Config/services.php +++ b/src/FrameworkBridge/Symfony/Config/services.php @@ -67,7 +67,7 @@ $services->set(ServiceProxySubscriber::class) ->public() ->args([ - tagged_iterator('openclassrooms.service_proxy'), + tagged_iterator('openclassrooms.service_proxy.proxy_method_instance'), tagged_iterator('openclassrooms.service_proxy.start_up_interceptor'), ]) ->tag('kernel.event_subscriber'); diff --git a/src/FrameworkBridge/Symfony/DependencyInjection/Compiler/ServiceProxyPass.php b/src/FrameworkBridge/Symfony/DependencyInjection/Compiler/ServiceProxyPass.php index 4c066c3..97c15ea 100644 --- a/src/FrameworkBridge/Symfony/DependencyInjection/Compiler/ServiceProxyPass.php +++ b/src/FrameworkBridge/Symfony/DependencyInjection/Compiler/ServiceProxyPass.php @@ -4,7 +4,10 @@ namespace OpenClassrooms\ServiceProxy\FrameworkBridge\Symfony\DependencyInjection\Compiler; +use OpenClassrooms\ServiceProxy\Model\Request\Instance; +use OpenClassrooms\ServiceProxy\Model\Request\Method; use OpenClassrooms\ServiceProxy\ProxyFactory; +use ProxyManager\Proxy\ValueHolderInterface; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -48,5 +51,17 @@ private function buildServiceProxyFactoryDefinition(string $taggedServiceName): $factoryDefinition->setPublic($definition->isPublic()); $factoryDefinition->setLazy($definition->isLazy()); $factoryDefinition->setTags($definition->getTags()); + + $proxyRef = new \ReflectionClass($definition->getClass()); + $proxyMethodsRef = $proxyRef->getMethods(\ReflectionMethod::IS_PUBLIC); + foreach ($proxyMethodsRef as $proxyMethodRef) { + $instance = new Definition(Instance::class); + $instance->setFactory([new Reference(Instance::class), 'createFromProxy']); + $instance->setArguments([ + new Reference($taggedServiceName), + $proxyMethodRef, + ]); + $instance->setTags(['openclassrooms.service_proxy.proxy_method_instance']); + } } } diff --git a/src/FrameworkBridge/Symfony/Subscriber/ServiceProxySubscriber.php b/src/FrameworkBridge/Symfony/Subscriber/ServiceProxySubscriber.php index 9fdf2dd..50a4af3 100644 --- a/src/FrameworkBridge/Symfony/Subscriber/ServiceProxySubscriber.php +++ b/src/FrameworkBridge/Symfony/Subscriber/ServiceProxySubscriber.php @@ -28,7 +28,7 @@ final class ServiceProxySubscriber implements EventSubscriberInterface * @throws \Doctrine\Common\Annotations\AnnotationException */ public function __construct( - private readonly iterable $proxies, + private readonly iterable $proxyMethodInstances, iterable $startUpInterceptors, ) { if (!\is_array($startUpInterceptors)) { @@ -56,42 +56,12 @@ public function startUp(RequestEvent $event): void StartUpInterceptor $b ) => $a->getStartUpPriority() <=> $b->getStartUpPriority() ); - foreach ($this->getInstances() as $instance) { + foreach ($this->proxyMethodInstances as $proxyMethodInstance) { foreach ($this->startUpInterceptors as $interceptor) { - if ($interceptor->supportsStartUp($instance)) { - $interceptor->startUp($instance); + if ($interceptor->supportsStartUp($proxyMethodInstance)) { + $interceptor->startUp($proxyMethodInstance); } } } } - - /** - * @return iterable - */ - public function getInstances(): iterable - { - foreach ($this->proxies as $proxy) { - $object = $proxy; - if ($proxy instanceof ValueHolderInterface) { - $object = $proxy->getWrappedValueHolderValue(); - if ($object === null) { - continue; - } - } - $instanceRef = new \ReflectionObject($object); - $methods = $instanceRef->getMethods(\ReflectionMethod::IS_PUBLIC); - foreach ($methods as $methodRef) { - $methodAnnotations = $this->annotationReader->getMethodAnnotations($methodRef); - $instance = Instance::create( - $proxy, - $instanceRef, - Method::create( - $methodRef, - $methodAnnotations, - ) - ); - yield $instance; - } - } - } } diff --git a/src/Model/Request/Instance.php b/src/Model/Request/Instance.php index 8a44678..f36c7ac 100644 --- a/src/Model/Request/Instance.php +++ b/src/Model/Request/Instance.php @@ -6,6 +6,7 @@ use Doctrine\Common\Annotations\AnnotationException; use Doctrine\Common\Annotations\AnnotationReader; +use ProxyManager\Proxy\ValueHolderInterface; final class Instance { @@ -64,6 +65,24 @@ public static function create( return $self; } + public static function createFromProxy( + object $proxy, + \ReflectionMethod $methodRef + ): self { + $object = $proxy; + if ($proxy instanceof ValueHolderInterface) { + $object = $proxy->getWrappedValueHolderValue(); + if ($object === null) { + throw new \Exception('The proxy is not initialized.'); + } + } + return Instance::create( + $proxy, + new \ReflectionObject($object), + Method::create($methodRef) + ); + } + /** * @param array $parameters */ diff --git a/src/Model/Request/Method.php b/src/Model/Request/Method.php index 63cad01..7ddb751 100644 --- a/src/Model/Request/Method.php +++ b/src/Model/Request/Method.php @@ -35,7 +35,7 @@ private function __construct() /** * @param array $annotations */ - public static function create(\ReflectionMethod $reflection, array $annotations): self + public static function create(\ReflectionMethod $reflection, array $annotations = []): self { $self = new self(); $self->reflection = $reflection; From e908f4c9db26c29f94a04c82356de4e9ec6b65f4 Mon Sep 17 00:00:00 2001 From: Nicolas Mugnier <6680190+NicolasMugnier@users.noreply.github.com> Date: Fri, 8 Dec 2023 12:01:52 +0100 Subject: [PATCH 2/2] WIP --- .../DependencyInjection/Compiler/ServiceProxyPass.php | 7 ++++++- .../Symfony/Subscriber/ServiceProxySubscriber.php | 3 --- src/Model/Request/Instance.php | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/FrameworkBridge/Symfony/DependencyInjection/Compiler/ServiceProxyPass.php b/src/FrameworkBridge/Symfony/DependencyInjection/Compiler/ServiceProxyPass.php index 97c15ea..917022c 100644 --- a/src/FrameworkBridge/Symfony/DependencyInjection/Compiler/ServiceProxyPass.php +++ b/src/FrameworkBridge/Symfony/DependencyInjection/Compiler/ServiceProxyPass.php @@ -4,6 +4,7 @@ namespace OpenClassrooms\ServiceProxy\FrameworkBridge\Symfony\DependencyInjection\Compiler; +use OC\Common\Util\Chrono; use OpenClassrooms\ServiceProxy\Model\Request\Instance; use OpenClassrooms\ServiceProxy\Model\Request\Method; use OpenClassrooms\ServiceProxy\ProxyFactory; @@ -43,6 +44,7 @@ private function buildServiceProxies(): void private function buildServiceProxyFactoryDefinition(string $taggedServiceName): void { + Chrono::start(); $definition = $this->container->findDefinition($taggedServiceName); $factoryDefinition = new Definition($definition->getClass()); $factoryDefinition->setFactory([new Reference(ProxyFactory::class), 'createProxy']); @@ -59,9 +61,12 @@ private function buildServiceProxyFactoryDefinition(string $taggedServiceName): $instance->setFactory([new Reference(Instance::class), 'createFromProxy']); $instance->setArguments([ new Reference($taggedServiceName), - $proxyMethodRef, + $proxyMethodRef->getName(), ]); $instance->setTags(['openclassrooms.service_proxy.proxy_method_instance']); + dump($taggedServiceName.'_'.$proxyMethodRef->getName().'_instance'); + $this->container->setDefinition($taggedServiceName.'_'.$proxyMethodRef->getName().'_instance', $instance); } + Chrono::end(); } } diff --git a/src/FrameworkBridge/Symfony/Subscriber/ServiceProxySubscriber.php b/src/FrameworkBridge/Symfony/Subscriber/ServiceProxySubscriber.php index 50a4af3..c95234b 100644 --- a/src/FrameworkBridge/Symfony/Subscriber/ServiceProxySubscriber.php +++ b/src/FrameworkBridge/Symfony/Subscriber/ServiceProxySubscriber.php @@ -6,9 +6,6 @@ use Doctrine\Common\Annotations\AnnotationReader; use OpenClassrooms\ServiceProxy\Interceptor\Contract\StartUpInterceptor; -use OpenClassrooms\ServiceProxy\Model\Request\Instance; -use OpenClassrooms\ServiceProxy\Model\Request\Method; -use ProxyManager\Proxy\ValueHolderInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\RequestEvent; diff --git a/src/Model/Request/Instance.php b/src/Model/Request/Instance.php index f36c7ac..21f595c 100644 --- a/src/Model/Request/Instance.php +++ b/src/Model/Request/Instance.php @@ -67,7 +67,7 @@ public static function create( public static function createFromProxy( object $proxy, - \ReflectionMethod $methodRef + string $methodName ): self { $object = $proxy; if ($proxy instanceof ValueHolderInterface) { @@ -79,7 +79,7 @@ public static function createFromProxy( return Instance::create( $proxy, new \ReflectionObject($object), - Method::create($methodRef) + Method::create(new \ReflectionMethod($proxy, $methodName)) ); }