/**
  * {@inheritDoc}
  */
 public function extractResponse(ActionInterface $action, CallableInterface $callable)
 {
     $response = $action->getResponse();
     if (!$response) {
         return null;
     }
     if (!is_object($response) || !$response instanceof ObjectResponse) {
         throw new ResponseExtractorNotSupportException(sprintf('The response must be ObjectResponse for extract, but "%s" given.'));
     }
     $class = $response->getClass();
     if (substr($class, strlen($class) - 2) == '[]') {
         $type = 'collection';
         $class = substr($class, 0, strlen($class) - 2);
     } else {
         $type = 'object';
     }
     if (!$class) {
         return null;
     }
     if (!class_exists($class)) {
         throw new ResponseExtractException(sprintf('Can not extract response from class "%s" for callable "%s". Class not found.', $class, Reflection::getCalledMethod($callable->getReflection())));
     }
     // Get properties from object
     $properties = $this->getPropertiesForClass($action, $callable, $class);
     $responseProperties = [];
     foreach ($properties as $property) {
         $responseProperties[] = $this->extractResponseProperty($action, $callable, $property);
     }
     return new Response($type, $class, $responseProperties);
 }
 /**
  * {@inheritDoc}
  */
 public function convertParameter(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $method, $value, $group, array $attributes = [])
 {
     $converter = $this->getConverter($group);
     if (!$converter->isSupported($parameter, $method)) {
         throw new ConverterNotSupportedException(sprintf('The parameter converter "%s" not supported in function "%s".', $parameter->getName(), Reflection::getCalledMethod($method)));
     }
     $value = $converter->convert($parameter, $method, $value, $attributes);
     return $value;
 }
 /**
  * {@inheritDoc}
  */
 public function convert(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $method, $value, array $attributes = [])
 {
     foreach ($this->converters as $converter) {
         if (true === $converter->isSupported($parameter, $method)) {
             return $converter->convert($parameter, $method, $value, $attributes);
         }
     }
     throw new ConverterNotFoundException(sprintf('Not found parameter converter for argument "%s" in function "%s".', $parameter->getName(), Reflection::getCalledMethod($method)));
 }
 /**
  * {@inheritDoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $handlerRegistry = $this->getContainer()->get('api.handler_registry');
     $callableResolver = $this->getContainer()->get('api.callable_resolver');
     $projectDirectory = realpath($this->getContainer()->getParameter('kernel.root_dir') . '/..');
     $handlerKeys = $handlerRegistry->getHandlerKeys();
     if ($input->getArgument('handler')) {
         $handlerKeys = array_diff($handlerKeys, array_diff($handlerKeys, $input->getArgument('handler')));
     }
     if (!count($handlerKeys)) {
         $output->writeln('Not found handlers.');
         return 0;
     }
     foreach ($handlerKeys as $handlerKey) {
         $handler = $handlerRegistry->getHandler($handlerKey);
         $actions = $handler->getActions();
         /** @var \Symfony\Component\Console\Helper\Table $table */
         $table = $this->getHelper('table');
         $table->setHeaders(['Name', 'Callable', 'File / Line']);
         $rows = [];
         foreach ($actions as $action) {
             try {
                 $callable = $callableResolver->resolve($action);
             } catch (\Exception $e) {
                 $rows[] = [$action->getName(), '<error>Not supported</error>', ''];
                 continue;
             }
             $reflection = $callable->getReflection();
             $file = str_replace($projectDirectory, '', $reflection->getFileName());
             $callableName = Reflection::getCalledMethod($callable->getReflection(), false);
             $fileAndLine = sprintf('%s on lines %d:%d', ltrim($file, '/'), $reflection->getStartLine(), $reflection->getEndLine());
             $rows[] = [$action->getName(), $callableName, $fileAndLine];
         }
         $output->writeln(sprintf('Action list for handler <info>%s</info>:', $handlerKey));
         $table->setRows($rows);
         $table->render($output);
         $output->writeln([null, null]);
     }
     return 0;
 }
 /**
  * Resolve request parameter
  *
  * @param ActionInterface      $action
  * @param CallableInterface    $callable
  * @param array                $inputArguments
  * @param \ReflectionParameter $parameter
  *
  * @return object
  *
  * @throws \Exception
  */
 private function resolveRequest(ActionInterface $action, CallableInterface $callable, array $inputArguments, \ReflectionParameter $parameter)
 {
     $class = $parameter->getClass();
     if ($class->isInterface()) {
         throw new \RuntimeException(sprintf('Could not create instance via interface for parameter "%s" in method "%s". ' . 'You must set the class for type hinting.', $parameter->getName(), Reflection::getCalledMethod($callable->getReflection())));
     }
     if ($class->isAbstract()) {
         throw new \RuntimeException(sprintf('Could not create instance via abstract class for parameter "%s" in method "%s". ' . 'You must set the real class for type hinting.', $parameter->getName(), Reflection::getCalledMethod($callable->getReflection())));
     }
     /** @var RequestInterface $request */
     $request = $class->newInstance();
     // Map arguments
     $this->objectMapper->map($request, $inputArguments, $action->getRequestMappingGroup());
     // First step validation: Strict mode
     if ($this->validator && $action->isStrictValidation()) {
         $this->strictRequestValidate($request);
     }
     // Second step validation: Base validation
     if ($this->validator && $action->getValidationGroups()) {
         $violationList = $this->validator->validate($request, null, $action->getValidationGroups());
         if (count($violationList)) {
             throw ViolationListException::create($violationList);
         }
     }
     // Convert request properties
     if ($this->propertyConverter) {
         try {
             $this->propertyConverter->convertProperties($request, PropertyConverterManagerInterface::GROUP_DEFAULT);
         } catch (InvalidArgumentException $e) {
             $constraintViolation = new ConstraintViolation($e->getMessage(), null, [], null, $e->getName(), $e->getInvalidValue());
             $constraintViolationList = new ConstraintViolationList([$constraintViolation]);
             throw ViolationListException::create($constraintViolationList);
         } catch (ConverterNotFoundException $e) {
             if ($this->logger) {
                 $this->logger->warning(sprintf('Could not convert properties with message: %s.', rtrim($e->getMessage(), '.')));
             }
             // Nothing action
         }
     }
     return $request;
 }
 /**
  * Get converter annotation
  *
  * @param \ReflectionParameter $parameter
  * @param \ReflectionMethod    $method
  *
  * @return ORM
  *
  * @throws ORMAnnotationNotFoundException
  */
 private function getConverterAnnotation(\ReflectionParameter $parameter, \ReflectionMethod $method)
 {
     $annotations = $this->reader->getMethodAnnotations($method);
     foreach ($annotations as $annotation) {
         if ($annotation instanceof ORM) {
             // Check parameter name
             if ($annotation->name === $parameter->name) {
                 return $annotation;
             }
             // Check classes
             if ($class = $parameter->getClass()) {
                 if (is_a($class->getName(), $annotation->entityClass, true)) {
                     return $annotation;
                 }
             }
             if (!$annotation->name && !$annotation->entityClass) {
                 throw new \RuntimeException(sprintf('Invalid @ORM annotation. The name or entity class must be specified in method "%s".', Reflection::getCalledMethod($method)));
             }
         }
     }
     throw new ORMAnnotationNotFoundException(sprintf('Not found ORM annotation for parameter "%s" in method "%s".', $parameter->getName(), Reflection::getCalledMethod($method)));
 }
