Merge branch 'master' of github.com:doctrine/doctrine2
This commit is contained in:
commit
bffca232e2
@ -272,7 +272,7 @@ abstract class AbstractQuery
|
|||||||
* @param boolean $bool
|
* @param boolean $bool
|
||||||
* @param integer $timeToLive
|
* @param integer $timeToLive
|
||||||
* @param string $resultCacheId
|
* @param string $resultCacheId
|
||||||
* @return This query instance.
|
* @return Doctrine\ORM\AbstractQuery This query instance.
|
||||||
*/
|
*/
|
||||||
public function useResultCache($bool, $timeToLive = null, $resultCacheId = null)
|
public function useResultCache($bool, $timeToLive = null, $resultCacheId = null)
|
||||||
{
|
{
|
||||||
|
@ -160,11 +160,14 @@ class EntityRepository implements ObjectRepository
|
|||||||
* Finds entities by a set of criteria.
|
* Finds entities by a set of criteria.
|
||||||
*
|
*
|
||||||
* @param array $criteria
|
* @param array $criteria
|
||||||
* @return array
|
* @param array|null $orderBy
|
||||||
|
* @param int|null $limit
|
||||||
|
* @param int|null $offset
|
||||||
|
* @return array The objects.
|
||||||
*/
|
*/
|
||||||
public function findBy(array $criteria)
|
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||||
{
|
{
|
||||||
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->loadAll($criteria);
|
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->loadAll($criteria, $orderBy, $limit, $offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,6 +75,10 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
// Remember which associations are "fetch joined", so that we know where to inject
|
// Remember which associations are "fetch joined", so that we know where to inject
|
||||||
// collection stubs or proxies and where not.
|
// collection stubs or proxies and where not.
|
||||||
if (isset($this->_rsm->relationMap[$dqlAlias])) {
|
if (isset($this->_rsm->relationMap[$dqlAlias])) {
|
||||||
|
if ( ! isset($this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]])) {
|
||||||
|
throw HydrationException::parentObjectOfRelationNotFound($dqlAlias, $this->_rsm->parentAliasMap[$dqlAlias]);
|
||||||
|
}
|
||||||
|
|
||||||
$sourceClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]];
|
$sourceClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]];
|
||||||
$sourceClass = $this->_getClassMetadata($sourceClassName);
|
$sourceClass = $this->_getClassMetadata($sourceClassName);
|
||||||
$assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]];
|
$assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]];
|
||||||
@ -195,7 +199,7 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
*/
|
*/
|
||||||
private function _getEntity(array $data, $dqlAlias)
|
private function _getEntity(array $data, $dqlAlias)
|
||||||
{
|
{
|
||||||
$className = $this->_rsm->aliasMap[$dqlAlias];
|
$className = $this->_rsm->aliasMap[$dqlAlias];
|
||||||
if (isset($this->_rsm->discriminatorColumns[$dqlAlias])) {
|
if (isset($this->_rsm->discriminatorColumns[$dqlAlias])) {
|
||||||
$discrColumn = $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]];
|
$discrColumn = $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]];
|
||||||
$className = $this->_ce[$className]->discriminatorMap[$data[$discrColumn]];
|
$className = $this->_ce[$className]->discriminatorMap[$data[$discrColumn]];
|
||||||
@ -286,7 +290,7 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
|
|
||||||
// Get a reference to the parent object to which the joined element belongs.
|
// Get a reference to the parent object to which the joined element belongs.
|
||||||
if ($this->_rsm->isMixed && isset($this->_rootAliases[$parentAlias])) {
|
if ($this->_rsm->isMixed && isset($this->_rootAliases[$parentAlias])) {
|
||||||
$first = reset($this->_resultPointers);
|
$first = reset($this->_resultPointers);
|
||||||
$parentObject = $this->_resultPointers[$parentAlias][key($first)];
|
$parentObject = $this->_resultPointers[$parentAlias][key($first)];
|
||||||
} else if (isset($this->_resultPointers[$parentAlias])) {
|
} else if (isset($this->_resultPointers[$parentAlias])) {
|
||||||
$parentObject = $this->_resultPointers[$parentAlias];
|
$parentObject = $this->_resultPointers[$parentAlias];
|
||||||
|
@ -1628,6 +1628,7 @@ class ClassMetadataInfo implements ClassMetadata
|
|||||||
if (strpos($className, '\\') === false && strlen($this->namespace)) {
|
if (strpos($className, '\\') === false && strlen($this->namespace)) {
|
||||||
$className = $this->namespace . '\\' . $className;
|
$className = $this->namespace . '\\' . $className;
|
||||||
}
|
}
|
||||||
|
$className = ltrim($className, '\\');
|
||||||
$this->discriminatorMap[$value] = $className;
|
$this->discriminatorMap[$value] = $className;
|
||||||
if ($this->name == $className) {
|
if ($this->name == $className) {
|
||||||
$this->discriminatorValue = $value;
|
$this->discriminatorValue = $value;
|
||||||
|
@ -67,10 +67,10 @@ class AnnotationDriver implements Driver
|
|||||||
* Initializes a new AnnotationDriver that uses the given AnnotationReader for reading
|
* Initializes a new AnnotationDriver that uses the given AnnotationReader for reading
|
||||||
* docblock annotations.
|
* docblock annotations.
|
||||||
*
|
*
|
||||||
* @param $reader The AnnotationReader to use.
|
* @param AnnotationReader $reader The AnnotationReader to use, duck-typed.
|
||||||
* @param string|array $paths One or multiple paths where mapping classes can be found.
|
* @param string|array $paths One or multiple paths where mapping classes can be found.
|
||||||
*/
|
*/
|
||||||
public function __construct(AnnotationReader $reader, $paths = null)
|
public function __construct($reader, $paths = null)
|
||||||
{
|
{
|
||||||
$this->_reader = $reader;
|
$this->_reader = $reader;
|
||||||
if ($paths) {
|
if ($paths) {
|
||||||
|
@ -67,6 +67,26 @@ class DatabaseDriver implements Driver
|
|||||||
$this->_sm = $schemaManager;
|
$this->_sm = $schemaManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set tables manually instead of relying on the reverse engeneering capabilities of SchemaManager.
|
||||||
|
*
|
||||||
|
* @param array $entityTables
|
||||||
|
* @param array $manyToManyTables
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setTables($entityTables, $manyToManyTables)
|
||||||
|
{
|
||||||
|
$this->tables = $this->manyToManyTables = $this->classToTableNames = array();
|
||||||
|
foreach ($entityTables AS $table) {
|
||||||
|
$className = Inflector::classify(strtolower($table->getName()));
|
||||||
|
$this->classToTableNames[$className] = $table->getName();
|
||||||
|
$this->tables[$table->getName()] = $table;
|
||||||
|
}
|
||||||
|
foreach ($manyToManyTables AS $table) {
|
||||||
|
$this->manyToManyTables[$table->getName()] = $table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function reverseEngineerMappingFromDatabase()
|
private function reverseEngineerMappingFromDatabase()
|
||||||
{
|
{
|
||||||
if ($this->tables !== null) {
|
if ($this->tables !== null) {
|
||||||
@ -77,7 +97,7 @@ class DatabaseDriver implements Driver
|
|||||||
$tables[$tableName] = $this->_sm->listTableDetails($tableName);
|
$tables[$tableName] = $this->_sm->listTableDetails($tableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->tables = array();
|
$this->tables = $this->manyToManyTables = $this->classToTableNames = array();
|
||||||
foreach ($tables AS $tableName => $table) {
|
foreach ($tables AS $tableName => $table) {
|
||||||
/* @var $table Table */
|
/* @var $table Table */
|
||||||
if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
|
if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
|
||||||
@ -95,11 +115,7 @@ class DatabaseDriver implements Driver
|
|||||||
sort($pkColumns);
|
sort($pkColumns);
|
||||||
sort($allForeignKeyColumns);
|
sort($allForeignKeyColumns);
|
||||||
|
|
||||||
if ($pkColumns == $allForeignKeyColumns) {
|
if ($pkColumns == $allForeignKeyColumns && count($foreignKeys) == 2) {
|
||||||
if (count($table->getForeignKeys()) > 2) {
|
|
||||||
throw new \InvalidArgumentException("ManyToMany table '" . $tableName . "' with more or less than two foreign keys are not supported by the Database Reverese Engineering Driver.");
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->manyToManyTables[$tableName] = $table;
|
$this->manyToManyTables[$tableName] = $table;
|
||||||
} else {
|
} else {
|
||||||
// lower-casing is necessary because of Oracle Uppercase Tablenames,
|
// lower-casing is necessary because of Oracle Uppercase Tablenames,
|
||||||
@ -191,8 +207,10 @@ class DatabaseDriver implements Driver
|
|||||||
|
|
||||||
foreach ($this->manyToManyTables AS $manyTable) {
|
foreach ($this->manyToManyTables AS $manyTable) {
|
||||||
foreach ($manyTable->getForeignKeys() AS $foreignKey) {
|
foreach ($manyTable->getForeignKeys() AS $foreignKey) {
|
||||||
|
// foreign key maps to the table of the current entity, many to many association probably exists
|
||||||
if (strtolower($tableName) == strtolower($foreignKey->getForeignTableName())) {
|
if (strtolower($tableName) == strtolower($foreignKey->getForeignTableName())) {
|
||||||
$myFk = $foreignKey;
|
$myFk = $foreignKey;
|
||||||
|
$otherFk = null;
|
||||||
foreach ($manyTable->getForeignKeys() AS $foreignKey) {
|
foreach ($manyTable->getForeignKeys() AS $foreignKey) {
|
||||||
if ($foreignKey != $myFk) {
|
if ($foreignKey != $myFk) {
|
||||||
$otherFk = $foreignKey;
|
$otherFk = $foreignKey;
|
||||||
@ -200,6 +218,12 @@ class DatabaseDriver implements Driver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$otherFk) {
|
||||||
|
// the definition of this many to many table does not contain
|
||||||
|
// enough foreign key information to continue reverse engeneering.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$localColumn = current($myFk->getColumns());
|
$localColumn = current($myFk->getColumns());
|
||||||
$associationMapping = array();
|
$associationMapping = array();
|
||||||
$associationMapping['fieldName'] = Inflector::camelize(str_replace('_id', '', strtolower(current($otherFk->getColumns()))));
|
$associationMapping['fieldName'] = Inflector::camelize(str_replace('_id', '', strtolower(current($otherFk->getColumns()))));
|
||||||
|
@ -680,12 +680,15 @@ class BasicEntityPersister
|
|||||||
* Loads a list of entities by a list of field criteria.
|
* Loads a list of entities by a list of field criteria.
|
||||||
*
|
*
|
||||||
* @param array $criteria
|
* @param array $criteria
|
||||||
|
* @param array $orderBy
|
||||||
|
* @param int $limit
|
||||||
|
* @param int $offset
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function loadAll(array $criteria = array())
|
public function loadAll(array $criteria = array(), array $orderBy = null, $limit = null, $offset = null)
|
||||||
{
|
{
|
||||||
$entities = array();
|
$entities = array();
|
||||||
$sql = $this->_getSelectEntitiesSQL($criteria);
|
$sql = $this->_getSelectEntitiesSQL($criteria, null, 0, $limit, $offset, $orderBy);
|
||||||
list($params, $types) = $this->expandParameters($criteria);
|
list($params, $types) = $this->expandParameters($criteria);
|
||||||
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
||||||
|
|
||||||
@ -831,19 +834,21 @@ class BasicEntityPersister
|
|||||||
* @param AssociationMapping $assoc
|
* @param AssociationMapping $assoc
|
||||||
* @param string $orderBy
|
* @param string $orderBy
|
||||||
* @param int $lockMode
|
* @param int $lockMode
|
||||||
|
* @param int $limit
|
||||||
|
* @param int $offset
|
||||||
|
* @param array $orderBy
|
||||||
* @return string
|
* @return string
|
||||||
* @todo Refactor: _getSelectSQL(...)
|
* @todo Refactor: _getSelectSQL(...)
|
||||||
*/
|
*/
|
||||||
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0, $limit = null, $offset = null)
|
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0, $limit = null, $offset = null, array $orderBy = null)
|
||||||
{
|
{
|
||||||
$joinSql = $assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY ?
|
$joinSql = $assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY ?
|
||||||
$this->_getSelectManyToManyJoinSQL($assoc) : '';
|
$this->_getSelectManyToManyJoinSQL($assoc) : '';
|
||||||
|
|
||||||
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
|
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
|
||||||
|
|
||||||
$orderBySql = $assoc !== null && isset($assoc['orderBy']) ?
|
$orderBy = ($assoc !== null && isset($assoc['orderBy'])) ? $assoc['orderBy'] : $orderBy;
|
||||||
$this->_getCollectionOrderBySQL($assoc['orderBy'], $this->_getSQLTableAlias($this->_class->name))
|
$orderBySql = $orderBy ? $this->_getOrderBySQL($orderBy, $this->_getSQLTableAlias($this->_class->name)) : '';
|
||||||
: '';
|
|
||||||
|
|
||||||
$lockSql = '';
|
$lockSql = '';
|
||||||
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
if ($lockMode == LockMode::PESSIMISTIC_READ) {
|
||||||
@ -869,12 +874,12 @@ class BasicEntityPersister
|
|||||||
* @return string
|
* @return string
|
||||||
* @todo Rename: _getOrderBySQL
|
* @todo Rename: _getOrderBySQL
|
||||||
*/
|
*/
|
||||||
protected final function _getCollectionOrderBySQL(array $orderBy, $baseTableAlias)
|
protected final function _getOrderBySQL(array $orderBy, $baseTableAlias)
|
||||||
{
|
{
|
||||||
$orderBySql = '';
|
$orderBySql = '';
|
||||||
foreach ($orderBy as $fieldName => $orientation) {
|
foreach ($orderBy as $fieldName => $orientation) {
|
||||||
if ( ! isset($this->_class->fieldMappings[$fieldName])) {
|
if ( ! isset($this->_class->fieldMappings[$fieldName])) {
|
||||||
ORMException::unrecognizedField($fieldName);
|
throw ORMException::unrecognizedField($fieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
$tableAlias = isset($this->_class->fieldMappings[$fieldName]['inherited']) ?
|
$tableAlias = isset($this->_class->fieldMappings[$fieldName]['inherited']) ?
|
||||||
|
@ -238,7 +238,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0, $limit = null, $offset = null)
|
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0, $limit = null, $offset = null, array $orderBy = null)
|
||||||
{
|
{
|
||||||
$idColumns = $this->_class->getIdentifierColumnNames();
|
$idColumns = $this->_class->getIdentifierColumnNames();
|
||||||
$baseTableAlias = $this->_getSQLTableAlias($this->_class->name);
|
$baseTableAlias = $this->_getSQLTableAlias($this->_class->name);
|
||||||
@ -343,10 +343,8 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
|||||||
|
|
||||||
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
|
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
|
||||||
|
|
||||||
$orderBySql = '';
|
$orderBy = ($assoc !== null && isset($assoc['orderBy'])) ? $assoc['orderBy'] : $orderBy;
|
||||||
if ($assoc != null && isset($assoc['orderBy'])) {
|
$orderBySql = $orderBy ? $this->_getOrderBySQL($orderBy, $baseTableAlias) : '';
|
||||||
$orderBySql = $this->_getCollectionOrderBySQL($assoc['orderBy'], $baseTableAlias);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->_selectColumnListSql === null) {
|
if ($this->_selectColumnListSql === null) {
|
||||||
$this->_selectColumnListSql = $columnList;
|
$this->_selectColumnListSql = $columnList;
|
||||||
|
@ -126,7 +126,7 @@ class Lexer extends \Doctrine\Common\Lexer
|
|||||||
'[a-z_\\\][a-z0-9_\:\\\]*[a-z0-9_]{1}',
|
'[a-z_\\\][a-z0-9_\:\\\]*[a-z0-9_]{1}',
|
||||||
'(?:[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?',
|
'(?:[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?',
|
||||||
"'(?:[^']|'')*'",
|
"'(?:[^']|'')*'",
|
||||||
'\?[1-9][0-9]*|:[a-z][a-z0-9_]+'
|
'\?[1-9][0-9]*|:[a-z]{1}[a-z0-9_]{0,}'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ class Parser
|
|||||||
* If they match, updates the lookahead token; otherwise raises a syntax
|
* If they match, updates the lookahead token; otherwise raises a syntax
|
||||||
* error.
|
* error.
|
||||||
*
|
*
|
||||||
* @param int|string token type or value
|
* @param int token type
|
||||||
* @return void
|
* @return void
|
||||||
* @throws QueryException If the tokens dont match.
|
* @throws QueryException If the tokens dont match.
|
||||||
*/
|
*/
|
||||||
@ -2308,7 +2308,8 @@ class Parser
|
|||||||
if ($peek['value'] == '.') {
|
if ($peek['value'] == '.') {
|
||||||
return $this->StateFieldPathExpression();
|
return $this->StateFieldPathExpression();
|
||||||
} else if ($peek['value'] == '(') {
|
} else if ($peek['value'] == '(') {
|
||||||
return $this->FunctionsReturningStrings();
|
// do NOT directly go to FunctionsReturningString() because it doesnt check for custom functions.
|
||||||
|
return $this->FunctionDeclaration();
|
||||||
} else {
|
} else {
|
||||||
$this->syntaxError("'.' or '('");
|
$this->syntaxError("'.' or '('");
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
@ -393,4 +391,3 @@ class ResultSetMapping
|
|||||||
$this->columnOwnerMap[$columnName] = $alias;
|
$this->columnOwnerMap[$columnName] = $alias;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
100
lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php
Normal file
100
lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<?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\Query;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ResultSetMappingBuilder uses the EntityManager to automatically populate entity fields
|
||||||
|
*
|
||||||
|
* @author Michael Ridgway <mcridgway@gmail.com>
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
class ResultSetMappingBuilder extends ResultSetMapping
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var EntityManager
|
||||||
|
*/
|
||||||
|
private $em;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param EntityManager
|
||||||
|
*/
|
||||||
|
public function __construct(EntityManager $em)
|
||||||
|
{
|
||||||
|
$this->em = $em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a root entity and all of its fields to the result set.
|
||||||
|
*
|
||||||
|
* @param string $class The class name of the root entity.
|
||||||
|
* @param string $alias The unique alias to use for the root entity.
|
||||||
|
* @param array $renamedColumns Columns that have been renamed (tableColumnName => queryColumnName)
|
||||||
|
*/
|
||||||
|
public function addRootEntityFromClassMetadata($class, $alias, $renamedColumns = array())
|
||||||
|
{
|
||||||
|
$this->addEntityResult($class, $alias);
|
||||||
|
$classMetadata = $this->em->getClassMetadata($class);
|
||||||
|
if ($classMetadata->isInheritanceTypeSingleTable() || $classMetadata->isInheritanceTypeJoined()) {
|
||||||
|
throw new \InvalidArgumentException('ResultSetMapping builder does not currently support inheritance.');
|
||||||
|
}
|
||||||
|
$platform = $this->em->getConnection()->getDatabasePlatform();
|
||||||
|
foreach ($classMetadata->getColumnNames() AS $columnName) {
|
||||||
|
$propertyName = $classMetadata->getFieldName($columnName);
|
||||||
|
if (isset($renamedColumns[$columnName])) {
|
||||||
|
$columnName = $renamedColumns[$columnName];
|
||||||
|
}
|
||||||
|
if (isset($this->fieldMappings[$columnName])) {
|
||||||
|
throw new \InvalidArgumentException("The column '$columnName' conflicts with another column in the mapper.");
|
||||||
|
}
|
||||||
|
$this->addFieldResult($alias, $platform->getSQLResultCasing($columnName), $propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a joined entity and all of its fields to the result set.
|
||||||
|
*
|
||||||
|
* @param string $class The class name of the joined entity.
|
||||||
|
* @param string $alias The unique alias to use for the joined entity.
|
||||||
|
* @param string $parentAlias The alias of the entity result that is the parent of this joined result.
|
||||||
|
* @param object $relation The association field that connects the parent entity result with the joined entity result.
|
||||||
|
* @param array $renamedColumns Columns that have been renamed (tableColumnName => queryColumnName)
|
||||||
|
*/
|
||||||
|
public function addJoinedEntityFromClassMetadata($class, $alias, $parentAlias, $relation, $renamedColumns = array())
|
||||||
|
{
|
||||||
|
$this->addJoinedEntityResult($class, $alias, $parentAlias, $relation);
|
||||||
|
$classMetadata = $this->em->getClassMetadata($class);
|
||||||
|
if ($classMetadata->isInheritanceTypeSingleTable() || $classMetadata->isInheritanceTypeJoined()) {
|
||||||
|
throw new \InvalidArgumentException('ResultSetMapping builder does not currently support inheritance.');
|
||||||
|
}
|
||||||
|
$platform = $this->em->getConnection()->getDatabasePlatform();
|
||||||
|
foreach ($classMetadata->getColumnNames() AS $columnName) {
|
||||||
|
$propertyName = $classMetadata->getFieldName($columnName);
|
||||||
|
if (isset($renamedColumns[$columnName])) {
|
||||||
|
$columnName = $renamedColumns[$columnName];
|
||||||
|
}
|
||||||
|
if (isset($this->fieldMappings[$columnName])) {
|
||||||
|
throw new \InvalidArgumentException("The column '$columnName' conflicts with another column in the mapper.");
|
||||||
|
}
|
||||||
|
$this->addFieldResult($alias, $platform->getSQLResultCasing($columnName), $propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -65,7 +65,7 @@ EOT
|
|||||||
|
|
||||||
protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas)
|
protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas)
|
||||||
{
|
{
|
||||||
$output->write('ATTENTION: This operation should not be executed in an production enviroment.' . PHP_EOL . PHP_EOL);
|
$output->write('ATTENTION: This operation should not be executed in a production enviroment.' . PHP_EOL . PHP_EOL);
|
||||||
|
|
||||||
if ($input->getOption('dump-sql') === true) {
|
if ($input->getOption('dump-sql') === true) {
|
||||||
$sqls = $schemaTool->getCreateSchemaSql($metadatas);
|
$sqls = $schemaTool->getCreateSchemaSql($metadatas);
|
||||||
|
@ -92,7 +92,7 @@ EOT
|
|||||||
}
|
}
|
||||||
$output->write('Database schema dropped successfully!' . PHP_EOL);
|
$output->write('Database schema dropped successfully!' . PHP_EOL);
|
||||||
} else {
|
} else {
|
||||||
$output->write('ATTENTION: This operation should not be executed in an production enviroment.' . PHP_EOL . PHP_EOL);
|
$output->write('ATTENTION: This operation should not be executed in a production enviroment.' . PHP_EOL . PHP_EOL);
|
||||||
|
|
||||||
if ($isFullDatabaseDrop) {
|
if ($isFullDatabaseDrop) {
|
||||||
$sqls = $schemaTool->getDropDatabaseSQL();
|
$sqls = $schemaTool->getDropDatabaseSQL();
|
||||||
|
@ -86,7 +86,7 @@ EOT
|
|||||||
$schemaTool->updateSchema($metadatas, $saveMode);
|
$schemaTool->updateSchema($metadatas, $saveMode);
|
||||||
$output->write('Database schema updated successfully!' . PHP_EOL);
|
$output->write('Database schema updated successfully!' . PHP_EOL);
|
||||||
} else {
|
} else {
|
||||||
$output->write('ATTENTION: This operation should not be executed in an production enviroment.' . PHP_EOL);
|
$output->write('ATTENTION: This operation should not be executed in a production enviroment.' . PHP_EOL);
|
||||||
$output->write('Use the incremental update to detect changes during development and use' . PHP_EOL);
|
$output->write('Use the incremental update to detect changes during development and use' . PHP_EOL);
|
||||||
$output->write('this SQL DDL to manually update your database in production.' . PHP_EOL . PHP_EOL);
|
$output->write('this SQL DDL to manually update your database in production.' . PHP_EOL . PHP_EOL);
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ public function <methodName>()
|
|||||||
$this->_isNew = !file_exists($path) || (file_exists($path) && $this->_regenerateEntityIfExists);
|
$this->_isNew = !file_exists($path) || (file_exists($path) && $this->_regenerateEntityIfExists);
|
||||||
|
|
||||||
if ( ! $this->_isNew) {
|
if ( ! $this->_isNew) {
|
||||||
$this->_parseTokensInEntityFile($path);
|
$this->_parseTokensInEntityFile(file_get_contents($path));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->_backupExisting && file_exists($path)) {
|
if ($this->_backupExisting && file_exists($path)) {
|
||||||
@ -400,24 +400,42 @@ public function <methodName>()
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo this won't work if there is a namespace in brackets and a class outside of it.
|
* @todo this won't work if there is a namespace in brackets and a class outside of it.
|
||||||
* @param string $path
|
* @param string $src
|
||||||
*/
|
*/
|
||||||
private function _parseTokensInEntityFile($path)
|
private function _parseTokensInEntityFile($src)
|
||||||
{
|
{
|
||||||
$tokens = token_get_all(file_get_contents($path));
|
$tokens = token_get_all($src);
|
||||||
$lastSeenNamespace = "";
|
$lastSeenNamespace = "";
|
||||||
$lastSeenClass = false;
|
$lastSeenClass = false;
|
||||||
|
|
||||||
|
$inNamespace = false;
|
||||||
|
$inClass = false;
|
||||||
for ($i = 0; $i < count($tokens); $i++) {
|
for ($i = 0; $i < count($tokens); $i++) {
|
||||||
$token = $tokens[$i];
|
$token = $tokens[$i];
|
||||||
if ($token[0] == T_NAMESPACE) {
|
if (in_array($token[0], array(T_WHITESPACE, T_COMMENT, T_DOC_COMMENT))) {
|
||||||
$lastSeenNamespace = $tokens[$i+2][1] . "\\";
|
continue;
|
||||||
} else if ($token[0] == T_NS_SEPARATOR) {
|
}
|
||||||
$lastSeenNamespace .= $tokens[$i+1][1] . "\\";
|
|
||||||
} else if ($token[0] == T_CLASS) {
|
if ($inNamespace) {
|
||||||
$lastSeenClass = $lastSeenNamespace . $tokens[$i+2][1];
|
if ($token[0] == T_NS_SEPARATOR || $token[0] == T_STRING) {
|
||||||
|
$lastSeenNamespace .= $token[1];
|
||||||
|
} else if (is_string($token) && in_array($token, array(';', '{'))) {
|
||||||
|
$inNamespace = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($inClass) {
|
||||||
|
$inClass = false;
|
||||||
|
$lastSeenClass = $lastSeenNamespace . '\\' . $token[1];
|
||||||
$this->_staticReflection[$lastSeenClass]['properties'] = array();
|
$this->_staticReflection[$lastSeenClass]['properties'] = array();
|
||||||
$this->_staticReflection[$lastSeenClass]['methods'] = array();
|
$this->_staticReflection[$lastSeenClass]['methods'] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($token[0] == T_NAMESPACE) {
|
||||||
|
$lastSeenNamespace = "";
|
||||||
|
$inNamespace = true;
|
||||||
|
} else if ($token[0] == T_CLASS) {
|
||||||
|
$inClass = true;
|
||||||
} else if ($token[0] == T_FUNCTION) {
|
} else if ($token[0] == T_FUNCTION) {
|
||||||
if ($tokens[$i+2][0] == T_STRING) {
|
if ($tokens[$i+2][0] == T_STRING) {
|
||||||
$this->_staticReflection[$lastSeenClass]['methods'][] = $tokens[$i+2][1];
|
$this->_staticReflection[$lastSeenClass]['methods'][] = $tokens[$i+2][1];
|
||||||
@ -502,7 +520,7 @@ public function <methodName>()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($metadata->isMappedSuperclass) {
|
if ($metadata->isMappedSuperclass) {
|
||||||
$lines[] = ' * @' . $this->_annotationsPrefix . 'MappedSupperClass';
|
$lines[] = ' * @' . $this->_annotationsPrefix . 'MappedSuperClass';
|
||||||
} else {
|
} else {
|
||||||
$lines[] = ' * @' . $this->_annotationsPrefix . 'Entity';
|
$lines[] = ' * @' . $this->_annotationsPrefix . 'Entity';
|
||||||
}
|
}
|
||||||
|
@ -592,74 +592,44 @@ class SchemaTool
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Get SQL to drop the tables defined by the passed classes.
|
||||||
*
|
*
|
||||||
* @param array $classes
|
* @param array $classes
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getDropSchemaSQL(array $classes)
|
public function getDropSchemaSQL(array $classes)
|
||||||
{
|
{
|
||||||
/* @var $conn \Doctrine\DBAL\Connection */
|
$visitor = new \Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector($this->_platform);
|
||||||
$conn = $this->_em->getConnection();
|
$schema = $this->getSchemaFromMetadata($classes);
|
||||||
|
|
||||||
/* @var $sm \Doctrine\DBAL\Schema\AbstractSchemaManager */
|
$sm = $this->_em->getConnection()->getSchemaManager();
|
||||||
$sm = $conn->getSchemaManager();
|
$fullSchema = $sm->createSchema();
|
||||||
|
foreach ($fullSchema->getTables() AS $table) {
|
||||||
$sql = array();
|
if (!$schema->hasTable($table->getName())) {
|
||||||
$orderedTables = array();
|
foreach ($table->getForeignKeys() AS $foreignKey) {
|
||||||
|
/* @var $foreignKey \Doctrine\DBAL\Schema\ForeignKeyConstraint */
|
||||||
foreach ($classes AS $class) {
|
if ($schema->hasTable($foreignKey->getForeignTableName())) {
|
||||||
if ($class->isIdGeneratorSequence() && !$class->isMappedSuperclass && $class->name == $class->rootEntityName && $this->_platform->supportsSequences()) {
|
$visitor->acceptForeignKey($table, $foreignKey);
|
||||||
$sql[] = $this->_platform->getDropSequenceSQL($class->sequenceGeneratorDefinition['sequenceName']);
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
$visitor->acceptTable($table);
|
||||||
$commitOrder = $this->_getCommitOrder($classes);
|
foreach ($table->getForeignKeys() AS $foreignKey) {
|
||||||
$associationTables = $this->_getAssociationTables($commitOrder);
|
$visitor->acceptForeignKey($table, $foreignKey);
|
||||||
|
|
||||||
// Drop association tables first
|
|
||||||
foreach ($associationTables as $associationTable) {
|
|
||||||
if (!in_array($associationTable, $orderedTables)) {
|
|
||||||
$orderedTables[] = $associationTable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drop tables in reverse commit order
|
|
||||||
for ($i = count($commitOrder) - 1; $i >= 0; --$i) {
|
|
||||||
$class = $commitOrder[$i];
|
|
||||||
|
|
||||||
if (($class->isInheritanceTypeSingleTable() && $class->name != $class->rootEntityName)
|
|
||||||
|| $class->isMappedSuperclass) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_array($class->getTableName(), $orderedTables)) {
|
|
||||||
$orderedTables[] = $class->getTableName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$supportsForeignKeyConstraints = $conn->getDatabasePlatform()->supportsForeignKeyConstraints();
|
|
||||||
$dropTablesSql = array();
|
|
||||||
|
|
||||||
foreach ($orderedTables AS $tableName) {
|
|
||||||
if ($supportsForeignKeyConstraints) {
|
|
||||||
$foreignKeys = $sm->listTableForeignKeys($tableName);
|
|
||||||
|
|
||||||
foreach ($foreignKeys AS $foreignKey) {
|
|
||||||
$sql[] = $this->_platform->getDropForeignKeySQL($foreignKey, $tableName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$dropTablesSql[] = $this->_platform->getDropTableSQL($tableName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_merge($sql, $dropTablesSql);
|
return $visitor->getQueries();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the database schema of the given classes by comparing the ClassMetadata
|
* Updates the database schema of the given classes by comparing the ClassMetadata
|
||||||
* ins$tableNametances to the current database schema that is inspected.
|
* instances to the current database schema that is inspected. If $saveMode is set
|
||||||
|
* to true the command is executed in the Database, else SQL is returned.
|
||||||
*
|
*
|
||||||
* @param array $classes
|
* @param array $classes
|
||||||
|
* @param boolean $saveMode
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function updateSchema(array $classes, $saveMode=false)
|
public function updateSchema(array $classes, $saveMode=false)
|
||||||
@ -675,8 +645,11 @@ class SchemaTool
|
|||||||
/**
|
/**
|
||||||
* Gets the sequence of SQL statements that need to be performed in order
|
* Gets the sequence of SQL statements that need to be performed in order
|
||||||
* to bring the given class mappings in-synch with the relational schema.
|
* to bring the given class mappings in-synch with the relational schema.
|
||||||
|
* If $saveMode is set to true the command is executed in the Database,
|
||||||
|
* else SQL is returned.
|
||||||
*
|
*
|
||||||
* @param array $classes The classes to consider.
|
* @param array $classes The classes to consider.
|
||||||
|
* @param boolean $saveMode True for writing to DB, false for SQL string
|
||||||
* @return array The sequence of SQL statements.
|
* @return array The sequence of SQL statements.
|
||||||
*/
|
*/
|
||||||
public function getUpdateSchemaSql(array $classes, $saveMode=false)
|
public function getUpdateSchemaSql(array $classes, $saveMode=false)
|
||||||
@ -695,44 +668,4 @@ class SchemaTool
|
|||||||
return $schemaDiff->toSql($this->_platform);
|
return $schemaDiff->toSql($this->_platform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function _getCommitOrder(array $classes)
|
|
||||||
{
|
|
||||||
$calc = new CommitOrderCalculator;
|
|
||||||
|
|
||||||
// Calculate dependencies
|
|
||||||
foreach ($classes as $class) {
|
|
||||||
$calc->addClass($class);
|
|
||||||
|
|
||||||
foreach ($class->associationMappings as $assoc) {
|
|
||||||
if ($assoc['isOwningSide']) {
|
|
||||||
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
|
|
||||||
|
|
||||||
if ( ! $calc->hasClass($targetClass->name)) {
|
|
||||||
$calc->addClass($targetClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add dependency ($targetClass before $class)
|
|
||||||
$calc->addDependency($targetClass, $class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $calc->getCommitOrder();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function _getAssociationTables(array $classes)
|
|
||||||
{
|
|
||||||
$associationTables = array();
|
|
||||||
|
|
||||||
foreach ($classes as $class) {
|
|
||||||
foreach ($class->associationMappings as $assoc) {
|
|
||||||
if ($assoc['isOwningSide'] && $assoc['type'] == ClassMetadata::MANY_TO_MANY) {
|
|
||||||
$associationTables[] = $assoc['joinTable']['name'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $associationTables;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -406,8 +406,11 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
$actualData = array();
|
$actualData = array();
|
||||||
foreach ($class->reflFields as $name => $refProp) {
|
foreach ($class->reflFields as $name => $refProp) {
|
||||||
$value = $refProp->getValue($entity);
|
$value = $refProp->getValue($entity);
|
||||||
if ($class->isCollectionValuedAssociation($name) && $value !== null
|
if (isset($class->associationMappings[$name])
|
||||||
|
&& ($class->associationMappings[$name]['type'] & ClassMetadata::TO_MANY)
|
||||||
|
&& $value !== null
|
||||||
&& ! ($value instanceof PersistentCollection)) {
|
&& ! ($value instanceof PersistentCollection)) {
|
||||||
|
|
||||||
// If $value is not a Collection then use an ArrayCollection.
|
// If $value is not a Collection then use an ArrayCollection.
|
||||||
if ( ! $value instanceof Collection) {
|
if ( ! $value instanceof Collection) {
|
||||||
$value = new ArrayCollection($value);
|
$value = new ArrayCollection($value);
|
||||||
@ -426,7 +429,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
$coll->setDirty( ! $coll->isEmpty());
|
$coll->setDirty( ! $coll->isEmpty());
|
||||||
$class->reflFields[$name]->setValue($entity, $coll);
|
$class->reflFields[$name]->setValue($entity, $coll);
|
||||||
$actualData[$name] = $coll;
|
$actualData[$name] = $coll;
|
||||||
} else if ( ! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity()) {
|
} else if ( (! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity()) && ($name !== $class->versionField) ) {
|
||||||
$actualData[$name] = $value;
|
$actualData[$name] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -474,9 +477,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
}
|
}
|
||||||
} else if ($isChangeTrackingNotify) {
|
} else if ($isChangeTrackingNotify) {
|
||||||
continue;
|
continue;
|
||||||
} else if (is_object($orgValue) && $orgValue !== $actualValue) {
|
} else if ($orgValue !== $actualValue) {
|
||||||
$changeSet[$propName] = array($orgValue, $actualValue);
|
|
||||||
} else if ($orgValue != $actualValue || ($orgValue === null ^ $actualValue === null)) {
|
|
||||||
$changeSet[$propName] = array($orgValue, $actualValue);
|
$changeSet[$propName] = array($orgValue, $actualValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
lib/vendor/doctrine-common
vendored
2
lib/vendor/doctrine-common
vendored
@ -1 +1 @@
|
|||||||
Subproject commit ba63ae0f0b6b62a2a8617f01386698730ff2b713
|
Subproject commit 076a03f8f40b6e08f0ae2f4ee2678474e64b6f59
|
@ -104,9 +104,42 @@ class DatabaseDriverTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertArrayHasKey('user', $metadatas['CmsGroups']->associationMappings);
|
$this->assertArrayHasKey('user', $metadatas['CmsGroups']->associationMappings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testIgnoreManyToManyTableWithoutFurtherForeignKeyDetails()
|
||||||
|
{
|
||||||
|
$tableB = new \Doctrine\DBAL\Schema\Table("dbdriver_bar");
|
||||||
|
$tableB->addColumn('id', 'integer');
|
||||||
|
$tableB->setPrimaryKey(array('id'));
|
||||||
|
|
||||||
|
$tableA = new \Doctrine\DBAL\Schema\Table("dbdriver_baz");
|
||||||
|
$tableA->addColumn('id', 'integer');
|
||||||
|
$tableA->setPrimaryKey(array('id'));
|
||||||
|
|
||||||
|
$tableMany = new \Doctrine\DBAL\Schema\Table("dbdriver_bar_baz");
|
||||||
|
$tableMany->addColumn('bar_id', 'integer');
|
||||||
|
$tableMany->addColumn('baz_id', 'integer');
|
||||||
|
$tableMany->addForeignKeyConstraint('dbdriver_bar', array('bar_id'), array('id'));
|
||||||
|
|
||||||
|
$metadatas = $this->convertToClassMetadata(array($tableA, $tableB), array($tableMany));
|
||||||
|
|
||||||
|
$this->assertEquals(0, count($metadatas['DbdriverBaz']->associationMappings), "no association mappings should be detected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function convertToClassMetadata(array $entityTables, array $manyTables = array())
|
||||||
|
{
|
||||||
|
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($this->_sm);
|
||||||
|
$driver->setTables($entityTables, $manyTables);
|
||||||
|
|
||||||
|
$metadatas = array();
|
||||||
|
foreach ($driver->getAllClassNames() AS $className) {
|
||||||
|
$class = new ClassMetadataInfo($className);
|
||||||
|
$driver->loadMetadataForClass($className, $class);
|
||||||
|
$metadatas[$className] = $class;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $metadatas;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param string $className
|
* @param string $className
|
||||||
* @return ClassMetadata
|
* @return ClassMetadata
|
||||||
*/
|
*/
|
||||||
|
@ -320,5 +320,40 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertEquals(1, count($params), "Should only execute with one parameter.");
|
$this->assertEquals(1, count($params), "Should only execute with one parameter.");
|
||||||
$this->assertEquals(array('romanb'), $params);
|
$this->assertEquals(array('romanb'), $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1094
|
||||||
|
*/
|
||||||
|
public function testFindByLimitOffset()
|
||||||
|
{
|
||||||
|
$this->loadFixture();
|
||||||
|
|
||||||
|
$repos = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser');
|
||||||
|
|
||||||
|
$users1 = $repos->findBy(array(), null, 1, 0);
|
||||||
|
$users2 = $repos->findBy(array(), null, 1, 1);
|
||||||
|
|
||||||
|
$this->assertEquals(2, count($repos->findBy(array())));
|
||||||
|
$this->assertEquals(1, count($users1));
|
||||||
|
$this->assertEquals(1, count($users2));
|
||||||
|
$this->assertNotSame($users1[0], $users2[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1094
|
||||||
|
*/
|
||||||
|
public function testFindByOrderBy()
|
||||||
|
{
|
||||||
|
$this->loadFixture();
|
||||||
|
|
||||||
|
$repos = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsUser');
|
||||||
|
$usersAsc = $repos->findBy(array(), array("username" => "ASC"));
|
||||||
|
$usersDesc = $repos->findBy(array(), array("username" => "DESC"));
|
||||||
|
|
||||||
|
$this->assertEquals(2, count($usersAsc), "Pre-condition: only two users in fixture");
|
||||||
|
$this->assertEquals(2, count($usersDesc), "Pre-condition: only two users in fixture");
|
||||||
|
$this->assertSame($usersAsc[0], $usersDesc[1]);
|
||||||
|
$this->assertSame($usersAsc[1], $usersDesc[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,12 @@
|
|||||||
namespace Doctrine\Tests\ORM\Functional;
|
namespace Doctrine\Tests\ORM\Functional;
|
||||||
|
|
||||||
use Doctrine\ORM\Query\ResultSetMapping;
|
use Doctrine\ORM\Query\ResultSetMapping;
|
||||||
|
use Doctrine\ORM\Query\ResultSetMappingBuilder;
|
||||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||||
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
||||||
use Doctrine\Tests\Models\CMS\CmsAddress;
|
use Doctrine\Tests\Models\CMS\CmsAddress;
|
||||||
|
use Doctrine\Tests\Models\Company\CompanyFixContract;
|
||||||
|
use Doctrine\Tests\Models\Company\CompanyEmployee;
|
||||||
|
|
||||||
require_once __DIR__ . '/../../TestInit.php';
|
require_once __DIR__ . '/../../TestInit.php';
|
||||||
|
|
||||||
@ -156,5 +159,111 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
|
|
||||||
$this->assertSame($q, $q2);
|
$this->assertSame($q, $q2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testJoinedOneToManyNativeQueryWithRSMBuilder()
|
||||||
|
{
|
||||||
|
$user = new CmsUser;
|
||||||
|
$user->name = 'Roman';
|
||||||
|
$user->username = 'romanb';
|
||||||
|
$user->status = 'dev';
|
||||||
|
|
||||||
|
$phone = new CmsPhonenumber;
|
||||||
|
$phone->phonenumber = 424242;
|
||||||
|
|
||||||
|
$user->addPhonenumber($phone);
|
||||||
|
|
||||||
|
$this->_em->persist($user);
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$rsm = new ResultSetMappingBuilder($this->_em);
|
||||||
|
$rsm->addRootEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||||
|
$rsm->addJoinedEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsPhonenumber', 'p', 'u', 'phonenumbers');
|
||||||
|
$query = $this->_em->createNativeQuery('SELECT u.*, p.* FROM cms_users u LEFT JOIN cms_phonenumbers p ON u.id = p.user_id WHERE username = ?', $rsm);
|
||||||
|
$query->setParameter(1, 'romanb');
|
||||||
|
|
||||||
|
$users = $query->getResult();
|
||||||
|
$this->assertEquals(1, count($users));
|
||||||
|
$this->assertTrue($users[0] instanceof CmsUser);
|
||||||
|
$this->assertEquals('Roman', $users[0]->name);
|
||||||
|
$this->assertTrue($users[0]->getPhonenumbers() instanceof \Doctrine\ORM\PersistentCollection);
|
||||||
|
$this->assertTrue($users[0]->getPhonenumbers()->isInitialized());
|
||||||
|
$this->assertEquals(1, count($users[0]->getPhonenumbers()));
|
||||||
|
$phones = $users[0]->getPhonenumbers();
|
||||||
|
$this->assertEquals(424242, $phones[0]->phonenumber);
|
||||||
|
$this->assertTrue($phones[0]->getUser() === $users[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testJoinedOneToOneNativeQueryWithRSMBuilder()
|
||||||
|
{
|
||||||
|
$user = new CmsUser;
|
||||||
|
$user->name = 'Roman';
|
||||||
|
$user->username = 'romanb';
|
||||||
|
$user->status = 'dev';
|
||||||
|
|
||||||
|
$addr = new CmsAddress;
|
||||||
|
$addr->country = 'germany';
|
||||||
|
$addr->zip = 10827;
|
||||||
|
$addr->city = 'Berlin';
|
||||||
|
|
||||||
|
|
||||||
|
$user->setAddress($addr);
|
||||||
|
|
||||||
|
$this->_em->persist($user);
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
|
||||||
|
$rsm = new ResultSetMappingBuilder($this->_em);
|
||||||
|
$rsm->addRootEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||||
|
$rsm->addJoinedEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress', 'a', 'u', 'address', array('id' => 'a_id'));
|
||||||
|
|
||||||
|
$query = $this->_em->createNativeQuery('SELECT u.*, a.*, a.id AS a_id FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?', $rsm);
|
||||||
|
$query->setParameter(1, 'romanb');
|
||||||
|
|
||||||
|
$users = $query->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals(1, count($users));
|
||||||
|
$this->assertTrue($users[0] instanceof CmsUser);
|
||||||
|
$this->assertEquals('Roman', $users[0]->name);
|
||||||
|
$this->assertTrue($users[0]->getPhonenumbers() instanceof \Doctrine\ORM\PersistentCollection);
|
||||||
|
$this->assertFalse($users[0]->getPhonenumbers()->isInitialized());
|
||||||
|
$this->assertTrue($users[0]->getAddress() instanceof CmsAddress);
|
||||||
|
$this->assertTrue($users[0]->getAddress()->getUser() == $users[0]);
|
||||||
|
$this->assertEquals('germany', $users[0]->getAddress()->getCountry());
|
||||||
|
$this->assertEquals(10827, $users[0]->getAddress()->getZipCode());
|
||||||
|
$this->assertEquals('Berlin', $users[0]->getAddress()->getCity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testRSMBuilderThrowsExceptionOnColumnConflict()
|
||||||
|
{
|
||||||
|
$rsm = new ResultSetMappingBuilder($this->_em);
|
||||||
|
$rsm->addRootEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||||
|
$rsm->addJoinedEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress', 'a', 'u', 'address');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group PR-39
|
||||||
|
*/
|
||||||
|
public function testUnknownParentAliasThrowsException()
|
||||||
|
{
|
||||||
|
$rsm = new ResultSetMappingBuilder($this->_em);
|
||||||
|
$rsm->addRootEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||||
|
$rsm->addJoinedEntityFromClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress', 'a', 'un', 'address', array('id' => 'a_id'));
|
||||||
|
|
||||||
|
$query = $this->_em->createNativeQuery('SELECT u.*, a.*, a.id AS a_id FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?', $rsm);
|
||||||
|
$query->setParameter(1, 'romanb');
|
||||||
|
|
||||||
|
$this->setExpectedException(
|
||||||
|
"Doctrine\ORM\Internal\Hydration\HydrationException",
|
||||||
|
"The parent object of entity result with alias 'a' was not found. The parent alias is 'un'."
|
||||||
|
);
|
||||||
|
$users = $query->getResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,4 +50,19 @@ class CompanySchemaTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertFalse($table->getColumn('pricePerHour')->getNotnull());
|
$this->assertFalse($table->getColumn('pricePerHour')->getNotnull());
|
||||||
$this->assertFalse($table->getColumn('maxPrice')->getNotnull());
|
$this->assertFalse($table->getColumn('maxPrice')->getNotnull());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DBAL-115
|
||||||
|
*/
|
||||||
|
public function testDropPartSchemaWithForeignKeys()
|
||||||
|
{
|
||||||
|
if (!$this->_em->getConnection()->getDatabasePlatform()->supportsForeignKeyConstraints()) {
|
||||||
|
$this->markTestSkipped("Foreign Key test");
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = $this->_schemaTool->getDropSchemaSQL(array(
|
||||||
|
$this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyManager'),
|
||||||
|
));
|
||||||
|
$this->assertEquals(3, count($sql));
|
||||||
|
}
|
||||||
}
|
}
|
36
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1043Test.php
Normal file
36
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1043Test.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
require_once __DIR__ . '/../../../TestInit.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1043
|
||||||
|
*/
|
||||||
|
class DDC1043Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->useModelSet('cms');
|
||||||
|
parent::setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testChangeSetPlusWeirdPHPCastingIntCastingRule()
|
||||||
|
{
|
||||||
|
$user = new \Doctrine\Tests\Models\CMS\CmsUser();
|
||||||
|
$user->name = "John Galt";
|
||||||
|
$user->username = "jgalt";
|
||||||
|
$user->status = "+44";
|
||||||
|
|
||||||
|
$this->_em->persist($user);
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$user->status = "44";
|
||||||
|
$this->_em->flush();
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$user = $this->_em->find("Doctrine\Tests\Models\CMS\CmsUser", $user->id);
|
||||||
|
$this->assertSame("44", $user->status);
|
||||||
|
}
|
||||||
|
}
|
46
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1129Test.php
Normal file
46
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1129Test.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
require_once __DIR__ . '/../../../TestInit.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1129
|
||||||
|
*/
|
||||||
|
class DDC1129Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->useModelSet('cms');
|
||||||
|
parent::setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testVersionFieldIgnoredInChangesetComputation()
|
||||||
|
{
|
||||||
|
$article = new \Doctrine\Tests\Models\CMS\CmsArticle();
|
||||||
|
$article->text = "I don't know.";
|
||||||
|
$article->topic = "Who is John Galt?";
|
||||||
|
|
||||||
|
$this->_em->persist($article);
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$this->assertEquals(1, $article->version);
|
||||||
|
|
||||||
|
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsArticle');
|
||||||
|
$uow = $this->_em->getUnitOfWork();
|
||||||
|
|
||||||
|
$uow->computeChangeSet($class, $article);
|
||||||
|
$changeSet = $uow->getEntityChangeSet($article);
|
||||||
|
$this->assertEquals(0, count($changeSet), "No changesets should be computed.");
|
||||||
|
|
||||||
|
$article->text = "This is John Galt speaking.";
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
$this->assertEquals(2, $article->version);
|
||||||
|
|
||||||
|
$uow->computeChangeSet($class, $article);
|
||||||
|
$changeSet = $uow->getEntityChangeSet($article);
|
||||||
|
$this->assertEquals(0, count($changeSet), "No changesets should be computed.");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Performance;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../TestInit.php';
|
||||||
|
|
||||||
|
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of InsertPerformanceTest
|
||||||
|
*
|
||||||
|
* @author robo
|
||||||
|
*/
|
||||||
|
class UnitOfWorkPerformanceTest extends \Doctrine\Tests\OrmPerformanceTestCase
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->useModelSet('cms');
|
||||||
|
parent::setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testComputeChanges()
|
||||||
|
{
|
||||||
|
$n = 100;
|
||||||
|
|
||||||
|
$users = array();
|
||||||
|
for ($i=1; $i<=$n; ++$i) {
|
||||||
|
$user = new CmsUser;
|
||||||
|
$user->status = 'user';
|
||||||
|
$user->username = 'user' . $i;
|
||||||
|
$user->name = 'Mr.Smith-' . $i;
|
||||||
|
$this->_em->persist($user);
|
||||||
|
$users[] = $user;
|
||||||
|
}
|
||||||
|
$this->_em->flush();
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($users AS $user) {
|
||||||
|
$user->status = 'other';
|
||||||
|
$user->username = $user->username . '++';
|
||||||
|
$user->name = str_replace('Mr.', 'Mrs.', $user->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
$s = microtime(true);
|
||||||
|
$this->_em->flush();
|
||||||
|
$e = microtime(true);
|
||||||
|
|
||||||
|
echo ' Compute ChangeSet '.$n.' objects in ' . ($e - $s) . ' seconds' . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
@ -482,6 +482,16 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
$this->assertValidDQL('SELECT u, u.id + ?1 AS someNumber FROM Doctrine\Tests\Models\CMS\CmsUser u');
|
$this->assertValidDQL('SELECT u, u.id + ?1 AS someNumber FROM Doctrine\Tests\Models\CMS\CmsUser u');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1091
|
||||||
|
*/
|
||||||
|
public function testCustomFunctionsReturningStringInStringPrimary()
|
||||||
|
{
|
||||||
|
$this->_em->getConfiguration()->addCustomStringFunction('CC', 'Doctrine\ORM\Query\AST\Functions\ConcatFunction');
|
||||||
|
|
||||||
|
$this->assertValidDQL("SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE CC('%', u.name) LIKE '%foo%'", true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group DDC-505
|
* @group DDC-505
|
||||||
*/
|
*/
|
||||||
@ -513,6 +523,14 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
$this->assertInvalidDQL('SELECT g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g');
|
$this->assertInvalidDQL('SELECT g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-1108
|
||||||
|
*/
|
||||||
|
public function testInputParameterSingleChar()
|
||||||
|
{
|
||||||
|
$this->assertValidDQL('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = :q');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group DDC-1053
|
* @group DDC-1053
|
||||||
*/
|
*/
|
||||||
|
@ -200,6 +200,54 @@ class EntityGeneratorTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
$this->assertEquals($cm->idGenerator, $metadata->idGenerator);
|
$this->assertEquals($cm->idGenerator, $metadata->idGenerator);
|
||||||
$this->assertEquals($cm->customRepositoryClassName, $metadata->customRepositoryClassName);
|
$this->assertEquals($cm->customRepositoryClassName, $metadata->customRepositoryClassName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getParseTokensInEntityFileData
|
||||||
|
*/
|
||||||
|
public function testParseTokensInEntityFile($php, $classes)
|
||||||
|
{
|
||||||
|
$r = new \ReflectionObject($this->_generator);
|
||||||
|
$m = $r->getMethod('_parseTokensInEntityFile');
|
||||||
|
$m->setAccessible(true);
|
||||||
|
|
||||||
|
$p = $r->getProperty('_staticReflection');
|
||||||
|
$p->setAccessible(true);
|
||||||
|
|
||||||
|
$ret = $m->invoke($this->_generator, $php);
|
||||||
|
$this->assertEquals($classes, array_keys($p->getValue($this->_generator)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParseTokensInEntityFileData()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(
|
||||||
|
'<?php namespace Foo\Bar; class Baz {}',
|
||||||
|
array('Foo\Bar\Baz'),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'<?php namespace Foo\Bar; use Foo; class Baz {}',
|
||||||
|
array('Foo\Bar\Baz'),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'<?php namespace /*Comment*/ Foo\Bar; /** Foo */class /* Comment */ Baz {}',
|
||||||
|
array('Foo\Bar\Baz'),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'
|
||||||
|
<?php namespace
|
||||||
|
/*Comment*/
|
||||||
|
Foo\Bar
|
||||||
|
;
|
||||||
|
|
||||||
|
/** Foo */
|
||||||
|
class
|
||||||
|
/* Comment */
|
||||||
|
Baz {}
|
||||||
|
',
|
||||||
|
array('Foo\Bar\Baz'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EntityGeneratorAuthor {}
|
class EntityGeneratorAuthor {}
|
||||||
|
Loading…
Reference in New Issue
Block a user