Issue #2976335 by alexpott, Erik Frèrejean, HenrikBak, andypost: Use Zend-Feed's standalone extension managers to prevent sites breaking

8.7.x
Nathaniel Catchpole 2018-07-30 20:50:24 +09:00
parent d1eee651be
commit 68eee65ffc
3 changed files with 77 additions and 2 deletions

View File

@ -1418,11 +1418,13 @@ services:
class: Drupal\Component\Bridge\ZfExtensionManagerSfContainer
calls:
- [setContainer, ['@service_container']]
- [setStandalone, ['\Zend\Feed\Reader\StandaloneExtensionManager']]
arguments: ['feed.reader.']
feed.bridge.writer:
class: Drupal\Component\Bridge\ZfExtensionManagerSfContainer
calls:
- [setContainer, ['@service_container']]
- [setStandalone, ['\Zend\Feed\Writer\StandaloneExtensionManager']]
arguments: ['feed.writer.']
# Zend Feed reader plugins. Plugin instances should not be shared.
feed.reader.dublincoreentry:

View File

@ -4,6 +4,7 @@ namespace Drupal\Component\Bridge;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Zend\Feed\Reader\ExtensionManagerInterface as ReaderManagerInterface;
use Zend\Feed\Writer\ExtensionManagerInterface as WriterManagerInterface;
@ -48,6 +49,11 @@ class ZfExtensionManagerSfContainer implements ReaderManagerInterface, WriterMan
*/
protected $canonicalNames;
/**
* @var \Zend\Feed\Reader\ExtensionManagerInterface|\Zend\Feed\Writer\ExtensionManagerInterface
*/
protected $standalone;
/**
* Constructs a ZfExtensionManagerSfContainer object.
*
@ -62,14 +68,25 @@ class ZfExtensionManagerSfContainer implements ReaderManagerInterface, WriterMan
* {@inheritdoc}
*/
public function get($extension) {
return $this->container->get($this->prefix . $this->canonicalizeName($extension));
try {
return $this->container->get($this->prefix . $this->canonicalizeName($extension));
}
catch (ServiceNotFoundException $e) {
if ($this->standalone && $this->standalone->has($extension)) {
return $this->standalone->get($extension);
}
throw $e;
}
}
/**
* {@inheritdoc}
*/
public function has($extension) {
return $this->container->has($this->prefix . $this->canonicalizeName($extension));
if ($this->container->has($this->prefix . $this->canonicalizeName($extension))) {
return TRUE;
}
return $this->standalone && $this->standalone->has($extension);
}
/**
@ -102,4 +119,14 @@ class ZfExtensionManagerSfContainer implements ReaderManagerInterface, WriterMan
$this->container = $container;
}
/**
* @param $class
*/
public function setStandalone($class) {
if (!is_subclass_of($class, ReaderManagerInterface::class) && !is_subclass_of($class, WriterManagerInterface::class)) {
throw new \RuntimeException("$class must implement Zend\Feed\Reader\ExtensionManagerInterface or Zend\Feed\Writer\ExtensionManagerInterface");
}
$this->standalone = new $class();
}
}

View File

@ -5,6 +5,9 @@ namespace Drupal\Tests\Component\Bridge;
use Drupal\Component\Bridge\ZfExtensionManagerSfContainer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Zend\Feed\Reader\Extension\Atom\Entry;
use Zend\Feed\Reader\StandaloneExtensionManager;
/**
* @coversDefaultClass \Drupal\Component\Bridge\ZfExtensionManagerSfContainer
@ -14,6 +17,7 @@ class ZfExtensionManagerSfContainerTest extends TestCase {
/**
* @covers ::setContainer
* @covers ::setStandalone
* @covers ::get
*/
public function testGet() {
@ -24,10 +28,16 @@ class ZfExtensionManagerSfContainerTest extends TestCase {
$bridge = new ZfExtensionManagerSfContainer();
$bridge->setContainer($container);
$this->assertEquals($service, $bridge->get('foo'));
$bridge->setStandalone(StandaloneExtensionManager::class);
$this->assertInstanceOf(Entry::class, $bridge->get('Atom\Entry'));
// Ensure that the container is checked first.
$container->set('atomentry', $service);
$this->assertEquals($service, $bridge->get('Atom\Entry'));
}
/**
* @covers ::setContainer
* @covers ::setStandalone
* @covers ::has
*/
public function testHas() {
@ -39,6 +49,42 @@ class ZfExtensionManagerSfContainerTest extends TestCase {
$bridge->setContainer($container);
$this->assertTrue($bridge->has('foo'));
$this->assertFalse($bridge->has('bar'));
$this->assertFalse($bridge->has('Atom\Entry'));
$bridge->setStandalone(StandaloneExtensionManager::class);
$this->assertTrue($bridge->has('Atom\Entry'));
}
/**
* @covers ::setStandalone
*/
public function testSetStandaloneException() {
if (method_exists($this, 'expectException')) {
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Drupal\Tests\Component\Bridge\ZfExtensionManagerSfContainerTest must implement Zend\Feed\Reader\ExtensionManagerInterface or Zend\Feed\Writer\ExtensionManagerInterface');
}
else {
$this->setExpectedException(\RuntimeException::class, 'Drupal\Tests\Component\Bridge\ZfExtensionManagerSfContainerTest must implement Zend\Feed\Reader\ExtensionManagerInterface or Zend\Feed\Writer\ExtensionManagerInterface');
}
$bridge = new ZfExtensionManagerSfContainer();
$bridge->setStandalone(static::class);
}
/**
* @covers ::get
*/
public function testGetContainerException() {
if (method_exists($this, 'expectException')) {
$this->expectException(ServiceNotFoundException::class);
$this->expectExceptionMessage('You have requested a non-existent service "test.foo".');
}
else {
$this->setExpectedException(ServiceNotFoundException::class, 'You have requested a non-existent service "test.foo".');
}
$container = new ContainerBuilder();
$bridge = new ZfExtensionManagerSfContainer('test.');
$bridge->setContainer($container);
$bridge->setStandalone(StandaloneExtensionManager::class);
$bridge->get('foo');
}
/**