ソースを参照

[DependencyInjection] adds property injection

Johannes Schmitt 14 年 前
コミット
eb2eb2e47a

+ 7 - 5
src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php

@@ -31,16 +31,16 @@ class AnalyzeServiceReferencesPass implements RepeatablePassInterface
     protected $currentId;
     protected $currentDefinition;
     protected $repeatedPass;
-    protected $ignoreMethodCalls;
+    protected $onlyConstructorArguments;
 
     /**
      * Constructor.
      *
      * @param boolean $ignoreMethodCalls Sets this Service Reference pass to ignore method calls
      */
-    public function __construct($ignoreMethodCalls = false)
+    public function __construct($onlyConstructorArguments = false)
     {
-        $this->ignoreMethodCalls = (Boolean) $ignoreMethodCalls;
+        $this->onlyConstructorArguments = (Boolean) $onlyConstructorArguments;
     }
 
     /**
@@ -53,7 +53,7 @@ class AnalyzeServiceReferencesPass implements RepeatablePassInterface
     /**
      * Processes a ContainerBuilder object to populate the service reference graph.
      *
-     * @param ContainerBuilder $container 
+     * @param ContainerBuilder $container
      */
     public function process(ContainerBuilder $container)
     {
@@ -70,8 +70,9 @@ class AnalyzeServiceReferencesPass implements RepeatablePassInterface
             $this->currentDefinition = $definition;
             $this->processArguments($definition->getArguments());
 
-            if (!$this->ignoreMethodCalls) {
+            if (!$this->onlyConstructorArguments) {
                 $this->processArguments($definition->getMethodCalls());
+                $this->processArguments($definition->getProperties());
             }
         }
 
@@ -101,6 +102,7 @@ class AnalyzeServiceReferencesPass implements RepeatablePassInterface
             } else if ($argument instanceof Definition) {
                 $this->processArguments($argument->getArguments());
                 $this->processArguments($argument->getMethodCalls());
+                $this->processArguments($argument->getProperties());
             }
         }
     }

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

@@ -29,7 +29,7 @@ class CheckReferenceValidityPass implements CompilerPassInterface
     /**
      * Processes the ContainerBuilder to validate References.
      *
-     * @param ContainerBuilder $container 
+     * @param ContainerBuilder $container
      */
     public function process(ContainerBuilder $container)
     {
@@ -66,6 +66,7 @@ class CheckReferenceValidityPass implements CompilerPassInterface
 
             $this->validateReferences($definition->getArguments());
             $this->validateReferences($definition->getMethodCalls());
+            $this->validateReferences($definition->getProperties());
         }
     }
 
@@ -100,8 +101,8 @@ class CheckReferenceValidityPass implements CompilerPassInterface
     /**
      * Validates the scope of a single Reference.
      *
-     * @param Reference $reference 
-     * @param Definition $definition 
+     * @param Reference $reference
+     * @param Definition $definition
      * @throws \RuntimeException when there is an issue with the Reference scope
      */
     protected function validateScope(Reference $reference, Definition $definition = null)

+ 5 - 0
src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php

@@ -51,6 +51,10 @@ class InlineServiceDefinitionsPass implements RepeatablePassInterface
             $definition->setMethodCalls(
                 $this->inlineArguments($container, $definition->getMethodCalls())
             );
+
+            $definition->setProperties(
+                $this->inlineArguments($container, $definition->getProperties())
+            );
         }
     }
 
@@ -80,6 +84,7 @@ class InlineServiceDefinitionsPass implements RepeatablePassInterface
             } else if ($argument instanceof Definition) {
                 $argument->setArguments($this->inlineArguments($container, $argument->getArguments()));
                 $argument->setMethodCalls($this->inlineArguments($container, $argument->getMethodCalls()));
+                $argument->setProperties($this->inlineArguments($container, $argument->getProperties()));
             }
         }
 

+ 8 - 2
src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php

