diff --git a/core/lib/Drupal/Component/ProxyBuilder/ProxyBuilder.php b/core/lib/Drupal/Component/ProxyBuilder/ProxyBuilder.php index bce65dc..4e32501 100644 --- a/core/lib/Drupal/Component/ProxyBuilder/ProxyBuilder.php +++ b/core/lib/Drupal/Component/ProxyBuilder/ProxyBuilder.php @@ -55,6 +55,8 @@ public function build($class_name) { $class_start .= ' implements ' . implode(', ', $interfaces); } + $output .= $this->buildUseStatements(); + // The actual class; $properties = <<<'EOS' /** @@ -67,6 +69,13 @@ public function build($class_name) { */ protected $service; +/** + * The service container. + * + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ +protected $container; + EOS; @@ -97,7 +106,7 @@ public function build($class_name) { if ($value === '') { return $value; } - return " $value"; + return " $value"; }, explode("\n", $output))); $final_output = $class_documentation . $class_start . "\n{\n\n" . $output . "\n}\n"; @@ -239,7 +248,7 @@ protected function buildMethodBody(\ReflectionMethod $reflection_method) { */ protected function buildConstructorMethod() { $output = <<<'EOS' -public function __construct(ContainerInterface $container, $serviceId) +public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $serviceId) { $this->container = $container; $this->serviceId = $serviceId; @@ -249,4 +258,16 @@ public function __construct(ContainerInterface $container, $serviceId) return $output; } + + /** + * Build the required use statements of the proxy class. + * + * @return string + */ + protected function buildUseStatements() { + $output = ''; + + return $output; + } + } diff --git a/core/lib/Drupal/Component/ProxyBuilder/composer.json b/core/lib/Drupal/Component/ProxyBuilder/composer.json new file mode 100644 index 0000000..0d3e5eb --- /dev/null +++ b/core/lib/Drupal/Component/ProxyBuilder/composer.json @@ -0,0 +1,16 @@ +{ + "name": "drupal/proxy-builder", + "description": "Provides a lightweight mechanism to provide lazy loaded proxies.", + "keywords": ["drupal", "proxy"], + "homepage": "https://drupal.org/project/drupal", + "license": "GPL-2.0+", + "require": { + "php": ">=5.4.2", + "symfony/dependency-injection": "~2.6" + }, + "autoload": { + "psr-4": { + "Drupal\\Component\\ProxyBuilder\\": "" + } + } +} \ No newline at end of file diff --git a/core/lib/Drupal/Core/ProxyBuilder/ProxyBuilder.php b/core/lib/Drupal/Core/ProxyBuilder/ProxyBuilder.php new file mode 100644 index 0000000..8d6a271 --- /dev/null +++ b/core/lib/Drupal/Core/ProxyBuilder/ProxyBuilder.php @@ -0,0 +1,28 @@ +lazyLoadItself()->method(); - } + public function method() + { + return $this->lazyLoadItself()->method(); + } EOS; $this->assertEquals($this->buildExpectedClass($class, $method_body), $result); @@ -86,10 +86,10 @@ public function testBuildMethodWithParameter() { $method_body = <<<'EOS' - public function methodWithParameter($parameter) - { - return $this->lazyLoadItself()->methodWithParameter($parameter); - } + public function methodWithParameter($parameter) + { + return $this->lazyLoadItself()->methodWithParameter($parameter); + } EOS; $this->assertEquals($this->buildExpectedClass($class, $method_body), $result); @@ -108,11 +108,11 @@ public function testBuildComplexMethod() { // @todo Solve the silly linebreak for array() $method_body = <<<'EOS' - public function complexMethod($parameter, callable $function, \Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod $test_service = NULL, array &$elements = array ( - )) - { - return $this->lazyLoadItself()->complexMethod($parameter, $function, $test_service, $elements); - } + public function complexMethod($parameter, callable $function, \Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod $test_service = NULL, array &$elements = array ( + )) + { + return $this->lazyLoadItself()->complexMethod($parameter, $function, $test_service, $elements); + } EOS; @@ -131,10 +131,10 @@ public function testBuildWithInterface() { $method_body = <<<'EOS' - public function testMethod($parameter) - { - return $this->lazyLoadItself()->testMethod($parameter); - } + public function testMethod($parameter) + { + return $this->lazyLoadItself()->testMethod($parameter); + } EOS; @@ -154,10 +154,10 @@ public function testBuildWithProtectedAndPrivateMethod() { $method_body = <<<'EOS' - public function testMethod($parameter) - { - return $this->lazyLoadItself()->testMethod($parameter); - } + public function testMethod($parameter) + { + return $this->lazyLoadItself()->testMethod($parameter); + } EOS; @@ -177,10 +177,10 @@ public function testBuildWithPublicStaticMethod() { // Ensure that the static method is not wrapped. $method_body = <<<'EOS' - public static function testMethod($parameter) - { - \Drupal\Tests\Component\ProxyBuilder\TestServiceWithPublicStaticMethod::testMethod($parameter); - } + public static function testMethod($parameter) + { + \Drupal\Tests\Component\ProxyBuilder\TestServiceWithPublicStaticMethod::testMethod($parameter); + } EOS; @@ -207,31 +207,38 @@ protected function buildExpectedClass($class, $expected_methods_body, $interface class {{ proxy_class }}{{ interface_string }} { - /** - * @var string - */ - protected $serviceId; - - /** - * @var \{{ class }} - */ - protected $service; - - public function __construct(ContainerInterface $container, $serviceId) - { - $this->container = $container; - $this->serviceId = $serviceId; - } - - protected function lazyLoadItself() - { - if (!isset($this->service)) { - $method_name = 'get' . Container::camelize($this->serviceId) . 'Service'; - $this->service = $this->container->$method_name(false); - } - - return $this->service; - } + /** + * @var string + */ + protected $serviceId; + + /** + * @var \{{ class }} + */ + protected $service; + + /** + * The service container. + * + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ + protected $container; + + public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $serviceId) + { + $this->container = $container; + $this->serviceId = $serviceId; + } + + protected function lazyLoadItself() + { + if (!isset($this->service)) { + $method_name = 'get' . Container::camelize($this->serviceId) . 'Service'; + $this->service = $this->container->$method_name(false); + } + + return $this->service; + } {{ expected_methods_body }} } diff --git a/core/tests/Drupal/Tests/Core/ProxyBuilder/ProxyBuilderTest.php b/core/tests/Drupal/Tests/Core/ProxyBuilder/ProxyBuilderTest.php new file mode 100644 index 0000000..d3cc447 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/ProxyBuilder/ProxyBuilderTest.php @@ -0,0 +1,135 @@ +proxyBuilder = new ProxyBuilder(); + } + + /** + * @covers ::buildMethod() + * @covers ::buildParameter() + * @covers ::buildMethodBody() + */ + public function testBuildComplexMethod() { + $class = 'Drupal\Tests\Core\ProxyBuilder\TestServiceComplexMethod'; + + $result = $this->proxyBuilder->build($class); + + // @todo Solve the silly linebreak for array() + $method_body = <<<'EOS' + + public function complexMethod($parameter, callable $function, \Drupal\Tests\Core\ProxyBuilder\TestServiceNoMethod $test_service = NULL, array &$elements = array ( + )) + { + return $this->lazyLoadItself()->complexMethod($parameter, $function, $test_service, $elements); + } + +EOS; + + $this->assertEquals($this->buildExpectedClass($class, $method_body), $result); + } + + /** + * Constructs the expected class output. + * + * @param string $expected_methods_body + * The expected body of decorated methods. + * + * @return string + * The code of the entire proxy. + */ + protected function buildExpectedClass($class, $expected_methods_body, $interface_string = '') { + $proxy_class = $this->proxyBuilder->buildProxyClassName($class); + $expected_string = <<<'EOS' +/** + * Provides a proxy class for \{{ class }}. + * + * @see \Drupal\Component\ProxyBuilder + */ +class {{ proxy_class }}{{ interface_string }} +{ + + use \Drupal\Core\DependencyInjection\DependencySerializationTrait; + + /** + * @var string + */ + protected $serviceId; + + /** + * @var \{{ class }} + */ + protected $service; + + /** + * The service container. + * + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ + protected $container; + + public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $serviceId) + { + $this->container = $container; + $this->serviceId = $serviceId; + } + + protected function lazyLoadItself() + { + if (!isset($this->service)) { + $method_name = 'get' . Container::camelize($this->serviceId) . 'Service'; + $this->service = $this->container->$method_name(false); + } + + return $this->service; + } +{{ expected_methods_body }} +} + +EOS; + $expected_string = str_replace('{{ proxy_class }}', $proxy_class, $expected_string); + $expected_string = str_replace('{{ class }}', $class, $expected_string); + $expected_string = str_replace('{{ expected_methods_body }}', $expected_methods_body, $expected_string); + $expected_string = str_replace('{{ interface_string }}', $interface_string, $expected_string); + + return $expected_string; + } +} + +class TestServiceNoMethod { + +} + +class TestServiceComplexMethod { + + public function complexMethod($parameter, callable $function, TestServiceNoMethod $test_service = NULL, array &$elements = array()) { + + } + +}