* * This source file is subject to the MIT license that is bundled * with this source code in the file LICENSE. */ namespace Bundle\WebServiceBundle\ServiceDefinition\Loader; use Bundle\WebServiceBundle\ServiceDefinition\Argument; use Bundle\WebServiceBundle\ServiceDefinition\Method; use Bundle\WebServiceBundle\ServiceDefinition\Type; use Bundle\WebServiceBundle\ServiceDefinition\ServiceDefinition; use Bundle\WebServiceBundle\ServiceDefinition\Annotation\Method as MethodAnnotation; use Bundle\WebServiceBundle\ServiceDefinition\Annotation\Param as ParamAnnotation; use Bundle\WebServiceBundle\ServiceDefinition\Annotation\Result as ResultAnnotation; use Doctrine\Common\Annotations\Reader; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Loader\LoaderResolver; /** * AnnotationClassLoader loads ServiceDefinition from a PHP class and its methods. * * Based on \Symfony\Component\Routing\Loader\AnnotationClassLoader * * @author Christian Kerl */ class AnnotationClassLoader implements LoaderInterface { private $methodAnnotationClass = 'Bundle\\WebServiceBundle\\ServiceDefinition\\Annotation\\Method'; private $paramAnnotationClass = 'Bundle\\WebServiceBundle\\ServiceDefinition\\Annotation\\Param'; private $resultAnnotationClass = 'Bundle\\WebServiceBundle\\ServiceDefinition\\Annotation\\Result'; protected $reader; /** * Constructor. * * @param \Doctrine\Common\Annotations\Reader $reader */ public function __construct(Reader $reader) { $this->reader = $reader; } /** * Loads a ServiceDefinition from annotations from a class. * * @param string $class A class name * @param string $type The resource type * * @return ServiceDefinition A ServiceDefinition instance * * @throws \InvalidArgumentException When route can't be parsed */ public function load($class, $type = null) { if (!class_exists($class)) { throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); } $class = new \ReflectionClass($class); $definition = new ServiceDefinition(); foreach ($class->getMethods() as $method) { $serviceArguments = array(); $serviceMethod = $serviceReturn = null; foreach ($this->reader->getMethodAnnotations($method) as $i => $annotation) { if ($annotation instanceof ParamAnnotation) { $serviceArguments[] = new Argument( $annotation->getValue(), new Type($annotation->getPhpType(), $annotation->getXmlType()) ); } elseif ($annotation instanceof MethodAnnotation) { if ($serviceMethod) { throw new \LogicException(sprintf('@Method defined twice for "%s".', $method->getName())); } $serviceMethod = new Method( $annotation->getValue(), $this->getController($method, $annotation) ); } elseif ($annotation instanceof ResultAnnotation) { if ($serviceReturn) { throw new \LogicException(sprintf('@Result defined twice for "%s".', $method->getName())); } $serviceReturn = new Type($annotation->getPhpType(), $annotation->getXmlType()); } } if (!$serviceMethod && (!empty($serviceArguments) || $serviceReturn)) { throw new \LogicException(sprintf('@Method non-existent for "%s".', $method->getName())); } if ($serviceMethod) { $serviceMethod->setArguments($serviceArguments); if ($serviceReturn) { $serviceMethod->setReturn($serviceReturn); } $definition->getMethods()->add($serviceMethod); } } return $definition; } private function getController(\ReflectionMethod $method, MethodAnnotation $annotation) { if(null !== $annotation->getService()) { return $annotation->getService() . ':' . $method->name; } else { return $method->class . '::' . $method->name; } } /** * Returns true if this class supports the given resource. * * @param mixed $resource A resource * @param string $type The resource type * * @return Boolean True if this class supports the given resource, false otherwise */ public function supports($resource, $type = null) { return is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type); } /** * Sets the loader resolver. * * @param LoaderResolver $resolver A LoaderResolver instance */ public function setResolver(LoaderResolver $resolver) { } /** * Gets the loader resolver. * * @return LoaderResolver A LoaderResolver instance */ public function getResolver() { } }