Commit f12134b5 authored by alexpott's avatar alexpott

Issue #2408357 by dawehner: The ProxyBuilder includes parent interfaces, which causes php errors

parent c34c3dfd
...@@ -48,11 +48,28 @@ public function build($class_name) { ...@@ -48,11 +48,28 @@ public function build($class_name) {
EOS; EOS;
$class_start = 'class {{ proxy_class_name }}'; $class_start = 'class {{ proxy_class_name }}';
if ($interfaces = $reflection->getInterfaceNames()) { // For cases in which the implemented interface is a child of another
foreach ($interfaces as &$interface) { // interface, getInterfaceNames() also returns the parent. This causes a
$interface = '\\' . $interface; // PHP error.
// In order to avoid that, check for each interface, whether one of its
// parents is also in the list and exclude it.
if ($interfaces = $reflection->getInterfaces()) {
foreach ($interfaces as $interface_name => $interface) {
// Exclude all parents from the list of implemented interfaces of the
// class.
if ($parent_interfaces = $interface->getInterfaceNames()) {
foreach ($parent_interfaces as $parent_interface) {
if (isset($interfaces[$parent_interface])) {}
unset($interfaces[$parent_interface]);
}
}
} }
$class_start .= ' implements ' . implode(', ', $interfaces);
$interface_names = [];
foreach ($interfaces as $interface) {
$interface_names[] = '\\' . $interface->getName();
}
$class_start .= ' implements ' . implode(', ', $interface_names);
} }
$output .= $this->buildUseStatements(); $output .= $this->buildUseStatements();
...@@ -102,7 +119,7 @@ public function build($class_name) { ...@@ -102,7 +119,7 @@ public function build($class_name) {
$output .= implode("\n", $methods); $output .= implode("\n", $methods);
// Indent the output. // Indent the output.
$output = implode("\n", array_map(function($value) { $output = implode("\n", array_map(function ($value) {
if ($value === '') { if ($value === '') {
return $value; return $value;
} }
...@@ -174,7 +191,7 @@ protected function buildMethod(\ReflectionMethod $reflection_method) { ...@@ -174,7 +191,7 @@ protected function buildMethod(\ReflectionMethod $reflection_method) {
$output .= $this->buildMethodBody($reflection_method); $output .= $this->buildMethodBody($reflection_method);
$output .= "\n". '}'; $output .= "\n" . '}';
return $output; return $output;
} }
......
...@@ -15,6 +15,13 @@ ...@@ -15,6 +15,13 @@
*/ */
class ProxyDumper implements DumperInterface { class ProxyDumper implements DumperInterface {
/**
* Keeps track of already existing proxy classes.
*
* @var array
*/
protected $buildClasses = [];
/** /**
* The proxy builder. * The proxy builder.
* *
...@@ -56,7 +63,16 @@ public function getProxyFactoryCode(Definition $definition, $id) { ...@@ -56,7 +63,16 @@ public function getProxyFactoryCode(Definition $definition, $id) {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getProxyCode(Definition $definition) { public function getProxyCode(Definition $definition) {
return $this->builder->build($definition->getClass()); // Maybe the same class is used in different services, which are both marked
// as lazy (just think about 2 database connections).
// In those cases we should not generate proxy code the second time.
if (!isset($this->buildClasses[$definition->getClass()])) {
$this->buildClasses[$definition->getClass()] = TRUE;
return $this->builder->build($definition->getClass());
}
else {
return '';
}
} }
} }
...@@ -164,6 +164,19 @@ public function testMethod($parameter) ...@@ -164,6 +164,19 @@ public function testMethod($parameter)
$this->assertEquals($this->buildExpectedClass($class, $method_body, $interface_string), $result); $this->assertEquals($this->buildExpectedClass($class, $method_body, $interface_string), $result);
} }
/**
* @covers ::build()
*/
public function testBuildWithNestedInterface() {
$class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithChildInterfaces';
$result = $this->proxyBuilder->build($class);
$method_body = '';
$interface_string = ' implements \Drupal\Tests\Component\ProxyBuilder\TestChildInterface';
$this->assertEquals($this->buildExpectedClass($class, $method_body, $interface_string), $result);
}
/** /**
* @covers ::buildMethod() * @covers ::buildMethod()
* @covers ::buildParameter() * @covers ::buildParameter()
...@@ -348,3 +361,14 @@ public static function testMethod($parameter) { ...@@ -348,3 +361,14 @@ public static function testMethod($parameter) {
} }
interface TestBaseInterface {
}
interface TestChildInterface extends TestBaseInterface {
}
class TestServiceWithChildInterfaces implements TestChildInterface {
}
...@@ -85,6 +85,9 @@ public function testGetProxyFactoryCode() { ...@@ -85,6 +85,9 @@ public function testGetProxyFactoryCode() {
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
} }
/**
* @covers ::getProxyCode()
*/
public function testGetProxyCode() { public function testGetProxyCode() {
$definition = new Definition('Drupal\Tests\Component\ProxyBuilder\TestService'); $definition = new Definition('Drupal\Tests\Component\ProxyBuilder\TestService');
$definition->setLazy(TRUE); $definition->setLazy(TRUE);
...@@ -99,6 +102,26 @@ public function testGetProxyCode() { ...@@ -99,6 +102,26 @@ public function testGetProxyCode() {
$this->assertEquals($class, $result); $this->assertEquals($class, $result);
} }
/**
* @covers ::getProxyCode()
*/
public function testGetProxyCodeWithSameClassMultipleTimes() {
$definition = new Definition('Drupal\Tests\Component\ProxyBuilder\TestService');
$definition->setLazy(TRUE);
$class = 'class Drupal_Tests_Component_ProxyBuilder_TestService_Proxy {}';
$this->proxyBuilder->expects($this->once())
->method('build')
->with('Drupal\Tests\Component\ProxyBuilder\TestService')
->willReturn($class);
$result = $this->proxyDumper->getProxyCode($definition);
$this->assertEquals($class, $result);
$result = $this->proxyDumper->getProxyCode($definition);
$this->assertEquals('', $result);
}
} }
class TestService { class TestService {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment