1
0
mirror of synced 2024-12-14 15:16:04 +03:00

Merge branch 'master' into assignid

This commit is contained in:
Alexander 2011-10-15 19:33:42 +02:00
commit c5e51e6fa9
29 changed files with 1196 additions and 80 deletions

View File

@ -1,6 +1,6 @@
# Doctrine 2 ORM
Doctrine 2 is an object-relational mapper (ORM) for PHP 5.3.0+ that provides transparent persistence
Doctrine 2 is an object-relational mapper (ORM) for PHP 5.3.2+ that provides transparent persistence
for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features
is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL),
inspired by Hibernates HQL. This provides developers with a powerful alternative to SQL that maintains flexibility

View File

@ -1,3 +1,14 @@
# EntityManager#getPartialReference() creates read-only entity
Entities returned from EntityManager#getPartialReference() are now marked as read-only if they
haven't been in the identity map before. This means objects of this kind never lead to changes
in the UnitOfWork.
# Fields omitted in a partial DQL query or a native query are never updated
Fields of an entity that are not returned from a partial DQL Query or native SQL query
will never be updated through an UPDATE statement.
# Removed support for onUpdate in @JoinColumn
The onUpdate foreign key handling makes absolutly no sense in an ORM. Additionally Oracle doesn't even support it. Support for it is removed.

20
composer.json Normal file
View File

@ -0,0 +1,20 @@
{
"name": "doctrine/orm",
"type": "library",
"description": "Object-Relational-Mapper for PHP",
"keywords": ["orm", "database"],
"homepage": "http://www.doctrine-project.org",
"license": "LGPL",
"authors": [
{"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
{"name": "Roman Borschel", "email": "roman@code-factory.org"},
{"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"}
],
"require": {
"php": ">=5.3.2",
"ext-pdo": "*",
"doctrine/common": "master-dev",
"doctrine/dbal": "master-dev"
}
}

View File

@ -413,6 +413,7 @@ class EntityManager implements ObjectManager
$entity = $class->newInstance();
$class->setIdentifierValues($entity, $identifier);
$this->unitOfWork->registerManaged($entity, $identifier, array());
$this->unitOfWork->markReadOnly($entity);
return $entity;
}

View File

@ -0,0 +1,110 @@
<?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 LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Event;
use \Doctrine\Common\EventSubscriber;
use \LogicException;
/**
* Delegate events only for certain entities they are registered for.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @since 2.2
*/
class EntityEventDelegator implements EventSubscriber
{
/**
* Keeps track of all the event listeners.
*
* @var array
*/
private $listeners = array();
/**
* If frozen no new event listeners can be added.
*
* @var bool
*/
private $frozen = false;
/**
* Adds an event listener that listens on the specified events.
*
* @param string|array $events The event(s) to listen on.
* @param string|array $entities The entities to trigger this listener for
* @param object $listener The listener object.
*/
public function addEventListener($events, $entities, $listener)
{
if ($this->frozen) {
throw new LogicException("Cannot add event listeners after EntityEventDelegator::getSubscribedEvents() " .
"is called once. This happens when you register the delegator with the event manager.");
}
// Picks the hash code related to that listener
$hash = spl_object_hash($listener);
foreach ((array) $events as $event) {
// Overrides listener if a previous one was associated already
// Prevents duplicate listeners on same event (same instance only)
$this->listeners[$event][$hash] = array('listener' => $listener, 'entities' => array_flip((array)$entities));
}
}
/**
* Adds an EventSubscriber. The subscriber is asked for all the events he is
* interested in and added as a listener for these events.
*
* @param Doctrine\Common\EventSubscriber $subscriber The subscriber.
*/
public function addEventSubscriber(EventSubscriber $subscriber, $entities)
{
$this->addEventListener($subscriber->getSubscribedEvents(), $entities, $subscriber);
}
/**
* Returns an array of events this subscriber wants to listen to.
*
* @return array
*/
public function getSubscribedEvents()
{
$this->frozen = true;
return array_keys($this->listeners);
}
/**
* Delegate the event to an appropriate listener
*
* @param $eventName
* @param $event
* @return void
*/
public function __call($eventName, $args)
{
$event = $args[0];
foreach ($this->listeners[$eventName] AS $listenerData) {
$class = get_class($event->getEntity());
if (isset($listenerData['entities'][$class])) {
$listenerData['listener']->$eventName($event);
}
}
}
}

View File

@ -90,7 +90,7 @@ class PreUpdateEventArgs extends LifecycleEventArgs
if (!isset($this->_entityChangeSet[$field])) {
throw new \InvalidArgumentException(
"Field '".$field."' is not a valid field of the entity ".
"'".get_class($this->getEntity())."' in PreInsertUpdateEventArgs."
"'".get_class($this->getEntity())."' in PreUpdateEventArgs."
);
}
}

View File

