PageRenderTime 53ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/core/tests/Drupal/Tests/Component/ProxyBuilder/ProxyBuilderTest.php

http://github.com/drupal/drupal
PHP | 445 lines | 197 code | 113 blank | 135 comment | 2 complexity | b4c0ecefaf7504d321ddbc02386527ab MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * @file
  4. * Contains \Drupal\Tests\Component\ProxyBuilder\ProxyBuilderTest.
  5. */
  6. namespace Drupal\Tests\Component\ProxyBuilder;
  7. use Drupal\Component\ProxyBuilder\ProxyBuilder;
  8. use PHPUnit\Framework\TestCase;
  9. /**
  10. * @coversDefaultClass \Drupal\Component\ProxyBuilder\ProxyBuilder
  11. * @group proxy_builder
  12. */
  13. class ProxyBuilderTest extends TestCase {
  14. /**
  15. * The tested proxy builder.
  16. *
  17. * @var \Drupal\Component\ProxyBuilder\ProxyBuilder
  18. */
  19. protected $proxyBuilder;
  20. /**
  21. * {@inheritdoc}
  22. */
  23. protected function setUp() {
  24. parent::setUp();
  25. $this->proxyBuilder = new ProxyBuilder();
  26. }
  27. /**
  28. * @covers ::buildProxyClassName
  29. */
  30. public function testBuildProxyClassName() {
  31. $class_name = $this->proxyBuilder->buildProxyClassName('Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod');
  32. $this->assertEquals('Drupal\Tests\ProxyClass\Component\ProxyBuilder\TestServiceNoMethod', $class_name);
  33. }
  34. /**
  35. * @covers ::buildProxyClassName
  36. */
  37. public function testBuildProxyClassNameForModule() {
  38. $class_name = $this->proxyBuilder->buildProxyClassName('Drupal\views_ui\ParamConverter\ViewUIConverter');
  39. $this->assertEquals('Drupal\views_ui\ProxyClass\ParamConverter\ViewUIConverter', $class_name);
  40. }
  41. /**
  42. * @covers ::buildProxyNamespace
  43. */
  44. public function testBuildProxyNamespace() {
  45. $class_name = $this->proxyBuilder->buildProxyNamespace('Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod');
  46. $this->assertEquals('Drupal\Tests\ProxyClass\Component\ProxyBuilder', $class_name);
  47. }
  48. /**
  49. * Tests the basic methods like the constructor and the lazyLoadItself method.
  50. *
  51. * @covers ::build
  52. * @covers ::buildConstructorMethod
  53. * @covers ::buildLazyLoadItselfMethod
  54. */
  55. public function testBuildNoMethod() {
  56. $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod';
  57. $result = $this->proxyBuilder->build($class);
  58. $this->assertEquals($this->buildExpectedClass($class, ''), $result);
  59. }
  60. /**
  61. * @covers ::buildMethod
  62. * @covers ::buildMethodBody
  63. */
  64. public function testBuildSimpleMethod() {
  65. $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceSimpleMethod';
  66. $result = $this->proxyBuilder->build($class);
  67. $method_body = <<<'EOS'
  68. /**
  69. * {@inheritdoc}
  70. */
  71. public function method()
  72. {
  73. return $this->lazyLoadItself()->method();
  74. }
  75. EOS;
  76. $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
  77. }
  78. /**
  79. * @covers ::buildMethod
  80. * @covers ::buildParameter
  81. * @covers ::buildMethodBody
  82. */
  83. public function testBuildMethodWithParameter() {
  84. $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceMethodWithParameter';
  85. $result = $this->proxyBuilder->build($class);
  86. $method_body = <<<'EOS'
  87. /**
  88. * {@inheritdoc}
  89. */
  90. public function methodWithParameter($parameter)
  91. {
  92. return $this->lazyLoadItself()->methodWithParameter($parameter);
  93. }
  94. EOS;
  95. $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
  96. }
  97. /**
  98. * @covers ::buildMethod
  99. * @covers ::buildParameter
  100. * @covers ::buildMethodBody
  101. */
  102. public function testBuildComplexMethod() {
  103. $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceComplexMethod';
  104. $result = $this->proxyBuilder->build($class);
  105. // @todo Solve the silly linebreak for array()
  106. $method_body = <<<'EOS'
  107. /**
  108. * {@inheritdoc}
  109. */
  110. public function complexMethod($parameter, callable $function, \Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod $test_service = NULL, array &$elements = array (
  111. ))
  112. {
  113. return $this->lazyLoadItself()->complexMethod($parameter, $function, $test_service, $elements);
  114. }
  115. EOS;
  116. $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
  117. }
  118. /**
  119. * @covers ::buildMethod
  120. * @covers ::buildMethodBody
  121. */
  122. public function testBuildReturnReference() {
  123. $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceReturnReference';
  124. $result = $this->proxyBuilder->build($class);
  125. // @todo Solve the silly linebreak for array()
  126. $method_body = <<<'EOS'
  127. /**
  128. * {@inheritdoc}
  129. */
  130. public function &returnReference()
  131. {
  132. return $this->lazyLoadItself()->returnReference();
  133. }
  134. EOS;
  135. $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
  136. }
  137. /**
  138. * @covers ::buildMethod
  139. * @covers ::buildParameter
  140. * @covers ::buildMethodBody
  141. */
  142. public function testBuildWithInterface() {
  143. $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithInterface';
  144. $result = $this->proxyBuilder->build($class);
  145. $method_body = <<<'EOS'
  146. /**
  147. * {@inheritdoc}
  148. */
  149. public function testMethod($parameter)
  150. {
  151. return $this->lazyLoadItself()->testMethod($parameter);
  152. }
  153. EOS;
  154. $interface_string = ' implements \Drupal\Tests\Component\ProxyBuilder\TestInterface';
  155. $this->assertEquals($this->buildExpectedClass($class, $method_body, $interface_string), $result);
  156. }
  157. /**
  158. * @covers ::build
  159. */
  160. public function testBuildWithNestedInterface() {
  161. $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithChildInterfaces';
  162. $result = $this->proxyBuilder->build($class);
  163. $method_body = '';
  164. $interface_string = ' implements \Drupal\Tests\Component\ProxyBuilder\TestChildInterface';
  165. $this->assertEquals($this->buildExpectedClass($class, $method_body, $interface_string), $result);
  166. }
  167. /**
  168. * @covers ::buildMethod
  169. * @covers ::buildParameter
  170. * @covers ::buildMethodBody
  171. */
  172. public function testBuildWithProtectedAndPrivateMethod() {
  173. $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithProtectedMethods';
  174. $result = $this->proxyBuilder->build($class);
  175. $method_body = <<<'EOS'
  176. /**
  177. * {@inheritdoc}
  178. */
  179. public function testMethod($parameter)
  180. {
  181. return $this->lazyLoadItself()->testMethod($parameter);
  182. }
  183. EOS;
  184. $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
  185. }
  186. /**
  187. * @covers ::buildMethod
  188. * @covers ::buildParameter
  189. * @covers ::buildMethodBody
  190. */
  191. public function testBuildWithPublicStaticMethod() {
  192. $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithPublicStaticMethod';
  193. $result = $this->proxyBuilder->build($class);
  194. // Ensure that the static method is not wrapped.
  195. $method_body = <<<'EOS'
  196. /**
  197. * {@inheritdoc}
  198. */
  199. public static function testMethod($parameter)
  200. {
  201. \Drupal\Tests\Component\ProxyBuilder\TestServiceWithPublicStaticMethod::testMethod($parameter);
  202. }
  203. EOS;
  204. $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
  205. }
  206. /**
  207. * Constructs the expected class output.
  208. *
  209. * @param string $expected_methods_body
  210. * The expected body of decorated methods.
  211. *
  212. * @return string
  213. * The code of the entire proxy.
  214. */
  215. protected function buildExpectedClass($class, $expected_methods_body, $interface_string = '') {
  216. $namespace = ProxyBuilder::buildProxyNamespace($class);
  217. $reflection = new \ReflectionClass($class);
  218. $proxy_class = $reflection->getShortName();
  219. $expected_string = <<<'EOS'
  220. namespace {{ namespace }} {
  221. /**
  222. * Provides a proxy class for \{{ class }}.
  223. *
  224. * @see \Drupal\Component\ProxyBuilder
  225. */
  226. class {{ proxy_class }}{{ interface_string }}
  227. {
  228. /**
  229. * The id of the original proxied service.
  230. *
  231. * @var string
  232. */
  233. protected $drupalProxyOriginalServiceId;
  234. /**
  235. * The real proxied service, after it was lazy loaded.
  236. *
  237. * @var \{{ class }}
  238. */
  239. protected $service;
  240. /**
  241. * The service container.
  242. *
  243. * @var \Symfony\Component\DependencyInjection\ContainerInterface
  244. */
  245. protected $container;
  246. /**
  247. * Constructs a ProxyClass Drupal proxy object.
  248. *
  249. * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
  250. * The container.
  251. * @param string $drupal_proxy_original_service_id
  252. * The service ID of the original service.
  253. */
  254. public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $drupal_proxy_original_service_id)
  255. {
  256. $this->container = $container;
  257. $this->drupalProxyOriginalServiceId = $drupal_proxy_original_service_id;
  258. }
  259. /**
  260. * Lazy loads the real service from the container.
  261. *
  262. * @return object
  263. * Returns the constructed real service.
  264. */
  265. protected function lazyLoadItself()
  266. {
  267. if (!isset($this->service)) {
  268. $this->service = $this->container->get($this->drupalProxyOriginalServiceId);
  269. }
  270. return $this->service;
  271. }
  272. {{ expected_methods_body }}
  273. }
  274. }
  275. EOS;
  276. $expected_methods_body = implode("\n", array_map(function ($value) {
  277. if ($value === '') {
  278. return $value;
  279. }
  280. return " $value";
  281. }, explode("\n", $expected_methods_body)));
  282. $expected_string = str_replace('{{ proxy_class }}', $proxy_class, $expected_string);
  283. $expected_string = str_replace('{{ namespace }}', $namespace, $expected_string);
  284. $expected_string = str_replace('{{ class }}', $class, $expected_string);
  285. $expected_string = str_replace('{{ expected_methods_body }}', $expected_methods_body, $expected_string);
  286. $expected_string = str_replace('{{ interface_string }}', $interface_string, $expected_string);
  287. return $expected_string;
  288. }
  289. }
  290. class TestServiceNoMethod {
  291. }
  292. class TestServiceSimpleMethod {
  293. public function method() {
  294. }
  295. }
  296. class TestServiceMethodWithParameter {
  297. public function methodWithParameter($parameter) {
  298. }
  299. }
  300. class TestServiceComplexMethod {
  301. public function complexMethod($parameter, callable $function, TestServiceNoMethod $test_service = NULL, array &$elements = []) {
  302. }
  303. }
  304. class TestServiceReturnReference {
  305. public function &returnReference() {
  306. }
  307. }
  308. interface TestInterface {
  309. public function testMethod($parameter);
  310. }
  311. class TestServiceWithInterface implements TestInterface {
  312. public function testMethod($parameter) {
  313. }
  314. }
  315. class TestServiceWithProtectedMethods {
  316. public function testMethod($parameter) {
  317. }
  318. protected function protectedMethod($parameter) {
  319. }
  320. protected function privateMethod($parameter) {
  321. }
  322. }
  323. class TestServiceWithPublicStaticMethod {
  324. public static function testMethod($parameter) {
  325. }
  326. }
  327. interface TestBaseInterface {
  328. }
  329. interface TestChildInterface extends TestBaseInterface {
  330. }
  331. class TestServiceWithChildInterfaces implements TestChildInterface {
  332. }