Ver código fonte

Merge remote branch 'schmittjoh/security'

Fabien Potencier 14 anos atrás
pai
commit
18de62ccb1
19 arquivos alterados com 199 adições e 84 exclusões
  1. 2 1
      src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php
  2. 4 29
      src/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php
  3. 2 1
      src/Symfony/Component/DependencyInjection/Container.php
  4. 4 2
      src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
  5. 32 0
      src/Symfony/Component/DependencyInjection/Exception/CircularReferenceException.php
  6. 32 0
      src/Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php
  7. 0 23
      src/Symfony/Component/DependencyInjection/Exception/ScopeCrossingException.php
  8. 56 0
      src/Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php
  9. 0 23
      src/Symfony/Component/DependencyInjection/Exception/ScopeWideningException.php
  10. 55 0
      src/Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php
  11. 3 3
      tests/Symfony/Tests/Component/DependencyInjection/ContainerBuilderTest.php
  12. 2 2
      tests/Symfony/Tests/Component/DependencyInjection/ContainerTest.php
  13. 1 0
      tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services1-1.php
  14. 1 0
      tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services1.php
  15. 1 0
      tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services8.php
  16. 1 0
      tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services9.php
  17. 1 0
      tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services_interfaces-1-1.php
  18. 1 0
      tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services_interfaces-1.php
  19. 1 0
      tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services_interfaces-2.php

+ 2 - 1
src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php

@@ -2,6 +2,7 @@
 
 namespace Symfony\Component\DependencyInjection\Compiler;
 
+use Symfony\Component\DependencyInjection\Exception\CircularReferenceException;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 
 /**
@@ -50,7 +51,7 @@ class CheckCircularReferencesPass implements CompilerPassInterface
             $this->currentPath[] = $id = $node->getId();
 
             if ($this->currentId === $id) {
-                throw new \RuntimeException(sprintf('Circular reference detected for "%s", path: "%s".', $this->currentId, implode(' -> ', $this->currentPath)));
+                throw new CircularReferenceException($this->currentId, $this->currentPath);
             }
 
             $this->checkOutEdges($node->getOutEdges());

+ 4 - 29
src/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php

@@ -2,8 +2,8 @@
 
 namespace Symfony\Component\DependencyInjection\Compiler;
 
-use Symfony\Component\DependencyInjection\Exception\ScopeWideningException;
-use Symfony\Component\DependencyInjection\Exception\ScopeCrossingException;
+use Symfony\Component\DependencyInjection\Exception\ScopeWideningInjectionException;
+use Symfony\Component\DependencyInjection\Exception\ScopeCrossingInjectionException;
 use Symfony\Component\DependencyInjection\Definition;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Reference;
@@ -128,36 +128,11 @@ class CheckReferenceValidityPass implements CompilerPassInterface
         $id = (string) $reference;
 
         if (in_array($scope, $this->currentScopeChildren, true)) {
-            $ex = new ScopeWideningException(sprintf(
-                'Scope Widening Injection detected: The definition "%s" references the service "%s" which belongs to a narrower scope. '
-               .'Generally, it is safer to either move "%s" to scope "%s" or alternatively rely on the provider pattern by injecting the container itself, and requesting the service "%s" each time it is needed. '
-               .'In rare, special cases however that might not be necessary, then you can set the reference to strict=false to get rid of this error.',
-               $this->currentId,
-               $id,
-               $this->currentId,
-               $scope,
-               $id
-            ));
-            $ex->setServiceId($this->currentId);
-
-            throw $ex;
+            throw new ScopeWideningInjectionException($this->currentId, $this->currentScope, $id, $scope);
         }
 
         if (!in_array($scope, $this->currentScopeAncestors, true)) {
-            $ex = new ScopeCrossingException(sprintf(
-                'Scope Crossing Injection detected: The definition "%s" references the service "%s" which belongs to another scope hierarchy. '
-               .'This service might not be available consistently. Generally, it is safer to either move the definition "%s" to scope "%s", or '
-               .'declare "%s" as a child scope of "%s". If you can be sure that the other scope is always active, you can set the reference to strict=false to get rid of this error.',
-               $this->currentId,
-               $id,
-               $this->currentId,
-               $scope,
-               $this->currentScope,
-               $scope
-            ));
-            $ex->setServiceId($this->currentId);
-
-            throw $ex;
+            throw new ScopeCrossingInjectionException($this->currentId, $this->currentScope, $id, $scope);
         }
     }
 

+ 2 - 1
src/Symfony/Component/DependencyInjection/Container.php

@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\DependencyInjection;
 
+use Symfony\Component\DependencyInjection\Exception\CircularReferenceException;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
 use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
@@ -217,7 +218,7 @@ class Container implements ContainerInterface
         }
 
         if (isset($this->loading[$id])) {
-            throw new \LogicException(sprintf('Circular reference detected for service "%s" (services currently loading: %s).', $id, implode(', ', array_keys($this->loading))));
+            throw new CircularReferenceException($id, array_keys($this->loading));
         }
 
         if (method_exists($this, $method = 'get'.strtr($id, array('_' => '', '.' => '_')).'Service')) {

+ 4 - 2
src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\DependencyInjection\Dumper;
 
+use Symfony\Component\DependencyInjection\Exception\CircularReferenceException;
 use Symfony\Component\DependencyInjection\Variable;
 use Symfony\Component\DependencyInjection\Definition;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -251,7 +252,7 @@ EOF;
                 // $a = new ServiceA(ServiceB $b);
                 // $b->setServiceA(ServiceA $a);
                 if ($this->hasReference($id, $sDefinition->getArguments())) {
-                    throw new \RuntimeException('Unresolvable reference detected in service definition for '.$id);
+                    throw new CircularReferenceException($id, array($id));
                 }
 
                 $arguments = array();
@@ -549,7 +550,7 @@ EOF;
         if (ContainerInterface::SCOPE_CONTAINER !== $scope && ContainerInterface::SCOPE_PROTOTYPE !== $scope) {
             $code .= <<<EOF
         if (!isset(\$this->scopedServices['$scope'])) {
-            throw new \RuntimeException('You cannot create a service ("$id") of an inactive scope ("$scope").');
+            throw new InactiveScopeException('$id', '$scope');
         }
 
 
@@ -653,6 +654,7 @@ EOF;
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\DependencyInjection\Parameter;
 $bagClass

+ 32 - 0
src/Symfony/Component/DependencyInjection/Exception/CircularReferenceException.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace Symfony\Component\DependencyInjection\Exception;
+
+/**
+ * This exception is thrown when a circular reference is detected.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class CircularReferenceException extends RuntimeException
+{
+    private $serviceId;
+    private $path;
+
+    public function __construct($serviceId, array $path)
+    {
+        parent::__construct(sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, implode(' -> ', $path)));
+
+        $this->serviceId = $serviceId;
+        $this->path = $path;
+    }
+
+    public function getServiceId()
+    {
+        return $this->serviceId;
+    }
+
+    public function getPath()
+    {
+        return $this->path;
+    }
+}

+ 32 - 0
src/Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace Symfony\Component\DependencyInjection\Exception;
+
+/**
+ * This exception is thrown when you try to create a service of an inactive scope.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class InactiveScopeException extends RuntimeException
+{
+    private $serviceId;
+    private $scope;
+
+    public function __construct($serviceId, $scope)
+    {
+        parent::__construct(sprintf('You cannot create a service ("%s") of an inactive scope ("%s").', $serviceId, $scope));
+
+        $this->serviceId = $serviceId;
+        $this->scope = $scope;
+    }
+
+    public function getServiceId()
+    {
+        return $this->serviceId;
+    }
+
+    public function getScope()
+    {
+        return $this->scope;
+    }
+}

+ 0 - 23
src/Symfony/Component/DependencyInjection/Exception/ScopeCrossingException.php

@@ -1,23 +0,0 @@
-<?php
-
-namespace Symfony\Component\DependencyInjection\Exception;
-
-/**
- * This exception is thrown when the a scope crossing injection is detected.
- *
- * @author Johannes M. Schmitt <schmittjoh@gmail.com>
- */
-class ScopeCrossingException extends RuntimeException
-{
-    private $serviceId;
-
-    public function setServiceId($id)
-    {
-        $this->serviceId = $id;
-    }
-
-    public function getServiceId()
-    {
-        return $this->serviceId;
-    }
-}

