Permalink
Browse files

Merge branch 'DDC-717' into 2.4

  • Loading branch information...
2 parents c4255b9 + 01a9a97 commit 7877938b8972be0653cc8e71803df6bcb5443a1f @beberlei beberlei committed Aug 20, 2013
View
4 .travis.yml
@@ -1,8 +1,5 @@
language: php
-env:
- - OPCODE_CACHE=apc
-
php:
- 5.3.3
- 5.3
@@ -11,4 +8,3 @@ php:
before_script:
- composer --prefer-source install
- - php ./bin/travis-setup.php $OPCODE_CACHE
View
141 bin/travis-setup.php
@@ -1,141 +0,0 @@
-<?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>.
- */
-
-/**
- * Install PHP extensions required for testing by Travis CI.
- *
- * @author Victor Berchet <victor@suumit.com>
- * @since 2.2
- */
-$installer = new PhpExtensions();
-
-if (isset($argv[1]) && 'APC' === strtoupper($argv[1])) {
- $installer->install('apc');
-} else {
- $installer->install('xcache');
-}
-
-$installer->install('memcache');
-$installer->install('memcached');
-
-class PhpExtensions
-{
- protected $extensions;
- protected $phpVersion;
- protected $iniPath;
-
- public function __construct()
- {
- $this->phpVersion = phpversion();
- $this->iniPath = php_ini_loaded_file();
- $this->extensions = array(
- 'memcache' => array(
- 'url' => 'http://pecl.php.net/get/memcache-2.2.6.tgz',
- 'php_version' => array(),
- 'cfg' => array('--enable-memcache'),
- 'ini' => array('extension=memcache.so'),
- ),
- 'memcached' => array(
- 'url' => 'http://pecl.php.net/get/memcached-1.0.2.tgz',
- 'php_version' => array(
- // memcached 1.0.2 does not build on PHP 5.4
- array('<', '5.4'),
- ),
- 'cfg' => array(),
- 'ini' => array('extension=memcached.so'),
- ),
- 'apc' => array(
- 'url' => 'http://pecl.php.net/get/APC-3.1.9.tgz',
- 'php_version' => array(
- // apc 3.1.9 causes a segfault on PHP 5.4
- array('<', '5.4'),
- ),
- 'cfg' => array(),
- 'ini' => array(
- 'extension=apc.so',
- 'apc.enabled=1',
- 'apc.enable_cli=1'
- ),
- ),
- 'xcache' => array(
- 'url' => 'http://xcache.lighttpd.net/pub/Releases/1.2.2/xcache-1.2.2.tar.gz',
- 'php_version' => array(
- // xcache does not build with Travis CI (as of 2012-01-09)
- array('<', '5'),
- ),
- 'cfg' => array('--enable-xcache'),
- 'ini' => array(
- 'extension=xcache.so',
- 'xcache.cacher=false',
- 'xcache.admin.enable_auth=0',
- 'xcache.var_size=1M',
- ),
- ),
- );
- }
-
- public function install($name)
- {
- if (array_key_exists($name, $this->extensions)) {
- $extension = $this->extensions[$name];
-
-
- echo "== extension: $name ==\n";
-
- foreach ($extension['php_version'] as $version) {
- if (!version_compare($this->phpVersion, $version[1], $version[0])) {
- printf(
- "=> not installed, requires a PHP version %s %s (%s installed)\n",
- $version[0],
- $version[1],
- $this->phpVersion
- );
-
- return;
- }
- }
-
- $this->system(sprintf("wget %s > /dev/null 2>&1", $extension['url']));
- $file = basename($extension['url']);
- $this->system(sprintf("tar -xzf %s > /dev/null 2>&1", $file));
- $folder = basename($file, ".tgz");
- $folder = basename($folder, ".tar.gz");
- $this->system(sprintf(
- 'sh -c "cd %s && phpize && ./configure %s && make && sudo make install" > /dev/null 2>&1',
- $folder,
- implode(' ', $extension['cfg'])
- ));
- foreach ($extension['ini'] as $ini) {
- $this->system(sprintf("echo %s >> %s", $ini, $this->iniPath));
- }
- printf("=> installed (%s)\n", $folder);
- }
- }
-
- private function system($cmd)
- {
- $ret = 0;
- system($cmd, $ret);
- if (0 !== $ret) {
- printf("=> Command '%s' failed !", $cmd);
-
- exit($ret);
- }
- }
-}
View
65 lib/Doctrine/Common/Proxy/AbstractProxyFactory.php
@@ -32,6 +32,43 @@
abstract class AbstractProxyFactory
{
/**
+ * Never autogenerate a proxy and rely that it was generated by some
+ * process before deployment.
+ *
+ * @var integer
+ */
+ const AUTOGENERATE_NEVER = 0;
+
+ /**
+ * Always generates a new proxy in every request.
+ *
+ * This is only sane during development.
+ *
+ * @var integer
+ */
+ const AUTOGENERATE_ALWAYS = 1;
+
+ /**
+ * Autogenerate the proxy class when the proxy file does not exist.
+ *
+ * This strategy causes a file exists call whenever any proxy is used the
+ * first time in a request.
+ *
+ * @var integer
+ */
+ const AUTOGENERATE_FILE_NOT_EXISTS = 2;
+
+ /**
+ * Generate the proxy classes using eval().
+ *
+ * This strategy is only sane for development, and even then it gives me
+ * the creeps a little.
+ *
+ * @var integer
+ */
+ const AUTOGENERATE_EVAL = 3;
+
+ /**
* @var \Doctrine\Common\Persistence\Mapping\ClassMetadataFactory
*/
private $metadataFactory;
@@ -54,13 +91,13 @@
/**
* @param \Doctrine\Common\Proxy\ProxyGenerator $proxyGenerator
* @param \Doctrine\Common\Persistence\Mapping\ClassMetadataFactory $metadataFactory
- * @param bool $autoGenerate
+ * @param bool|int $autoGenerate
*/
public function __construct(ProxyGenerator $proxyGenerator, ClassMetadataFactory $metadataFactory, $autoGenerate)
{
$this->proxyGenerator = $proxyGenerator;
$this->metadataFactory = $metadataFactory;
- $this->autoGenerate = $autoGenerate;
+ $this->autoGenerate = (int)$autoGenerate;
}
/**
@@ -158,11 +195,27 @@ private function getProxyDefinition($className)
if ( ! class_exists($proxyClassName, false)) {
$fileName = $this->proxyGenerator->getProxyFileName($className);
- if ($this->autoGenerate) {
- $this->proxyGenerator->generateProxyClass($classMetadata);
+ switch ($this->autoGenerate) {
+ case self::AUTOGENERATE_NEVER:
+ require $fileName;
+ break;
+
+ case self::AUTOGENERATE_FILE_NOT_EXISTS:
+ if ( ! file_exists($fileName)) {
+ $this->proxyGenerator->generateProxyClass($classMetadata, $fileName);
+ }
+ require $fileName;
+ break;
+
+ case self::AUTOGENERATE_ALWAYS:
+ $this->proxyGenerator->generateProxyClass($classMetadata, $fileName);
+ require $fileName;
+ break;
+
+ case self::AUTOGENERATE_EVAL:
+ $this->proxyGenerator->generateProxyClass($classMetadata, false);
+ break;
}
-
- require $fileName;
}
return $this->definitions[$className];
View
18 lib/Doctrine/Common/Proxy/ProxyGenerator.php
@@ -254,11 +254,11 @@ public function setProxyClassTemplate($proxyClassTemplate)
* Generates a proxy class file.
*
* @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class Metadata for the original class.
- * @param string $fileName Filename (full path) for the generated class.
+ * @param string|bool $fileName Filename (full path) for the generated class. If none is given, eval() is used.
*
* @throws UnexpectedValueException
*/
- public function generateProxyClass(ClassMetadata $class, $fileName = null)
+ public function generateProxyClass(ClassMetadata $class, $fileName = false)
{
preg_match_all('(<([a-zA-Z]+)>)', $this->proxyClassTemplate, $placeholderMatches);
@@ -277,8 +277,18 @@ public function generateProxyClass(ClassMetadata $class, $fileName = null)
}
}
- $proxyCode = strtr($this->proxyClassTemplate, $placeholders);
- $fileName = $fileName ?: $this->getProxyFileName($class->getName());
+ $proxyCode = strtr($this->proxyClassTemplate, $placeholders);
+
+ if ( ! $fileName) {
+ $proxyClassName = $this->generateNamespace($class) . '\\' . $this->generateProxyShortClassName($class);
+
+ if ( ! class_exists($proxyClassName)) {
+ eval(substr($proxyCode, 5));
+ }
+
+ return;
+ }
+
$parentDirectory = dirname($fileName);
if ( ! is_dir($parentDirectory) && (false === @mkdir($parentDirectory, 0775, true))) {
View
70 tests/Doctrine/Tests/Common/Proxy/ProxyClassGeneratorTest.php
@@ -61,8 +61,7 @@ protected function setUp()
return;
}
- $this->proxyGenerator->generateProxyClass($this->metadata);
- require_once $this->proxyGenerator->getProxyFileName($this->metadata->getName());
+ $this->generateAndRequire($this->proxyGenerator, $this->metadata);
}
public function testReferenceProxyRespectsMethodsParametersTypeHinting()
@@ -107,38 +106,37 @@ public function testNonNamespacedProxyGeneration()
public function testClassWithSleepProxyGeneration()
{
if (!class_exists('Doctrine\Tests\Common\ProxyProxy\__CG__\SleepClass', false)) {
- $metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata');
- $reflClass = new ReflectionClass('Doctrine\Tests\Common\Proxy\SleepClass');
- $metadata->expects($this->any())->method('getReflectionClass')->will($this->returnValue($reflClass));
- $metadata->expects($this->any())->method('getIdentifierFieldNames')->will($this->returnValue(array('id')));
- $metadata->expects($this->any())->method('getName')->will($this->returnValue($reflClass->getName()));
+ $className = 'Doctrine\Tests\Common\Proxy\SleepClass';
+ $metadata = $this->createClassMetadata($className, array('id'));
$proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true);
- $proxyGenerator->generateProxyClass($metadata);
- require_once $proxyGenerator->getProxyFileName($metadata->getName());
+
+ $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()'));
}
+ 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)) {
- $metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata');
- $reflClass = new ReflectionClass('Doctrine\Tests\Common\Proxy\CallableTypeHintClass');
- $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true);
-
- $metadata->expects($this->any())->method('getReflectionClass')->will($this->returnValue($reflClass));
- $metadata->expects($this->any())->method('getIdentifierFieldNames')->will($this->returnValue(array('id')));
- $metadata->expects($this->any())->method('getName')->will($this->returnValue($reflClass->getName()));
+ $className = 'Doctrine\Tests\Common\Proxy\CallableTypeHintClass';
+ $metadata = $this->createClassMetadata($className, array('id'));
- $proxyGenerator->generateProxyClass($metadata);
- require_once $proxyGenerator->getProxyFileName($metadata->getName());
+ $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true);
+ $this->generateAndRequire($proxyGenerator, $metadata);
}
$classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxyCallableTypeHintClass.php');
@@ -149,11 +147,7 @@ public function testClassWithCallableTypeHintOnProxiedMethod()
public function testClassWithInvalidTypeHintOnProxiedMethod()
{
$className = 'Doctrine\Tests\Common\Proxy\InvalidTypeHintClass';
- $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(array()));
- $metadata->expects($this->any())->method('getName')->will($this->returnValue($className));
+ $metadata = $this->createClassMetadata($className, array('id'));
$proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true);
$this->setExpectedException(
@@ -182,4 +176,34 @@ public function testInvalidPlaceholderThrowsException()
$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
+{
}
View
2 tests/Doctrine/Tests/Common/Proxy/ProxyMagicMethodsTest.php
@@ -299,7 +299,7 @@ private function generateProxyClass($className)
->method('getTypeOfField')
->will($this->returnValue('string'));
- $this->proxyGenerator->generateProxyClass($metadata);
+ $this->proxyGenerator->generateProxyClass($metadata, $this->proxyGenerator->getProxyFileName($className));
require_once $this->proxyGenerator->getProxyFileName($className);
return $proxyClassName;

0 comments on commit 7877938

Please sign in to comment.