@@ -19,7 +19,7 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
     /**
      * Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances.
      *
-     * @param ContainerBuilder $container 
+     * @param ContainerBuilder $container
      */
     public function process(ContainerBuilder $container)
     {
@@ -40,7 +40,7 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
      * Resolves the definition
      *
      * @param string $id The definition identifier
-     * @param DefinitionDecorator $definition 
+     * @param DefinitionDecorator $definition
      * @return Definition
      */
     protected function resolveDefinition($id, DefinitionDecorator $definition)
@@ -61,6 +61,7 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
         $def->setClass($parentDef->getClass());
         $def->setArguments($parentDef->getArguments());
         $def->setMethodCalls($parentDef->getMethodCalls());
+        $def->setProperties($parentDef->getProperties());
         $def->setFactoryClass($parentDef->getFactoryClass());
         $def->setFactoryMethod($parentDef->getFactoryMethod());
         $def->setFactoryService($parentDef->getFactoryService());
@@ -107,6 +108,11 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
             $def->setArgument($index, $v);
         }
 
+        // merge properties
+        foreach ($definition->getProperties() as $k => $v) {
+            $def->setProperty($k, $v);
+        }
+
         // append method calls
         if (count($calls = $definition->getMethodCalls()) > 0) {
             $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));

+ 14 - 3
src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php

@@ -26,7 +26,7 @@ class ResolveInvalidReferencesPass implements CompilerPassInterface
     protected $container;
     protected $exceptions;
 
-    /** 
+    /**
      * Constructor.
      *
      * @param array $exceptions An array of exceptions
@@ -49,7 +49,7 @@ class ResolveInvalidReferencesPass implements CompilerPassInterface
     /**
      * Process the ContainerBuilder to resolve invalid references.
      *
-     * @param ContainerBuilder $container 
+     * @param ContainerBuilder $container
      */
     public function process(ContainerBuilder $container)
     {
@@ -72,6 +72,17 @@ class ResolveInvalidReferencesPass implements CompilerPassInterface
                 }
             }
             $definition->setMethodCalls($calls);
+
+            $properties = array();
+            foreach ($definition->getProperties() as $name => $value) {
+                try {
+                    $value = $this->processArguments(array($value), true);
+                    $properties[$name] = reset($value);
+                } catch (\RuntimeException $ignore) {
+                    // ignore property
+                }
+            }
+            $definition->setProperties($properties);
         }
     }
 
@@ -79,7 +90,7 @@ class ResolveInvalidReferencesPass implements CompilerPassInterface
      * Processes arguments to determine invalid references.
      *
      * @param array $arguments An array of Reference objects
-     * @param boolean $inMethodCall 
+     * @param boolean $inMethodCall
      */
     protected function processArguments(array $arguments, $inMethodCall = false)
     {

+ 3 - 1
src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php

@@ -25,7 +25,7 @@ class ResolveParameterPlaceHoldersPass implements CompilerPassInterface
     /**
      * Processes the ContainerBuilder to resolve parameter placeholders.
      *
-     * @param ContainerBuilder $container 
+     * @param ContainerBuilder $container
      */
     public function process(ContainerBuilder $container)
     {
@@ -41,6 +41,8 @@ class ResolveParameterPlaceHoldersPass implements CompilerPassInterface
                 $calls[$this->resolveValue($name)] = $this->resolveValue($arguments);
             }
             $definition->setMethodCalls($calls);
+
+            $definition->setProperties($this->resolveValue($definition->getProperties()));
         }
 
         $aliases = array();

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

@@ -27,7 +27,7 @@ class ResolveReferencesToAliasesPass implements CompilerPassInterface
     /**
      * Processes the ContainerBuilder to replace references to aliases with actual service references.
      *
-     * @param ContainerBuilder $container 
+     * @param ContainerBuilder $container
      */
     public function process(ContainerBuilder $container)
     {
@@ -40,6 +40,7 @@ class ResolveReferencesToAliasesPass implements CompilerPassInterface
 
             $definition->setArguments($this->processArguments($definition->getArguments()));
             $definition->setMethodCalls($this->processArguments($definition->getMethodCalls()));
+            $definition->setProperties($this->processArguments($definition->getProperties()));
         }
 
         foreach ($container->getAliases() as $id => $alias) {

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

@@ -25,6 +25,7 @@ class Definition
     protected $factoryService;
     protected $scope;
     protected $arguments;
+    protected $properties;
     protected $calls;
     protected $configurator;
     protected $tags;
@@ -48,6 +49,7 @@ class Definition
         $this->public = true;
         $this->synthetic = false;
         $this->abstract = false;
+        $this->properties = array();
     }
 
     /**
@@ -161,6 +163,25 @@ class Definition
         return $this;
     }
 
+    public function setProperties(array $properties)
+    {
+        $this->properties = $properties;
+
+        return $this;
+    }
+
+    public function getProperties()
+    {
+        return $this->properties;
+    }
+
+    public function setProperty($name, $value)
+    {
+        $this->properties[$name] = $value;
+
+        return $this;
+    }
+
     /**
      * Adds an argument to pass to the service constructor/factory method.
      *

+ 58 - 43
src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

@@ -134,8 +134,8 @@ EOF;
     /**
      * Generates Service local temp variables.
      *
-     * @param string $cId 
-     * @param string $definition 
+     * @param string $cId
+     * @param string $definition
      * @return string
      */
     protected function addServiceLocalTempVariables($cId, $definition)