@ -0,0 +1,176 @@
<?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 LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Mapping\Driver;
use Doctrine\ORM\Mapping\MappingException;
/**
* XmlDriver that additionally looks for mapping information in a global file.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @license MIT
*/
class SimplifiedXmlDriver extends XmlDriver
{
protected $_prefixes = array();
protected $_globalBasename;
protected $_classCache;
protected $_fileExtension = '.orm.xml';
public function __construct($prefixes)
{
$this->addNamespacePrefixes($prefixes);
}
public function setGlobalBasename($file)
{
$this->_globalBasename = $file;
}
public function getGlobalBasename()
{
return $this->_globalBasename;
}
public function addNamespacePrefixes($prefixes)
{
$this->_prefixes = array_merge($this->_prefixes, $prefixes);
$this->addPaths(array_flip($prefixes));
}
public function getNamespacePrefixes()
{
return $this->_prefixes;
}
public function isTransient($className)
{
if (null === $this->_classCache) {
$this->initialize();
}
// The mapping is defined in the global mapping file
if (isset($this->_classCache[$className])) {
return false;
}
try {
$this->_findMappingFile($className);
return false;
} catch (MappingException $e) {
return true;
}
}
public function getAllClassNames()
{
if (null === $this->_classCache) {
$this->initialize();
}
$classes = array();
if ($this->_paths) {
foreach ((array) $this->_paths as $path) {
if (!is_dir($path)) {
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
}
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path),
\RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($iterator as $file) {
$fileName = $file->getBasename($this->_fileExtension);
if ($fileName == $file->getBasename() || $fileName == $this->_globalBasename) {
continue;
}
// NOTE: All files found here means classes are not transient!
if (isset($this->_prefixes[$path])) {
$classes[] = $this->_prefixes[$path].'\\'.str_replace('.', '\\', $fileName);
} else {
$classes[] = str_replace('.', '\\', $fileName);
}
}
}
}
return array_merge($classes, array_keys($this->_classCache));
}
public function getElement($className)
{
if (null === $this->_classCache) {
$this->initialize();
}
if (!isset($this->_classCache[$className])) {
$this->_classCache[$className] = parent::getElement($className);
}
return $this->_classCache[$className];
}
protected function initialize()
{
$this->_classCache = array();
if (null !== $this->_globalBasename) {
foreach ($this->_paths as $path) {
if (is_file($file = $path.'/'.$this->_globalBasename.$this->_fileExtension)) {
$this->_classCache = array_merge($this->_classCache, $this->_loadMappingFile($file));
}
}
}
}
protected function _findMappingFile($className)
{
$defaultFileName = str_replace('\\', '.', $className).$this->_fileExtension;
foreach ($this->_paths as $path) {
if (!isset($this->_prefixes[$path])) {
if (is_file($path.DIRECTORY_SEPARATOR.$defaultFileName)) {
return $path.DIRECTORY_SEPARATOR.$defaultFileName;
}
continue;
}
$prefix = $this->_prefixes[$path];
if (0 !== strpos($className, $prefix.'\\')) {
continue;
}
$filename = $path.'/'.strtr(substr($className, strlen($prefix)+1), '\\', '.').$this->_fileExtension;
if (is_file($filename)) {
return $filename;
}
throw MappingException::mappingFileNotFound($className, $filename);
}
throw MappingException::mappingFileNotFound($className, substr($className, strrpos($className, '\\') + 1).$this->_fileExtension);
}
}

View File

@ -0,0 +1,182 @@
<?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 LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Mapping\Driver;
use Doctrine\ORM\Mapping\MappingException;
/**
* YamlDriver that additionally looks for mapping information in a global file.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @license MIT
*/
class SimplifiedYamlDriver extends YamlDriver
{
protected $_prefixes = array();
protected $_globalBasename;
protected $_classCache;
protected $_fileExtension = '.orm.yml';
public function __construct($prefixes)
{
$this->addNamespacePrefixes($prefixes);
}
public function setGlobalBasename($file)
{
$this->_globalBasename = $file;
}
public function getGlobalBasename()
{
return $this->_globalBasename;
}
public function addNamespacePrefixes($prefixes)
{
$this->_prefixes = array_merge($this->_prefixes, $prefixes);
$this->addPaths(array_flip($prefixes));
}
public function addNamespacePrefix($prefix, $path)
{
$this->_prefixes[$path] = $prefix;
}
public function getNamespacePrefixes()
{
return $this->_prefixes;
}
public function isTransient($className)
{
if (null === $this->_classCache) {
$this->initialize();
}
// The mapping is defined in the global mapping file
if (isset($this->_classCache[$className])) {
return false;
}
try {
$this->_findMappingFile($className);
return false;
} catch (MappingException $e) {
return true;
}
}
public function getAllClassNames()
{
if (null === $this->_classCache) {
$this->initialize();
}
$classes = array();
if ($this->_paths) {
foreach ((array) $this->_paths as $path) {
if (!is_dir($path)) {
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
}
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path),
\RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($iterator as $file) {
$fileName = $file->getBasename($this->_fileExtension);
if ($fileName == $file->getBasename() || $fileName == $this->_globalBasename) {
continue;
}
// NOTE: All files found here means classes are not transient!
if (isset($this->_prefixes[$path])) {
$classes[] = $this->_prefixes[$path].'\\'.str_replace('.', '\\', $fileName);
} else {
$classes[] = str_replace('.', '\\', $fileName);
}
}
}
}
return array_merge($classes, array_keys($this->_classCache));
}
public function getElement($className)
{
if (null === $this->_classCache) {
$this->initialize();
}
if (!isset($this->_classCache[$className])) {
$this->_classCache[$className] = parent::getElement($className);
}
return $this->_classCache[$className];
}
protected function initialize()
{
$this->_classCache = array();
if (null !== $this->_globalBasename) {
foreach ($this->_paths as $path) {
if (is_file($file = $path.'/'.$this->_globalBasename.$this->_fileExtension)) {
$this->_classCache = array_merge($this->_classCache, $this->_loadMappingFile($file));
}
}
}
}
protected function _findMappingFile($className)
{
$defaultFileName = str_replace('\\', '.', $className).$this->_fileExtension;
foreach ($this->_paths as $path) {
if (!isset($this->_prefixes[$path])) {
if (is_file($path.DIRECTORY_SEPARATOR.$defaultFileName)) {
return $path.DIRECTORY_SEPARATOR.$defaultFileName;
}
continue;
}
$prefix = $this->_prefixes[$path];
if (0 !== strpos($className, $prefix.'\\')) {
continue;
}
$filename = $path.'/'.strtr(substr($className, strlen($prefix)+1), '\\', '.').$this->_fileExtension;
if (is_file($filename)) {
return $filename;
}
throw MappingException::mappingFileNotFound($className, $filename);
}
throw MappingException::mappingFileNotFound($className, substr($className, strrpos($className, '\\') + 1).$this->_fileExtension);
}
}

View File

