parent
cf574fcba8
commit
b98243d193
@ -0,0 +1 @@ |
||||
../doctrine/dbal/bin/doctrine-dbal |
||||
@ -0,0 +1,10 @@ |
||||
build/ |
||||
logs/ |
||||
reports/ |
||||
dist/ |
||||
tests/Doctrine/Tests/Common/Proxy/generated/ |
||||
vendor/ |
||||
.idea |
||||
composer.lock |
||||
doctrine-common-*.tar |
||||
doctrine-common-*.tar.gz |
||||
@ -0,0 +1,3 @@ |
||||
[submodule "lib/vendor/doctrine-build-common"] |
||||
path = lib/vendor/doctrine-build-common |
||||
url = git://github.com/doctrine/doctrine-build-common.git |
||||
@ -0,0 +1,26 @@ |
||||
language: php |
||||
|
||||
sudo: false |
||||
|
||||
cache: |
||||
directory: |
||||
- $HOME/.composer/cache |
||||
|
||||
php: |
||||
- 5.3.3 |
||||
- 5.3 |
||||
- 5.4 |
||||
- 5.5 |
||||
- 5.6 |
||||
- 7.0 |
||||
- hhvm |
||||
|
||||
before_script: |
||||
- composer --prefer-source install |
||||
|
||||
script: |
||||
- ./vendor/bin/phpunit |
||||
|
||||
matrix: |
||||
allow_failures: |
||||
- php: 7.0 |
||||
@ -0,0 +1,3 @@ |
||||
# Version class and file |
||||
project.version_class = Doctrine\\Common\\Version |
||||
project.version_file = lib/Doctrine/Common/Version.php |
||||
@ -0,0 +1,101 @@ |
||||
<?xml version="1.0"?> |
||||
<project name="DoctrineCommon" default="build" basedir="."> |
||||
<property file="build.properties" /> |
||||
|
||||
<target name="php"> |
||||
<exec executable="which" outputproperty="php_executable"> |
||||
<arg value="php" /> |
||||
</exec> |
||||
</target> |
||||
|
||||
<target name="prepare"> |
||||
<mkdir dir="build" /> |
||||
</target> |
||||
|
||||
<target name="build" depends="check-git-checkout-clean,prepare,php,composer"> |
||||
<exec executable="${php_executable}"> |
||||
<arg value="build/composer.phar" /> |
||||
<arg value="archive" /> |
||||
<arg value="--dir=build" /> |
||||
</exec> |
||||
</target> |
||||
|
||||
<target name="composer" depends="php,composer-check,composer-download"> |
||||
<exec executable="${php_executable}"> |
||||
<arg value="build/composer.phar" /> |
||||
<arg value="install" /> |
||||
</exec> |
||||
</target> |
||||
|
||||
<target name="composer-check" depends="prepare"> |
||||
<available file="build/composer.phar" property="composer.present"/> |
||||
</target> |
||||
|
||||
<target name="composer-download" unless="composer.present"> |
||||
<exec executable="wget"> |
||||
<arg value="-Obuild/composer.phar" /> |
||||
<arg value="http://getcomposer.org/composer.phar" /> |
||||
</exec> |
||||
</target> |
||||
|
||||
<target name="make-release" depends="check-git-checkout-clean,prepare,php"> |
||||
<replace file="${project.version_file}" token="-DEV" value="" failOnNoReplacements="true" /> |
||||
<exec executable="${php_executable}" outputproperty="doctrine.current_version" failonerror="true"> |
||||
<arg value="-r" /> |
||||
<arg value="require_once '${project.version_file}';echo ${project.version_class}::VERSION;" /> |
||||
</exec> |
||||
<exec executable="${php_executable}" outputproperty="doctrine.next_version" failonerror="true"> |
||||
<arg value="-r" /> |
||||
<arg value="$parts = explode('.', str_ireplace(array('-DEV', '-ALPHA', '-BETA'), '', '${doctrine.current_version}')); |
||||
if (count($parts) != 3) { |
||||
throw new \InvalidArgumentException('Version is assumed in format x.y.z, ${doctrine.current_version} given'); |
||||
} |
||||
$parts[2]++; |
||||
echo implode('.', $parts); |
||||
" /> |
||||
</exec> |
||||
|
||||
<git-commit file="${project.version_file}" message="Release ${doctrine.current_version}" /> |
||||
<git-tag version="${doctrine.current_version}" /> |
||||
<replace file="${project.version_file}" token="${doctrine.current_version}" value="${doctrine.next_version}-DEV" /> |
||||
<git-commit file="${project.version_file}" message="Bump version to ${doctrine.next_version}" /> |
||||
</target> |
||||
|
||||
<target name="check-git-checkout-clean"> |
||||
<exec executable="git" failonerror="true"> |
||||
<arg value="diff-index" /> |
||||
<arg value="--quiet" /> |
||||
<arg value="HEAD" /> |
||||
</exec> |
||||
</target> |
||||
|
||||
<macrodef name="git-commit"> |
||||
<attribute name="file" default="NOT SET"/> |
||||
<attribute name="message" default="NOT SET"/> |
||||
|
||||
<sequential> |
||||
<exec executable="git"> |
||||
<arg value="add" /> |
||||
<arg value="@{file}" /> |
||||
</exec> |
||||
<exec executable="git"> |
||||
<arg value="commit" /> |
||||
<arg value="-m" /> |
||||
<arg value="@{message}" /> |
||||
</exec> |
||||
</sequential> |
||||
</macrodef> |
||||
|
||||
<macrodef name="git-tag"> |
||||
<attribute name="version" default="NOT SET" /> |
||||
|
||||
<sequential> |
||||
<exec executable="git"> |
||||
<arg value="tag" /> |
||||
<arg value="-m" /> |
||||
<arg value="v@{version}" /> |
||||
<arg value="v@{version}" /> |
||||
</exec> |
||||
</sequential> |
||||
</macrodef> |
||||
</project> |
||||
@ -0,0 +1,25 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<phpunit backupGlobals="false" |
||||
backupStaticAttributes="false" |
||||
colors="true" |
||||
convertErrorsToExceptions="true" |
||||
convertNoticesToExceptions="true" |
||||
convertWarningsToExceptions="true" |
||||
processIsolation="false" |
||||
stopOnFailure="false" |
||||
syntaxCheck="false" |
||||
bootstrap="./tests/Doctrine/Tests/TestInit.php" |
||||
> |
||||
<testsuites> |
||||
<testsuite name="Doctrine Common Test Suite"> |
||||
<directory>./tests/Doctrine/</directory> |
||||
</testsuite> |
||||
</testsuites> |
||||
|
||||
<filter> |
||||
<whitelist> |
||||
<directory>./lib/Doctrine/</directory> |
||||
</whitelist> |
||||
</filter> |
||||
</phpunit> |
||||
@ -0,0 +1,3 @@ |
||||
Doctrine/Tests/Proxies/ |
||||
Doctrine/Tests/ORM/Proxy/generated/ |
||||
Doctrine/Tests/ORM/Tools/Export/export |
||||
@ -0,0 +1,133 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common; |
||||
|
||||
use Doctrine\Common\ClassLoader; |
||||
|
||||
class ClassLoaderTest extends \Doctrine\Tests\DoctrineTestCase |
||||
{ |
||||
public function testClassLoader() |
||||
{ |
||||
$classLoader = new ClassLoader('ClassLoaderTest'); |
||||
$classLoader->setIncludePath(__DIR__); |
||||
$classLoader->setFileExtension('.class.php'); |
||||
$classLoader->setNamespaceSeparator('_'); |
||||
|
||||
$this->assertTrue($classLoader->canLoadClass('ClassLoaderTest_ClassA')); |
||||
$this->assertTrue($classLoader->canLoadClass('ClassLoaderTest_ClassB')); |
||||
$this->assertTrue($classLoader->canLoadClass('ClassLoaderTest_ClassC')); |
||||
$this->assertFalse($classLoader->canLoadClass('OtherClass')); |
||||
$this->assertEquals($classLoader->loadClass('ClassLoaderTest_ClassA'), true); |
||||
$this->assertEquals($classLoader->loadClass('ClassLoaderTest_ClassB'), true); |
||||
$this->assertEquals($classLoader->loadClass('ClassLoaderTest_ClassC'), true); |
||||
} |
||||
|
||||
public function testClassExists() |
||||
{ |
||||
$this->assertFalse(ClassLoader::classExists('ClassLoaderTest\ClassD')); |
||||
$badLoader = function($className) { |
||||
require __DIR__ . '/ClassLoaderTest/ClassD.php'; |
||||
return true; |
||||
}; |
||||
spl_autoload_register($badLoader); |
||||
$this->assertTrue(ClassLoader::classExists('ClassLoaderTest\ClassD')); |
||||
spl_autoload_unregister($badLoader); |
||||
} |
||||
|
||||
public function testGetClassLoader() |
||||
{ |
||||
$cl = new ClassLoader('ClassLoaderTest', __DIR__); |
||||
$cl->register(); |
||||
$this->assertTrue(ClassLoader::getClassLoader('ClassLoaderTest\ClassD') instanceof \Doctrine\Common\ClassLoader); |
||||
$this->assertNull(ClassLoader::getClassLoader('This\Class\Does\Not\Exist')); |
||||
$cl->unregister(); |
||||
} |
||||
|
||||
public function testClassExistsWithSilentAutoloader() |
||||
{ |
||||
$test = $this; |
||||
$silentLoader = function ($className) use ($test) { |
||||
$test->assertSame('ClassLoaderTest\ClassE', $className); |
||||
require __DIR__ . '/ClassLoaderTest/ClassE.php'; |
||||
}; |
||||
$additionalLoader = function () use ($test) { |
||||
$test->fail('Should not call this loader, class was already loaded'); |
||||
}; |
||||
|
||||
$this->assertFalse(ClassLoader::classExists('ClassLoaderTest\ClassE')); |
||||
spl_autoload_register($silentLoader); |
||||
spl_autoload_register($additionalLoader); |
||||
$this->assertTrue(ClassLoader::classExists('ClassLoaderTest\ClassE')); |
||||
spl_autoload_unregister($additionalLoader); |
||||
spl_autoload_unregister($silentLoader); |
||||
} |
||||
|
||||
public function testClassExistsWhenLoaderIsProtected() |
||||
{ |
||||
require_once __DIR__ . '/ClassLoaderTest/ExternalLoader.php'; |
||||
|
||||
// Test static call |
||||
\ClassLoaderTest\ExternalLoader::registerStatic(); |
||||
$this->assertFalse(ClassLoader::classExists('ClassLoaderTest\Class\That\Does\Not\Exist')); |
||||
\ClassLoaderTest\ExternalLoader::unregisterStatic(); |
||||
|
||||
// Test object |
||||
$loader = new \ClassLoaderTest\ExternalLoader(); |
||||
$loader->register(); |
||||
$this->assertFalse(ClassLoader::classExists('ClassLoaderTest\Class\That\Does\Not\Exist')); |
||||
$loader->unregister(); |
||||
} |
||||
|
||||
public function testLoadNonExistingClass() |
||||
{ |
||||
$classLoader = new ClassLoader('ClassLoaderTest', __DIR__); |
||||
|
||||
$this->assertFalse($classLoader->loadClass('ClassLoaderTest\Non\Existing\ClassName')); |
||||
} |
||||
|
||||
public function testLoadFileNotContainingClassClass() |
||||
{ |
||||
$classLoader = new ClassLoader('ClassLoaderTest', __DIR__); |
||||
|
||||
$classLoader->setFileExtension('.class.php'); |
||||
|
||||
$this->assertFalse($classLoader->loadClass('ClassLoaderTest\EmptyFile')); |
||||
} |
||||
|
||||
public function testSupportsInterfaceAutoloading() |
||||
{ |
||||
$classLoader = new ClassLoader(); |
||||
$classLoader->setIncludePath(__DIR__); |
||||
$classLoader->setFileExtension('.class.php'); |
||||
$classLoader->setNamespaceSeparator('_'); |
||||
|
||||
$this->assertTrue($classLoader->loadClass('ClassLoaderTest_InterfaceA')); |
||||
$this->assertTrue(interface_exists('ClassLoaderTest_InterfaceA', false)); |
||||
} |
||||
|
||||
public function testSupportsTraitAutoloading() |
||||
{ |
||||
if (! function_exists('trait_exists')) { |
||||
$this->markTestSkipped('You need a PHP version that supports traits in order to run this test'); |
||||
} |
||||
|
||||
$classLoader = new ClassLoader(); |
||||
$classLoader->setIncludePath(__DIR__); |
||||
$classLoader->setFileExtension('.class.php'); |
||||
$classLoader->setNamespaceSeparator('_'); |
||||
|
||||
$this->assertTrue($classLoader->loadClass('ClassLoaderTest_TraitA')); |
||||
$this->assertTrue(trait_exists('ClassLoaderTest_TraitA', false)); |
||||
} |
||||
|
||||
public function testMultipleAutoloadRequestsWillProduceSameResult() |
||||
{ |
||||
$classLoader = new ClassLoader(); |
||||
$classLoader->setIncludePath(__DIR__); |
||||
$classLoader->setFileExtension('.class.php'); |
||||
$classLoader->setNamespaceSeparator('_'); |
||||
|
||||
$this->assertTrue($classLoader->loadClass('ClassLoaderTest_ClassA')); |
||||
$this->assertTrue($classLoader->loadClass('ClassLoaderTest_ClassA')); |
||||
} |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
class ClassLoaderTest_ClassA |
||||
{ |
||||
|
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
class ClassLoaderTest_ClassB |
||||
{ |
||||
|
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
class ClassLoaderTest_ClassC |
||||
{ |
||||
|
||||
} |
||||
@ -0,0 +1,5 @@ |
||||
<?php |
||||
|
||||
namespace ClassLoaderTest; |
||||
|
||||
class ClassD {} |
||||
@ -0,0 +1,5 @@ |
||||
<?php |
||||
|
||||
namespace ClassLoaderTest; |
||||
|
||||
class ClassE {} |
||||
@ -0,0 +1,38 @@ |
||||
<?php |
||||
|
||||
namespace ClassLoaderTest; |
||||
|
||||
class ExternalLoader |
||||
{ |
||||
public static function registerStatic() { |
||||
spl_autoload_register(array('ClassLoaderTest\ExternalLoader', 'load1')); |
||||
spl_autoload_register(array('ClassLoaderTest\ExternalLoader', 'load2')); |
||||
spl_autoload_register('ClassLoaderTest\ExternalLoader::load3'); |
||||
} |
||||
|
||||
public static function unregisterStatic() { |
||||
spl_autoload_unregister(array('ClassLoaderTest\ExternalLoader', 'load1')); |
||||
spl_autoload_unregister(array('ClassLoaderTest\ExternalLoader', 'load2')); |
||||
spl_autoload_unregister('ClassLoaderTest\ExternalLoader::load3'); |
||||
} |
||||
|
||||
public static function load1() {} |
||||
|
||||
protected static function load2() {} |
||||
|
||||
protected static function load3() {} |
||||
|
||||
public function register() { |
||||
spl_autoload_register(array($this, 'load4')); |
||||
spl_autoload_register(array($this, 'load5')); |
||||
} |
||||
|
||||
public function unregister() { |
||||
spl_autoload_unregister(array($this, 'load4')); |
||||
spl_autoload_unregister(array($this, 'load5')); |
||||
} |
||||
|
||||
public function load4() {} |
||||
|
||||
protected function load5() {} |
||||
} |
||||
@ -0,0 +1,5 @@ |
||||
<?php |
||||
|
||||
interface ClassLoaderTest_InterfaceA |
||||
{ |
||||
} |
||||
@ -0,0 +1,5 @@ |
||||
<?php |
||||
|
||||
trait ClassLoaderTest_TraitA |
||||
{ |
||||
} |
||||
@ -0,0 +1,88 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common; |
||||
|
||||
use Doctrine\Common\EventManager; |
||||
use Doctrine\Common\EventArgs; |
||||
|
||||
class EventManagerTest extends \Doctrine\Tests\DoctrineTestCase |
||||
{ |
||||
/* Some pseudo events */ |
||||
const preFoo = 'preFoo'; |
||||
const postFoo = 'postFoo'; |
||||
const preBar = 'preBar'; |
||||
const postBar = 'postBar'; |
||||
|
||||
private $_preFooInvoked = false; |
||||
private $_postFooInvoked = false; |
||||
|
||||
private $_eventManager; |
||||
|
||||
protected function setUp() |
||||
{ |
||||
$this->_eventManager = new EventManager; |
||||
$this->_preFooInvoked = false; |
||||
$this->_postFooInvoked = false; |
||||
} |
||||
|
||||
public function testInitialState() |
||||
{ |
||||
$this->assertEquals(array(), $this->_eventManager->getListeners()); |
||||
$this->assertFalse($this->_eventManager->hasListeners(self::preFoo)); |
||||
$this->assertFalse($this->_eventManager->hasListeners(self::postFoo)); |
||||
} |
||||
|
||||
public function testAddEventListener() |
||||
{ |
||||
$this->_eventManager->addEventListener(array('preFoo', 'postFoo'), $this); |
||||
$this->assertTrue($this->_eventManager->hasListeners(self::preFoo)); |
||||
$this->assertTrue($this->_eventManager->hasListeners(self::postFoo)); |
||||
$this->assertEquals(1, count($this->_eventManager->getListeners(self::preFoo))); |
||||
$this->assertEquals(1, count($this->_eventManager->getListeners(self::postFoo))); |
||||
$this->assertEquals(2, count($this->_eventManager->getListeners())); |
||||
} |
||||
|
||||
public function testDispatchEvent() |
||||
{ |
||||
$this->_eventManager->addEventListener(array('preFoo', 'postFoo'), $this); |
||||
$this->_eventManager->dispatchEvent(self::preFoo); |
||||
$this->assertTrue($this->_preFooInvoked); |
||||
$this->assertFalse($this->_postFooInvoked); |
||||
} |
||||
|
||||
public function testRemoveEventListener() |
||||
{ |
||||
$this->_eventManager->addEventListener(array('preBar'), $this); |
||||
$this->assertTrue($this->_eventManager->hasListeners(self::preBar)); |
||||
$this->_eventManager->removeEventListener(array('preBar'), $this); |
||||
$this->assertFalse($this->_eventManager->hasListeners(self::preBar)); |
||||
} |
||||
|
||||
public function testAddEventSubscriber() |
||||
{ |
||||
$eventSubscriber = new TestEventSubscriber(); |
||||
$this->_eventManager->addEventSubscriber($eventSubscriber); |
||||
$this->assertTrue($this->_eventManager->hasListeners(self::preFoo)); |
||||
$this->assertTrue($this->_eventManager->hasListeners(self::postFoo)); |
||||
} |
||||
|
||||
/* Listener methods */ |
||||
|
||||
public function preFoo(EventArgs $e) |
||||
{ |
||||
$this->_preFooInvoked = true; |
||||
} |
||||
|
||||
public function postFoo(EventArgs $e) |
||||
{ |
||||
$this->_postFooInvoked = true; |
||||
} |
||||
} |
||||
|
||||
class TestEventSubscriber implements \Doctrine\Common\EventSubscriber |
||||
{ |
||||
public function getSubscribedEvents() |
||||
{ |
||||
return array('preFoo', 'postFoo'); |
||||
} |
||||
} |
||||
@ -0,0 +1,102 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence; |
||||
|
||||
use Doctrine\Common\Persistence\AbstractManagerRegistry; |
||||
use Doctrine\Tests\Common\Persistence\Mapping\TestClassMetadataFactory; |
||||
use Doctrine\Tests\DoctrineTestCase; |
||||
use PHPUnit_Framework_TestCase; |
||||
|
||||
/** |
||||
* @groups DCOM-270 |
||||
* @uses Doctrine\Tests\Common\Persistence\TestObject |
||||
*/ |
||||
class ManagerRegistryTest extends DoctrineTestCase |
||||
{ |
||||
/** |
||||
* @var TestManagerRegistry |
||||
*/ |
||||
private $mr; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setUp() |
||||
{ |
||||
$this->mr = new TestManagerRegistry( |
||||
'ORM', |
||||
array('default_connection'), |
||||
array('default_manager'), |
||||
'default', |
||||
'default', |
||||
'Doctrine\Common\Persistence\ObjectManagerAware' |
||||
); |
||||
} |
||||
|
||||
public function testGetManagerForClass() |
||||
{ |
||||
$this->mr->getManagerForClass('Doctrine\Tests\Common\Persistence\TestObject'); |
||||
} |
||||
|
||||
public function testGetManagerForProxyInterface() |
||||
{ |
||||
$this->assertNull($this->mr->getManagerForClass('Doctrine\Common\Persistence\ObjectManagerAware')); |
||||
} |
||||
|
||||
public function testGetManagerForInvalidClass() |
||||
{ |
||||
$this->setExpectedException( |
||||
'ReflectionException', |
||||
'Class Doctrine\Tests\Common\Persistence\TestObjectInexistent does not exist' |
||||
); |
||||
|
||||
$this->mr->getManagerForClass('prefix:TestObjectInexistent'); |
||||
} |
||||
|
||||
public function testGetManagerForAliasedClass() |
||||
{ |
||||
$this->mr->getManagerForClass('prefix:TestObject'); |
||||
} |
||||
|
||||
public function testGetManagerForInvalidAliasedClass() |
||||
{ |
||||
$this->setExpectedException( |
||||
'ReflectionException', |
||||
'Class Doctrine\Tests\Common\Persistence\TestObject:Foo does not exist' |
||||
); |
||||
|
||||
$this->mr->getManagerForClass('prefix:TestObject:Foo'); |
||||
} |
||||
} |
||||
|
||||
class TestManager extends PHPUnit_Framework_TestCase |
||||
{ |
||||
public function getMetadataFactory() |
||||
{ |
||||
$driver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); |
||||
$metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
|
||||
return new TestClassMetadataFactory($driver, $metadata); |
||||
} |
||||
} |
||||
|
||||
class TestManagerRegistry extends AbstractManagerRegistry |
||||
{ |
||||
protected function getService($name) |
||||
{ |
||||
return new TestManager(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function resetService($name) |
||||
{ |
||||
|
||||
} |
||||
|
||||
public function getAliasNamespace($alias) |
||||
{ |
||||
return __NAMESPACE__; |
||||
} |
||||
} |
||||
@ -0,0 +1,29 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence\Mapping; |
||||
|
||||
use Doctrine\Common\Annotations\AnnotationReader; |
||||
use Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver; |
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata; |
||||
|
||||
class AnnotationDriverTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
public function testGetAllClassNames() |
||||
{ |
||||
$reader = new AnnotationReader(); |
||||
$driver = new SimpleAnnotationDriver($reader, array(__DIR__ . '/_files/annotation')); |
||||
|
||||
$classes = $driver->getAllClassNames(); |
||||
|
||||
$this->assertEquals(array('Doctrine\TestClass'), $classes); |
||||
} |
||||
} |
||||
|
||||
class SimpleAnnotationDriver extends AnnotationDriver |
||||
{ |
||||
protected $entityAnnotationClasses = array('Doctrine\Entity' => true); |
||||
|
||||
public function loadMetadataForClass($className, ClassMetadata $metadata) |
||||
{ |
||||
} |
||||
} |
||||
@ -0,0 +1,152 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence\Mapping; |
||||
|
||||
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain; |
||||
use Doctrine\Tests\DoctrineTestCase; |
||||
|
||||
class DriverChainTest extends DoctrineTestCase |
||||
{ |
||||
public function testDelegateToMatchingNamespaceDriver() |
||||
{ |
||||
$className = 'Doctrine\Tests\Common\Persistence\Mapping\DriverChainEntity'; |
||||
$classMetadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
|
||||
$chain = new MappingDriverChain(); |
||||
|
||||
$driver1 = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); |
||||
$driver1->expects($this->never()) |
||||
->method('loadMetadataForClass'); |
||||
$driver1->expectS($this->never()) |
||||
->method('isTransient'); |
||||
|
||||
$driver2 = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); |
||||
$driver2->expects($this->at(0)) |
||||
->method('loadMetadataForClass') |
||||
->with($this->equalTo($className), $this->equalTo($classMetadata)); |
||||
$driver2->expects($this->at(1)) |
||||
->method('isTransient') |
||||
->with($this->equalTo($className)) |
||||
->will($this->returnValue( true )); |
||||
|
||||
$chain->addDriver($driver1, 'Doctrine\Tests\Models\Company'); |
||||
$chain->addDriver($driver2, 'Doctrine\Tests\Common\Persistence\Mapping'); |
||||
|
||||
$chain->loadMetadataForClass($className, $classMetadata); |
||||
|
||||
$this->assertTrue( $chain->isTransient($className) ); |
||||
} |
||||
|
||||
public function testLoadMetadata_NoDelegatorFound_ThrowsMappingException() |
||||
{ |
||||
$className = 'Doctrine\Tests\Common\Persistence\Mapping\DriverChainEntity'; |
||||
$classMetadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
|
||||
$chain = new MappingDriverChain(); |
||||
|
||||
$this->setExpectedException('Doctrine\Common\Persistence\Mapping\MappingException'); |
||||
$chain->loadMetadataForClass($className, $classMetadata); |
||||
} |
||||
|
||||
public function testGatherAllClassNames() |
||||
{ |
||||
$className = 'Doctrine\Tests\Common\Persistence\Mapping\DriverChainEntity'; |
||||
$classMetadata = $this->getMock('Doctrine\Common\Persistence\ClassMetadata'); |
||||
|
||||
$chain = new MappingDriverChain(); |
||||
|
||||
$driver1 = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); |
||||
$driver1->expects($this->once()) |
||||
->method('getAllClassNames') |
||||
->will($this->returnValue(array('Doctrine\Tests\Models\Company\Foo'))); |
||||
|
||||
$driver2 = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); |
||||
$driver2->expects($this->once()) |
||||
->method('getAllClassNames') |
||||
->will($this->returnValue(array('Doctrine\Tests\ORM\Mapping\Bar', 'Doctrine\Tests\ORM\Mapping\Baz', 'FooBarBaz'))); |
||||
|
||||
$chain->addDriver($driver1, 'Doctrine\Tests\Models\Company'); |
||||
$chain->addDriver($driver2, 'Doctrine\Tests\ORM\Mapping'); |
||||
|
||||
$this->assertEquals(array( |
||||
'Doctrine\Tests\Models\Company\Foo', |
||||
'Doctrine\Tests\ORM\Mapping\Bar', |
||||
'Doctrine\Tests\ORM\Mapping\Baz' |
||||
), $chain->getAllClassNames()); |
||||
} |
||||
|
||||
/** |
||||
* @group DDC-706 |
||||
*/ |
||||
public function testIsTransient() |
||||
{ |
||||
$driver1 = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); |
||||
$chain = new MappingDriverChain(); |
||||
$chain->addDriver($driver1, 'Doctrine\Tests\Models\CMS'); |
||||
|
||||
$this->assertTrue($chain->isTransient('stdClass'), "stdClass isTransient"); |
||||
} |
||||
|
||||
/** |
||||
* @group DDC-1412 |
||||
*/ |
||||
public function testDefaultDriver() |
||||
{ |
||||
$companyDriver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); |
||||
$defaultDriver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); |
||||
$entityClassName = 'Doctrine\Tests\ORM\Mapping\DriverChainEntity'; |
||||
$managerClassName = 'Doctrine\Tests\Models\Company\CompanyManager'; |
||||
$chain = new MappingDriverChain(); |
||||
|
||||
$companyDriver->expects($this->never()) |
||||
->method('loadMetadataForClass'); |
||||
$companyDriver->expects($this->once()) |
||||
->method('isTransient') |
||||
->with($this->equalTo($managerClassName)) |
||||
->will($this->returnValue(false)); |
||||
|
||||
$defaultDriver->expects($this->never()) |
||||
->method('loadMetadataForClass'); |
||||
$defaultDriver->expects($this->once()) |
||||
->method('isTransient') |
||||
->with($this->equalTo($entityClassName)) |
||||
->will($this->returnValue(true)); |
||||
|
||||
$this->assertNull($chain->getDefaultDriver()); |
||||
|
||||
$chain->setDefaultDriver($defaultDriver); |
||||
$chain->addDriver($companyDriver, 'Doctrine\Tests\Models\Company'); |
||||
|
||||
$this->assertSame($defaultDriver, $chain->getDefaultDriver()); |
||||
|
||||
$this->assertTrue($chain->isTransient($entityClassName)); |
||||
$this->assertFalse($chain->isTransient($managerClassName)); |
||||
} |
||||
|
||||
public function testDefaultDriverGetAllClassNames() |
||||
{ |
||||
$companyDriver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); |
||||
$defaultDriver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); |
||||
$chain = new MappingDriverChain(); |
||||
|
||||
$companyDriver->expects($this->once()) |
||||
->method('getAllClassNames') |
||||
->will($this->returnValue(array('Doctrine\Tests\Models\Company\Foo'))); |
||||
|
||||
$defaultDriver->expects($this->once()) |
||||
->method('getAllClassNames') |
||||
->will($this->returnValue(array('Other\Class'))); |
||||
|
||||
$chain->setDefaultDriver($defaultDriver); |
||||
$chain->addDriver($companyDriver, 'Doctrine\Tests\Models\Company'); |
||||
|
||||
$classNames = $chain->getAllClassNames(); |
||||
|
||||
$this->assertEquals(array('Doctrine\Tests\Models\Company\Foo', 'Other\Class'), $classNames); |
||||
} |
||||
} |
||||
|
||||
class DriverChainEntity |
||||
{ |
||||
|
||||
} |
||||
@ -0,0 +1,209 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence\Mapping; |
||||
|
||||
use Doctrine\Tests\DoctrineTestCase; |
||||
use Doctrine\Common\Persistence\Mapping\Driver\DefaultFileLocator; |
||||
use Doctrine\Common\Persistence\Mapping\ReflectionService; |
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata; |
||||
use Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory; |
||||
use Doctrine\Common\Cache\ArrayCache; |
||||
|
||||
class ClassMetadataFactoryTest extends DoctrineTestCase |
||||
{ |
||||
/** |
||||
* @var TestClassMetadataFactory |
||||
*/ |
||||
private $cmf; |
||||
|
||||
public function setUp() |
||||
{ |
||||
$driver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); |
||||
$metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
$this->cmf = new TestClassMetadataFactory($driver, $metadata); |
||||
} |
||||
|
||||
public function testGetCacheDriver() |
||||
{ |
||||
$this->assertNull($this->cmf->getCacheDriver()); |
||||
$cache = new ArrayCache(); |
||||
$this->cmf->setCacheDriver($cache); |
||||
$this->assertSame($cache, $this->cmf->getCacheDriver()); |
||||
} |
||||
|
||||
public function testGetMetadataFor() |
||||
{ |
||||
$metadata = $this->cmf->getMetadataFor('stdClass'); |
||||
|
||||
$this->assertInstanceOf('Doctrine\Common\Persistence\Mapping\ClassMetadata', $metadata); |
||||
$this->assertTrue($this->cmf->hasMetadataFor('stdClass')); |
||||
} |
||||
|
||||
public function testGetMetadataForAbsentClass() |
||||
{ |
||||
$this->setExpectedException('Doctrine\Common\Persistence\Mapping\MappingException'); |
||||
$this->cmf->getMetadataFor(__NAMESPACE__ . '\AbsentClass'); |
||||
} |
||||
|
||||
public function testGetParentMetadata() |
||||
{ |
||||
$metadata = $this->cmf->getMetadataFor(__NAMESPACE__ . '\ChildEntity'); |
||||
|
||||
$this->assertInstanceOf('Doctrine\Common\Persistence\Mapping\ClassMetadata', $metadata); |
||||
$this->assertTrue($this->cmf->hasMetadataFor(__NAMESPACE__ . '\ChildEntity')); |
||||
$this->assertTrue($this->cmf->hasMetadataFor(__NAMESPACE__ . '\RootEntity')); |
||||
} |
||||
|
||||
public function testGetCachedMetadata() |
||||
{ |
||||
$metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
$cache = new ArrayCache(); |
||||
$cache->save(__NAMESPACE__. '\ChildEntity$CLASSMETADATA', $metadata); |
||||
|
||||
$this->cmf->setCacheDriver($cache); |
||||
|
||||
$loadedMetadata = $this->cmf->getMetadataFor(__NAMESPACE__ . '\ChildEntity'); |
||||
$this->assertSame($loadedMetadata, $metadata); |
||||
} |
||||
|
||||
public function testCacheGetMetadataFor() |
||||
{ |
||||
$cache = new ArrayCache(); |
||||
$this->cmf->setCacheDriver($cache); |
||||
|
||||
$loadedMetadata = $this->cmf->getMetadataFor(__NAMESPACE__ . '\ChildEntity'); |
||||
|
||||
$this->assertSame($loadedMetadata, $cache->fetch(__NAMESPACE__. '\ChildEntity$CLASSMETADATA')); |
||||
} |
||||
|
||||
public function testGetAliasedMetadata() |
||||
{ |
||||
$this->cmf->getMetadataFor('prefix:ChildEntity'); |
||||
|
||||
$this->assertTrue($this->cmf->hasMetadataFor(__NAMESPACE__ . '\ChildEntity')); |
||||
$this->assertTrue($this->cmf->hasMetadataFor('prefix:ChildEntity')); |
||||
} |
||||
|
||||
/** |
||||
* @group DCOM-270 |
||||
*/ |
||||
public function testGetInvalidAliasedMetadata() |
||||
{ |
||||
$this->setExpectedException( |
||||
'Doctrine\Common\Persistence\Mapping\MappingException', |
||||
'Class \'Doctrine\Tests\Common\Persistence\Mapping\ChildEntity:Foo\' does not exist' |
||||
); |
||||
|
||||
$this->cmf->getMetadataFor('prefix:ChildEntity:Foo'); |
||||
} |
||||
|
||||
/** |
||||
* @group DCOM-270 |
||||
*/ |
||||
public function testClassIsTransient() |
||||
{ |
||||
$this->assertTrue($this->cmf->isTransient('prefix:ChildEntity:Foo')); |
||||
} |
||||
|
||||
public function testWillFallbackOnNotLoadedMetadata() |
||||
{ |
||||
$classMetadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
|
||||
$this->cmf->fallbackCallback = function () use ($classMetadata) { |
||||
return $classMetadata; |
||||
}; |
||||
|
||||
$this->cmf->metadata = null; |
||||
|
||||
$this->assertSame($classMetadata, $this->cmf->getMetadataFor('Foo')); |
||||
} |
||||
|
||||
public function testWillFailOnFallbackFailureWithNotLoadedMetadata() |
||||
{ |
||||
$this->cmf->fallbackCallback = function () { |
||||
return null; |
||||
}; |
||||
|
||||
$this->cmf->metadata = null; |
||||
|
||||
$this->setExpectedException('Doctrine\Common\Persistence\Mapping\MappingException'); |
||||
|
||||
$this->cmf->getMetadataFor('Foo'); |
||||
} |
||||
} |
||||
|
||||
class TestClassMetadataFactory extends AbstractClassMetadataFactory |
||||
{ |
||||
public $driver; |
||||
public $metadata; |
||||
|
||||
/** @var callable|null */ |
||||
public $fallbackCallback; |
||||
|
||||
public function __construct($driver, $metadata) |
||||
{ |
||||
$this->driver = $driver; |
||||
$this->metadata = $metadata; |
||||
} |
||||
|
||||
protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonSuperclassParents) |
||||
{ |
||||
|
||||
} |
||||
|
||||
protected function getFqcnFromAlias($namespaceAlias, $simpleClassName) |
||||
{ |
||||
return __NAMESPACE__ . '\\' . $simpleClassName; |
||||
} |
||||
|
||||
protected function initialize() |
||||
{ |
||||
|
||||
} |
||||
|
||||
protected function newClassMetadataInstance($className) |
||||
{ |
||||
return $this->metadata; |
||||
} |
||||
|
||||
protected function getDriver() |
||||
{ |
||||
return $this->driver; |
||||
} |
||||
protected function wakeupReflection(ClassMetadata $class, ReflectionService $reflService) |
||||
{ |
||||
} |
||||
|
||||
protected function initializeReflection(ClassMetadata $class, ReflectionService $reflService) |
||||
{ |
||||
} |
||||
|
||||
protected function isEntity(ClassMetadata $class) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
protected function onNotFoundMetadata($className) |
||||
{ |
||||
if (! $fallback = $this->fallbackCallback) { |
||||
return null; |
||||
} |
||||
|
||||
return $fallback(); |
||||
} |
||||
|
||||
public function isTransient($class) |
||||
{ |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
class RootEntity |
||||
{ |
||||
|
||||
} |
||||
|
||||
class ChildEntity extends RootEntity |
||||
{ |
||||
|
||||
} |
||||
@ -0,0 +1,98 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence\Mapping; |
||||
|
||||
use Doctrine\Tests\DoctrineTestCase; |
||||
use Doctrine\Common\Persistence\Mapping\Driver\DefaultFileLocator; |
||||
|
||||
class DefaultFileLocatorTest extends DoctrineTestCase |
||||
{ |
||||
public function testGetPaths() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
|
||||
$locator = new DefaultFileLocator(array($path)); |
||||
$this->assertEquals(array($path), $locator->getPaths()); |
||||
|
||||
$locator = new DefaultFileLocator($path); |
||||
$this->assertEquals(array($path), $locator->getPaths()); |
||||
} |
||||
|
||||
public function testGetFileExtension() |
||||
{ |
||||
$locator = new DefaultFileLocator(array(), ".yml"); |
||||
$this->assertEquals(".yml", $locator->getFileExtension()); |
||||
$locator->setFileExtension(".xml"); |
||||
$this->assertEquals(".xml", $locator->getFileExtension()); |
||||
} |
||||
|
||||
public function testUniquePaths() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
|
||||
$locator = new DefaultFileLocator(array($path, $path)); |
||||
$this->assertEquals(array($path), $locator->getPaths()); |
||||
} |
||||
|
||||
public function testFindMappingFile() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
|
||||
$locator = new DefaultFileLocator(array($path), ".yml"); |
||||
|
||||
$this->assertEquals(__DIR__ . '/_files' . DIRECTORY_SEPARATOR . 'stdClass.yml', $locator->findMappingFile('stdClass')); |
||||
} |
||||
|
||||
public function testFindMappingFileNotFound() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
|
||||
$locator = new DefaultFileLocator(array($path), ".yml"); |
||||
|
||||
$this->setExpectedException( |
||||
'Doctrine\Common\Persistence\Mapping\MappingException', |
||||
"No mapping file found named 'stdClass2.yml' for class 'stdClass2'" |
||||
); |
||||
$locator->findMappingFile('stdClass2'); |
||||
} |
||||
|
||||
public function testGetAllClassNames() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
|
||||
$locator = new DefaultFileLocator(array($path), ".yml"); |
||||
$allClasses = $locator->getAllClassNames(null); |
||||
$globalClasses = $locator->getAllClassNames("global"); |
||||
|
||||
$expectedAllClasses = array('global', 'stdClass', 'subDirClass'); |
||||
$expectedGlobalClasses = array('subDirClass', 'stdClass'); |
||||
|
||||
sort($allClasses); |
||||
sort($globalClasses); |
||||
sort($expectedAllClasses); |
||||
sort($expectedGlobalClasses); |
||||
|
||||
$this->assertEquals($expectedAllClasses, $allClasses); |
||||
$this->assertEquals($expectedGlobalClasses, $globalClasses); |
||||
} |
||||
|
||||
public function testGetAllClassNamesNonMatchingFileExtension() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
|
||||
$locator = new DefaultFileLocator(array($path), ".xml"); |
||||
$this->assertEquals(array(), $locator->getAllClassNames("global")); |
||||
} |
||||
|
||||
public function testFileExists() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
|
||||
$locator = new DefaultFileLocator(array($path), ".yml"); |
||||
|
||||
$this->assertTrue($locator->fileExists("stdClass")); |
||||
$this->assertFalse($locator->fileExists("stdClass2")); |
||||
$this->assertTrue($locator->fileExists("global")); |
||||
$this->assertFalse($locator->fileExists("global2")); |
||||
} |
||||
} |
||||
@ -0,0 +1,142 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence\Mapping; |
||||
|
||||
use Doctrine\Tests\DoctrineTestCase; |
||||
use Doctrine\Common\Persistence\Mapping\Driver\FileDriver; |
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata; |
||||
|
||||
class FileDriverTest extends DoctrineTestCase |
||||
{ |
||||
public function testGlobalBasename() |
||||
{ |
||||
$driver = new TestFileDriver(array()); |
||||
|
||||
$this->assertNull($driver->getGlobalBasename()); |
||||
|
||||
$driver->setGlobalBasename("global"); |
||||
$this->assertEquals("global", $driver->getGlobalBasename()); |
||||
} |
||||
|
||||
public function testGetElementFromGlobalFile() |
||||
{ |
||||
$driver = new TestFileDriver($this->newLocator()); |
||||
$driver->setGlobalBasename("global"); |
||||
|
||||
$element = $driver->getElement('stdGlobal'); |
||||
|
||||
$this->assertEquals('stdGlobal', $element); |
||||
} |
||||
|
||||
public function testGetElementFromFile() |
||||
{ |
||||
$locator = $this->newLocator(); |
||||
$locator->expects($this->once()) |
||||
->method('findMappingFile') |
||||
->with($this->equalTo('stdClass')) |
||||
->will($this->returnValue(__DIR__ . '/_files/stdClass.yml')); |
||||
|
||||
$driver = new TestFileDriver($locator); |
||||
|
||||
$this->assertEquals('stdClass', $driver->getElement('stdClass')); |
||||
} |
||||
|
||||
public function testGetAllClassNamesGlobalBasename() |
||||
{ |
||||
$driver = new TestFileDriver($this->newLocator()); |
||||
$driver->setGlobalBasename("global"); |
||||
|
||||
$classNames = $driver->getAllClassNames(); |
||||
|
||||
$this->assertEquals(array('stdGlobal', 'stdGlobal2'), $classNames); |
||||
} |
||||
|
||||
public function testGetAllClassNamesFromMappingFile() |
||||
{ |
||||
$locator = $this->newLocator(); |
||||
$locator->expects($this->any()) |
||||
->method('getAllClassNames') |
||||
->with($this->equalTo(null)) |
||||
->will($this->returnValue(array('stdClass'))); |
||||
$driver = new TestFileDriver($locator); |
||||
|
||||
$classNames = $driver->getAllClassNames(); |
||||
|
||||
$this->assertEquals(array('stdClass'), $classNames); |
||||
} |
||||
|
||||
public function testGetAllClassNamesBothSources() |
||||
{ |
||||
$locator = $this->newLocator(); |
||||
$locator->expects($this->any()) |
||||
->method('getAllClassNames') |
||||
->with($this->equalTo('global')) |
||||
->will($this->returnValue(array('stdClass'))); |
||||
$driver = new TestFileDriver($locator); |
||||
$driver->setGlobalBasename("global"); |
||||
|
||||
$classNames = $driver->getAllClassNames(); |
||||
|
||||
$this->assertEquals(array('stdGlobal', 'stdGlobal2', 'stdClass'), $classNames); |
||||
} |
||||
|
||||
public function testIsNotTransient() |
||||
{ |
||||
$locator = $this->newLocator(); |
||||
$locator->expects($this->once()) |
||||
->method('fileExists') |
||||
->with($this->equalTo('stdClass')) |
||||
->will($this->returnValue( true )); |
||||
|
||||
$driver = new TestFileDriver($locator); |
||||
$driver->setGlobalBasename("global"); |
||||
|
||||
$this->assertFalse($driver->isTransient('stdClass')); |
||||
$this->assertFalse($driver->isTransient('stdGlobal')); |
||||
$this->assertFalse($driver->isTransient('stdGlobal2')); |
||||
} |
||||
|
||||
public function testIsTransient() |
||||
{ |
||||
$locator = $this->newLocator(); |
||||
$locator->expects($this->once()) |
||||
->method('fileExists') |
||||
->with($this->equalTo('stdClass2')) |
||||
->will($this->returnValue( false )); |
||||
|
||||
$driver = new TestFileDriver($locator); |
||||
|
||||
$this->assertTrue($driver->isTransient('stdClass2')); |
||||
} |
||||
|
||||
public function testNonLocatorFallback() |
||||
{ |
||||
$driver = new TestFileDriver(__DIR__ . '/_files', '.yml'); |
||||
$this->assertTrue($driver->isTransient('stdClass2')); |
||||
$this->assertFalse($driver->isTransient('stdClass')); |
||||
} |
||||
|
||||
private function newLocator() |
||||
{ |
||||
$locator = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\FileLocator'); |
||||
$locator->expects($this->any())->method('getFileExtension')->will($this->returnValue('.yml')); |
||||
$locator->expects($this->any())->method('getPaths')->will($this->returnValue(array(__DIR__ . "/_files"))); |
||||
return $locator; |
||||
} |
||||
} |
||||
|
||||
class TestFileDriver extends FileDriver |
||||
{ |
||||
protected function loadMappingFile($file) |
||||
{ |
||||
if (strpos($file, "global.yml") !== false) { |
||||
return array('stdGlobal' => 'stdGlobal', 'stdGlobal2' => 'stdGlobal2'); |
||||
} |
||||
return array('stdClass' => 'stdClass'); |
||||
} |
||||
|
||||
public function loadMetadataForClass($className, ClassMetadata $metadata) |
||||
{ |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence\Mapping; |
||||
|
||||
use Doctrine\Tests\DoctrineTestCase; |
||||
use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver; |
||||
|
||||
class PHPDriverTest extends DoctrineTestCase |
||||
{ |
||||
public function testLoadMetadata() |
||||
{ |
||||
$metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
$metadata->expects($this->once())->method('getFieldNames'); |
||||
|
||||
$driver = new PHPDriver(array(__DIR__ . "/_files")); |
||||
$driver->loadMetadataForClass('TestEntity', $metadata); |
||||
} |
||||
} |
||||
@ -0,0 +1,84 @@ |
||||
<?php |
||||
/* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
* This software consists of voluntary contributions made by many individuals |
||||
* and is licensed under the MIT license. For more information, see |
||||
* <http://www.doctrine-project.org>. |
||||
*/ |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence\Mapping; |
||||
|
||||
use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService; |
||||
|
||||
/** |
||||
* @group DCOM-93 |
||||
*/ |
||||
class RuntimeReflectionServiceTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
/** |
||||
* @var RuntimeReflectionService |
||||
*/ |
||||
private $reflectionService; |
||||
|
||||
public $unusedPublicProperty; |
||||
|
||||
public function setUp() |
||||
{ |
||||
$this->reflectionService = new RuntimeReflectionService(); |
||||
} |
||||
|
||||
public function testShortname() |
||||
{ |
||||
$this->assertEquals("RuntimeReflectionServiceTest", $this->reflectionService->getClassShortName(__CLASS__)); |
||||
} |
||||
|
||||
public function testClassNamespaceName() |
||||
{ |
||||
$this->assertEquals("Doctrine\Tests\Common\Persistence\Mapping", $this->reflectionService->getClassNamespace(__CLASS__)); |
||||
} |
||||
|
||||
public function testGetParentClasses() |
||||
{ |
||||
$classes = $this->reflectionService->getParentClasses(__CLASS__); |
||||
$this->assertTrue(count($classes) >= 1, "The test class ".__CLASS__." should have at least one parent."); |
||||
} |
||||
|
||||
public function testGetParentClassesForAbsentClass() |
||||
{ |
||||
$this->setExpectedException('Doctrine\Common\Persistence\Mapping\MappingException'); |
||||
$this->reflectionService->getParentClasses(__NAMESPACE__ . '\AbsentClass'); |
||||
} |
||||
|
||||
public function testGetReflectionClass() |
||||
{ |
||||
$class = $this->reflectionService->getClass(__CLASS__); |
||||
$this->assertInstanceOf("ReflectionClass", $class); |
||||
} |
||||
|
||||
public function testGetMethods() |
||||
{ |
||||
$this->assertTrue($this->reflectionService->hasPublicMethod(__CLASS__, "testGetMethods")); |
||||
$this->assertFalse($this->reflectionService->hasPublicMethod(__CLASS__, "testGetMethods2")); |
||||
} |
||||
|
||||
public function testGetAccessibleProperty() |
||||
{ |
||||
$reflProp = $this->reflectionService->getAccessibleProperty(__CLASS__, "reflectionService"); |
||||
$this->assertInstanceOf("ReflectionProperty", $reflProp); |
||||
|
||||
$reflProp = $this->reflectionService->getAccessibleProperty(__CLASS__, "unusedPublicProperty"); |
||||
$this->assertInstanceOf("Doctrine\Common\Reflection\RuntimePublicReflectionProperty", $reflProp); |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,35 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence\Mapping; |
||||
|
||||
use Doctrine\Tests\DoctrineTestCase; |
||||
use Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver; |
||||
|
||||
class StaticPHPDriverTest extends DoctrineTestCase |
||||
{ |
||||
public function testLoadMetadata() |
||||
{ |
||||
$metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
$metadata->expects($this->once())->method('getFieldNames'); |
||||
|
||||
$driver = new StaticPHPDriver(array(__DIR__)); |
||||
$driver->loadMetadataForClass(__NAMESPACE__ . '\\TestEntity', $metadata); |
||||
} |
||||
|
||||
public function testGetAllClassNames() |
||||
{ |
||||
$driver = new StaticPHPDriver(array(__DIR__)); |
||||
$classNames = $driver->getAllClassNames(); |
||||
|
||||
$this->assertContains( |
||||
'Doctrine\Tests\Common\Persistence\Mapping\TestEntity', $classNames); |
||||
} |
||||
} |
||||
|
||||
class TestEntity |
||||
{ |
||||
static public function loadMetadata($metadata) |
||||
{ |
||||
$metadata->getFieldNames(); |
||||
} |
||||
} |
||||
@ -0,0 +1,70 @@ |
||||
<?php |
||||
/* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
* This software consists of voluntary contributions made by many individuals |
||||
* and is licensed under the MIT license. For more information, see |
||||
* <http://www.doctrine-project.org>. |
||||
*/ |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence\Mapping; |
||||
|
||||
use Doctrine\Common\Persistence\Mapping\StaticReflectionService; |
||||
|
||||
/** |
||||
* @group DCOM-93 |
||||
*/ |
||||
class StaticReflectionServiceTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
private $reflectionService; |
||||
|
||||
public function setUp() |
||||
{ |
||||
$this->reflectionService = new StaticReflectionService(); |
||||
} |
||||
|
||||
public function testShortname() |
||||
{ |
||||
$this->assertEquals("StaticReflectionServiceTest", $this->reflectionService->getClassShortName(__CLASS__)); |
||||
} |
||||
|
||||
public function testClassNamespaceName() |
||||
{ |
||||
$this->assertEquals("Doctrine\Tests\Common\Persistence\Mapping", $this->reflectionService->getClassNamespace(__CLASS__)); |
||||
} |
||||
|
||||
public function testGetParentClasses() |
||||
{ |
||||
$classes = $this->reflectionService->getParentClasses(__CLASS__); |
||||
$this->assertTrue(count($classes) == 0, "The test class ".__CLASS__." should have no parents according to static reflection."); |
||||
} |
||||
|
||||
public function testGetReflectionClass() |
||||
{ |
||||
$class = $this->reflectionService->getClass(__CLASS__); |
||||
$this->assertNull($class); |
||||
} |
||||
|
||||
public function testGetMethods() |
||||
{ |
||||
$this->assertTrue($this->reflectionService->hasPublicMethod(__CLASS__, "testGetMethods")); |
||||
$this->assertTrue($this->reflectionService->hasPublicMethod(__CLASS__, "testGetMethods2")); |
||||
} |
||||
|
||||
public function testGetAccessibleProperty() |
||||
{ |
||||
$reflProp = $this->reflectionService->getAccessibleProperty(__CLASS__, "reflectionService"); |
||||
$this->assertNull($reflProp); |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,181 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence\Mapping; |
||||
|
||||
use Doctrine\Tests\DoctrineTestCase; |
||||
use Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator; |
||||
|
||||
class SymfonyFileLocatorTest extends DoctrineTestCase |
||||
{ |
||||
public function testGetPaths() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
$prefix = "Foo"; |
||||
|
||||
$locator = new SymfonyFileLocator(array($path => $prefix)); |
||||
$this->assertEquals(array($path), $locator->getPaths()); |
||||
|
||||
$locator = new SymfonyFileLocator(array($path => $prefix)); |
||||
$this->assertEquals(array($path), $locator->getPaths()); |
||||
} |
||||
|
||||
public function testGetPrefixes() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
$prefix = "Foo"; |
||||
|
||||
$locator = new SymfonyFileLocator(array($path => $prefix)); |
||||
$this->assertEquals(array($path => $prefix), $locator->getNamespacePrefixes()); |
||||
} |
||||
|
||||
public function testGetFileExtension() |
||||
{ |
||||
$locator = new SymfonyFileLocator(array(), ".yml"); |
||||
$this->assertEquals(".yml", $locator->getFileExtension()); |
||||
$locator->setFileExtension(".xml"); |
||||
$this->assertEquals(".xml", $locator->getFileExtension()); |
||||
} |
||||
|
||||
public function testFileExists() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
$prefix = "Foo"; |
||||
|
||||
$locator = new SymfonyFileLocator(array($path => $prefix), ".yml"); |
||||
|
||||
$this->assertTrue($locator->fileExists("Foo\stdClass")); |
||||
$this->assertTrue($locator->fileExists("Foo\global")); |
||||
$this->assertFalse($locator->fileExists("Foo\stdClass2")); |
||||
$this->assertFalse($locator->fileExists("Foo\global2")); |
||||
} |
||||
|
||||
public function testGetAllClassNames() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
$prefix = "Foo"; |
||||
|
||||
$locator = new SymfonyFileLocator(array($path => $prefix), ".yml"); |
||||
$allClasses = $locator->getAllClassNames(null); |
||||
$globalClasses = $locator->getAllClassNames("global"); |
||||
|
||||
$expectedAllClasses = array("Foo\\Bar\\subDirClass", "Foo\\global", "Foo\\stdClass"); |
||||
$expectedGlobalClasses = array("Foo\\Bar\\subDirClass", "Foo\\stdClass"); |
||||
|
||||
sort($allClasses); |
||||
sort($globalClasses); |
||||
sort($expectedAllClasses); |
||||
sort($expectedGlobalClasses); |
||||
|
||||
$this->assertEquals($expectedAllClasses, $allClasses); |
||||
$this->assertEquals($expectedGlobalClasses, $globalClasses); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException \InvalidArgumentException |
||||
* @expectedExceptionMessage Namespace separator should not be empty |
||||
*/ |
||||
public function testInvalidCustomNamespaceSeparator() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
$prefix = "Foo"; |
||||
|
||||
new SymfonyFileLocator(array($path => $prefix), ".yml", null); |
||||
} |
||||
|
||||
public function customNamespaceSeparatorProvider() |
||||
{ |
||||
return array( |
||||
'directory separator' => array(DIRECTORY_SEPARATOR, "/_custom_ns/dir"), |
||||
'default dot separator' => array('.', "/_custom_ns/dot"), |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider customNamespaceSeparatorProvider |
||||
* |
||||
* @param $separator string Directory separator to test against |
||||
* @param $dir string Path to load mapping data from |
||||
* |
||||
* @throws \Doctrine\Common\Persistence\Mapping\MappingException |
||||
*/ |
||||
public function testGetClassNamesWithCustomNsSeparator($separator, $dir) |
||||
{ |
||||
$path = __DIR__ . $dir; |
||||
$prefix = "Foo"; |
||||
|
||||
$locator = new SymfonyFileLocator(array($path => $prefix), ".yml", $separator); |
||||
$classes = $locator->getAllClassNames(null); |
||||
sort($classes); |
||||
|
||||
$this->assertEquals(array("Foo\\stdClass", "Foo\\sub\\subClass", "Foo\\sub\\subsub\\subSubClass"), $classes); |
||||
} |
||||
|
||||
public function customNamespaceLookupQueryProvider() |
||||
{ |
||||
return array( |
||||
'directory separator' => array( |
||||
DIRECTORY_SEPARATOR, |
||||
"/_custom_ns/dir", |
||||
array( |
||||
"stdClass.yml" => "Foo\\stdClass", |
||||
"sub/subClass.yml" => "Foo\\sub\\subClass", |
||||
"sub/subsub/subSubClass.yml" => "Foo\\sub\\subsub\\subSubClass", |
||||
) |
||||
), |
||||
'default dot separator' => array( |
||||
'.', |
||||
"/_custom_ns/dot", |
||||
array( |
||||
"stdClass.yml" => "Foo\\stdClass", |
||||
"sub.subClass.yml" => "Foo\\sub\\subClass", |
||||
"sub.subsub.subSubClass.yml" => "Foo\\sub\\subsub\\subSubClass", |
||||
) |
||||
), |
||||
); |
||||
} |
||||
|
||||
/** @dataProvider customNamespaceLookupQueryProvider |
||||
* @param $separator string Directory separator to test against |
||||
* @param $dir string Path to load mapping data from |
||||
* @param $files array Files to lookup classnames |
||||
* |
||||
* @throws \Doctrine\Common\Persistence\Mapping\MappingException |
||||
*/ |
||||
public function testFindMappingFileWithCustomNsSeparator($separator, $dir, $files) |
||||
{ |
||||
$path = __DIR__ . $dir; |
||||
$prefix = "Foo"; |
||||
|
||||
$locator = new SymfonyFileLocator(array($path => $prefix), ".yml", $separator); |
||||
|
||||
foreach ($files as $filePath => $className) { |
||||
$this->assertEquals(realpath($path .'/'. $filePath), realpath($locator->findMappingFile($className))); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
public function testFindMappingFile() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
$prefix = "Foo"; |
||||
|
||||
$locator = new SymfonyFileLocator(array($path => $prefix), ".yml"); |
||||
|
||||
$this->assertEquals(__DIR__ . "/_files/stdClass.yml", $locator->findMappingFile("Foo\\stdClass")); |
||||
} |
||||
|
||||
public function testFindMappingFileNotFound() |
||||
{ |
||||
$path = __DIR__ . "/_files"; |
||||
$prefix = "Foo"; |
||||
|
||||
$locator = new SymfonyFileLocator(array($path => $prefix), ".yml"); |
||||
|
||||
$this->setExpectedException( |
||||
"Doctrine\Common\Persistence\Mapping\MappingException", |
||||
"No mapping file found named '".__DIR__."/_files/stdClass2.yml' for class 'Foo\stdClass2'." |
||||
); |
||||
$locator->findMappingFile("Foo\\stdClass2"); |
||||
} |
||||
} |
||||
@ -0,0 +1 @@ |
||||
test |
||||
@ -0,0 +1 @@ |
||||
test |
||||
@ -0,0 +1 @@ |
||||
test |
||||
@ -0,0 +1 @@ |
||||
test |
||||
@ -0,0 +1 @@ |
||||
test |
||||
@ -0,0 +1 @@ |
||||
test |
||||
@ -0,0 +1 @@ |
||||
test |
||||
@ -0,0 +1,3 @@ |
||||
<?php |
||||
|
||||
$metadata->getFieldNames(); |
||||
@ -0,0 +1,17 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine; |
||||
|
||||
/** |
||||
* @Doctrine\Entity |
||||
*/ |
||||
class TestClass |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* @Annotation |
||||
*/ |
||||
class Entity |
||||
{ |
||||
} |
||||
@ -0,0 +1 @@ |
||||
test |
||||
@ -0,0 +1 @@ |
||||
test |
||||
@ -0,0 +1,60 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence; |
||||
|
||||
use Doctrine\Common\Persistence\ObjectManagerDecorator; |
||||
use Doctrine\Common\Persistence\ObjectManager; |
||||
|
||||
class NullObjectManagerDecorator extends ObjectManagerDecorator |
||||
{ |
||||
public function __construct(ObjectManager $wrapped) |
||||
{ |
||||
$this->wrapped = $wrapped; |
||||
} |
||||
} |
||||
|
||||
class ObjectManagerDecoratorTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
private $wrapped; |
||||
private $decorated; |
||||
|
||||
public function setUp() |
||||
{ |
||||
$this->wrapped = $this->getMock('Doctrine\Common\Persistence\ObjectManager'); |
||||
$this->decorated = new NullObjectManagerDecorator($this->wrapped); |
||||
} |
||||
|
||||
public function getMethodParameters() |
||||
{ |
||||
$class = new \ReflectionClass('Doctrine\Common\Persistence\ObjectManager'); |
||||
|
||||
$methods = array(); |
||||
foreach ($class->getMethods() as $method) { |
||||
if ($method->getNumberOfRequiredParameters() === 0) { |
||||
$methods[] = array($method->getName(), array()); |
||||
} elseif ($method->getNumberOfRequiredParameters() > 0) { |
||||
$methods[] = array($method->getName(), array_fill(0, $method->getNumberOfRequiredParameters(), 'req') ?: array()); |
||||
} |
||||
if ($method->getNumberOfParameters() != $method->getNumberOfRequiredParameters()) { |
||||
$methods[] = array($method->getName(), array_fill(0, $method->getNumberOfParameters(), 'all') ?: array()); |
||||
} |
||||
} |
||||
|
||||
return $methods; |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider getMethodParameters |
||||
*/ |
||||
public function testAllMethodCallsAreDelegatedToTheWrappedInstance($method, array $parameters) |
||||
{ |
||||
$stub = $this->wrapped |
||||
->expects($this->once()) |
||||
->method($method) |
||||
->will($this->returnValue('INNER VALUE FROM ' . $method)); |
||||
|
||||
call_user_func_array(array($stub, 'with'), $parameters); |
||||
|
||||
$this->assertSame('INNER VALUE FROM ' . $method, call_user_func_array(array($this->decorated, $method), $parameters)); |
||||
} |
||||
} |
||||
@ -0,0 +1,247 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Persistence; |
||||
|
||||
use Doctrine\Common\Persistence\PersistentObject; |
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata; |
||||
use Doctrine\Common\Persistence\Mapping\ReflectionService; |
||||
|
||||
/** |
||||
* @group DDC-1448 |
||||
*/ |
||||
class PersistentObjectTest extends \Doctrine\Tests\DoctrineTestCase |
||||
{ |
||||
private $cm; |
||||
private $om; |
||||
private $object; |
||||
|
||||
public function setUp() |
||||
{ |
||||
$this->cm = new TestObjectMetadata; |
||||
$this->om = $this->getMock('Doctrine\Common\Persistence\ObjectManager'); |
||||
$this->om->expects($this->any())->method('getClassMetadata') |
||||
->will($this->returnValue($this->cm)); |
||||
$this->object = new TestObject; |
||||
PersistentObject::setObjectManager($this->om); |
||||
$this->object->injectObjectManager($this->om, $this->cm); |
||||
} |
||||
|
||||
public function testGetObjectManager() |
||||
{ |
||||
$this->assertSame($this->om, PersistentObject::getObjectManager()); |
||||
} |
||||
|
||||
public function testNonMatchingObjectManager() |
||||
{ |
||||
$this->setExpectedException('RuntimeException'); |
||||
$om = $this->getMock('Doctrine\Common\Persistence\ObjectManager'); |
||||
$this->object->injectObjectManager($om, $this->cm); |
||||
} |
||||
|
||||
public function testGetField() |
||||
{ |
||||
$this->assertEquals('beberlei', $this->object->getName()); |
||||
} |
||||
|
||||
public function testSetField() |
||||
{ |
||||
$this->object->setName("test"); |
||||
$this->assertEquals("test", $this->object->getName()); |
||||
} |
||||
|
||||
public function testGetIdentifier() |
||||
{ |
||||
$this->assertEquals(1, $this->object->getId()); |
||||
} |
||||
|
||||
public function testSetIdentifier() |
||||
{ |
||||
$this->setExpectedException('BadMethodCallException'); |
||||
$this->object->setId(2); |
||||
} |
||||
|
||||
public function testSetUnknownField() |
||||
{ |
||||
$this->setExpectedException('BadMethodCallException'); |
||||
$this->object->setUnknown("test"); |
||||
} |
||||
|
||||
public function testGetUnknownField() |
||||
{ |
||||
$this->setExpectedException('BadMethodCallException'); |
||||
$this->object->getUnknown(); |
||||
} |
||||
|
||||
public function testGetToOneAssociation() |
||||
{ |
||||
$this->assertNull($this->object->getParent()); |
||||
} |
||||
|
||||
public function testSetToOneAssociation() |
||||
{ |
||||
$parent = new TestObject(); |
||||
$this->object->setParent($parent); |
||||
$this->assertSame($parent, $this->object->getParent($parent)); |
||||
} |
||||
|
||||
public function testSetInvalidToOneAssociation() |
||||
{ |
||||
$parent = new \stdClass(); |
||||
|
||||
$this->setExpectedException('InvalidArgumentException'); |
||||
$this->object->setParent($parent); |
||||
} |
||||
|
||||
public function testSetToOneAssociationNull() |
||||
{ |
||||
$parent = new TestObject(); |
||||
$this->object->setParent($parent); |
||||
$this->object->setParent(null); |
||||
$this->assertNull($this->object->getParent()); |
||||
} |
||||
|
||||
public function testAddToManyAssociation() |
||||
{ |
||||
$child = new TestObject(); |
||||
$this->object->addChildren($child); |
||||
|
||||
$this->assertSame($this->object, $child->getParent()); |
||||
$this->assertEquals(1, count($this->object->getChildren())); |
||||
|
||||
$child = new TestObject(); |
||||
$this->object->addChildren($child); |
||||
|
||||
$this->assertEquals(2, count($this->object->getChildren())); |
||||
} |
||||
|
||||
public function testAddInvalidToManyAssociation() |
||||
{ |
||||
$this->setExpectedException('InvalidArgumentException'); |
||||
$this->object->addChildren(new \stdClass()); |
||||
} |
||||
|
||||
public function testNoObjectManagerSet() |
||||
{ |
||||
PersistentObject::setObjectManager(null); |
||||
$child = new TestObject(); |
||||
|
||||
$this->setExpectedException('RuntimeException'); |
||||
$child->setName("test"); |
||||
} |
||||
|
||||
public function testInvalidMethod() |
||||
{ |
||||
$this->setExpectedException('BadMethodCallException'); |
||||
$this->object->asdf(); |
||||
} |
||||
|
||||
public function testAddInvalidCollection() |
||||
{ |
||||
$this->setExpectedException('BadMethodCallException'); |
||||
$this->object->addAsdf(new \stdClass()); |
||||
} |
||||
} |
||||
|
||||
class TestObject extends PersistentObject |
||||
{ |
||||
protected $id = 1; |
||||
protected $name = 'beberlei'; |
||||
protected $parent; |
||||
protected $children; |
||||
} |
||||
|
||||
class TestObjectMetadata implements ClassMetadata |
||||
{ |
||||
|
||||
public function getAssociationMappedByTargetField($assocName) |
||||
{ |
||||
$assoc = array('children' => 'parent'); |
||||
return $assoc[$assocName]; |
||||
} |
||||
|
||||
public function getAssociationNames() |
||||
{ |
||||
return array('parent', 'children'); |
||||
} |
||||
|
||||
public function getAssociationTargetClass($assocName) |
||||
{ |
||||
return __NAMESPACE__ . '\TestObject'; |
||||
} |
||||
|
||||
public function getFieldNames() |
||||
{ |
||||
return array('id', 'name'); |
||||
} |
||||
|
||||
public function getIdentifier() |
||||
{ |
||||
return array('id'); |
||||
} |
||||
|
||||
public function getName() |
||||
{ |
||||
return __NAMESPACE__ . '\TestObject'; |
||||
} |
||||
|
||||
public function getReflectionClass() |
||||
{ |
||||
return new \ReflectionClass($this->getName()); |
||||
} |
||||
|
||||
public function getTypeOfField($fieldName) |
||||
{ |
||||
$types = array('id' => 'integer', 'name' => 'string'); |
||||
return $types[$fieldName]; |
||||
} |
||||
|
||||
public function hasAssociation($fieldName) |
||||
{ |
||||
return in_array($fieldName, array('parent', 'children')); |
||||
} |
||||
|
||||
public function hasField($fieldName) |
||||
{ |
||||
return in_array($fieldName, array('id', 'name')); |
||||
} |
||||
|
||||
public function isAssociationInverseSide($assocName) |
||||
{ |
||||
return ($assocName === 'children'); |
||||
} |
||||
|
||||
public function isCollectionValuedAssociation($fieldName) |
||||
{ |
||||
return ($fieldName === 'children'); |
||||
} |
||||
|
||||
public function isIdentifier($fieldName) |
||||
{ |
||||
return $fieldName === 'id'; |
||||
} |
||||
|
||||
public function isSingleValuedAssociation($fieldName) |
||||
{ |
||||
return $fieldName === 'parent'; |
||||
} |
||||
|
||||
public function getIdentifierValues($entity) |
||||
{ |
||||
|
||||
} |
||||
|
||||
public function getIdentifierFieldNames() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public function initializeReflection(ReflectionService $reflService) |
||||
{ |
||||
|
||||
} |
||||
|
||||
public function wakeupReflection(ReflectionService $reflService) |
||||
{ |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,146 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
use Doctrine\Tests\DoctrineTestCase; |
||||
use Doctrine\Common\Proxy\ProxyDefinition; |
||||
|
||||
class AbstractProxyFactoryTest extends DoctrineTestCase |
||||
{ |
||||
public function testGenerateProxyClasses() |
||||
{ |
||||
$metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
$proxyGenerator = $this->getMock('Doctrine\Common\Proxy\ProxyGenerator', array(), array(), '', false); |
||||
|
||||
$proxyGenerator |
||||
->expects($this->once()) |
||||
->method('getProxyFileName'); |
||||
$proxyGenerator |
||||
->expects($this->once()) |
||||
->method('generateProxyClass'); |
||||
|
||||
$metadataFactory = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadataFactory'); |
||||
$proxyFactory = $this->getMockForAbstractClass( |
||||
'Doctrine\Common\Proxy\AbstractProxyFactory', |
||||
array($proxyGenerator, $metadataFactory, true) |
||||
); |
||||
|
||||
$proxyFactory |
||||
->expects($this->any()) |
||||
->method('skipClass') |
||||
->will($this->returnValue(false)); |
||||
|
||||
$generated = $proxyFactory->generateProxyClasses(array($metadata), sys_get_temp_dir()); |
||||
|
||||
$this->assertEquals(1, $generated, 'One proxy was generated'); |
||||
} |
||||
|
||||
public function testGetProxy() |
||||
{ |
||||
$metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
$proxy = $this->getMock('Doctrine\Common\Proxy\Proxy'); |
||||
$definition = new ProxyDefinition(get_class($proxy), array(), array(), null, null); |
||||
$proxyGenerator = $this->getMock('Doctrine\Common\Proxy\ProxyGenerator', array(), array(), '', false); |
||||
$metadataFactory = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadataFactory'); |
||||
|
||||
$metadataFactory |
||||
->expects($this->once()) |
||||
->method('getMetadataFor') |
||||
->will($this->returnValue($metadata)); |
||||
|
||||
$proxyFactory = $this->getMockForAbstractClass( |
||||
'Doctrine\Common\Proxy\AbstractProxyFactory', |
||||
array($proxyGenerator, $metadataFactory, true) |
||||
); |
||||
|
||||
$proxyFactory |
||||
->expects($this->any()) |
||||
->method('createProxyDefinition') |
||||
->will($this->returnValue($definition)); |
||||
|
||||
$generatedProxy = $proxyFactory->getProxy('Class', array('id' => 1)); |
||||
|
||||
$this->assertInstanceOf(get_class($proxy), $generatedProxy); |
||||
} |
||||
|
||||
public function testResetUnitializedProxy() |
||||
{ |
||||
$metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
$proxy = $this->getMock('Doctrine\Common\Proxy\Proxy'); |
||||
$definition = new ProxyDefinition(get_class($proxy), array(), array(), null, null); |
||||
$proxyGenerator = $this->getMock('Doctrine\Common\Proxy\ProxyGenerator', array(), array(), '', false); |
||||
$metadataFactory = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadataFactory'); |
||||
|
||||
$metadataFactory |
||||
->expects($this->once()) |
||||
->method('getMetadataFor') |
||||
->will($this->returnValue($metadata)); |
||||
|
||||
$proxyFactory = $this->getMockForAbstractClass( |
||||
'Doctrine\Common\Proxy\AbstractProxyFactory', |
||||
array($proxyGenerator, $metadataFactory, true) |
||||
); |
||||
|
||||
$proxyFactory |
||||
->expects($this->any()) |
||||
->method('createProxyDefinition') |
||||
->will($this->returnValue($definition)); |
||||
|
||||
$proxy |
||||
->expects($this->once()) |
||||
->method('__isInitialized') |
||||
->will($this->returnValue(false)); |
||||
$proxy |
||||
->expects($this->once()) |
||||
->method('__setInitializer'); |
||||
$proxy |
||||
->expects($this->once()) |
||||
->method('__setCloner'); |
||||
|
||||
$proxyFactory->resetUninitializedProxy($proxy); |
||||
} |
||||
|
||||
public function testDisallowsResettingInitializedProxy() |
||||
{ |
||||
$proxyFactory = $this->getMockForAbstractClass('Doctrine\Common\Proxy\AbstractProxyFactory', array(), '', false); |
||||
$proxy = $this->getMock('Doctrine\Common\Proxy\Proxy'); |
||||
|
||||
$proxy |
||||
->expects($this->any()) |
||||
->method('__isInitialized') |
||||
->will($this->returnValue(true)); |
||||
|
||||
$this->setExpectedException('Doctrine\Common\Proxy\Exception\InvalidArgumentException'); |
||||
|
||||
$proxyFactory->resetUninitializedProxy($proxy); |
||||
} |
||||
|
||||
public function testMissingPrimaryKeyValue() |
||||
{ |
||||
$metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
$proxy = $this->getMock('Doctrine\Common\Proxy\Proxy'); |
||||
$definition = new ProxyDefinition(get_class($proxy), array('missingKey'), array(), null, null); |
||||
$proxyGenerator = $this->getMock('Doctrine\Common\Proxy\ProxyGenerator', array(), array(), '', false); |
||||
$metadataFactory = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadataFactory'); |
||||
|
||||
$metadataFactory |
||||
->expects($this->once()) |
||||
->method('getMetadataFor') |
||||
->will($this->returnValue($metadata)); |
||||
|
||||
$proxyFactory = $this->getMockForAbstractClass( |
||||
'Doctrine\Common\Proxy\AbstractProxyFactory', |
||||
array($proxyGenerator, $metadataFactory, true) |
||||
); |
||||
|
||||
$proxyFactory |
||||
->expects($this->any()) |
||||
->method('createProxyDefinition') |
||||
->will($this->returnValue($definition)); |
||||
|
||||
$this->setExpectedException('\OutOfBoundsException'); |
||||
|
||||
$generatedProxy = $proxyFactory->getProxy('Class', array()); |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,72 @@ |
||||
<?php |
||||
/* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
* This software consists of voluntary contributions made by many individuals |
||||
* and is licensed under the MIT license. For more information, see |
||||
* <http://www.doctrine-project.org>. |
||||
*/ |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
use PHPUnit_Framework_TestCase; |
||||
use Doctrine\Common\Proxy\Autoloader; |
||||
|
||||
/** |
||||
* @group DDC-1698 |
||||
*/ |
||||
class AutoloaderTest extends PHPUnit_Framework_TestCase |
||||
{ |
||||
public static function dataResolveFile() |
||||
{ |
||||
return array( |
||||
array('/tmp', 'MyProxy', 'MyProxy\__CG__\RealClass', '/tmp' . DIRECTORY_SEPARATOR . '__CG__RealClass.php'), |
||||
array('/tmp', 'MyProxy\Subdir', 'MyProxy\Subdir\__CG__\RealClass', '/tmp' . DIRECTORY_SEPARATOR . '__CG__RealClass.php'), |
||||
array('/tmp', 'MyProxy', 'MyProxy\__CG__\Other\RealClass', '/tmp' . DIRECTORY_SEPARATOR . '__CG__OtherRealClass.php'), |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider dataResolveFile |
||||
*/ |
||||
public function testResolveFile($proxyDir, $proxyNamespace, $className, $expectedProxyFile) |
||||
{ |
||||
$actualProxyFile = Autoloader::resolveFile($proxyDir, $proxyNamespace, $className); |
||||
$this->assertEquals($expectedProxyFile, $actualProxyFile); |
||||
} |
||||
|
||||
public function testAutoload() |
||||
{ |
||||
if (file_exists(sys_get_temp_dir() ."/AutoloaderTestClass.php")) { |
||||
unlink(sys_get_temp_dir() ."/AutoloaderTestClass.php"); |
||||
} |
||||
|
||||
$autoloader = Autoloader::register(sys_get_temp_dir(), 'ProxyAutoloaderTest', function($proxyDir, $proxyNamespace, $className) { |
||||
file_put_contents(sys_get_temp_dir() . "/AutoloaderTestClass.php", "<?php namespace ProxyAutoloaderTest; class AutoloaderTestClass {} ");
|
||||
}); |
||||
|
||||
$this->assertTrue(class_exists('ProxyAutoloaderTest\AutoloaderTestClass', true)); |
||||
unlink(sys_get_temp_dir() ."/AutoloaderTestClass.php"); |
||||
} |
||||
|
||||
public function testRegisterWithInvalidCallback() |
||||
{ |
||||
$this->setExpectedException( |
||||
'Doctrine\Common\Proxy\Exception\InvalidArgumentException', |
||||
'Invalid \$notFoundCallback given: must be a callable, "stdClass" given' |
||||
); |
||||
|
||||
Autoloader::register('', '', new \stdClass()); |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,16 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset class |
||||
*/ |
||||
class CallableTypeHintClass |
||||
{ |
||||
/** |
||||
* @param callable $foo |
||||
*/ |
||||
public function call(callable $foo) |
||||
{ |
||||
} |
||||
} |
||||
@ -0,0 +1,16 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset class |
||||
*/ |
||||
class InvalidTypeHintClass |
||||
{ |
||||
/** |
||||
* @param InvalidHint (non existing class type hint) |
||||
*/ |
||||
public function invalidTypeHintMethod(InvalidHint $foo) |
||||
{ |
||||
} |
||||
} |
||||
@ -0,0 +1,115 @@ |
||||
<?php |
||||
/* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
* This software consists of voluntary contributions made by many individuals |
||||
* and is licensed under the MIT license. For more information, see |
||||
* <http://www.doctrine-project.org>. |
||||
*/ |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset representing a lazy loadable object |
||||
* |
||||
* @author Marco Pivetta <ocramius@gmail.com> |
||||
* @since 2.4 |
||||
*/ |
||||
class LazyLoadableObject |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $publicIdentifierField; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $protectedIdentifierField; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $publicTransientField = 'publicTransientFieldValue'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $protectedTransientField = 'protectedTransientFieldValue'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $publicPersistentField = 'publicPersistentFieldValue'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $protectedPersistentField = 'protectedPersistentFieldValue'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $publicAssociation = 'publicAssociationValue'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $protectedAssociation = 'protectedAssociationValue'; |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function getProtectedIdentifierField() |
||||
{ |
||||
return $this->protectedIdentifierField; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function testInitializationTriggeringMethod() |
||||
{ |
||||
return 'testInitializationTriggeringMethod'; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function getProtectedAssociation() |
||||
{ |
||||
return $this->protectedAssociation; |
||||
} |
||||
|
||||
/** |
||||
* @param \stdClass $param |
||||
*/ |
||||
public function publicTypeHintedMethod(\stdClass $param) |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public function &byRefMethod() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* @param mixed $thisIsNotByRef |
||||
* @param &mixed $thisIsByRef |
||||
*/ |
||||
public function byRefParamMethod($thisIsNotByRef, &$thisIsByRef) |
||||
{ |
||||
} |
||||
} |
||||
@ -0,0 +1,195 @@ |
||||
<?php |
||||
/* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
* This software consists of voluntary contributions made by many individuals |
||||
* and is licensed under the MIT license. For more information, see |
||||
* <http://www.doctrine-project.org>. |
||||
*/ |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
use ReflectionClass; |
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata; |
||||
|
||||
/** |
||||
* Class metadata test asset for @see LazyLoadableObject |
||||
* |
||||
* @author Marco Pivetta <ocramius@gmail.com> |
||||
* @since 2.4 |
||||
*/ |
||||
class LazyLoadableObjectClassMetadata implements ClassMetadata |
||||
{ |
||||
/** |
||||
* @var ReflectionClass |
||||
*/ |
||||
protected $reflectionClass; |
||||
|
||||
/** |
||||
* @var array |
||||
*/ |
||||
protected $identifier = array( |
||||
'publicIdentifierField' => true, |
||||
'protectedIdentifierField' => true, |
||||
); |
||||
|
||||
/** |
||||
* @var array |
||||
*/ |
||||
protected $fields = array( |
||||
'publicIdentifierField' => true, |
||||
'protectedIdentifierField' => true, |
||||
'publicPersistentField' => true, |
||||
'protectedPersistentField' => true, |
||||
); |
||||
|
||||
/** |
||||
* @var array |
||||
*/ |
||||
protected $associations = array( |
||||
'publicAssociation' => true, |
||||
'protectedAssociation' => true, |
||||
); |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return $this->getReflectionClass()->getName(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function getIdentifier() |
||||
{ |
||||
return array_keys($this->identifier); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function getReflectionClass() |
||||
{ |
||||
if (null === $this->reflectionClass) { |
||||
$this->reflectionClass = new \ReflectionClass(__NAMESPACE__ . '\LazyLoadableObject'); |
||||
} |
||||
|
||||
return $this->reflectionClass; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function isIdentifier($fieldName) |
||||
{ |
||||
return isset($this->identifier[$fieldName]); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function hasField($fieldName) |
||||
{ |
||||
return isset($this->fields[$fieldName]); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function hasAssociation($fieldName) |
||||
{ |
||||
return isset($this->associations[$fieldName]); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function isSingleValuedAssociation($fieldName) |
||||
{ |
||||
throw new \BadMethodCallException('not implemented'); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function isCollectionValuedAssociation($fieldName) |
||||
{ |
||||
throw new \BadMethodCallException('not implemented'); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function getFieldNames() |
||||
{ |
||||
return array_keys($this->fields); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function getIdentifierFieldNames() |
||||
{ |
||||
return $this->getIdentifier(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function getAssociationNames() |
||||
{ |
||||
return array_keys($this->associations); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function getTypeOfField($fieldName) |
||||
{ |
||||
return 'string'; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function getAssociationTargetClass($assocName) |
||||
{ |
||||
throw new \BadMethodCallException('not implemented'); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function isAssociationInverseSide($assocName) |
||||
{ |
||||
throw new \BadMethodCallException('not implemented'); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function getAssociationMappedByTargetField($assocName) |
||||
{ |
||||
throw new \BadMethodCallException('not implemented'); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function getIdentifierValues($object) |
||||
{ |
||||
throw new \BadMethodCallException('not implemented'); |
||||
} |
||||
} |
||||
@ -0,0 +1,37 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset class |
||||
*/ |
||||
class MagicCloneClass |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $id = 'id'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $publicField = 'publicField'; |
||||
|
||||
/** |
||||
* @var boolean |
||||
*/ |
||||
public $cloned = false; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $clonedValue = 'defaultValue'; |
||||
|
||||
/** |
||||
* @return void |
||||
*/ |
||||
public function __clone() |
||||
{ |
||||
$this->clonedValue = 'newClonedValue'; |
||||
} |
||||
} |
||||
@ -0,0 +1,51 @@ |
||||
<?php |
||||
/* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
* This software consists of voluntary contributions made by many individuals |
||||
* and is licensed under the MIT license. For more information, see |
||||
* <http://www.doctrine-project.org>. |
||||
*/ |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
use InvalidArgumentException; |
||||
|
||||
/** |
||||
* Test asset class |
||||
* |
||||
* @since 2.4 |
||||
*/ |
||||
class MagicGetByRefClass |
||||
{ |
||||
/** |
||||
* @var mixed |
||||
*/ |
||||
public $valueField; |
||||
|
||||
/** |
||||
* @param string $name |
||||
* |
||||
* @return mixed |
||||
* |
||||
* @throws \InvalidArgumentException |
||||
*/ |
||||
public function & __get($name) |
||||
{ |
||||
if ($name === 'value') { |
||||
return $this->valueField; |
||||
} |
||||
|
||||
throw new InvalidArgumentException(); |
||||
} |
||||
} |
||||
@ -0,0 +1,38 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset class |
||||
*/ |
||||
class MagicGetClass |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $id = 'id'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $publicField = 'publicField'; |
||||
|
||||
/** |
||||
* @param $name |
||||
* |
||||
* @return string |
||||
* @throws \BadMethodCallException |
||||
*/ |
||||
public function __get($name) |
||||
{ |
||||
if ($name === 'test') { |
||||
return 'test'; |
||||
} |
||||
|
||||
if ($name === 'publicField' || $name === 'id') { |
||||
throw new \BadMethodCallException('Should never be called for "publicField" or "id"'); |
||||
} |
||||
|
||||
return 'not defined'; |
||||
} |
||||
} |
||||
@ -0,0 +1,38 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset class |
||||
*/ |
||||
class MagicIssetClass |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $id = 'id'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $publicField = 'publicField'; |
||||
|
||||
/** |
||||
* @param string $name |
||||
* |
||||
* @return bool |
||||
* @throws \BadMethodCallException |
||||
*/ |
||||
public function __isset($name) |
||||
{ |
||||
if ('test' === $name) { |
||||
return true; |
||||
} |
||||
|
||||
if ('publicField' === $name || 'id' === $name) { |
||||
throw new \BadMethodCallException('Should never be called for "publicField" or "id"'); |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
} |
||||
@ -0,0 +1,43 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset class |
||||
*/ |
||||
class MagicSetClass |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $id = 'id'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $publicField = 'publicField'; |
||||
|
||||
/** |
||||
* @var string|null |
||||
*/ |
||||
public $testAttribute; |
||||
|
||||
/** |
||||
* @param string $name |
||||
* @param mixed $value |
||||
* |
||||
* @throws \BadMethodCallException |
||||
*/ |
||||
public function __set($name, $value) |
||||
{ |
||||
if ($name === 'test') { |
||||
$this->testAttribute = $value; |
||||
} |
||||
|
||||
if ($name === 'publicField' || $name === 'id') { |
||||
throw new \BadMethodCallException('Should never be called for "publicField" or "id"'); |
||||
} |
||||
|
||||
$this->testAttribute = $value; |
||||
} |
||||
} |
||||
@ -0,0 +1,37 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset class |
||||
*/ |
||||
class MagicSleepClass |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $id = 'id'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $publicField = 'publicField'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $serializedField = 'defaultValue'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $nonSerializedField = 'defaultValue'; |
||||
|
||||
/** |
||||
* @return array |
||||
*/ |
||||
public function __sleep() |
||||
{ |
||||
return array('serializedField'); |
||||
} |
||||
} |
||||
@ -0,0 +1,32 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset class |
||||
*/ |
||||
class MagicWakeupClass |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $id = 'id'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $publicField = 'publicField'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $wakeupValue = 'defaultValue'; |
||||
|
||||
/** |
||||
* @return void |
||||
*/ |
||||
public function __wakeup() |
||||
{ |
||||
$this->wakeupValue = 'newWakeupValue'; |
||||
} |
||||
} |
||||
@ -0,0 +1,249 @@ |
||||
<?php |
||||
/* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
* This software consists of voluntary contributions made by many individuals |
||||
* and is licensed under the MIT license. For more information, see |
||||
* <http://www.doctrine-project.org>. |
||||
*/ |
||||
|
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
use Doctrine\Common\Proxy\ProxyGenerator; |
||||
use ReflectionClass; |
||||
use ReflectionMethod; |
||||
use PHPUnit_Framework_TestCase; |
||||
|
||||
/** |
||||
* Test the proxy generator. Its work is generating on-the-fly subclasses of a given model, which implement the Proxy |
||||
* pattern. |
||||
* |
||||
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com> |
||||
* @author Marco Pivetta <ocramius@gmail.com> |
||||
*/ |
||||
class ProxyClassGeneratorTest extends PHPUnit_Framework_TestCase |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
protected $proxyClass = 'Doctrine\Tests\Common\ProxyProxy\__CG__\Doctrine\Tests\Common\Proxy\LazyLoadableObject'; |
||||
|
||||
/** |
||||
* @var LazyLoadableObjectClassMetadata |
||||
*/ |
||||
protected $metadata; |
||||
|
||||
/** |
||||
* @var ProxyGenerator |
||||
*/ |
||||
protected $proxyGenerator; |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
protected function setUp() |
||||
{ |
||||
$this->metadata = new LazyLoadableObjectClassMetadata(); |
||||
$this->proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); |
||||
|
||||
if (class_exists($this->proxyClass, false)) { |
||||
return; |
||||
} |
||||
|
||||
$this->generateAndRequire($this->proxyGenerator, $this->metadata); |
||||
} |
||||
|
||||
public function testReferenceProxyRespectsMethodsParametersTypeHinting() |
||||
{ |
||||
$method = new ReflectionMethod($this->proxyClass, 'publicTypeHintedMethod'); |
||||
$params = $method->getParameters(); |
||||
|
||||
$this->assertEquals(1, count($params)); |
||||
$this->assertEquals('stdClass', $params[0]->getClass()->getName()); |
||||
} |
||||
|
||||
public function testProxyRespectsMethodsWhichReturnValuesByReference() |
||||
{ |
||||
$method = new ReflectionMethod($this->proxyClass, 'byRefMethod'); |
||||
|
||||
$this->assertTrue($method->returnsReference()); |
||||
} |
||||
|
||||
public function testProxyRespectsByRefMethodParameters() |
||||
{ |
||||
$method = new ReflectionMethod($this->proxyClass, 'byRefParamMethod'); |
||||
$parameters = $method->getParameters(); |
||||
$this->assertSame('thisIsNotByRef', $parameters[0]->getName()); |
||||
$this->assertFalse($parameters[0]->isPassedByReference()); |
||||
$this->assertSame('thisIsByRef', $parameters[1]->getName()); |
||||
$this->assertTrue($parameters[1]->isPassedByReference()); |
||||
} |
||||
|
||||
public function testCreatesAssociationProxyAsSubclassOfTheOriginalOne() |
||||
{ |
||||
$this->assertTrue(is_subclass_of($this->proxyClass, $this->metadata->getName())); |
||||
} |
||||
|
||||
public function testNonNamespacedProxyGeneration() |
||||
{ |
||||
$classCode = file_get_contents($this->proxyGenerator->getProxyFileName($this->metadata->getName())); |
||||
|
||||
$this->assertNotContains("class LazyLoadableObject extends \\\\" . $this->metadata->getName(), $classCode); |
||||
$this->assertContains("class LazyLoadableObject extends \\" . $this->metadata->getName(), $classCode); |
||||
} |
||||
|
||||
public function testClassWithSleepProxyGeneration() |
||||
{ |
||||
if (!class_exists('Doctrine\Tests\Common\ProxyProxy\__CG__\SleepClass', false)) { |
||||
$className = 'Doctrine\Tests\Common\Proxy\SleepClass'; |
||||
$metadata = $this->createClassMetadata($className, array('id')); |
||||
$proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); |
||||
|
||||
$this->generateAndRequire($proxyGenerator, $metadata); |
||||
} |
||||
|
||||
$classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxySleepClass.php'); |
||||
$this->assertEquals(1, substr_count($classCode, 'function __sleep')); |
||||
$this->assertEquals(1, substr_count($classCode, 'parent::__sleep()')); |
||||
} |
||||
|
||||
/** |
||||
* Check that the proxy doesn't serialize static properties (in __sleep() method) |
||||
* @group DCOM-212 |
||||
*/ |
||||
public function testClassWithStaticPropertyProxyGeneration() |
||||
{ |
||||
if (!class_exists('Doctrine\Tests\Common\ProxyProxy\__CG__\StaticPropertyClass', false)) { |
||||
$className = 'Doctrine\Tests\Common\Proxy\StaticPropertyClass'; |
||||
$metadata = $this->createClassMetadata($className, array()); |
||||
$proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); |
||||
|
||||
$this->generateAndRequire($proxyGenerator, $metadata); |
||||
} |
||||
|
||||
$classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxyStaticPropertyClass.php'); |
||||
$this->assertEquals(1, substr_count($classCode, 'function __sleep')); |
||||
$this->assertNotContains('protectedStaticProperty', $classCode); |
||||
} |
||||
|
||||
private function generateAndRequire($proxyGenerator, $metadata) |
||||
{ |
||||
$proxyGenerator->generateProxyClass($metadata, $proxyGenerator->getProxyFileName($metadata->getName())); |
||||
|
||||
require_once $proxyGenerator->getProxyFileName($metadata->getName()); |
||||
} |
||||
|
||||
public function testClassWithCallableTypeHintOnProxiedMethod() |
||||
{ |
||||
if (PHP_VERSION_ID < 50400) { |
||||
$this->markTestSkipped('`callable` is only supported in PHP >=5.4.0'); |
||||
} |
||||
|
||||
if (!class_exists('Doctrine\Tests\Common\ProxyProxy\__CG__\CallableTypeHintClass', false)) { |
||||
$className = 'Doctrine\Tests\Common\Proxy\CallableTypeHintClass'; |
||||
$metadata = $this->createClassMetadata($className, array('id')); |
||||
|
||||
$proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); |
||||
$this->generateAndRequire($proxyGenerator, $metadata); |
||||
} |
||||
|
||||
$classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxyCallableTypeHintClass.php'); |
||||
|
||||
$this->assertEquals(1, substr_count($classCode, 'call(callable $foo)')); |
||||
} |
||||
|
||||
public function testClassWithVariadicArgumentOnProxiedMethod() |
||||
{ |
||||
if (PHP_VERSION_ID < 50600) { |
||||
$this->markTestSkipped('`...` is only supported in PHP >=5.6.0'); |
||||
} |
||||
|
||||
if (!class_exists('Doctrine\Tests\Common\ProxyProxy\__CG__\VariadicTypeHintClass', false)) { |
||||
$className = 'Doctrine\Tests\Common\Proxy\VariadicTypeHintClass'; |
||||
$metadata = $this->createClassMetadata($className, array('id')); |
||||
|
||||
$proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); |
||||
$this->generateAndRequire($proxyGenerator, $metadata); |
||||
} |
||||
|
||||
$classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxyVariadicTypeHintClass.php'); |
||||
|
||||
$this->assertEquals(1, substr_count($classCode, 'function addType(...$types)')); |
||||
$this->assertEquals(1, substr_count($classCode, '__invoke($this, \'addType\', array($types))')); |
||||
$this->assertEquals(1, substr_count($classCode, 'parent::addType(...$types)')); |
||||
} |
||||
|
||||
public function testClassWithInvalidTypeHintOnProxiedMethod() |
||||
{ |
||||
$className = 'Doctrine\Tests\Common\Proxy\InvalidTypeHintClass'; |
||||
$metadata = $this->createClassMetadata($className, array('id')); |
||||
$proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); |
||||
|
||||
$this->setExpectedException( |
||||
'Doctrine\Common\Proxy\Exception\UnexpectedValueException', |
||||
'The type hint of parameter "foo" in method "invalidTypeHintMethod"' |
||||
.' in class "' . $className . '" is invalid.' |
||||
); |
||||
$proxyGenerator->generateProxyClass($metadata); |
||||
} |
||||
|
||||
public function testNoConfigDirThrowsException() |
||||
{ |
||||
$this->setExpectedException('Doctrine\Common\Proxy\Exception\InvalidArgumentException'); |
||||
new ProxyGenerator(null, null); |
||||
} |
||||
|
||||
public function testNoNamespaceThrowsException() |
||||
{ |
||||
$this->setExpectedException('Doctrine\Common\Proxy\Exception\InvalidArgumentException'); |
||||
new ProxyGenerator(__DIR__ . '/generated', null); |
||||
} |
||||
|
||||
public function testInvalidPlaceholderThrowsException() |
||||
{ |
||||
$this->setExpectedException('Doctrine\Common\Proxy\Exception\InvalidArgumentException'); |
||||
$generator = new ProxyGenerator(__DIR__ . '/generated', 'SomeNamespace'); |
||||
$generator->setPlaceholder('<somePlaceholder>', array()); |
||||
} |
||||
|
||||
public function testUseEvalIfNoFilenameIsGiven() |
||||
{ |
||||
$proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); |
||||
|
||||
$className = __NAMESPACE__ . '\\EvalBase'; |
||||
|
||||
$metadata = $this->createClassMetadata($className, array('id')); |
||||
|
||||
$proxyGenerator->generateProxyClass($metadata); |
||||
|
||||
$reflClass = new ReflectionClass('Doctrine\Tests\Common\ProxyProxy\__CG__\Doctrine\Tests\Common\Proxy\EvalBase'); |
||||
|
||||
$this->assertContains("eval()'d code", $reflClass->getFileName()); |
||||
} |
||||
|
||||
private function createClassMetadata($className, array $ids) |
||||
{ |
||||
$metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
$reflClass = new ReflectionClass($className); |
||||
$metadata->expects($this->any())->method('getReflectionClass')->will($this->returnValue($reflClass)); |
||||
$metadata->expects($this->any())->method('getIdentifierFieldNames')->will($this->returnValue($ids)); |
||||
$metadata->expects($this->any())->method('getName')->will($this->returnValue($className)); |
||||
|
||||
return $metadata; |
||||
} |
||||
} |
||||
|
||||
class EvalBase |
||||
{ |
||||
} |
||||
@ -0,0 +1,752 @@ |
||||
<?php |
||||
/* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
* This software consists of voluntary contributions made by many individuals |
||||
* and is licensed under the MIT license. For more information, see |
||||
* <http://www.doctrine-project.org>. |
||||
*/ |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
use Doctrine\Common\Proxy\ProxyGenerator; |
||||
use Doctrine\Common\Proxy\Proxy; |
||||
use Doctrine\Common\Proxy\Exception\UnexpectedValueException; |
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata; |
||||
use PHPUnit_Framework_TestCase; |
||||
|
||||
/** |
||||
* Test the generated proxies behavior. These tests make assumptions about the structure of LazyLoadableObject |
||||
* |
||||
* @author Marco Pivetta <ocramius@gmail.com> |
||||
*/ |
||||
class ProxyLogicTest extends PHPUnit_Framework_TestCase |
||||
{ |
||||
/** |
||||
* @var \PHPUnit_Framework_MockObject_MockObject |
||||
*/ |
||||
protected $proxyLoader; |
||||
|
||||
/** |
||||
* @var ClassMetadata |
||||
*/ |
||||
protected $lazyLoadableObjectMetadata; |
||||
|
||||
/** |
||||
* @var LazyLoadableObject|Proxy |
||||
*/ |
||||
protected $lazyObject; |
||||
|
||||
protected $identifier = array( |
||||
'publicIdentifierField' => 'publicIdentifierFieldValue', |
||||
'protectedIdentifierField' => 'protectedIdentifierFieldValue', |
||||
); |
||||
|
||||
/** |
||||
* @var \PHPUnit_Framework_MockObject_MockObject|Callable |
||||
*/ |
||||
protected $initializerCallbackMock; |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function setUp() |
||||
{ |
||||
$this->proxyLoader = $loader = $this->getMock('stdClass', array('load'), array(), '', false); |
||||
$this->initializerCallbackMock = $this->getMock('stdClass', array('__invoke')); |
||||
$identifier = $this->identifier; |
||||
$this->lazyLoadableObjectMetadata = $metadata = new LazyLoadableObjectClassMetadata(); |
||||
|
||||
// emulating what should happen in a proxy factory |
||||
$cloner = function (LazyLoadableObject $proxy) use ($loader, $identifier, $metadata) { |
||||
/* @var $proxy LazyLoadableObject|Proxy */ |
||||
if ($proxy->__isInitialized()) { |
||||
return; |
||||
} |
||||
|
||||
$proxy->__setInitialized(true); |
||||
$proxy->__setInitializer(null); |
||||
$original = $loader->load($identifier); |
||||
|
||||
if (null === $original) { |
||||
throw new UnexpectedValueException(); |
||||
} |
||||
|
||||
foreach ($metadata->getReflectionClass()->getProperties() as $reflProperty) { |
||||
$propertyName = $reflProperty->getName(); |
||||
|
||||
if ($metadata->hasField($propertyName) || $metadata->hasAssociation($propertyName)) { |
||||
$reflProperty->setAccessible(true); |
||||
$reflProperty->setValue($proxy, $reflProperty->getValue($original)); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
$proxyClassName = 'Doctrine\Tests\Common\ProxyProxy\__CG__\Doctrine\Tests\Common\Proxy\LazyLoadableObject'; |
||||
|
||||
// creating the proxy class |
||||
if (!class_exists($proxyClassName, false)) { |
||||
$proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); |
||||
$proxyGenerator->generateProxyClass($metadata); |
||||
require_once $proxyGenerator->getProxyFileName($metadata->getName()); |
||||
} |
||||
|
||||
$this->lazyObject = new $proxyClassName($this->getClosure($this->initializerCallbackMock), $cloner); |
||||
|
||||
// setting identifiers in the proxy via reflection |
||||
foreach ($metadata->getIdentifierFieldNames() as $idField) { |
||||
$prop = $metadata->getReflectionClass()->getProperty($idField); |
||||
$prop->setAccessible(true); |
||||
$prop->setValue($this->lazyObject, $identifier[$idField]); |
||||
} |
||||
|
||||
$this->assertFalse($this->lazyObject->__isInitialized()); |
||||
} |
||||
|
||||
public function testFetchingPublicIdentifierDoesNotCauseLazyLoading() |
||||
{ |
||||
$this->configureInitializerMock(0); |
||||
|
||||
$this->assertSame('publicIdentifierFieldValue', $this->lazyObject->publicIdentifierField); |
||||
} |
||||
|
||||
public function testFetchingIdentifiersViaPublicGetterDoesNotCauseLazyLoading() |
||||
{ |
||||
$this->configureInitializerMock(0); |
||||
|
||||
$this->assertSame('protectedIdentifierFieldValue', $this->lazyObject->getProtectedIdentifierField()); |
||||
} |
||||
|
||||
public function testCallingMethodCausesLazyLoading() |
||||
{ |
||||
$this->configureInitializerMock( |
||||
1, |
||||
array($this->lazyObject, 'testInitializationTriggeringMethod', array()), |
||||
function (Proxy $proxy) { |
||||
$proxy->__setInitializer(null); |
||||
} |
||||
); |
||||
|
||||
$this->lazyObject->testInitializationTriggeringMethod(); |
||||
$this->lazyObject->testInitializationTriggeringMethod(); |
||||
} |
||||
|
||||
public function testFetchingPublicFieldsCausesLazyLoading() |
||||
{ |
||||
$test = $this; |
||||
$this->configureInitializerMock( |
||||
1, |
||||
array($this->lazyObject, '__get', array('publicPersistentField')), |
||||
function () use ($test) { |
||||
$test->setProxyValue('publicPersistentField', 'loadedValue'); |
||||
} |
||||
); |
||||
|
||||
$this->assertSame('loadedValue', $this->lazyObject->publicPersistentField); |
||||
$this->assertSame('loadedValue', $this->lazyObject->publicPersistentField); |
||||
} |
||||
|
||||
public function testFetchingPublicAssociationCausesLazyLoading() |
||||
{ |
||||
$test = $this; |
||||
$this->configureInitializerMock( |
||||
1, |
||||
array($this->lazyObject, '__get', array('publicAssociation')), |
||||
function () use ($test) { |
||||
$test->setProxyValue('publicAssociation', 'loadedAssociation'); |
||||
} |
||||
); |
||||
|
||||
$this->assertSame('loadedAssociation', $this->lazyObject->publicAssociation); |
||||
$this->assertSame('loadedAssociation', $this->lazyObject->publicAssociation); |
||||
} |
||||
|
||||
public function testFetchingProtectedAssociationViaPublicGetterCausesLazyLoading() |
||||
{ |
||||
$this->configureInitializerMock( |
||||
1, |
||||
array($this->lazyObject, 'getProtectedAssociation', array()), |
||||
function (Proxy $proxy) { |
||||
$proxy->__setInitializer(null); |
||||
} |
||||
); |
||||
|
||||
$this->assertSame('protectedAssociationValue', $this->lazyObject->getProtectedAssociation()); |
||||
$this->assertSame('protectedAssociationValue', $this->lazyObject->getProtectedAssociation()); |
||||
} |
||||
|
||||
public function testLazyLoadingTriggeredOnlyAtFirstPublicPropertyRead() |
||||
{ |
||||
$test = $this; |
||||
$this->configureInitializerMock( |
||||
1, |
||||
array($this->lazyObject, '__get', array('publicPersistentField')), |
||||
function () use ($test) { |
||||
$test->setProxyValue('publicPersistentField', 'loadedValue'); |
||||
$test->setProxyValue('publicAssociation', 'publicAssociationValue'); |
||||
} |
||||
); |
||||
|
||||
$this->assertSame('loadedValue', $this->lazyObject->publicPersistentField); |
||||
$this->assertSame('publicAssociationValue', $this->lazyObject->publicAssociation); |
||||
} |
||||
|
||||
public function testNoticeWhenReadingNonExistentPublicProperties() |
||||
{ |
||||
$this->configureInitializerMock(0); |
||||
|
||||
$class = get_class($this->lazyObject); |
||||
$this->setExpectedException( |
||||
'PHPUnit_Framework_Error_Notice', |
||||
'Undefined property: ' . $class . '::$non_existing_property' |
||||
); |
||||
|
||||
$this->lazyObject->non_existing_property; |
||||
} |
||||
|
||||
public function testFalseWhenCheckingNonExistentProperty() |
||||
{ |
||||
$this->configureInitializerMock(0); |
||||
|
||||
$this->assertFalse(isset($this->lazyObject->non_existing_property)); |
||||
} |
||||
|
||||
public function testNoErrorWhenSettingNonExistentProperty() |
||||
{ |
||||
$this->configureInitializerMock(0); |
||||
|
||||
$this->lazyObject->non_existing_property = 'now has a value'; |
||||
$this->assertSame('now has a value', $this->lazyObject->non_existing_property); |
||||
} |
||||
|
||||
public function testCloningCallsClonerWithClonedObject() |
||||
{ |
||||
$lazyObject = $this->lazyObject; |
||||
$test = $this; |
||||
$cb = $this->getMock('stdClass', array('cb')); |
||||
$cb |
||||
->expects($this->once()) |
||||
->method('cb') |
||||
->will($this->returnCallback(function (LazyLoadableObject $proxy) use ($lazyObject, $test) { |
||||
/* @var $proxy LazyLoadableObject|Proxy */ |
||||
$test->assertNotSame($proxy, $lazyObject); |
||||
$proxy->__setInitializer(null); |
||||
$proxy->publicAssociation = 'clonedAssociation'; |
||||
})); |
||||
|
||||
$this->lazyObject->__setCloner($this->getClosure(array($cb, 'cb'))); |
||||
|
||||
$cloned = clone $this->lazyObject; |
||||
$this->assertSame('clonedAssociation', $cloned->publicAssociation); |
||||
$this->assertNotSame($cloned, $lazyObject, 'a clone of the lazy object is retrieved'); |
||||
} |
||||
|
||||
public function testFetchingTransientPropertiesWillNotTriggerLazyLoading() |
||||
{ |
||||
$this->configureInitializerMock(0); |
||||
|
||||
$this->assertSame( |
||||
'publicTransientFieldValue', |
||||
$this->lazyObject->publicTransientField, |
||||
'fetching public transient field won\'t trigger lazy loading' |
||||
); |
||||
$property = $this |
||||
->lazyLoadableObjectMetadata |
||||
->getReflectionClass() |
||||
->getProperty('protectedTransientField'); |
||||
$property->setAccessible(true); |
||||
$this->assertSame( |
||||
'protectedTransientFieldValue', |
||||
$property->getValue($this->lazyObject), |
||||
'fetching protected transient field via reflection won\'t trigger lazy loading' |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Provided to guarantee backwards compatibility |
||||
*/ |
||||
public function testLoadProxyMethod() |
||||
{ |
||||
$this->configureInitializerMock(2, array($this->lazyObject, '__load', array())); |
||||
|
||||
$this->lazyObject->__load(); |
||||
$this->lazyObject->__load(); |
||||
} |
||||
|
||||
public function testLoadingWithPersisterWillBeTriggeredOnlyOnce() |
||||
{ |
||||
$this |
||||
->proxyLoader |
||||
->expects($this->once()) |
||||
->method('load') |
||||
->with( |
||||
array( |
||||
'publicIdentifierField' => 'publicIdentifierFieldValue', |
||||
'protectedIdentifierField' => 'protectedIdentifierFieldValue', |
||||
), |
||||
$this->lazyObject |
||||
) |
||||
->will($this->returnCallback(function ($id, LazyLoadableObject $lazyObject) { |
||||
// setting a value to verify that the persister can actually set something in the object |
||||
$lazyObject->publicAssociation = $id['publicIdentifierField'] . '-test'; |
||||
return true; |
||||
})); |
||||
$this->lazyObject->__setInitializer($this->getSuggestedInitializerImplementation()); |
||||
|
||||
$this->lazyObject->__load(); |
||||
$this->lazyObject->__load(); |
||||
$this->assertSame('publicIdentifierFieldValue-test', $this->lazyObject->publicAssociation); |
||||
} |
||||
|
||||
public function testFailedLoadingWillThrowException() |
||||
{ |
||||
$this->proxyLoader->expects($this->any())->method('load')->will($this->returnValue(null)); |
||||
$this->setExpectedException('UnexpectedValueException'); |
||||
$this->lazyObject->__setInitializer($this->getSuggestedInitializerImplementation()); |
||||
|
||||
$this->lazyObject->__load(); |
||||
} |
||||
|
||||
public function testCloningWithPersister() |
||||
{ |
||||
$this->lazyObject->publicTransientField = 'should-not-change'; |
||||
$this |
||||
->proxyLoader |
||||
->expects($this->exactly(2)) |
||||
->method('load') |
||||
->with(array( |
||||
'publicIdentifierField' => 'publicIdentifierFieldValue', |
||||
'protectedIdentifierField' => 'protectedIdentifierFieldValue', |
||||
)) |
||||
->will($this->returnCallback(function () { |
||||
$blueprint = new LazyLoadableObject(); |
||||
$blueprint->publicPersistentField = 'checked-persistent-field'; |
||||
$blueprint->publicAssociation = 'checked-association-field'; |
||||
$blueprint->publicTransientField = 'checked-transient-field'; |
||||
|
||||
return $blueprint; |
||||
})); |
||||
|
||||
$firstClone = clone $this->lazyObject; |
||||
$this->assertSame( |
||||
'checked-persistent-field', |
||||
$firstClone->publicPersistentField, |
||||
'Persistent fields are cloned correctly' |
||||
); |
||||
$this->assertSame( |
||||
'checked-association-field', |
||||
$firstClone->publicAssociation, |
||||
'Associations are cloned correctly' |
||||
); |
||||
$this->assertSame( |
||||
'should-not-change', |
||||
$firstClone->publicTransientField, |
||||
'Transient fields are not overwritten' |
||||
); |
||||
|
||||
$secondClone = clone $this->lazyObject; |
||||
$this->assertSame( |
||||
'checked-persistent-field', |
||||
$secondClone->publicPersistentField, |
||||
'Persistent fields are cloned correctly' |
||||
); |
||||
$this->assertSame( |
||||
'checked-association-field', |
||||
$secondClone->publicAssociation, |
||||
'Associations are cloned correctly' |
||||
); |
||||
$this->assertSame( |
||||
'should-not-change', |
||||
$secondClone->publicTransientField, |
||||
'Transient fields are not overwritten' |
||||
); |
||||
|
||||
// those should not trigger lazy loading |
||||
$firstClone->__load(); |
||||
$secondClone->__load(); |
||||
} |
||||
|
||||
public function testNotInitializedProxyUnserialization() |
||||
{ |
||||
$this->configureInitializerMock(); |
||||
|
||||
$serialized = serialize($this->lazyObject); |
||||
/* @var $unserialized LazyLoadableObject|Proxy */ |
||||
$unserialized = unserialize($serialized); |
||||
$reflClass = $this->lazyLoadableObjectMetadata->getReflectionClass(); |
||||
|
||||
$this->assertFalse($unserialized->__isInitialized(), 'serialization didn\'t cause intialization'); |
||||
|
||||
// Checking identifiers |
||||
$this->assertSame('publicIdentifierFieldValue', $unserialized->publicIdentifierField, 'identifiers are kept'); |
||||
$protectedIdentifierField = $reflClass->getProperty('protectedIdentifierField'); |
||||
$protectedIdentifierField->setAccessible(true); |
||||
$this->assertSame( |
||||
'protectedIdentifierFieldValue', |
||||
$protectedIdentifierField->getValue($unserialized), |
||||
'identifiers are kept' |
||||
); |
||||
|
||||
// Checking transient fields |
||||
$this->assertSame( |
||||
'publicTransientFieldValue', |
||||
$unserialized->publicTransientField, |
||||
'transient fields are kept' |
||||
); |
||||
$protectedTransientField = $reflClass->getProperty('protectedTransientField'); |
||||
$protectedTransientField->setAccessible(true); |
||||
$this->assertSame( |
||||
'protectedTransientFieldValue', |
||||
$protectedTransientField->getValue($unserialized), |
||||
'transient fields are kept' |
||||
); |
||||
|
||||
// Checking persistent fields |
||||
$this->assertSame( |
||||
'publicPersistentFieldValue', |
||||
$unserialized->publicPersistentField, |
||||
'persistent fields are kept' |
||||
); |
||||
$protectedPersistentField = $reflClass->getProperty('protectedPersistentField'); |
||||
$protectedPersistentField->setAccessible(true); |
||||
$this->assertSame( |
||||
'protectedPersistentFieldValue', |
||||
$protectedPersistentField->getValue($unserialized), |
||||
'persistent fields are kept' |
||||
); |
||||
|
||||
// Checking associations |
||||
$this->assertSame('publicAssociationValue', $unserialized->publicAssociation, 'associations are kept'); |
||||
$protectedAssociationField = $reflClass->getProperty('protectedAssociation'); |
||||
$protectedAssociationField->setAccessible(true); |
||||
$this->assertSame( |
||||
'protectedAssociationValue', |
||||
$protectedAssociationField->getValue($unserialized), |
||||
'associations are kept' |
||||
); |
||||
} |
||||
|
||||
public function testInitializedProxyUnserialization() |
||||
{ |
||||
// persister will retrieve the lazy object itself, so that we don't have to re-define all field values |
||||
$this->proxyLoader->expects($this->once())->method('load')->will($this->returnValue($this->lazyObject)); |
||||
$this->lazyObject->__setInitializer($this->getSuggestedInitializerImplementation()); |
||||
$this->lazyObject->__load(); |
||||
|
||||
$serialized = serialize($this->lazyObject); |
||||
$reflClass = $this->lazyLoadableObjectMetadata->getReflectionClass(); |
||||
/* @var $unserialized LazyLoadableObject|Proxy */ |
||||
$unserialized = unserialize($serialized); |
||||
|
||||
$this->assertTrue($unserialized->__isInitialized(), 'serialization didn\'t cause intialization'); |
||||
|
||||
// Checking transient fields |
||||
$this->assertSame( |
||||
'publicTransientFieldValue', |
||||
$unserialized->publicTransientField, |
||||
'transient fields are kept' |
||||
); |
||||
$protectedTransientField = $reflClass->getProperty('protectedTransientField'); |
||||
$protectedTransientField->setAccessible(true); |
||||
$this->assertSame( |
||||
'protectedTransientFieldValue', |
||||
$protectedTransientField->getValue($unserialized), |
||||
'transient fields are kept' |
||||
); |
||||
|
||||
// Checking persistent fields |
||||
$this->assertSame( |
||||
'publicPersistentFieldValue', |
||||
$unserialized->publicPersistentField, |
||||
'persistent fields are kept' |
||||
); |
||||
$protectedPersistentField = $reflClass->getProperty('protectedPersistentField'); |
||||
$protectedPersistentField->setAccessible(true); |
||||
$this->assertSame( |
||||
'protectedPersistentFieldValue', |
||||
$protectedPersistentField->getValue($unserialized), |
||||
'persistent fields are kept' |
||||
); |
||||
|
||||
// Checking identifiers |
||||
$this->assertSame( |
||||
'publicIdentifierFieldValue', |
||||
$unserialized->publicIdentifierField, |
||||
'identifiers are kept' |
||||
); |
||||
$protectedIdentifierField = $reflClass->getProperty('protectedIdentifierField'); |
||||
$protectedIdentifierField->setAccessible(true); |
||||
$this->assertSame( |
||||
'protectedIdentifierFieldValue', |
||||
$protectedIdentifierField->getValue($unserialized), |
||||
'identifiers are kept' |
||||
); |
||||
|
||||
// Checking associations |
||||
$this->assertSame('publicAssociationValue', $unserialized->publicAssociation, 'associations are kept'); |
||||
$protectedAssociationField = $reflClass->getProperty('protectedAssociation'); |
||||
$protectedAssociationField->setAccessible(true); |
||||
$this->assertSame( |
||||
'protectedAssociationValue', |
||||
$protectedAssociationField->getValue($unserialized), |
||||
'associations are kept' |
||||
); |
||||
} |
||||
|
||||
public function testInitializationRestoresDefaultPublicLazyLoadedFieldValues() |
||||
{ |
||||
// setting noop persister |
||||
$this->proxyLoader->expects($this->once())->method('load')->will($this->returnValue($this->lazyObject)); |
||||
$this->lazyObject->__setInitializer($this->getSuggestedInitializerImplementation()); |
||||
|
||||
$this->assertSame( |
||||
'publicPersistentFieldValue', |
||||
$this->lazyObject->publicPersistentField, |
||||
'Persistent field is restored to default value' |
||||
); |
||||
$this->assertSame( |
||||
'publicAssociationValue', |
||||
$this->lazyObject->publicAssociation, |
||||
'Association is restored to default value' |
||||
); |
||||
} |
||||
|
||||
public function testSettingPublicFieldsCausesLazyLoading() |
||||
{ |
||||
$test = $this; |
||||
$this->configureInitializerMock( |
||||
1, |
||||
array($this->lazyObject, '__set', array('publicPersistentField', 'newPublicPersistentFieldValue')), |
||||
function () use ($test) { |
||||
$test->setProxyValue('publicPersistentField', 'overrideValue'); |
||||
$test->setProxyValue('publicAssociation', 'newAssociationValue'); |
||||
} |
||||
); |
||||
|
||||
$this->lazyObject->publicPersistentField = 'newPublicPersistentFieldValue'; |
||||
$this->assertSame('newPublicPersistentFieldValue', $this->lazyObject->publicPersistentField); |
||||
$this->assertSame('newAssociationValue', $this->lazyObject->publicAssociation); |
||||
} |
||||
|
||||
public function testSettingPublicAssociationCausesLazyLoading() |
||||
{ |
||||
$test = $this; |
||||
$this->configureInitializerMock( |
||||
1, |
||||
array($this->lazyObject, '__set', array('publicAssociation', 'newPublicAssociationValue')), |
||||
function () use ($test) { |
||||
$test->setProxyValue('publicPersistentField', 'newPublicPersistentFieldValue'); |
||||
$test->setProxyValue('publicAssociation', 'overrideValue'); |
||||
} |
||||
); |
||||
|
||||
$this->lazyObject->publicAssociation = 'newPublicAssociationValue'; |
||||
$this->assertSame('newPublicAssociationValue', $this->lazyObject->publicAssociation); |
||||
$this->assertSame('newPublicPersistentFieldValue', $this->lazyObject->publicPersistentField); |
||||
} |
||||
|
||||
public function testCheckingPublicFieldsCausesLazyLoading() |
||||
{ |
||||
$test = $this; |
||||
$this->configureInitializerMock( |
||||
1, |
||||
array($this->lazyObject, '__isset', array('publicPersistentField')), |
||||
function () use ($test) { |
||||
$test->setProxyValue('publicPersistentField', null); |
||||
$test->setProxyValue('publicAssociation', 'setPublicAssociation'); |
||||
} |
||||
); |
||||
|
||||
$this->assertFalse(isset($this->lazyObject->publicPersistentField)); |
||||
$this->assertNull($this->lazyObject->publicPersistentField); |
||||
$this->assertTrue(isset($this->lazyObject->publicAssociation)); |
||||
$this->assertSame('setPublicAssociation', $this->lazyObject->publicAssociation); |
||||
} |
||||
|
||||
public function testCheckingPublicAssociationCausesLazyLoading() |
||||
{ |
||||
$test = $this; |
||||
$this->configureInitializerMock( |
||||
1, |
||||
array($this->lazyObject, '__isset', array('publicAssociation')), |
||||
function () use ($test) { |
||||
$test->setProxyValue('publicPersistentField', 'newPersistentFieldValue'); |
||||
$test->setProxyValue('publicAssociation', 'setPublicAssociation'); |
||||
} |
||||
); |
||||
|
||||
$this->assertTrue(isset($this->lazyObject->publicAssociation)); |
||||
$this->assertSame('setPublicAssociation', $this->lazyObject->publicAssociation); |
||||
$this->assertTrue(isset($this->lazyObject->publicPersistentField)); |
||||
$this->assertSame('newPersistentFieldValue', $this->lazyObject->publicPersistentField); |
||||
} |
||||
|
||||
public function testCallingVariadicMethodCausesLazyLoading() |
||||
{ |
||||
if (PHP_VERSION_ID < 50600) { |
||||
$this->markTestSkipped('Test applies only to PHP 5.6+'); |
||||
} |
||||
|
||||
$proxyClassName = 'Doctrine\Tests\Common\ProxyProxy\__CG__\Doctrine\Tests\Common\Proxy\VariadicTypeHintClass'; |
||||
|
||||
/* @var $metadata \Doctrine\Common\Persistence\Mapping\ClassMetadata|\PHPUnit_Framework_MockObject_MockObject */ |
||||
$metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); |
||||
|
||||
$metadata |
||||
->expects($this->any()) |
||||
->method('getName') |
||||
->will($this->returnValue('Doctrine\Tests\Common\Proxy\VariadicTypeHintClass')); |
||||
$metadata |
||||
->expects($this->any()) |
||||
->method('getReflectionClass') |
||||
->will($this->returnValue(new \ReflectionClass('Doctrine\Tests\Common\Proxy\VariadicTypeHintClass'))); |
||||
|
||||
// creating the proxy class |
||||
if (!class_exists($proxyClassName, false)) { |
||||
$proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); |
||||
$proxyGenerator->generateProxyClass($metadata); |
||||
require_once $proxyGenerator->getProxyFileName($metadata->getName()); |
||||
} |
||||
|
||||
/* @var $invocationMock callable|\PHPUnit_Framework_MockObject_MockObject */ |
||||
$invocationMock = $this->getMock('stdClass', array('__invoke')); |
||||
|
||||
/* @var $lazyObject \Doctrine\Tests\Common\Proxy\VariadicTypeHintClass */ |
||||
$lazyObject = new $proxyClassName( |
||||
function ($proxy, $method, $parameters) use ($invocationMock) { |
||||
$invocationMock($proxy, $method, $parameters); |
||||
}, |
||||
function () {} |
||||
); |
||||
|
||||
$invocationMock |
||||
->expects($this->at(0)) |
||||
->method('__invoke') |
||||
->with($lazyObject, 'addType', array(array('type1', 'type2'))); |
||||
$invocationMock |
||||
->expects($this->at(1)) |
||||
->method('__invoke') |
||||
->with($lazyObject, 'addTypeWithMultipleParameters', array('foo', 'bar', array('baz1', 'baz2'))); |
||||
|
||||
$lazyObject->addType('type1', 'type2'); |
||||
$this->assertSame(array('type1', 'type2'), $lazyObject->types); |
||||
|
||||
$lazyObject->addTypeWithMultipleParameters('foo', 'bar', 'baz1', 'baz2'); |
||||
$this->assertSame('foo', $lazyObject->foo); |
||||
$this->assertSame('bar', $lazyObject->bar); |
||||
$this->assertSame(array('baz1', 'baz2'), $lazyObject->baz); |
||||
} |
||||
|
||||
/** |
||||
* Converts a given callable into a closure |
||||
* |
||||
* @param callable $callable |
||||
* @return \Closure |
||||
*/ |
||||
public function getClosure($callable) { |
||||
return function () use ($callable) { |
||||
call_user_func_array($callable, func_get_args()); |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Configures the current initializer callback mock with provided matcher params |
||||
* |
||||
* @param int $expectedCallCount the number of invocations to be expected. If a value< 0 is provided, `any` is used |
||||
* @param array $callParamsMatch an ordered array of parameters to be expected |
||||
* @param callable $callbackClosure a return callback closure |
||||
* |
||||
* @return \PHPUnit_Framework_MockObject_MockObject| |
||||
*/ |
||||
protected function configureInitializerMock( |
||||
$expectedCallCount = 0, |
||||
array $callParamsMatch = null, |
||||
\Closure $callbackClosure = null |
||||
) { |
||||
if (!$expectedCallCount) { |
||||
$invocationCountMatcher = $this->exactly((int) $expectedCallCount); |
||||
} else { |
||||
$invocationCountMatcher = $expectedCallCount < 0 ? $this->any() : $this->exactly($expectedCallCount); |
||||
} |
||||
|
||||
$invocationMocker = $this->initializerCallbackMock->expects($invocationCountMatcher)->method('__invoke'); |
||||
|
||||
if (null !== $callParamsMatch) { |
||||
call_user_func_array(array($invocationMocker, 'with'), $callParamsMatch); |
||||
} |
||||
|
||||
if ($callbackClosure) { |
||||
$invocationMocker->will($this->returnCallback($callbackClosure)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sets a value in the current proxy object without triggering lazy loading through `__set` |
||||
* |
||||
* @link https://bugs.php.net/bug.php?id=63463 |
||||
* |
||||
* @param string $property |
||||
* @param mixed $value |
||||
*/ |
||||
public function setProxyValue($property, $value) |
||||
{ |
||||
$reflectionProperty = new \ReflectionProperty($this->lazyObject, $property); |
||||
$initializer = $this->lazyObject->__getInitializer(); |
||||
|
||||
// disabling initializer since setting `publicPersistentField` triggers `__set`/`__get` |
||||
$this->lazyObject->__setInitializer(null); |
||||
$reflectionProperty->setValue($this->lazyObject, $value); |
||||
$this->lazyObject->__setInitializer($initializer); |
||||
} |
||||
|
||||
/** |
||||
* Retrieves the suggested implementation of an initializer that proxy factories in O*M |
||||
* are currently following, and that should be used to initialize the current proxy object |
||||
* |
||||
* @return \Closure |
||||
*/ |
||||
protected function getSuggestedInitializerImplementation() |
||||
{ |
||||
$loader = $this->proxyLoader; |
||||
$identifier = $this->identifier; |
||||
|
||||
return function (LazyLoadableObject $proxy) use ($loader, $identifier) { |
||||
/* @var $proxy LazyLoadableObject|Proxy */ |
||||
$proxy->__setInitializer(null); |
||||
$proxy->__setCloner(null); |
||||
|
||||
|
||||
if ($proxy->__isInitialized()) { |
||||
return; |
||||
} |
||||
|
||||
$properties = $proxy->__getLazyProperties(); |
||||
|
||||
foreach ($properties as $propertyName => $property) { |
||||
if (!isset($proxy->$propertyName)) { |
||||
$proxy->$propertyName = $properties[$propertyName]; |
||||
} |
||||
} |
||||
|
||||
$proxy->__setInitialized(true); |
||||
|
||||
if (method_exists($proxy, '__wakeup')) { |
||||
$proxy->__wakeup(); |
||||
} |
||||
|
||||
if (null === $loader->load($identifier, $proxy)) { |
||||
throw new \UnexpectedValueException('Couldn\'t load'); |
||||
} |
||||
}; |
||||
} |
||||
} |
||||
@ -0,0 +1,327 @@ |
||||
<?php |
||||
/* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
* This software consists of voluntary contributions made by many individuals |
||||
* and is licensed under the MIT license. For more information, see |
||||
* <http://www.doctrine-project.org>. |
||||
*/ |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
use Doctrine\Common\Proxy\ProxyGenerator; |
||||
use Doctrine\Common\Proxy\Proxy; |
||||
use Doctrine\Common\Proxy\Exception\UnexpectedValueException; |
||||
use PHPUnit_Framework_TestCase; |
||||
use ReflectionClass; |
||||
|
||||
/** |
||||
* Test for behavior of proxies with inherited magic methods |
||||
* |
||||
* @author Marco Pivetta <ocramius@gmail.com> |
||||
*/ |
||||
class ProxyMagicMethodsTest extends PHPUnit_Framework_TestCase |
||||
{ |
||||
/** |
||||
* @var \Doctrine\Common\Proxy\ProxyGenerator |
||||
*/ |
||||
protected $proxyGenerator; |
||||
|
||||
/** |
||||
* @var LazyLoadableObject|Proxy |
||||
*/ |
||||
protected $lazyObject; |
||||
|
||||
protected $identifier = array( |
||||
'publicIdentifierField' => 'publicIdentifierFieldValue', |
||||
'protectedIdentifierField' => 'protectedIdentifierFieldValue', |
||||
); |
||||
|
||||
/** |
||||
* @var \PHPUnit_Framework_MockObject_MockObject|Callable |
||||
*/ |
||||
protected $initializerCallbackMock; |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function setUp() |
||||
{ |
||||
$this->proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . '\\MagicMethodProxy'); |
||||
} |
||||
|
||||
public static function tearDownAfterClass() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public function testInheritedMagicGet() |
||||
{ |
||||
$proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicGetClass'); |
||||
$proxy = new $proxyClassName( |
||||
function (Proxy $proxy, $method, $params) use (&$counter) { |
||||
if ( ! in_array($params[0], array('publicField', 'test', 'notDefined'))) { |
||||
throw new \InvalidArgumentException('Unexpected access to field "' . $params[0] . '"'); |
||||
} |
||||
|
||||
$initializer = $proxy->__getInitializer(); |
||||
|
||||
$proxy->__setInitializer(null); |
||||
|
||||
$proxy->publicField = 'modifiedPublicField'; |
||||
$counter += 1; |
||||
|
||||
$proxy->__setInitializer($initializer); |
||||
|
||||
} |
||||
); |
||||
|
||||
$this->assertSame('id', $proxy->id); |
||||
$this->assertSame('modifiedPublicField', $proxy->publicField); |
||||
$this->assertSame('test', $proxy->test); |
||||
$this->assertSame('not defined', $proxy->notDefined); |
||||
|
||||
$this->assertSame(3, $counter); |
||||
} |
||||
|
||||
/** |
||||
* @group DCOM-194 |
||||
*/ |
||||
public function testInheritedMagicGetByRef() |
||||
{ |
||||
$proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicGetByRefClass'); |
||||
/* @var $proxy \Doctrine\Tests\Common\Proxy\MagicGetByRefClass */ |
||||
$proxy = new $proxyClassName(); |
||||
$proxy->valueField = 123; |
||||
$value = & $proxy->__get('value'); |
||||
|
||||
$this->assertSame(123, $value); |
||||
|
||||
$value = 456; |
||||
|
||||
$this->assertSame(456, $proxy->__get('value'), 'Value was fetched by reference'); |
||||
|
||||
$this->setExpectedException('InvalidArgumentException'); |
||||
|
||||
$undefined = $proxy->nonExisting; |
||||
} |
||||
|
||||
public function testInheritedMagicSet() |
||||
{ |
||||
$proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicSetClass'); |
||||
$proxy = new $proxyClassName( |
||||
function (Proxy $proxy, $method, $params) use (&$counter) { |
||||
if ( ! in_array($params[0], array('publicField', 'test', 'notDefined'))) { |
||||
throw new \InvalidArgumentException('Unexpected access to field "' . $params[0] . '"'); |
||||
} |
||||
|
||||
$counter += 1; |
||||
} |
||||
); |
||||
|
||||
$this->assertSame('id', $proxy->id); |
||||
|
||||
$proxy->publicField = 'publicFieldValue'; |
||||
|
||||
$this->assertSame('publicFieldValue', $proxy->publicField); |
||||
|
||||
$proxy->test = 'testValue'; |
||||
|
||||
$this->assertSame('testValue', $proxy->testAttribute); |
||||
|
||||
$proxy->notDefined = 'not defined'; |
||||
|
||||
$this->assertSame('not defined', $proxy->testAttribute); |
||||
$this->assertSame(3, $counter); |
||||
} |
||||
|
||||
public function testInheritedMagicSleep() |
||||
{ |
||||
$proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicSleepClass'); |
||||
$proxy = new $proxyClassName(); |
||||
|
||||
$this->assertSame('defaultValue', $proxy->serializedField); |
||||
$this->assertSame('defaultValue', $proxy->nonSerializedField); |
||||
|
||||
$proxy->serializedField = 'changedValue'; |
||||
$proxy->nonSerializedField = 'changedValue'; |
||||
|
||||
$unserialized = unserialize(serialize($proxy)); |
||||
|
||||
$this->assertSame('changedValue', $unserialized->serializedField); |
||||
$this->assertSame('defaultValue', $unserialized->nonSerializedField, 'Field was not returned by "__sleep"'); |
||||
} |
||||
|
||||
public function testInheritedMagicWakeup() |
||||
{ |
||||
$proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicWakeupClass'); |
||||
$proxy = new $proxyClassName(); |
||||
|
||||
$this->assertSame('defaultValue', $proxy->wakeupValue); |
||||
|
||||
$proxy->wakeupValue = 'changedValue'; |
||||
$unserialized = unserialize(serialize($proxy)); |
||||
|
||||
$this->assertSame('newWakeupValue', $unserialized->wakeupValue, '"__wakeup" was called'); |
||||
|
||||
$unserialized->__setInitializer(function (Proxy $proxy) { |
||||
$proxy->__setInitializer(null); |
||||
|
||||
$proxy->publicField = 'newPublicFieldValue'; |
||||
}); |
||||
|
||||
$this->assertSame('newPublicFieldValue', $unserialized->publicField, 'Proxy can still be initialized'); |
||||
} |
||||
|
||||
public function testInheritedMagicIsset() |
||||
{ |
||||
$proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicIssetClass'); |
||||
$proxy = new $proxyClassName(function (Proxy $proxy, $method, $params) use (&$counter) { |
||||
if (in_array($params[0], array('publicField', 'test', 'nonExisting'))) { |
||||
$initializer = $proxy->__getInitializer(); |
||||
|
||||
$proxy->__setInitializer(null); |
||||
|
||||
$proxy->publicField = 'modifiedPublicField'; |
||||
$counter += 1; |
||||
|
||||
$proxy->__setInitializer($initializer); |
||||
|
||||
return; |
||||
} |
||||
|
||||
throw new \InvalidArgumentException( |
||||
sprintf('Should not be initialized when checking isset("%s")', $params[0]) |
||||
); |
||||
}); |
||||
|
||||
$this->assertTrue(isset($proxy->id)); |
||||
$this->assertTrue(isset($proxy->publicField)); |
||||
$this->assertTrue(isset($proxy->test)); |
||||
$this->assertFalse(isset($proxy->nonExisting)); |
||||
|
||||
$this->assertSame(3, $counter); |
||||
} |
||||
|
||||
public function testInheritedMagicClone() |
||||
{ |
||||
$proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicCloneClass'); |
||||
$proxy = new $proxyClassName( |
||||
null, |
||||
function ($proxy) { |
||||
$proxy->cloned = true; |
||||
} |
||||
); |
||||
|
||||
$cloned = clone $proxy; |
||||
|
||||
$this->assertSame('newClonedValue', $cloned->clonedValue); |
||||
$this->assertFalse($proxy->cloned); |
||||
$this->assertTrue($cloned->cloned); |
||||
} |
||||
|
||||
/** |
||||
* @group DCOM-175 |
||||
*/ |
||||
public function testClonesPrivateProperties() |
||||
{ |
||||
$proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\SerializedClass'); |
||||
/* @var $proxy SerializedClass */ |
||||
$proxy = new $proxyClassName(); |
||||
|
||||
$proxy->setFoo(1); |
||||
$proxy->setBar(2); |
||||
$proxy->setBaz(3); |
||||
|
||||
$unserialized = unserialize(serialize($proxy)); |
||||
|
||||
$this->assertSame(1, $unserialized->getFoo()); |
||||
$this->assertSame(2, $unserialized->getBar()); |
||||
$this->assertSame(3, $unserialized->getBaz()); |
||||
} |
||||
|
||||
/** |
||||
* @param $className |
||||
* |
||||
* @return string |
||||
*/ |
||||
private function generateProxyClass($className) |
||||
{ |
||||
$proxyClassName = 'Doctrine\\Tests\\Common\\Proxy\\MagicMethodProxy\\__CG__\\' . $className; |
||||
|
||||
if (class_exists($proxyClassName, false)) { |
||||
return $proxyClassName; |
||||
} |
||||
|
||||
$metadata = $this->getMock('Doctrine\\Common\\Persistence\\Mapping\\ClassMetadata'); |
||||
|
||||
$metadata |
||||
->expects($this->any()) |
||||
->method('getName') |
||||
->will($this->returnValue($className)); |
||||
|
||||
$metadata |
||||
->expects($this->any()) |
||||
->method('getIdentifier') |
||||
->will($this->returnValue(array('id'))); |
||||
|
||||
$metadata |
||||
->expects($this->any()) |
||||
->method('getReflectionClass') |
||||
->will($this->returnValue(new ReflectionClass($className))); |
||||
|
||||
$metadata |
||||
->expects($this->any()) |
||||
->method('isIdentifier') |
||||
->will($this->returnCallback(function ($fieldName) { |
||||
return 'id' === $fieldName; |
||||
})); |
||||
|
||||
$metadata |
||||
->expects($this->any()) |
||||
->method('hasField') |
||||
->will($this->returnCallback(function ($fieldName) { |
||||
return in_array($fieldName, array('id', 'publicField')); |
||||
})); |
||||
|
||||
$metadata |
||||
->expects($this->any()) |
||||
->method('hasAssociation') |
||||
->will($this->returnValue(false)); |
||||
|
||||
$metadata |
||||
->expects($this->any()) |
||||
->method('getFieldNames') |
||||
->will($this->returnValue(array('id', 'publicField'))); |
||||
|
||||
$metadata |
||||
->expects($this->any()) |
||||
->method('getIdentifierFieldNames') |
||||
->will($this->returnValue(array('id'))); |
||||
|
||||
$metadata |
||||
->expects($this->any()) |
||||
->method('getAssociationNames') |
||||
->will($this->returnValue(array())); |
||||
|
||||
$metadata |
||||
->expects($this->any()) |
||||
->method('getTypeOfField') |
||||
->will($this->returnValue('string')); |
||||
|
||||
$this->proxyGenerator->generateProxyClass($metadata, $this->proxyGenerator->getProxyFileName($className)); |
||||
require_once $this->proxyGenerator->getProxyFileName($className); |
||||
|
||||
return $proxyClassName; |
||||
} |
||||
} |
||||
@ -0,0 +1,72 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset class |
||||
*/ |
||||
class SerializedClass |
||||
{ |
||||
/** |
||||
* @var mixed |
||||
*/ |
||||
private $foo = 'foo'; |
||||
|
||||
/** |
||||
* @var mixed |
||||
*/ |
||||
protected $bar = 'bar'; |
||||
|
||||
/** |
||||
* @var mixed |
||||
*/ |
||||
public $baz = 'baz'; |
||||
|
||||
/** |
||||
* @param mixed $foo |
||||
*/ |
||||
public function setFoo($foo) |
||||
{ |
||||
$this->foo = $foo; |
||||
} |
||||
|
||||
/** |
||||
* @return mixed|string |
||||
*/ |
||||
public function getFoo() |
||||
{ |
||||
return $this->foo; |
||||
} |
||||
|
||||
/** |
||||
* @param $bar |
||||
*/ |
||||
public function setBar($bar) |
||||
{ |
||||
$this->bar = $bar; |
||||
} |
||||
|
||||
/** |
||||
* @return mixed|string |
||||
*/ |
||||
public function getBar() |
||||
{ |
||||
return $this->bar; |
||||
} |
||||
|
||||
/** |
||||
* @param $baz |
||||
*/ |
||||
public function setBaz($baz) |
||||
{ |
||||
$this->baz = $baz; |
||||
} |
||||
|
||||
/** |
||||
* @return mixed|string |
||||
*/ |
||||
public function getBaz() |
||||
{ |
||||
return $this->baz; |
||||
} |
||||
} |
||||
@ -0,0 +1,19 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset class |
||||
*/ |
||||
class SleepClass |
||||
{ |
||||
public $id; |
||||
|
||||
/** |
||||
* @return array |
||||
*/ |
||||
public function __sleep() |
||||
{ |
||||
return array('id'); |
||||
} |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset class |
||||
*/ |
||||
class StaticPropertyClass |
||||
{ |
||||
protected static $protectedStaticProperty; |
||||
} |
||||
@ -0,0 +1,29 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Proxy; |
||||
|
||||
/** |
||||
* Test asset class |
||||
*/ |
||||
class VariadicTypeHintClass |
||||
{ |
||||
public $types; |
||||
public $foo; |
||||
public $bar; |
||||
public $baz; |
||||
|
||||
/** |
||||
* @param ...$types |
||||
*/ |
||||
public function addType(...$types) |
||||
{ |
||||
$this->types = $types; |
||||
} |
||||
|
||||
public function addTypeWithMultipleParameters($foo, $bar, ...$baz) |
||||
{ |
||||
$this->foo = $foo; |
||||
$this->bar = $bar; |
||||
$this->baz = $baz; |
||||
} |
||||
} |
||||
@ -0,0 +1,7 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Reflection; |
||||
|
||||
class DeeperNamespaceParent extends Dummies\NoParent |
||||
{ |
||||
} |
||||
@ -0,0 +1,8 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Reflection\Dummies; |
||||
|
||||
class NoParent |
||||
{ |
||||
public $test; |
||||
} |
||||
@ -0,0 +1,14 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Reflection; |
||||
|
||||
use Doctrine\Common\Annotations\Annotation; |
||||
|
||||
/** |
||||
* @Annotation( |
||||
* key = "value" |
||||
* ) |
||||
*/ |
||||
class ExampleAnnotationClass { |
||||
|
||||
} |
||||
@ -0,0 +1,7 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Reflection; |
||||
|
||||
class FullyClassifiedParent extends \Doctrine\Tests\Common\Reflection\NoParent |
||||
{ |
||||
} |
||||
@ -0,0 +1,8 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Reflection; |
||||
|
||||
class NoParent |
||||
{ |
||||
public $test; |
||||
} |
||||
@ -0,0 +1,192 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Reflection; |
||||
|
||||
use PHPUnit_Framework_TestCase; |
||||
use Doctrine\Common\Reflection\RuntimePublicReflectionProperty; |
||||
use Doctrine\Common\Proxy\Proxy; |
||||
|
||||
class RuntimePublicReflectionPropertyTest extends PHPUnit_Framework_TestCase |
||||
{ |
||||
public function testGetValueOnProxyPublicProperty() |
||||
{ |
||||
$getCheckMock = $this->getMock('stdClass', array('callGet')); |
||||
$getCheckMock->expects($this->never())->method('callGet'); |
||||
$initializer = function () use ($getCheckMock) { |
||||
call_user_func($getCheckMock); |
||||
}; |
||||
|
||||
$mockProxy = new RuntimePublicReflectionPropertyTestProxyMock(); |
||||
$mockProxy->__setInitializer($initializer); |
||||
|
||||
$reflProperty = new RuntimePublicReflectionProperty( |
||||
__NAMESPACE__ . '\RuntimePublicReflectionPropertyTestProxyMock', |
||||
'checkedProperty' |
||||
); |
||||
|
||||
$this->assertSame('testValue', $reflProperty->getValue($mockProxy)); |
||||
unset($mockProxy->checkedProperty); |
||||
$this->assertNull($reflProperty->getValue($mockProxy)); |
||||
} |
||||
|
||||
public function testSetValueOnProxyPublicProperty() |
||||
{ |
||||
$setCheckMock = $this->getMock('stdClass', array('neverCallSet')); |
||||
$setCheckMock->expects($this->never())->method('neverCallSet'); |
||||
$initializer = function () use ($setCheckMock) { |
||||
call_user_func(array($setCheckMock, 'neverCallSet')); |
||||
}; |
||||
|
||||
$mockProxy = new RuntimePublicReflectionPropertyTestProxyMock(); |
||||
$mockProxy->__setInitializer($initializer); |
||||
|
||||
$reflProperty = new RuntimePublicReflectionProperty( |
||||
__NAMESPACE__ . '\RuntimePublicReflectionPropertyTestProxyMock', |
||||
'checkedProperty' |
||||
); |
||||
|
||||
$reflProperty->setValue($mockProxy, 'newValue'); |
||||
$this->assertSame('newValue', $mockProxy->checkedProperty); |
||||
|
||||
unset($mockProxy->checkedProperty); |
||||
$reflProperty->setValue($mockProxy, 'otherNewValue'); |
||||
$this->assertSame('otherNewValue', $mockProxy->checkedProperty); |
||||
|
||||
$setCheckMock = $this->getMock('stdClass', array('callSet')); |
||||
$setCheckMock->expects($this->once())->method('callSet'); |
||||
$initializer = function () use ($setCheckMock) { |
||||
call_user_func(array($setCheckMock, 'callSet')); |
||||
}; |
||||
|
||||
$mockProxy->__setInitializer($initializer); |
||||
$mockProxy->__setInitialized(true); |
||||
|
||||
unset($mockProxy->checkedProperty); |
||||
$reflProperty->setValue($mockProxy, 'againNewValue'); |
||||
$this->assertSame('againNewValue', $mockProxy->checkedProperty); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Mock that simulates proxy public property lazy loading |
||||
*/ |
||||
class RuntimePublicReflectionPropertyTestProxyMock implements Proxy |
||||
{ |
||||
/** |
||||
* @var \Closure|null |
||||
*/ |
||||
private $initializer = null; |
||||
|
||||
/** |
||||
* @var \Closure|null |
||||
*/ |
||||
private $initialized = false; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
public $checkedProperty = 'testValue'; |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function __getInitializer() |
||||
{ |
||||
return $this->initializer; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function __setInitializer(\Closure $initializer = null) |
||||
{ |
||||
$this->initializer = $initializer; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function __getLazyProperties() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function __load() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function __isInitialized() |
||||
{ |
||||
return $this->initialized; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function __setInitialized($initialized) |
||||
{ |
||||
$this->initialized = (bool) $initialized; |
||||
} |
||||
|
||||
/** |
||||
* @param string $name |
||||
*/ |
||||
public function __get($name) |
||||
{ |
||||
if ($this->initializer) { |
||||
$cb = $this->initializer; |
||||
$cb(); |
||||
} |
||||
|
||||
return $this->checkedProperty; |
||||
} |
||||
|
||||
/** |
||||
* @param string $name |
||||
* @param mixed $value |
||||
*/ |
||||
public function __set($name, $value) |
||||
{ |
||||
if ($this->initializer) { |
||||
$cb = $this->initializer; |
||||
$cb(); |
||||
} |
||||
|
||||
// triggers notices if `$name` is used: see https://bugs.php.net/bug.php?id=63463 |
||||
$this->checkedProperty = $value; |
||||
} |
||||
|
||||
/** |
||||
* @param string $name |
||||
* |
||||
* @return integer |
||||
*/ |
||||
public function __isset($name) |
||||
{ |
||||
if ($this->initializer) { |
||||
$cb = $this->initializer; |
||||
$cb(); |
||||
} |
||||
|
||||
return isset($this->checkedProperty); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function __setCloner(\Closure $cloner = null) |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function __getCloner() |
||||
{ |
||||
} |
||||
} |
||||
@ -0,0 +1,7 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Reflection; |
||||
|
||||
class SameNamespaceParent extends NoParent |
||||
{ |
||||
} |
||||
@ -0,0 +1,93 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Reflection; |
||||
|
||||
use Doctrine\Tests\DoctrineTestCase; |
||||
use Doctrine\Common\Reflection\StaticReflectionParser; |
||||
use Doctrine\Common\Reflection\Psr0FindFile; |
||||
|
||||
class StaticReflectionParserTest extends DoctrineTestCase |
||||
{ |
||||
/** |
||||
* @dataProvider parentClassData |
||||
* |
||||
* @param bool $classAnnotationOptimize |
||||
* @param string $parsedClassName |
||||
* @param string $expectedClassName |
||||
* |
||||
* @return void |
||||
*/ |
||||
public function testParentClass($classAnnotationOptimize, $parsedClassName, $expectedClassName) |
||||
{ |
||||
// If classed annotation optimization is enabled the properties tested |
||||
// below cannot be found. |
||||
if ($classAnnotationOptimize) { |
||||
$this->setExpectedException('ReflectionException'); |
||||
} |
||||
|
||||
$testsRoot = substr(__DIR__, 0, -strlen(__NAMESPACE__) - 1); |
||||
$paths = array( |
||||
'Doctrine\\Tests' => array($testsRoot), |
||||
); |
||||
$staticReflectionParser = new StaticReflectionParser($parsedClassName, new Psr0FindFile($paths), $classAnnotationOptimize); |
||||
$declaringClassName = $staticReflectionParser->getStaticReflectionParserForDeclaringClass('property', 'test')->getClassName(); |
||||
$this->assertEquals($expectedClassName, $declaringClassName); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* @return array |
||||
*/ |
||||
public function parentClassData() |
||||
{ |
||||
$data = array(); |
||||
$noParentClassName = 'Doctrine\\Tests\\Common\\Reflection\\NoParent'; |
||||
$dummyParentClassName = 'Doctrine\\Tests\\Common\\Reflection\\Dummies\\NoParent'; |
||||
foreach (array(false, true) as $classAnnotationOptimize) { |
||||
$data[] = array( |
||||
$classAnnotationOptimize, $noParentClassName, $noParentClassName, |
||||
); |
||||
$data[] = array( |
||||
$classAnnotationOptimize, 'Doctrine\\Tests\\Common\\Reflection\\FullyClassifiedParent', $noParentClassName, |
||||
); |
||||
$data[] = array( |
||||
$classAnnotationOptimize, 'Doctrine\\Tests\\Common\\Reflection\\SameNamespaceParent', $noParentClassName, |
||||
); |
||||
$data[] = array( |
||||
$classAnnotationOptimize, 'Doctrine\\Tests\\Common\\Reflection\\DeeperNamespaceParent', $dummyParentClassName, |
||||
); |
||||
$data[] = array( |
||||
$classAnnotationOptimize, 'Doctrine\\Tests\\Common\\Reflection\\UseParent', $dummyParentClassName, |
||||
); |
||||
} |
||||
return $data; |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider classAnnotationOptimize |
||||
*/ |
||||
public function testClassAnnotationOptimizedParsing($classAnnotationOptimize) { |
||||
$testsRoot = substr(__DIR__, 0, -strlen(__NAMESPACE__) - 1); |
||||
$paths = array( |
||||
'Doctrine\\Tests' => array($testsRoot), |
||||
); |
||||
$staticReflectionParser = new StaticReflectionParser('Doctrine\\Tests\\Common\\Reflection\\ExampleAnnotationClass', new Psr0FindFile($paths), $classAnnotationOptimize); |
||||
$expectedDocComment = '/** |
||||
* @Annotation( |
||||
* key = "value" |
||||
* ) |
||||
*/'; |
||||
$this->assertEquals($expectedDocComment, $staticReflectionParser->getDocComment('class')); |
||||
} |
||||
|
||||
/** |
||||
* @return array |
||||
*/ |
||||
public function classAnnotationOptimize() |
||||
{ |
||||
return array( |
||||
array(false), |
||||
array(true) |
||||
); |
||||
} |
||||
} |
||||
@ -0,0 +1,9 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Reflection; |
||||
|
||||
use Doctrine\Tests\Common\Reflection\Dummies\NoParent as Test; |
||||
|
||||
class UseParent extends Test |
||||
{ |
||||
} |
||||
@ -0,0 +1,100 @@ |
||||
<?php |
||||
|
||||
namespace Doctrine\Tests\Common\Util |
||||
{ |
||||
use Doctrine\Tests\DoctrineTestCase; |
||||
use Doctrine\Common\Util\ClassUtils; |
||||
|
||||
class ClassUtilsTest extends DoctrineTestCase |
||||
{ |
||||
static public function dataGetClass() |
||||
{ |
||||
return array( |
||||
array('stdClass', 'stdClass'), |
||||
array('Doctrine\Common\Util\ClassUtils', 'Doctrine\Common\Util\ClassUtils'), |
||||
array( 'MyProject\Proxies\__CG__\stdClass', 'stdClass' ), |
||||
array( 'MyProject\Proxies\__CG__\OtherProject\Proxies\__CG__\stdClass', 'stdClass' ), |
||||
array( 'MyProject\Proxies\__CG__\Doctrine\Tests\Common\Util\ChildObject','Doctrine\Tests\Common\Util\ChildObject' ) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider dataGetClass |
||||
*/ |
||||
public function testGetRealClass($className, $expectedClassName) |
||||
{ |
||||
$this->assertEquals($expectedClassName, ClassUtils::getRealClass($className)); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider dataGetClass |
||||
*/ |
||||
public function testGetClass( $className, $expectedClassName ) |
||||
{ |
||||
$object = new $className(); |
||||
$this->assertEquals($expectedClassName, ClassUtils::getClass($object)); |
||||
} |
||||
|
||||
public function testGetParentClass() |
||||
{ |
||||
$parentClass = ClassUtils::getParentClass( 'MyProject\Proxies\__CG__\OtherProject\Proxies\__CG__\Doctrine\Tests\Common\Util\ChildObject' ); |
||||
$this->assertEquals('stdClass', $parentClass); |
||||
} |
||||
|
||||
public function testGenerateProxyClassName() |
||||
{ |
||||
$this->assertEquals( 'Proxies\__CG__\stdClass', ClassUtils::generateProxyClassName( 'stdClass', 'Proxies' ) ); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider dataGetClass |
||||
*/ |
||||
public function testNewReflectionClass( $className, $expectedClassName ) |
||||
{ |
||||
$reflClass = ClassUtils::newReflectionClass( $className ); |
||||
$this->assertEquals( $expectedClassName, $reflClass->getName() ); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider dataGetClass |
||||
*/ |
||||
public function testNewReflectionObject( $className, $expectedClassName ) |
||||
{ |
||||
$object = new $className; |
||||
$reflClass = ClassUtils::newReflectionObject( $object ); |
||||
$this->assertEquals( $expectedClassName, $reflClass->getName() ); |
||||
} |
||||
} |
||||
|
||||
class ChildObject extends \stdClass |
||||
{ |
||||
} |
||||
} |
||||
|
||||
namespace MyProject\Proxies\__CG__ |
||||
{ |
||||
class stdClass extends \stdClass |
||||
{ |
||||
} |
||||
} |
||||
|
||||
namespace MyProject\Proxies\__CG__\Doctrine\Tests\Common\Util |
||||
{ |
||||
class ChildObject extends \Doctrine\Tests\Common\Util\ChildObject |
||||
{ |
||||
} |
||||
} |
||||
|
||||
namespace MyProject\Proxies\__CG__\OtherProject\Proxies\__CG__ |
||||
{ |
||||
class stdClass extends \MyProject\Proxies\__CG__\stdClass |
||||
{ |
||||
} |
||||
} |
||||
|
||||
namespace MyProject\Proxies\__CG__\OtherProject\Proxies\__CG__\Doctrine\Tests\Common\Util |
||||
{ |
||||
class ChildObject extends \MyProject\Proxies\__CG__\Doctrine\Tests\Common\Util\ChildObject |
||||
{ |
||||
} |
||||
} |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue