Browse Source

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

Fabien Potencier 15 năm trước cách đây
mục cha
commit
a9ad743006

+ 1 - 5
src/Symfony/Components/DependencyInjection/Loader/XmlFileLoader.php

@@ -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));

+ 2 - 2
src/Symfony/Components/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd

@@ -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>
 

+ 23 - 0
tests/Symfony/Tests/Components/DependencyInjection/Fixtures/includes/ProjectWithXsdExtension.php

@@ -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';
+    }
+}

+ 13 - 0
tests/Symfony/Tests/Components/DependencyInjection/Fixtures/includes/schema/project-1.0.xsd

@@ -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>

+ 3 - 1
tests/Symfony/Tests/Components/DependencyInjection/Fixtures/xml/services10.xml

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

+ 19 - 0
tests/Symfony/Tests/Components/DependencyInjection/Fixtures/xml/extensions/services2.xml

@@ -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>

+ 19 - 0
tests/Symfony/Tests/Components/DependencyInjection/Fixtures/xml/extensions/services3.xml

@@ -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>

+ 2 - 4
tests/Symfony/Tests/Components/DependencyInjection/Fixtures/xml/services11.xml

@@ -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>

+ 11 - 0
tests/Symfony/Tests/Components/DependencyInjection/Fixtures/xml/extensions/services5.xml

@@ -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>

+ 0 - 8
tests/Symfony/Tests/Components/DependencyInjection/Fixtures/xml/services12.xml

@@ -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>

+ 32 - 7
tests/Symfony/Tests/Components/DependencyInjection/Loader/XmlFileLoaderTest.php

@@ -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('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('services11.xml');
+            $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');
         }
     }
 }