private function getSecureMethodInvocation(MethodMetadata $method)
 {
     $code = 'new MethodInvocation(' . var_export($method->getReflection()->getDeclaringClass()->getName(), true) . ', ' . var_export($method->getReflection()->getName(), true) . ', $this' . ', array(';
     $arguments = array();
     foreach ($method->getReflection()->getParameters() as $param) {
         $arguments[] = '$' . $param->getName();
     }
     $code .= implode(', ', $arguments) . '))';
     return $code;
 }
 public function convertMethodAnnotations(\ReflectionMethod $method, array $annotations)
 {
     $parameters = array();
     foreach ($method->getParameters() as $index => $parameter) {
         $parameters[$parameter->getName()] = $index;
     }
     $methodMetadata = new MethodMetadata($method);
     foreach ($annotations as $annotation) {
         if ($annotation instanceof Secure) {
             $methodMetadata->setRoles($annotation->getRoles());
         } else {
             if ($annotation instanceof SecureParam) {
                 if (!isset($parameters[$annotation->getName()])) {
                     throw new \InvalidArgumentException(sprintf('The parameter "%s" does not exist for method "%s".', $annotation->getName(), $method->getName()));
                 }
                 $methodMetadata->addParamPermissions($parameters[$annotation->getName()], $annotation->getPermissions());
             } else {
                 if ($annotation instanceof SecureReturn) {
                     $methodMetadata->addReturnPermissions($annotation->getPermissions());
                 } else {
                     if ($annotation instanceof SatisfiesParentSecurityPolicy) {
                         $methodMetadata->setSatisfiesParentSecurityPolicy();
                     } else {
                         if ($annotation instanceof RunAs) {
                             $methodMetadata->setRunAsRoles($annotation->getRoles());
                         }
                     }
                 }
             }
         }
     }
     return $methodMetadata;
 }
 /**
  * @dataProvider getTestData
  */
 public function testGenerate($class, $method, array $arguments)
 {
     $generator = new ProxyClassGenerator();
     $metadata = new ServiceMetadata();
     $reflection = new \ReflectionClass($class);
     $methodMetadata = new MethodMetadata($reflection->getMethod($method));
     $methodMetadata->setRoles(array('ROLE_FOO'));
     $methodMetadata->setReturnPermissions(array('PERMISSION_RETURN'));
     $metadata->addMethod($method, $methodMetadata);
     $definition = new Definition();
     $definition->setClass($reflection->getName());
     list($className, $proxy) = $generator->generate($definition, $metadata);
     $tmpFile = tempnam(sys_get_temp_dir(), 'proxy');
     file_put_contents($tmpFile, $proxy);
     require_once $tmpFile;
     unlink($tmpFile);
     $className = 'SecurityProxies\\' . $className;
     $proxyClass = new $className();
     $mock = $this->getMockBuilder('JMS\\SecurityExtraBundle\\Security\\Authorization\\Interception\\MethodSecurityInterceptor')->disableOriginalConstructor()->getMock();
     $mock->expects($this->once())->method('invoke')->will($this->returnValue($return = new \stdClass()));
     $proxyClass->jmsSecurityExtraBundle__setMethodSecurityInterceptor($mock);
     $this->assertSame($return, call_user_func_array(array($proxyClass, $method), $arguments));
 }
 private function normalizeMetadata()
 {
     $secureMethods = array();
     foreach ($this->metadata->getClasses() as $class) {
         if ($class->getReflection()->isFinal()) {
             throw new \RuntimeException('Final classes cannot be secured.');
         }
         foreach ($class->getMethods() as $name => $method) {
             if ($method->getReflection()->isStatic() || $method->getReflection()->isFinal()) {
                 throw new \RuntimeException('Annotations cannot be defined on final, or static methods.');
             }
             if (!isset($secureMethods[$name])) {
                 $this->metadata->addMethod($name, $method);
                 $secureMethods[$name] = $method;
             } else {
                 if ($method->getReflection()->isAbstract()) {
                     $secureMethods[$name]->merge($method);
                 } else {
                     if (false === $secureMethods[$name]->satisfiesParentSecurityPolicy() && $method->getReflection()->getDeclaringClass()->getName() !== $secureMethods[$name]->getReflection()->getDeclaringClass()->getName()) {
                         throw new \RuntimeException(sprintf('Unresolved security metadata conflict for method "%s::%s" in "%s". Please copy the respective annotations, and add @SatisfiesParentSecurityPolicy to the child method.', $secureMethods[$name]->getReflection()->getDeclaringClass()->getName(), $name, $secureMethods[$name]->getReflection()->getDeclaringClass()->getFileName()));
                     }
                 }
             }
         }
     }
     foreach ($secureMethods as $name => $method) {
         if ($method->getReflection()->isAbstract()) {
             $previous = null;
             $abstractClass = $method->getReflection()->getDeclaringClass()->getName();
             foreach ($this->hierarchy as $refClass) {
                 if ($abstractClass === ($fqcn = $refClass->getName())) {
                     $methodMetadata = new MethodMetadata($previous->getMethod($name));
                     $methodMetadata->merge($method);
                     $this->metadata->addMethod($name, $methodMetadata);
                     continue 2;
                 }
                 if (!$refClass->isInterface() && $this->hasMethod($refClass, $name)) {
                     $previous = $refClass;
                 }
             }
         }
     }
 }