Просмотр исходного кода

adds synthetic attribute to definitions

This attribute can be used to hint that the service is being injected
dynamically at runtime, and not constructed by the DIC.
Johannes M. Schmitt 14 лет назад
Родитель
Сommit
0144dd86da

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml

@@ -35,7 +35,7 @@
             This service definition only defines the scope of the request.
             It is used to check references scope.
         -->
-        <service id="request" scope="request" />
+        <service id="request" scope="request" synthetic="true" />
 
         <service id="response" class="%response.class%" scope="prototype">
             <call method="setCharset">

+ 28 - 0
src/Symfony/Component/DependencyInjection/Definition.php

@@ -28,6 +28,7 @@ class Definition
     protected $configurator;
     protected $tags;
     protected $public;
+    protected $synthetic;
 
     /**
      * Constructor.
@@ -43,6 +44,7 @@ class Definition
         $this->scope = ContainerInterface::SCOPE_CONTAINER;
         $this->tags = array();
         $this->public = true;
+        $this->synthetic = false;
     }
 
     /**
@@ -377,6 +379,32 @@ class Definition
         return $this->public;
     }
 
+    /**
+     * Sets whether this definition is synthetic, that is not constructed by the
+     * container, but dynamically injected.
+     *
+     * @param Boolean $boolean
+     *
+     * @return Definition the current instance
+     */
+    public function setSynthetic($boolean)
+    {
+        $this->synthetic = (Boolean) $boolean;
+
+        return $this;
+    }
+
+    /**
+     * Whether this definition is synthetic, that is not constructed by the
+     * container, but dynamically injected.
+     *
+     * @return Boolean
+     */
+    public function isSynthetic()
+    {
+        return $this->synthetic;
+    }
+
     /**
      * Sets a configurator to call after the service is fully initialized.
      *

+ 17 - 11
src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

@@ -394,7 +394,9 @@ EOF;
         $this->variableCount = 0;
 
         $return = '';
-        if ($class = $definition->getClass()) {
+        if ($definition->isSynthetic()) {
+            $return = sprintf('@throws \RuntimeException always since this service is expected to be injected dynamically');
+        } else if ($class = $definition->getClass()) {
             $return = sprintf("@return %s A %s instance.", 0 === strpos($class, '%') ? 'Object' : $class, $class);
         } elseif ($definition->getFactoryService()) {
             $return = sprintf('@return Object An instance returned by %s::%s().', $definition->getFactoryService(), $definition->getFactoryMethod());
@@ -443,16 +445,20 @@ EOF;
 EOF;
         }
 
-        $code .=
-            $this->addServiceInclude($id, $definition).
-            $this->addServiceLocalTempVariables($id, $definition).
-            $this->addServiceInlinedDefinitions($id, $definition).
-            $this->addServiceInstance($id, $definition).
-            $this->addServiceInlinedDefinitionsSetup($id, $definition).
-            $this->addServiceMethodCalls($id, $definition).
-            $this->addServiceConfigurator($id, $definition).
-            $this->addServiceReturn($id, $definition)
-        ;
+        if ($definition->isSynthetic()) {
+            $code .= sprintf("        throw new \RuntimeException('You have requested a synthetic service (\"%s\"). The DIC does not know how to construct this service.');\n    }\n", $id);
+        } else {
+            $code .=
+                $this->addServiceInclude($id, $definition).
+                $this->addServiceLocalTempVariables($id, $definition).
+                $this->addServiceInlinedDefinitions($id, $definition).
+                $this->addServiceInstance($id, $definition).
+                $this->addServiceInlinedDefinitionsSetup($id, $definition).
+                $this->addServiceMethodCalls($id, $definition).
+                $this->addServiceConfigurator($id, $definition).
+                $this->addServiceReturn($id, $definition)
+            ;
+        }
 
         $this->definitionVariables = null;
         $this->referenceVariables = null;

+ 1 - 3
src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php

@@ -12,9 +12,7 @@
 namespace Symfony\Component\DependencyInjection\Loader;
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
-
 use Symfony\Component\DependencyInjection\Alias;
-
 use Symfony\Component\DependencyInjection\InterfaceInjector;
 use Symfony\Component\DependencyInjection\Definition;
 use Symfony\Component\DependencyInjection\Reference;
@@ -139,7 +137,7 @@ class XmlFileLoader extends FileLoader
 
         $definition = new Definition();
 
-        foreach (array('class', 'scope', 'public', 'factory-method', 'factory-service') as $key) {
+        foreach (array('class', 'scope', 'public', 'factory-method', 'factory-service', 'synthetic') as $key) {
             if (isset($service[$key])) {
                 $method = 'set'.str_replace('-', '', $key);
                 $definition->$method((string) $service->getAttributeAsPhp($key));

+ 4 - 1
src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php

@@ -12,7 +12,6 @@
 namespace Symfony\Component\DependencyInjection\Loader;
 
 use Symfony\Component\DependencyInjection\Alias;
-
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\InterfaceInjector;
 use Symfony\Component\DependencyInjection\Definition;
@@ -148,6 +147,10 @@ class YamlFileLoader extends FileLoader
             $definition->setScope($service['scope']);
         }
 
+        if (isset($service['synthetic'])) {
+            $definition->setSynthetic($service['synthetic']);
+        }
+
         if (isset($service['public'])) {
             $definition->setPublic($service['public']);
         }

+ 1 - 0
src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd

@@ -103,6 +103,7 @@
     <xsd:attribute name="class" type="xsd:string" />
     <xsd:attribute name="scope" type="xsd:string" />
     <xsd:attribute name="public" type="boolean" />
+    <xsd:attribute name="synthetic" type="boolean" />
     <xsd:attribute name="factory-method" type="xsd:string" />
     <xsd:attribute name="factory-service" type="xsd:string" />
     <xsd:attribute name="alias" type="xsd:string" />

+ 12 - 0
tests/Symfony/Tests/Component/DependencyInjection/DefinitionTest.php

@@ -125,6 +125,18 @@ class DefinitionTest extends \PHPUnit_Framework_TestCase
         $this->assertFalse($def->isPublic(), '->isPublic() returns false if the instance must not be public.');
     }
 
+    /**
+     * @covers Symfony\Component\DependencyInjection\Definition::setSynthetic
+     * @covers Symfony\Component\DependencyInjection\Definition::isSynthetic
+     */
+    public function testSetIsSynthetic()
+    {
+        $def = new Definition('stdClass');
+        $this->assertFalse($def->isSynthetic(), '->isSynthetic() returns false by default');
+        $this->assertSame($def, $def->setSynthetic(true), '->setSynthetic() implements a fluent interface');
+        $this->assertTrue($def->isSynthetic(), '->isSynthetic() returns true if the instance must not be public.');
+    }
+
     /**
      * @covers Symfony\Component\DependencyInjection\Definition::setConfigurator
      * @covers Symfony\Component\DependencyInjection\Definition::getConfigurator