123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- <?php
-
- namespace JMS\SecurityExtraBundle\Metadata\Driver;
-
- use JMS\SecurityExtraBundle\Security\Authorization\Expression\Expression;
- use JMS\SecurityExtraBundle\Metadata\MethodMetadata;
- use JMS\SecurityExtraBundle\Metadata\ClassMetadata;
- use Metadata\Driver\DriverInterface;
-
- /**
- * Uses Symfony2 DI configuration for metadata.
- *
- * @author Johannes M. Schmitt <schmittjoh@gmail.com>
- */
- class ConfigDriver implements DriverInterface
- {
- private $bundles;
- private $config;
-
- public function __construct(array $bundles, array $config)
- {
- uasort($bundles, function($a, $b) {
- return strlen($b) - strlen($a);
- });
-
- foreach ($bundles as $name => $namespace) {
- $bundles[$name] = substr($namespace, 0, strrpos($namespace, '\\'));
- }
-
- $this->bundles = $bundles;
- $this->config = $config;
- }
-
- public function loadMetadataForClass(\ReflectionClass $class)
- {
- $metadata = new ClassMetadata($class->name);
-
- foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
- if ($method->getDeclaringClass()->name !== $class->name) {
- continue;
- }
-
- $expression = null;
- if (null !== $notation = $this->getControllerNotation($method)) {
- $expression = $this->getExpressionForSignature($notation);
- }
-
- if (null === $expression && null === $expression =
- $this->getExpressionForSignature($method->class.'::'.$method->name)) {
- continue;
- }
-
- $methodMetadata = new MethodMetadata($method->class, $method->name);
- $methodMetadata->roles = array(new Expression($expression));
- $metadata->addMethodMetadata($methodMetadata);
- }
-
- if (!$metadata->methodMetadata) {
- return null;
- }
-
- return $metadata;
- }
-
- private function getExpressionForSignature($signature)
- {
- foreach ($this->config as $pattern => $expr) {
- if (!preg_match('#'.$pattern.'#i', $signature)) {
- continue;
- }
-
- return $expr;
- }
-
- return null;
- }
-
- // TODO: Is it feasible to reverse-engineer the notation for service controllers?
- private function getControllerNotation(\ReflectionMethod $method)
- {
- $signature = $method->class.'::'.$method->name;
-
- // check if class is a controller
- if (0 === preg_match('#\\\\Controller\\\\([^\\\\]+)Controller::(.+)Action$#', $signature, $match)) {
- return null;
- }
-
- foreach ($this->bundles as $name => $namespace) {
- if (0 !== strpos($method->class, $namespace)) {
- continue;
- }
-
- // controller notation (AcmeBundle:Foo:foo)
- return $name.':'.$match[1].':'.$match[2];
- }
-
- return null;
- }
- }
|