Compare commits

...

65 Commits

Author SHA1 Message Date
Benjamin Eberlei 0363a5548d Release 2.4.2 2014-02-08 17:35:09 +01:00
Benjamin Eberlei 3764e49e6c Merge branch 'DDC-2895' into 2.4 2014-02-08 16:01:57 +01:00
Geoffrey Wagner 6ee20204a5 Fix some code standard things 2014-02-08 16:01:41 +01:00
Geoffrey Wagner d9b0c87ded Fix some code standard things 2014-02-08 16:01:41 +01:00
Geoffrey Wagner 8594e5c4da Add a test
addLifecycleCallback now only allows a callback once so we do not hook them twice
2014-02-08 16:01:41 +01:00
Geoffrey Wagner 5f821f3b98 Fix Lifecycle Callbacks
Remove a bit of code that breaks lifecycle callbacks of parent MappedSuperclasses
2014-02-08 16:01:41 +01:00
Benjamin Eberlei b566525099 Merge branch 'DDC-2931' into 2.4 2014-02-08 15:53:12 +01:00
Marco Pivetta 215c4a03e1 DDC-2931 - Removing previous broken fix for DDC-2931 - hardened 2014-02-08 15:52:46 +01:00
Marco Pivetta b3ccd6466b DDC-2931 - Safe comparison between proxies and entities when refreshing objects 2014-02-08 15:52:46 +01:00
Marco Pivetta b596bbb29f DDC-2931 - adding test that verifies that fetch-joined entities get refreshed with hints 2014-02-08 15:52:46 +01:00
Marco Pivetta c204e6c6a1 DDC-2931 - removing old comments 2014-02-08 15:52:46 +01:00
Marco Pivetta 0bc94589e1 DDC-2931 - Removing refresh hints when fetching association data in hydrators 2014-02-08 15:52:45 +01:00
Marco Pivetta f37856829f DDC-2931 - Detailed explanation 2014-02-08 15:52:45 +01:00
Marco Pivetta 157c793810 DDC-2931 - cleaning up code formatting/simplifying test case 2014-02-08 15:52:45 +01:00
root 72d838a804 [DDC-2931] testcase to reproduce Jira 2931 2014-02-08 15:52:45 +01:00
Benjamin Eberlei 58f8dc5d4c Update UPGRADE.md notes with BC mention. 2014-02-08 15:42:09 +01:00
Benjamin Eberlei 7d3ecd9481 Merge branch 'DDC-2947' into 2.4 2014-02-08 15:31:56 +01:00
Tim Lieberman 1bb55703a7 Make SchemaTool and SchemaValidator use EntityManagerInterface instead of EntityManager 2014-02-08 15:31:08 +01:00
Tim Lieberman 56cbcec13d Substitute EntityManagerInterface for EntityManager in Console EntityManagerHelper 2014-02-08 15:31:07 +01:00
Tim Lieberman 837c19bfc0 Console EntityManagerHelper now accepts EntityManagerInterface as constructor argument, instead of insisting on an EntityManager 2014-02-08 15:31:07 +01:00
Benjamin Eberlei 7b8f09ee4a Merge branch 'DDC-2700' into 2.4 2014-01-02 23:51:07 +01:00
Benjamin Eberlei 488a4dc78a [DDC-2700] Add test and fix CS. 2014-01-02 23:50:37 +01:00
Alex Pogodin 1364b6acc6 Identifier can be empty for MappedSuperclasses
When MappedSuperclass is inspected without identifier column been assigned, always return false. Solves "Undefined offset" notice.
2014-01-02 23:50:37 +01:00
Benjamin Eberlei 3dbe181762 Merge branch 'DDC-2732' into 2.4 2014-01-02 23:34:44 +01:00
Benjamin Eberlei a3acaab65c [DDC-2732] Add tests for XML id options fix. 2014-01-02 23:34:17 +01:00
Eduardo f183d25a33 Options not respected for ID Fields in XML Mapping Driver (XSD update)
XSD update.

