5 * Contains \Drupal\Tests\Component\ProxyBuilder\ProxyBuilderTest.
8 namespace Drupal\Tests\Component\ProxyBuilder;
10 use Drupal\Component\ProxyBuilder\ProxyBuilder;
11 use PHPUnit\Framework\TestCase;
14 * @coversDefaultClass \Drupal\Component\ProxyBuilder\ProxyBuilder
15 * @group proxy_builder
17 class ProxyBuilderTest extends TestCase {
20 * The tested proxy builder.
22 * @var \Drupal\Component\ProxyBuilder\ProxyBuilder
24 protected $proxyBuilder;
29 protected function setUp() {
32 $this->proxyBuilder = new ProxyBuilder();
36 * @covers ::buildProxyClassName
38 public function testBuildProxyClassName() {
39 $class_name = $this->proxyBuilder->buildProxyClassName('Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod');
40 $this->assertEquals('Drupal\Tests\ProxyClass\Component\ProxyBuilder\TestServiceNoMethod', $class_name);
44 * @covers ::buildProxyClassName
46 public function testBuildProxyClassNameForModule() {
47 $class_name = $this->proxyBuilder->buildProxyClassName('Drupal\views_ui\ParamConverter\ViewUIConverter');
48 $this->assertEquals('Drupal\views_ui\ProxyClass\ParamConverter\ViewUIConverter', $class_name);
52 * @covers ::buildProxyNamespace
54 public function testBuildProxyNamespace() {
55 $class_name = $this->proxyBuilder->buildProxyNamespace('Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod');
56 $this->assertEquals('Drupal\Tests\ProxyClass\Component\ProxyBuilder', $class_name);
60 * Tests the basic methods like the constructor and the lazyLoadItself method.
63 * @covers ::buildConstructorMethod
64 * @covers ::buildLazyLoadItselfMethod
66 public function testBuildNoMethod() {
67 $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod';
69 $result = $this->proxyBuilder->build($class);
70 $this->assertEquals($this->buildExpectedClass($class, ''), $result);
74 * @covers ::buildMethod
75 * @covers ::buildMethodBody
77 public function testBuildSimpleMethod() {
78 $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceSimpleMethod';
80 $result = $this->proxyBuilder->build($class);
82 $method_body = <<<'EOS'
87 public function method()
89 return $this->lazyLoadItself()->method();
93 $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
97 * @covers ::buildMethod
98 * @covers ::buildParameter
99 * @covers ::buildMethodBody
101 public function testBuildMethodWithParameter() {
102 $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceMethodWithParameter';
104 $result = $this->proxyBuilder->build($class);
106 $method_body = <<<'EOS'
111 public function methodWithParameter($parameter)
113 return $this->lazyLoadItself()->methodWithParameter($parameter);
117 $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
121 * @covers ::buildMethod
122 * @covers ::buildParameter
123 * @covers ::buildMethodBody
125 public function testBuildComplexMethod() {
126 $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceComplexMethod';
128 $result = $this->proxyBuilder->build($class);
130 // @todo Solve the silly linebreak for array()
131 $method_body = <<<'EOS'
136 public function complexMethod($parameter, callable $function, \Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod $test_service = NULL, array &$elements = array (
139 return $this->lazyLoadItself()->complexMethod($parameter, $function, $test_service, $elements);
144 $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
148 * @covers ::buildMethod
149 * @covers ::buildMethodBody
151 public function testBuildReturnReference() {
152 $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceReturnReference';
154 $result = $this->proxyBuilder->build($class);
156 // @todo Solve the silly linebreak for array()
157 $method_body = <<<'EOS'
162 public function &returnReference()
164 return $this->lazyLoadItself()->returnReference();
169 $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
173 * @covers ::buildMethod
174 * @covers ::buildParameter
175 * @covers ::buildMethodBody
177 public function testBuildWithInterface() {
178 $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithInterface';
180 $result = $this->proxyBuilder->build($class);
182 $method_body = <<<'EOS'
187 public function testMethod($parameter)
189 return $this->lazyLoadItself()->testMethod($parameter);
194 $interface_string = ' implements \Drupal\Tests\Component\ProxyBuilder\TestInterface';
195 $this->assertEquals($this->buildExpectedClass($class, $method_body, $interface_string), $result);
201 public function testBuildWithNestedInterface() {
202 $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithChildInterfaces';
204 $result = $this->proxyBuilder->build($class);
207 $interface_string = ' implements \Drupal\Tests\Component\ProxyBuilder\TestChildInterface';
208 $this->assertEquals($this->buildExpectedClass($class, $method_body, $interface_string), $result);
212 * @covers ::buildMethod
213 * @covers ::buildParameter
214 * @covers ::buildMethodBody
216 public function testBuildWithProtectedAndPrivateMethod() {
217 $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithProtectedMethods';
219 $result = $this->proxyBuilder->build($class);
221 $method_body = <<<'EOS'
226 public function testMethod($parameter)
228 return $this->lazyLoadItself()->testMethod($parameter);
233 $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
237 * @covers ::buildMethod
238 * @covers ::buildParameter
239 * @covers ::buildMethodBody
241 public function testBuildWithPublicStaticMethod() {
242 $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithPublicStaticMethod';
244 $result = $this->proxyBuilder->build($class);
246 // Ensure that the static method is not wrapped.
247 $method_body = <<<'EOS'
252 public static function testMethod($parameter)
254 \Drupal\Tests\Component\ProxyBuilder\TestServiceWithPublicStaticMethod::testMethod($parameter);
259 $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
263 * Constructs the expected class output.
265 * @param string $expected_methods_body
266 * The expected body of decorated methods.
269 * The code of the entire proxy.
271 protected function buildExpectedClass($class, $expected_methods_body, $interface_string = '') {
272 $namespace = ProxyBuilder::buildProxyNamespace($class);
273 $reflection = new \ReflectionClass($class);
274 $proxy_class = $reflection->getShortName();
276 $expected_string = <<<'EOS'
278 namespace {{ namespace }} {
281 * Provides a proxy class for \{{ class }}.
283 * @see \Drupal\Component\ProxyBuilder
285 class {{ proxy_class }}{{ interface_string }}
289 * The id of the original proxied service.
293 protected $drupalProxyOriginalServiceId;
296 * The real proxied service, after it was lazy loaded.
303 * The service container.
305 * @var \Symfony\Component\DependencyInjection\ContainerInterface
307 protected $container;
310 * Constructs a ProxyClass Drupal proxy object.
312 * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
314 * @param string $drupal_proxy_original_service_id
315 * The service ID of the original service.
317 public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $drupal_proxy_original_service_id)
319 $this->container = $container;
320 $this->drupalProxyOriginalServiceId = $drupal_proxy_original_service_id;
324 * Lazy loads the real service from the container.
327 * Returns the constructed real service.
329 protected function lazyLoadItself()
331 if (!isset($this->service)) {
332 $this->service = $this->container->get($this->drupalProxyOriginalServiceId);
335 return $this->service;
337 {{ expected_methods_body }}
344 $expected_methods_body = implode("\n", array_map(function ($value) {
349 }, explode("\n", $expected_methods_body)));
351 $expected_string = str_replace('{{ proxy_class }}', $proxy_class, $expected_string);
352 $expected_string = str_replace('{{ namespace }}', $namespace, $expected_string);
353 $expected_string = str_replace('{{ class }}', $class, $expected_string);
354 $expected_string = str_replace('{{ expected_methods_body }}', $expected_methods_body, $expected_string);
355 $expected_string = str_replace('{{ interface_string }}', $interface_string, $expected_string);
357 return $expected_string;
362 class TestServiceNoMethod {
366 class TestServiceSimpleMethod {
368 public function method() {
374 class TestServiceMethodWithParameter {
376 public function methodWithParameter($parameter) {
382 class TestServiceComplexMethod {
384 public function complexMethod($parameter, callable $function, TestServiceNoMethod $test_service = NULL, array &$elements = []) {
390 class TestServiceReturnReference {
392 public function &returnReference() {
398 interface TestInterface {
400 public function testMethod($parameter);
404 class TestServiceWithInterface implements TestInterface {
406 public function testMethod($parameter) {
412 class TestServiceWithProtectedMethods {
414 public function testMethod($parameter) {
418 protected function protectedMethod($parameter) {
422 protected function privateMethod($parameter) {
428 class TestServiceWithPublicStaticMethod {
430 public static function testMethod($parameter) {
435 interface TestBaseInterface {
439 interface TestChildInterface extends TestBaseInterface {
443 class TestServiceWithChildInterfaces implements TestChildInterface {