diff -r 000000000000 -r 7f95f8617b0b vendor/bundles/JMS/SecurityExtraBundle/Generator/ProxyClassGenerator.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/bundles/JMS/SecurityExtraBundle/Generator/ProxyClassGenerator.php Sat Sep 24 15:40:41 2011 +0200 @@ -0,0 +1,211 @@ + + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace JMS\SecurityExtraBundle\Generator; + +use JMS\SecurityExtraBundle\Metadata\MethodMetadata; +use JMS\SecurityExtraBundle\Metadata\ServiceMetadata; +use Symfony\Component\DependencyInjection\Definition; +use \ReflectionClass; +use \ReflectionMethod; + +/** + * Generates the proxy class which has security checks built-in according to + * the given metadata information. + * + * @author Johannes M. Schmitt + * + */ +class ProxyClassGenerator +{ + private $classCount = array(); + + /** + * Generates the proxy class + * + * @param Definition $definition + * @param ServiceMetadata $metadata + * @return array + */ + public function generate(Definition $definition, ServiceMetadata $metadata) + { + list($className, $proxy) = $this->getClassDefinition($definition); + foreach ($metadata->methodMetadata as $name => $method) { + $reflection = $method->reflection; + + $proxy .= $this->getMethodDefinition($reflection); + + $proxy .= ' static $jmsSecurityExtra__metadata = '.$this->getMethodSecurityMetadata($method).'; + + '; + + $proxy .= ' return '; + + $proxy .= '$this->jmsSecurityExtraBundle__methodSecurityInterceptor->invoke( + '; + $proxy .= ' '.$this->getSecureMethodInvocation($method).', + '; + $proxy .= ' $jmsSecurityExtra__metadata + '; + $proxy .= ' );'; + + $proxy .= ' + } + + '; + } + + return array($className, substr($proxy, 0, -6).'}'); + } + + private function getMethodSecurityMetadata(MethodMetadata $method) + { + $metadata = var_export($method->getAsArray(), true); + + $staticReplaces = array( + "\n" => '', + 'array (' => 'array(', + ); + $metadata = strtr($metadata, $staticReplaces); + + $regexReplaces = array( + '/\s+/' => ' ', + '/\(\s+/' => '(', + '/[0-9]+\s+=>\s+/' => '', + '/,\s*\)/' => ')', + ); + $metadata = preg_replace(array_keys($regexReplaces), array_values($regexReplaces), $metadata); + + return $metadata; + } + + private function getSecureMethodInvocation(MethodMetadata $method) + { + $code = 'new MethodInvocation(' + .var_export($method->reflection->getDeclaringClass()->getName(), true) + .', '.var_export($method->reflection->getName(), true) + .', $this' + .', array('; + + $arguments = array(); + foreach ($method->reflection->getParameters() as $param) { + $arguments[] = '$'.$param->getName(); + } + $code .= implode(', ', $arguments).'))'; + + return $code; + } + + private function getClassDefinition(Definition $definition) + { + $baseClass = $definition->getClass(); + if (false !== $pos = strrpos($baseClass, '\\')) { + $className = substr($baseClass, $pos + 1); + } else { + $className = $baseClass; + } + + if (isset($this->classCount[$className])) { + $className .= '_'.(++$this->classCount[$className]); + } else { + $this->classCount[$className] = 1; + } + + $requiredFiles = ''; + if (null !== $file = $definition->getFile()) { + $requiredFiles .= sprintf("\nrequire_once %s;", var_export($definition->getFile(), true)); + } + if ('' !== $requiredFiles) { + $requiredFiles .= "\n"; + } + + return array($className, sprintf(' + */ +class %s extends \%s +{ + private $jmsSecurityExtraBundle__methodSecurityInterceptor; + + public function jmsSecurityExtraBundle__setMethodSecurityInterceptor(MethodSecurityInterceptor $interceptor) + { + $this->jmsSecurityExtraBundle__methodSecurityInterceptor = $interceptor; + } + + ', $requiredFiles, $className, $baseClass)); + } + + private function getMethodDefinition(ReflectionMethod $method) + { + $def = ''; + if ($method->isProtected()) { + $def .= 'protected '; + } else { + $def .= 'public '; + } + + if ($method->isStatic()) { + $def .= 'static '; + } + + if ($method->returnsReference()) { + $def .= '&'; + } + + $def .= 'function '.$method->getName().'('; + $parameters = $method->getParameters(); + foreach ($parameters as $param) { + if (null !== $class = $param->getClass()) { + $def .= '\\'.$class->getName().' '; + } else if ($param->isArray()) { + $def .= 'array '; + } + + if ($param->isPassedByReference()) { + $def .= '&'; + } + + $def .= '$'.$param->getName(); + + if ($param->isOptional()) { + $def .= ' = '.var_export($param->getDefaultValue(), true); + } + + $def .= ', '; + } + + if (count($parameters) > 0) { + $def = substr($def, 0, -2); + } + + $def .= ') + { + '; + + return $def; + } +} \ No newline at end of file