@@ -151,6 +151,7 @@ EOF;
         foreach ($localDefinitions as $iDefinition) {
             $this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior);
             $this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior);
+            $this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior);
         }
 
         $code = '';
@@ -182,7 +183,7 @@ EOF;
      * Generates the require_once statement for service includes.
      *
      * @param string $id The service id
-     * @param Definition $definition 
+     * @param Definition $definition
      * @return string
      */
     protected function addServiceInclude($id, $definition)
@@ -210,8 +211,8 @@ EOF;
     /**
      * Generates the inline definition of a service.
      *
-     * @param string $id 
-     * @param Definition $definition 
+     * @param string $id
+     * @param Definition $definition
      * @return string
      */
     protected function addServiceInlinedDefinitions($id, $definition)
@@ -238,7 +239,7 @@ EOF;
             $processed->offsetSet($sDefinition);
 
             $class = $this->dumpValue($sDefinition->getClass());
-            if ($nbOccurrences->offsetGet($sDefinition) > 1 || count($sDefinition->getMethodCalls()) > 0 || null !== $sDefinition->getConfigurator() || false !== strpos($class, '$')) {
+            if ($nbOccurrences->offsetGet($sDefinition) > 1 || count($sDefinition->getMethodCalls()) > 0 || $sDefinition->getProperties() || null !== $sDefinition->getConfigurator() || false !== strpos($class, '$')) {
                 $name = $this->getNextVariableName();
                 $variableMap->offsetSet($sDefinition, new Variable($name));
 
@@ -272,8 +273,9 @@ EOF;
                     $code .= sprintf("        \$%s = new \\%s(%s);\n", $name, substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments));
                 }
 
-                if (!$this->hasReference($id, $sDefinition->getMethodCalls())) {
+                if (!$this->hasReference($id, $sDefinition->getMethodCalls()) && !$this->hasReference($id, $sDefinition->getProperties())) {
                     $code .= $this->addServiceMethodCalls(null, $sDefinition, $name);
+                    $code .= $this->addServiceProperties(null, $sDefinition, $name);
                     $code .= $this->addServiceConfigurator(null, $sDefinition, $name);
                 }
 
@@ -288,7 +290,7 @@ EOF;
      * Adds the service return statement.
      *
      * @param string $id Service id
-     * @param Definition $definition 
+     * @param Definition $definition
      * @return string
      */
     protected function addServiceReturn($id, $definition)
@@ -304,7 +306,7 @@ EOF;
      * Generates the service instance.
      *
      * @param string $id
-     * @param Definition $definition 
+     * @param Definition $definition
      * @return string
      *
      * @throws \InvalidArgumentException
@@ -365,8 +367,8 @@ EOF;
     /**
      * Checks if the definition is a simple instance.
      *
-     * @param string $id 
-     * @param Definition $definition 
+     * @param string $id
+     * @param Definition $definition
      * @return boolean
      */
     protected function isSimpleInstance($id, $definition)
@@ -376,7 +378,7 @@ EOF;
                 continue;
             }
 
-            if ($sDefinition->getMethodCalls() || $sDefinition->getConfigurator()) {
+            if ($sDefinition->getMethodCalls() || $sDefinition->getProperties() || $sDefinition->getConfigurator()) {
                 return false;
             }
         }
@@ -387,9 +389,9 @@ EOF;
     /**
      * Adds method calls to a service definition.
      *
-     * @param string $id 
-     * @param Definition $definition 
-     * @param string $variableName 
+     * @param string $id
+     * @param Definition $definition
+     * @param string $variableName
      * @return string
      */
     protected function addServiceMethodCalls($id, $definition, $variableName = 'instance')
@@ -411,11 +413,23 @@ EOF;
         return $calls;
     }
 
