/** * {@inheritdoc} */ public function getParameters(ReflectionFunctionAbstract $reflection, array $providedParameters, array $resolvedParameters) { // Skip parameters already resolved if (!empty($resolvedParameters)) { $providedParameters = array_diff_key($providedParameters, $resolvedParameters); } foreach ($providedParameters as $key => $value) { if (!$value instanceof DefinitionHelper) { continue; } $definition = $value->getDefinition(''); $value = $this->definitionResolver->resolve($definition); if (is_int($key)) { // Indexed by position $resolvedParameters[$key] = $value; } else { // Indexed by parameter name // TODO optimize? $reflectionParameters = $reflection->getParameters(); foreach ($reflectionParameters as $reflectionParameter) { if ($key === $reflectionParameter->name) { $resolvedParameters[$reflectionParameter->getPosition()] = $value; } } } } return $resolvedParameters; }
/** * @param MethodInjection $definition * @param \ReflectionFunctionAbstract $functionReflection * @param array $parameters * * @throws DefinitionException A parameter has no value defined or guessable. * @return array Parameters to use to call the function. */ public function resolveParameters(MethodInjection $definition = null, \ReflectionFunctionAbstract $functionReflection = null, array $parameters = []) { $args = []; if (!$functionReflection) { return $args; } $definitionParameters = $definition ? $definition->getParameters() : array(); foreach ($functionReflection->getParameters() as $index => $parameter) { if (array_key_exists($parameter->getName(), $parameters)) { // Look in the $parameters array $value =& $parameters[$parameter->getName()]; } elseif (array_key_exists($index, $definitionParameters)) { // Look in the definition $value =& $definitionParameters[$index]; } else { // If the parameter is optional and wasn't specified, we take its default value if ($parameter->isOptional()) { $args[] = $this->getParameterDefaultValue($parameter, $functionReflection); continue; } throw new DefinitionException(sprintf("The parameter '%s' of %s has no value defined or guessable", $parameter->getName(), $this->getFunctionName($functionReflection))); } if ($value instanceof DefinitionHelper) { $nestedDefinition = $value->getDefinition(''); // If the container cannot produce the entry, we can use the default parameter value if ($parameter->isOptional() && !$this->definitionResolver->isResolvable($nestedDefinition)) { $value = $this->getParameterDefaultValue($parameter, $functionReflection); } else { $value = $this->definitionResolver->resolve($nestedDefinition); } } $args[] =& $value; } return $args; }
private function resolveDefinition(DefinitionHelper $value, ArrayDefinition $definition, $key) { try { return $this->definitionResolver->resolve($value->getDefinition('')); } catch (DependencyException $e) { throw $e; } catch (Exception $e) { throw new DependencyException(sprintf('Error while resolving %s[%s]. %s', $definition->getName(), $key, $e->getMessage()), 0, $e); } }
/** * {@inheritdoc} */ public function getParameters(ReflectionFunctionAbstract $reflection, array $providedParameters, array $resolvedParameters) { foreach ($resolvedParameters as &$parameter) { if ($parameter instanceof DefinitionHelper) { $definition = $parameter->getDefinition(''); $parameter = $this->definitionResolver->resolve($definition); } } return $resolvedParameters; }
/** * Resolve an environment variable definition to a value. * * @param EnvironmentVariableDefinition $definition * * {@inheritdoc} */ public function resolve(Definition $definition, array $parameters = []) { $value = call_user_func($this->variableReader, $definition->getVariableName()); if (false !== $value) { return $value; } if (!$definition->isOptional()) { throw new DefinitionException(sprintf("The environment variable '%s' has not been defined", $definition->getVariableName())); } $value = $definition->getDefaultValue(); // Nested definition if ($value instanceof DefinitionHelper) { return $this->definitionResolver->resolve($value->getDefinition('')); } return $value; }
/** * Resolve a decorator definition to a value. * * This will call the callable of the definition and pass it the decorated entry. * * @param DecoratorDefinition $definition * * {@inheritdoc} */ public function resolve(Definition $definition, array $parameters = []) { $callable = $definition->getCallable(); if (!is_callable($callable)) { throw new DefinitionException(sprintf('The decorator "%s" is not callable', $definition->getName())); } $decoratedDefinition = $definition->getDecoratedDefinition(); if (!$decoratedDefinition instanceof Definition) { if (!$definition->getSubDefinitionName()) { throw new DefinitionException('Decorators cannot be nested in another definition'); } throw new DefinitionException(sprintf('Entry "%s" decorates nothing: no previous definition with the same name was found', $definition->getName())); } $decorated = $this->definitionResolver->resolve($decoratedDefinition); return call_user_func($callable, $decorated, $this->container); }
private function resolveExtraParams(array $params) { $resolved = []; foreach ($params as $key => $value) { if ($value instanceof DefinitionHelper) { // As per ObjectCreator::injectProperty, use '' for an anonymous sub-definition $value = $value->getDefinition(''); } if (!$value instanceof Definition) { $resolved[$key] = $value; } else { $resolved[$key] = $this->resolver->resolve($value); } } return $resolved; }
/** * Resolves a definition. * * Checks for circular dependencies while resolving the definition. * * @param Definition $definition * @param array $parameters * * @throws DependencyException Error while resolving the entry. * @return mixed */ private function resolveDefinition(Definition $definition, array $parameters = []) { $entryName = $definition->getName(); // Check if we are already getting this entry -> circular dependency if (isset($this->entriesBeingResolved[$entryName])) { throw new DependencyException("Circular dependency detected while trying to resolve entry '{$entryName}'"); } $this->entriesBeingResolved[$entryName] = true; // Resolve the definition try { $value = $this->definitionResolver->resolve($definition, $parameters); } catch (Exception $exception) { unset($this->entriesBeingResolved[$entryName]); throw $exception; } unset($this->entriesBeingResolved[$entryName]); return $value; }
/** * Inject dependencies into properties. * * @param object $object Object to inject dependencies into * @param PropertyInjection $propertyInjection Property injection definition * * @throws DependencyException * @throws DefinitionException */ private function injectProperty($object, PropertyInjection $propertyInjection) { $propertyName = $propertyInjection->getPropertyName(); $property = new ReflectionProperty(get_class($object), $propertyName); $value = $propertyInjection->getValue(); if ($value instanceof DefinitionHelper) { /** @var Definition $nestedDefinition */ $nestedDefinition = $value->getDefinition(''); try { $value = $this->definitionResolver->resolve($nestedDefinition); } catch (DependencyException $e) { throw $e; } catch (Exception $e) { throw new DependencyException(sprintf("Error while injecting in %s::%s. %s", get_class($object), $propertyName, $e->getMessage()), 0, $e); } } if (!$property->isPublic()) { $property->setAccessible(true); } $property->setValue($object, $value); }