/**
  * @param ReflectionClass $reflectionClass
  * @param string $docComment
  * @param string $parameterName
  * @param ReflectionClass $parameterReflectionClass
  * @param mixed $defaultValueAvailable
  * @param mixed $defaultValue
  * @param $preferredServices
  * @return mixed
  */
 private function getValue(ReflectionClass $reflectionClass, $docComment, $parameterName, ReflectionClass $parameterReflectionClass = null, $defaultValueAvailable, $defaultValue, $preferredServices)
 {
     $className = null;
     $isArray = false;
     // resolve class name, whether value is array
     if ($parameterName !== null) {
         // parse parameter class
         if ($parameterReflectionClass) {
             $className = $parameterReflectionClass->getName();
         } elseif (preg_match("/@param\\s+([a-zA-Z0-9\\\\_]+)(\\[\\])?(\\|[^\\s]+)*\\s+\\\$" . preg_quote($parameterName) . "/", $docComment, $m)) {
             $className = $m[1];
             $isArray = isset($m[2]) && $m[2] === "[]";
         } elseif (!$defaultValueAvailable) {
             throw new AutowiringException("Could not parse parameter type - neither type hint, nor @param annotation available.");
         }
     } else {
         // parse property class
         if (preg_match("/@var\\s+([a-zA-Z0-9\\\\_]+)(\\[\\])?/", $docComment, $m)) {
             $className = $m[1];
             $isArray = isset($m[2]) && $m[2] === "[]";
         } elseif (!$defaultValueAvailable) {
             throw new AutowiringException("Could not parse property type - no @var annotation.");
         }
     }
     // resolve class name to FQN
     $lowerClassName = trim(strtolower($className), "\\ \t\n");
     $useStatements = $this->getUseStatements($reflectionClass);
     if (isset($useStatements[$lowerClassName])) {
         $className = $useStatements[$lowerClassName];
     } elseif (strpos($className, "\\") === false) {
         $className = $reflectionClass->getNamespaceName() . "\\" . $className;
     }
     $className = trim($className, "\\");
     // autowire from class map
     if ($isArray) {
         return array_map(function ($serviceId) {
             return new Reference($serviceId);
         }, $this->classMap->getMulti($className));
     } elseif ($className !== null) {
         try {
             return new Reference($this->classMap->getSingle($className));
         } catch (NoValueException $exception) {
             if ($defaultValueAvailable) {
                 return $defaultValue;
             } else {
                 throw new AutowiringException(sprintf("Missing service of type '%s'.", $className));
             }
         } catch (MultipleValuesException $exception) {
             if (isset($preferredServices[$className])) {
                 return new Reference($preferredServices[$className]);
             } else {
                 throw new AutowiringException(sprintf("Multiple services of type '%s'.", $className));
             }
         }
     } elseif ($defaultValueAvailable) {
         return $defaultValue;
     } else {
         throw new AutowiringException("Could not autowire.");
     }
 }
 public function process(ContainerBuilder $container)
 {
     $parameterBag = $container->getParameterBag();
     try {
         $autoscanPsr4 = (array) $parameterBag->resolveValue("%autowiring.autoscan_psr4%");
     } catch (ParameterNotFoundException $e) {
         $autoscanPsr4 = [];
     }
     try {
         $fastAnnotationChecksRegex = implode("|", array_map(function ($s) {
             return preg_quote($s);
         }, (array) $parameterBag->resolveValue("%autowiring.fast_annotation_checks%")));
     } catch (ParameterNotFoundException $e) {
         $fastAnnotationChecksRegex = null;
     }
     $env = $parameterBag->resolveValue("%kernel.environment%");
     // TODO: better error state handling
     if (empty($autoscanPsr4) || empty($fastAnnotationChecksRegex)) {
         return;
     }
     // TODO: more find methods than grep
     $grep = "egrep -lir " . escapeshellarg($fastAnnotationChecksRegex);
     foreach ($autoscanPsr4 as $ns => $dir) {
         if (!is_dir($dir)) {
             throw new AutowiringException(sprintf("Autoscan directory '%s' does not exits.", $dir));
         }
         $autoscanPsr4[$ns] = $dir = realpath($dir);
         $grep .= " " . escapeshellarg($dir);
     }
     if (($files = shell_exec($grep)) === null) {
         throw new AutowiringException("Autoscan grep failed.");
     }
     $classNames = [];
     foreach (explode("\n", trim($files)) as $file) {
         if (substr($file, -4) !== ".php") {
             continue;
         }
         foreach ($autoscanPsr4 as $ns => $dir) {
             if (strncmp($file, $dir, strlen($dir)) === 0) {
                 $fileWithoutDir = substr($file, strlen($dir), strlen($file) - strlen($dir) - 4);
                 $className = $ns . str_replace("/", "\\", $fileWithoutDir);
                 $classNames[$className] = $file;
                 break;
             }
         }
     }
     foreach ($classNames as $className => $file) {
         $serviceIds = $this->classMap->getMulti($className);
         if (!empty($serviceIds)) {
             continue;
         }
         try {
             $rc = new \ReflectionClass($className);
         } catch (\ReflectionException $e) {
             throw new AutowiringException(sprintf("File '%s' does not contain class '%s', or class is not autoload-able. " . "Check 'autowiring.autoscan_psr4' configuration if you specified the path correctly.", $file, $className));
         }
         $annotations = $this->annotationReader->getClassAnnotations($rc);
         foreach ($annotations as $annotation) {
             if ($annotation instanceof Component && ($annotation->env === $env || $annotation->env === null)) {
                 $serviceId = $annotation->name;
                 if ($serviceId === null) {
                     $annotationClassName = get_class($annotation);
                     $annotationSimpleName = substr($annotationClassName, strrpos($annotationClassName, "\\") + 1);
                     $classNameParts = explode("\\", $className);
                     $classSimpleName = array_pop($classNameParts);
                     $annotationLen = strlen($annotationSimpleName);
                     if (substr($classSimpleName, -$annotationLen) === $annotationSimpleName) {
                         $classSimpleName = substr($classSimpleName, 0, strlen($classSimpleName) - $annotationLen);
                     }
                     $middle = ".";
                     do {
                         $serviceId = lcfirst($annotationSimpleName) . $middle . lcfirst($classSimpleName);
                         do {
                             $part = array_pop($classNameParts);
                         } while ($part === $annotationSimpleName && !empty($classNameParts));
                         $middle = "." . lcfirst($part) . $middle;
                     } while ($container->hasDefinition($serviceId) && !empty($classNameParts));
                 }
                 if ($container->hasDefinition($serviceId)) {
                     throw new AutowiringException(sprintf("Class '%s' cannot be added as service '%s', service ID already exists.", $className, $serviceId));
                 }
                 $container->setDefinition($serviceId, new Definition($className));
             }
         }
     }
 }
Ejemplo n.º 3
0
 public function testGetMultiForClassAddedTwice()
 {
     $this->classMultiMap->put(self::SOME_CLASS_NAME, "someValue");
     $this->classMultiMap->put(self::SOME_CLASS_NAME, "someOtherValue");
     $this->assertSame(["someValue", "someOtherValue"], $this->classMultiMap->getMulti(self::SOME_CLASS_NAME));
 }