+    protected function addServiceProperties($id, $definition, $variableName = 'instance')
+    {
+        $code = '';
+        foreach ($definition->getProperties() as $name => $value) {
+            $code .= sprintf("        \$%s = new \ReflectionProperty(\$%s, %s);\n", $refName = $this->getNextVariableName(), $variableName, var_export($name, true));
+            $code .= sprintf("        \$%s->setAccessible(true);\n", $refName);
+            $code .= sprintf("        \$%s->setValue(\$%s, %s);\n", $refName, $variableName, $this->dumpValue($value));
+        }
+
+        return $code;
+    }
+
     /**
      * Generates the inline definition setup.
      *
-     * @param string $id 
-     * @param Definition $definition 
+     * @param string $id
+     * @param Definition $definition
      * @return string
      */
     protected function addServiceInlinedDefinitionsSetup($id, $definition)
@@ -452,9 +466,9 @@ EOF;
     /**
      * Adds configurator definition
      *
-     * @param string $id 
-     * @param Definition $definition 
-     * @param string $variableName 
+     * @param string $id
+     * @param Definition $definition
+     * @param string $variableName
      * @return string
      */
     protected function addServiceConfigurator($id, $definition, $variableName = 'instance')
@@ -477,8 +491,8 @@ EOF;
     /**
      * Adds a service
      *
-     * @param string $id 
-     * @param Definition $definition 
+     * @param string $id
+     * @param Definition $definition
      * @return string
      */
     protected function addService($id, $definition)
@@ -552,6 +566,7 @@ EOF;
                 $this->addServiceInstance($id, $definition).
                 $this->addServiceInlinedDefinitionsSetup($id, $definition).
                 $this->addServiceMethodCalls($id, $definition).
+                $this->addServiceProperties($id, $definition).
                 $this->addServiceConfigurator($id, $definition).
                 $this->addServiceReturn($id, $definition)
             ;
@@ -566,8 +581,8 @@ EOF;
     /**
      * Adds a service alias.
      *
-     * @param string $alias 
-     * @param string $id 
+     * @param string $alias
+     * @param string $id
      * @return string
      */
     protected function addServiceAlias($alias, $id)
@@ -795,8 +810,8 @@ EOF;
     /**
      * Exports parameters.
      *
-     * @param string $parameters 
-     * @param integer $indent 
+     * @param string $parameters
+     * @param integer $indent
      * @return string
      */
     protected function exportParameters($parameters, $indent = 12)
@@ -837,8 +852,8 @@ EOF;
     /**
      * Wraps the service conditionals.
      *
-     * @param string $value 
-     * @param string $code 
+     * @param string $value
+     * @param string $code
      * @return string
      */
     protected function wrapServiceConditionals($value, $code)
