vendor/bundles/JMS/SecurityExtraBundle/Generator/ProxyClassGenerator.php
changeset 0 7f95f8617b0b
--- /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 @@
+<?php
+
+/*
+ * Copyright 2010 Johannes M. Schmitt <schmittjoh@gmail.com>
+ *
+ * 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 <schmittjoh@gmail.com>
+ *
+ */
+class ProxyClassGenerator
+{
+    private $classCount = array();
+
+    /**
+     * Generates the proxy class
+     *
+     * @param Definition $definition
+     * @param ServiceMetadata $metadata
+     * @return array<string, string>
+     */
+    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('<?php
+
+namespace SecurityProxies;
+
+use JMS\SecurityExtraBundle\Security\Authorization\Interception\MethodInvocation;
+use JMS\SecurityExtraBundle\Security\Authorization\Interception\MethodSecurityInterceptor;
+%s
+/**
+ * This class has been auto-generated. Manual changes will be lost.
+ * Last updated at '.date('r').'
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+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