More updates to stop using dev or alpha or beta versions.
[yaffs-website] / web / core / tests / Drupal / Tests / Component / ProxyBuilder / ProxyBuilderTest.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\Tests\Component\ProxyBuilder\ProxyBuilderTest.
6  */
7
8 namespace Drupal\Tests\Component\ProxyBuilder;
9
10 use Drupal\Component\ProxyBuilder\ProxyBuilder;
11 use PHPUnit\Framework\TestCase;
12
13 /**
14  * @coversDefaultClass \Drupal\Component\ProxyBuilder\ProxyBuilder
15  * @group proxy_builder
16  */
17 class ProxyBuilderTest extends TestCase {
18
19   /**
20    * The tested proxy builder.
21    *
22    * @var \Drupal\Component\ProxyBuilder\ProxyBuilder
23    */
24   protected $proxyBuilder;
25
26   /**
27    * {@inheritdoc}
28    */
29   protected function setUp() {
30     parent::setUp();
31
32     $this->proxyBuilder = new ProxyBuilder();
33   }
34
35   /**
36    * @covers ::buildProxyClassName
37    */
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);
41   }
42
43   /**
44    * @covers ::buildProxyClassName
45    */
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);
49   }
50
51   /**
52    * @covers ::buildProxyNamespace
53    */
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);
57   }
58
59   /**
60    * Tests the basic methods like the constructor and the lazyLoadItself method.
61    *
62    * @covers ::build
63    * @covers ::buildConstructorMethod
64    * @covers ::buildLazyLoadItselfMethod
65    */
66   public function testBuildNoMethod() {
67     $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod';
68
69     $result = $this->proxyBuilder->build($class);
70     $this->assertEquals($this->buildExpectedClass($class, ''), $result);
71   }
72
73   /**
74    * @covers ::buildMethod
75    * @covers ::buildMethodBody
76    */
77   public function testBuildSimpleMethod() {
78     $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceSimpleMethod';
79
80     $result = $this->proxyBuilder->build($class);
81
82     $method_body = <<<'EOS'
83
84 /**
85  * {@inheritdoc}
86  */
87 public function method()
88 {
89     return $this->lazyLoadItself()->method();
90 }
91
92 EOS;
93     $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
94   }
95
96   /**
97    * @covers ::buildMethod
98    * @covers ::buildParameter
99    * @covers ::buildMethodBody
100    */
101   public function testBuildMethodWithParameter() {
102     $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceMethodWithParameter';
103
104     $result = $this->proxyBuilder->build($class);
105
106     $method_body = <<<'EOS'
107
108 /**
109  * {@inheritdoc}
110  */
111 public function methodWithParameter($parameter)
112 {
113     return $this->lazyLoadItself()->methodWithParameter($parameter);
114 }
115
116 EOS;
117     $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
118   }
119
120   /**
121    * @covers ::buildMethod
122    * @covers ::buildParameter
123    * @covers ::buildMethodBody
124    */
125   public function testBuildComplexMethod() {
126     $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceComplexMethod';
127
128     $result = $this->proxyBuilder->build($class);
129
130     // @todo Solve the silly linebreak for array()
131     $method_body = <<<'EOS'
132
133 /**
134  * {@inheritdoc}
135  */
136 public function complexMethod($parameter, callable $function, \Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod $test_service = NULL, array &$elements = array (
137 ))
138 {
139     return $this->lazyLoadItself()->complexMethod($parameter, $function, $test_service, $elements);
140 }
141
142 EOS;
143
144     $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
145   }
146
147   /**
148    * @covers ::buildMethod
149    * @covers ::buildMethodBody
150    */
151   public function testBuildReturnReference() {
152     $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceReturnReference';
153
154     $result = $this->proxyBuilder->build($class);
155
156     // @todo Solve the silly linebreak for array()
157     $method_body = <<<'EOS'
158
159 /**
160  * {@inheritdoc}
161  */
162 public function &returnReference()
163 {
164     return $this->lazyLoadItself()->returnReference();
165 }
166
167 EOS;
168
169     $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
170   }
171
172   /**
173    * @covers ::buildMethod
174    * @covers ::buildParameter
175    * @covers ::buildMethodBody
176    */
177   public function testBuildWithInterface() {
178     $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithInterface';
179
180     $result = $this->proxyBuilder->build($class);
181
182     $method_body = <<<'EOS'
183
184 /**
185  * {@inheritdoc}
186  */
187 public function testMethod($parameter)
188 {
189     return $this->lazyLoadItself()->testMethod($parameter);
190 }
191
192 EOS;
193
194     $interface_string = ' implements \Drupal\Tests\Component\ProxyBuilder\TestInterface';
195     $this->assertEquals($this->buildExpectedClass($class, $method_body, $interface_string), $result);
196   }
197
198   /**
199    * @covers ::build
200    */
201   public function testBuildWithNestedInterface() {
202     $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithChildInterfaces';
203
204     $result = $this->proxyBuilder->build($class);
205     $method_body = '';
206
207     $interface_string = ' implements \Drupal\Tests\Component\ProxyBuilder\TestChildInterface';
208     $this->assertEquals($this->buildExpectedClass($class, $method_body, $interface_string), $result);
209   }
210
211   /**
212    * @covers ::buildMethod
213    * @covers ::buildParameter
214    * @covers ::buildMethodBody
215    */
216   public function testBuildWithProtectedAndPrivateMethod() {
217     $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithProtectedMethods';
218
219     $result = $this->proxyBuilder->build($class);
220
221     $method_body = <<<'EOS'
222
223 /**
224  * {@inheritdoc}
225  */
226 public function testMethod($parameter)
227 {
228     return $this->lazyLoadItself()->testMethod($parameter);
229 }
230
231 EOS;
232
233     $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
234   }
235
236   /**
237    * @covers ::buildMethod
238    * @covers ::buildParameter
239    * @covers ::buildMethodBody
240    */
241   public function testBuildWithPublicStaticMethod() {
242     $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithPublicStaticMethod';
243
244     $result = $this->proxyBuilder->build($class);
245
246     // Ensure that the static method is not wrapped.
247     $method_body = <<<'EOS'
248
249 /**
250  * {@inheritdoc}
251  */
252 public static function testMethod($parameter)
253 {
254     \Drupal\Tests\Component\ProxyBuilder\TestServiceWithPublicStaticMethod::testMethod($parameter);
255 }
256
257 EOS;
258
259     $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
260   }
261
262   /**
263    * Constructs the expected class output.
264    *
265    * @param string $expected_methods_body
266    *   The expected body of decorated methods.
267    *
268    * @return string
269    *   The code of the entire proxy.
270    */
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();
275
276     $expected_string = <<<'EOS'
277
278 namespace {{ namespace }} {
279
280     /**
281      * Provides a proxy class for \{{ class }}.
282      *
283      * @see \Drupal\Component\ProxyBuilder
284      */
285     class {{ proxy_class }}{{ interface_string }}
286     {
287
288         /**
289          * The id of the original proxied service.
290          *
291          * @var string
292          */
293         protected $drupalProxyOriginalServiceId;
294
295         /**
296          * The real proxied service, after it was lazy loaded.
297          *
298          * @var \{{ class }}
299          */
300         protected $service;
301
302         /**
303          * The service container.
304          *
305          * @var \Symfony\Component\DependencyInjection\ContainerInterface
306          */
307         protected $container;
308
309         /**
310          * Constructs a ProxyClass Drupal proxy object.
311          *
312          * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
313          *   The container.
314          * @param string $drupal_proxy_original_service_id
315          *   The service ID of the original service.
316          */
317         public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $drupal_proxy_original_service_id)
318         {
319             $this->container = $container;
320             $this->drupalProxyOriginalServiceId = $drupal_proxy_original_service_id;
321         }
322
323         /**
324          * Lazy loads the real service from the container.
325          *
326          * @return object
327          *   Returns the constructed real service.
328          */
329         protected function lazyLoadItself()
330         {
331             if (!isset($this->service)) {
332                 $this->service = $this->container->get($this->drupalProxyOriginalServiceId);
333             }
334
335             return $this->service;
336         }
337 {{ expected_methods_body }}
338     }
339
340 }
341
342 EOS;
343
344     $expected_methods_body = implode("\n", array_map(function ($value) {
345       if ($value === '') {
346         return $value;
347       }
348       return "        $value";
349     }, explode("\n", $expected_methods_body)));
350
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);
356
357     return $expected_string;
358   }
359
360 }
361
362 class TestServiceNoMethod {
363
364 }
365
366 class TestServiceSimpleMethod {
367
368   public function method() {
369
370   }
371
372 }
373
374 class TestServiceMethodWithParameter {
375
376   public function methodWithParameter($parameter) {
377
378   }
379
380 }
381
382 class TestServiceComplexMethod {
383
384   public function complexMethod($parameter, callable $function, TestServiceNoMethod $test_service = NULL, array &$elements = []) {
385
386   }
387
388 }
389
390 class TestServiceReturnReference {
391
392   public function &returnReference() {
393
394   }
395
396 }
397
398 interface TestInterface {
399
400   public function testMethod($parameter);
401
402 }
403
404 class TestServiceWithInterface implements TestInterface {
405
406   public function testMethod($parameter) {
407
408   }
409
410 }
411
412 class TestServiceWithProtectedMethods {
413
414   public function testMethod($parameter) {
415
416   }
417
418   protected function protectedMethod($parameter) {
419
420   }
421
422   protected function privateMethod($parameter) {
423
424   }
425
426 }
427
428 class TestServiceWithPublicStaticMethod {
429
430   public static function testMethod($parameter) {
431   }
432
433 }
434
435 interface TestBaseInterface {
436
437 }
438
439 interface TestChildInterface extends TestBaseInterface {
440
441 }
442
443 class TestServiceWithChildInterfaces implements TestChildInterface {
444
445 }