+ 56 - 0
src/Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace Symfony\Component\DependencyInjection\Exception;
+
+/**
+ * This exception is thrown when the a scope crossing injection is detected.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class ScopeCrossingInjectionException extends RuntimeException
+{
+    private $sourceServiceId;
+    private $sourceScope;
+    private $destServiceId;
+    private $destScope;
+
+    public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope)
+    {
+        parent::__construct(sprintf(
+            'Scope Crossing Injection detected: The definition "%s" references the service "%s" which belongs to another scope hierarchy. '
+           .'This service might not be available consistently. Generally, it is safer to either move the definition "%s" to scope "%s", or '
+           .'declare "%s" as a child scope of "%s". If you can be sure that the other scope is always active, you can set the reference to strict=false to get rid of this error.',
+           $sourceServiceId,
+           $destServiceId,
+           $sourceServiceId,
+           $destScope,
+           $sourceScope,
+           $destScope
+        ));
+
+        $this->sourceServiceId = $sourceServiceId;
+        $this->sourceScope = $sourceScope;
+        $this->destServiceId = $destServiceId;
+        $this->destScope = $destScope;
+    }
+
+    public function getSourceServiceId()
+    {
+        return $this->sourceServiceId;
+    }
+
+    public function getSourceScope()
+    {
+        return $this->sourceScope;
+    }
+
+    public function getDestServiceId()
+    {
+        return $this->destServiceId;
+    }
+
+    public function getDestScope()
+    {
+        return $this->destScope;
+    }
+}

+ 0 - 23
src/Symfony/Component/DependencyInjection/Exception/ScopeWideningException.php

@@ -1,23 +0,0 @@
-<?php
-
-namespace Symfony\Component\DependencyInjection\Exception;
-
-/**
- * Thrown when a scope widening injection is detected.
- *
- * @author Johannes M. Schmitt <schmittjoh@gmail.com>
- */
-class ScopeWideningException extends RuntimeException
-{
-    private $serviceId;
-
-    public function setServiceId($id)
-    {
-        $this->serviceId = $id;
-    }
-
-    public function getServiceId()
-    {
-        return $this->serviceId;
-    }
-}

