Skip to content
This repository was archived by the owner on Nov 9, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Compiler/ClassConstructorFiller.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function autowireParams(ReflectionMethod $constructor, $serviceId, Defini
} else if ($parameter->isDefaultValueAvailable()) {
$allArguments[] = $parameter->getDefaultValue();
} else {
$allArguments[] = $this->parameterProcessor->getParameterValue($parameter, $classes, $serviceId);
$allArguments[] = $this->parameterProcessor->getParameterValue($constructor, $classes, $serviceId, $parameter);
}
}

Expand Down
101 changes: 86 additions & 15 deletions Compiler/ParameterProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,114 @@
namespace Kutny\AutowiringBundle\Compiler;

use ReflectionClass;
use ReflectionMethod;
use ReflectionParameter;
use Symfony\Component\DependencyInjection\Reference;

class ParameterProcessor
{

public function getParameterValue(ReflectionParameter $parameter, array $classes, $serviceId)
public function getParameterValue(ReflectionMethod $method, array $classes, $serviceId, ReflectionParameter $parameter)
{
$parameterClass = $parameter->getClass();
$value = null;
$resolved = false;

if ($parameterClass) {
// resolve by type hint
if (!$resolved && ($parameterClass = $parameter->getClass())) {
$value = $this->processParameterClass($parameterClass, $parameter, $classes);
} else {
if ($parameter->isDefaultValueAvailable()) {
$value = $parameter->getDefaultValue();
} else {
$message = 'Class ' . $parameter->getDeclaringClass()->getName() . ' (service: ' . $serviceId . '), parameter $' . $parameter->getName();
$resolved = true;
}

// resolve array by doc comment @param type
if (!$resolved && $parameter->isArray()) {
if ($docComment = $method->getDocComment()) {
$paramAnnotationExists = preg_match(
"/@param\\s+(?<type>[A-Za-z0-9_]+)\\[\\]\\s+\\\${$parameter->getName()}/",
$docComment,
$paramAnnotation
);

throw new CannotResolveParameterException($message);
if ($paramAnnotationExists) {
$uses = $this->extractUses($method->getDeclaringClass());
$parameterClass = $paramAnnotation["type"];
if ($parameterClass[0] !== "\\") {
if (isset($uses[$parameterClass])) {
$parameterClass = $uses[$parameterClass];
} else {
$parameterClass = $method->getDeclaringClass()->getNamespaceName() . "\\" . $parameterClass;
}
}

$parameterClass = trim($parameterClass, "\\");

$value = $this->processParameterClass(new ReflectionClass($parameterClass), $parameter, $classes, true);
$resolved = true;
}
}
}

// try default value
if (!$resolved && $parameter->isDefaultValueAvailable()) {
$value = $parameter->getDefaultValue();
$resolved = true;
}

// exception if not resolved
if (!$resolved) {
throw new CannotResolveParameterException(
'Class ' . $parameter->getDeclaringClass()->getName() .
' (service: ' . $serviceId . '), ' .
'parameter $' . $parameter->getName()
);
}

return $value;
}

private function processParameterClass(ReflectionClass $parameterClass, ReflectionParameter $parameter, $classes)
private function extractUses(ReflectionClass $class)
{
$fileContents = file_get_contents($class->getFileName());
$uses = array();

if (preg_match_all(
"/\\b[uU][sS][eE]\\s+((?<fqn>[A-Za-z0-9_\\\\]+)(?:\\s+[aA][sS]\\s+(?<alias>[A-Za-z0-9_\\\\]+))?)\\s*;/",
$fileContents, $matches)
) {
for ($i = 0, $l = count($matches["fqn"]); $i < $l; ++$i) {
list($fqn, $alias) = array($matches["fqn"][$i], $matches["alias"][$i]);

if (empty($alias)) {
$classPath = explode("\\", $fqn);
$alias = array_pop($classPath);
}

$uses[$alias] = $fqn;
}
}

return $uses;
}

private function processParameterClass(ReflectionClass $parameterClass, ReflectionParameter $parameter, $classes, $arrayOfServices = false)
{
$class = $parameterClass->getName();

if (isset($classes[$class])) {
if (count($classes[$class]) === 1) {
$value = new Reference($classes[$class][0]);
if ($arrayOfServices) {
$value = array_map(function ($serviceId) {
return new Reference($serviceId);
}, $classes[$class]);

} else {
$serviceNames = implode(', ', $classes[$class]);
$message = 'Multiple services of ' . $class . ' defined (' . $serviceNames . '), class used in ' . $parameter->getDeclaringClass()->getName();
if (count($classes[$class]) === 1) {
$value = new Reference($classes[$class][0]);

} else {
$serviceNames = implode(', ', $classes[$class]);
$message = 'Multiple services of ' . $class . ' defined (' . $serviceNames . '), class used in ' . $parameter->getDeclaringClass()->getName();

throw new MultipleServicesOfClassException($message);
throw new MultipleServicesOfClassException($message);
}
}
} else {
if ($parameter->isDefaultValueAvailable()) {
Expand Down