@ -747,6 +747,7 @@ class BasicEntityPersister
*
* @param array $assoc
* @param Doctrine\DBAL\Statement $stmt
*
* @return array
*/
private function loadArrayFromStatement($assoc, $stmt)
@ -771,6 +772,8 @@ class BasicEntityPersister
* @param array $assoc
* @param Doctrine\DBAL\Statement $stmt
* @param PersistentCollection $coll
*
* @return array
*/
private function loadCollectionFromStatement($assoc, $stmt, $coll)
{
@ -784,7 +787,8 @@ class BasicEntityPersister
}
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
$hydrator->hydrateAll($stmt, $rsm, $hints);
return $hydrator->hydrateAll($stmt, $rsm, $hints);
}
/**
@ -1056,10 +1060,10 @@ class BasicEntityPersister
if ($columnList) $columnList .= ', ';
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
$columnList .= $this->_getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) )
. '.' . $srcColumn . ' AS ' . $columnAlias;
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
$this->_rsm->addMetaResult($alias, $this->_platform->getSQLResultCasing($columnAlias), $srcColumn, isset($assoc['id']) && $assoc['id'] === true);
$columnList .= $this->_getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) )
. '.' . $srcColumn . ' AS ' . $resultColumnName;
$this->_rsm->addMetaResult($alias, $resultColumnName, $srcColumn, isset($assoc['id']) && $assoc['id'] === true);
}
}
@ -1179,6 +1183,7 @@ class BasicEntityPersister
$sql = $this->_getSQLTableAlias($class->name, $alias == 'r' ? '' : $alias)
. '.' . $class->getQuotedColumnName($field, $this->_platform);
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
$this->_rsm->addFieldResult($alias, $columnAlias, $field);
return $sql . ' AS ' . $columnAlias;
@ -1228,7 +1233,9 @@ class BasicEntityPersister
$sql = 'SELECT 1 '
. $this->_platform->appendLockHint($this->getLockTablesSql(), $lockMode)
. ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' ' . $lockSql;
list($params, $types) = $this->expandParameters($criteria);
$stmt = $this->_conn->executeQuery($sql, $params, $types);
}
@ -1320,7 +1327,8 @@ class BasicEntityPersister
public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
{
$stmt = $this->getOneToManyStatement($assoc, $sourceEntity);
$this->loadCollectionFromStatement($assoc, $stmt, $coll);
return $this->loadCollectionFromStatement($assoc, $stmt, $coll);
}
/**
@ -1478,6 +1486,7 @@ class BasicEntityPersister
public function exists($entity, array $extraConditions = array())
{
$criteria = $this->_class->getIdentifierValues($entity);
if ($extraConditions) {
$criteria = array_merge($criteria, $extraConditions);
}
@ -1485,7 +1494,9 @@ class BasicEntityPersister
$sql = 'SELECT 1'
. ' FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' ' . $this->_getSQLTableAlias($this->_class->name)
. ' WHERE ' . $this->_getSelectConditionSQL($criteria);
return (bool) $this->_conn->fetchColumn($sql, array_values($criteria));
list($params, $types) = $this->expandParameters($criteria);
return (bool) $this->_conn->fetchColumn($sql, $params);
}
}

View File

@ -41,6 +41,10 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
/** {@inheritdoc} */
protected function _getSelectColumnListSQL()
{
if ($this->_selectColumnListSql !== null) {
return $this->_selectColumnListSql;
}
$columnList = parent::_getSelectColumnListSQL();
// Append discriminator column
@ -81,7 +85,8 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
}
}
return $columnList;
$this->_selectColumnListSql = $columnList;
return $this->_selectColumnListSql;
}
/** {@inheritdoc} */

View File

@ -23,7 +23,7 @@ namespace Doctrine\ORM\Query\AST;
/**
* SelectExpression ::= IdentificationVariable ["." "*"] | StateFieldPathExpression |
* (AggregateExpression | "(" Subselect ")") [["AS"] FieldAliasIdentificationVariable]
* (AggregateExpression | "(" Subselect ")") [["AS"] ["HIDDEN"] FieldAliasIdentificationVariable]
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
@ -37,11 +37,13 @@ class SelectExpression extends Node
{
public $expression;
public $fieldIdentificationVariable;
public $hiddenAliasResultVariable;
public function __construct($expression, $fieldIdentificationVariable)
public function __construct($expression, $fieldIdentificationVariable, $hiddenAliasResultVariable = false)
{
$this->expression = $expression;
$this->fieldIdentificationVariable = $fieldIdentificationVariable;
$this->hiddenAliasResultVariable = $hiddenAliasResultVariable;
}
public function dispatch($sqlWalker)

View File

@ -76,39 +76,40 @@ class Lexer extends \Doctrine\Common\Lexer
const T_FROM = 122;
const T_GROUP = 123;
const T_HAVING = 124;
const T_IN = 125;
const T_INDEX = 126;
const T_INNER = 127;
const T_INSTANCE = 128;
const T_IS = 129;
const T_JOIN = 130;
const T_LEADING = 131;
const T_LEFT = 132;
const T_LIKE = 133;
const T_MAX = 134;
const T_MEMBER = 135;
const T_MIN = 136;
const T_NOT = 137;
const T_NULL = 138;
const T_NULLIF = 139;
const T_OF = 140;
const T_OR = 141;
const T_ORDER = 142;
const T_OUTER = 143;
const T_SELECT = 144;
const T_SET = 145;
const T_SIZE = 146;
const T_SOME = 147;
const T_SUM = 148;
const T_THEN = 149;
const T_TRAILING = 150;
const T_TRUE = 151;
const T_UPDATE = 152;
const T_WHEN = 153;
const T_WHERE = 154;
const T_WITH = 155;
const T_PARTIAL = 156;
const T_MOD = 157;
const T_HIDDEN = 125;
const T_IN = 126;
const T_INDEX = 127;
const T_INNER = 128;
const T_INSTANCE = 129;
const T_IS = 130;
const T_JOIN = 131;
const T_LEADING = 132;
const T_LEFT = 133;
const T_LIKE = 134;
const T_MAX = 135;
const T_MEMBER = 136;
const T_MIN = 137;
const T_NOT = 138;
const T_NULL = 139;
const T_NULLIF = 140;
const T_OF = 141;
const T_OR = 142;
const T_ORDER = 143;
const T_OUTER = 144;
const T_SELECT = 145;
const T_SET = 146;
const T_SIZE = 147;
const T_SOME = 148;
const T_SUM = 149;
const T_THEN = 150;
const T_TRAILING = 151;
const T_TRUE = 152;
const T_UPDATE = 153;
const T_WHEN = 154;
const T_WHERE = 155;
const T_WITH = 156;
const T_PARTIAL = 157;
const T_MOD = 158;
/**
* Creates a new query scanner object.

View File

@ -1831,7 +1831,7 @@ class Parser
/**
* SelectExpression ::=
* IdentificationVariable | StateFieldPathExpression |
* (AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] AliasResultVariable]
* (AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] ["HIDDEN"] AliasResultVariable]
*
* @return Doctrine\ORM\Query\AST\SelectExpression
*/
@ -1839,6 +1839,7 @@ class Parser
{
$expression = null;
$identVariable = null;
$hiddenAliasResultVariable = false;
$fieldAliasIdentificationVariable = null;
$peek = $this->_lexer->glimpse();
@ -1900,6 +1901,12 @@ class Parser
if ($this->_lexer->isNextToken(Lexer::T_AS)) {
$this->match(Lexer::T_AS);
}
if ($this->_lexer->isNextToken(Lexer::T_HIDDEN)) {
$this->match(Lexer::T_HIDDEN);
$hiddenAliasResultVariable = true;
}
if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
$token = $this->_lexer->lookahead;
@ -1914,10 +1921,12 @@ class Parser
}
}
$expr = new AST\SelectExpression($expression, $fieldAliasIdentificationVariable);
if (!$supportsAlias) {
$expr = new AST\SelectExpression($expression, $fieldAliasIdentificationVariable, $hiddenAliasResultVariable);
if ( ! $supportsAlias) {
$this->_identVariableExpressions[$identVariable] = $expr;
}
return $expr;
}