Пример #7
0
 /**
  * {@inheritDoc}
  */
 public function handle($method, array $parameters)
 {
     try {
         // Get action and callable
         $action = $this->actionManager->getAction($method);
         $callable = $this->callableResolver->resolve($action);
         // Resolve parameters
         $parameters = $this->parameterResolver->resolve($action, $callable, $parameters);
         // Dispatch "pre dispatch" event
         $event = new ActionDispatchEvent($action, $callable, $parameters);
         $this->eventDispatcher->dispatch(ApiEvents::ACTION_PRE_DISPATCH, $event);
         // Call to API method
         $response = $callable->apply($parameters);
         if (null === $response) {
             throw new \RuntimeException(sprintf('The callable "%s" should be return Response or any values. Can not be empty.', Reflection::getCalledMethod($callable->getReflection())));
         }
         if (!$response instanceof ResponseInterface) {
             // Try transform in listeners.
             $event = new ActionViewEvent($action, $callable, $parameters, $response);
             $this->eventDispatcher->dispatch(ApiEvents::ACTION_VIEW, $event);
             $response = $event->getResponse();
             if (!$response) {
                 throw new \RuntimeException(sprintf('Not found response after dispatch view event in API method "%s". ' . 'You must return response or transform response in view event. ' . 'Maybe not found transformer for object?', Reflection::getCalledMethod($callable->getReflection())));
             }
             if (!$response instanceof ResponseInterface) {
                 throw new \RuntimeException(sprintf('The response after dispatch view event must be a ResponseInterface instance, but "%s" given ' . 'for method "%s".', is_object($response) ? get_class($response) : gettype($response)));
             }
         }
         $event = new ActionDispatchEvent($action, $callable, $parameters, $response);
         $this->eventDispatcher->dispatch(ApiEvents::ACTION_POST_DISPATCH, $event);
         return $response;
     } catch (\Exception $e) {
         $event = new ActionExceptionEvent(isset($action) ? $action : null, $e);
         $this->eventDispatcher->dispatch(ApiEvents::ACTION_EXCEPTION, $event);
         if ($event->hasResponse()) {
             return $event->getResponse();
         }
         throw $e;
     }
 }
Пример #8
0
 /**
  * On pre dispatch event
  *
  * @param ActionDispatchEvent $event
  */
 public function onPreDispatch(ActionDispatchEvent $event)
 {
     $message = sprintf('Match callable "%s" for action "%s".', Reflection::getCalledMethod($event->getCallable()->getReflection()), $event->getAction()->getName());
     $this->logger->debug($message);
 }