/**
  * @param string $methodName
  * @param array  $arguments
  *
  * @return mixed
  *
  * @throws MethodNotFoundException
  */
 public function dispatch($methodName, array $arguments = [])
 {
     $methodCollection = $this->getMethodCollection();
     $callable = $methodCollection->get($methodName);
     if (!is_callable($callable)) {
         throw new MethodNotFoundException(sprintf('Method "%s" is not found', $methodName));
     }
     $requestObject = $this->argumentMapper->mapToObject($callable, $arguments);
     return $this->methodInvoker->invoke($callable, $requestObject);
 }
 /**
  * {@inheritdoc}
  */
 public function invoke(callable $callable, $requestObject)
 {
     /** @var Attribute $attributeAnnotation */
     $attributeAnnotation = $this->annotationReader->getMethodAnnotation(ReflectionFunctionFactory::createReflectionMethodFromCallable($callable), Attribute::class);
     $attributeName = $attributeAnnotation->name;
     $attributeValue = $this->propertyAccessor->getValue($requestObject, $attributeAnnotation->valueAt);
     $userId = $this->userProvider->getUserId();
     if (!is_array($attributeValue) && !$this->guard->isGranted($userId, $attributeName, $attributeValue)) {
         throw new AccessDeniedException();
     }
     if (is_array($attributeValue)) {
         $attributeValue = $this->guard->filterGranted($userId, $attributeName, $attributeValue);
         $this->propertyAccessor->setValue($requestObject, $attributeAnnotation->valueAt, $attributeValue);
     }
     return $this->methodInvoker->invoke($callable, $requestObject);
 }
 public function it_should_invoke_specified_method(LoaderInterface $loader, ArgumentMapperInterface $argumentMapper, MethodInvokerInterface $methodInvoker, SampleService $sampleService)
 {
     $loader->load()->willReturn(new MethodCollection(['sampleMethod' => [$sampleService->getWrappedObject(), 'sampleMethod']]));
     $argumentMapper->mapToObject([$sampleService, 'sampleMethod'], [1, 2, 3])->willReturn([1, 2, 3])->shouldBeCalled();
     $methodInvoker->invoke([$sampleService->getWrappedObject(), 'sampleMethod'], [1, 2, 3])->willReturn(6)->shouldBeCalled();
     $this->dispatch('sampleMethod', [1, 2, 3])->shouldBe(6);
 }
 public function it_should_not_invoke_method_if_guard_denies(MethodInvokerInterface $methodInvoker, UserProviderInterface $userProvider, GuardInterface $guard, Reader $annotationReader, PropertyAccessor $propertyAccessor)
 {
     $securedService = new SecuredAreaApi();
     $requestObject = new \stdClass();
     $requestObject->prop1 = 'asd';
     $responseObject = new \stdClass();
     $responseObject->prop2 = 'asd';
     $attributeAnnotation = new Attribute();
     $attributeAnnotation->name = 'test';
     $attributeAnnotation->valueAt = 'test';
     $annotationReader->getMethodAnnotation(new \ReflectionMethod($securedService, 'securedMethod'), Attribute::class)->willReturn($attributeAnnotation)->shouldBeCalled();
     $propertyAccessor->getValue($requestObject, 'test')->willReturn('sec-attr-val')->shouldBeCalled();
     $userProvider->getUserId()->willReturn(12)->shouldBeCalled();
     $guard->isGranted(12, 'test', 'sec-attr-val')->willReturn(false)->shouldBeCalled();
     $methodInvoker->invoke([$securedService, 'securedMethod'], $requestObject)->willReturn($responseObject)->shouldNotBeCalled();
     $this->shouldThrow(AccessDeniedException::class)->duringInvoke([$securedService, 'securedMethod'], $requestObject);
 }