1
0
mirror of synced 2025-02-21 14:43:14 +03:00

[2.0] Work on ID generators, functional tests and more.

This commit is contained in:
romanb 2009-03-30 19:43:05 +00:00
parent 2812318254
commit f9a222817c
45 changed files with 534 additions and 519 deletions

View File

@ -25,13 +25,16 @@ class DoctrineException extends \Exception
public static function __callStatic($method, $arguments) public static function __callStatic($method, $arguments)
{ {
$class = get_called_class();
$messageKey = substr($class, strrpos($class, '\\') + 1) . "#$method";
$end = end($arguments); $end = end($arguments);
if ($end instanceof Exception) { if ($end instanceof Exception) {
$this->_innerException = $end; $this->_innerException = $end;
unset($arguments[count($arguments) - 1]); unset($arguments[count($arguments) - 1]);
} }
if ($message = self::getExceptionMessage($method)) { if ($message = self::getExceptionMessage($messageKey)) {
$message = sprintf($message, $arguments); $message = sprintf($message, $arguments);
} else { } else {
$message = strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $method)); $message = strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $method));
@ -42,22 +45,25 @@ class DoctrineException extends \Exception
} }
$message .= ' (' . implode(', ', $args) . ')'; $message .= ' (' . implode(', ', $args) . ')';
} }
$class = get_called_class();
return new $class($message); return new $class($message);
} }
public static function getExceptionMessage($method) public static function getExceptionMessage($messageKey)
{ {
if ( ! self::$_messages) { if ( ! self::$_messages) {
// Lazy-init messages
self::$_messages = array( self::$_messages = array(
'partialObjectsAreDangerous' => 'DoctrineException#partialObjectsAreDangerous' =>
"Loading partial objects is dangerous. Fetch full objects or consider " . "Loading partial objects is dangerous. Fetch full objects or consider " .
"using a different fetch mode. If you really want partial objects, " . "using a different fetch mode. If you really want partial objects, " .
"set the doctrine.forcePartialLoad query hint to TRUE." "set the doctrine.forcePartialLoad query hint to TRUE.",
'QueryException#nonUniqueResult' =>
"The query contains more than one result."
); );
} }
if (isset(self::$_messages[$method])) { if (isset(self::$_messages[$messageKey])) {
return self::$_messages[$method]; return self::$_messages[$messageKey];
} }
return false; return false;
} }

View File

