[DependencyInjection] changed the main services.xsd to be more strict (the validation was basically disabled because of ##any)

This commit is contained in:
Fabien Potencier 2010-07-05 09:13:01 +02:00
parent 72254b9569
commit a9ad743006
11 changed files with 125 additions and 27 deletions

View File

@ -244,7 +244,7 @@ class XmlFileLoader extends FileLoader
if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) {
$items = preg_split('/\s+/', $element);
for ($i = 0, $nb = count($items); $i < $nb; $i += 2) {
if ($extension = static::getExtension($items[$i])) {
if (($extension = static::getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) {
$path = str_replace($extension->getNamespace(), str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]);
if (!file_exists($path)) {
@ -295,10 +295,6 @@ EOF
continue;
}
if ($node->namespaceURI === 'http://www.symfony-project.org/schema/dic/services') {
throw new \InvalidArgumentException(sprintf('The "%s" tag is not valid (in %s).', $node->tagName, $file));
}
// can it be handled by an extension?
if (!static::getExtension($node->namespaceURI)) {
throw new \InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in %s).', $node->tagName, $file));

View File

@ -24,11 +24,11 @@
]]></xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="imports" type="imports" minOccurs="0" maxOccurs="1" />
<xsd:element name="parameters" type="parameters" minOccurs="0" maxOccurs="1" />
<xsd:element name="services" type="services" minOccurs="0" maxOccurs="1" />
<xsd:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>

View File

@ -0,0 +1,23 @@
<?php
use Symfony\Components\DependencyInjection\BuilderConfiguration;
use Symfony\Components\DependencyInjection\Definition;
use Symfony\Components\DependencyInjection\Loader\LoaderExtension;
class ProjectWithXsdExtension extends ProjectExtension
{
public function getXsdValidationBasePath()
{
return __DIR__.'/schema';
}
public function getNamespace()
{
return 'http://www.example.com/schema/projectwithxsd';
}
public function getAlias()
{
return 'projectwithxsd';
}
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.example.com/schema/projectwithxsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com/schema/projectwithxsd"
elementFormDefault="qualified">
<xsd:element name="bar" type="bar" />
<xsd:complexType name="bar">
<xsd:attribute name="foo" type="xsd:string" />
</xsd:complexType>
</xsd:schema>

View File

@ -11,6 +11,8 @@
<service id="project.service.foo" class="BAR" />
</services>
<project:bar />
<project:bar babar="babar">
<another />
</project:bar>
</container>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" ?>
<container xmlns="http://www.symfony-project.org/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:project="http://www.example.com/schema/projectwithxsd"
xsi:schemaLocation="http://www.symfony-project.org/schema/dic/services http://www.symfony-project.org/schema/dic/services/services-1.0.xsd
http://www.example.com/schema/projectwithxsd http://www.example.com/schema/projectwithxsd/project-1.0.xsd">
<parameters>
<parameter key="project.parameter.foo">BAR</parameter>
</parameters>
<services>
<service id="project.service.foo" class="BAR" />
</services>
<project:bar />
</container>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" ?>
<container xmlns="http://www.symfony-project.org/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:project="http://www.example.com/schema/projectwithxsd"
xsi:schemaLocation="http://www.symfony-project.org/schema/dic/services http://www.symfony-project.org/schema/dic/services/services-1.0.xsd
http://www.example.com/schema/projectwithxsd http://www.example.com/schema/projectwithxsd/project-1.0.xsd">
<parameters>
<parameter key="project.parameter.foo">BAR</parameter>
</parameters>
<services>
<service id="project.service.foo" class="BAR" />
</services>
<project:bar bar="bar" />
</container>

View File

@ -1,8 +1,6 @@
<?xml version="1.0" ?>
<container xmlns="http://www.symfony-project.org/schema/dic/services"
xmlns:foobar="http://www.example.com/schema/foobar">
<foobar:foobar />
xmlns:project="http://www.example.com/schema/not_registered_extension">
<project:bar />
</container>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" ?>
<container xmlns="http://www.symfony-project.org/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:project="http://www.example.com/schema/projectwithxsd"
xsi:schemaLocation="http://www.symfony-project.org/schema/dic/services http://www.symfony-project.org/schema/dic/services/services-1.0.xsd
http://www.example.com/schema/projectwithxsd http://www.example.com/schema/projectwithxsd/project-1.0.xsd">
<project:foobar />
</container>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" ?>
<container xmlns="http://www.symfony-project.org/schema/dic/services"
xmlns:project="http://www.example.com/schema/project">
<foobar />
</container>

View File

@ -24,6 +24,7 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
require_once self::$fixturesPath.'/includes/ProjectExtension.php';
require_once self::$fixturesPath.'/includes/ProjectWithXsdExtension.php';
}
public function testLoad()
@ -161,9 +162,11 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
public function testExtensions()
{
Loader::registerExtension(new \ProjectExtension());
Loader::registerExtension(new \ProjectWithXsdExtension());
$loader = new ProjectLoader2(self::$fixturesPath.'/xml');
$config = $loader->load('services10.xml');
// extension without an XSD
$config = $loader->load('extensions/services1.xml');
$services = $config->getDefinitions();
$parameters = $config->getParameterBag()->all();
@ -173,20 +176,42 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
$this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');
// extension with an XSD
$config = $loader->load('extensions/services2.xml');
$services = $config->getDefinitions();
$parameters = $config->getParameterBag()->all();
$this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements');
$this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements');
$this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
$this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');
// extension with an XSD (does not validate)
try {
$config = $loader->load('services11.xml');
$config = $loader->load('extensions/services3.xml');
$this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
} catch (\Exception $e) {
$this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
$this->assertRegexp('/The attribute \'bar\' is not allowed/', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
}
// non-registered extension
try {
$config = $loader->load('extensions/services4.xml');
$this->fail('->load() throws an InvalidArgumentException if the tag is not valid');
} catch (\Exception $e) {
$this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid');
$this->assertStringStartsWith('There is no extension able to load the configuration for "foobar:foobar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid');
$this->assertStringStartsWith('There is no extension able to load the configuration for "project:bar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid');
}
// non-existent tag for a known extension
try {
$config = $loader->load('services12.xml');
$this->fail('->load() throws an InvalidArgumentException if an extension is not loaded');
$config = $loader->load('extensions/services5.xml');
$this->fail('->load() throws an InvalidArgumentException if a tag is not valid for a given extension');
} catch (\Exception $e) {
$this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if an extension is not loaded');
$this->assertStringStartsWith('The "foobar" tag is not valid (in', $e->getMessage(), '->load() throws an InvalidArgumentException if an extension is not loaded');
$this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag is not valid for a given extension');
$this->assertStringStartsWith('The tag "projectwithxsd:foobar" is not defined in the "projectwithxsd" extension.', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag is not valid for a given extension');
}
}
}