diff --git a/src/Symfony/Component/Security/Acl/Domain/ObjectIdentity.php b/src/Symfony/Component/Security/Acl/Domain/ObjectIdentity.php index 2bd152a606..e37e82b0e1 100644 --- a/src/Symfony/Component/Security/Acl/Domain/ObjectIdentity.php +++ b/src/Symfony/Component/Security/Acl/Domain/ObjectIdentity.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Security\Acl\Domain; +use Symfony\Component\Security\Core\Util\ClassUtils; use Symfony\Component\Security\Acl\Exception\InvalidDomainObjectException; use Symfony\Component\Security\Acl\Model\DomainObjectInterface; use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface; @@ -59,9 +60,9 @@ final class ObjectIdentity implements ObjectIdentityInterface try { if ($domainObject instanceof DomainObjectInterface) { - return new self($domainObject->getObjectIdentifier(), get_class($domainObject)); + return new self($domainObject->getObjectIdentifier(), ClassUtils::getRealClass($domainObject)); } elseif (method_exists($domainObject, 'getId')) { - return new self($domainObject->getId(), get_class($domainObject)); + return new self($domainObject->getId(), ClassUtils::getRealClass($domainObject)); } } catch (\InvalidArgumentException $invalid) { throw new InvalidDomainObjectException($invalid->getMessage(), 0, $invalid); diff --git a/src/Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.php b/src/Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.php index df2be3850e..6bc1ba18b4 100644 --- a/src/Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.php +++ b/src/Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.php @@ -13,6 +13,7 @@ namespace Symfony\Component\Security\Acl\Domain; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Core\Util\ClassUtils; use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface; /** @@ -52,7 +53,7 @@ final class UserSecurityIdentity implements SecurityIdentityInterface */ static public function fromAccount(UserInterface $user) { - return new self($user->getUsername(), get_class($user)); + return new self($user->getUsername(), ClassUtils::getRealClass($user)); } /** @@ -69,7 +70,7 @@ final class UserSecurityIdentity implements SecurityIdentityInterface return self::fromAccount($user); } - return new self((string) $user, is_object($user)? get_class($user) : get_class($token)); + return new self((string) $user, is_object($user) ? ClassUtils::getRealClass($user) : ClassUtils::getRealClass($token)); } /** diff --git a/src/Symfony/Component/Security/Core/Util/ClassUtils.php b/src/Symfony/Component/Security/Core/Util/ClassUtils.php new file mode 100644 index 0000000000..7b583a328c --- /dev/null +++ b/src/Symfony/Component/Security/Core/Util/ClassUtils.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Util; + +/** + * Class related functionality for objects that + * might or might not be proxy objects at the moment. + * + * @see Doctrine\Common\Util\ClassUtils + * + * @author Benjamin Eberlei + * @author Johannes Schmitt + */ +class ClassUtils +{ + /** + * Marker for Proxy class names. + * + * @var string + */ + const MARKER = '__CG__'; + + /** + * Length of the proxy marker + * + * @var int + */ + const MARKER_LENGTH = 6; + + /** + * Gets the real class name of a class name that could be a proxy. + * + * @param string|object + * @return string + */ + public static function getRealClass($object) + { + $class = is_object($object) ? get_class($object) : $object; + + if (false === $pos = strrpos($class, '\\'.self::MARKER.'\\')) { + return $class; + } + + return substr($class, $pos + self::MARKER_LENGTH + 2); + } +} diff --git a/src/Symfony/Component/Security/Tests/Acl/Domain/ObjectIdentityTest.php b/src/Symfony/Component/Security/Tests/Acl/Domain/ObjectIdentityTest.php index 20dbedfdf5..20c74d5eeb 100644 --- a/src/Symfony/Component/Security/Tests/Acl/Domain/ObjectIdentityTest.php +++ b/src/Symfony/Component/Security/Tests/Acl/Domain/ObjectIdentityTest.php @@ -9,83 +9,108 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Security\Tests\Acl\Domain; - -use Symfony\Component\Security\Acl\Domain\ObjectIdentity; - -class ObjectIdentityTest extends \PHPUnit_Framework_TestCase +namespace Symfony\Component\Security\Tests\Acl\Domain { - public function testConstructor() + use Symfony\Component\Security\Acl\Domain\ObjectIdentity; + + class ObjectIdentityTest extends \PHPUnit_Framework_TestCase { - $id = new ObjectIdentity('fooid', 'footype'); + public function testConstructor() + { + $id = new ObjectIdentity('fooid', 'footype'); + + $this->assertEquals('fooid', $id->getIdentifier()); + $this->assertEquals('footype', $id->getType()); + } - $this->assertEquals('fooid', $id->getIdentifier()); - $this->assertEquals('footype', $id->getType()); - } + // Test that constructor never changes passed type, even with proxies + public function testConstructorWithProxy() + { + $id = new ObjectIdentity('fooid', 'Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject'); - public function testFromDomainObjectPrefersInterfaceOverGetId() - { - $domainObject = $this->getMock('Symfony\Component\Security\Acl\Model\DomainObjectInterface'); - $domainObject - ->expects($this->once()) - ->method('getObjectIdentifier') - ->will($this->returnValue('getObjectIdentifier()')) - ; - $domainObject - ->expects($this->never()) - ->method('getId') - ->will($this->returnValue('getId()')) - ; + $this->assertEquals('fooid', $id->getIdentifier()); + $this->assertEquals('Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject', $id->getType()); + } + + public function testFromDomainObjectPrefersInterfaceOverGetId() + { + $domainObject = $this->getMock('Symfony\Component\Security\Acl\Model\DomainObjectInterface'); + $domainObject + ->expects($this->once()) + ->method('getObjectIdentifier') + ->will($this->returnValue('getObjectIdentifier()')) + ; + $domainObject + ->expects($this->never()) + ->method('getId') + ->will($this->returnValue('getId()')) + ; + + $id = ObjectIdentity::fromDomainObject($domainObject); + $this->assertEquals('getObjectIdentifier()', $id->getIdentifier()); + } + + public function testFromDomainObjectWithoutInterface() + { + $id = ObjectIdentity::fromDomainObject(new TestDomainObject()); + $this->assertEquals('getId()', $id->getIdentifier()); + $this->assertEquals('Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject', $id->getType()); + } - $id = ObjectIdentity::fromDomainObject($domainObject); - $this->assertEquals('getObjectIdentifier()', $id->getIdentifier()); - } - - public function testFromDomainObjectWithoutInterface() - { - $id = ObjectIdentity::fromDomainObject(new TestDomainObject()); - $this->assertEquals('getId()', $id->getIdentifier()); - } - - /** - * @dataProvider getCompareData - */ - public function testEquals($oid1, $oid2, $equal) - { - if ($equal) { - $this->assertTrue($oid1->equals($oid2)); - } else { - $this->assertFalse($oid1->equals($oid2)); + public function testFromDomainObjectWithProxy() + { + $id = ObjectIdentity::fromDomainObject(new \Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject()); + $this->assertEquals('getId()', $id->getIdentifier()); + $this->assertEquals('Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject', $id->getType()); + } + + /** + * @dataProvider getCompareData + */ + public function testEquals($oid1, $oid2, $equal) + { + if ($equal) { + $this->assertTrue($oid1->equals($oid2)); + } else { + $this->assertFalse($oid1->equals($oid2)); + } + } + + public function getCompareData() + { + return array( + array(new ObjectIdentity('123', 'foo'), new ObjectIdentity('123', 'foo'), true), + array(new ObjectIdentity('123', 'foo'), new ObjectIdentity(123, 'foo'), true), + array(new ObjectIdentity('1', 'foo'), new ObjectIdentity('2', 'foo'), false), + array(new ObjectIdentity('1', 'bla'), new ObjectIdentity('1', 'blub'), false), + ); + } + + protected function setUp() + { + if (!class_exists('Doctrine\DBAL\DriverManager')) { + $this->markTestSkipped('The Doctrine2 DBAL is required for this test'); + } } } - - public function getCompareData() + + class TestDomainObject { - return array( - array(new ObjectIdentity('123', 'foo'), new ObjectIdentity('123', 'foo'), true), - array(new ObjectIdentity('123', 'foo'), new ObjectIdentity(123, 'foo'), true), - array(new ObjectIdentity('1', 'foo'), new ObjectIdentity('2', 'foo'), false), - array(new ObjectIdentity('1', 'bla'), new ObjectIdentity('1', 'blub'), false), - ); - } - - protected function setUp() - { - if (!class_exists('Doctrine\DBAL\DriverManager')) { - $this->markTestSkipped('The Doctrine2 DBAL is required for this test'); + public function getObjectIdentifier() + { + return 'getObjectIdentifier()'; + } + + public function getId() + { + return 'getId()'; } } } -class TestDomainObject +namespace Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain { - public function getObjectIdentifier() + class TestDomainObject extends \Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject { - return 'getObjectIdentifier()'; - } - - public function getId() - { - return 'getId()'; } } diff --git a/src/Symfony/Component/Security/Tests/Acl/Domain/UserSecurityIdentityTest.php b/src/Symfony/Component/Security/Tests/Acl/Domain/UserSecurityIdentityTest.php index bb98fd0989..9650803ee2 100644 --- a/src/Symfony/Component/Security/Tests/Acl/Domain/UserSecurityIdentityTest.php +++ b/src/Symfony/Component/Security/Tests/Acl/Domain/UserSecurityIdentityTest.php @@ -24,6 +24,15 @@ class UserSecurityIdentityTest extends \PHPUnit_Framework_TestCase $this->assertEquals('Foo', $id->getClass()); } + // Test that constructor never changes the type, even for proxies + public function testContructorWithProxy() + { + $id = new UserSecurityIdentity('foo', 'Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain\Foo'); + + $this->assertEquals('foo', $id->getUsername()); + $this->assertEquals('Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain\Foo', $id->getClass()); + } + /** * @dataProvider getCompareData */ diff --git a/src/Symfony/Component/Security/Tests/Core/Util/ClassUtilsTest.php b/src/Symfony/Component/Security/Tests/Core/Util/ClassUtilsTest.php new file mode 100644 index 0000000000..7a6e698754 --- /dev/null +++ b/src/Symfony/Component/Security/Tests/Core/Util/ClassUtilsTest.php @@ -0,0 +1,41 @@ +assertEquals($expectedClassName, ClassUtils::getRealClass($object)); + } + } + + class TestObject + { + } +} + +namespace Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Core\Util +{ + class TestObject extends \Symfony\Component\Security\Tests\Core\Util\TestObject + { + } +}