+ 55 - 0
src/Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace Symfony\Component\DependencyInjection\Exception;
+
+/**
+ * Thrown when a scope widening injection is detected.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class ScopeWideningInjectionException extends RuntimeException
+{
+    private $sourceServiceId;
+    private $sourceScope;
+    private $destServiceId;
+    private $destScope;
+
+    public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope)
+    {
+        parent::__construct(sprintf(
+            'Scope Widening Injection detected: The definition "%s" references the service "%s" which belongs to a narrower scope. '
+           .'Generally, it is safer to either move "%s" to scope "%s" or alternatively rely on the provider pattern by injecting the container itself, and requesting the service "%s" each time it is needed. '
+           .'In rare, special cases however that might not be necessary, then you can set the reference to strict=false to get rid of this error.',
+           $sourceServiceId,
+           $destServiceId,
+           $sourceServiceId,
+           $destScope,
+           $destServiceId
+        ));
+
+        $this->sourceServiceId = $sourceServiceId;
+        $this->sourceScope = $sourceScope;
+        $this->destServiceId = $destServiceId;
+        $this->destScope = $destScope;
+    }
+
+    public function getSourceServiceId()
+    {
+        return $this->sourceServiceId;
+    }
+
+    public function getSourceScope()
+    {
+        return $this->sourceScope;
+    }
+
+    public function getDestServiceId()
+    {
+        return $this->destServiceId;
+    }
+
+    public function getDestScope()
+    {
+        return $this->destScope;
+    }
+}

+ 3 - 3
tests/Symfony/Tests/Component/DependencyInjection/ContainerBuilderTest.php

@@ -107,9 +107,9 @@ class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
         $builder->register('baz', 'stdClass')->setArguments(array(new Reference('baz')));
         try {
             @$builder->get('baz');
-            $this->fail('->get() throws a LogicException if the service has a circular reference to itself');
-        } catch (\LogicException $e) {
-            $this->assertEquals('Circular reference detected for service "baz" (services currently loading: baz).', $e->getMessage(), '->get() throws a LogicException if the service has a circular reference to itself');
+            $this->fail('->get() throws a CircularReferenceException if the service has a circular reference to itself');
+        } catch (\Symfony\Component\DependencyInjection\Exception\CircularReferenceException $e) {
+            $this->assertEquals('Circular reference detected for service "baz", path: "baz".', $e->getMessage(), '->get() throws a LogicException if the service has a circular reference to itself');
         }
 
         $builder->register('foobar', 'stdClass')->setScope('container');

+ 2 - 2
tests/Symfony/Tests/Component/DependencyInjection/ContainerTest.php

@@ -173,9 +173,9 @@ class ContainerTest extends \PHPUnit_Framework_TestCase
         $sc = new ProjectServiceContainer();
         try {
             $sc->get('circular');
-            $this->fail('->get() throws a \LogicException if it contains circular reference');
+            $this->fail('->get() throws a CircularReferenceException if it contains circular reference');
         } catch (\Exception $e) {
-            $this->assertInstanceOf('\LogicException', $e, '->get() throws a \LogicException if it contains circular reference');
+            $this->assertInstanceOf('\Symfony\Component\DependencyInjection\Exception\CircularReferenceException', $e, '->get() throws a CircularReferenceException if it contains circular reference');
             $this->assertStringStartsWith('Circular reference detected for service "circular"', $e->getMessage(), '->get() throws a \LogicException if it contains circular reference');
         }
     }

+ 1 - 0
tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services1-1.php

@@ -2,6 +2,7 @@
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\DependencyInjection\Parameter;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

+ 1 - 0
tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services1.php

@@ -2,6 +2,7 @@
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\DependencyInjection\Parameter;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

+ 1 - 0
tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services8.php

@@ -2,6 +2,7 @@
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\DependencyInjection\Parameter;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

+ 1 - 0
tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services9.php

@@ -2,6 +2,7 @@
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\DependencyInjection\Parameter;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

+ 1 - 0
tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services_interfaces-1-1.php

@@ -2,6 +2,7 @@
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\DependencyInjection\Parameter;
 

+ 1 - 0
tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services_interfaces-1.php

@@ -2,6 +2,7 @@
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\DependencyInjection\Parameter;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

+ 1 - 0
tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services_interfaces-2.php

@@ -2,6 +2,7 @@
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\DependencyInjection\Parameter;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;