@@ -861,7 +876,7 @@ EOF;
     /**
      * Builds service calls from arguments
      *
-     * @param array $arguments 
+     * @param array $arguments
      * @param string $calls By reference
      * @param string $behavior By reference
      * @return void
@@ -891,17 +906,17 @@ EOF;
     /**
      * Returns the inline definition
      *
-     * @param Definition $definition 
+     * @param Definition $definition
      * @return string
      */
     protected function getInlinedDefinitions(Definition $definition)
     {
         if (false === $this->inlinedDefinitions->contains($definition)) {
-            $definitions = $this->getDefinitionsFromArguments($definition->getArguments());
-
-            foreach ($definition->getMethodCalls() as $arguments) {
-                $definitions = array_merge($definitions, $this->getDefinitionsFromArguments($arguments));
-            }
+            $definitions = array_merge(
+                $this->getDefinitionsFromArguments($definition->getArguments()),
+                $this->getDefinitionsFromArguments($definition->getMethodCalls()),
+                $this->getDefinitionsFromArguments($definition->getProperties())
+            );
 
             $this->inlinedDefinitions->offsetSet($definition, $definitions);
 
@@ -914,7 +929,7 @@ EOF;
     /**
      * Gets the definition from arguments
      *
-     * @param array $arguments 
+     * @param array $arguments
      * @return array
      */
     protected function getDefinitionsFromArguments(array $arguments)
@@ -938,8 +953,8 @@ EOF;
     /**
      * Checks if a service id has a reference
      *
-     * @param string $id 
-     * @param array $arguments 
+     * @param string $id
+     * @param array $arguments
      * @return boolean
      */
     protected function hasReference($id, array $arguments)
@@ -962,8 +977,8 @@ EOF;
     /**
      * Dumps values.
      *
-     * @param string $value 
-     * @param boolean $interpolate 
+     * @param string $value
+     * @param boolean $interpolate
      * @return string
      */
     protected function dumpValue($value, $interpolate = true)
@@ -1046,7 +1061,7 @@ EOF;
     /**
      * Dumps a parameter
      *
-     * @param string $name 
+     * @param string $name
      * @return string
      */
     public function dumpParameter($name)
@@ -1061,8 +1076,8 @@ EOF;
     /**
      * Gets a service call
      *
-     * @param string $id 
-     * @param Reference $reference 
+     * @param string $id
+     * @param Reference $reference
      * @return string
      */
     protected function getServiceCall($id, Reference $reference = null)

+ 17 - 16
src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php

@@ -79,8 +79,8 @@ class XmlFileLoader extends FileLoader
     /**
      * Parses parameters
      *
-     * @param SimpleXMLElement $xml 
-     * @param string $file 
+     * @param SimpleXMLElement $xml
+     * @param string $file
      * @return void
      */
     protected function parseParameters(SimpleXMLElement $xml, $file)
@@ -95,8 +95,8 @@ class XmlFileLoader extends FileLoader
     /**
      * Parses imports
      *
-     * @param SimpleXMLElement $xml 
-     * @param string $file 
+     * @param SimpleXMLElement $xml
+     * @param string $file
      * @return void
      */
     protected function parseImports(SimpleXMLElement $xml, $file)
@@ -114,8 +114,8 @@ class XmlFileLoader extends FileLoader
     /**
      * Parses interface injectors
      *
-     * @param SimpleXMLElement $xml 
-     * @param string $file 
+     * @param SimpleXMLElement $xml
+     * @param string $file
      * @return void
      */
     protected function parseInterfaceInjectors(SimpleXMLElement $xml, $file)
@@ -148,8 +148,8 @@ class XmlFileLoader extends FileLoader
     /**
      * Parses multiple definitions
      *
-     * @param SimpleXMLElement $xml 
-     * @param string $file 
+     * @param SimpleXMLElement $xml
+     * @param string $file
      * @return void
      */
     protected function parseDefinitions(SimpleXMLElement $xml, $file)
@@ -166,9 +166,9 @@ class XmlFileLoader extends FileLoader
     /**
      * Parses an individual Definition
      *
-     * @param string $id 
-     * @param SimpleXMLElement $service 
-     * @param string $file 
+     * @param string $id
+     * @param SimpleXMLElement $service
+     * @param string $file
      * @return void
      */
     protected function parseDefinition($id, $service, $file)
@@ -201,6 +201,7 @@ class XmlFileLoader extends FileLoader
         }
 
         $definition->setArguments($service->getArgumentsAsPhp('argument'));
+        $definition->setProperties($service->getArgumentsAsPhp('property'));
 
         if (isset($service->configurator)) {
             if (isset($service->configurator['function'])) {
@@ -260,8 +261,8 @@ class XmlFileLoader extends FileLoader
     /**
      * Processes anonymous services
      *
-     * @param SimpleXMLElement $xml 
-     * @param string $file 
+     * @param SimpleXMLElement $xml
+     * @param string $file
      * @return array An array of anonymous services
      */
     protected function processAnonymousServices(SimpleXMLElement $xml, $file)
@@ -314,8 +315,8 @@ class XmlFileLoader extends FileLoader
     /**
      * Validates an XML document.
      *
-     * @param DOMDocument $dom 
-     * @param string $file 
+     * @param DOMDocument $dom
+     * @param string $file
      */
     protected function validate(\DOMDocument $dom, $file)
     {
@@ -448,7 +449,7 @@ EOF
     /**
      * Loads from an extension.
      *
-     * @param SimpleXMLElement $xml 
+     * @param SimpleXMLElement $xml
      * @return void
      */
     protected function loadFromExtensions(SimpleXMLElement $xml)

+ 16 - 13
src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php

@@ -12,7 +12,6 @@
 namespace Symfony\Component\DependencyInjection\Loader;
 
 use Symfony\Component\DependencyInjection\DefinitionDecorator;
-
 use Symfony\Component\DependencyInjection\Alias;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\InterfaceInjector;
@@ -86,8 +85,8 @@ class YamlFileLoader extends FileLoader
     /**
      * Parses all imports
      *
-     * @param array $content 
-     * @param string $file 
+     * @param array $content
+     * @param string $file
      * @return void
      */
     protected function parseImports($content, $file)
@@ -105,8 +104,8 @@ class YamlFileLoader extends FileLoader
     /**
      * Parses interface injectors.
      *
-     * @param array $content 
-     * @param string $file 
+     * @param array $content
+     * @param string $file
      * @return void
      */
     protected function parseInterfaceInjectors($content, $file)
@@ -142,8 +141,8 @@ class YamlFileLoader extends FileLoader
     /**
      * Parses definitions
      *
-     * @param array $content 
-     * @param string $file 
+     * @param array $content
+     * @param string $file
      * @return void
      */
     protected function parseDefinitions($content, $file)
@@ -160,9 +159,9 @@ class YamlFileLoader extends FileLoader
     /**
      * Parses a definition.
      *
-     * @param string $id 
-     * @param array $service 
-     * @param string $file 
+     * @param string $id
+     * @param array $service
+     * @param string $file
      * @return void
      */
     protected function parseDefinition($id, $service, $file)
@@ -224,6 +223,10 @@ class YamlFileLoader extends FileLoader
             $definition->setArguments($this->resolveServices($service['arguments']));
         }
 
+        if (isset($service['properties'])) {
+            $definition->setProperties($this->resolveServices($service['properties']));
+        }
+
         if (isset($service['configurator'])) {
             if (is_string($service['configurator'])) {
                 $definition->setConfigurator($service['configurator']);
@@ -261,7 +264,7 @@ class YamlFileLoader extends FileLoader
     /**
      * Loads a YAML file.
      *
-     * @param string $file 
+     * @param string $file
      * @return array The file content
      */
     protected function loadFile($file)
@@ -304,7 +307,7 @@ class YamlFileLoader extends FileLoader
     /**
      * Resolves services.
      *
-     * @param string $value 
+     * @param string $value
      * @return void
      */
     protected function resolveServices($value)
@@ -336,7 +339,7 @@ class YamlFileLoader extends FileLoader
     /**
      * Loads from Extensions
      *
-     * @param array $content 
+     * @param array $content
      * @return void
      */
     protected function loadFromExtensions($content)

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

@@ -98,6 +98,7 @@
       <xsd:element name="configurator" type="configurator" minOccurs="0" maxOccurs="1" />
       <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
       <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
     </xsd:choice>
     <xsd:attribute name="id" type="xsd:string" />
     <xsd:attribute name="class" type="xsd:string" />
@@ -135,6 +136,14 @@
     <xsd:attribute name="on-invalid" type="invalid_sequence" />
   </xsd:complexType>
 
+  <xsd:complexType name="property" mixed="true">
+    <xsd:attribute name="type" type="argument_type" />
+    <xsd:attribute name="id" type="xsd:string" />
+    <xsd:attribute name="name" type="xsd:string" />
+    <xsd:attribute name="on-invalid" type="xsd:string" />
+    <xsd:attribute name="strict" type="boolean" />
+  </xsd:complexType>
+
   <xsd:complexType name="argument" mixed="true">
     <xsd:choice maxOccurs="unbounded">
       <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />

+ 6 - 3
src/Symfony/Component/DependencyInjection/SimpleXMLElement.php

@@ -21,7 +21,7 @@ class SimpleXMLElement extends \SimpleXMLElement
     /**
      * Converts an attribute as a php type.
      *
-     * @param string $name 
+     * @param string $name
      * @return mixed
      */
     public function getAttributeAsPhp($name)
@@ -32,13 +32,16 @@ class SimpleXMLElement extends \SimpleXMLElement
     /**
      * Returns arguments as valid php types.
      *
-     * @param string $name 
+     * @param string $name
      * @return mixed
      */
     public function getArgumentsAsPhp($name)
     {
         $arguments = array();
         foreach ($this->$name as $arg) {
+            if (isset($arg['name'])) {
+                $arg['key'] = (string) $arg['name'];
+            }
             $key = isset($arg['key']) ? (string) $arg['key'] : (!$arguments ? 0 : max(array_keys($arguments)) + 1);
 
             // parameter keys are case insensitive
@@ -89,7 +92,7 @@ class SimpleXMLElement extends \SimpleXMLElement
     /**
      * Converts an xml value to a php type.
      *
-     * @param mixed $value 
+     * @param mixed $value
      * @return mixed
      */
     static public function phpize($value)