@ -515,7 +515,7 @@ class Connection
{ {
$this->connect(); $this->connect();
try { try {
echo $query . PHP_EOL; echo "DBAL:" . $query . PHP_EOL;
if ( ! empty($params)) { if ( ! empty($params)) {
$stmt = $this->prepare($query); $stmt = $this->prepare($query);
$stmt->execute($params); $stmt->execute($params);
@ -756,6 +756,7 @@ class Connection
*/ */
public function getWrappedConnection() public function getWrappedConnection()
{ {
$this->connect();
return $this->_conn; return $this->_conn;
} }

View File

@ -28,7 +28,18 @@ class Driver implements \Doctrine\DBAL\Driver
*/ */
private function _constructPdoDsn(array $params) private function _constructPdoDsn(array $params)
{ {
//TODO $dsn = 'pgsql:';
if (isset($params['host'])) {
$dsn .= 'host=' . $params['host'] . ' ';
}
if (isset($params['port'])) {
$dsn .= 'port=' . $params['port'] . ' ';
}
if (isset($params['dbname'])) {
$dsn .= 'dbname=' . $params['dbname'] . ' ';
}
return $dsn;
} }
public function getDatabasePlatform() public function getDatabasePlatform()

View File

@ -108,13 +108,6 @@ class EntityManager
*/ */
private $_eventManager; private $_eventManager;
/**
* The maintained (cached) Id generators.
*
* @var array
*/
private $_idGenerators = array();
/** /**
* The maintained (cached) hydrators. One instance per type. * The maintained (cached) hydrators. One instance per type.
* *
@ -202,38 +195,6 @@ class EntityManager
{ {
return $this->_metadataFactory->getMetadataFor($className); return $this->_metadataFactory->getMetadataFor($className);
} }
/**
* Gets an IdGenerator that can be used to generate identifiers for the specified
* class.
*/
public function getIdGenerator($className)
{
if (!isset($this->_idGenerators[$className])) {
$this->_idGenerators[$className] = $this->_createIdGenerator(
$this->getClassMetadata($className)->getIdGeneratorType());
}
return $this->_idGenerators[$className];
}
/**
* Used to lazily create an ID generator.
*
* @param string $generatorType
* @return object
*/
protected function _createIdGenerator($generatorType)
{
if ($generatorType == ClassMetadata::GENERATOR_TYPE_IDENTITY) {
return new \Doctrine\ORM\Id\IdentityGenerator($this);
} else if ($generatorType == ClassMetadata::GENERATOR_TYPE_SEQUENCE) {
return new \Doctrine\ORM\Id\SequenceGenerator($this);
} else if ($generatorType == ClassMetadata::GENERATOR_TYPE_TABLE) {
return new \Doctrine\ORM\Id\TableGenerator($this);
} else {
return new \Doctrine\ORM\Id\Assigned($this);
}
}
/** /**
* Creates a new Query object. * Creates a new Query object.
@ -265,7 +226,7 @@ class EntityManager
* Creates a query with the specified name. * Creates a query with the specified name.
* *
* @todo Implementation. * @todo Implementation.
* @throws SomeException If there is no query registered with the given name. * @throws DoctrineException If there is no query registered with the given name.
*/ */
public function createNamedQuery($name) public function createNamedQuery($name)
{ {

View File

@ -1,182 +0,0 @@
<?php
/*
* $Id$
*
* 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\Export;
use Doctrine\ORM\EntityManager;
/**
* The ClassExporter can generate database schemas/structures from ClassMetadata
* class descriptors.
*
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Roman Borschel <roman@code-factory.org>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 4805 $
*/
class ClassExporter
{
/** The SchemaManager */
private $_sm;
/** The EntityManager */
private $_em;
/** The DatabasePlatform */
private $_platform;
/**
* Initializes a new ClassExporter instance that uses the connection of the
* provided EntityManager.
*
* @param Doctrine\ORM\EntityManager $em
*/
public function __construct(EntityManager $em)
{
$this->_em = $em;
$this->_sm = $em->getConnection()->getSchemaManager();
$this->_platform = $em->getConnection()->getDatabasePlatform();
}
/**
* Exports an array of class meta data instances to your database
*
* @param array $classes
*/
public function exportClasses(array $classes)
{
$exportClassesSql = $this->getExportClassesSql($classes);
foreach ($exportClassesSql as $sql) {
$this->_em->getConnection()->execute($sql);
}
}
/**
* Get an array of sql statements for the specified array of class meta data instances
*
* @param array $classes
* @return array $sql
*/
public function getExportClassesSql(array $classes)
{
$sql = array();
$foreignKeyConstraints = array();
// First we create the tables
foreach ($classes as $class) {
$columns = array();
$options = array();
foreach ($class->getFieldMappings() as $fieldName => $mapping) {
$column = array();
$column['name'] = $mapping['columnName'];
$column['type'] = $mapping['type'];
$column['length'] = $mapping['length'];
$column['notnull'] = ! $mapping['nullable'];
if ($class->isIdentifier($fieldName)) {
$column['primary'] = true;
$options['primary'][] = $mapping['columnName'];
if ($class->isIdGeneratorIdentity()) {
$column['autoincrement'] = true;
}
}
$columns[$mapping['columnName']] = $column;
}
foreach ($class->getAssociationMappings() as $mapping) {
$foreignClass = $this->_em->getClassMetadata($mapping->getTargetEntityName());
if ($mapping->isOneToOne() && $mapping->isOwningSide()) {
$constraint = array();
$constraint['tableName'] = $class->getTableName();
$constraint['foreignTable'] = $foreignClass->getTableName();
$constraint['local'] = array();
$constraint['foreign'] = array();
foreach ($mapping->getJoinColumns() as $joinColumn) {
$column = array();
$column['name'] = $joinColumn['name'];
$column['type'] = $foreignClass->getTypeOfColumn($joinColumn['referencedColumnName']);
$columns[$joinColumn['name']] = $column;
$constraint['local'][] = $joinColumn['name'];
$constraint['foreign'][] = $joinColumn['referencedColumnName'];
}
$foreignKeyConstraints[] = $constraint;
} else if ($mapping->isOneToMany() && $mapping->isOwningSide()) {
//... create join table, one-many through join table supported later
\Doctrine\Common\DoctrineException::updateMe("Not yet implemented.");
} else if ($mapping->isManyToMany() && $mapping->isOwningSide()) {
//... create join table
$joinTableColumns = array();
$joinTableOptions = array();
$joinTable = $mapping->getJoinTable();
$constraint1 = array();
$constraint1['tableName'] = $joinTable['name'];
$constraint1['foreignTable'] = $class->getTableName();
$constraint1['local'] = array();
$constraint1['foreign'] = array();
foreach ($joinTable['joinColumns'] as $joinColumn) {
$column = array();
$column['primary'] = true;
$joinTableOptions['primary'][] = $joinColumn['name'];
$column['name'] = $joinColumn['name'];
$column['type'] = $class->getTypeOfColumn($joinColumn['referencedColumnName']);
$joinTableColumns[$joinColumn['name']] = $column;
$constraint1['local'][] = $joinColumn['name'];
$constraint1['foreign'][] = $joinColumn['referencedColumnName'];
}
$foreignKeyConstraints[] = $constraint1;
$constraint2 = array();
$constraint2['tableName'] = $joinTable['name'];
$constraint2['foreignTable'] = $foreignClass->getTableName();
$constraint2['local'] = array();
$constraint2['foreign'] = array();
foreach ($joinTable['inverseJoinColumns'] as $inverseJoinColumn) {
$column = array();
$column['primary'] = true;
$joinTableOptions['primary'][] = $inverseJoinColumn['name'];
$column['name'] = $inverseJoinColumn['name'];
$column['type'] = $this->_em->getClassMetadata($mapping->getTargetEntityName())
->getTypeOfColumn($inverseJoinColumn['referencedColumnName']);
$joinTableColumns[$inverseJoinColumn['name']] = $column;
$constraint2['local'][] = $inverseJoinColumn['name'];
$constraint2['foreign'][] = $inverseJoinColumn['referencedColumnName'];
}
$foreignKeyConstraints[] = $constraint2;
$sql = array_merge($sql, $this->_platform->getCreateTableSql(
$joinTable['name'], $joinTableColumns, $joinTableOptions));
}
}
$sql = array_merge($sql, $this->_platform->getCreateTableSql($class->getTableName(), $columns, $options));
}
// Now create the foreign key constraints
if ($this->_platform->supportsForeignKeyConstraints()) {
foreach ($foreignKeyConstraints as $fkConstraint) {
$sql = array_merge($sql, (array)$this->_platform->getCreateForeignKeySql($fkConstraint['tableName'], $fkConstraint));
}
}
return $sql;
}
}

View File

@ -8,21 +8,14 @@ use Doctrine\ORM\EntityManager;
* Enter description here... * Enter description here...
*/ */
abstract class AbstractIdGenerator abstract class AbstractIdGenerator
{ {
protected $_em;
public function __construct(EntityManager $em)
{
$this->_em = $em;
}
/** /**
* Generates an identifier for an entity. * Generates an identifier for an entity.
* *
* @param Doctrine\ORM\Entity $entity * @param Doctrine\ORM\Entity $entity
* @return mixed * @return mixed
*/ */
abstract public function generate($entity); abstract public function generate(EntityManager $em, $entity);
/** /**
* Gets whether this generator is a post-insert generator which means that * Gets whether this generator is a post-insert generator which means that

View File

@ -21,6 +21,7 @@
namespace Doctrine\ORM\Id; namespace Doctrine\ORM\Id;
use Doctrine\ORM\EntityManager;
use Doctrine\Common\DoctrineException; use Doctrine\Common\DoctrineException;
/** /**
@ -38,9 +39,9 @@ class Assigned extends AbstractIdGenerator
* @return mixed * @return mixed
* @override * @override
*/ */
public function generate($entity) public function generate(EntityManager $em, $entity)
{ {
$class = $this->_em->getClassMetadata(get_class($entity)); $class = $em->getClassMetadata(get_class($entity));
$identifier = null; $identifier = null;
if ($class->isIdentifierComposite()) { if ($class->isIdentifierComposite()) {
$identifier = array(); $identifier = array();
@ -61,7 +62,7 @@ class Assigned extends AbstractIdGenerator
} }
if ( ! $identifier) { if ( ! $identifier) {
\Doctrine\Common\DoctrineException::updateMe("Entity of type '" . get_class($entity) . "' is missing an assigned ID."); throw DoctrineException::updateMe("Entity of type '" . get_class($entity) . "' is missing an assigned ID.");
} }
return $identifier; return $identifier;

View File

@ -2,18 +2,20 @@
namespace Doctrine\ORM\Id; namespace Doctrine\ORM\Id;
use Doctrine\ORM\EntityManager;
class IdentityGenerator extends AbstractIdGenerator class IdentityGenerator extends AbstractIdGenerator
{ {
/** /**
* Enter description here... * Generates an ID for the given entity.
* *
* @param Doctrine_ORM_Entity $entity * @param object $entity
* @return unknown * @return integer|float
* @override * @override
*/ */
public function generate($entity) public function generate(EntityManager $em, $entity)
{ {
return $this->_em->getConnection()->lastInsertId(); return $em->getConnection()->lastInsertId();
} }
/** /**

View File

@ -1,19 +1,50 @@
<?php <?php
/*
* $Id$
*
* 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\Id; namespace Doctrine\ORM\Id;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
class SequenceGenerator extends AbstractIdGenerator /**
* Represents an ID generator that uses a database sequence.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
*/
class SequenceGenerator extends AbstractIdGenerator implements \Serializable
{ {
private $_allocationSize; private $_allocationSize;
private $_sequenceName; private $_sequenceName;
private $_nextValue = 0; private $_nextValue = 0;
private $_maxValue = null; private $_maxValue = null;
public function __construct(EntityManager $em, $sequenceName, $allocationSize = 20) /**
* Initializes a new sequence generator.
*
* @param Doctrine\ORM\EntityManager $em The EntityManager to use.
* @param string $sequenceName The name of the sequence.
* @param integer $allocationSize The allocation size of the sequence.
*/
public function __construct($sequenceName, $allocationSize)
{ {
parent::__construct($em);
$this->_sequenceName = $sequenceName; $this->_sequenceName = $sequenceName;
$this->_allocationSize = $allocationSize; $this->_allocationSize = $allocationSize;
} }
@ -25,11 +56,11 @@ class SequenceGenerator extends AbstractIdGenerator
* @return integer|float The generated value. * @return integer|float The generated value.
* @override * @override
*/ */
public function generate($entity) public function generate(EntityManager $em, $entity)
{ {
if ($this->_maxValue === null || $this->_nextValue == $this->_maxValue) { if ($this->_maxValue === null || $this->_nextValue == $this->_maxValue) {
// Allocate new values // Allocate new values
$conn = $this->_em->getConnection(); $conn = $em->getConnection();
$sql = $conn->getDatabasePlatform()->getSequenceNextValSql($this->_sequenceName); $sql = $conn->getDatabasePlatform()->getSequenceNextValSql($this->_sequenceName);
$this->_maxValue = $conn->fetchOne($sql); $this->_maxValue = $conn->fetchOne($sql);
$this->_nextValue = $this->_maxValue - $this->_allocationSize; $this->_nextValue = $this->_maxValue - $this->_allocationSize;
@ -37,13 +68,38 @@ class SequenceGenerator extends AbstractIdGenerator
return $this->_nextValue++; return $this->_nextValue++;
} }
/**
* Gets the maximum value of the currently allocated bag of values.
*
* @return integer|float
*/
public function getCurrentMaxValue() public function getCurrentMaxValue()
{ {
return $this->_maxValue; return $this->_maxValue;
} }
/**
* Gets the next value that will be returned by generate().
*
* @return integer|float
*/
public function getNextValue() public function getNextValue()
{ {
return $this->_nextValue; return $this->_nextValue;
} }
public function serialize()
{
return serialize(array(
'allocationSize' => $this->_allocationSize,
'sequenceName' => $this->_sequenceName
));
}
public function unserialize($serialized)
{
$array = unserialize($serialized);
$this->_sequenceName = $array['sequenceName'];
$this->_allocationSize = $array['allocationSize'];
}
} }

View File

@ -2,6 +2,8 @@
namespace Doctrine\ORM\Id; namespace Doctrine\ORM\Id;
use Doctrine\ORM\EntityManager;
class SequenceIdentityGenerator extends IdentityGenerator class SequenceIdentityGenerator extends IdentityGenerator
{ {
private $_sequenceName; private $_sequenceName;
@ -10,15 +12,18 @@ class SequenceIdentityGenerator extends IdentityGenerator
{ {
$this->_sequenceName = $sequenceName; $this->_sequenceName = $sequenceName;
} }
public function generate(EntityManager $em, $entity)
{
return $em->getConnection()->lastInsertId($this->_sequenceName);
}
/** /**
* Enter description here... * @return boolean
*
* @param Doctrine_Connection $conn
* @override * @override
*/ */
public function getPostInsertId() public function isPostInsertGenerator()
{ {
return $this->_em->getConnection()->lastInsertId($this->_sequenceName); return true;
} }
} }

View File

@ -2,6 +2,8 @@
namespace Doctrine\ORM\Id; namespace Doctrine\ORM\Id;
use Doctrine\ORM\EntityManager;
/** /**
* Id generator that uses a single-row database table and a hi/lo algorithm. * Id generator that uses a single-row database table and a hi/lo algorithm.
* *
@ -9,7 +11,7 @@ namespace Doctrine\ORM\Id;
*/ */
class TableGenerator extends AbstractIdGenerator class TableGenerator extends AbstractIdGenerator
{ {
public function generate($entity) public function generate(EntityManager $em, $entity)
{ {
throw \Doctrine\Common\DoctrineException::updateMe("Not implemented"); throw \Doctrine\Common\DoctrineException::updateMe("Not implemented");
} }

View File

@ -333,6 +333,36 @@ final class ClassMetadata
private $_reflectionProperties; private $_reflectionProperties;
//private $_insertSql; //private $_insertSql;
/**
* The name of the ID generator used for this class. Only used for SEQUENCE
* and TABLE generation strategies.
*
* @var string
*/
//private $_idGeneratorName;
/**
* The ID generator used for generating IDs for this class.
*
* @var AbstractIdGenerator
*/
private $_idGenerator;
/**
* The definition of the sequence generator of this class. Only used for the
* SEQUENCE generation strategy.
*
* @var array
*/
private $_sequenceGeneratorDefinition;
/**
* The definition of the table generator of this class. Only used for the
* TABLE generation strategy.
*
* @var array
*/
//private $_tableGeneratorDefinition;
/** /**
* Initializes a new ClassMetadata instance that will hold the object-relational mapping * Initializes a new ClassMetadata instance that will hold the object-relational mapping
@ -389,7 +419,7 @@ final class ClassMetadata
public function getSingleIdReflectionProperty() public function getSingleIdReflectionProperty()
{ {
if ($this->_isIdentifierComposite) { if ($this->_isIdentifierComposite) {
\Doctrine\Common\DoctrineException::updateMe("getSingleIdReflectionProperty called on entity with composite key."); throw DoctrineException::updateMe("getSingleIdReflectionProperty called on entity with composite key.");
} }
return $this->_reflectionProperties[$this->_identifier[0]]; return $this->_reflectionProperties[$this->_identifier[0]];
} }
@ -635,17 +665,6 @@ final class ClassMetadata
if ( ! in_array($mapping['fieldName'], $this->_identifier)) { if ( ! in_array($mapping['fieldName'], $this->_identifier)) {
$this->_identifier[] = $mapping['fieldName']; $this->_identifier[] = $mapping['fieldName'];
} }
if (isset($mapping['idGenerator'])) {
if ( ! $this->_isIdGeneratorType($mapping['idGenerator'])) {
//TODO: check if the idGenerator specifies an existing generator by name
throw MappingException::invalidGeneratorType($mapping['idGenerator']);
} else if (count($this->_identifier) > 1) {
throw MappingException::generatorNotAllowedWithCompositeId();
}
$this->_generatorType = $mapping['idGenerator'];
}
// TODO: validate/complete 'tableGenerator' and 'sequenceGenerator' mappings
// Check for composite key // Check for composite key
if ( ! $this->_isIdentifierComposite && count($this->_identifier) > 1) { if ( ! $this->_isIdentifierComposite && count($this->_identifier) > 1) {
$this->_isIdentifierComposite = true; $this->_isIdentifierComposite = true;
@ -719,12 +738,23 @@ final class ClassMetadata
public function getSingleIdentifierFieldName() public function getSingleIdentifierFieldName()
{ {
if ($this->_isIdentifierComposite) { if ($this->_isIdentifierComposite) {
throw \Doctrine\Common\DoctrineException::updateMe("Calling getSingleIdentifierFieldName " throw DoctrineException::updateMe("Calling getSingleIdentifierFieldName "
. "on a class that uses a composite identifier is not allowed."); . "on a class that uses a composite identifier is not allowed.");
} }
return $this->_identifier[0]; return $this->_identifier[0];
} }
/**
* Gets the column name of the single id column. Note that this only works on
* entity classes that have a single-field pk.
*
* @return string
*/
public function getSingleIdentifierColumnName()
{
return $this->getColumnName($this->getSingleIdentifierFieldName());
}
public function setIdentifier(array $identifier) public function setIdentifier(array $identifier)
{ {
$this->_identifier = $identifier; $this->_identifier = $identifier;
@ -1067,7 +1097,7 @@ final class ClassMetadata
} }
/** /**
* Sets the primary table definition. The provided array must have th * Sets the primary table definition. The provided array must have the
* following structure: * following structure:
* *
* name => <tableName> * name => <tableName>
@ -1471,7 +1501,82 @@ final class ClassMetadata
! $this->_associationMappings[$fieldName]->isOneToOne(); ! $this->_associationMappings[$fieldName]->isOneToOne();
} }
/** Creates a string representation of the instance. */ /**
* Gets the name of the ID generator used for this class.
* Only classes that use a SEQUENCE or TABLE ID generation strategy have a generator name.
*
* @return string|null The name of the ID generator or NULL if this class does not
* use a named ID generator.
*/
/*public function getIdGeneratorName()
{
return $this->_idGeneratorName;
}*/
/**
* Sets the ID generator used to generate IDs for instances of this class.
*
* @param AbstractIdGenerator $generator
*/
public function setIdGenerator($generator)
{
$this->_idGenerator = $generator;
}
/**
* Gets the ID generator used to generate IDs for instances of this class.
*
* @return AbstractIdGenerator
*/
public function getIdGenerator()
{
return $this->_idGenerator;
}
/**
* Gets the definition of the sequence ID generator for this class.
*
* The definition has the following structure:
* <code>
* array(
* 'sequenceName' => 'name',
* 'allocationSize' => 20,
* 'initialValue' => 1
* )
* </code>
*
* @return array|null An array with the generator definition or NULL if this class
* has no sequence generator definition.
*/
public function getSequenceGeneratorDefinition()
{
return $this->_sequenceGeneratorDefinition;
}
/**
* Sets the definition of the sequence ID generator for this class.
*
* The definition must have the following structure:
* <code>
* array(
* 'sequenceName' => 'name',
* 'allocationSize' => 20,
* 'initialValue' => 1
* )
* </code>
*
* @param array $definition
*/
public function setSequenceGeneratorDefinition(array $definition)
{
$this->_sequenceGeneratorDefinition = $definition;
}
/**
* Creates a string representation of this instance.
*
* @return string The string representation of this instance.
*/
public function __toString() public function __toString()
{ {
return __CLASS__ . '@' . spl_object_hash($this); return __CLASS__ . '@' . spl_object_hash($this);

View File

@ -21,6 +21,7 @@
namespace Doctrine\ORM\Mapping; namespace Doctrine\ORM\Mapping;
use Doctrine\Common\DoctrineException;
use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\AbstractPlatform;
/** /**
@ -134,6 +135,11 @@ class ClassMetadataFactory
// Invoke driver // Invoke driver
$this->_driver->loadMetadataForClass($className, $class); $this->_driver->loadMetadataForClass($className, $class);
// Verify & complete identifier mapping
if ( ! $class->getIdentifier()) {
throw MappingException::identifierRequired($className);
}
$this->_completeIdGeneratorMapping($class); $this->_completeIdGeneratorMapping($class);
if ($parent && $parent->isInheritanceTypeSingleTable()) { if ($parent && $parent->isInheritanceTypeSingleTable()) {
@ -195,7 +201,8 @@ class ClassMetadataFactory
*/ */
private function _completeIdGeneratorMapping(ClassMetadata $class) private function _completeIdGeneratorMapping(ClassMetadata $class)
{ {
if ($class->getIdGeneratorType() == ClassMetadata::GENERATOR_TYPE_AUTO) { $idGenType = $class->getIdGeneratorType();
if ($idGenType == ClassMetadata::GENERATOR_TYPE_AUTO) {
if ($this->_targetPlatform->prefersSequences()) { if ($this->_targetPlatform->prefersSequences()) {
$class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_SEQUENCE); $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_SEQUENCE);
} else if ($this->_targetPlatform->prefersIdentityColumns()) { } else if ($this->_targetPlatform->prefersIdentityColumns()) {
@ -204,5 +211,35 @@ class ClassMetadataFactory
$class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_TABLE); $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_TABLE);
} }
} }
// Create & assign an appropriate ID generator instance
switch ($class->getIdGeneratorType()) {
case ClassMetadata::GENERATOR_TYPE_IDENTITY:
$class->setIdGenerator(new \Doctrine\ORM\Id\IdentityGenerator());
break;
case ClassMetadata::GENERATOR_TYPE_SEQUENCE:
// If there is no sequence definition yet, create a default definition
$definition = $class->getSequenceGeneratorDefinition();
if ( ! $definition) {
$definition['sequenceName'] = $class->getTableName() . '_' . $class->getSingleIdentifierColumnName() . '_seq';
$definition['allocationSize'] = 20;
$definition['initialValue'] = 1;
$class->setSequenceGeneratorDefinition($definition);
}
$sequenceGenerator = new \Doctrine\ORM\Id\SequenceGenerator(
$definition['sequenceName'],
$definition['allocationSize']
);
$class->setIdGenerator($sequenceGenerator);
break;
case ClassMetadata::GENERATOR_TYPE_NONE:
$class->setIdGenerator(new \Doctrine\ORM\Id\Assigned());
break;
case ClassMetadata::GENERATOR_TYPE_TABLE:
throw new DoctrineException("DoctrineTableGenerator not yet implemented.");
break;
default:
throw new DoctrineException("Unexhaustive match.");
}
} }
} }

View File

@ -21,6 +21,7 @@
namespace Doctrine\ORM\Mapping\Driver; namespace Doctrine\ORM\Mapping\Driver;
use Doctrine\Common\DoctrineException;
use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\MappingException; use Doctrine\ORM\Mapping\MappingException;
@ -48,7 +49,7 @@ class AnnotationDriver
// Evaluate DoctrineEntity annotation // Evaluate DoctrineEntity annotation
if (($entityAnnot = $annotClass->getAnnotation('DoctrineEntity')) === false) { if (($entityAnnot = $annotClass->getAnnotation('DoctrineEntity')) === false) {
throw \Doctrine\Common\DoctrineException::updateMe("$className is no entity."); throw DoctrineException::updateMe("$className is no entity.");
} }
$metadata->setCustomRepositoryClass($entityAnnot->repositoryClass); $metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
@ -109,7 +110,7 @@ class AnnotationDriver
// DoctrineOneToOne, DoctrineOneToMany, DoctrineManyToOne, DoctrineManyToMany // DoctrineOneToOne, DoctrineOneToMany, DoctrineManyToOne, DoctrineManyToMany
if ($columnAnnot = $property->getAnnotation('DoctrineColumn')) { if ($columnAnnot = $property->getAnnotation('DoctrineColumn')) {
if ($columnAnnot->type == null) { if ($columnAnnot->type == null) {
throw \Doctrine\Common\DoctrineException::updateMe("Missing type on property " . $property->getName()); throw DoctrineException::updateMe("Missing type on property " . $property->getName());
} }
$mapping['type'] = $columnAnnot->type; $mapping['type'] = $columnAnnot->type;
$mapping['length'] = $columnAnnot->length; $mapping['length'] = $columnAnnot->length;
@ -117,10 +118,22 @@ class AnnotationDriver
if ($idAnnot = $property->getAnnotation('DoctrineId')) { if ($idAnnot = $property->getAnnotation('DoctrineId')) {
$mapping['id'] = true; $mapping['id'] = true;
} }
if ($idGeneratorAnnot = $property->getAnnotation('DoctrineIdGenerator')) { if ($generatedValueAnnot = $property->getAnnotation('DoctrineGeneratedValue')) {
$mapping['idGenerator'] = $idGeneratorAnnot->value; $metadata->setIdGeneratorType($generatedValueAnnot->strategy);
} }
$metadata->mapField($mapping); $metadata->mapField($mapping);
// Check for SequenceGenerator/TableGenerator definition
if ($seqGeneratorAnnot = $property->getAnnotation('DoctrineSequenceGenerator')) {
$metadata->setSequenceGeneratorDefinition(array(
'sequenceName' => $seqGeneratorAnnot->sequenceName,
'allocationSize' => $seqGeneratorAnnot->allocationSize,
'initialValue' => $seqGeneratorAnnot->initialValue
));
} else if ($tblGeneratorAnnot = $property->getAnnotation('DoctrineTableGenerator')) {
throw new DoctrineException("DoctrineTableGenerator not yet implemented.");
}
} else if ($oneToOneAnnot = $property->getAnnotation('DoctrineOneToOne')) { } else if ($oneToOneAnnot = $property->getAnnotation('DoctrineOneToOne')) {
$mapping['targetEntity'] = $oneToOneAnnot->targetEntity; $mapping['targetEntity'] = $oneToOneAnnot->targetEntity;
$mapping['joinColumns'] = $joinColumns; $mapping['joinColumns'] = $joinColumns;

View File

@ -33,7 +33,10 @@ final class DoctrineDiscriminatorColumn extends \Addendum\Annotation {
final class DoctrineDiscriminatorMap extends \Addendum\Annotation {} final class DoctrineDiscriminatorMap extends \Addendum\Annotation {}
final class DoctrineSubClasses extends \Addendum\Annotation {} final class DoctrineSubClasses extends \Addendum\Annotation {}
final class DoctrineId extends \Addendum\Annotation {} final class DoctrineId extends \Addendum\Annotation {}
final class DoctrineIdGenerator extends \Addendum\Annotation {} final class DoctrineGeneratedValue extends \Addendum\Annotation {
public $strategy;
//public $generator;
}
final class DoctrineVersion extends \Addendum\Annotation {} final class DoctrineVersion extends \Addendum\Annotation {}
final class DoctrineJoinColumn extends \Addendum\Annotation { final class DoctrineJoinColumn extends \Addendum\Annotation {
public $name; public $name;
@ -85,7 +88,10 @@ final class DoctrineJoinTable extends \Addendum\Annotation {
public $inverseJoinColumns; public $inverseJoinColumns;
} }
final class DoctrineSequenceGenerator extends \Addendum\Annotation { final class DoctrineSequenceGenerator extends \Addendum\Annotation {
public $name; //public $name;
public $sequenceName;
public $allocationSize = 20; public $allocationSize = 20;
public $initialValue; public $initialValue = 1;
/** The name of the class that defines the generator. */
//public $definingClass;
} }

View File

@ -94,9 +94,9 @@ abstract class AbstractEntityPersister
$insertData = array(); $insertData = array();
$this->_prepareData($entity, $insertData, true); $this->_prepareData($entity, $insertData, true);
$this->_conn->insert($this->_classMetadata->getTableName(), $insertData); $this->_conn->insert($this->_classMetadata->getTableName(), $insertData);
$idGen = $this->_em->getIdGenerator($this->_classMetadata->getClassName()); $idGen = $this->_classMetadata->getIdGenerator();
if ($idGen->isPostInsertGenerator()) { if ($idGen->isPostInsertGenerator()) {
return $idGen->generate($entity); return $idGen->generate($this->_em, $entity);
} }
return null; return null;
} }

View File

@ -21,6 +21,7 @@
namespace Doctrine\ORM; namespace Doctrine\ORM;
use Doctrine\ORM\Query\CacheHandler;
use Doctrine\ORM\Query\Parser; use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\QueryException; use Doctrine\ORM\Query\QueryException;
@ -129,7 +130,7 @@ class Query extends AbstractQuery
} }
/** /**
* Retrieves the assocated EntityManager to this Query instance. * Retrieves the associated EntityManager of this Query instance.
* *
* @return Doctrine\ORM\EntityManager * @return Doctrine\ORM\EntityManager
*/ */
@ -243,13 +244,13 @@ class Query extends AbstractQuery
if ($cached === false) { if ($cached === false) {
// Cache does not exist, we have to create it. // Cache does not exist, we have to create it.
$result = $this->_execute($params, self::HYDRATE_ARRAY); $result = $this->_execute($params, self::HYDRATE_ARRAY);
$queryResult = \Doctrine\ORM\Query\CacheHandler::fromResultSet($this, $result); $queryResult = CacheHandler::fromResultSet($this, $result);
$cacheDriver->save($hash, $queryResult->toCachedForm(), $this->_resultCacheTTL); $cacheDriver->save($hash, $queryResult->toCachedForm(), $this->_resultCacheTTL);
return $result; return $result;
} else { } else {
// Cache exists, recover it and return the results. // Cache exists, recover it and return the results.
$queryResult = \Doctrine\ORM\Query\CacheHandler::fromCachedResult($this, $cached); $queryResult = CacheHandler::fromCachedResult($this, $cached);
return $queryResult->getResultSet(); return $queryResult->getResultSet();
} }
@ -288,7 +289,7 @@ class Query extends AbstractQuery
$cacheDriver->save($hash, $this->_parserResult->toCachedForm(), $this->_queryCacheTTL); $cacheDriver->save($hash, $this->_parserResult->toCachedForm(), $this->_queryCacheTTL);
} else { } else {
// Cache exists, recover it and return the results. // Cache exists, recover it and return the results.
$this->_parserResult = Doctrine\ORM\Query\CacheHandler::fromCachedQuery($this, $cached); $this->_parserResult = CacheHandler::fromCachedQuery($this, $cached);
$executor = $this->_parserResult->getSqlExecutor(); $executor = $this->_parserResult->getSqlExecutor();
} }
@ -327,7 +328,7 @@ class Query extends AbstractQuery
public function setResultCache($resultCache) public function setResultCache($resultCache)
{ {
if ($resultCache !== null && ! ($resultCache instanceof \Doctrine\ORM\Cache\Cache)) { if ($resultCache !== null && ! ($resultCache instanceof \Doctrine\ORM\Cache\Cache)) {
\Doctrine\Common\DoctrineException::updateMe( throw DoctrineException::updateMe(
'Method setResultCache() accepts only an instance of Doctrine_Cache_Interface or null.' 'Method setResultCache() accepts only an instance of Doctrine_Cache_Interface or null.'
); );
} }
@ -409,7 +410,7 @@ class Query extends AbstractQuery
public function setQueryCache($queryCache) public function setQueryCache($queryCache)
{ {
if ($queryCache !== null && ! ($queryCache instanceof \Doctrine\ORM\Cache\Cache)) { if ($queryCache !== null && ! ($queryCache instanceof \Doctrine\ORM\Cache\Cache)) {
\Doctrine\Common\DoctrineException::updateMe( throw DoctrineException::updateMe(
'Method setResultCache() accepts only an instance of Doctrine_ORM_Cache_Interface or null.' 'Method setResultCache() accepts only an instance of Doctrine_ORM_Cache_Interface or null.'
); );
} }
@ -510,7 +511,6 @@ class Query extends AbstractQuery
/** /**
* Gets the array of results for the query. * Gets the array of results for the query.
* Object graphs are represented as nested array structures.
* *
* Alias for execute(array(), HYDRATE_ARRAY). * Alias for execute(array(), HYDRATE_ARRAY).
* *
@ -575,9 +575,11 @@ class Query extends AbstractQuery
} }
/** /**
* Executes the query and returns an IterableResult that can be iterated over. * Executes the query and returns an IterableResult that can be used to incrementally
* Objects in the result are initialized on-demand. * iterated over the result.
* *
* @param array $params The query parameters.
* @param integer $hydrationMode The hydratio mode to use.
* @return IterableResult * @return IterableResult
*/ */
public function iterate(array $params = array(), $hydrationMode = self::HYDRATE_OBJECT) public function iterate(array $params = array(), $hydrationMode = self::HYDRATE_OBJECT)

View File

@ -32,6 +32,7 @@ use Doctrine\Common\DoctrineException;
* @version $Revision: 1393 $ * @version $Revision: 1393 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Roman Borschel <roman@code-factory.org>
*/ */
abstract class AbstractResult abstract class AbstractResult
{ {

View File

@ -11,10 +11,4 @@ namespace Doctrine\ORM\Query;
* *
* @author robo * @author robo
*/ */
class QueryException extends \Doctrine\Common\DoctrineException class QueryException extends \Doctrine\Common\DoctrineException {}
{
public static function nonUniqueResult()
{
return new self("The query contains more than one result.");
}
}

View File

@ -28,7 +28,6 @@ use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Mapping; use Doctrine\ORM\Mapping;
use Doctrine\ORM\Persisters; use Doctrine\ORM\Persisters;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Exceptions\UnitOfWorkException;
/** /**
* The UnitOfWork is responsible for tracking changes to objects during an * The UnitOfWork is responsible for tracking changes to objects during an
@ -440,9 +439,9 @@ class UnitOfWork
$oid = spl_object_hash($entry); $oid = spl_object_hash($entry);
if ($state == self::STATE_NEW) { if ($state == self::STATE_NEW) {
// Get identifier, if possible (not post-insert) // Get identifier, if possible (not post-insert)
$idGen = $this->_em->getIdGenerator($targetClass->getClassName()); $idGen = $targetClass->getIdGenerator();
if ( ! $idGen->isPostInsertGenerator()) { if ( ! $idGen->isPostInsertGenerator()) {
$idValue = $idGen->generate($entry); $idValue = $idGen->generate($this->_em, $entry);
$this->_entityStates[$oid] = self::STATE_MANAGED; $this->_entityStates[$oid] = self::STATE_MANAGED;
if ( ! $idGen instanceof \Doctrine\ORM\Id\Assigned) { if ( ! $idGen instanceof \Doctrine\ORM\Id\Assigned) {
$this->_entityIdentifiers[$oid] = array($idValue); $this->_entityIdentifiers[$oid] = array($idValue);
@ -828,7 +827,7 @@ class UnitOfWork
$classMetadata = $this->_em->getClassMetadata(get_class($entity)); $classMetadata = $this->_em->getClassMetadata(get_class($entity));
$idHash = $this->getIdentifierHash($this->_entityIdentifiers[$oid]); $idHash = $this->getIdentifierHash($this->_entityIdentifiers[$oid]);
if ($idHash === '') { if ($idHash === '') {
\Doctrine\Common\DoctrineException::updateMe("Entity with oid '" . spl_object_hash($entity) throw DoctrineException::updateMe("Entity with oid '" . spl_object_hash($entity)
. "' has no identity and therefore can't be removed from the identity map."); . "' has no identity and therefore can't be removed from the identity map.");
} }
$className = $classMetadata->getRootClassName(); $className = $classMetadata->getRootClassName();
@ -974,11 +973,11 @@ class UnitOfWork
} }
break; break;
case self::STATE_NEW: case self::STATE_NEW:
$idGen = $this->_em->getIdGenerator($class->getClassName()); $idGen = $class->getIdGenerator();
if ($idGen->isPostInsertGenerator()) { if ($idGen->isPostInsertGenerator()) {
$insertNow[$oid] = $entity; $insertNow[$oid] = $entity;
} else { } else {
$idValue = $idGen->generate($entity); $idValue = $idGen->generate($this->_em, $entity);
$this->_entityStates[$oid] = self::STATE_MANAGED; $this->_entityStates[$oid] = self::STATE_MANAGED;
if ( ! $idGen instanceof \Doctrine\ORM\Id\Assigned) { if ( ! $idGen instanceof \Doctrine\ORM\Id\Assigned) {
$this->_entityIdentifiers[$oid] = array($idValue); $this->_entityIdentifiers[$oid] = array($idValue);
@ -990,7 +989,7 @@ class UnitOfWork
$this->registerNew($entity); $this->registerNew($entity);
break; break;
case self::STATE_DETACHED: case self::STATE_DETACHED:
\Doctrine\Common\DoctrineException::updateMe("Behavior of save() for a detached entity " throw DoctrineException::updateMe("Behavior of save() for a detached entity "
. "is not yet defined."); . "is not yet defined.");
case self::STATE_DELETED: case self::STATE_DELETED:
// entity becomes managed again // entity becomes managed again
@ -1004,7 +1003,7 @@ class UnitOfWork
break; break;
default: default:
//TODO: throw UnitOfWorkException::invalidEntityState() //TODO: throw UnitOfWorkException::invalidEntityState()
\Doctrine\Common\DoctrineException::updateMe("Encountered invalid entity state."); throw DoctrineException::updateMe("Encountered invalid entity state.");
} }
$this->_cascadeSave($entity, $visited, $insertNow); $this->_cascadeSave($entity, $visited, $insertNow);
} }
@ -1046,9 +1045,9 @@ class UnitOfWork
$this->registerDeleted($entity); $this->registerDeleted($entity);
break; break;
case self::STATE_DETACHED: case self::STATE_DETACHED:
\Doctrine\Common\DoctrineException::updateMe("A detached entity can't be deleted."); throw DoctrineException::updateMe("A detached entity can't be deleted.");
default: default:
\Doctrine\Common\DoctrineException::updateMe("Encountered invalid entity state."); throw DoctrineException::updateMe("Encountered invalid entity state.");
} }
$this->_cascadeDelete($entity, $visited); $this->_cascadeDelete($entity, $visited);
} }
@ -1298,7 +1297,7 @@ class UnitOfWork
/** /**
* Gets the identifier of an entity. * Gets the identifier of an entity.
* The returned value is always an array of identifier values. If the entity * The returned value is always an array of identifier values. If the entity
* has a composite primary key then the identifier values are in the same * has a composite identifier then the identifier values are in the same
* order as the identifier field names as returned by ClassMetadata#getIdentifierFieldNames(). * order as the identifier field names as returned by ClassMetadata#getIdentifierFieldNames().
* *
* @param object $entity * @param object $entity
@ -1343,8 +1342,6 @@ class UnitOfWork
/** /**
* Gets the EntityPersister for an Entity. * Gets the EntityPersister for an Entity.
* *
* This is usually not of interest for users, mainly for internal use.
*
* @param string $entityName The name of the Entity. * @param string $entityName The name of the Entity.
* @return Doctrine\ORM\Persister\AbstractEntityPersister * @return Doctrine\ORM\Persister\AbstractEntityPersister
*/ */

View File

@ -5,7 +5,8 @@ namespace Doctrine\Tests\Mocks;
class DatabasePlatformMock extends \Doctrine\DBAL\Platforms\AbstractPlatform class DatabasePlatformMock extends \Doctrine\DBAL\Platforms\AbstractPlatform
{ {
private $_sequenceNextValSql = ""; private $_sequenceNextValSql = "";
private $_prefersIdentityColumns = false; private $_prefersIdentityColumns = true;
private $_prefersSequences = false;
/** /**
* @override * @override
@ -25,6 +26,14 @@ class DatabasePlatformMock extends \Doctrine\DBAL\Platforms\AbstractPlatform
return $this->_prefersIdentityColumns; return $this->_prefersIdentityColumns;
} }
/**
* @override
*/
public function prefersSequences()
{
return $this->_prefersSequences;
}
/** @override */ /** @override */
public function getSequenceNextValSql($sequenceName) public function getSequenceNextValSql($sequenceName)
{ {
@ -37,15 +46,9 @@ class DatabasePlatformMock extends \Doctrine\DBAL\Platforms\AbstractPlatform
/** @override */ /** @override */
public function getBigIntTypeDeclarationSql(array $field) {} public function getBigIntTypeDeclarationSql(array $field) {}
/** @override */
public function getTinyIntTypeDeclarationSql(array $field) {}
/** @override */ /** @override */
public function getSmallIntTypeDeclarationSql(array $field) {} public function getSmallIntTypeDeclarationSql(array $field) {}
/** @override */
public function getMediumIntTypeDeclarationSql(array $field) {}
/** @override */ /** @override */
protected function _getCommonIntegerTypeDeclarationSql(array $columnDef) {} protected function _getCommonIntegerTypeDeclarationSql(array $columnDef) {}
@ -56,7 +59,12 @@ class DatabasePlatformMock extends \Doctrine\DBAL\Platforms\AbstractPlatform
public function setPrefersIdentityColumns($bool) public function setPrefersIdentityColumns($bool)
{ {
$this->_prefersIdentityColumns = (bool)$bool; $this->_prefersIdentityColumns = $bool;
}
public function setPrefersSequences($bool)
{
$this->_prefersSequences = $bool;
} }
public function setSequenceNextValSql($sql) public function setSequenceNextValSql($sql)

View File

@ -70,14 +70,14 @@ class EntityManagerMock extends \Doctrine\ORM\EntityManager
return new EntityManagerMock($conn, $config, $eventManager); return new EntityManagerMock($conn, $config, $eventManager);
} }
/*
public function setIdGenerator($className, $generator) public function setIdGenerator($className, $generator)
{ {
$this->_idGenerators[$className] = $generator; $this->_idGenerators[$className] = $generator;
} }
*/
/** @override */ /** @override */
public function getIdGenerator($className) /* public function getIdGenerator($className)
{ {
if (isset($this->_idGenerators[$className])) { if (isset($this->_idGenerators[$className])) {
@ -86,4 +86,5 @@ class EntityManagerMock extends \Doctrine\ORM\EntityManager
return parent::getIdGenerator($className); return parent::getIdGenerator($className);
} }
*/
} }

View File

@ -2,6 +2,8 @@
namespace Doctrine\Tests\Mocks; namespace Doctrine\Tests\Mocks;
use Doctrine\ORM\EntityManager;
class SequenceMock extends \Doctrine\ORM\Id\SequenceGenerator class SequenceMock extends \Doctrine\ORM\Id\SequenceGenerator
{ {
private $_sequenceNumber = 0; private $_sequenceNumber = 0;
@ -9,10 +11,10 @@ class SequenceMock extends \Doctrine\ORM\Id\SequenceGenerator
/** /**
* Enter description here... * Enter description here...
* *
* @param Doctrine_Entity $entity * @param object $entity
* @override * @override
*/ */
public function generate($entity) public function generate(EntityManager $em, $entity)
{ {
return $this->_sequenceNumber++; return $this->_sequenceNumber++;
} }

View File

@ -14,7 +14,7 @@ class CmsAddress
/** /**
* @DoctrineColumn(type="integer") * @DoctrineColumn(type="integer")
* @DoctrineId * @DoctrineId
* @DoctrineIdGenerator("auto") * @DoctrineGeneratedValue(strategy="auto")
*/ */
public $id; public $id;

View File

@ -11,7 +11,7 @@ class CmsArticle
/** /**
* @DoctrineId * @DoctrineId
* @DoctrineColumn(type="integer") * @DoctrineColumn(type="integer")
* @DoctrineIdGenerator("auto") * @DoctrineGeneratedValue(strategy="auto")
*/ */
public $id; public $id;
/** /**

View File

@ -11,7 +11,7 @@ class CmsComment
/** /**
* @DoctrineColumn(type="integer") * @DoctrineColumn(type="integer")
* @DoctrineId * @DoctrineId
* @DoctrineIdGenerator("auto") * @DoctrineGeneratedValue(strategy="auto")
*/ */
public $id; public $id;
/** /**

View File

@ -18,7 +18,7 @@ class CmsGroup
/** /**
* @DoctrineId * @DoctrineId
* @DoctrineColumn(type="integer") * @DoctrineColumn(type="integer")
* @DoctrineIdGenerator("auto") * @DoctrineGeneratedValue(strategy="auto")
*/ */
public $id; public $id;
/** /**

View File

@ -11,7 +11,7 @@ class CmsUser
/** /**
* @DoctrineId * @DoctrineId
* @DoctrineColumn(type="integer") * @DoctrineColumn(type="integer")
* @DoctrineIdGenerator("auto") * @DoctrineGeneratedValue(strategy="auto")
*/ */
public $id; public $id;
/** /**

View File

@ -17,7 +17,7 @@ class CompanyEmployee
/** /**
* @DoctrineId * @DoctrineId
* @DoctrineColumn(type="integer") * @DoctrineColumn(type="integer")
* @DoctrineIdGenerator("auto") * @DoctrineGeneratedValue(strategy="auto")
*/ */
public $id; public $id;

View File

@ -11,7 +11,7 @@ class ForumAvatar
/** /**
* @DoctrineId * @DoctrineId
* @DoctrineColumn(type="integer") * @DoctrineColumn(type="integer")
* @DoctrineIdGenerator("auto") * @DoctrineGeneratedValue(strategy="auto")
*/ */
public $id; public $id;
} }

View File

@ -11,7 +11,7 @@ class ForumEntry
/** /**
* @DoctrineId * @DoctrineId
* @DoctrineColumn(type="integer") * @DoctrineColumn(type="integer")
* @DoctrineIdGenerator("auto") * @DoctrineGeneratedValue(strategy="auto")
*/ */
public $id; public $id;
/** /**

View File

@ -17,7 +17,7 @@ class ForumUser
/** /**
* @DoctrineColumn(type="integer") * @DoctrineColumn(type="integer")
* @DoctrineId * @DoctrineId
* @DoctrineIdGenerator("auto") * @DoctrineGeneratedValue(strategy="auto")
*/ */
public $id; public $id;
/** /**

View File

@ -36,7 +36,7 @@ class AllTests
$suite->addTest(Query\AllTests::suite()); $suite->addTest(Query\AllTests::suite());
$suite->addTest(Hydration\AllTests::suite()); $suite->addTest(Hydration\AllTests::suite());
$suite->addTest(Entity\AllTests::suite()); $suite->addTest(Entity\AllTests::suite());
$suite->addTest(Export\AllTests::suite()); $suite->addTest(Tools\AllTests::suite());
$suite->addTest(Associations\AllTests::suite()); $suite->addTest(Associations\AllTests::suite());
$suite->addTest(Mapping\AllTests::suite()); $suite->addTest(Mapping\AllTests::suite());
$suite->addTest(Functional\AllTests::suite()); $suite->addTest(Functional\AllTests::suite());

View File

@ -26,8 +26,8 @@ class EntityPersisterTest extends \Doctrine\Tests\OrmTestCase
$this->_emMock = EntityManagerMock::create($this->_connMock); $this->_emMock = EntityManagerMock::create($this->_connMock);
$this->_uowMock = new UnitOfWorkMock($this->_emMock); $this->_uowMock = new UnitOfWorkMock($this->_emMock);
$this->_emMock->setUnitOfWork($this->_uowMock); $this->_emMock->setUnitOfWork($this->_uowMock);
$this->_idGenMock = new SequenceMock($this->_emMock, 'seq'); $this->_idGenMock = new SequenceMock($this->_emMock, 'seq', 20);
$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumUser', $this->_idGenMock); //$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumUser', $this->_idGenMock);
} }
public function testSimpleInsert() public function testSimpleInsert()

View File

@ -1,29 +0,0 @@
<?php
namespace Doctrine\Tests\ORM\Export;
use Doctrine\ORM\Export\ClassExporter;
require_once __DIR__ . '/../../TestInit.php';
class ClassExporterTest extends \Doctrine\Tests\OrmTestCase
{
public function testGetExportClassesSql()
{
$driver = new \Doctrine\Tests\Mocks\DriverMock;
$conn = new \Doctrine\Tests\Mocks\ConnectionMock(array(), $driver);
$conn->setDatabasePlatform(new \Doctrine\DBAL\Platforms\MySqlPlatform());
$em = $this->_getTestEntityManager($conn);
$classes = array(
$em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress'),
$em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'),
$em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsPhonenumber'),
);
$exporter = new ClassExporter($em);
$sql = $exporter->getExportClassesSql($classes);
$this->assertEquals(count($sql), 8);
}
}

View File

@ -19,7 +19,7 @@ class AllTests
{ {
$suite = new \Doctrine\Tests\OrmFunctionalTestSuite('Doctrine Orm Functional'); $suite = new \Doctrine\Tests\OrmFunctionalTestSuite('Doctrine Orm Functional');
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\BasicCRUDTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\BasicFunctionalTest');
return $suite; return $suite;
} }

View File

@ -2,7 +2,7 @@
namespace Doctrine\Tests\ORM\Functional; namespace Doctrine\Tests\ORM\Functional;
use Doctrine\ORM\Export\ClassExporter; use Doctrine\ORM\Tools\SchemaTool;
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;
@ -10,27 +10,16 @@ use Doctrine\Tests\Models\CMS\CmsGroup;
require_once __DIR__ . '/../../TestInit.php'; require_once __DIR__ . '/../../TestInit.php';
class BasicCRUDTest extends \Doctrine\Tests\OrmFunctionalTestCase class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
{ {
protected function tearDown() protected function setUp()
{ {
$conn = $this->_em->getConnection(); $this->useModelSet('cms');
$conn->exec('DELETE FROM cms_users_groups'); parent::setUp();
$conn->exec('DELETE FROM cms_groups');
$conn->exec('DELETE FROM cms_addresses');
$conn->exec('DELETE FROM cms_phonenumbers');
$conn->exec('DELETE FROM cms_users');
} }
public function testBasicUnitsOfWorkWithOneToManyAssociation() public function testBasicUnitsOfWorkWithOneToManyAssociation()
{ {
$this->_exporter->exportClasses(array(
$this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'),
$this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsPhonenumber'),
$this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress'),
$this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsGroup')
));
// Create // Create
$user = new CmsUser; $user = new CmsUser;
$user->name = 'Roman'; $user->name = 'Roman';
@ -175,7 +164,7 @@ class BasicCRUDTest extends \Doctrine\Tests\OrmFunctionalTestCase
$group->users[] = $user; $group->users[] = $user;
} }
$this->_em->save($user); // Saves the user, cause of post-insert ID $this->_em->save($user); // Saves the user, 'cause of post-insert ID
$this->_em->flush(); $this->_em->flush();
@ -215,6 +204,22 @@ class BasicCRUDTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals('developer', $users[0]->status); $this->assertEquals('developer', $users[0]->status);
$this->assertNull($users[0]->phonenumbers); $this->assertNull($users[0]->phonenumbers);
$this->assertNull($users[0]->articles); $this->assertNull($users[0]->articles);
$usersArray = $query->getResultArray();
$this->assertTrue(is_array($usersArray));
$this->assertEquals(1, count($usersArray));
$this->assertEquals('Guilherme', $usersArray[0]['name']);
$this->assertEquals('gblanco', $usersArray[0]['username']);
$this->assertEquals('developer', $usersArray[0]['status']);
$usersScalar = $query->getScalarResult();
$this->assertTrue(is_array($usersScalar));
$this->assertEquals(1, count($usersScalar));
$this->assertEquals('Guilherme', $usersScalar[0]['u_name']);
$this->assertEquals('gblanco', $usersScalar[0]['u_username']);
$this->assertEquals('developer', $usersScalar[0]['u_status']);
} }
public function testBasicInnerJoin() public function testBasicInnerJoin()

View File

@ -1,11 +1,9 @@
<?php <?php
namespace Doctrine\Tests\ORM\Export; namespace Doctrine\Tests\ORM\Id;
if (!defined('PHPUnit_MAIN_METHOD')) { if (!defined('PHPUnit_MAIN_METHOD')) {
define('PHPUnit_MAIN_METHOD', 'Orm_Export_AllTests::main'); define('PHPUnit_MAIN_METHOD', 'Orm_Id_AllTests::main');
} }
require_once __DIR__ . '/../../TestInit.php'; require_once __DIR__ . '/../../TestInit.php';
@ -19,14 +17,14 @@ class AllTests
public static function suite() public static function suite()
{ {
$suite = new \Doctrine\Tests\DoctrineTestSuite('Doctrine Orm Export'); $suite = new \Doctrine\Tests\DoctrineTestSuite('Doctrine Orm Id');
$suite->addTestSuite('Doctrine\Tests\ORM\Export\ClassExporterTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Id\SequenceGeneratorTest');
return $suite; return $suite;
} }
} }
if (PHPUnit_MAIN_METHOD == 'Orm_Export_AllTests::main') { if (PHPUnit_MAIN_METHOD == 'Orm_Id_AllTests::main') {
AllTests::main(); AllTests::main();
} }

View File

@ -0,0 +1,40 @@
<?php
namespace Doctrine\Tests\ORM\Id;
use Doctrine\ORM\Id\SequenceGenerator;
require_once __DIR__ . '/../../TestInit.php';
/**
* Description of SequenceGeneratorTest
*
* @author robo
*/
class SequenceGeneratorTest extends \Doctrine\Tests\OrmTestCase
{
private $_em;
private $_seqGen;
protected function setUp()
{
$this->_em = $this->_getTestEntityManager();
$this->_seqGen = new SequenceGenerator('seq', 10);
}
public function testGeneration()
{
for ($i=0; $i < 42; ++$i) {
if ($i % 10 == 0) {
$this->_em->getConnection()->setFetchOneResult((int)($i / 10) * 10 + 10);
}
$id = $this->_seqGen->generate($this->_em, null);
$this->assertEquals($i, $id);
$this->assertEquals((int)($i / 10) * 10 + 10, $this->_seqGen->getCurrentMaxValue());
$this->assertEquals($i + 1, $this->_seqGen->getNextValue());
}
}
}

View File

@ -15,11 +15,15 @@ class ClassMetadataFactoryTest extends \Doctrine\Tests\OrmTestCase
{ {
$mockPlatform = new DatabasePlatformMock(); $mockPlatform = new DatabasePlatformMock();
$mockDriver = new MetadataDriverMock(); $mockDriver = new MetadataDriverMock();
$mockPlatform->setPrefersSequences(true);
$mockPlatform->setPrefersIdentityColumns(false);
// Self-made metadata // Self-made metadata
$cm1 = new ClassMetadata('Doctrine\Tests\ORM\Mapping\TestEntity1'); $cm1 = new ClassMetadata('Doctrine\Tests\ORM\Mapping\TestEntity1');
// Add a mapped field // Add a mapped field
$cm1->mapField(array('fieldName' => 'name', 'type' => 'varchar')); $cm1->mapField(array('fieldName' => 'name', 'type' => 'varchar'));
// Add a mapped field
$cm1->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true));
// and a mapped association // and a mapped association
$cm1->mapOneToOne(array('fieldName' => 'other', 'targetEntity' => 'Other', 'mappedBy' => 'this')); $cm1->mapOneToOne(array('fieldName' => 'other', 'targetEntity' => 'Other', 'mappedBy' => 'this'));
// and an id generator type // and an id generator type
@ -41,8 +45,7 @@ class ClassMetadataFactoryTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals(array(), $cm1->getParentClasses()); $this->assertEquals(array(), $cm1->getParentClasses());
$this->assertTrue($cm1->hasField('name')); $this->assertTrue($cm1->hasField('name'));
// The default fallback for id generation is the table strategy $this->assertEquals('sequence', $cm1->getIdGeneratorType());
$this->assertEquals('table', $cm1->getIdGeneratorType());
} }
public function testGetMetadataForClassInHierarchy() public function testGetMetadataForClassInHierarchy()
@ -56,6 +59,8 @@ class ClassMetadataFactoryTest extends \Doctrine\Tests\OrmTestCase
$cm1->setInheritanceType('singleTable'); $cm1->setInheritanceType('singleTable');
// Add a mapped field // Add a mapped field
$cm1->mapField(array('fieldName' => 'name', 'type' => 'varchar')); $cm1->mapField(array('fieldName' => 'name', 'type' => 'varchar'));
// Add a mapped field
$cm1->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true));
// and a mapped association // and a mapped association
$cm1->mapOneToOne(array('fieldName' => 'other', 'targetEntity' => 'Other', 'mappedBy' => 'this')); $cm1->mapOneToOne(array('fieldName' => 'other', 'targetEntity' => 'Other', 'mappedBy' => 'this'));
// and an id generator type // and an id generator type
@ -144,6 +149,7 @@ class ClassMetadataFactoryTestSubject extends \Doctrine\ORM\Mapping\ClassMetadat
class TestEntity1 class TestEntity1
{ {
protected $id;
protected $name; protected $name;
protected $other; protected $other;
} }

View File

@ -0,0 +1,30 @@
<?php
namespace Doctrine\Tests\ORM\Tools;
if (!defined('PHPUnit_MAIN_METHOD')) {
define('PHPUnit_MAIN_METHOD', 'Orm_Tools_AllTests::main');
}
require_once __DIR__ . '/../../TestInit.php';
class AllTests
{
public static function main()
{
\PHPUnit_TextUI_TestRunner::run(self::suite());
}
public static function suite()
{
$suite = new \Doctrine\Tests\DoctrineTestSuite('Doctrine Orm Tools');
$suite->addTestSuite('Doctrine\Tests\ORM\Tools\SchemaToolTest');
return $suite;
}
}
if (PHPUnit_MAIN_METHOD == 'Orm_Tools_AllTests::main') {
AllTests::main();
}

View File

@ -54,8 +54,8 @@ class UnitOfWorkTest extends \Doctrine\Tests\OrmTestCase
// Setup fake persister and id generator for identity generation // Setup fake persister and id generator for identity generation
$userPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumUser")); $userPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumUser"));
$this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumUser', $userPersister); $this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumUser', $userPersister);
$idGeneratorMock = new IdentityIdGeneratorMock($this->_emMock); //$idGeneratorMock = new IdentityIdGeneratorMock($this->_emMock);
$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumUser', $idGeneratorMock); //$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumUser', $idGeneratorMock);
$userPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY); $userPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY);
// Test // Test
@ -95,14 +95,14 @@ class UnitOfWorkTest extends \Doctrine\Tests\OrmTestCase
//ForumUser //ForumUser
$userPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumUser")); $userPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumUser"));
$this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumUser', $userPersister); $this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumUser', $userPersister);
$userIdGeneratorMock = new IdentityIdGeneratorMock($this->_emMock); //$userIdGeneratorMock = new IdentityIdGeneratorMock($this->_emMock);
$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumUser', $userIdGeneratorMock); //$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumUser', $userIdGeneratorMock);
$userPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY); $userPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY);
// ForumAvatar // ForumAvatar
$avatarPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumAvatar")); $avatarPersister = new EntityPersisterMock($this->_emMock, $this->_emMock->getClassMetadata("Doctrine\Tests\Models\Forum\ForumAvatar"));
$this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumAvatar', $avatarPersister); $this->_unitOfWork->setEntityPersister('Doctrine\Tests\Models\Forum\ForumAvatar', $avatarPersister);
$avatarIdGeneratorMock = new IdentityIdGeneratorMock($this->_emMock); //$avatarIdGeneratorMock = new IdentityIdGeneratorMock($this->_emMock);
$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumAvatar', $avatarIdGeneratorMock); //$this->_emMock->setIdGenerator('Doctrine\Tests\Models\Forum\ForumAvatar', $avatarIdGeneratorMock);
$avatarPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY); $avatarPersister->setMockIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_IDENTITY);
// Test // Test