View File

@ -975,8 +975,9 @@ class SqlWalker implements TreeWalker
*/
public function walkSelectExpression($selectExpression)
{
$sql = '';
$expr = $selectExpression->expression;
$sql = '';
$expr = $selectExpression->expression;
$hidden = $selectExpression->hiddenAliasResultVariable;
if ($expr instanceof AST\PathExpression) {
if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) {
@ -1006,7 +1007,10 @@ class SqlWalker implements TreeWalker
$columnAlias = $this->getSQLColumnAlias($columnName);
$sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias;
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
} else if ($expr instanceof AST\AggregateExpression) {
if ( ! $selectExpression->fieldIdentificationVariable) {
$resultAlias = $this->_scalarResultCounter++;
@ -1019,7 +1023,10 @@ class SqlWalker implements TreeWalker
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
} else if ($expr instanceof AST\Subselect) {
if ( ! $selectExpression->fieldIdentificationVariable) {
$resultAlias = $this->_scalarResultCounter++;
@ -1032,7 +1039,10 @@ class SqlWalker implements TreeWalker
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
} else if ($expr instanceof AST\Functions\FunctionNode) {
if ( ! $selectExpression->fieldIdentificationVariable) {
$resultAlias = $this->_scalarResultCounter++;
@ -1045,7 +1055,10 @@ class SqlWalker implements TreeWalker
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
} else if (
$expr instanceof AST\SimpleArithmeticExpression ||
$expr instanceof AST\ArithmeticTerm ||
@ -1070,7 +1083,10 @@ class SqlWalker implements TreeWalker
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
} else if (
$expr instanceof AST\NullIfExpression ||
$expr instanceof AST\CoalesceExpression ||
@ -1090,7 +1106,10 @@ class SqlWalker implements TreeWalker
$this->_scalarResultAliasMap[$resultAlias] = $columnAlias;
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
}
} else {
// IdentificationVariable or PartialObjectExpression
if ($expr instanceof AST\PartialObjectExpression) {
@ -1107,8 +1126,9 @@ class SqlWalker implements TreeWalker
if ( ! isset($this->_selectedClasses[$dqlAlias])) {
$this->_selectedClasses[$dqlAlias] = $class;
}
$beginning = true;
// Select all fields from the queried class
foreach ($class->fieldMappings as $fieldName => $mapping) {
if ($partialFieldSet && !in_array($fieldName, $partialFieldSet)) {
@ -1127,6 +1147,7 @@ class SqlWalker implements TreeWalker
. ' AS ' . $columnAlias;
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name);
}
@ -1138,6 +1159,7 @@ class SqlWalker implements TreeWalker
foreach ($class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName);
$sqlTableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias);
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
if (isset($mapping['inherited']) || $partialFieldSet && !in_array($fieldName, $partialFieldSet)) {
continue;
@ -1159,8 +1181,10 @@ class SqlWalker implements TreeWalker
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE && ! isset($assoc['inherited'])) {
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
if ($beginning) $beginning = false; else $sql .= ', ';
$columnAlias = $this->getSQLColumnAlias($srcColumn);
$sql .= $sqlTableAlias . '.' . $srcColumn . ' AS ' . $columnAlias;
$this->_rsm->addMetaResult($dqlAlias, $this->_platform->getSQLResultCasing($columnAlias), $srcColumn);
}
}
@ -1826,12 +1850,16 @@ class SqlWalker implements TreeWalker
switch ($literal->type) {
case AST\Literal::STRING:
return $this->_conn->quote($literal->value);
case AST\Literal::BOOLEAN:
$bool = strtolower($literal->value) == 'true' ? true : false;
$boolVal = $this->_conn->getDatabasePlatform()->convertBooleans($bool);
return is_string($boolVal) ? $this->_conn->quote($boolVal) : $boolVal;
return $boolVal;
case AST\Literal::NUMERIC:
return $literal->value;
default:
throw QueryException::invalidLiteral($literal);
}

View File

@ -21,7 +21,8 @@ namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
use Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Symfony\Component\Console;
Symfony\Component\Console,
Doctrine\Common\Cache;
/**
* Command to clear the metadata cache of the various cache drivers.
@ -83,6 +84,10 @@ EOT
if ( ! $cacheDriver) {
throw new \InvalidArgumentException('No Metadata cache driver is configured on given EntityManager.');
}
if ($cacheDriver instanceof Cache\ApcCache) {
throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
}
$output->write('Clearing ALL Metadata cache entries' . PHP_EOL);

View File

@ -21,7 +21,8 @@ namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
use Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Symfony\Component\Console;
Symfony\Component\Console,
Doctrine\Common\Cache;
/**
* Command to clear the query cache of the various cache drivers.
@ -83,6 +84,10 @@ EOT
if ( ! $cacheDriver) {
throw new \InvalidArgumentException('No Query cache driver is configured on given EntityManager.');
}
if ($cacheDriver instanceof Cache\ApcCache) {
throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
}
$output->write('Clearing ALL Query cache entries' . PHP_EOL);

View File

@ -21,7 +21,8 @@ namespace Doctrine\ORM\Tools\Console\Command\ClearCache;
use Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Symfony\Component\Console;
Symfony\Component\Console,
Doctrine\Common\Cache;
/**
* Command to clear the result cache of the various cache drivers.
@ -78,13 +79,17 @@ EOT
protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output)
{
$em = $this->getHelper('em')->getEntityManager();
$cacheDriver = $em->getConfiguration()->getQueryCacheImpl();
$cacheDriver = $em->getConfiguration()->getResultCacheImpl();
if ( ! $cacheDriver) {
throw new \InvalidArgumentException('No Result cache driver is configured on given EntityManager.');
}
if ($cacheDriver instanceof Cache\ApcCache) {
throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI.");
}
$output->write('Clearing ALL Query cache entries' . PHP_EOL);
$output->write('Clearing ALL Result cache entries' . PHP_EOL);
$result = $cacheDriver->deleteAll();
$message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.';

View File

@ -150,7 +150,7 @@ public function <methodName>()
public function __construct()
{
if (version_compare(\Doctrine\Common\Version::VERSION, '3.0.0-DEV', '>=')) {
if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) {
$this->_annotationsPrefix = 'ORM\\';
}
}
@ -399,14 +399,17 @@ public function <methodName>()
}
$collections = array();
foreach ($metadata->associationMappings AS $mapping) {
if ($mapping['type'] & ClassMetadataInfo::TO_MANY) {
$collections[] = '$this->'.$mapping['fieldName'].' = new \Doctrine\Common\Collections\ArrayCollection();';
}
}
if ($collections) {
return $this->_prefixCodeWithSpaces(str_replace("<collections>", implode("\n", $collections), self::$_constructorMethodTemplate));
}
return '';
}
@ -788,7 +791,7 @@ public function <methodName>()
}
if (isset($joinColumn['onDelete'])) {
$joinColumnAnnot[] = 'onDelete=' . ($joinColumn['onDelete'] ? 'true' : 'false');
$joinColumnAnnot[] = 'onDelete="' . ($joinColumn['onDelete'] . '"');
}
if (isset($joinColumn['columnDefinition'])) {

View File

@ -215,8 +215,13 @@ class UnitOfWork implements PropertyChangedListener
* @var array
*/
private $orphanRemovals = array();
//private $_readOnlyObjects = array();
/**
* Read-Only objects are never evaluated
*
* @var array
*/
private $readOnlyObjects = array();
/**
* Map of Entity Class-Names and corresponding IDs that should eager loaded when requested.
@ -393,6 +398,8 @@ class UnitOfWork implements PropertyChangedListener
* If a PersistentCollection has been de-referenced in a fully MANAGED entity,
* then this collection is marked for deletion.
*
* @ignore
* @internal Don't call from the outside.
* @param ClassMetadata $class The class descriptor of the entity.
* @param object $entity The entity for which to compute the changes.
*/
@ -403,6 +410,11 @@ class UnitOfWork implements PropertyChangedListener
}
$oid = spl_object_hash($entity);
if (isset($this->readOnlyObjects[$oid])) {
return;
}
$actualData = array();
foreach ($class->reflFields as $name => $refProp) {
$value = $refProp->getValue($entity);
@ -458,7 +470,15 @@ class UnitOfWork implements PropertyChangedListener
$changeSet = ($isChangeTrackingNotify && isset($this->entityChangeSets[$oid])) ? $this->entityChangeSets[$oid] : array();
foreach ($actualData as $propName => $actualValue) {
$orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null;
if (isset($originalData[$propName])) {
$orgValue = $originalData[$propName];
} else if (array_key_exists($propName, $originalData)) {
$orgValue = null;
} else {
// skip field, its a partially omitted one!
continue;
}
if (isset($class->associationMappings[$propName])) {
$assoc = $class->associationMappings[$propName];
if ($assoc['type'] & ClassMetadata::TO_ONE && $orgValue !== $actualValue) {
@ -528,7 +548,7 @@ class UnitOfWork implements PropertyChangedListener
foreach ($entitiesToProcess as $entity) {
// Ignore uninitialized proxy objects
if (/* $entity is readOnly || */ $entity instanceof Proxy && ! $entity->__isInitialized__) {
if ($entity instanceof Proxy && ! $entity->__isInitialized__) {
continue;
}
// Only MANAGED entities that are NOT SCHEDULED FOR INSERTION are processed here.
@ -635,7 +655,7 @@ class UnitOfWork implements PropertyChangedListener
* @param object $entity The entity for which to (re)calculate the change set.
* @throws InvalidArgumentException If the passed entity is not MANAGED.
*/
public function recomputeSingleEntityChangeSet($class, $entity)
public function recomputeSingleEntityChangeSet(ClassMetadata $class, $entity)
{
$oid = spl_object_hash($entity);
@ -853,6 +873,7 @@ class UnitOfWork implements PropertyChangedListener
$targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
if ( ! $calc->hasClass($targetClass->name)) {
$calc->addClass($targetClass);
$newNodes[] = $targetClass;
}
$calc->addDependency($targetClass, $class);
// If the target class has mapped subclasses,
@ -2407,4 +2428,37 @@ class UnitOfWork implements PropertyChangedListener
{
return method_exists($obj, '__toString') ? (string)$obj : get_class($obj).'@'.spl_object_hash($obj);
}
/**
* Marks an entity as read-only so that it will not be considered for updates during UnitOfWork#commit().
*
* This operation cannot be undone as some parts of the UnitOfWork now keep gathering information
* on this object that might be necessary to perform a correct udpate.
*
* @throws \InvalidArgumentException
* @param $object
* @return void
*/
public function markReadOnly($object)
{
if ( ! is_object($object) || ! $this->isInIdentityMap($object)) {
throw new InvalidArgumentException("Managed entity required");
}
$this->readOnlyObjects[spl_object_hash($object)] = true;
}
/**
* Is this entity read only?
*
* @throws \InvalidArgumentException
* @param $object
* @return void
*/
public function isReadOnly($object)
{
if ( ! is_object($object) ) {
throw new InvalidArgumentException("Managed entity required");
}
return isset($this->readOnlyObjects[spl_object_hash($object)]);
}
}

View File

@ -7,7 +7,11 @@ namespace Doctrine\Tests\Models\Company;
* @Table(name="company_contracts")
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"fix" = "CompanyFixContract", "flexible" = "CompanyFlexContract", "flexultra" = "CompanyFlexUltraContract"})
* @DiscriminatorMap({
* "fix" = "CompanyFixContract",
* "flexible" = "CompanyFlexContract",
* "flexultra" = "CompanyFlexUltraContract"
* })
*/
abstract class CompanyContract
{

View File

@ -0,0 +1,91 @@
<?php
namespace Doctrine\Tests\ORM\Event;
use Doctrine\ORM\Mapping\ClassMetadata;
/**
* @group DDC-1415
*/
class EntityEventDelegatorTest extends \Doctrine\Tests\OrmTestCase
{
/**
* @var \Doctrine\ORM\Event\EntityEventDelegator
*/
private $delegator;
public function setUp()
{
$this->delegator = new \Doctrine\ORM\Event\EntityEventDelegator();
}
public function testGetSubscribedEventsWhenEmpty()
{
$this->assertEquals(array(), $this->delegator->getSubscribedEvents());
}
public function testAddListener()
{
$this->delegator->addEventListener('postLoad', 'stdClass', new DelegateeEventListener());
$this->assertEquals(array('postLoad'), $this->delegator->getSubscribedEvents());
}
public function testAddSubscriber()
{
$this->delegator->addEventSubscriber(new DelegateeEventListener(), 'stdClass');
$this->assertEquals(array('postLoad'), $this->delegator->getSubscribedEvents());
}
public function testAddListenerAfterFrozenThrowsException()
{
$this->delegator->getSubscribedEvents(); // freezes
$this->setExpectedException("LogicException", "Cannot add event listeners aft");
$this->delegator->addEventListener('postLoad', 'stdClass', new DelegateeEventListener());
}
public function testDelegateEvent()
{
$delegatee = new DelegateeEventListener();
$this->delegator->addEventListener('postLoad', 'stdClass', $delegatee);
$event = new \Doctrine\ORM\Event\LifecycleEventArgs(new \stdClass(), $this->_getTestEntityManager());
$this->delegator->postLoad($event);
$this->delegator->postLoad($event);
$this->assertEquals(2, $delegatee->postLoad);
}
public function testDelegatePickEntity()
{
$delegatee = new DelegateeEventListener();
$this->delegator->addEventListener('postLoad', 'stdClass', $delegatee);
$event1 = new \Doctrine\ORM\Event\LifecycleEventArgs(new \stdClass(), $this->_getTestEntityManager());
$event2 = new \Doctrine\ORM\Event\LifecycleEventArgs(new \Doctrine\Tests\Models\CMS\CmsUser(), $this->_getTestEntityManager());
$this->delegator->postLoad($event1);
$this->delegator->postLoad($event2);
$this->assertEquals(1, $delegatee->postLoad);
}
}
class DelegateeEventListener implements \Doctrine\Common\EventSubscriber
{
public $postLoad = 0;
public function postLoad($args)
{
$this->postLoad++;
}
/**
* Returns an array of events this subscriber wants to listen to.
*
* @return array
*/
function getSubscribedEvents()
{
return array('postLoad');
}
}

View File

@ -863,7 +863,6 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testGetPartialReferenceToUpdateObjectWithoutLoadingIt()
{
//$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
$user = new CmsUser();
$user->username = "beberlei";
$user->name = "Benjamin E.";
@ -882,7 +881,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->flush();
$this->_em->clear();
$this->assertEquals('Stephan', $this->_em->find(get_class($user), $userId)->name);
$this->assertEquals('Benjamin E.', $this->_em->find(get_class($user), $userId)->name);
}
public function testMergePersistsNewEntities()

View File

@ -54,7 +54,30 @@ class DefaultValuesTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals($userId, $a2->getUser()->getId());
$this->assertEquals('Poweruser', $a2->getUser()->type);
}
/**
* @group DDC-1386
*/
public function testGetPartialReferenceWithDefaultValueNotEvalutedInFlush()
{
$user = new DefaultValueUser;
$user->name = 'romanb';
$user->type = 'Normaluser';
$this->_em->persist($user);
$this->_em->flush();
$this->_em->clear();
$user = $this->_em->getPartialReference('Doctrine\Tests\ORM\Functional\DefaultValueUser', $user->id);
$this->assertTrue($this->_em->getUnitOfWork()->isReadOnly($user));
$this->_em->flush();
$this->_em->clear();
$user = $this->_em->find('Doctrine\Tests\ORM\Functional\DefaultValueUser', $user->id);
$this->assertEquals('Normaluser', $user->type);
}
}

View File

@ -533,4 +533,34 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(2, count($users));
}
public function testQueryWithHiddenAsSelectExpression()
{
$userA = new CmsUser;
$userA->name = 'Benjamin';
$userA->username = 'beberlei';
$userA->status = 'developer';
$this->_em->persist($userA);
$userB = new CmsUser;
$userB->name = 'Roman';
$userB->username = 'romanb';
$userB->status = 'developer';
$this->_em->persist($userB);
$userC = new CmsUser;
$userC->name = 'Jonathan';
$userC->username = 'jwage';
$userC->status = 'developer';
$this->_em->persist($userC);
$this->_em->flush();
$this->_em->clear();
$query = $this->_em->createQuery("SELECT u, (SELECT COUNT(u2.id) FROM Doctrine\Tests\Models\CMS\CmsUser u2) AS HIDDEN total FROM Doctrine\Tests\Models\CMS\CmsUser u");
$users = $query->execute();
$this->assertEquals(3, count($users));
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $users[0]);
}
}

View File

@ -37,6 +37,10 @@ class TypeTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(0.1515, $decimal->highScale);
}
/**
* @group DDC-1394
* @return void
*/
public function testBoolean()
{
$bool = new BooleanModel();
@ -46,7 +50,7 @@ class TypeTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->flush();
$this->_em->clear();
$dql = "SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b";
$dql = "SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = true";
$bool = $this->_em->createQuery($dql)->getSingleResult();
$this->assertTrue($bool->booleanField);
@ -56,7 +60,7 @@ class TypeTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->flush();
$this->_em->clear();
$dql = "SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b";
$dql = "SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = false";
$bool = $this->_em->createQuery($dql)->getSingleResult();
$this->assertFalse($bool->booleanField);

View File

@ -0,0 +1,113 @@
<?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 LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Tests\ORM\Mapping\Symfony;
/**
* @group DDC-1418
*/
abstract class AbstractDriverTest extends \PHPUnit_Framework_TestCase
{
public function testFindMappingFile()
{
$driver = $this->getDriver(array(
'MyNamespace\MySubnamespace\EntityFoo' => 'foo',
'MyNamespace\MySubnamespace\Entity' => $this->dir,
));
touch($filename = $this->dir.'/Foo'.$this->getFileExtension());
$this->assertEquals($filename, $this->invoke($driver, '_findMappingFile', array('MyNamespace\MySubnamespace\Entity\Foo')));
}
public function testFindMappingFileInSubnamespace()
{
$driver = $this->getDriver(array(
'MyNamespace\MySubnamespace\Entity' => $this->dir,
));
touch($filename = $this->dir.'/Foo.Bar'.$this->getFileExtension());
$this->assertEquals($filename, $this->invoke($driver, '_findMappingFile', array('MyNamespace\MySubnamespace\Entity\Foo\Bar')));
}
public function testFindMappingFileNamespacedFoundFileNotFound()
{
$this->setExpectedException(
'Doctrine\ORM\Mapping\MappingException',
"No mapping file found named '".$this->dir."/Foo".$this->getFileExtension()."' for class 'MyNamespace\MySubnamespace\Entity\Foo'."
);
$driver = $this->getDriver(array(
'MyNamespace\MySubnamespace\Entity' => $this->dir,
));
$this->invoke($driver, '_findMappingFile', array('MyNamespace\MySubnamespace\Entity\Foo'));
}
public function testFindMappingNamespaceNotFound()
{
$this->setExpectedException(
'Doctrine\ORM\Mapping\MappingException',
"No mapping file found named 'Foo".$this->getFileExtension()."' for class 'MyOtherNamespace\MySubnamespace\Entity\Foo'."
);
$driver = $this->getDriver(array(
'MyNamespace\MySubnamespace\Entity' => $this->dir,
));
$this->invoke($driver, '_findMappingFile', array('MyOtherNamespace\MySubnamespace\Entity\Foo'));
}
protected function setUp()
{
$this->dir = sys_get_temp_dir().'/abstract_driver_test';
@mkdir($this->dir, 0777, true);
}
protected function tearDown()
{
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->dir), \RecursiveIteratorIterator::CHILD_FIRST);
foreach ($iterator as $path) {
if ($path->isDir()) {
@rmdir($path);
} else {
@unlink($path);
}
}
@rmdir($this->dir);
}
abstract protected function getFileExtension();
abstract protected function getDriver(array $paths = array());
private function setField($obj, $field, $value)
{
$ref = new \ReflectionProperty($obj, $field);
$ref->setAccessible(true);
$ref->setValue($obj, $value);
}
private function invoke($obj, $method, array $args = array()) {
$ref = new \ReflectionMethod($obj, $method);
$ref->setAccessible(true);
return $ref->invokeArgs($obj, $args);
}
}