The same bug of the yaml driver: see http://www.doctrine-project.org/jira/browse/DDC-2661
2014-01-02 23:34:17 +01:00
Eduardo 7c8350094e Options not respected for ID Fields in XML Mapping Driver
Same bug of the YAML driver, see: http://www.doctrine-project.org/jira/browse/DDC-2661
2014-01-02 23:34:17 +01:00
Benjamin Eberlei c613410ba6 Merge branch 'DDC-2764' into 2.4 2014-01-02 23:16:56 +01:00
Sander Marechal 6bb7581dd7 Add rootAlias to Criteria where clauses 2014-01-02 23:16:35 +01:00
Sander Marechal ab71dab7d1 Set rootAlias outside loop 2014-01-02 23:15:31 +01:00
Sander Marechal 2c114756bd [DDC-2764] Prefix criteria orderBy with rootAlias 2014-01-02 23:15:31 +01:00
Benjamin Eberlei 45496f040d Merge branch 'DDC-2775' into 2.4 2014-01-02 23:11:16 +01:00
Benjamin Eberlei b40866c624 [DDC-2775] cleanup test. 2014-01-02 23:11:07 +01:00
Matthieu Napoli a89cc7abea Inlined the model for the DCC2775 test case inside the test class 2014-01-02 23:07:53 +01:00
Matthieu Napoli 5ac111e5f8 Cleaned up tests for DDC-2775 2014-01-02 23:07:53 +01:00
Matthieu Napoli c5f66e6e7f Fixed tests failing in pgsql because of used of a reserved keyword 2014-01-02 23:07:53 +01:00
Matthieu Napoli b59f495875 Fixed tests for pgsql: was using reserved keyword as table name 2014-01-02 23:07:53 +01:00
Matthieu Napoli 3829b9c28b [DDC-2775] Bugfix 2014-01-02 23:07:53 +01:00
Matthieu Napoli 65bcdbf4c7 [DDC-2775] Tests reproducing DDC-2775 2014-01-02 23:07:53 +01:00
Benjamin Eberlei 95d000e51b Merge branch 'DDC-2692' into 2.4 2014-01-02 22:17:20 +01:00
Stefan Kleff 3657df3b01 Listener class prefix 2014-01-02 22:16:59 +01:00
Stefan Kleff 1661ffae9a removed unused use statements, fixed typo and group tag 2014-01-02 22:16:59 +01:00
Stefan Kleff b424a5cf14 Added unit test 2014-01-02 22:16:59 +01:00
Stefan Kleff 2767a4eec4 Multiple invokation of listeners on PreFlush event
Only lifecycle callbacks and entity listeners should be triggered here. The preFlush listener event is already triggered at the beginning of commit()
2014-01-02 22:16:59 +01:00
Benjamin Eberlei 9486867279 Merge branch 'DDC-2645' into 2.4 2013-12-15 23:34:57 +01:00
Pouyan Savoli 6f2bb08972 [DDC-2645] Apply patch to fix issue 2013-12-15 23:34:34 +01:00
Aaron Muylaert da2d3b406e Create failing test for DDC-2645.
Merge not dealing correctly with composite primary keys.
2013-12-15 23:34:34 +01:00
Benjamin Eberlei c4b7d3fbea Bump version to 2.4.2 2013-11-12 13:40:15 +01:00
Benjamin Eberlei 84373d05a4 Release 2.4.1 2013-11-12 13:40:13 +01:00
Benjamin Eberlei e82e7147fa Merge branch 'DDC-2715' into 2.4 2013-10-29 09:25:13 +01:00
jan brunnert e23ed2250d Removed unnecessary is_object() check 2013-10-29 09:24:52 +01:00
jan brunnert 192bb6fd21 When the OptimisticLockingException is generated with the static function lockFailedVersionMismatch and the passed parameters are DateTime instances, the exception could not be thrown because the DateTime object is not implicitly converted to a string. 2013-10-29 09:24:52 +01:00
Benjamin Eberlei 0f3679f034 Merge branch 'DDC-2759' into 2.4 2013-10-26 11:17:34 +02:00
Benjamin Eberlei 1d2cd82706 [DDC-2759] Fix regression in ArrayHydrator introduced in DDC-1884 at SHA c7b4c9bf0f 2013-10-26 11:16:53 +02:00
Chris Collins b983d86612 Added a failing test case for DDC-2759. 2013-10-26 11:16:53 +02:00
Benjamin Eberlei b11f01643c Merge branch 'DDC-2668' into 2.4 2013-09-26 23:24:14 +02:00
Fabio B. Silva b58fb8f5d4 [DDC-2668] Fix trim leading zero string 2013-09-26 23:23:49 +02:00
Benjamin Eberlei 925a22b71d Merge branch 'DDC-2608' into 2.4 2013-09-08 16:01:38 +02:00
Benjamin Eberlei 0f0d8abd67 [DDC-2608][DDC-2662] Fix SequenceGenerator requiring "sequenceName" and now throw exception. Fix a bug in quoting the sequenceName. 2013-09-08 16:00:14 +02:00
Benjamin Eberlei 470c15ce05 Merge branch 'DDC-2660' into 2.4 2013-09-08 14:39:54 +02:00
Benjamin Eberlei 3cc5fc0252 [DDC-2660] Fix error with NativeSQL, ResultSetMappingBuilder and Associations as Primary Key. 2013-09-08 14:39:25 +02:00
Benjamin Eberlei fd0657089a Merge branch 'DDC-2661' into 2.4 2013-09-08 10:38:03 +02:00
Benjamin Eberlei de3b237292 [DDC-2661] Fix bug in YamlDriver not passing options from id to mapField() 2013-09-08 10:37:42 +02:00
Benjamin Eberlei 1221cc3a2a More excludes 2013-09-07 18:27:20 +02:00
Benjamin Eberlei 9efbc1fa71 Bump version to 2.4.1 2013-09-07 18:19:57 +02:00
35 changed files with 1101 additions and 95 deletions
+6
View File
@@ -44,6 +44,12 @@ Now parenthesis are considered, the previous DQL will generate:
# Upgrade to 2.3
## Auto Discriminator Map breaks userland implementations with Listener
The new feature to detect discriminator maps automatically when none
are provided breaks userland implementations doing this with a
listener in ``loadClassMetadata`` event.
## EntityManager#find() not calls EntityRepository#find() anymore
Previous to 2.3, calling ``EntityManager#find()`` would be delegated to
+1 -1
View File
@@ -35,6 +35,6 @@
}
},
"archive": {
"exclude": ["!vendor", "tests", "*phpunit.xml", ".travis.yml", "build.xml", "build.properties", "composer.phar", "vendor/satooshi", "lib/vendor"]
"exclude": ["!vendor", "tests", "*phpunit.xml", ".travis.yml", "build.xml", "build.properties", "composer.phar", "vendor/satooshi", "lib/vendor", "*.swp", "*coveralls.yml"]
}
}
+1
View File
@@ -350,6 +350,7 @@
<xs:element name="generator" type="orm:generator" minOccurs="0" />
<xs:element name="sequence-generator" type="orm:sequence-generator" minOccurs="0" maxOccurs="1" />
<xs:element name="custom-id-generator" type="orm:custom-id-generator" minOccurs="0" maxOccurs="1" />
<xs:element name="options" type="orm:options" minOccurs="0" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
@@ -190,17 +190,14 @@ class ArrayHydrator extends AbstractHydrator
( ! isset($baseElement[$relationAlias]))
) {
$baseElement[$relationAlias] = null;
} else if (
( ! isset($baseElement[$relationAlias])) ||
( ! isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]))
) {
} else if ( ! isset($baseElement[$relationAlias])) {
$baseElement[$relationAlias] = $data;
}
}
$coll =& $baseElement[$relationAlias];
if ($coll !== null) {
if (is_array($coll)) {
$this->updateResultPointer($coll, $index, $dqlAlias, $oneToOne);
}
} else {
+15 -2
View File
@@ -1031,9 +1031,14 @@ class ClassMetadataInfo implements ClassMetadata
*/
public function isIdentifier($fieldName)
{
if ( ! $this->identifier) {
return false;
}
if ( ! $this->isIdentifierComposite) {
return $fieldName === $this->identifier[0];
}
return in_array($fieldName, $this->identifier);
}
@@ -2483,6 +2488,10 @@ class ClassMetadataInfo implements ClassMetadata
*/
public function addLifecycleCallback($callback, $event)
{
if(isset($this->lifecycleCallbacks[$event]) && in_array($callback, $this->lifecycleCallbacks[$event])) {
return;
}
$this->lifecycleCallbacks[$event][] = $callback;
}
@@ -2790,8 +2799,12 @@ class ClassMetadataInfo implements ClassMetadata
*/
public function setSequenceGeneratorDefinition(array $definition)
{
if (isset($definition['name']) && $definition['name'] == '`') {
$definition['name'] = trim($definition['name'], '`');
if ( ! isset($definition['sequenceName'])) {
throw MappingException::missingSequenceName($this->name);
}
if ($definition['sequenceName'][0] == '`') {
$definition['sequenceName'] = trim($definition['sequenceName'], '`');
$definition['quoted'] = true;
}
@@ -450,12 +450,9 @@ class AnnotationDriver extends AbstractAnnotationDriver
if (isset($classAnnotations['Doctrine\ORM\Mapping\HasLifecycleCallbacks'])) {
/* @var $method \ReflectionMethod */
foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
// filter for the declaring class only, callbacks from parents will already be registered.
if ($method->getDeclaringClass()->name !== $class->name) {
continue;
}
foreach ($this->getMethodCallbacks($method) as $value) {
$metadata->addLifecycleCallback($value[0], $value[1]);
}
}
@@ -278,6 +278,10 @@ class XmlDriver extends FileDriver
$mapping['columnDefinition'] = (string)$idElement['column-definition'];
}
if (isset($idElement->options)) {
$mapping['options'] = $this->_parseOptions($idElement->options->children());
}
$metadata->mapField($mapping);
if (isset($idElement->generator)) {
@@ -264,6 +264,10 @@ class YamlDriver extends FileDriver
$mapping['columnDefinition'] = $idElement['columnDefinition'];
}
if (isset($idElement['options'])) {
$mapping['options'] = $idElement['options'];
}
$metadata->mapField($mapping);
if (isset($idElement['generator'])) {
@@ -757,4 +757,16 @@ class MappingException extends \Doctrine\ORM\ORMException
$cascades
));
}
/**
* @param string $className
*
* @return MappingException
*/
public static function missingSequenceName($className)
{
return new self(
sprintf('Missing "sequenceName" attribute for sequence id generator definition on class "%s".', $className)
);
}
}
@@ -73,6 +73,8 @@ class OptimisticLockException extends ORMException
*/
public static function lockFailedVersionMismatch($entity, $expectedLockVersion, $actualLockVersion)
{
$expectedLockVersion = ($expectedLockVersion instanceof \DateTime) ? $expectedLockVersion->getTimestamp() : $expectedLockVersion;
$actualLockVersion = ($actualLockVersion instanceof \DateTime) ? $actualLockVersion->getTimestamp() : $actualLockVersion;
return new self("The optimistic lock failed, version " . $expectedLockVersion . " was expected, but is actually ".$actualLockVersion, $entity);
}
@@ -20,6 +20,8 @@
namespace Doctrine\ORM\Query\AST\Functions;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
@@ -36,71 +38,60 @@ use Doctrine\DBAL\Platforms\AbstractPlatform;
class TrimFunction extends FunctionNode
{
/**
* @var bool
* @var boolean
*/
public $leading;
/**
* @var bool
* @var boolean
*/
public $trailing;
/**
* @var bool
* @var boolean
*/
public $both;
/**
* @var bool
* @var boolean
*/
public $trimChar = false;
/**
* @var \Doctrine\ORM\Query\AST\Node
*/
public $stringPrimary;
/**
* @override
* {@inheritdoc}
*/
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
public function getSql(SqlWalker $sqlWalker)
{
$pos = AbstractPlatform::TRIM_UNSPECIFIED;
if ($this->leading) {
$pos = AbstractPlatform::TRIM_LEADING;
} else if ($this->trailing) {
$pos = AbstractPlatform::TRIM_TRAILING;
} else if ($this->both) {
$pos = AbstractPlatform::TRIM_BOTH;
}
$stringPrimary = $sqlWalker->walkStringPrimary($this->stringPrimary);
$platform = $sqlWalker->getConnection()->getDatabasePlatform();
$trimMode = $this->getTrimMode();
$trimChar = ($this->trimChar !== false)
? $sqlWalker->getConnection()->quote($this->trimChar)
: false;
return $sqlWalker->getConnection()->getDatabasePlatform()->getTrimExpression(
$sqlWalker->walkStringPrimary($this->stringPrimary),
$pos,
($this->trimChar != false) ? $sqlWalker->getConnection()->quote($this->trimChar) : false
);
return $platform->getTrimExpression($stringPrimary, $trimMode, $trimChar);
}
/**
* @override
* {@inheritdoc}
*/
public function parse(\Doctrine\ORM\Query\Parser $parser)
public function parse(Parser $parser)
{
$lexer = $parser->getLexer();
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
if (strcasecmp('leading', $lexer->lookahead['value']) === 0) {
$parser->match(Lexer::T_LEADING);
$this->leading = true;
} else if (strcasecmp('trailing', $lexer->lookahead['value']) === 0) {
$parser->match(Lexer::T_TRAILING);
$this->trailing = true;
} else if (strcasecmp('both', $lexer->lookahead['value']) === 0) {
$parser->match(Lexer::T_BOTH);
$this->both = true;
}
$this->parseTrimMode($parser);
if ($lexer->isNextToken(Lexer::T_STRING)) {
$parser->match(Lexer::T_STRING);
$this->trimChar = $lexer->token['value'];
}
@@ -112,4 +103,61 @@ class TrimFunction extends FunctionNode
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
/**
* @param \Doctrine\ORM\Query\Parser $parser
*
* @return integer
*/
private function getTrimMode()
{
if ($this->leading) {
return AbstractPlatform::TRIM_LEADING;
}
if ($this->trailing) {
return AbstractPlatform::TRIM_TRAILING;
}
if ($this->both) {
return AbstractPlatform::TRIM_BOTH;
}
return AbstractPlatform::TRIM_UNSPECIFIED;
}
/**
* @param \Doctrine\ORM\Query\Parser $parser
*
* @return void
*/
private function parseTrimMode(Parser $parser)
{
$lexer = $parser->getLexer();
$value = $lexer->lookahead['value'];
if (strcasecmp('leading', $value) === 0) {
$parser->match(Lexer::T_LEADING);
$this->leading = true;
return;
}
if (strcasecmp('trailing', $value) === 0) {
$parser->match(Lexer::T_TRAILING);
$this->trailing = true;
return;
}
if (strcasecmp('both', $value) === 0) {
$parser->match(Lexer::T_BOTH);
$this->both = true;
return;
}
}
}
@@ -47,6 +47,11 @@ class QueryExpressionVisitor extends ExpressionVisitor
Comparison::LTE => Expr\Comparison::LTE
);
/**
* @var string
*/
private $rootAlias;
/**
* @var Expr
*/
@@ -58,10 +63,13 @@ class QueryExpressionVisitor extends ExpressionVisitor
private $parameters = array();
/**
* Constructor with internal initialization.
* Constructor
*
* @param string $rootAlias
*/
public function __construct()
public function __construct($rootAlias)
{
$this->rootAlias = $rootAlias;
$this->expr = new Expr();
}
@@ -133,33 +141,33 @@ class QueryExpressionVisitor extends ExpressionVisitor
switch ($comparison->getOperator()) {
case Comparison::IN:
$this->parameters[] = $parameter;
return $this->expr->in($comparison->getField(), $placeholder);
return $this->expr->in($this->rootAlias . '.' . $comparison->getField(), $placeholder);
case Comparison::NIN:
$this->parameters[] = $parameter;
return $this->expr->notIn($comparison->getField(), $placeholder);
return $this->expr->notIn($this->rootAlias . '.' . $comparison->getField(), $placeholder);
case Comparison::EQ:
case Comparison::IS:
if ($this->walkValue($comparison->getValue()) === null) {
return $this->expr->isNull($comparison->getField());
return $this->expr->isNull($this->rootAlias . '.' . $comparison->getField());
}
$this->parameters[] = $parameter;
return $this->expr->eq($comparison->getField(), $placeholder);
return $this->expr->eq($this->rootAlias . '.' . $comparison->getField(), $placeholder);
case Comparison::NEQ:
if ($this->walkValue($comparison->getValue()) === null) {
return $this->expr->isNotNull($comparison->getField());
return $this->expr->isNotNull($this->rootAlias . '.' . $comparison->getField());
}
$this->parameters[] = $parameter;
return $this->expr->neq($comparison->getField(), $placeholder);
return $this->expr->neq($this->rootAlias . '.' . $comparison->getField(), $placeholder);
default:
$operator = self::convertComparisonOperator($comparison->getOperator());
if ($operator) {
$this->parameters[] = $parameter;
return new Expr\Comparison(
$comparison->getField(),
$this->rootAlias . '.' . $comparison->getField(),
$operator,
$placeholder
);
@@ -168,7 +168,12 @@ class ResultSetMappingBuilder extends ResultSetMapping
throw new \InvalidArgumentException("The column '$columnAlias' conflicts with another column in the mapper.");
}
$this->addMetaResult($alias, $columnAlias, $columnName);
$this->addMetaResult(
$alias,
$columnAlias,
$columnName,
(isset($associationMapping['id']) && $associationMapping['id'] === true)
);
}
}
}
+3 -2
View File
@@ -1087,7 +1087,8 @@ class QueryBuilder
*/
public function addCriteria(Criteria $criteria)
{
$visitor = new QueryExpressionVisitor();
$rootAlias = $this->getRootAlias();
$visitor = new QueryExpressionVisitor($rootAlias);
if ($whereExpression = $criteria->getWhereExpression()) {
$this->andWhere($visitor->dispatch($whereExpression));
@@ -1098,7 +1099,7 @@ class QueryBuilder
if ($criteria->getOrderings()) {
foreach ($criteria->getOrderings() as $sort => $order) {
$this->addOrderBy($sort, $order);
$this->addOrderBy($rootAlias . '.' . $sort, $order);
}
}
@@ -19,8 +19,9 @@
namespace Doctrine\ORM\Tools\Console\Helper;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Helper\Helper;
use Doctrine\ORM\EntityManager;
/**
* Doctrine CLI Connection Helper.
@@ -35,18 +36,18 @@ use Doctrine\ORM\EntityManager;
class EntityManagerHelper extends Helper
{
/**
* Doctrine ORM EntityManager.
* Doctrine ORM EntityManagerInterface.
*
* @var EntityManager
* @var EntityManagerInterface
*/
protected $_em;
/**
* Constructor.
*
* @param \Doctrine\ORM\EntityManager $em
* @param EntityManagerInterface $em
*/
public function __construct(EntityManager $em)
public function __construct(EntityManagerInterface $em)
{
$this->_em = $em;
}
@@ -54,7 +55,7 @@ class EntityManagerHelper extends Helper
/**
* Retrieves Doctrine ORM EntityManager.
*
* @return EntityManager
* @return EntityManagerInterface
*/
public function getEntityManager()
{
+4 -4
View File
@@ -26,7 +26,7 @@ use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector;
use Doctrine\DBAL\Schema\Visitor\RemoveNamespacedAssets;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Internal\CommitOrderCalculator;
use Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs;
@@ -47,7 +47,7 @@ use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
class SchemaTool
{
/**
* @var \Doctrine\ORM\EntityManager
* @var \Doctrine\ORM\EntityManagerInterface
*/
private $em;
@@ -67,9 +67,9 @@ class SchemaTool
* Initializes a new SchemaTool instance that uses the connection of the
* provided EntityManager.
*
* @param \Doctrine\ORM\EntityManager $em
* @param \Doctrine\ORM\EntityManagerInterface $em
*/
public function __construct(EntityManager $em)
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
$this->platform = $em->getConnection()->getDatabasePlatform();
+4 -4
View File
@@ -19,7 +19,7 @@
namespace Doctrine\ORM\Tools;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\DBAL\Types\Type;
@@ -37,14 +37,14 @@ use Doctrine\DBAL\Types\Type;
class SchemaValidator
{
/**
* @var EntityManager
* @var EntityManagerInterface
*/
private $em;
/**
* @param EntityManager $em
* @param EntityManagerInterface $em
*/
public function __construct(EntityManager $em)
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
+47 -6
View File
@@ -530,7 +530,7 @@ class UnitOfWork implements PropertyChangedListener
$class = $this->em->getClassMetadata(get_class($entity));
}
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preFlush);
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preFlush) & ~ListenersInvoker::INVOKE_MANAGER;
if ($invoke !== ListenersInvoker::INVOKE_NONE) {
$this->listenersInvoker->invoke($class, Events::preFlush, $entity, new PreFlushEventArgs($this->em), $invoke);
@@ -1736,6 +1736,8 @@ class UnitOfWork implements PropertyChangedListener
$associatedId = $this->getEntityIdentifier($idValue);
$flatId[$idField] = $associatedId[$targetClassMetadata->identifier[0]];
} else {
$flatId[$idField] = $idValue;
}
}
@@ -2231,6 +2233,8 @@ class UnitOfWork implements PropertyChangedListener
function ($assoc) { return $assoc['isCascadeRemove']; }
);
$entitiesToCascade = array();
foreach ($associationMappings as $assoc) {
if ($entity instanceof Proxy && !$entity->__isInitialized__) {
$entity->__load();
@@ -2243,18 +2247,22 @@ class UnitOfWork implements PropertyChangedListener
case (is_array($relatedEntities)):
// If its a PersistentCollection initialization is intended! No unwrap!
foreach ($relatedEntities as $relatedEntity) {
$this->doRemove($relatedEntity, $visited);
$entitiesToCascade[] = $relatedEntity;
}
break;
case ($relatedEntities !== null):
$this->doRemove($relatedEntities, $visited);
$entitiesToCascade[] = $relatedEntities;
break;
default:
// Do nothing
}
}
foreach ($entitiesToCascade as $relatedEntity) {
$this->doRemove($relatedEntity, $visited);
}
}
/**
@@ -2490,14 +2498,14 @@ class UnitOfWork implements PropertyChangedListener
&& isset($hints[Query::HINT_REFRESH_ENTITY])
&& ($unmanagedProxy = $hints[Query::HINT_REFRESH_ENTITY]) !== $entity
&& $unmanagedProxy instanceof Proxy
&& (($unmanagedProxyClass = $this->em->getClassMetadata(get_class($unmanagedProxy))) === $class)
&& $this->isIdentifierEquals($unmanagedProxy, $entity)
) {
// DDC-1238 - we have a managed instance, but it isn't the provided one.
// Therefore we clear its identifier. Also, we must re-fetch metadata since the
// refreshed object may be anything
foreach ($unmanagedProxyClass->identifier as $fieldName) {
$unmanagedProxyClass->reflFields[$fieldName]->setValue($unmanagedProxy, null);
foreach ($class->identifier as $fieldName) {
$class->reflFields[$fieldName]->setValue($unmanagedProxy, null);
}
return $unmanagedProxy;
@@ -3206,4 +3214,37 @@ class UnitOfWork implements PropertyChangedListener
$this->evm->dispatchEvent(Events::postFlush, new PostFlushEventArgs($this->em));
}
}
/**
* Verifies if two given entities actually are the same based on identifier comparison
*
* @param object $entity1
* @param object $entity2
*
* @return bool
*/
private function isIdentifierEquals($entity1, $entity2)
{
if ($entity1 === $entity2) {
return true;
}
$class = $this->em->getClassMetadata(get_class($entity1));
if ($class !== $this->em->getClassMetadata(get_class($entity2))) {
return false;
}
$oid1 = spl_object_hash($entity1);
$oid2 = spl_object_hash($entity2);
$id1 = isset($this->entityIdentifiers[$oid1])
? $this->entityIdentifiers[$oid1]
: $this->flattenIdentifier($class, $class->getIdentifierValues($entity1));
$id2 = isset($this->entityIdentifiers[$oid2])
? $this->entityIdentifiers[$oid2]
: $this->flattenIdentifier($class, $class->getIdentifierValues($entity2));
return $id1 === $id2 || implode(' ', $id1) === implode(' ', $id2);
}
}
+1 -1
View File
@@ -36,7 +36,7 @@ class Version
/**
* Current Doctrine Version
*/
const VERSION = '2.4.0';
const VERSION = '2.4.2';
/**
* Compares a Doctrine version with the current one.
@@ -7,6 +7,8 @@ use Doctrine\ORM\OptimisticLockException;
use Doctrine\Common\EventManager;
use Doctrine\ORM\Mapping\ClassMetadataFactory;
use Doctrine\Tests\TestUtil;
use Doctrine\DBAL\LockMode;
use DateTime;
require_once __DIR__ . '/../../../TestInit.php';
@@ -181,13 +183,44 @@ class OptimisticTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_conn->executeQuery('UPDATE optimistic_timestamp SET version = ? WHERE id = ?', array(date($format, strtotime($test->version->format($format)) + 3600), $test->id));
// Try and update the record and it should throw an exception
$caughtException = null;
$test->name = 'Testing again';
try {
$this->_em->flush();
} catch (OptimisticLockException $e) {
$this->assertSame($test, $e->getEntity());
$caughtException = $e;
}
$this->assertNotNull($caughtException, "No OptimisticLockingException was thrown");
$this->assertSame($test, $caughtException->getEntity());
}
/**
* @depends testOptimisticTimestampSetsDefaultValue
*/
public function testOptimisticTimestampLockFailureThrowsException(OptimisticTimestamp $entity)
{
$q = $this->_em->createQuery('SELECT t FROM Doctrine\Tests\ORM\Functional\Locking\OptimisticTimestamp t WHERE t.id = :id');
$q->setParameter('id', $entity->id);
$test = $q->getSingleResult();
$this->assertInstanceOf('DateTime', $test->version);
// Try to lock the record with an older timestamp and it should throw an exception
$caughtException = null;
try {
$expectedVersionExpired = DateTime::createFromFormat('U', $test->version->getTimestamp()-3600);
$this->_em->lock($test, LockMode::OPTIMISTIC, $expectedVersionExpired);
} catch (OptimisticLockException $e) {
$caughtException = $e;
}
$this->assertNotNull($caughtException, "No OptimisticLockingException was thrown");
$this->assertSame($test, $caughtException->getEntity());
}
}
/**
@@ -0,0 +1,55 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-2645
*/
class DDC2645Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function testIssue()
{
$bar = new DDC2645Bar;
$bar->id = 123;
$foo = new DDC2645Foo(1, $bar, 'Foo');
$foo2 = new DDC2645Foo(1, $bar, 'Bar');
$this->_em->persist($bar);
$this->_em->persist($foo);
$foo3 = $this->_em->merge($foo2);
$this->assertSame($foo, $foo3);
$this->assertEquals('Bar', $foo->name);
}
}
/** @Entity */
class DDC2645Foo
{
/** @Id @Column(type="integer") */
private $id;
/** @Id @ManyToOne(targetEntity="DDC2645Bar") */
private $bar;
/** @Column */
public $name;
public function __construct($id, $bar, $name)
{
$this->id = $id;
$this->bar = $bar;
$this->name = $name;
}
}
/** @Entity */
class DDC2645Bar
{
/** @Id @Column(type="integer") @GeneratedValue(strategy="NONE") */
public $id;
}
@@ -0,0 +1,122 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\ORM\Query\ResultSetMappingBuilder;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @group
*/
class DDC2660Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
/**
* {@inheritDoc}
*/
protected function setup()
{
parent::setup();
try {
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2660Product'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2660Customer'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2660CustomerOrder')
));
} catch(\Exception $e) {
return;
}
for ($i = 0; $i < 5; $i++) {
$product = new DDC2660Product();
$customer = new DDC2660Customer();
$order = new DDC2660CustomerOrder($product, $customer, 'name' . $i);
$this->_em->persist($product);
$this->_em->persist($customer);
$this->_em->flush();
$this->_em->persist($order);
$this->_em->flush();
}
$this->_em->clear();
}
public function testIssueWithExtraColumn()
{
$sql = "SELECT o.product_id, o.customer_id, o.name FROM ddc_2660_customer_order o";
$rsm = new ResultSetMappingBuilder($this->_getEntityManager());
$rsm->addRootEntityFromClassMetadata(__NAMESPACE__ . '\DDC2660CustomerOrder', 'c');
$query = $this->_em->createNativeQuery($sql, $rsm);
$result = $query->getResult();
$this->assertCount(5, $result);
foreach ($result as $order) {
$this->assertNotNull($order);
$this->assertInstanceOf(__NAMESPACE__ . '\\DDC2660CustomerOrder', $order);
}
}
public function testIssueWithoutExtraColumn()
{
$sql = "SELECT o.product_id, o.customer_id FROM ddc_2660_customer_order o";
$rsm = new ResultSetMappingBuilder($this->_getEntityManager());
$rsm->addRootEntityFromClassMetadata(__NAMESPACE__ . '\DDC2660CustomerOrder', 'c');
$query = $this->_em->createNativeQuery($sql, $rsm);
$result = $query->getResult();
$this->assertCount(5, $result);
foreach ($result as $order) {
$this->assertNotNull($order);
$this->assertInstanceOf(__NAMESPACE__ . '\\DDC2660CustomerOrder', $order);
}
}
}
/**
* @Entity @Table(name="ddc_2660_product")
*/
class DDC2660Product
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
}
/** @Entity @Table(name="ddc_2660_customer") */
class DDC2660Customer
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
}
/** @Entity @Table(name="ddc_2660_customer_order") */
class DDC2660CustomerOrder
{
/**
* @Id @ManyToOne(targetEntity="DDC2660Product")
*/
public $product;
/**
* @Id @ManyToOne(targetEntity="DDC2660Customer")
*/
public $customer;
/**
* @Column(type="string")
*/
public $name;
public function __construct(DDC2660Product $product, DDC2660Customer $customer, $name)
{
$this->product = $product;
$this->customer = $customer;
$this->name = $name;
}
}
@@ -0,0 +1,63 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\PreFlushEventArgs;
/**
* @group DDC-2692
*/
class DDC2692Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
/**
* {@inheritDoc}
*/
protected function setup()
{
parent::setup();
try {
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2692Foo'),
));
} catch(\Exception $e) {
return;
}
$this->_em->clear();
}
public function testIsListenerCalledOnlyOnceOnPreFlush()
{
$listener = $this->getMock('Doctrine\Tests\ORM\Functional\Ticket\DDC2692Listener', array('preFlush'));
$listener->expects($this->once())->method('preFlush');
$this->_em->getEventManager()->addEventSubscriber($listener);
$this->_em->persist(new DDC2692Foo);
$this->_em->persist(new DDC2692Foo);
$this->_em->flush();
$this->_em->clear();
}
}
/**
* @Entity @Table(name="ddc_2692_foo")
*/
class DDC2692Foo
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
}
class DDC2692Listener implements EventSubscriber {
public function getSubscribedEvents() {
return array(\Doctrine\ORM\Events::preFlush);
}
public function preFlush(PreFlushEventArgs $args) {
}
}
@@ -0,0 +1,121 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
/**
* @group DDC-2759
*/
class DDC2759Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
/**
* {@inheritDoc}
*/
protected function setup()
{
parent::setup();
try {
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2759Qualification'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2759Category'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2759QualificationMetadata'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2759MetadataCategory'),
));
} catch(\Exception $e) {
return;
}
$qualification = new DDC2759Qualification();
$qualificationMetadata = new DDC2759QualificationMetadata($qualification);
$category1 = new DDC2759Category();
$category2 = new DDC2759Category();
$metadataCategory1 = new DDC2759MetadataCategory($qualificationMetadata, $category1);
$metadataCategory2 = new DDC2759MetadataCategory($qualificationMetadata, $category2);
$this->_em->persist($qualification);
$this->_em->persist($qualificationMetadata);
$this->_em->persist($category1);
$this->_em->persist($category2);
$this->_em->persist($metadataCategory1);
$this->_em->persist($metadataCategory2);
$this->_em->flush();
$this->_em->clear();
}
public function testCorrectNumberOfAssociationsIsReturned()
{
$repository = $this->_em->getRepository(__NAMESPACE__ . '\DDC2759Qualification');
$builder = $repository->createQueryBuilder('q')
->select('q, qm, qmc')
->innerJoin('q.metadata', 'qm')
->innerJoin('qm.metadataCategories', 'qmc');
$result = $builder->getQuery()
->getArrayResult();
$this->assertCount(2, $result[0]['metadata']['metadataCategories']);
}
}
/** @Entity @Table(name="ddc_2759_qualification") */
class DDC2759Qualification
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @OneToOne(targetEntity="DDC2759QualificationMetadata", mappedBy="content") */
public $metadata;
}
/** @Entity @Table(name="ddc_2759_category") */
class DDC2759Category
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @OneToMany(targetEntity="DDC2759MetadataCategory", mappedBy="category") */
public $metadataCategories;
}
/** @Entity @Table(name="ddc_2759_qualification_metadata") */
class DDC2759QualificationMetadata
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @OneToOne(targetEntity="DDC2759Qualification", inversedBy="metadata") */
public $content;
/** @OneToMany(targetEntity="DDC2759MetadataCategory", mappedBy="metadata") */
protected $metadataCategories;
public function __construct(DDC2759Qualification $content)
{
$this->content = $content;
}
}
/** @Entity @Table(name="ddc_2759_metadata_category") */
class DDC2759MetadataCategory
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @ManyToOne(targetEntity="DDC2759QualificationMetadata", inversedBy="metadataCategories") */
public $metadata;
/** @ManyToOne(targetEntity="DDC2759Category", inversedBy="metadataCategories") */
public $category;
public function __construct(DDC2759QualificationMetadata $metadata, DDC2759Category $category)
{
$this->metadata = $metadata;
$this->category = $category;
}
}
@@ -0,0 +1,146 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\OrmFunctionalTestCase;
/**
* Functional tests for cascade remove with class table inheritance.
*
* @author Matthieu Napoli <matthieu@mnapoli.fr>
*/
class DDC2775Test extends OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
$this->setUpEntitySchema(array(
'Doctrine\Tests\ORM\Functional\Ticket\User',
'Doctrine\Tests\ORM\Functional\Ticket\Role',
'Doctrine\Tests\ORM\Functional\Ticket\AdminRole',
'Doctrine\Tests\ORM\Functional\Ticket\Authorization',
));
}
/**
* @group DDC-2775
*/
public function testIssueCascadeRemove()
{
$user = new User();
$role = new AdminRole();
$user->addRole($role);
$authorization = new Authorization();
$user->addAuthorization($authorization);
$role->addAuthorization($authorization);
$this->_em->persist($user);
$this->_em->flush();
// Need to clear so that associations are lazy-loaded
$this->_em->clear();
$user = $this->_em->find('Doctrine\Tests\ORM\Functional\Ticket\User', $user->id);
$this->_em->remove($user);
$this->_em->flush();
// With the bug, the second flush throws an error because the cascade remove didn't work correctly
$this->_em->flush();
}
}
/**
* @Entity @Table(name="ddc2775_role")
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="role_type", type="string")
* @DiscriminatorMap({"admin"="AdminRole"})
*/
abstract class Role
{
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
public $id;
/**
* @ManyToOne(targetEntity="User", inversedBy="roles")
*/
public $user;
/**
* @OneToMany(targetEntity="Authorization", mappedBy="role", cascade={"all"}, orphanRemoval=true)
*/
public $authorizations;
public function addAuthorization(Authorization $authorization)
{
$this->authorizations[] = $authorization;
$authorization->role = $this;
}
}
/** @Entity @Table(name="ddc2775_admin_role") */
class AdminRole extends Role
{
}
/**
* @Entity @Table(name="ddc2775_authorizations")
*/
class Authorization
{
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
public $id;
/**
* @ManyToOne(targetEntity="User", inversedBy="authorizations")
*/
public $user;
/**
* @ManyToOne(targetEntity="Role", inversedBy="authorizations")
*/
public $role;
}
/**
* @Entity @Table(name="ddc2775_users")
*/
class User
{
/**
* @Id @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* @OneToMany(targetEntity="Role", mappedBy="user", cascade={"all"}, orphanRemoval=true)
*/
public $roles;
/**
* @OneToMany(targetEntity="Authorization", mappedBy="user", cascade={"all"}, orphanRemoval=true)
*/
public $authorizations;
public function addRole(Role $role)
{
$this->roles[] = $role;
$role->user = $this;
}
public function addAuthorization(Authorization $authorization)
{
$this->authorizations[] = $authorization;
$authorization->user = $this;
}
}
@@ -0,0 +1,112 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
/**
* Class DDC2895Test
* @package Doctrine\Tests\ORM\Functional\Ticket
* @author http://github.com/gwagner
*/
class DDC2895Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
parent::setUp();
try {
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC2895'),
));
} catch(\Exception $e) {
}
}
public function testPostLoadOneToManyInheritance()
{
$cm = $this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC2895');
$this->assertEquals(
array(
"prePersist" => array("setLastModifiedPreUpdate"),
"preUpdate" => array("setLastModifiedPreUpdate"),
),
$cm->lifecycleCallbacks
);
$ddc2895 = new DDC2895();
$this->_em->persist($ddc2895);
$this->_em->flush();
$this->_em->clear();
/** @var DDC2895 $ddc2895 */
$ddc2895 = $this->_em->find(get_class($ddc2895), $ddc2895->id);
$this->assertNotNull($ddc2895->getLastModified());
}
}
/**
* @MappedSuperclass
* @HasLifecycleCallbacks
*/
abstract class AbstractDDC2895
{
/**
* @Column(name="last_modified", type="datetimetz", nullable=false)
* @var \DateTime
*/
protected $lastModified;
/**
* @PrePersist
* @PreUpdate
*/
public function setLastModifiedPreUpdate()
{
$this->setLastModified(new \DateTime());
}
/**
* @param \DateTime $lastModified
*/
public function setLastModified( $lastModified )
{
$this->lastModified = $lastModified;
}
/**
* @return \DateTime
*/
public function getLastModified()
{
return $this->lastModified;
}
}
/**
* @Entity
* @HasLifecycleCallbacks
*/
class DDC2895 extends AbstractDDC2895
{
/** @Id @GeneratedValue @Column(type="integer") */
public $id;
/**
* @param mixed $id
*/
public function setId( $id )
{
$this->id = $id;
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
}
+119
View File
@@ -0,0 +1,119 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\ORM\Query;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-2931
*/
class DDC2931Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
parent::setUp();
try {
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2931User'),
));
} catch (\Exception $e) {
// no action needed - schema seems to be already in place
}
}
public function testIssue()
{
$first = new DDC2931User();
$second = new DDC2931User();
$third = new DDC2931User();
$second->parent = $first;
$third->parent = $second;
$this->_em->persist($first);
$this->_em->persist($second);
$this->_em->persist($third);
$this->_em->flush();
$this->_em->clear();
$second = $this->_em->find('Doctrine\Tests\ORM\Functional\Ticket\DDC2931User', $second->id);
$this->assertSame(2, $second->getRank());
}
public function testFetchJoinedEntitiesCanBeRefreshed()
{
$first = new DDC2931User();
$second = new DDC2931User();
$third = new DDC2931User();
$second->parent = $first;
$third->parent = $second;
$first->value = 1;
$second->value = 2;
$third->value = 3;
$this->_em->persist($first);
$this->_em->persist($second);
$this->_em->persist($third);
$this->_em->flush();
$first->value = 4;
$second->value = 5;
$third->value = 6;
$refreshedSecond = $this
->_em
->createQuery(
'SELECT e, p, c FROM '
. __NAMESPACE__ . '\\DDC2931User e LEFT JOIN e.parent p LEFT JOIN e.child c WHERE e = :id'
)
->setParameter('id', $second)
->setHint(Query::HINT_REFRESH, true)
->getResult();
$this->assertCount(1, $refreshedSecond);
$this->assertSame(1, $first->value);
$this->assertSame(2, $second->value);
$this->assertSame(3, $third->value);
}
}
/** @Entity */
class DDC2931User
{
/** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */
public $id;
/** @OneToOne(targetEntity="DDC2931User", inversedBy="child") */
public $parent;
/** @OneToOne(targetEntity="DDC2931User", mappedBy="parent") */
public $child;
/** @Column(type="integer") */
public $value = 0;
/**
* Return Rank recursively
* My rank is 1 + rank of my parent
* @return integer
*/
public function getRank()
{
return 1 + ($this->parent ? $this->parent->getRank() : 0);
}
public function __wakeup()
{
echo 'foo';
}
}
@@ -187,12 +187,32 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
$this->assertTrue($class->fieldMappings['name']['nullable']);
$this->assertTrue($class->fieldMappings['name']['unique']);
return $class;
}
/**
* @depends testEntityTableNameAndInheritance
* @param ClassMetadata $class
*/
public function testFieldOptions($class)
{
$expected = array('foo' => 'bar', 'baz' => array('key' => 'val'));
$this->assertEquals($expected, $class->fieldMappings['name']['options']);
return $class;
}
/**
* @depends testEntityTableNameAndInheritance
* @param ClassMetadata $class
*/
public function testIdFieldOptions($class)
{
$this->assertEquals(array('foo' => 'bar'), $class->fieldMappings['id']['options']);
return $class;
}
/**
* @depends testFieldMappings
* @param ClassMetadata $class
@@ -890,7 +910,7 @@ class User
{
/**
* @Id
* @Column(type="integer")
* @Column(type="integer", options={"foo": "bar"})
* @generatedValue(strategy="AUTO")
* @SequenceGenerator(sequenceName="tablename_seq", initialValue=1, allocationSize=100)
**/
@@ -971,6 +991,7 @@ class User
'fieldName' => 'id',
'type' => 'integer',
'columnName' => 'id',
'options' => array('foo' => 'bar'),
));
$metadata->mapField(array(
'fieldName' => 'name',
@@ -1066,6 +1066,50 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals(array('customtypeparent_source' => 'id'), $cm->associationMappings['friendsWithMe']['relationToSourceKeyColumns']);
$this->assertEquals(array('customtypeparent_target' => 'id'), $cm->associationMappings['friendsWithMe']['relationToTargetKeyColumns']);
}
/**
* @group DDC-2608
*/
public function testSetSequenceGeneratorThrowsExceptionWhenSequenceNameIsMissing()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException');
$cm->setSequenceGeneratorDefinition(array());
}
/**
* @group DDC-2662
*/
public function testQuotedSequenceName()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
$cm->setSequenceGeneratorDefinition(array('sequenceName' => '`foo`'));
$this->assertEquals(array('sequenceName' => 'foo', 'quoted' => true), $cm->sequenceGeneratorDefinition);
}
/**
* @group DDC-2700
*/
public function testIsIdentifierMappedSuperClass()
{
$class = new ClassMetadata(__NAMESPACE__ . '\\DDC2700MappedSuperClass');
$this->assertFalse($class->isIdentifier('foo'));
}
}
/**
* @MappedSuperclass
*/
class DDC2700MappedSuperClass
{
/** @Column */
private $foo;
}
class MyNamespacedNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStrategy
@@ -1092,4 +1136,4 @@ class MyPrefixNamingStrategy extends \Doctrine\ORM\Mapping\DefaultNamingStrategy
{
return strtolower($this->classToTableName($className)) . '_' . $propertyName;
}
}
}
@@ -19,6 +19,7 @@ $metadata->mapField(array(
'fieldName' => 'id',
'type' => 'integer',
'columnName' => 'id',
'options' => array('foo' => 'bar'),
));
$metadata->mapField(array(
'fieldName' => 'name',
@@ -35,6 +35,9 @@
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
<sequence-generator sequence-name="tablename_seq" allocation-size="100" initial-value="1" />
<options>
<option name="foo">bar</option>
</options>
</id>
<field name="name" column="name" type="string" length="50" nullable="true" unique="true">
@@ -16,6 +16,8 @@ Doctrine\Tests\ORM\Mapping\User:
sequenceName: tablename_seq
allocationSize: 100
initialValue: 1
options:
foo: bar
fields:
name:
type: string
@@ -47,7 +47,7 @@ class QueryExpressionVisitorTest extends \PHPUnit_Framework_TestCase
*/
protected function setUp()
{
$this->visitor = new QueryExpressionVisitor();
$this->visitor = new QueryExpressionVisitor('o');
}
/**
@@ -71,22 +71,22 @@ class QueryExpressionVisitorTest extends \PHPUnit_Framework_TestCase
$qb = new QueryBuilder();
return array(
array($cb->eq('field', 'value'), $qb->eq('field', ':field'), new Parameter('field', 'value')),
array($cb->neq('field', 'value'), $qb->neq('field', ':field'), new Parameter('field', 'value')),
array($cb->eq('field', null), $qb->isNull('field')),
array($cb->neq('field', null), $qb->isNotNull('field')),
array($cb->isNull('field'), $qb->isNull('field')),
array($cb->eq('field', 'value'), $qb->eq('o.field', ':field'), new Parameter('field', 'value')),
array($cb->neq('field', 'value'), $qb->neq('o.field', ':field'), new Parameter('field', 'value')),
array($cb->eq('field', null), $qb->isNull('o.field')),
array($cb->neq('field', null), $qb->isNotNull('o.field')),
array($cb->isNull('field'), $qb->isNull('o.field')),
array($cb->gt('field', 'value'), $qb->gt('field', ':field'), new Parameter('field', 'value')),
array($cb->gte('field', 'value'), $qb->gte('field', ':field'), new Parameter('field', 'value')),
array($cb->lt('field', 'value'), $qb->lt('field', ':field'), new Parameter('field', 'value')),
array($cb->lte('field', 'value'), $qb->lte('field', ':field'), new Parameter('field', 'value')),
array($cb->gt('field', 'value'), $qb->gt('o.field', ':field'), new Parameter('field', 'value')),
array($cb->gte('field', 'value'), $qb->gte('o.field', ':field'), new Parameter('field', 'value')),
array($cb->lt('field', 'value'), $qb->lt('o.field', ':field'), new Parameter('field', 'value')),
array($cb->lte('field', 'value'), $qb->lte('o.field', ':field'), new Parameter('field', 'value')),
array($cb->in('field', array('value')), $qb->in('field', ':field'), new Parameter('field', array('value'))),
array($cb->notIn('field', array('value')), $qb->notIn('field', ':field'), new Parameter('field', array('value'))),
array($cb->in('field', array('value')), $qb->in('o.field', ':field'), new Parameter('field', array('value'))),
array($cb->notIn('field', array('value')), $qb->notIn('o.field', ':field'), new Parameter('field', array('value'))),
// Test parameter conversion
array($cb->eq('object.field', 'value'), $qb->eq('object.field', ':object_field'), new Parameter('object_field', 'value')),
array($cb->eq('object.field', 'value'), $qb->eq('o.object.field', ':object_field'), new Parameter('object_field', 'value')),
);
}
@@ -394,6 +394,17 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
);
}
/**
* @group DDC-2668
*/
public function testSupportsTrimLeadingZeroString()
{
$this->assertSqlGeneration(
"SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE TRIM(TRAILING '0' FROM u.name) != ''",
"SELECT c0_.name AS name0 FROM cms_users c0_ WHERE TRIM(TRAILING '0' FROM c0_.name) <> ''"
);
}
// Ticket 894
public function testSupportsBetweenClauseWithPositionalParameters()
{
+16 -3
View File
@@ -402,30 +402,39 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
public function testAddCriteriaWhere()
{
$qb = $this->_em->createQueryBuilder();
$qb->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u');
$criteria = new Criteria();
$criteria->where($criteria->expr()->eq('field', 'value'));
$qb->addCriteria($criteria);
$this->assertEquals('field = :field', (string) $qb->getDQLPart('where'));
$this->assertEquals('u.field = :field', (string) $qb->getDQLPart('where'));
$this->assertNotNull($qb->getParameter('field'));
}
public function testAddCriteriaOrder()
{
$qb = $this->_em->createQueryBuilder();
$qb->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u');
$criteria = new Criteria();
$criteria->orderBy(array('field' => Criteria::DESC));
$qb->addCriteria($criteria);
$this->assertCount(1, $orderBy = $qb->getDQLPart('orderBy'));
$this->assertEquals('field DESC', (string) $orderBy[0]);
$this->assertEquals('u.field DESC', (string) $orderBy[0]);
}
public function testAddCriteriaLimit()
{
$qb = $this->_em->createQueryBuilder();
$qb->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u');
$criteria = new Criteria();
$criteria->setFirstResult(2);
$criteria->setMaxResults(10);
@@ -439,7 +448,11 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
public function testAddCriteriaUndefinedLimit()
{
$qb = $this->_em->createQueryBuilder();
$qb->setFirstResult(2)->setMaxResults(10);
$qb->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->setFirstResult(2)
->setMaxResults(10);
$criteria = new Criteria();
$qb->addCriteria($criteria);