View File

@ -3,7 +3,7 @@
namespace Doctrine\Tests; namespace Doctrine\Tests;
/** /**
* Base testcase class for all orm testcases. * Base testcase class for all functional ORM testcases.
* *
* @since 2.0 * @since 2.0
*/ */
@ -15,119 +15,88 @@ class OrmFunctionalTestCase extends OrmTestCase
/** The EntityManager for this testcase. */ /** The EntityManager for this testcase. */
protected $_em; protected $_em;
/** The ClassExporter for this testcase. */ /** The SchemaTool. */
protected $_exporter; protected $_schemaTool;
/** /** The names of the model sets used in this testcase. */
* The currently loaded model names of the fixtures for the testcase. private $_usedModelSets = array();
*/
private $_loadedFixtures = array(); /** Whether the database schema has already been created. */
private static $_tablesCreated = array();
/**
* All loaded fixtures during test execution. Common fixture cache. /** List of model sets and their classes. */
*/ private static $_modelSets = array(
private static $_fixtures = array(); 'cms' => array(
'Doctrine\Tests\Models\CMS\CmsUser',
/** 'Doctrine\Tests\Models\CMS\CmsPhonenumber',
* The names of all tables that were already exported. Each table is exported 'Doctrine\Tests\Models\CMS\CmsAddress',
* only once. Then it's just filled & erased for each testmethod in a testcase 'Doctrine\Tests\Models\CMS\CmsGroup'
* that uses one or more fixtures. ),
*/ 'forum' => array(),
private static $_exportedTables = array(); 'company' => array(),
'ecommerce' => array()
/** );
* Loads a data fixture into the database. This method must only be called
* from within the setUp() method of testcases. The database will then be protected function useModelSet($setName)
* populated with fresh data of all loaded fixtures for each test method.
*
* WARNING: A single testcase should never load fixtures from different scenarios of
* the same package as the concistency and uniqueness of keys is not guaranteed.
*
* @param string $package The package name. Must be one of Doctrine's test model packages
* (forum, cms or ecommerce).
* @param string $scenario The fixture scenario. A model package can have many fixture
* scenarios. Within a scenario all primary keys and foreign keys
* of fixtures are consistent and unique.
* @param string $name The name of the fixture to load from the specified package.
*/
protected function loadFixture($package, $scenario, $name)
{ {
$uniqueName = $package . '/' . $scenario . '/' . $name; $this->_usedModelSets[] = $setName;
if ( ! isset(self::$_fixtures[$uniqueName])) {
// load fixture file
$fixtureFile = 'fixtures'
. DIRECTORY_SEPARATOR . $package
. DIRECTORY_SEPARATOR . $scenario
. DIRECTORY_SEPARATOR . $name
. '.php';
require $fixtureFile;
self::$_fixtures[$uniqueName] = $fixture;
}
$fixture = self::$_fixtures[$uniqueName];
$this->_loadedFixtures[] = $fixture['table'];
$conn = $this->sharedFixture['conn'];
$tableName = $fixture['table'];
if ( ! in_array($tableName, self::$_exportedTables)) {
$conn->getSchemaManager()->exportClasses(array($fixture['model']));
self::$_exportedTables[] = $tableName;
}
foreach ($fixture['rows'] as $row) {
$conn->insert($tableName, $row);
}
} }
/** /**
* Loads multiple fixtures of the same package and scenario. * Sweeps the database tables and clears the EntityManager.
* This method must only be called from within the setUp() method of testcases.
* The database will then be populated with fresh data of all loaded fixtures for each
* test method.
*
* WARNING: A single testcase should never load fixtures from different scenarios of
* the same package as the concistency and uniqueness of keys is not guaranteed.
*
* @param string $package The package name. Must be one of Doctrine's test model packages
* (forum, cms or ecommerce).
* @param string $scenario The fixture scenario. A model package can have many fixture
* scenarios. Within a scenario all primary keys and foreign keys
* of fixtures are consistent and unique.
* @param array $names The names of the fixtures to load from the specified package.
*/
protected function loadFixtures($package, $scenario, array $names)
{
foreach ($names as $name) {
$this->loadFixture($package, $scenario, $name);
}
}
/**
* Sweeps the database tables of all used fixtures and clears the EntityManager.
*/ */
protected function tearDown() protected function tearDown()
{ {
$conn = $this->sharedFixture['conn']; $conn = $this->sharedFixture['conn'];
foreach (array_reverse($this->_loadedFixtures) as $table) { if (in_array('cms', $this->_usedModelSets)) {
$conn->exec("DELETE FROM " . $table); $conn->exec('DELETE FROM cms_users_groups');
$conn->exec('DELETE FROM cms_groups');
$conn->exec('DELETE FROM cms_addresses');
$conn->exec('DELETE FROM cms_phonenumbers');
$conn->exec('DELETE FROM cms_users');
} }
$this->_em->clear(); $this->_em->clear();
} }
/**
* Creates a connection to the test database, if there is none yet, and
* creates the necessary tables.
*/
protected function setUp() protected function setUp()
{ {
$forceCreateTables = false;
if ( ! isset($this->sharedFixture['conn'])) { if ( ! isset($this->sharedFixture['conn'])) {
echo PHP_EOL . " --- CREATE CONNECTION ----" . PHP_EOL;
$this->sharedFixture['conn'] = TestUtil::getConnection(); $this->sharedFixture['conn'] = TestUtil::getConnection();
if ($this->sharedFixture['conn']->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) {
$forceCreateTables = true;
}
} }
if ( ! $this->_em) { if ( ! $this->_em) {
$this->_em = $this->_getEntityManager(); $this->_em = $this->_getEntityManager();
$this->_exporter = new \Doctrine\ORM\Export\ClassExporter($this->_em); $this->_schemaTool = new \Doctrine\ORM\Tools\SchemaTool($this->_em);
}
$classes = array();
foreach ($this->_usedModelSets as $setName) {
if ( ! isset(self::$_tablesCreated[$setName]) || $forceCreateTables) {
foreach (self::$_modelSets[$setName] as $className) {
$classes[] = $this->_em->getClassMetadata($className);
}
self::$_tablesCreated[$setName] = true;
}
}
if ($classes) {
$this->_schemaTool->createSchema($classes);
} }
} }
/**
* Gets an EntityManager for testing purposes.
*
* @param Configuration $config The Configuration to pass to the EntityManager.
* @param EventManager $eventManager The EventManager to pass to the EntityManager.
* @return EntityManager
*/
protected function _getEntityManager($config = null, $eventManager = null) { protected function _getEntityManager($config = null, $eventManager = null) {
// NOTE: Functional tests use their own shared metadata cache, because // NOTE: Functional tests use their own shared metadata cache, because
// the actual database platform used during execution has effect on some // the actual database platform used during execution has effect on some

View File

@ -1,10 +0,0 @@
<?php
$fixture = array(
'model' => 'ForumAdministrator',
'rows' => array(
array(
'id' => 1,
'access_level' => 4
)
)
);

View File

@ -1,16 +0,0 @@
<?php
$fixture = array(
'model' => 'ForumUser',
'rows' => array(
array(
'id' => 1,
'username' => 'romanb',
'dtype' => 'admin'
),
array(
'id' => 2,
'username' => 'jwage',
'dtype' => 'user'
)
)
);