View File

@ -0,0 +1,40 @@
<?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 LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Tests\ORM\Mapping\Symfony;
use \Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver;
/**
* @group DDC-1418
*/
class XmlDriverTest extends AbstractDriverTest
{
protected function getFileExtension()
{
return '.orm.xml';
}
protected function getDriver(array $paths = array())
{
$driver = new SimplifiedXmlDriver(array_flip($paths));
return $driver;
}
}

View File

@ -0,0 +1,40 @@
<?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 LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Tests\ORM\Mapping\Symfony;
use \Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver;
/**
* @group DDC-1418
*/
class YamlDriverTest extends AbstractDriverTest
{
protected function getFileExtension()
{
return '.orm.yml';
}
protected function getDriver(array $paths = array())
{
$driver = new SimplifiedYamlDriver(array_flip($paths));
return $driver;
}
}

View File

@ -33,7 +33,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
}
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
->useQueryCache(false);
->useQueryCache(false);
foreach ($queryHints AS $name => $value) {
$query->setHint($name, $value);
@ -65,7 +65,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
}
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
->useQueryCache(false);
->useQueryCache(false);
foreach ($queryHints AS $name => $value) {
$query->setHint($name, $value);
@ -729,12 +729,12 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
$this->assertSqlGeneration(
"SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = true",
"SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = 'true'"
"SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = true"
);
$this->assertSqlGeneration(
"SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = false",
"SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = 'false'"
"SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = false"
);
$this->_em->getConnection()->setDatabasePlatform($oldPlat);
@ -1095,6 +1095,150 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
"Doctrine\ORM\Query\QueryException"
);
}
/**
* @group DDC-1389
*/
public function testInheritanceTypeJoinInRootClassWithDisabledForcePartialLoad()
{
$this->assertSqlGeneration(
'SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p',
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c1_.car_id AS car_id3, c2_.salary AS salary4, c2_.department AS department5, c2_.startDate AS startDate6, c0_.discr AS discr7, c0_.spouse_id AS spouse_id8 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id',
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
);
}
/**
* @group DDC-1389
*/
public function testInheritanceTypeJoinInRootClassWithEnabledForcePartialLoad()
{
$this->assertSqlGeneration(
'SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p',
'SELECT c0_.id AS id0, c0_.name AS name1, c0_.discr AS discr2 FROM company_persons c0_',
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
);
}
/**
* @group DDC-1389
*/
public function testInheritanceTypeJoinInChildClassWithDisabledForcePartialLoad()
{
$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c2_.title AS title5, c2_.car_id AS car_id6, c0_.discr AS discr7, c0_.spouse_id AS spouse_id8 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id',
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
);
}
/**
* @group DDC-1389
*/
public function testInheritanceTypeJoinInChildClassWithEnabledForcePartialLoad()
{
$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e',
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c0_.discr AS discr5 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id',
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
);
}
/**
* @group DDC-1389
*/
public function testInheritanceTypeJoinInLeafClassWithDisabledForcePartialLoad()
{
$this->assertSqlGeneration(
'SELECT m FROM Doctrine\Tests\Models\Company\CompanyManager m',
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c2_.title AS title5, c0_.discr AS discr6, c0_.spouse_id AS spouse_id7, c2_.car_id AS car_id8 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id',
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
);
}
/**
* @group DDC-1389
*/
public function testInheritanceTypeJoinInLeafClassWithEnabledForcePartialLoad()
{
$this->assertSqlGeneration(
'SELECT m FROM Doctrine\Tests\Models\Company\CompanyManager m',
'SELECT c0_.id AS id0, c0_.name AS name1, c1_.salary AS salary2, c1_.department AS department3, c1_.startDate AS startDate4, c2_.title AS title5, c0_.discr AS discr6 FROM company_managers c2_ INNER JOIN company_employees c1_ ON c2_.id = c1_.id INNER JOIN company_persons c0_ ON c2_.id = c0_.id',
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
);
}
/**
* @group DDC-1389
*/
public function testInheritanceTypeSingleTableInRootClassWithDisabledForcePartialLoad()
{
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c',
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.fixPrice AS fixPrice2, c0_.hoursWorked AS hoursWorked3, c0_.pricePerHour AS pricePerHour4, c0_.maxPrice AS maxPrice5, c0_.discr AS discr6, c0_.salesPerson_id AS salesPerson_id7 FROM company_contracts c0_ WHERE c0_.discr IN ('fix', 'flexible', 'flexultra')",
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
);
}
/**
* @group DDC-1389
*/
public function testInheritanceTypeSingleTableInRootClassWithEnabledForcePartialLoad()
{
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c',
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.fixPrice AS fixPrice2, c0_.hoursWorked AS hoursWorked3, c0_.pricePerHour AS pricePerHour4, c0_.maxPrice AS maxPrice5, c0_.discr AS discr6 FROM company_contracts c0_ WHERE c0_.discr IN ('fix', 'flexible', 'flexultra')",
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
);
}
/**
* @group DDC-1389
*/
public function testInheritanceTypeSingleTableInChildClassWithDisabledForcePartialLoad()
{
$this->assertSqlGeneration(
'SELECT fc FROM Doctrine\Tests\Models\Company\CompanyFlexContract fc',
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.hoursWorked AS hoursWorked2, c0_.pricePerHour AS pricePerHour3, c0_.maxPrice AS maxPrice4, c0_.discr AS discr5, c0_.salesPerson_id AS salesPerson_id6 FROM company_contracts c0_ WHERE c0_.discr IN ('flexible', 'flexultra')",
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
);
}
/**
* @group DDC-1389
*/
public function testInheritanceTypeSingleTableInChildClassWithEnabledForcePartialLoad()
{
$this->assertSqlGeneration(
'SELECT fc FROM Doctrine\Tests\Models\Company\CompanyFlexContract fc',
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.hoursWorked AS hoursWorked2, c0_.pricePerHour AS pricePerHour3, c0_.maxPrice AS maxPrice4, c0_.discr AS discr5 FROM company_contracts c0_ WHERE c0_.discr IN ('flexible', 'flexultra')",
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
);
}
/**
* @group DDC-1389
*/
public function testInheritanceTypeSingleTableInLeafClassWithDisabledForcePartialLoad()
{
$this->assertSqlGeneration(
'SELECT fuc FROM Doctrine\Tests\Models\Company\CompanyFlexUltraContract fuc',
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.hoursWorked AS hoursWorked2, c0_.pricePerHour AS pricePerHour3, c0_.maxPrice AS maxPrice4, c0_.discr AS discr5, c0_.salesPerson_id AS salesPerson_id6 FROM company_contracts c0_ WHERE c0_.discr IN ('flexultra')",
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
);
}
/**
* @group DDC-1389
*/
public function testInheritanceTypeSingleTableInLeafClassWithEnabledForcePartialLoad()
{
$this->assertSqlGeneration(
'SELECT fuc FROM Doctrine\Tests\Models\Company\CompanyFlexUltraContract fuc',
"SELECT c0_.id AS id0, c0_.completed AS completed1, c0_.hoursWorked AS hoursWorked2, c0_.pricePerHour AS pricePerHour3, c0_.maxPrice AS maxPrice4, c0_.discr AS discr5 FROM company_contracts c0_ WHERE c0_.discr IN ('flexultra')",
array(Query::HINT_FORCE_PARTIAL_LOAD => true)
);
}
}