| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 | 
							- <?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\DependencyInjection\Compiler;
 - 
 - use JMS\SecurityExtraBundle\Analysis\ServiceAnalyzer;
 - use JMS\SecurityExtraBundle\Metadata\ServiceMetadata;
 - use JMS\SecurityExtraBundle\Metadata\ClassMetadata;
 - use JMS\SecurityExtraBundle\Generator\ProxyClassGenerator;
 - use JMS\SecurityExtraBundle\Metadata\Driver\DriverChain;
 - use \ReflectionClass;
 - use \ReflectionMethod;
 - use Symfony\Component\Config\Resource\FileResource;
 - use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
 - use Symfony\Component\DependencyInjection\ContainerBuilder;
 - use Symfony\Component\DependencyInjection\Definition;
 - use Symfony\Component\DependencyInjection\Reference;
 - use Symfony\Component\Security\Core\SecurityContext;
 - 
 - /**
 -  * Modifies the container, and sets the proxy classes where needed
 -  *
 -  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 -  */
 - class SecureMethodInvocationsPass implements CompilerPassInterface
 - {
 -     private $cacheDir;
 -     private $generator;
 -     private $cacheMetadata;
 - 
 -     public function __construct($cacheDir)
 -     {
 -         $cacheDir .= '/security/';
 -         if (!file_exists($cacheDir)) {
 -             @mkdir($cacheDir, 0777, true);
 -         }
 -         if (false === is_writable($cacheDir)) {
 -             throw new \RuntimeException('Cannot write to cache folder: '.$cacheDir);
 -         }
 -         $this->cacheDir = $cacheDir;
 - 
 -         if (!file_exists($cacheDir.'SecurityProxies/')) {
 -             @mkdir($cacheDir.'SecurityProxies/', 0777, true);
 -         }
 -         if (false === is_writeable($cacheDir.'SecurityProxies/')) {
 -             throw new \RuntimeException('Cannot write to cache folder: '.$cacheDir.'SecurityProxies/');
 -         }
 - 
 -         $this->generator = new ProxyClassGenerator();
 -         $this->createOrLoadCacheMetadata();
 -     }
 - 
 -     /**
 -      * {@inheritDoc}
 -      */
 -     public function process(ContainerBuilder $container)
 -     {
 -         if (!$container->hasDefinition('security.access.method_interceptor')) {
 -             return;
 -         }
 - 
 -         $services = $container->findTaggedServiceIds('security.secure_service');
 -         $secureNotAll = !$container->getParameter('security.extra.secure_all_services');
 - 
 -         $parameterBag = $container->getParameterBag();
 -         foreach ($container->getDefinitions() as $id => $definition) {
 -             if ($secureNotAll && !isset($services[$id])) {
 -                 continue;
 -             }
 - 
 -             if ((null === $class = $definition->getClass()) || !class_exists($class)) {
 -                 if ($secureNotAll) {
 -                     throw new \RuntimeException(sprintf('Could not find class "%s" for "%s".', $class, $id));
 -                 }
 - 
 -                 continue;
 -             }
 - 
 -             if (null !== $definition->getFactoryMethod() || $definition->isAbstract() || $definition->isSynthetic()) {
 -                 if ($secureNotAll) {
 -                     throw new \RuntimeException(sprintf('You cannot secure service "%s", because it is either created by a factory, or an abstract/synthetic service.', $id));
 -                 }
 - 
 -                 continue;
 -             }
 - 
 -             $this->processDefinition($container, $id, $definition);
 -         }
 - 
 -         $this->writeCacheMetadata();
 -     }
 - 
 -     private function processDefinition(ContainerBuilder $container, $id, Definition $definition)
 -     {
 -         if ($this->needsReAssessment($id, $definition)) {
 -             $analyzer = new ServiceAnalyzer($definition->getClass(), $container->get('annotation_reader'));
 -             $analyzer->analyze();
 - 
 -             $files = array();
 -             foreach ($analyzer->getFiles() as $file) {
 -                 $container->addResource($file = new FileResource($file));
 -                 $files[] = $file;
 -             }
 - 
 -             $metadata = $analyzer->getMetadata();
 -             $proxyClass = $path = null;
 -             if (true === $metadata->isProxyRequired()) {
 -                 list($newClassName, $content) = $this->generator->generate($definition, $metadata);
 -                 file_put_contents($path = $this->cacheDir.'SecurityProxies/'.$newClassName.'.php', $content);
 -                 $definition->setFile($path);
 -                 $definition->setClass($proxyClass = 'SecurityProxies\\'.$newClassName);
 -                 $definition->addMethodCall('jmsSecurityExtraBundle__setMethodSecurityInterceptor', array(new Reference('security.access.method_interceptor')));
 -             } else if (isset($this->cacheMetadata[$id]['proxy_class'])) {
 -                 @unlink($this->cacheDir.$this->cacheMetadata[$id]['proxy_class'].'.php');
 -             }
 - 
 -             $this->cacheMetadata[$id] = array(
 -                 'class' => $definition->getClass(),
 -                 'proxy_class' => $proxyClass,
 -                 'proxy_file'  => $path,
 -             		'analyze_time' => time(),
 -                 'files' => $files,
 -             );
 -         } else {
 -             foreach ($this->cacheMetadata[$id]['files'] as $file) {
 -                 $container->addResource($file);
 -             }
 - 
 -             if (null !== $proxyClass = $this->cacheMetadata[$id]['proxy_class']) {
 -                 $definition->setFile($this->cacheMetadata[$id]['proxy_file']);
 -                 $definition->setClass($proxyClass);
 -                 $definition->addMethodCall('jmsSecurityExtraBundle__setMethodSecurityInterceptor', array(new Reference('security.access.method_interceptor')));
 -             }
 -         }
 -     }
 - 
 -     private function needsReAssessment($id, Definition $definition)
 -     {
 -         if (!isset($this->cacheMetadata[$id])) {
 -             return true;
 -         }
 - 
 -         $metadata = $this->cacheMetadata[$id];
 -         if ($metadata['class'] !== $definition->getClass()) {
 -             return true;
 -         }
 - 
 -         $lastAnalyzed = $metadata['analyze_time'];
 -         foreach ($metadata['files'] as $file) {
 -             if (false === $file->isFresh($lastAnalyzed)) {
 -                 return true;
 -             }
 -         }
 - 
 -         return false;
 -     }
 - 
 -     private function createOrLoadCacheMetadata()
 -     {
 -         if (file_exists($this->cacheDir.'cache.meta')) {
 -             if (!is_readable($this->cacheDir.'cache.meta')) {
 -                 throw new \RuntimeException('Cannot load security cache meta data from: '.$this->cacheDir.'cache.meta');
 -             }
 - 
 -             $this->cacheMetadata = unserialize(file_get_contents($this->cacheDir.'cache.meta'));
 -         } else {
 -             set_time_limit(0);
 -             $this->cacheMetadata = array();
 -         }
 -     }
 - 
 -     private function writeCacheMetadata()
 -     {
 -         if (false === file_put_contents($this->cacheDir.'cache.meta', serialize($this->cacheMetadata))) {
 -             throw new \RuntimeException('Could not write to cache file: '.$this->cacheDir.'cache.meta');
 -         }
 -     }
 - }
 
 
  |