- * @since 2.0
- * @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
- */
-abstract class AssociationMapping
-{
- /**
- * Specifies that an association is to be fetched when it is first accessed.
- *
- * @var integer
- */
- const FETCH_LAZY = 2;
- /**
- * Specifies that an association is to be fetched when the owner of the
- * association is fetched.
- *
- * @var integer
- */
- const FETCH_EAGER = 3;
-
- /**
- * READ-ONLY: Whether the association cascades delete() operations from the source entity
- * to the target entity/entities.
- *
- * @var boolean
- */
- public $isCascadeRemove;
-
- /**
- * READ-ONLY: Whether the association cascades persist() operations from the source entity
- * to the target entity/entities.
- *
- * @var boolean
- */
- public $isCascadePersist;
-
- /**
- * READ-ONLY: Whether the association cascades refresh() operations from the source entity
- * to the target entity/entities.
- *
- * @var boolean
- */
- public $isCascadeRefresh;
-
- /**
- * READ-ONLY: Whether the association cascades merge() operations from the source entity
- * to the target entity/entities.
- *
- * @var boolean
- */
- public $isCascadeMerge;
-
- /**
- * READ-ONLY: Whether the association cascades detach() operations from the source entity
- * to the target entity/entities.
- *
- * @var boolean
- */
- public $isCascadeDetach;
-
- /**
- * READ-ONLY: The fetch mode used for the association.
- *
- * @var integer
- */
- public $fetchMode;
-
- /**
- * READ-ONLY: Flag that indicates whether the class that defines this mapping is
- * the owning side of the association.
- *
- * @var boolean
- */
- public $isOwningSide = true;
-
- /**
- * READ-ONLY: The name of the source Entity (the Entity that defines this mapping).
- *
- * @var string
- */
- public $sourceEntityName;
-
- /**
- * READ-ONLY: The name of the target Entity (the Enitity that is the target of the
- * association).
- *
- * @var string
- */
- public $targetEntityName;
-
- /**
- * READ-ONLY: Identifies the field on the source class (the class this AssociationMapping
- * belongs to) that represents the association and stores the reference to the
- * other entity/entities.
- *
- * @var string
- */
- public $sourceFieldName;
-
- /**
- * READ-ONLY: Identifies the field on the owning side of a bidirectional association that
- * controls the mapping for the association. This is only set on the inverse side
- * of an association.
- *
- * @var string
- */
- public $mappedBy;
-
- /**
- * READ-ONLY: Identifies the field on the inverse side of a bidirectional association.
- * This is only set on the owning side of an association.
- *
- * @var string
- */
- public $inversedBy;
-
- /**
- * READ-ONLY: The join table definition, if any.
- *
- * @var array
- */
- public $joinTable;
-
- /**
- * READ-ONLY: The name of the entity class from which the association was
- * inherited in an inheritance hierarchy.
- *
- * @var string
- */
- public $inherited;
-
- /**
- * READ-ONLY: The name of the entity or mapped superclass that declares
- * the association field in an inheritance hierarchy.
- *
- * @var string
- */
- public $declared;
-
- /**
- * Initializes a new instance of a class derived from AssociationMapping.
- *
- * @param array $mapping The mapping definition.
- */
- public function __construct(array $mapping)
- {
- $this->_validateAndCompleteMapping($mapping);
- }
-
- /**
- * Validates & completes the mapping. Mapping defaults are applied here.
- *
- * @param array $mapping
- * @throws MappingException If something is wrong with the mapping.
- */
- protected function _validateAndCompleteMapping(array $mapping)
- {
- // Mandatory attributes for both sides
- if ( ! isset($mapping['fieldName'])) {
- throw MappingException::missingFieldName();
- }
- $this->sourceFieldName = $mapping['fieldName'];
-
- if ( ! isset($mapping['sourceEntity'])) {
- throw MappingException::missingSourceEntity($mapping['fieldName']);
- }
- $this->sourceEntityName = $mapping['sourceEntity'];
-
- if ( ! isset($mapping['targetEntity'])) {
- throw MappingException::missingTargetEntity($mapping['fieldName']);
- }
- $this->targetEntityName = $mapping['targetEntity'];
-
- // Mandatory and optional attributes for either side
- if ( ! isset($mapping['mappedBy'])) {
- // Optional
- if (isset($mapping['joinTable']) && $mapping['joinTable']) {
- if ($mapping['joinTable']['name'][0] == '`') {
- $mapping['joinTable']['name'] = trim($mapping['joinTable']['name'], '`');
- $mapping['joinTable']['quoted'] = true;
- }
- $this->joinTable = $mapping['joinTable'];
- }
- if (isset($mapping['inversedBy'])) {
- $this->inversedBy = $mapping['inversedBy'];
- }
- } else {
- $this->isOwningSide = false;
- $this->mappedBy = $mapping['mappedBy'];
- }
-
- // Optional attributes for both sides
- $this->fetchMode = isset($mapping['fetch']) ? $mapping['fetch'] : self::FETCH_LAZY;
- $cascades = isset($mapping['cascade']) ? $mapping['cascade'] : array();
-
- if (in_array('all', $cascades)) {
- $cascades = array(
- 'remove',
- 'persist',
- 'refresh',
- 'merge',
- 'detach'
- );
- }
-
- $this->isCascadeRemove = in_array('remove', $cascades);
- $this->isCascadePersist = in_array('persist', $cascades);
- $this->isCascadeRefresh = in_array('refresh', $cascades);
- $this->isCascadeMerge = in_array('merge', $cascades);
- $this->isCascadeDetach = in_array('detach', $cascades);
- }
-
- /**
- * Whether the target entity/entities of the association are eagerly fetched.
- *
- * @return boolean
- */
- public function isEagerlyFetched()
- {
- return $this->fetchMode == self::FETCH_EAGER;
- }
-
- /**
- * Whether the target entity/entities of the association are lazily fetched.
- *
- * @return boolean
- */
- public function isLazilyFetched()
- {
- return $this->fetchMode == self::FETCH_LAZY;
- }
-
- /**
- * Whether the association is a one-to-one association.
- *
- * @return boolean
- */
- public function isOneToOne()
- {
- return false;
- }
-
- /**
- * Whether the association is a one-to-many association.
- *
- * @return boolean
- */
- public function isOneToMany()
- {
- return false;
- }
-
- /**
- * Whether the association is a many-to-many association.
- *
- * @return boolean
- */
- public function isManyToMany()
- {
- return false;
- }
-
- /**
- * Whether the association uses a join table for the mapping.
- *
- * @return boolean
- */
- public function usesJoinTable()
- {
- return (bool) $this->joinTable;
- }
-
- /**
- * Checks whether the association has any cascades configured.
- *
- * @return boolean
- */
- public function hasCascades()
- {
- return $this->isCascadePersist ||
- $this->isCascadeRemove ||
- $this->isCascadeRefresh ||
- $this->isCascadeMerge ||
- $this->isCascadeDetach;
- }
-
- /**
- * Loads data in $target domain object using this association.
- * The data comes from the association navigated from $sourceEntity
- * using $em.
- *
- * @param object $sourceEntity
- * @param object $target an entity or a collection
- * @param EntityManager $em
- * @param array $joinColumnValues foreign keys (significative for this
- * association) of $sourceEntity, if needed
- */
- abstract public function load($sourceEntity, $target, $em, array $joinColumnValues = array());
-
- /**
- * Gets the (possibly quoted) name of the join table.
- *
- * @param AbstractPlatform $platform
- * @return string
- */
- public function getQuotedJoinTableName($platform)
- {
- return isset($this->joinTable['quoted'])
- ? $platform->quoteIdentifier($this->joinTable['name'])
- : $this->joinTable['name'];
- }
-
- /**
- * Determines which fields get serialized.
- *
- * It is only serialized what is necessary for best unserialization performance.
- * That means any metadata properties that are not set or empty or simply have
- * their default value are NOT serialized.
- *
- * @return array The names of all the fields that should be serialized.
- */
- public function __sleep()
- {
- $serialized = array(
- 'sourceEntityName',
- 'targetEntityName',
- 'sourceFieldName',
- 'fetchMode'
- );
-
- if ($this->isCascadeDetach) {
- $serialized[] = 'isCascadeDetach';
- }
- if ($this->isCascadeMerge) {
- $serialized[] = 'isCascadeMerge';
- }
- if ($this->isCascadePersist) {
- $serialized[] = 'isCascadePersist';
- }
- if ($this->isCascadeRefresh) {
- $serialized[] = 'isCascadeRefresh';
- }
- if ($this->isCascadeRemove) {
- $serialized[] = 'isCascadeRemove';
- }
- if ( ! $this->isOwningSide) {
- $serialized[] = 'isOwningSide';
- }
- if ($this->mappedBy) {
- $serialized[] = 'mappedBy';
- }
- if ($this->inversedBy) {
- $serialized[] = 'inversedBy';
- }
- if ($this->joinTable) {
- $serialized[] = 'joinTable';
- }
- if ($this->inherited) {
- $serialized[] = 'inherited';
- }
- if ($this->declared) {
- $serialized[] = 'declared';
- }
-
- return $serialized;
- }
-}
diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadata.php b/lib/Doctrine/ORM/Mapping/ClassMetadata.php
index de3cad029..15112adbe 100644
--- a/lib/Doctrine/ORM/Mapping/ClassMetadata.php
+++ b/lib/Doctrine/ORM/Mapping/ClassMetadata.php
@@ -193,12 +193,12 @@ class ClassMetadata extends ClassMetadataInfo
*
* @param AssociationMapping $assocMapping
*/
- protected function _storeAssociationMapping(AssociationMapping $assocMapping)
+ protected function _storeAssociationMapping(array $assocMapping)
{
parent::_storeAssociationMapping($assocMapping);
// Store ReflectionProperty of mapped field
- $sourceFieldName = $assocMapping->sourceFieldName;
+ $sourceFieldName = $assocMapping['fieldName'];
$refProp = $this->reflClass->getProperty($sourceFieldName);
$refProp->setAccessible(true);
@@ -234,6 +234,19 @@ class ClassMetadata extends ClassMetadataInfo
$this->table['name'];
}
+ /**
+ * Gets the (possibly quoted) name of the join table.
+ *
+ * @param AbstractPlatform $platform
+ * @return string
+ */
+ public function getQuotedJoinTableName(array $assoc, $platform)
+ {
+ return isset($assoc['joinTable']['quoted'])
+ ? $platform->quoteIdentifier($assoc['joinTable']['name'])
+ : $assoc['joinTable']['name'];
+ }
+
/**
* Creates a string representation of this instance.
*
@@ -337,8 +350,8 @@ class ClassMetadata extends ClassMetadataInfo
}
foreach ($this->associationMappings as $field => $mapping) {
- if ($mapping->declared) {
- $reflField = new ReflectionProperty($mapping->declared, $field);
+ if (isset($mapping['declared'])) {
+ $reflField = new ReflectionProperty($mapping['declared'], $field);
} else {
$reflField = $this->reflClass->getProperty($field);
}
diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
index 14bc7015d..bc11daa3d 100644
--- a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
+++ b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
@@ -249,12 +249,13 @@ class ClassMetadataFactory
$class->setVersionField($parent->versionField);
$class->setDiscriminatorMap($parent->discriminatorMap);
$class->setLifecycleCallbacks($parent->lifecycleCallbacks);
+ $class->setChangeTrackingPolicy($parent->changeTrackingPolicy);
}
// Invoke driver
try {
$this->_driver->loadMetadataForClass($className, $class);
- } catch(ReflectionException $e) {
+ } catch (ReflectionException $e) {
throw MappingException::reflectionFailure($className, $e);
}
@@ -345,14 +346,14 @@ class ClassMetadataFactory
private function _addInheritedRelations(ClassMetadata $subClass, ClassMetadata $parentClass)
{
foreach ($parentClass->associationMappings as $field => $mapping) {
- $subclassMapping = clone $mapping;
- if ( ! isset($mapping->inherited) && ! $parentClass->isMappedSuperclass) {
- $subclassMapping->inherited = $parentClass->name;
+ //$subclassMapping = $mapping;
+ if ( ! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
+ $mapping['inherited'] = $parentClass->name;
}
- if ( ! isset($mapping->declared)) {
- $subclassMapping->declared = $parentClass->name;
+ if ( ! isset($mapping['declared'])) {
+ $mapping['declared'] = $parentClass->name;
}
- $subClass->addInheritedAssociationMapping($subclassMapping);
+ $subClass->addInheritedAssociationMapping($mapping);
}
}
diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
index edd7cd53f..fbf6ebdb3 100644
--- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
+++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
@@ -112,6 +112,39 @@ class ClassMetadataInfo
* the NotifyPropertyChanged interface.
*/
const CHANGETRACKING_NOTIFY = 3;
+ /**
+ * Specifies that an association is to be fetched when it is first accessed.
+ */
+ const FETCH_LAZY = 2;
+ /**
+ * Specifies that an association is to be fetched when the owner of the
+ * association is fetched.
+ */
+ const FETCH_EAGER = 3;
+ /**
+ * Identifies a one-to-one association.
+ */
+ const ONE_TO_ONE = 1;
+ /**
+ * Identifies a many-to-one association.
+ */
+ const MANY_TO_ONE = 2;
+ /**
+ * Combined bitmask for to-one (single-valued) associations.
+ */
+ const TO_ONE = 3;
+ /**
+ * Identifies a one-to-many association.
+ */
+ const ONE_TO_MANY = 4;
+ /**
+ * Identifies a many-to-many association.
+ */
+ const MANY_TO_MANY = 8;
+ /**
+ * Combined bitmask for to-many (collection-valued) associations.
+ */
+ const TO_MANY = 12;
/**
* READ-ONLY: The name of the entity class.
@@ -302,6 +335,52 @@ class ClassMetadataInfo
/**
* READ-ONLY: The association mappings of this class.
*
+ * The mapping definition array supports the following keys:
+ *
+ * - fieldName (string)
+ * The name of the field in the entity the association is mapped to.
+ *
+ * - targetEntity (string)
+ * The class name of the target entity. If it is fully-qualified it is used as is.
+ * If it is a simple, unqualified class name the namespace is assumed to be the same
+ * as the namespace of the source entity.
+ *
+ * - mappedBy (string, required for bidirectional associations)
+ * The name of the field that completes the bidirectional association on the owning side.
+ * This key must be specified on the inverse side of a bidirectional association.
+ *
+ * - inversedBy (string, required for bidirectional associations)
+ * The name of the field that completes the bidirectional association on the inverse side.
+ * This key must be specified on the owning side of a bidirectional association.
+ *
+ * - cascade (array, optional)
+ * The names of persistence operations to cascade on the association. The set of possible
+ * values are: "persist", "remove", "detach", "merge", "refresh", "all" (implies all others).
+ *
+ * - orderBy (array, one-to-many/many-to-many only)
+ * A map of field names (of the target entity) to sorting directions (ASC/DESC).
+ * Example: array('priority' => 'desc')
+ *
+ * - fetch (integer, optional)
+ * The fetching strategy to use for the association, usually defaults to FETCH_LAZY.
+ * Possible values are: ClassMetadata::FETCH_EAGER, ClassMetadata::FETCH_LAZY.
+ *
+ * - joinTable (array, optional, many-to-many only)
+ * Specification of the join table and its join columns (foreign keys).
+ * Only valid for many-to-many mappings. Note that one-to-many associations can be mapped
+ * through a join table by simply mapping the association as many-to-many with a unique
+ * constraint on the join table.
+ *
+ * A join table definition has the following structure:
+ *
+ * array(
+ * 'name' => ,
+ * 'joinColumns' => array(),
+ * 'inverseJoinColumns' => array()
+ * )
+ *
+ *
+ *
* @var array
*/
public $associationMappings = array();
@@ -600,6 +679,230 @@ class ClassMetadataInfo
}
}
+ /**
+ * Validates & completes the mapping. Mapping defaults are applied here.
+ *
+ * @param array $mapping
+ * @throws MappingException If something is wrong with the mapping.
+ */
+ protected function _validateAndCompleteAssociationMapping(array $mapping)
+ {
+ if ( ! isset($mapping['mappedBy'])) {
+ $mapping['mappedBy'] = null;
+ }
+ if ( ! isset($mapping['inversedBy'])) {
+ $mapping['inversedBy'] = null;
+ }
+ $mapping['isOwningSide'] = true;
+
+ $mapping['sourceEntity'] = $this->name;
+ if (isset($mapping['targetEntity']) && strpos($mapping['targetEntity'], '\\') === false && strlen($this->namespace) > 0) {
+ $mapping['targetEntity'] = $this->namespace . '\\' . $mapping['targetEntity'];
+ }
+
+ // Complete id mapping
+ if (isset($mapping['id']) && $mapping['id'] === true) {
+ if ( ! in_array($mapping['fieldName'], $this->identifier)) {
+ $this->identifier[] = $mapping['fieldName'];
+ }
+ // Check for composite key
+ if ( ! $this->isIdentifierComposite && count($this->identifier) > 1) {
+ $this->isIdentifierComposite = true;
+ }
+ }
+
+ // Mandatory attributes for both sides
+ if ( ! isset($mapping['fieldName'])) {
+ throw MappingException::missingFieldName();
+ }
+
+ if ( ! isset($mapping['sourceEntity'])) {
+ throw MappingException::missingSourceEntity($mapping['fieldName']);
+ }
+
+ if ( ! isset($mapping['targetEntity'])) {
+ throw MappingException::missingTargetEntity($mapping['fieldName']);
+ }
+
+ // Mandatory and optional attributes for either side
+ if ( ! isset($mapping['mappedBy'])) {
+ // Optional
+ if (isset($mapping['joinTable']) && $mapping['joinTable']) {
+ if ($mapping['joinTable']['name'][0] == '`') {
+ $mapping['joinTable']['name'] = trim($mapping['joinTable']['name'], '`');
+ $mapping['joinTable']['quoted'] = true;
+ }
+ }
+ } else {
+ $mapping['isOwningSide'] = false;
+ }
+
+ // Optional attributes for both sides
+ if ( ! isset($mapping['fetch'])) {
+ $mapping['fetch'] = self::FETCH_LAZY;
+ }
+ $cascades = isset($mapping['cascade']) ? $mapping['cascade'] : array();
+
+ if (in_array('all', $cascades)) {
+ $cascades = array(
+ 'remove',
+ 'persist',
+ 'refresh',
+ 'merge',
+ 'detach'
+ );
+ }
+ $mapping['cascade'] = $cascades;
+ $mapping['isCascadeRemove'] = in_array('remove', $cascades);
+ $mapping['isCascadePersist'] = in_array('persist', $cascades);
+ $mapping['isCascadeRefresh'] = in_array('refresh', $cascades);
+ $mapping['isCascadeMerge'] = in_array('merge', $cascades);
+ $mapping['isCascadeDetach'] = in_array('detach', $cascades);
+
+ return $mapping;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param array $mapping The mapping to validate & complete.
+ * @return array The validated & completed mapping.
+ * @override
+ */
+ protected function _validateAndCompleteOneToOneMapping(array $mapping)
+ {
+ $mapping = $this->_validateAndCompleteAssociationMapping($mapping);
+
+ if (isset($mapping['joinColumns']) && $mapping['joinColumns']) {
+ $mapping['isOwningSide'] = true;
+ }
+
+ if ($mapping['isOwningSide']) {
+ if ( ! isset($mapping['joinColumns']) || ! $mapping['joinColumns']) {
+ // Apply default join column
+ $mapping['joinColumns'] = array(array(
+ 'name' => $mapping['fieldName'] . '_id',
+ 'referencedColumnName' => 'id'
+ ));
+ }
+ foreach ($mapping['joinColumns'] AS $key => $joinColumn) {
+ if ($mapping['type'] == self::ONE_TO_ONE) {
+ $mapping['joinColumns'][$key]['unique'] = true;
+ }
+
+ $mapping['sourceToTargetKeyColumns'][$joinColumn['name']] = $joinColumn['referencedColumnName'];
+ $mapping['joinColumnFieldNames'][$joinColumn['name']] = isset($joinColumn['fieldName'])
+ ? $joinColumn['fieldName'] : $joinColumn['name'];
+ }
+ $mapping['targetToSourceKeyColumns'] = array_flip($mapping['sourceToTargetKeyColumns']);
+ }
+
+ //TODO: if orphanRemoval, cascade=remove is implicit!
+ $mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ?
+ (bool) $mapping['orphanRemoval'] : false;
+
+ return $mapping;
+ }
+
+ /**
+ * Validates and completes the mapping.
+ *
+ * @param array $mapping The mapping to validate and complete.
+ * @return array The validated and completed mapping.
+ * @override
+ */
+ protected function _validateAndCompleteOneToManyMapping(array $mapping)
+ {
+ $mapping = $this->_validateAndCompleteAssociationMapping($mapping);
+
+ // OneToMany-side MUST be inverse (must have mappedBy)
+ if ( ! isset($mapping['mappedBy'])) {
+ throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']);
+ }
+
+ //TODO: if orphanRemoval, cascade=remove is implicit!
+ $mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ?
+ (bool) $mapping['orphanRemoval'] : false;
+
+ if (isset($mapping['orderBy'])) {
+ if ( ! is_array($mapping['orderBy'])) {
+ throw new \InvalidArgumentException("'orderBy' is expected to be an array, not ".gettype($mapping['orderBy']));
+ }
+ }
+
+ return $mapping;
+ }
+
+ protected function _validateAndCompleteManyToManyMapping(array $mapping)
+ {
+ $mapping = $this->_validateAndCompleteAssociationMapping($mapping);
+ if ($mapping['isOwningSide']) {
+ // owning side MUST have a join table
+ if ( ! isset($mapping['joinTable']) || ! $mapping['joinTable']) {
+ // Apply default join table
+ $sourceShortName = substr($mapping['sourceEntity'], strrpos($mapping['sourceEntity'], '\\') + 1);
+ $targetShortName = substr($mapping['targetEntity'], strrpos($mapping['targetEntity'], '\\') + 1);
+ $mapping['joinTable'] = array(
+ 'name' => $sourceShortName .'_' . $targetShortName,
+ 'joinColumns' => array(
+ array(
+ 'name' => $sourceShortName . '_id',
+ 'referencedColumnName' => 'id',
+ 'onDelete' => 'CASCADE'
+ )
+ ),
+ 'inverseJoinColumns' => array(
+ array(
+ 'name' => $targetShortName . '_id',
+ 'referencedColumnName' => 'id',
+ 'onDelete' => 'CASCADE'
+ )
+ )
+ );
+ }
+ // owning side MUST specify joinColumns
+ else if ( ! isset($mapping['joinTable']['joinColumns'])) {
+ throw MappingException::missingRequiredOption(
+ $mapping['fieldName'], 'joinColumns',
+ 'Did you think of case sensitivity / plural s?'
+ );
+ }
+ // owning side MUST specify inverseJoinColumns
+ else if ( ! isset($mapping['joinTable']['inverseJoinColumns'])) {
+ throw MappingException::missingRequiredOption(
+ $mapping['fieldName'], 'inverseJoinColumns',
+ 'Did you think of case sensitivity / plural s?'
+ );
+ }
+
+ foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) {
+ if (isset($joinColumn['onDelete']) && strtolower($joinColumn['onDelete']) == 'cascade') {
+ $mapping['isOnDeleteCascade'] = true;
+ }
+
+ $mapping['relationToSourceKeyColumns'][$joinColumn['name']] = $joinColumn['referencedColumnName'];
+ $mapping['joinTableColumns'][] = $joinColumn['name'];
+ }
+
+ foreach ($mapping['joinTable']['inverseJoinColumns'] as $inverseJoinColumn) {
+ if (isset($inverseJoinColumn['onDelete']) && strtolower($inverseJoinColumn['onDelete']) == 'cascade') {
+ $mapping['isOnDeleteCascade'] = true;
+ }
+
+ $mapping['relationToTargetKeyColumns'][$inverseJoinColumn['name']] = $inverseJoinColumn['referencedColumnName'];
+ $mapping['joinTableColumns'][] = $inverseJoinColumn['name'];
+ }
+ }
+
+ if (isset($mapping['orderBy'])) {
+ if ( ! is_array($mapping['orderBy'])) {
+ throw new \InvalidArgumentException("'orderBy' is expected to be an array, not ".gettype($mapping['orderBy']));
+ }
+ }
+
+ return $mapping;
+ }
+
/**
* Gets the identifier (primary key) field names of the class.
*
@@ -688,7 +991,7 @@ class ClassMetadataInfo
$columnNames = array();
foreach ($this->identifier as $idField) {
if (isset($this->associationMappings[$idField])) {
- $columnNames[] = $this->associationMappings[$idField]->joinColumns[0]['name'];
+ $columnNames[] = $this->associationMappings[$idField]['joinColumns'][0]['name'];
} else {
$columnNames[] = $this->fieldMappings[$idField]['columnName'];
}
@@ -901,7 +1204,7 @@ class ClassMetadataInfo
*/
public function isInheritedAssociation($fieldName)
{
- return isset($this->associationMappings[$fieldName]->inherited);
+ return isset($this->associationMappings[$fieldName]['inherited']);
}
/**
@@ -998,12 +1301,12 @@ class ClassMetadataInfo
* @param AssociationMapping $mapping
* @param string $owningClassName The name of the class that defined this mapping.
*/
- public function addInheritedAssociationMapping(AssociationMapping $mapping/*, $owningClassName = null*/)
+ public function addInheritedAssociationMapping(array $mapping/*, $owningClassName = null*/)
{
- if (isset($this->associationMappings[$mapping->sourceFieldName])) {
- throw MappingException::duplicateAssociationMapping($this->name, $mapping->sourceFieldName);
+ if (isset($this->associationMappings[$mapping['fieldName']])) {
+ throw MappingException::duplicateAssociationMapping($this->name, $mapping['fieldName']);
}
- $this->associationMappings[$mapping->sourceFieldName] = $mapping;
+ $this->associationMappings[$mapping['fieldName']] = $mapping;
}
/**
@@ -1028,9 +1331,9 @@ class ClassMetadataInfo
*/
public function mapOneToOne(array $mapping)
{
- $mapping = $this->_completeAssociationMapping($mapping);
- $oneToOneMapping = new OneToOneMapping($mapping);
- $this->_storeAssociationMapping($oneToOneMapping);
+ $mapping['type'] = self::ONE_TO_ONE;
+ $mapping = $this->_validateAndCompleteOneToOneMapping($mapping);
+ $this->_storeAssociationMapping($mapping);
}
/**
@@ -1040,9 +1343,9 @@ class ClassMetadataInfo
*/
public function mapOneToMany(array $mapping)
{
- $mapping = $this->_completeAssociationMapping($mapping);
- $oneToManyMapping = new OneToManyMapping($mapping);
- $this->_storeAssociationMapping($oneToManyMapping);
+ $mapping['type'] = self::ONE_TO_MANY;
+ $mapping = $this->_validateAndCompleteOneToManyMapping($mapping);
+ $this->_storeAssociationMapping($mapping);
}
/**
@@ -1052,8 +1355,10 @@ class ClassMetadataInfo
*/
public function mapManyToOne(array $mapping)
{
- // A many-to-one mapping is simply a one-one backreference
- $this->mapOneToOne($mapping);
+ $mapping['type'] = self::MANY_TO_ONE;
+ // A many-to-one mapping is essentially a one-one backreference
+ $mapping = $this->_validateAndCompleteOneToOneMapping($mapping);
+ $this->_storeAssociationMapping($mapping);
}
/**
@@ -1063,9 +1368,9 @@ class ClassMetadataInfo
*/
public function mapManyToMany(array $mapping)
{
- $mapping = $this->_completeAssociationMapping($mapping);
- $manyToManyMapping = new ManyToManyMapping($mapping);
- $this->_storeAssociationMapping($manyToManyMapping);
+ $mapping['type'] = self::MANY_TO_MANY;
+ $mapping = $this->_validateAndCompleteManyToManyMapping($mapping);
+ $this->_storeAssociationMapping($mapping);
}
/**
@@ -1073,9 +1378,9 @@ class ClassMetadataInfo
*
* @param AssociationMapping $assocMapping
*/
- protected function _storeAssociationMapping(AssociationMapping $assocMapping)
+ protected function _storeAssociationMapping(array $assocMapping)
{
- $sourceFieldName = $assocMapping->sourceFieldName;
+ $sourceFieldName = $assocMapping['fieldName'];
if (isset($this->fieldMappings[$sourceFieldName]) || isset($this->associationMappings[$sourceFieldName])) {
throw MappingException::duplicateFieldMapping($this->name, $sourceFieldName);
}
@@ -1223,7 +1528,7 @@ class ClassMetadataInfo
public function isSingleValuedAssociation($fieldName)
{
return isset($this->associationMappings[$fieldName]) &&
- $this->associationMappings[$fieldName]->isOneToOne();
+ ($this->associationMappings[$fieldName]['type'] & self::TO_ONE);
}
/**
@@ -1236,7 +1541,7 @@ class ClassMetadataInfo
public function isCollectionValuedAssociation($fieldName)
{
return isset($this->associationMappings[$fieldName]) &&
- ! $this->associationMappings[$fieldName]->isOneToOne();
+ ! ($this->associationMappings[$fieldName]['type'] & self::TO_ONE);
}
/**
@@ -1310,4 +1615,4 @@ class ClassMetadataInfo
{
$this->versionField = $versionField;
}
-}
\ No newline at end of file
+}
diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
index a33eb4eb8..0f3db557a 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
@@ -300,14 +300,14 @@ class AnnotationDriver implements Driver
$mapping['inversedBy'] = $oneToOneAnnot->inversedBy;
$mapping['cascade'] = $oneToOneAnnot->cascade;
$mapping['orphanRemoval'] = $oneToOneAnnot->orphanRemoval;
- $mapping['fetch'] = constant('Doctrine\ORM\Mapping\AssociationMapping::FETCH_' . $oneToOneAnnot->fetch);
+ $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToOneAnnot->fetch);
$metadata->mapOneToOne($mapping);
} else if ($oneToManyAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToMany')) {
$mapping['mappedBy'] = $oneToManyAnnot->mappedBy;
$mapping['targetEntity'] = $oneToManyAnnot->targetEntity;
$mapping['cascade'] = $oneToManyAnnot->cascade;
$mapping['orphanRemoval'] = $oneToManyAnnot->orphanRemoval;
- $mapping['fetch'] = constant('Doctrine\ORM\Mapping\AssociationMapping::FETCH_' . $oneToManyAnnot->fetch);
+ $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToManyAnnot->fetch);
if ($orderByAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
$mapping['orderBy'] = $orderByAnnot->value;
@@ -323,7 +323,7 @@ class AnnotationDriver implements Driver
$mapping['cascade'] = $manyToOneAnnot->cascade;
$mapping['inversedBy'] = $manyToOneAnnot->inversedBy;
$mapping['targetEntity'] = $manyToOneAnnot->targetEntity;
- $mapping['fetch'] = constant('Doctrine\ORM\Mapping\AssociationMapping::FETCH_' . $manyToOneAnnot->fetch);
+ $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToOneAnnot->fetch);
$metadata->mapManyToOne($mapping);
} else if ($manyToManyAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToMany')) {
$joinTable = array();
@@ -364,7 +364,7 @@ class AnnotationDriver implements Driver
$mapping['mappedBy'] = $manyToManyAnnot->mappedBy;
$mapping['inversedBy'] = $manyToManyAnnot->inversedBy;
$mapping['cascade'] = $manyToManyAnnot->cascade;
- $mapping['fetch'] = constant('Doctrine\ORM\Mapping\AssociationMapping::FETCH_' . $manyToManyAnnot->fetch);
+ $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToManyAnnot->fetch);
if ($orderByAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
$mapping['orderBy'] = $orderByAnnot->value;
diff --git a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
index e8f97d835..3a95ca52c 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
@@ -238,7 +238,7 @@ class XmlDriver extends AbstractFileDriver
);
if (isset($oneToOneElement['fetch'])) {
- $mapping['fetch'] = constant('Doctrine\ORM\Mapping\AssociationMapping::FETCH_' . (string)$oneToOneElement['fetch']);
+ $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$oneToOneElement['fetch']);
}
if (isset($oneToOneElement['mapped-by'])) {
@@ -282,7 +282,7 @@ class XmlDriver extends AbstractFileDriver
);
if (isset($oneToManyElement['fetch'])) {
- $mapping['fetch'] = constant('Doctrine\ORM\Mapping\AssociationMapping::FETCH_' . (string)$oneToManyElement['fetch']);
+ $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$oneToManyElement['fetch']);
}
if (isset($oneToManyElement->cascade)) {
@@ -314,7 +314,7 @@ class XmlDriver extends AbstractFileDriver
);
if (isset($manyToOneElement['fetch'])) {
- $mapping['fetch'] = constant('Doctrine\ORM\Mapping\AssociationMapping::FETCH_' . (string)$manyToOneElement['fetch']);
+ $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$manyToOneElement['fetch']);
}
if (isset($manyToOneElement['inversed-by'])) {
@@ -357,7 +357,7 @@ class XmlDriver extends AbstractFileDriver
);
if (isset($manyToManyElement['fetch'])) {
- $mapping['fetch'] = constant('Doctrine\ORM\Mapping\AssociationMapping::FETCH_' . (string)$manyToManyElement['fetch']);
+ $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$manyToManyElement['fetch']);
}
if (isset($manyToManyElement['mapped-by'])) {
diff --git a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
index 967760785..5ab26e388 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
@@ -237,7 +237,7 @@ class YamlDriver extends AbstractFileDriver
);
if (isset($oneToOneElement['fetch'])) {
- $mapping['fetch'] = constant('Doctrine\ORM\Mapping\AssociationMapping::FETCH_' . $oneToOneElement['fetch']);
+ $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToOneElement['fetch']);
}
if (isset($oneToOneElement['mappedBy'])) {
@@ -282,7 +282,7 @@ class YamlDriver extends AbstractFileDriver
);
if (isset($oneToManyElement['fetch'])) {
- $mapping['fetch'] = constant('Doctrine\ORM\Mapping\AssociationMapping::FETCH_' . $oneToManyElement['fetch']);
+ $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToManyElement['fetch']);
}
if (isset($oneToManyElement['cascade'])) {
@@ -306,7 +306,7 @@ class YamlDriver extends AbstractFileDriver
);
if (isset($manyToOneElement['fetch'])) {
- $mapping['fetch'] = constant('Doctrine\ORM\Mapping\AssociationMapping::FETCH_' . $manyToOneElement['fetch']);
+ $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToOneElement['fetch']);
}
if (isset($manyToOneElement['inversedBy'])) {
@@ -346,7 +346,7 @@ class YamlDriver extends AbstractFileDriver
);
if (isset($manyToManyElement['fetch'])) {
- $mapping['fetch'] = constant('Doctrine\ORM\Mapping\AssociationMapping::FETCH_' . $manyToManyElement['fetch']);
+ $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToManyElement['fetch']);
}
if (isset($manyToManyElement['mappedBy'])) {
diff --git a/lib/Doctrine/ORM/Mapping/ManyToManyMapping.php b/lib/Doctrine/ORM/Mapping/ManyToManyMapping.php
deleted file mode 100644
index a308b4eb8..000000000
--- a/lib/Doctrine/ORM/Mapping/ManyToManyMapping.php
+++ /dev/null
@@ -1,195 +0,0 @@
-.
- */
-
-namespace Doctrine\ORM\Mapping;
-
-/**
- * A many-to-many mapping describes the mapping between two collections of
- * entities.
- *
- * IMPORTANT NOTE:
- *
- * The fields of this class are only public for 2 reasons:
- * 1) To allow fast READ access.
- * 2) To drastically reduce the size of a serialized instance (private/protected members
- * get the whole class name, namespace inclusive, prepended to every property in
- * the serialized representation).
- *
- * Instances of this class are stored serialized in the metadata cache together with the
- * owning ClassMetadata instance.
- *
- * @since 2.0
- * @author Roman Borschel
- * @author Giorgio Sironi
- * @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
- */
-class ManyToManyMapping extends AssociationMapping
-{
- /**
- * READ-ONLY: Maps the columns in the relational table to the columns in the source table.
- */
- public $relationToSourceKeyColumns = array();
-
- /**
- * READ-ONLY: Maps the columns in the relation table to the columns in the target table.
- */
- public $relationToTargetKeyColumns = array();
-
- /**
- * READ-ONLY: List of aggregated column names on the join table.
- */
- public $joinTableColumns = array();
-
- /** FUTURE: The key column mapping, if any. The key column holds the keys of the Collection. */
- //public $keyColumn;
-
- /**
- * READ-ONLY: Order this collection by the given DQL snippet.
- *
- * Only simple unqualified field names and ASC|DESC are allowed
- *
- * @var array
- */
- public $orderBy;
-
- /**
- * READ-ONLY: Are entries on the owning AND inverse side of this join-table deleted through a database onDelete="CASCADE" operation?
- *
- * @var bool
- */
- public $isOnDeleteCascade = false;
-
- /**
- * {@inheritdoc}
- */
- protected function _validateAndCompleteMapping(array $mapping)
- {
- parent::_validateAndCompleteMapping($mapping);
- if ($this->isOwningSide) {
- // owning side MUST have a join table
- if ( ! isset($mapping['joinTable']) || ! $mapping['joinTable']) {
- // Apply default join table
- $sourceShortName = substr($this->sourceEntityName, strrpos($this->sourceEntityName, '\\') + 1);
- $targetShortName = substr($this->targetEntityName, strrpos($this->targetEntityName, '\\') + 1);
- $mapping['joinTable'] = array(
- 'name' => $sourceShortName .'_' . $targetShortName,
- 'joinColumns' => array(
- array(
- 'name' => $sourceShortName . '_id',
- 'referencedColumnName' => 'id',
- 'onDelete' => 'CASCADE'
- )
- ),
- 'inverseJoinColumns' => array(
- array(
- 'name' => $targetShortName . '_id',
- 'referencedColumnName' => 'id',
- 'onDelete' => 'CASCADE'
- )
- )
- );
- $this->joinTable = $mapping['joinTable'];
- }
- // owning side MUST specify joinColumns
- else if ( ! isset($mapping['joinTable']['joinColumns'])) {
- throw MappingException::missingRequiredOption(
- $this->sourceFieldName, 'joinColumns',
- 'Did you think of case sensitivity / plural s?'
- );
- }
- // owning side MUST specify inverseJoinColumns
- else if ( ! isset($mapping['joinTable']['inverseJoinColumns'])) {
- throw MappingException::missingRequiredOption(
- $this->sourceFieldName, 'inverseJoinColumns',
- 'Did you think of case sensitivity / plural s?'
- );
- }
-
- foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) {
- if (isset($joinColumn['onDelete']) && strtolower($joinColumn['onDelete']) == 'cascade') {
- $this->isOnDeleteCascade = true;
- }
-
- $this->relationToSourceKeyColumns[$joinColumn['name']] = $joinColumn['referencedColumnName'];
- $this->joinTableColumns[] = $joinColumn['name'];
- }
-
- foreach ($mapping['joinTable']['inverseJoinColumns'] as $inverseJoinColumn) {
- if (isset($inverseJoinColumn['onDelete']) && strtolower($inverseJoinColumn['onDelete']) == 'cascade') {
- $this->isOnDeleteCascade = true;
- }
-
- $this->relationToTargetKeyColumns[$inverseJoinColumn['name']] = $inverseJoinColumn['referencedColumnName'];
- $this->joinTableColumns[] = $inverseJoinColumn['name'];
- }
- }
-
- if (isset($mapping['orderBy'])) {
- if ( ! is_array($mapping['orderBy'])) {
- throw new \InvalidArgumentException("'orderBy' is expected to be an array, not ".gettype($mapping['orderBy']));
- }
- $this->orderBy = $mapping['orderBy'];
- }
- }
-
- /**
- * Loads entities in $targetCollection using $em.
- * The data of $sourceEntity are used to restrict the collection
- * via the join table.
- *
- * @param object The owner of the collection.
- * @param object The collection to populate.
- * @param array
- * @todo Remove
- */
- public function load($sourceEntity, $targetCollection, $em, array $joinColumnValues = array())
- {
- $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadManyToManyCollection($this, $sourceEntity, $targetCollection);
- }
-
- /** {@inheritdoc} */
- public function isManyToMany()
- {
- return true;
- }
-
- /**
- * Determines which fields get serialized.
- *
- * It is only serialized what is necessary for best unserialization performance.
- * That means any metadata properties that are not set or empty or simply have
- * their default value are NOT serialized.
- *
- * @return array The names of all the fields that should be serialized.
- */
- public function __sleep()
- {
- $serialized = parent::__sleep();
- $serialized[] = 'joinTableColumns';
- $serialized[] = 'relationToSourceKeyColumns';
- $serialized[] = 'relationToTargetKeyColumns';
- if ($this->isOnDeleteCascade) {
- $serialized[] = 'isOnDeleteCascade';
- }
- if ($this->orderBy) {
- $serialized[] = 'orderBy';
- }
- return $serialized;
- }
-}
diff --git a/lib/Doctrine/ORM/Mapping/OneToManyMapping.php b/lib/Doctrine/ORM/Mapping/OneToManyMapping.php
deleted file mode 100644
index 4ffc1d511..000000000
--- a/lib/Doctrine/ORM/Mapping/OneToManyMapping.php
+++ /dev/null
@@ -1,144 +0,0 @@
-.
- */
-
-namespace Doctrine\ORM\Mapping;
-
-/**
- * Represents a one-to-many mapping.
- *
- * NOTE: One-to-many mappings can currently not be uni-directional (one -> many).
- * They must either be bidirectional (one <-> many) or unidirectional (many -> one).
- * In other words, the many-side MUST be the owning side and the one-side MUST be
- * the inverse side.
- *
- * IMPORTANT NOTE:
- *
- * The fields of this class are only public for 2 reasons:
- * 1) To allow fast READ access.
- * 2) To drastically reduce the size of a serialized instance (private/protected members
- * get the whole class name, namespace inclusive, prepended to every property in
- * the serialized representation).
- *
- * Instances of this class are stored serialized in the metadata cache together with the
- * owning ClassMetadata instance.
- *
- * @author Roman Borschel
- * @author Giorgio Sironi
- * @since 2.0
- * @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
- */
-class OneToManyMapping extends AssociationMapping
-{
- /**
- * READ-ONLY: Whether to delete orphaned elements (removed from the collection)
- *
- * @var boolean
- */
- public $orphanRemoval = false;
-
- /** FUTURE: The key column mapping, if any. The key column holds the keys of the Collection. */
- //public $keyColumn;
-
- /**
- * READ-ONLY: Order this collection by the given SQL snippet.
- */
- public $orderBy;
-
- /**
- * Validates and completes the mapping.
- *
- * @param array $mapping The mapping to validate and complete.
- * @return array The validated and completed mapping.
- * @override
- */
- protected function _validateAndCompleteMapping(array $mapping)
- {
- parent::_validateAndCompleteMapping($mapping);
-
- // OneToMany-side MUST be inverse (must have mappedBy)
- if ( ! isset($mapping['mappedBy'])) {
- throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']);
- }
-
- //TODO: if orphanRemoval, cascade=remove is implicit!
- $this->orphanRemoval = isset($mapping['orphanRemoval']) ?
- (bool) $mapping['orphanRemoval'] : false;
-
- if (isset($mapping['orderBy'])) {
- if (!is_array($mapping['orderBy'])) {
- throw new \InvalidArgumentException("'orderBy' is expected to be an array, not ".gettype($mapping['orderBy']));
- }
- $this->orderBy = $mapping['orderBy'];
- }
- }
-
- /**
- * Whether orphaned elements (removed from the collection) should be deleted.
- *
- * @return boolean TRUE if orphaned elements should be deleted, FALSE otherwise.
- */
- public function shouldDeleteOrphans()
- {
- return $this->deleteOrphans;
- }
-
- /**
- * {@inheritdoc}
- */
- public function isOneToMany()
- {
- return true;
- }
-
- /**
- * Loads a one-to-many collection.
- *
- * @param $sourceEntity The entity that owns the collection.
- * @param $targetCollection The collection to load/fill.
- * @param $em The EntityManager to use.
- * @param $joinColumnValues
- * @return void
- * @todo Remove
- */
- public function load($sourceEntity, $targetCollection, $em, array $joinColumnValues = array())
- {
- $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadOneToManyCollection($this, $sourceEntity, $targetCollection);
- }
-
- /**
- * Determines which fields get serialized.
- *
- * It is only serialized what is necessary for best unserialization performance.
- * That means any metadata properties that are not set or empty or simply have
- * their default value are NOT serialized.
- *
- * @return array The names of all the fields that should be serialized.
- */
- public function __sleep()
- {
- $serialized = parent::__sleep();
- if ($this->orderBy) {
- $serialized[] = 'orderBy';
- }
- if ($this->orphanRemoval) {
- $serialized[] = 'orphanRemoval';
- }
- return $serialized;
- }
-}
diff --git a/lib/Doctrine/ORM/Mapping/OneToOneMapping.php b/lib/Doctrine/ORM/Mapping/OneToOneMapping.php
deleted file mode 100644
index 918228060..000000000
--- a/lib/Doctrine/ORM/Mapping/OneToOneMapping.php
+++ /dev/null
@@ -1,165 +0,0 @@
-.
- */
-
-namespace Doctrine\ORM\Mapping;
-
-/**
- * A one-to-one mapping describes a uni-directional mapping from one entity
- * to another entity.
- *
- * IMPORTANT NOTE:
- *
- * The fields of this class are only public for 2 reasons:
- * 1) To allow fast READ access.
- * 2) To drastically reduce the size of a serialized instance (private/protected members
- * get the whole class name, namespace inclusive, prepended to every property in
- * the serialized representation).
- *
- * Instances of this class are stored serialized in the metadata cache together with the
- * owning ClassMetadata instance.
- *
- * @since 2.0
- * @author Roman Borschel
- * @author Giorgio Sironi
- * @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
- */
-class OneToOneMapping extends AssociationMapping
-{
- /**
- * READ-ONLY: Maps the source foreign/primary key columns to the target primary/foreign key columns.
- * i.e. source.id (pk) => target.user_id (fk).
- * Reverse mapping of _targetToSourceKeyColumns.
- */
- public $sourceToTargetKeyColumns = array();
-
- /**
- * READ-ONLY: Maps the target primary/foreign key columns to the source foreign/primary key columns.
- * i.e. target.user_id (fk) => source.id (pk).
- * Reverse mapping of _sourceToTargetKeyColumns.
- */
- public $targetToSourceKeyColumns = array();
-
- /**
- * READ-ONLY: Whether to delete orphaned elements (when nulled out, i.e. $foo->other = null)
- *
- * @var boolean
- */
- public $orphanRemoval = false;
-
- /**
- * READ-ONLY: The join column definitions. Only present on the owning side.
- *
- * @var array
- */
- public $joinColumns = array();
-
- /**
- * READ-ONLY: A map of join column names to field names that are used in cases
- * when the join columns are fetched as part of the query result.
- *
- * @var array
- */
- public $joinColumnFieldNames = array();
-
- /**
- * {@inheritdoc}
- *
- * @param array $mapping The mapping to validate & complete.
- * @return array The validated & completed mapping.
- * @override
- */
- protected function _validateAndCompleteMapping(array $mapping)
- {
- parent::_validateAndCompleteMapping($mapping);
-
- if (isset($mapping['joinColumns']) && $mapping['joinColumns']) {
- $this->isOwningSide = true;
- }
-
- if ($this->isOwningSide) {
- if ( ! isset($mapping['joinColumns']) || ! $mapping['joinColumns']) {
- // Apply default join column
- $mapping['joinColumns'] = array(array(
- 'name' => $this->sourceFieldName . '_id',
- 'referencedColumnName' => 'id'
- ));
- }
- foreach ($mapping['joinColumns'] as $joinColumn) {
- $this->sourceToTargetKeyColumns[$joinColumn['name']] = $joinColumn['referencedColumnName'];
- $this->joinColumnFieldNames[$joinColumn['name']] = isset($joinColumn['fieldName'])
- ? $joinColumn['fieldName'] : $joinColumn['name'];
- }
- $this->joinColumns = $mapping['joinColumns'];
- $this->targetToSourceKeyColumns = array_flip($this->sourceToTargetKeyColumns);
- }
-
- //TODO: if orphanRemoval, cascade=remove is implicit!
- $this->orphanRemoval = isset($mapping['orphanRemoval']) ?
- (bool) $mapping['orphanRemoval'] : false;
-
- return $mapping;
- }
-
- /**
- * {@inheritdoc}
- *
- * @return boolean
- * @override
- */
- public function isOneToOne()
- {
- return true;
- }
-
- /**
- * {@inheritdoc}
- *
- * @param object $sourceEntity the entity source of this association
- * @param object $targetEntity the entity to load data in
- * @param EntityManager $em
- * @param array $joinColumnValues Values of the join columns of $sourceEntity.
- * @todo Remove
- */
- public function load($sourceEntity, $targetEntity, $em, array $joinColumnValues = array())
- {
- return $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadOneToOneEntity($this, $sourceEntity, $targetEntity, $joinColumnValues);
- }
-
- /**
- * Determines which fields get serialized.
- *
- * It is only serialized what is necessary for best unserialization performance.
- * That means any metadata properties that are not set or empty or simply have
- * their default value are NOT serialized.
- *
- * @return array The names of all the fields that should be serialized.
- */
- public function __sleep()
- {
- $serialized = parent::__sleep();
- $serialized[] = 'joinColumns';
- $serialized[] = 'joinColumnFieldNames';
- $serialized[] = 'sourceToTargetKeyColumns';
- $serialized[] = 'targetToSourceKeyColumns';
- if ($this->orphanRemoval) {
- $serialized[] = 'orphanRemoval';
- }
- return $serialized;
- }
-}
diff --git a/lib/Doctrine/ORM/PersistentCollection.php b/lib/Doctrine/ORM/PersistentCollection.php
index c2e4207b7..34437d570 100644
--- a/lib/Doctrine/ORM/PersistentCollection.php
+++ b/lib/Doctrine/ORM/PersistentCollection.php
@@ -19,7 +19,7 @@
namespace Doctrine\ORM;
-use Doctrine\ORM\Mapping\AssociationMapping,
+use Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\Common\Collections\Collection,
Closure;
@@ -127,11 +127,11 @@ final class PersistentCollection implements Collection
* @param object $entity
* @param AssociationMapping $assoc
*/
- public function setOwner($entity, AssociationMapping $assoc)
+ public function setOwner($entity, array $assoc)
{
$this->owner = $entity;
$this->association = $assoc;
- $this->backRefFieldName = $assoc->inversedBy ?: $assoc->mappedBy;
+ $this->backRefFieldName = $assoc['inversedBy'] ?: $assoc['mappedBy'];
}
/**
@@ -162,7 +162,7 @@ final class PersistentCollection implements Collection
$this->coll->add($element);
// If _backRefFieldName is set and its a one-to-many association,
// we need to set the back reference.
- if ($this->backRefFieldName && $this->association->isOneToMany()) {
+ if ($this->backRefFieldName && $this->association['type'] == ClassMetadata::ONE_TO_MANY) {
// Set back reference to owner
$this->typeClass->reflFields[$this->backRefFieldName]
->setValue($element, $this->owner);
@@ -185,7 +185,7 @@ final class PersistentCollection implements Collection
$this->coll->set($key, $element);
// If _backRefFieldName is set, then the association is bidirectional
// and we need to set the back reference.
- if ($this->backRefFieldName && $this->association->isOneToMany()) {
+ if ($this->backRefFieldName && $this->association['type'] == ClassMetadata::ONE_TO_MANY) {
// Set back reference to owner
$this->typeClass->reflFields[$this->backRefFieldName]
->setValue($element, $this->owner);
@@ -204,7 +204,7 @@ final class PersistentCollection implements Collection
$newObjects = $this->coll->toArray();
}
$this->coll->clear();
- $this->association->load($this->owner, $this, $this->em);
+ $this->em->getUnitOfWork()->loadCollection($this);
$this->takeSnapshot();
// Reattach NEW objects added through add(), if any.
if (isset($newObjects)) {
@@ -279,7 +279,7 @@ final class PersistentCollection implements Collection
{
if ( ! $this->isDirty) {
$this->isDirty = true;
- if ($this->association !== null && $this->association->isOwningSide && $this->association->isManyToMany() &&
+ if ($this->association !== null && $this->association['isOwningSide'] && $this->association['type'] == ClassMetadata::MANY_TO_MANY &&
$this->em->getClassMetadata(get_class($this->owner))->isChangeTrackingNotify()) {
$this->em->getUnitOfWork()->scheduleForDirtyCheck($this->owner);
}
@@ -354,8 +354,8 @@ final class PersistentCollection implements Collection
$removed = $this->coll->remove($key);
if ($removed) {
$this->changed();
- if ($this->association !== null && $this->association->isOneToMany() &&
- $this->association->orphanRemoval) {
+ if ($this->association !== null && $this->association['type'] == ClassMetadata::ONE_TO_MANY &&
+ $this->association['orphanRemoval']) {
$this->em->getUnitOfWork()->scheduleOrphanRemoval($removed);
}
}
@@ -379,9 +379,15 @@ final class PersistentCollection implements Collection
}*/
$this->initialize();
- $result = $this->coll->removeElement($element);
- $this->changed();
- return $result;
+ $removed = $this->coll->removeElement($element);
+ if ($removed) {
+ $this->changed();
+ if ($this->association !== null && $this->association['type'] == ClassMetadata::ONE_TO_MANY &&
+ $this->association['orphanRemoval']) {
+ $this->em->getUnitOfWork()->scheduleOrphanRemoval($element);
+ }
+ }
+ return $removed;
}
/**
@@ -564,13 +570,13 @@ final class PersistentCollection implements Collection
if ($this->initialized && $this->isEmpty()) {
return;
}
- if ($this->association->isOneToMany() && $this->association->orphanRemoval) {
+ if ($this->association['type'] == ClassMetadata::ONE_TO_MANY && $this->association['orphanRemoval']) {
foreach ($this->coll as $element) {
$this->em->getUnitOfWork()->scheduleOrphanRemoval($element);
}
}
$this->coll->clear();
- if ($this->association->isOwningSide) {
+ if ($this->association['isOwningSide']) {
$this->changed();
$this->em->getUnitOfWork()->scheduleCollectionDeletion($this);
$this->takeSnapshot();
diff --git a/lib/Doctrine/ORM/Persisters/AbstractCollectionPersister.php b/lib/Doctrine/ORM/Persisters/AbstractCollectionPersister.php
index b3195f13d..489bb82fc 100644
--- a/lib/Doctrine/ORM/Persisters/AbstractCollectionPersister.php
+++ b/lib/Doctrine/ORM/Persisters/AbstractCollectionPersister.php
@@ -64,7 +64,8 @@ abstract class AbstractCollectionPersister
*/
public function delete(PersistentCollection $coll)
{
- if ( ! $coll->getMapping()->isOwningSide) {
+ $mapping = $coll->getMapping();
+ if ( ! $mapping['isOwningSide']) {
return; // ignore inverse side
}
$sql = $this->_getDeleteSQL($coll);
@@ -94,7 +95,8 @@ abstract class AbstractCollectionPersister
*/
public function update(PersistentCollection $coll)
{
- if ( ! $coll->getMapping()->isOwningSide) {
+ $mapping = $coll->getMapping();
+ if ( ! $mapping['isOwningSide']) {
return; // ignore inverse side
}
$this->deleteRows($coll);
diff --git a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php
index c2a1f4b63..8b0a38c4f 100644
--- a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php
+++ b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php
@@ -28,10 +28,7 @@ use PDO,
Doctrine\ORM\Query,
Doctrine\ORM\PersistentCollection,
Doctrine\ORM\Mapping\MappingException,
- Doctrine\ORM\Mapping\ClassMetadata,
- Doctrine\ORM\Mapping\OneToOneMapping,
- Doctrine\ORM\Mapping\OneToManyMapping,
- Doctrine\ORM\Mapping\ManyToManyMapping;
+ Doctrine\ORM\Mapping\ClassMetadata;
/**
* A BasicEntityPersiter maps an entity to a single table in a relational database.
@@ -342,32 +339,31 @@ class BasicEntityPersister
*/
protected function deleteJoinTableRecords($identifier)
{
- foreach ($this->_class->associationMappings AS $mapping) {
- /* @var $mapping \Doctrine\ORM\Mapping\AssociationMapping */
- if ($mapping->isManyToMany()) {
+ foreach ($this->_class->associationMappings as $mapping) {
+ if ($mapping['type'] == ClassMetadata::MANY_TO_MANY) {
// @Todo this only covers scenarios with no inheritance or of the same level. Is there something
// like self-referential relationship between different levels of an inheritance hierachy? I hope not!
- $selfReferential = ($mapping->targetEntityName == $mapping->sourceEntityName);
+ $selfReferential = ($mapping['targetEntity'] == $mapping['sourceEntity']);
- if (!$mapping->isOwningSide) {
- $relatedClass = $this->_em->getClassMetadata($mapping->targetEntityName);
- $mapping = $relatedClass->associationMappings[$mapping->mappedBy];
- $keys = array_keys($mapping->relationToTargetKeyColumns);
+ if ( ! $mapping['isOwningSide']) {
+ $relatedClass = $this->_em->getClassMetadata($mapping['targetEntity']);
+ $mapping = $relatedClass->associationMappings[$mapping['mappedBy']];
+ $keys = array_keys($mapping['relationToTargetKeyColumns']);
if ($selfReferential) {
- $otherKeys = array_keys($mapping->relationToSourceKeyColumns);
+ $otherKeys = array_keys($mapping['relationToSourceKeyColumns']);
}
} else {
- $keys = array_keys($mapping->relationToSourceKeyColumns);
+ $keys = array_keys($mapping['relationToSourceKeyColumns']);
if ($selfReferential) {
- $otherKeys = array_keys($mapping->relationToTargetKeyColumns);
+ $otherKeys = array_keys($mapping['relationToTargetKeyColumns']);
}
}
- if(!$mapping->isOnDeleteCascade) {
- $this->_conn->delete($mapping->joinTable['name'], array_combine($keys, $identifier));
+ if ( ! isset($mapping['isOnDeleteCascade'])) {
+ $this->_conn->delete($mapping['joinTable']['name'], array_combine($keys, $identifier));
if ($selfReferential) {
- $this->_conn->delete($mapping->joinTable['name'], array_combine($otherKeys, $identifier));
+ $this->_conn->delete($mapping['joinTable']['name'], array_combine($otherKeys, $identifier));
}
}
}
@@ -443,7 +439,7 @@ class BasicEntityPersister
if (isset($this->_class->associationMappings[$field])) {
$assoc = $this->_class->associationMappings[$field];
// Only owning side of x-1 associations can have a FK column.
- if ( ! $assoc->isOwningSide || ! $assoc->isOneToOne()) {
+ if ( ! $assoc['isOwningSide'] || ! ($assoc['type'] & ClassMetadata::TO_ONE)) {
continue;
}
@@ -464,10 +460,10 @@ class BasicEntityPersister
$newValId = $uow->getEntityIdentifier($newVal);
}
- $targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
+ $targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
$owningTable = $this->getOwningTable($field);
- foreach ($assoc->sourceToTargetKeyColumns as $sourceColumn => $targetColumn) {
+ foreach ($assoc['sourceToTargetKeyColumns'] as $sourceColumn => $targetColumn) {
if ($newVal === null) {
$result[$owningTable][$sourceColumn] = null;
} else {
@@ -540,7 +536,7 @@ class BasicEntityPersister
* Loads an entity of this persister's mapped class as part of a single-valued
* association from another entity.
*
- * @param OneToOneMapping $assoc The association to load.
+ * @param array $assoc The association to load.
* @param object $sourceEntity The entity that owns the association (not necessarily the "owning side").
* @param object $targetEntity The existing ghost entity (proxy) to load, if any.
* @param array $identifier The identifier of the entity to load. Must be provided if
@@ -548,21 +544,21 @@ class BasicEntityPersister
* the identifier is derived from the $sourceEntity.
* @return object The loaded and managed entity instance or NULL if the entity can not be found.
*/
- public function loadOneToOneEntity(OneToOneMapping $assoc, $sourceEntity, $targetEntity, array $identifier = array())
+ public function loadOneToOneEntity(array $assoc, $sourceEntity, $targetEntity, array $identifier = array())
{
- $targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
+ $targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
- if ($assoc->isOwningSide) {
- $isInverseSingleValued = $assoc->inversedBy && ! $targetClass->isCollectionValuedAssociation($assoc->inversedBy);
+ if ($assoc['isOwningSide']) {
+ $isInverseSingleValued = $assoc['inversedBy'] && ! $targetClass->isCollectionValuedAssociation($assoc['inversedBy']);
// Mark inverse side as fetched in the hints, otherwise the UoW would
// try to load it in a separate query (remember: to-one inverse sides can not be lazy).
$hints = array();
if ($isInverseSingleValued) {
- $hints['fetched'][$targetClass->name][$assoc->inversedBy] = true;
+ $hints['fetched'][$targetClass->name][$assoc['inversedBy']] = true;
if ($targetClass->subClasses) {
foreach ($targetClass->subClasses as $targetSubclassName) {
- $hints['fetched'][$targetSubclassName][$assoc->inversedBy] = true;
+ $hints['fetched'][$targetSubclassName][$assoc['inversedBy']] = true;
}
}
}
@@ -576,13 +572,13 @@ class BasicEntityPersister
// Complete bidirectional association, if necessary
if ($targetEntity !== null && $isInverseSingleValued) {
- $targetClass->reflFields[$assoc->inversedBy]->setValue($targetEntity, $sourceEntity);
+ $targetClass->reflFields[$assoc['inversedBy']]->setValue($targetEntity, $sourceEntity);
}
} else {
- $sourceClass = $this->_em->getClassMetadata($assoc->sourceEntityName);
- $owningAssoc = $targetClass->getAssociationMapping($assoc->mappedBy);
+ $sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
+ $owningAssoc = $targetClass->getAssociationMapping($assoc['mappedBy']);
// TRICKY: since the association is specular source and target are flipped
- foreach ($owningAssoc->targetToSourceKeyColumns as $sourceKeyColumn => $targetKeyColumn) {
+ foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$identifier[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else {
@@ -595,7 +591,7 @@ class BasicEntityPersister
$targetEntity = $this->load($identifier, $targetEntity, $assoc);
if ($targetEntity !== null) {
- $targetClass->setFieldValue($targetEntity, $assoc->mappedBy, $sourceEntity);
+ $targetClass->setFieldValue($targetEntity, $assoc['mappedBy'], $sourceEntity);
}
}
@@ -635,14 +631,14 @@ class BasicEntityPersister
// Refresh associations
foreach ($this->_class->associationMappings as $field => $assoc) {
$value = $this->_class->reflFields[$field]->getValue($entity);
- if ($assoc->isOneToOne()) {
+ if ($assoc['type'] & ClassMetadata::TO_ONE) {
if ($value instanceof Proxy && ! $value->__isInitialized__) {
continue; // skip uninitialized proxies
}
- if ($assoc->isOwningSide) {
+ if ($assoc['isOwningSide']) {
$joinColumnValues = array();
- foreach ($assoc->targetToSourceKeyColumns as $targetColumn => $srcColumn) {
+ foreach ($assoc['targetToSourceKeyColumns'] as $targetColumn => $srcColumn) {
if ($metaColumns[$srcColumn] !== null) {
$joinColumnValues[$targetColumn] = $metaColumns[$srcColumn];
}
@@ -653,18 +649,18 @@ class BasicEntityPersister
} else if ($value !== null) {
// Check identity map first, if the entity is not there,
// place a proxy in there instead.
- $targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
+ $targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
if ($found = $this->_em->getUnitOfWork()->tryGetById($joinColumnValues, $targetClass->rootEntityName)) {
$this->_class->reflFields[$field]->setValue($entity, $found);
// Complete inverse side, if necessary.
- if ($assoc->inversedBy) {
- $inverseAssoc = $targetClass->associationMappings[$assoc->inversedBy];
- $targetClass->reflFields[$inverseAssoc->sourceFieldName]->setValue($found, $entity);
+ if ($assoc['inversedBy']) {
+ $inverseAssoc = $targetClass->associationMappings[$assoc['inversedBy']];
+ $targetClass->reflFields[$inverseAssoc['fieldName']]->setValue($found, $entity);
}
$newData[$field] = $found;
} else {
// FIXME: What is happening with subClassees here?
- $proxy = $this->_em->getProxyFactory()->getProxy($assoc->targetEntityName, $joinColumnValues);
+ $proxy = $this->_em->getProxyFactory()->getProxy($assoc['targetEntity'], $joinColumnValues);
$this->_class->reflFields[$field]->setValue($entity, $proxy);
$newData[$field] = $proxy;
$this->_em->getUnitOfWork()->registerManaged($proxy, $joinColumnValues, array());
@@ -672,7 +668,9 @@ class BasicEntityPersister
}
} else {
// Inverse side of 1-1/1-x can never be lazy.
- $newData[$field] = $assoc->load($entity, null, $this->_em);
+ //$newData[$field] = $assoc->load($entity, null, $this->_em);
+ $newData[$field] = $this->_em->getUnitOfWork()->getEntityPersister($assoc['targetEntity'])
+ ->loadOneToOneEntity($assoc, $entity, null);
}
} else if ($value instanceof PersistentCollection && $value->isInitialized()) {
$value->setInitialized(false);
@@ -711,13 +709,13 @@ class BasicEntityPersister
* @param object $sourceEntity The entity that owns the collection.
* @param PersistentCollection $coll The collection to fill.
*/
- public function loadManyToManyCollection(ManyToManyMapping $assoc, $sourceEntity, PersistentCollection $coll)
+ public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
{
$criteria = array();
- $sourceClass = $this->_em->getClassMetadata($assoc->sourceEntityName);
+ $sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
$joinTableConditions = array();
- if ($assoc->isOwningSide) {
- foreach ($assoc->relationToSourceKeyColumns as $relationKeyColumn => $sourceKeyColumn) {
+ if ($assoc['isOwningSide']) {
+ foreach ($assoc['relationToSourceKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$criteria[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else {
@@ -727,9 +725,9 @@ class BasicEntityPersister
}
}
} else {
- $owningAssoc = $this->_em->getClassMetadata($assoc->targetEntityName)->associationMappings[$assoc->mappedBy];
+ $owningAssoc = $this->_em->getClassMetadata($assoc['targetEntity'])->associationMappings[$assoc['mappedBy']];
// TRICKY: since the association is inverted source and target are flipped
- foreach ($owningAssoc->relationToTargetKeyColumns as $relationKeyColumn => $sourceKeyColumn) {
+ foreach ($owningAssoc['relationToTargetKeyColumns'] as $relationKeyColumn => $sourceKeyColumn) {
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
$criteria[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
} else {
@@ -826,13 +824,13 @@ class BasicEntityPersister
*/
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0)
{
- $joinSql = $assoc != null && $assoc->isManyToMany() ?
+ $joinSql = $assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY ?
$this->_getSelectManyToManyJoinSQL($assoc) : '';
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
- $orderBySql = $assoc !== null && isset($assoc->orderBy) ?
- $this->_getCollectionOrderBySQL($assoc->orderBy, $this->_getSQLTableAlias($this->_class->name))
+ $orderBySql = $assoc !== null && isset($assoc['orderBy']) ?
+ $this->_getCollectionOrderBySQL($assoc['orderBy'], $this->_getSQLTableAlias($this->_class->name))
: '';
$lockSql = '';
@@ -917,17 +915,17 @@ class BasicEntityPersister
* @param ManyToManyMapping $manyToMany
* @return string
*/
- protected function _getSelectManyToManyJoinSQL(ManyToManyMapping $manyToMany)
+ protected function _getSelectManyToManyJoinSQL(array $manyToMany)
{
- if ($manyToMany->isOwningSide) {
+ if ($manyToMany['isOwningSide']) {
$owningAssoc = $manyToMany;
- $joinClauses = $manyToMany->relationToTargetKeyColumns;
+ $joinClauses = $manyToMany['relationToTargetKeyColumns'];
} else {
- $owningAssoc = $this->_em->getClassMetadata($manyToMany->targetEntityName)->associationMappings[$manyToMany->mappedBy];
- $joinClauses = $owningAssoc->relationToSourceKeyColumns;
+ $owningAssoc = $this->_em->getClassMetadata($manyToMany['targetEntity'])->associationMappings[$manyToMany['mappedBy']];
+ $joinClauses = $owningAssoc['relationToSourceKeyColumns'];
}
- $joinTableName = $owningAssoc->getQuotedJoinTableName($this->_platform);
+ $joinTableName = $this->_class->getQuotedJoinTableName($owningAssoc, $this->_platform);
$joinSql = '';
foreach ($joinClauses as $joinTableColumn => $sourceColumn) {
@@ -985,8 +983,8 @@ class BasicEntityPersister
}
if (isset($this->_class->associationMappings[$name])) {
$assoc = $this->_class->associationMappings[$name];
- if ($assoc->isOwningSide && $assoc->isOneToOne()) {
- foreach ($assoc->targetToSourceKeyColumns as $sourceCol) {
+ if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
+ foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) {
$columns[] = $sourceCol;
}
}
@@ -1030,8 +1028,8 @@ class BasicEntityPersister
{
$sql = '';
foreach ($class->associationMappings as $assoc) {
- if ($assoc->isOwningSide && $assoc->isOneToOne()) {
- foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
+ if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
+ foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
$sql .= ', ' . $this->_getSQLTableAlias($this->_class->name) . ".$srcColumn AS $columnAlias";
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
@@ -1127,12 +1125,12 @@ class BasicEntityPersister
// TODO: Composite Keys as Foreign Key PK? That would be super ugly! And should probably be disallowed ;)
$conditionSql .= $this->_getSQLTableAlias($this->_class->name) . '.';
- $conditionSql .= $this->_class->associationMappings[$field]->joinColumns[0]['name'];
+ $conditionSql .= $this->_class->associationMappings[$field]['joinColumns'][0]['name'];
} else if ($assoc !== null) {
- if ($assoc->isManyToMany()) {
- $owningAssoc = $assoc->isOwningSide ? $assoc : $this->_em->getClassMetadata($assoc->targetEntityName)
- ->associationMappings[$assoc->mappedBy];
- $conditionSql .= $owningAssoc->getQuotedJoinTableName($this->_platform) . '.' . $field;
+ if ($assoc['type'] == ClassMetadata::MANY_TO_MANY) {
+ $owningAssoc = $assoc['isOwningSide'] ? $assoc : $this->_em->getClassMetadata($assoc['targetEntity'])
+ ->associationMappings[$assoc['mappedBy']];
+ $conditionSql .= $this->_class->getQuotedJoinTableName($owningAssoc, $this->_platform) . '.' . $field;
} else {
$conditionSql .= $field;
}
@@ -1151,12 +1149,12 @@ class BasicEntityPersister
* @param array $criteria The criteria by which to select the entities.
* @param PersistentCollection The collection to load/fill.
*/
- public function loadOneToManyCollection(OneToManyMapping $assoc, $sourceEntity, PersistentCollection $coll)
+ public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
{
$criteria = array();
- $owningAssoc = $this->_class->associationMappings[$assoc->mappedBy];
- $sourceClass = $this->_em->getClassMetadata($assoc->sourceEntityName);
- foreach ($owningAssoc->targetToSourceKeyColumns as $sourceKeyColumn => $targetKeyColumn) {
+ $owningAssoc = $this->_class->associationMappings[$assoc['mappedBy']];
+ $sourceClass = $this->_em->getClassMetadata($assoc['sourceEntity']);
+ foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
$criteria[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
}
diff --git a/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php b/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php
index dc7d802a2..357497bb2 100644
--- a/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php
+++ b/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php
@@ -20,7 +20,7 @@
namespace Doctrine\ORM\Persisters;
use Doctrine\ORM\ORMException,
- Doctrine\ORM\Mapping\ManyToManyMapping;
+ Doctrine\ORM\Mapping\ClassMetadata;
/**
* The joined subclass persister maps a single entity instance to several tables in the
@@ -75,9 +75,9 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
public function getOwningTable($fieldName)
{
if ( ! isset($this->_owningTableMap[$fieldName])) {
- if (isset($this->_class->associationMappings[$fieldName]->inherited)) {
+ if (isset($this->_class->associationMappings[$fieldName]['inherited'])) {
$this->_owningTableMap[$fieldName] = $this->_em->getClassMetadata(
- $this->_class->associationMappings[$fieldName]->inherited
+ $this->_class->associationMappings[$fieldName]['inherited']
)->table['name'];
} else if (isset($this->_class->fieldMappings[$fieldName]['inherited'])) {
$this->_owningTableMap[$fieldName] = $this->_em->getClassMetadata(
@@ -247,11 +247,11 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// Add foreign key columns
foreach ($this->_class->associationMappings as $assoc2) {
- if ($assoc2->isOwningSide && $assoc2->isOneToOne()) {
- $tableAlias = $assoc2->inherited ?
- $this->_getSQLTableAlias($assoc2->inherited)
+ if ($assoc2['isOwningSide'] && $assoc2['type'] & ClassMetadata::TO_ONE) {
+ $tableAlias = isset($assoc2['inherited']) ?
+ $this->_getSQLTableAlias($assoc2['inherited'])
: $baseTableAlias;
- foreach ($assoc2->targetToSourceKeyColumns as $srcColumn) {
+ foreach ($assoc2['targetToSourceKeyColumns'] as $srcColumn) {
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
$columnList .= ", $tableAlias.$srcColumn AS $columnAlias";
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
@@ -304,8 +304,9 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// Add join columns (foreign keys)
foreach ($subClass->associationMappings as $assoc2) {
- if ($assoc2->isOwningSide && $assoc2->isOneToOne() && ! $assoc2->inherited) {
- foreach ($assoc2->targetToSourceKeyColumns as $srcColumn) {
+ if ($assoc2['isOwningSide'] && $assoc2['type'] & ClassMetadata::TO_ONE
+ && ! isset($assoc2['inherited'])) {
+ foreach ($assoc2['targetToSourceKeyColumns'] as $srcColumn) {
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
$columnList .= ', ' . $tableAlias . ".$srcColumn AS $columnAlias";
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
@@ -326,14 +327,14 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
}
- $joinSql .= $assoc != null && $assoc->isManyToMany() ?
+ $joinSql .= $assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY ?
$this->_getSelectManyToManyJoinSQL($assoc) : '';
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
$orderBySql = '';
- if ($assoc != null && isset($assoc->orderBy)) {
- $orderBySql = $this->_getCollectionOrderBySQL($assoc->orderBy, $baseTableAlias);
+ if ($assoc != null && isset($assoc['orderBy'])) {
+ $orderBySql = $this->_getCollectionOrderBySQL($assoc['orderBy'], $baseTableAlias);
}
if ($this->_selectColumnListSql === null) {
@@ -385,15 +386,15 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
foreach ($this->_class->reflFields as $name => $field) {
if (isset($this->_class->fieldMappings[$name]['inherited']) && ! isset($this->_class->fieldMappings[$name]['id'])
- || isset($this->_class->associationMappings[$name]->inherited)
+ || isset($this->_class->associationMappings[$name]['inherited'])
|| ($this->_class->isVersioned && $this->_class->versionField == $name)) {
continue;
}
if (isset($this->_class->associationMappings[$name])) {
$assoc = $this->_class->associationMappings[$name];
- if ($assoc->isOneToOne() && $assoc->isOwningSide) {
- foreach ($assoc->targetToSourceKeyColumns as $sourceCol) {
+ if ($assoc['type'] & ClassMetadata::TO_ONE && $assoc['isOwningSide']) {
+ foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) {
$columns[] = $sourceCol;
}
}
diff --git a/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php b/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php
index a182a9859..27e9a57fd 100644
--- a/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php
+++ b/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php
@@ -39,8 +39,8 @@ class ManyToManyPersister extends AbstractCollectionPersister
protected function _getDeleteRowSQL(PersistentCollection $coll)
{
$mapping = $coll->getMapping();
- $joinTable = $mapping->joinTable;
- $columns = $mapping->joinTableColumns;
+ $joinTable = $mapping['joinTable'];
+ $columns = $mapping['joinTableColumns'];
return 'DELETE FROM ' . $joinTable['name'] . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?';
}
@@ -74,8 +74,8 @@ class ManyToManyPersister extends AbstractCollectionPersister
protected function _getInsertRowSQL(PersistentCollection $coll)
{
$mapping = $coll->getMapping();
- $joinTable = $mapping->joinTable;
- $columns = $mapping->joinTableColumns;
+ $joinTable = $mapping['joinTable'];
+ $columns = $mapping['joinTableColumns'];
return 'INSERT INTO ' . $joinTable['name'] . ' (' . implode(', ', $columns) . ')'
. ' VALUES (' . implode(', ', array_fill(0, count($columns), '?')) . ')';
}
@@ -104,7 +104,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
{
$params = array();
$mapping = $coll->getMapping();
- $isComposite = count($mapping->joinTableColumns) > 2;
+ $isComposite = count($mapping['joinTableColumns']) > 2;
$identifier1 = $this->_uow->getEntityIdentifier($coll->getOwner());
$identifier2 = $this->_uow->getEntityIdentifier($element);
@@ -114,16 +114,16 @@ class ManyToManyPersister extends AbstractCollectionPersister
$class2 = $coll->getTypeClass();
}
- foreach ($mapping->joinTableColumns as $joinTableColumn) {
- if (isset($mapping->relationToSourceKeyColumns[$joinTableColumn])) {
+ foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
+ if (isset($mapping['relationToSourceKeyColumns'][$joinTableColumn])) {
if ($isComposite) {
- $params[] = $identifier1[$class1->fieldNames[$mapping->relationToSourceKeyColumns[$joinTableColumn]]];
+ $params[] = $identifier1[$class1->fieldNames[$mapping['relationToSourceKeyColumns'][$joinTableColumn]]];
} else {
$params[] = array_pop($identifier1);
}
} else {
if ($isComposite) {
- $params[] = $identifier2[$class2->fieldNames[$mapping->relationToTargetKeyColumns[$joinTableColumn]]];
+ $params[] = $identifier2[$class2->fieldNames[$mapping['relationToTargetKeyColumns'][$joinTableColumn]]];
} else {
$params[] = array_pop($identifier2);
}
@@ -141,9 +141,9 @@ class ManyToManyPersister extends AbstractCollectionPersister
protected function _getDeleteSQL(PersistentCollection $coll)
{
$mapping = $coll->getMapping();
- $joinTable = $mapping->joinTable;
+ $joinTable = $mapping['joinTable'];
$whereClause = '';
- foreach ($mapping->relationToSourceKeyColumns as $relationColumn => $srcColumn) {
+ foreach ($mapping['relationToSourceKeyColumns'] as $relationColumn => $srcColumn) {
if ($whereClause !== '') $whereClause .= ' AND ';
$whereClause .= "$relationColumn = ?";
}
@@ -162,9 +162,9 @@ class ManyToManyPersister extends AbstractCollectionPersister
$params = array();
$mapping = $coll->getMapping();
$identifier = $this->_uow->getEntityIdentifier($coll->getOwner());
- if (count($mapping->relationToSourceKeyColumns) > 1) {
+ if (count($mapping['relationToSourceKeyColumns']) > 1) {
$sourceClass = $this->_em->getClassMetadata(get_class($mapping->getOwner()));
- foreach ($mapping->relationToSourceKeyColumns as $relColumn => $srcColumn) {
+ foreach ($mapping['relationToSourceKeyColumns'] as $relColumn => $srcColumn) {
$params[] = $identifier[$sourceClass->fieldNames[$srcColumn]];
}
} else {
diff --git a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
index efecd2a50..f0d3aeafd 100644
--- a/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
+++ b/lib/Doctrine/ORM/Persisters/OneToManyPersister.php
@@ -50,7 +50,7 @@ class OneToManyPersister extends AbstractCollectionPersister
$targetClass = $this->_em->getClassMetadata($mapping->getTargetEntityName());
$table = $targetClass->getTableName();
- $ownerMapping = $targetClass->getAssociationMapping($mapping->mappedBy);
+ $ownerMapping = $targetClass->getAssociationMapping($mapping['mappedBy']);
$setClause = '';
foreach ($ownerMapping->sourceToTargetKeyColumns as $sourceCol => $targetCol) {
diff --git a/lib/Doctrine/ORM/Persisters/SingleTablePersister.php b/lib/Doctrine/ORM/Persisters/SingleTablePersister.php
index ddeb1b108..856ff3485 100644
--- a/lib/Doctrine/ORM/Persisters/SingleTablePersister.php
+++ b/lib/Doctrine/ORM/Persisters/SingleTablePersister.php
@@ -61,8 +61,8 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
}
// Foreign key columns
foreach ($subClass->associationMappings as $assoc) {
- if ($assoc->isOwningSide && $assoc->isOneToOne() && ! $assoc->inherited) {
- foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
+ if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE && ! isset($assoc['inherited'])) {
+ foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
$columnList .= ', ' . $tableAlias . ".$srcColumn AS $columnAlias";
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
diff --git a/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php
index 9065276ba..601c4f804 100644
--- a/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php
+++ b/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php
@@ -51,18 +51,18 @@ class SizeFunction extends FunctionNode
$assoc = $class->associationMappings[$assocField];
$sql = 'SELECT COUNT(*) FROM ';
- if ($assoc->isOneToMany()) {
- $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc->targetEntityName);
+ if ($assoc['type'] == \Doctrine\ORM\Mapping\ClassMetadata::ONE_TO_MANY) {
+ $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']);
$targetTableAlias = $sqlWalker->getSqlTableAlias($targetClass->table['name']);
$sourceTableAlias = $sqlWalker->getSqlTableAlias($class->table['name'], $dqlAlias);
$sql .= $targetClass->getQuotedTableName($platform) . ' ' . $targetTableAlias . ' WHERE ';
- $owningAssoc = $targetClass->associationMappings[$assoc->mappedBy];
+ $owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']];
$first = true;
- foreach ($owningAssoc->targetToSourceKeyColumns as $targetColumn => $sourceColumn) {
+ foreach ($owningAssoc['targetToSourceKeyColumns'] as $targetColumn => $sourceColumn) {
if ($first) $first = false; else $sql .= ' AND ';
$sql .= $targetTableAlias . '.' . $sourceColumn
@@ -70,19 +70,19 @@ class SizeFunction extends FunctionNode
. $sourceTableAlias . '.' . $class->getQuotedColumnName($class->fieldNames[$targetColumn], $platform);
}
} else { // many-to-many
- $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc->targetEntityName);
+ $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']);
- $owningAssoc = $assoc->isOwningSide ? $assoc : $targetClass->associationMappings[$assoc->mappedBy];
- $joinTable = $owningAssoc->joinTable;
+ $owningAssoc = $assoc['isOwningSide'] ? $assoc : $targetClass->associationMappings[$assoc['mappedBy']];
+ $joinTable = $owningAssoc['joinTable'];
// SQL table aliases
$joinTableAlias = $sqlWalker->getSqlTableAlias($joinTable['name']);
$sourceTableAlias = $sqlWalker->getSqlTableAlias($class->table['name'], $dqlAlias);
// join to target table
- $sql .= $owningAssoc->getQuotedJoinTableName($platform) . ' ' . $joinTableAlias . ' WHERE ';
+ $sql .= $targetClass->getQuotedJoinTableName($owningAssoc, $platform) . ' ' . $joinTableAlias . ' WHERE ';
- $joinColumns = $assoc->isOwningSide
+ $joinColumns = $assoc['isOwningSide']
? $joinTable['joinColumns']
: $joinTable['inverseJoinColumns'];
diff --git a/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php b/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php
index 62d8b314a..7298db976 100644
--- a/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php
+++ b/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php
@@ -86,7 +86,7 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
foreach ($updateItems as $updateItem) {
$field = $updateItem->pathExpression->field;
if (isset($class->fieldMappings[$field]) && ! isset($class->fieldMappings[$field]['inherited']) ||
- isset($class->associationMappings[$field]) && ! $class->associationMappings[$field]->inherited) {
+ isset($class->associationMappings[$field]) && ! isset($class->associationMappings[$field]['inherited'])) {
$newValue = $updateItem->newValue;
if ( ! $affected) {
diff --git a/lib/Doctrine/ORM/Query/Lexer.php b/lib/Doctrine/ORM/Query/Lexer.php
index 7026f6616..57ffc3ebe 100644
--- a/lib/Doctrine/ORM/Query/Lexer.php
+++ b/lib/Doctrine/ORM/Query/Lexer.php
@@ -119,7 +119,7 @@ class Lexer extends \Doctrine\Common\Lexer
protected function getCatchablePatterns()
{
return array(
- '[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]+)?',
"'(?:[^']|'')*'",
'\?[1-9][0-9]*|:[a-z][a-z0-9_]+'
diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php
index 21a86862d..2a2fa70cd 100644
--- a/lib/Doctrine/ORM/Query/Parser.php
+++ b/lib/Doctrine/ORM/Query/Parser.php
@@ -20,6 +20,7 @@
namespace Doctrine\ORM\Query;
use Doctrine\ORM\Query;
+use Doctrine\ORM\Mapping\ClassMetadata;
/**
* An LL(*) recursive-descent parser for the context-free grammar of the Doctrine Query Language.
@@ -581,9 +582,9 @@ class Parser
$fieldType = AST\PathExpression::TYPE_STATE_FIELD;
} else {
$assoc = $class->associationMappings[$field];
- $class = $this->_em->getClassMetadata($assoc->targetEntityName);
+ $class = $this->_em->getClassMetadata($assoc['targetEntity']);
- if ($assoc->isOneToOne()) {
+ if ($assoc['type'] & ClassMetadata::TO_ONE) {
$fieldType = AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION;
} else {
$fieldType = AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION;
@@ -765,7 +766,7 @@ class Parser
{
$this->match(Lexer::T_IDENTIFIER);
- $schemaName = $this->_lexer->token['value'];
+ $schemaName = ltrim($this->_lexer->token['value'], '\\');
if (strrpos($schemaName, ':') !== false) {
list($namespaceAlias, $simpleClassName) = explode(':', $schemaName);
@@ -1478,7 +1479,7 @@ class Parser
);
}
- $targetClassName = $parentClass->getAssociationMapping($assocField)->targetEntityName;
+ $targetClassName = $parentClass->associationMappings[$assocField]['targetEntity'];
// Building queryComponent
$joinQueryComponent = array(
diff --git a/lib/Doctrine/ORM/Query/QueryException.php b/lib/Doctrine/ORM/Query/QueryException.php
index 9969e28b5..f9dfd0823 100644
--- a/lib/Doctrine/ORM/Query/QueryException.php
+++ b/lib/Doctrine/ORM/Query/QueryException.php
@@ -91,7 +91,7 @@ class QueryException extends \Doctrine\ORM\ORMException
{
return new self(
"Invalid query operation: Not allowed to iterate over fetch join collections ".
- "in class ".$assoc->sourceEntityName." assocation ".$assoc->sourceFieldName
+ "in class ".$assoc['sourceEntity']." assocation ".$assoc['fieldName']
);
}
@@ -108,7 +108,7 @@ class QueryException extends \Doctrine\ORM\ORMException
{
return new self(
"Unsupported query operation: It is not yet possible to overwrite the join ".
- "conditions in class ".$assoc->sourceEntityName." assocation ".$assoc->sourceFieldName.". ".
+ "conditions in class ".$assoc['sourceEntityName']." assocation ".$assoc['fieldName'].". ".
"Use WITH to append additional join conditions to the association."
);
}
@@ -123,8 +123,8 @@ class QueryException extends \Doctrine\ORM\ORMException
public static function iterateWithFetchJoinNotAllowed($assoc) {
return new self(
- "Iterate with fetch join in class " . $assoc->sourceEntityName .
- " using association " . $assoc->sourceFieldName . " not allowed."
+ "Iterate with fetch join in class " . $assoc['sourceEntity'] .
+ " using association " . $assoc['fieldName'] . " not allowed."
);
}
diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php
index d30941884..baaafcf77 100644
--- a/lib/Doctrine/ORM/Query/SqlWalker.php
+++ b/lib/Doctrine/ORM/Query/SqlWalker.php
@@ -20,6 +20,7 @@
namespace Doctrine\ORM\Query;
use Doctrine\DBAL\LockMode,
+ Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\ORM\Query,
Doctrine\ORM\Query\QueryException;
@@ -287,8 +288,8 @@ class SqlWalker implements TreeWalker
$sql = '';
foreach ($this->_selectedClasses AS $dqlAlias => $class) {
$qComp = $this->_queryComponents[$dqlAlias];
- if (isset($qComp['relation']->orderBy)) {
- foreach ($qComp['relation']->orderBy AS $fieldName => $orientation) {
+ if (isset($qComp['relation']['orderBy'])) {
+ foreach ($qComp['relation']['orderBy'] AS $fieldName => $orientation) {
if ($qComp['metadata']->isInheritanceTypeJoined()) {
$tableName = $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName);
} else {
@@ -484,15 +485,15 @@ class SqlWalker implements TreeWalker
$dqlAlias = $pathExpr->identificationVariable;
$class = $this->_queryComponents[$dqlAlias]['metadata'];
- if (isset($class->associationMappings[$fieldName]->inherited)) {
- $class = $this->_em->getClassMetadata($class->associationMappings[$fieldName]->inherited);
+ if (isset($class->associationMappings[$fieldName]['inherited'])) {
+ $class = $this->_em->getClassMetadata($class->associationMappings[$fieldName]['inherited']);
}
$assoc = $class->associationMappings[$fieldName];
- if ($assoc->isOwningSide) {
+ if ($assoc['isOwningSide']) {
// COMPOSITE KEYS NOT (YET?) SUPPORTED
- if (count($assoc->sourceToTargetKeyColumns) > 1) {
+ if (count($assoc['sourceToTargetKeyColumns']) > 1) {
throw QueryException::associationPathCompositeKeyNotSupported();
}
@@ -500,7 +501,7 @@ class SqlWalker implements TreeWalker
$sql .= $this->getSqlTableAlias($class->table['name'], $dqlAlias) . '.';
}
- $sql .= reset($assoc->targetToSourceKeyColumns);
+ $sql .= reset($assoc['targetToSourceKeyColumns']);
} else {
throw QueryException::associationPathInverseSideNotSupported();
}
@@ -539,7 +540,7 @@ class SqlWalker implements TreeWalker
$this->_rsm->addJoinedEntityResult(
$class->name, $dqlAlias,
$this->_queryComponents[$dqlAlias]['parent'],
- $this->_queryComponents[$dqlAlias]['relation']->sourceFieldName
+ $this->_queryComponents[$dqlAlias]['relation']['fieldName']
);
}
@@ -559,15 +560,15 @@ class SqlWalker implements TreeWalker
if ($addMetaColumns) {
//FIXME: Include foreign key columns of child classes also!!??
foreach ($class->associationMappings as $assoc) {
- if ($assoc->isOwningSide && $assoc->isOneToOne()) {
- if ($assoc->inherited) {
- $owningClass = $this->_em->getClassMetadata($assoc->inherited);
+ if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
+ if (isset($assoc['inherited'])) {
+ $owningClass = $this->_em->getClassMetadata($assoc['inherited']);
$sqlTableAlias = $this->getSqlTableAlias($owningClass->table['name'], $dqlAlias);
} else {
$sqlTableAlias = $this->getSqlTableAlias($class->table['name'], $dqlAlias);
}
- foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
+ foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
$columnAlias = $this->getSqlColumnAlias($srcColumn);
$sql .= ", $sqlTableAlias." . $srcColumn . ' AS ' . $columnAlias;
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
@@ -581,8 +582,8 @@ class SqlWalker implements TreeWalker
if ($addMetaColumns) {
$sqlTableAlias = $this->getSqlTableAlias($class->table['name'], $dqlAlias);
foreach ($class->associationMappings as $assoc) {
- if ($assoc->isOwningSide && $assoc->isOneToOne()) {
- foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
+ if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
+ foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
$columnAlias = $this->getSqlColumnAlias($srcColumn);
$sql .= ', ' . $sqlTableAlias . '.' . $srcColumn . ' AS ' . $columnAlias;
$columnAlias = $this->_platform->getSQLResultCasing($columnAlias);
@@ -722,29 +723,29 @@ class SqlWalker implements TreeWalker
$joinAssocPathExpr = $join->joinAssociationPathExpression;
$joinedDqlAlias = $join->aliasIdentificationVariable;
$relation = $this->_queryComponents[$joinedDqlAlias]['relation'];
- $targetClass = $this->_em->getClassMetadata($relation->targetEntityName);
- $sourceClass = $this->_em->getClassMetadata($relation->sourceEntityName);
+ $targetClass = $this->_em->getClassMetadata($relation['targetEntity']);
+ $sourceClass = $this->_em->getClassMetadata($relation['sourceEntity']);
$targetTableName = $targetClass->getQuotedTableName($this->_platform);
$targetTableAlias = $this->getSqlTableAlias($targetClass->table['name'], $joinedDqlAlias);
$sourceTableAlias = $this->getSqlTableAlias($sourceClass->table['name'], $joinAssocPathExpr->identificationVariable);
// Ensure we got the owning side, since it has all mapping info
- $assoc = ( ! $relation->isOwningSide) ? $targetClass->associationMappings[$relation->mappedBy] : $relation;
+ $assoc = ( ! $relation['isOwningSide']) ? $targetClass->associationMappings[$relation['mappedBy']] : $relation;
if ($this->_query->getHint(Query::HINT_INTERNAL_ITERATION) == true) {
- if ($relation->isOneToMany() || $relation->isManyToMany()) {
+ if ($relation['type'] == ClassMetadata::ONE_TO_MANY || $relation['type'] == ClassMetadata::MANY_TO_MANY) {
throw QueryException::iterateWithFetchJoinNotAllowed($assoc);
}
}
- if ($assoc->isOneToOne()) {
+ if ($assoc['type'] & ClassMetadata::TO_ONE) {
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ';
$first = true;
- foreach ($assoc->sourceToTargetKeyColumns as $sourceColumn => $targetColumn) {
+ foreach ($assoc['sourceToTargetKeyColumns'] as $sourceColumn => $targetColumn) {
if ( ! $first) $sql .= ' AND '; else $first = false;
- if ($relation->isOwningSide) {
+ if ($relation['isOwningSide']) {
$quotedTargetColumn = $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform);
$sql .= $sourceTableAlias . '.' . $sourceColumn
. ' = '
@@ -756,15 +757,15 @@ class SqlWalker implements TreeWalker
. $targetTableAlias . '.' . $sourceColumn;
}
}
- } else if ($assoc->isManyToMany()) {
+ } else if ($assoc['type'] == ClassMetadata::MANY_TO_MANY) {
// Join relation table
- $joinTable = $assoc->joinTable;
+ $joinTable = $assoc['joinTable'];
$joinTableAlias = $this->getSqlTableAlias($joinTable['name'], $joinedDqlAlias);
- $sql .= $assoc->getQuotedJoinTableName($this->_platform) . ' ' . $joinTableAlias . ' ON ';
+ $sql .= $sourceClass->getQuotedJoinTableName($assoc, $this->_platform) . ' ' . $joinTableAlias . ' ON ';
$first = true;
- if ($relation->isOwningSide) {
- foreach ($assoc->relationToSourceKeyColumns as $relationColumn => $sourceColumn) {
+ if ($relation['isOwningSide']) {
+ foreach ($assoc['relationToSourceKeyColumns'] as $relationColumn => $sourceColumn) {
if ( ! $first) $sql .= ' AND '; else $first = false;
$sql .= $sourceTableAlias . '.' . $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$sourceColumn], $this->_platform)
@@ -772,7 +773,7 @@ class SqlWalker implements TreeWalker
. $joinTableAlias . '.' . $relationColumn;
}
} else {
- foreach ($assoc->relationToTargetKeyColumns as $relationColumn => $targetColumn) {
+ foreach ($assoc['relationToTargetKeyColumns'] as $relationColumn => $targetColumn) {
if ( ! $first) $sql .= ' AND '; else $first = false;
$sql .= $sourceTableAlias . '.' . $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$targetColumn], $this->_platform)
@@ -787,8 +788,8 @@ class SqlWalker implements TreeWalker
$sql .= $targetTableName . ' ' . $targetTableAlias . ' ON ';
$first = true;
- if ($relation->isOwningSide) {
- foreach ($assoc->relationToTargetKeyColumns as $relationColumn => $targetColumn) {
+ if ($relation['isOwningSide']) {
+ foreach ($assoc['relationToTargetKeyColumns'] as $relationColumn => $targetColumn) {
if ( ! $first) $sql .= ' AND '; else $first = false;
$sql .= $targetTableAlias . '.' . $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform)
@@ -796,7 +797,7 @@ class SqlWalker implements TreeWalker
. $joinTableAlias . '.' . $relationColumn;
}
} else {
- foreach ($assoc->relationToSourceKeyColumns as $relationColumn => $sourceColumn) {
+ foreach ($assoc['relationToSourceKeyColumns'] as $relationColumn => $sourceColumn) {
if ( ! $first) $sql .= ' AND '; else $first = false;
$sql .= $targetTableAlias . '.' . $targetClass->getQuotedColumnName($targetClass->fieldNames[$sourceColumn], $this->_platform)
@@ -995,8 +996,8 @@ class SqlWalker implements TreeWalker
// Add join columns (foreign keys) of the subclass
//TODO: Probably better do this in walkSelectClause to honor the INCLUDE_META_COLUMNS hint
foreach ($subClass->associationMappings as $fieldName => $assoc) {
- if ($assoc->isOwningSide && $assoc->isOneToOne() && ! $assoc->inherited) {
- foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
+ if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE && ! isset($assoc['inherited'])) {
+ foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
if ($beginning) $beginning = false; else $sql .= ', ';
$columnAlias = $this->getSqlColumnAlias($srcColumn);
$sql .= $sqlTableAlias . '.' . $srcColumn . ' AS ' . $columnAlias;
@@ -1359,19 +1360,19 @@ class SqlWalker implements TreeWalker
$assoc = $class->associationMappings[$fieldName];
- if ($assoc->isOneToMany()) {
- $targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
+ if ($assoc['type'] == ClassMetadata::ONE_TO_MANY) {
+ $targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
$targetTableAlias = $this->getSqlTableAlias($targetClass->table['name']);
$sourceTableAlias = $this->getSqlTableAlias($class->table['name'], $dqlAlias);
$sql .= $targetClass->getQuotedTableName($this->_platform)
. ' ' . $targetTableAlias . ' WHERE ';
- $owningAssoc = $targetClass->associationMappings[$assoc->mappedBy];
+ $owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']];
$first = true;
- foreach ($owningAssoc->targetToSourceKeyColumns as $targetColumn => $sourceColumn) {
+ foreach ($owningAssoc['targetToSourceKeyColumns'] as $targetColumn => $sourceColumn) {
if ($first) $first = false; else $sql .= ' AND ';
$sql .= $sourceTableAlias . '.' . $class->getQuotedColumnName($class->fieldNames[$targetColumn], $this->_platform)
@@ -1390,24 +1391,24 @@ class SqlWalker implements TreeWalker
. $targetClass->getQuotedColumnName($idField, $this->_platform) . ' = ?';
}
} else { // many-to-many
- $targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
-
- $owningAssoc = $assoc->isOwningSide ? $assoc : $targetClass->associationMappings[$assoc->mappedBy];
- $joinTable = $owningAssoc->joinTable;
+ $targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
+ $owningAssoc = $assoc['isOwningSide'] ? $assoc : $targetClass->associationMappings[$assoc['mappedBy']];
+ $joinTable = $owningAssoc['joinTable'];
+
// SQL table aliases
$joinTableAlias = $this->getSqlTableAlias($joinTable['name']);
$targetTableAlias = $this->getSqlTableAlias($targetClass->table['name']);
$sourceTableAlias = $this->getSqlTableAlias($class->table['name'], $dqlAlias);
// join to target table
- $sql .= $owningAssoc->getQuotedJoinTableName($this->_platform)
+ $sql .= $targetClass->getQuotedJoinTableName($owningAssoc, $this->_platform)
. ' ' . $joinTableAlias . ' INNER JOIN '
. $targetClass->getQuotedTableName($this->_platform)
. ' ' . $targetTableAlias . ' ON ';
// join conditions
- $joinColumns = $assoc->isOwningSide
+ $joinColumns = $assoc['isOwningSide']
? $joinTable['inverseJoinColumns']
: $joinTable['joinColumns'];
@@ -1423,7 +1424,7 @@ class SqlWalker implements TreeWalker
$sql .= ' WHERE ';
- $joinColumns = $assoc->isOwningSide
+ $joinColumns = $assoc['isOwningSide']
? $joinTable['joinColumns']
: $joinTable['inverseJoinColumns'];
diff --git a/lib/Doctrine/ORM/Tools/EntityGenerator.php b/lib/Doctrine/ORM/Tools/EntityGenerator.php
index 2af25891f..8e353bda9 100644
--- a/lib/Doctrine/ORM/Tools/EntityGenerator.php
+++ b/lib/Doctrine/ORM/Tools/EntityGenerator.php
@@ -379,7 +379,7 @@ public function ()
{
$refl = new \ReflectionClass($this->_getClassToExtend());
- return $refl->getShortName();
+ return $refl->getName();
}
private function _getClassToExtendNamespace()
@@ -505,34 +505,34 @@ public function ()
}
foreach ($metadata->associationMappings as $associationMapping) {
- if ($associationMapping instanceof \Doctrine\ORM\Mapping\OneToOneMapping) {
- if ($code = $this->_generateEntityStubMethod($metadata, 'set', $associationMapping->sourceFieldName, $associationMapping->targetEntityName)) {
+ if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) {
+ if ($code = $this->_generateEntityStubMethod($metadata, 'set', $associationMapping['fieldName'], $associationMapping['targetEntity'])) {
$methods[] = $code;
}
- if ($code = $this->_generateEntityStubMethod($metadata, 'get', $associationMapping->sourceFieldName, $associationMapping->targetEntityName)) {
+ if ($code = $this->_generateEntityStubMethod($metadata, 'get', $associationMapping['fieldName'], $associationMapping['targetEntity'])) {
$methods[] = $code;
}
- } else if ($associationMapping instanceof \Doctrine\ORM\Mapping\OneToManyMapping) {
+ } else if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) {
if ($associationMapping->isOwningSide) {
- if ($code = $this->_generateEntityStubMethod($metadata, 'set', $associationMapping->sourceFieldName, $associationMapping->targetEntityName)) {
+ if ($code = $this->_generateEntityStubMethod($metadata, 'set', $associationMapping['fieldName'], $associationMapping['targetEntity'])) {
$methods[] = $code;
}
- if ($code = $this->_generateEntityStubMethod($metadata, 'get', $associationMapping->sourceFieldName, $associationMapping->targetEntityName)) {
+ if ($code = $this->_generateEntityStubMethod($metadata, 'get', $associationMapping['fieldName'], $associationMapping['targetEntity'])) {
$methods[] = $code;
}
} else {
- if ($code = $this->_generateEntityStubMethod($metadata, 'add', $associationMapping->sourceFieldName, $associationMapping->targetEntityName)) {
+ if ($code = $this->_generateEntityStubMethod($metadata, 'add', $associationMapping['fieldName'], $associationMapping['targetEntity'])) {
$methods[] = $code;
}
- if ($code = $this->_generateEntityStubMethod($metadata, 'get', $associationMapping->sourceFieldName, 'Doctrine\Common\Collections\Collection')) {
+ if ($code = $this->_generateEntityStubMethod($metadata, 'get', $associationMapping['fieldName'], 'Doctrine\Common\Collections\Collection')) {
$methods[] = $code;
}
}
- } else if ($associationMapping instanceof \Doctrine\ORM\Mapping\ManyToManyMapping) {
- if ($code = $this->_generateEntityStubMethod($metadata, 'add', $associationMapping->sourceFieldName, $associationMapping->targetEntityName)) {
+ } else if ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) {
+ if ($code = $this->_generateEntityStubMethod($metadata, 'add', $associationMapping['fieldName'], $associationMapping['targetEntity'])) {
$methods[] = $code;
}
- if ($code = $this->_generateEntityStubMethod($metadata, 'get', $associationMapping->sourceFieldName, 'Doctrine\Common\Collections\Collection')) {
+ if ($code = $this->_generateEntityStubMethod($metadata, 'get', $associationMapping['fieldName'], 'Doctrine\Common\Collections\Collection')) {
$methods[] = $code;
}
}
@@ -563,13 +563,13 @@ public function ()
$lines = array();
foreach ($metadata->associationMappings as $associationMapping) {
- if ($this->_hasProperty($associationMapping->sourceFieldName, $metadata)) {
+ if ($this->_hasProperty($associationMapping['fieldName'], $metadata)) {
continue;
}
$lines[] = $this->_generateAssociationMappingPropertyDocBlock($associationMapping, $metadata);
- $lines[] = $this->_spaces . 'private $' . $associationMapping->sourceFieldName
- . ($associationMapping->isManyToMany() ? ' = array()' : null) . ";\n";
+ $lines[] = $this->_spaces . 'private $' . $associationMapping['fieldName']
+ . ($associationMapping['type'] == 'manyToMany' ? ' = array()' : null) . ";\n";
}
return implode("\n", $lines);
@@ -681,55 +681,68 @@ public function ()
return '@JoinColumn(' . implode(', ', $joinColumnAnnot) . ')';
}
- private function _generateAssociationMappingPropertyDocBlock(AssociationMapping $associationMapping, ClassMetadataInfo $metadata)
+ private function _generateAssociationMappingPropertyDocBlock(array $associationMapping, ClassMetadataInfo $metadata)
{
$lines = array();
$lines[] = $this->_spaces . '/**';
- $lines[] = $this->_spaces . ' * @var ' . $associationMapping->targetEntityName;
+ $lines[] = $this->_spaces . ' * @var ' . $associationMapping['targetEntity'];
if ($this->_generateAnnotations) {
$lines[] = $this->_spaces . ' *';
- $e = explode('\\', get_class($associationMapping));
- $type = str_replace('Mapping', '', end($e));
+ $type = null;
+ switch ($associationMapping['type']) {
+ case ClassMetadataInfo::ONE_TO_ONE:
+ $type = 'OneToOne';
+ break;
+ case ClassMetadataInfo::MANY_TO_ONE:
+ $type = 'ManyToOne';
+ break;
+ case ClassMetadataInfo::ONE_TO_MANY:
+ $type = 'OneToMany';
+ break;
+ case ClassMetadataInfo::MANY_TO_MANY:
+ $type = 'ManyToMany';
+ break;
+ }
$typeOptions = array();
- if (isset($associationMapping->targetEntityName)) {
- $typeOptions[] = 'targetEntity="' . $associationMapping->targetEntityName . '"';
+ if (isset($associationMapping['targetEntity'])) {
+ $typeOptions[] = 'targetEntity="' . $associationMapping['targetEntity'] . '"';
}
- if (isset($associationMapping->inversedBy)) {
- $typeOptions[] = 'inversedBy="' . $associationMapping->inversedBy . '"';
+ if (isset($associationMapping['inversedBy'])) {
+ $typeOptions[] = 'inversedBy="' . $associationMapping['inversedBy'] . '"';
}
- if (isset($associationMapping->mappedBy)) {
- $typeOptions[] = 'mappedBy="' . $associationMapping->mappedBy . '"';
+ if (isset($associationMapping['mappedBy'])) {
+ $typeOptions[] = 'mappedBy="' . $associationMapping['mappedBy'] . '"';
}
- if ($associationMapping->hasCascades()) {
+ if ($associationMapping['cascade']) {
$cascades = array();
- if ($associationMapping->isCascadePersist) $cascades[] = '"persist"';
- if ($associationMapping->isCascadeRemove) $cascades[] = '"remove"';
- if ($associationMapping->isCascadeDetach) $cascades[] = '"detach"';
- if ($associationMapping->isCascadeMerge) $cascades[] = '"merge"';
- if ($associationMapping->isCascadeRefresh) $cascades[] = '"refresh"';
+ if ($associationMapping['isCascadePersist']) $cascades[] = '"persist"';
+ if ($associationMapping['isCascadeRemove']) $cascades[] = '"remove"';
+ if ($associationMapping['isCascadeDetach']) $cascades[] = '"detach"';
+ if ($associationMapping['isCascadeMerge']) $cascades[] = '"merge"';
+ if ($associationMapping['isCascadeRefresh']) $cascades[] = '"refresh"';
$typeOptions[] = 'cascade={' . implode(',', $cascades) . '}';
}
- if (isset($associationMapping->orphanRemoval) && $associationMapping->orphanRemoval) {
- $typeOptions[] = 'orphanRemoval=' . ($associationMapping->orphanRemoval ? 'true' : 'false');
+ if (isset($associationMapping['orphanRemoval']) && $associationMapping['orphanRemoval']) {
+ $typeOptions[] = 'orphanRemoval=' . ($associationMapping['orphanRemoval'] ? 'true' : 'false');
}
$lines[] = $this->_spaces . ' * @' . $type . '(' . implode(', ', $typeOptions) . ')';
- if (isset($associationMapping->joinColumns) && $associationMapping->joinColumns) {
+ if (isset($associationMapping['joinColumns']) && $associationMapping['joinColumns']) {
$lines[] = $this->_spaces . ' * @JoinColumns({';
$joinColumnsLines = array();
- foreach ($associationMapping->joinColumns as $joinColumn) {
+ foreach ($associationMapping['joinColumns'] as $joinColumn) {
if ($joinColumnAnnot = $this->_generateJoinColumnAnnotation($joinColumn)) {
$joinColumnsLines[] = $this->_spaces . ' * ' . $joinColumnAnnot;
}
@@ -739,25 +752,25 @@ public function ()
$lines[] = $this->_spaces . ' * })';
}
- if (isset($associationMapping->joinTable) && $associationMapping->joinTable) {
+ if (isset($associationMapping['joinTable']) && $associationMapping['joinTable']) {
$joinTable = array();
- $joinTable[] = 'name="' . $associationMapping->joinTable['name'] . '"';
+ $joinTable[] = 'name="' . $associationMapping['joinTable']['name'] . '"';
- if (isset($associationMapping->joinTable['schema'])) {
- $joinTable[] = 'schema="' . $associationMapping->joinTable['schema'] . '"';
+ if (isset($associationMapping['joinTable']['schema'])) {
+ $joinTable[] = 'schema="' . $associationMapping['joinTable']['schema'] . '"';
}
$lines[] = $this->_spaces . ' * @JoinTable(' . implode(', ', $joinTable) . ',';
$lines[] = $this->_spaces . ' * joinColumns={';
- foreach ($associationMapping->joinTable['joinColumns'] as $joinColumn) {
+ foreach ($associationMapping['joinTable']['joinColumns'] as $joinColumn) {
$lines[] = $this->_spaces . ' * ' . $this->_generateJoinColumnAnnotation($joinColumn);
}
$lines[] = $this->_spaces . ' * },';
$lines[] = $this->_spaces . ' * inverseJoinColumns={';
- foreach ($associationMapping->joinTable['inverseJoinColumns'] as $joinColumn) {
+ foreach ($associationMapping['joinTable']['inverseJoinColumns'] as $joinColumn) {
$lines[] = $this->_spaces . ' * ' . $this->_generateJoinColumnAnnotation($joinColumn);
}
@@ -765,10 +778,10 @@ public function ()
$lines[] = $this->_spaces . ' * )';
}
- if (isset($associationMapping->orderBy)) {
+ if (isset($associationMapping['orderBy'])) {
$lines[] = $this->_spaces . ' * @OrderBy({';
- foreach ($associationMapping->orderBy as $name => $direction) {
+ foreach ($associationMapping['orderBy'] as $name => $direction) {
$lines[] = $this->_spaces . ' * "' . $name . '"="' . $direction . '",';
}
diff --git a/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php b/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php
index 831c28f4a..005b18a7a 100644
--- a/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php
+++ b/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php
@@ -99,41 +99,41 @@ class PhpExporter extends AbstractExporter
foreach ($metadata->associationMappings as $associationMapping) {
$cascade = array('remove', 'persist', 'refresh', 'merge', 'detach');
foreach ($cascade as $key => $value) {
- if ( ! $associationMapping->{'isCascade'.ucfirst($value)}) {
+ if ( ! $associationMapping['isCascade'.ucfirst($value)]) {
unset($cascade[$key]);
}
}
$associationMappingArray = array(
- 'fieldName' => $associationMapping->sourceFieldName,
- 'targetEntity' => $associationMapping->targetEntityName,
+ 'fieldName' => $associationMapping['fieldName'],
+ 'targetEntity' => $associationMapping['targetEntity'],
'cascade' => $cascade,
);
- if ($associationMapping instanceof \Doctrine\ORM\Mapping\OneToOneMapping) {
+ if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) {
$method = 'mapOneToOne';
$oneToOneMappingArray = array(
- 'mappedBy' => $associationMapping->mappedBy,
- 'inversedBy' => $associationMapping->inversedBy,
- 'joinColumns' => $associationMapping->joinColumns,
- 'orphanRemoval' => $associationMapping->orphanRemoval,
+ 'mappedBy' => $associationMapping['mappedBy'],
+ 'inversedBy' => $associationMapping['inversedBy'],
+ 'joinColumns' => $associationMapping['joinColumns'],
+ 'orphanRemoval' => $associationMapping['orphanRemoval'],
);
$associationMappingArray = array_merge($associationMappingArray, $oneToOneMappingArray);
- } else if ($associationMapping instanceof \Doctrine\ORM\Mapping\OneToManyMapping) {
+ } else if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) {
$method = 'mapOneToMany';
$oneToManyMappingArray = array(
- 'mappedBy' => $associationMapping->mappedBy,
- 'orphanRemoval' => $associationMapping->orphanRemoval,
- 'orderBy' => $associationMapping->orderBy
+ 'mappedBy' => $associationMapping['mappedBy'],
+ 'orphanRemoval' => $associationMapping['orphanRemoval'],
+ 'orderBy' => $associationMapping['orderBy']
);
$associationMappingArray = array_merge($associationMappingArray, $oneToManyMappingArray);
- } else if ($associationMapping instanceof \Doctrine\ORM\Mapping\ManyToManyMapping) {
+ } else if ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) {
$method = 'mapManyToMany';
$manyToManyMappingArray = array(
- 'mappedBy' => $associationMapping->mappedBy,
- 'joinTable' => $associationMapping->joinTable,
- 'orderBy' => $associationMapping->orderBy
+ 'mappedBy' => $associationMapping['mappedBy'],
+ 'joinTable' => $associationMapping['joinTable'],
+ 'orderBy' => $associationMapping['orderBy']
);
$associationMappingArray = array_merge($associationMappingArray, $manyToManyMappingArray);
diff --git a/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php b/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
index 63f28ffc9..097e77083 100644
--- a/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
+++ b/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
@@ -22,10 +22,7 @@
namespace Doctrine\ORM\Tools\Export\Driver;
-use Doctrine\ORM\Mapping\ClassMetadataInfo,
- Doctrine\ORM\Mapping\OneToOneMapping,
- Doctrine\ORM\Mapping\OneToManyMapping,
- Doctrine\ORM\Mapping\ManyToManyMapping;
+use Doctrine\ORM\Mapping\ClassMetadataInfo;
/**
* ClassMetadata exporter for Doctrine XML mapping files
@@ -182,31 +179,33 @@ class XmlExporter extends AbstractExporter
}
foreach ($metadata->associationMappings as $name => $associationMapping) {
- if ($associationMapping instanceof OneToOneMapping) {
+ if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_ONE) {
$associationMappingXml = $root->addChild('one-to-one');
- } else if ($associationMapping instanceof OneToManyMapping) {
+ } else if ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_ONE) {
+ $associationMappingXml = $root->addChild('many-to-one');
+ } else if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) {
$associationMappingXml = $root->addChild('one-to-many');
- } else if ($associationMapping instanceof ManyToManyMapping) {
+ } else if ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) {
$associationMappingXml = $root->addChild('many-to-many');
}
- $associationMappingXml->addAttribute('field', $associationMapping->sourceFieldName);
- $associationMappingXml->addAttribute('target-entity', $associationMapping->targetEntityName);
+ $associationMappingXml->addAttribute('field', $associationMapping['fieldName']);
+ $associationMappingXml->addAttribute('target-entity', $associationMapping['targetEntity']);
- if (isset($associationMapping->mappedBy)) {
- $associationMappingXml->addAttribute('mapped-by', $associationMapping->mappedBy);
+ if (isset($associationMapping['mappedBy'])) {
+ $associationMappingXml->addAttribute('mapped-by', $associationMapping['mappedBy']);
}
- if (isset($associationMapping->inversedBy)) {
- $associationMappingXml->addAttribute('inversed-by', $associationMapping->inversedBy);
+ if (isset($associationMapping['inversedBy'])) {
+ $associationMappingXml->addAttribute('inversed-by', $associationMapping['inversedBy']);
}
- if (isset($associationMapping->orphanRemoval)) {
- $associationMappingXml->addAttribute('orphan-removal', $associationMapping->orphanRemoval);
+ if (isset($associationMapping['orphanRemoval'])) {
+ $associationMappingXml->addAttribute('orphan-removal', $associationMapping['orphanRemoval']);
}
- if (isset($associationMapping->joinTable) && $associationMapping->joinTable) {
+ if (isset($associationMapping['joinTable']) && $associationMapping['joinTable']) {
$joinTableXml = $associationMappingXml->addChild('join-table');
- $joinTableXml->addAttribute('name', $associationMapping->joinTable['name']);
+ $joinTableXml->addAttribute('name', $associationMapping['joinTable']['name']);
$joinColumnsXml = $joinTableXml->addChild('join-columns');
- foreach ($associationMapping->joinTable['joinColumns'] as $joinColumn) {
+ foreach ($associationMapping['joinTable']['joinColumns'] as $joinColumn) {
$joinColumnXml = $joinColumnsXml->addChild('join-column');
$joinColumnXml->addAttribute('name', $joinColumn['name']);
$joinColumnXml->addAttribute('referenced-column-name', $joinColumn['referencedColumnName']);
@@ -218,7 +217,7 @@ class XmlExporter extends AbstractExporter
}
}
$inverseJoinColumnsXml = $joinTableXml->addChild('inverse-join-columns');
- foreach ($associationMapping->joinTable['inverseJoinColumns'] as $inverseJoinColumn) {
+ foreach ($associationMapping['joinTable']['inverseJoinColumns'] as $inverseJoinColumn) {
$inverseJoinColumnXml = $inverseJoinColumnsXml->addChild('join-column');
$inverseJoinColumnXml->addAttribute('name', $inverseJoinColumn['name']);
$inverseJoinColumnXml->addAttribute('referenced-column-name', $inverseJoinColumn['referencedColumnName']);
@@ -239,9 +238,9 @@ class XmlExporter extends AbstractExporter
}
}
}
- if (isset($associationMapping->joinColumns)) {
+ if (isset($associationMapping['joinColumns'])) {
$joinColumnsXml = $associationMappingXml->addChild('join-columns');
- foreach ($associationMapping->joinColumns as $joinColumn) {
+ foreach ($associationMapping['joinColumns'] as $joinColumn) {
$joinColumnXml = $joinColumnsXml->addChild('join-column');
$joinColumnXml->addAttribute('name', $joinColumn['name']);
$joinColumnXml->addAttribute('referenced-column-name', $joinColumn['referencedColumnName']);
@@ -259,28 +258,28 @@ class XmlExporter extends AbstractExporter
}
}
}
- if (isset($associationMapping->orderBy)) {
+ if (isset($associationMapping['orderBy'])) {
$orderByXml = $associationMappingXml->addChild('order-by');
- foreach ($associationMapping->orderBy as $name => $direction) {
+ foreach ($associationMapping['orderBy'] as $name => $direction) {
$orderByFieldXml = $orderByXml->addChild('order-by-field');
$orderByFieldXml->addAttribute('name', $name);
$orderByFieldXml->addAttribute('direction', $direction);
}
}
$cascade = array();
- if ($associationMapping->isCascadeRemove) {
+ if ($associationMapping['isCascadeRemove']) {
$cascade[] = 'cascade-remove';
}
- if ($associationMapping->isCascadePersist) {
+ if ($associationMapping['isCascadePersist']) {
$cascade[] = 'cascade-persist';
}
- if ($associationMapping->isCascadeRefresh) {
+ if ($associationMapping['isCascadeRefresh']) {
$cascade[] = 'cascade-refresh';
}
- if ($associationMapping->isCascadeMerge) {
+ if ($associationMapping['isCascadeMerge']) {
$cascade[] = 'cascade-merge';
}
- if ($associationMapping->isCascadeDetach) {
+ if ($associationMapping['isCascadeDetach']) {
$cascade[] = 'cascade-detach';
}
if ($cascade) {
diff --git a/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php b/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php
index 13094a1d9..28414cdbd 100644
--- a/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php
+++ b/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php
@@ -22,10 +22,7 @@
namespace Doctrine\ORM\Tools\Export\Driver;
-use Doctrine\ORM\Mapping\ClassMetadataInfo,
- Doctrine\ORM\Mapping\OneToOneMapping,
- Doctrine\ORM\Mapping\OneToManyMapping,
- Doctrine\ORM\Mapping\ManyToManyMapping;
+use Doctrine\ORM\Mapping\ClassMetadataInfo;
/**
* ClassMetadata exporter for Doctrine YAML mapping files
@@ -134,28 +131,28 @@ class YamlExporter extends AbstractExporter
$associations = array();
foreach ($metadata->associationMappings as $name => $associationMapping) {
$cascade = array();
- if ($associationMapping->isCascadeRemove) {
+ if ($associationMapping['isCascadeRemove']) {
$cascade[] = 'remove';
}
- if ($associationMapping->isCascadePersist) {
+ if ($associationMapping['isCascadePersist']) {
$cascade[] = 'persist';
}
- if ($associationMapping->isCascadeRefresh) {
+ if ($associationMapping['isCascadeRefresh']) {
$cascade[] = 'refresh';
}
- if ($associationMapping->isCascadeMerge) {
+ if ($associationMapping['isCascadeMerge']) {
$cascade[] = 'merge';
}
- if ($associationMapping->isCascadeDetach) {
+ if ($associationMapping['isCascadeDetach']) {
$cascade[] = 'detach';
}
$associationMappingArray = array(
- 'targetEntity' => $associationMapping->targetEntityName,
+ 'targetEntity' => $associationMapping['targetEntity'],
'cascade' => $cascade,
);
- if ($associationMapping instanceof OneToOneMapping) {
- $joinColumns = $associationMapping->joinColumns;
+ if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) {
+ $joinColumns = $associationMapping['joinColumns'];
$newJoinColumns = array();
foreach ($joinColumns as $joinColumn) {
$newJoinColumns[$joinColumn['name']]['referencedColumnName'] = $joinColumn['referencedColumnName'];
@@ -167,30 +164,30 @@ class YamlExporter extends AbstractExporter
}
}
$oneToOneMappingArray = array(
- 'mappedBy' => $associationMapping->mappedBy,
- 'inversedBy' => $associationMapping->inversedBy,
+ 'mappedBy' => $associationMapping['mappedBy'],
+ 'inversedBy' => $associationMapping['inversedBy'],
'joinColumns' => $newJoinColumns,
- 'orphanRemoval' => $associationMapping->orphanRemoval,
+ 'orphanRemoval' => $associationMapping['orphanRemoval'],
);
$associationMappingArray = array_merge($associationMappingArray, $oneToOneMappingArray);
$array['oneToOne'][$name] = $associationMappingArray;
- } else if ($associationMapping instanceof OneToManyMapping) {
+ } else if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) {
$oneToManyMappingArray = array(
- 'mappedBy' => $associationMapping->mappedBy,
- 'inversedBy' => $associationMapping->inversedBy,
- 'orphanRemoval' => $associationMapping->orphanRemoval,
- 'orderBy' => $associationMapping->orderBy
+ 'mappedBy' => $associationMapping['mappedBy'],
+ 'inversedBy' => $associationMapping['inversedBy'],
+ 'orphanRemoval' => $associationMapping['orphanRemoval'],
+ 'orderBy' => $associationMapping['orderBy']
);
$associationMappingArray = array_merge($associationMappingArray, $oneToManyMappingArray);
$array['oneToMany'][$name] = $associationMappingArray;
- } else if ($associationMapping instanceof ManyToManyMapping) {
+ } else if ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) {
$manyToManyMappingArray = array(
- 'mappedBy' => $associationMapping->mappedBy,
- 'inversedBy' => $associationMapping->inversedBy,
- 'joinTable' => $associationMapping->joinTable,
- 'orderBy' => $associationMapping->orderBy
+ 'mappedBy' => $associationMapping['mappedBy'],
+ 'inversedBy' => $associationMapping['inversedBy'],
+ 'joinTable' => $associationMapping['joinTable'],
+ 'orderBy' => isset($associationMapping['orderBy']) ? $associationMapping['orderBy'] : null
);
$associationMappingArray = array_merge($associationMappingArray, $manyToManyMappingArray);
diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php
index e53311c4a..f7851ee46 100644
--- a/lib/Doctrine/ORM/Tools/SchemaTool.php
+++ b/lib/Doctrine/ORM/Tools/SchemaTool.php
@@ -24,6 +24,7 @@ namespace Doctrine\ORM\Tools;
use Doctrine\ORM\ORMException,
Doctrine\DBAL\Types\Type,
Doctrine\ORM\EntityManager,
+ Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\ORM\Internal\CommitOrderCalculator,
Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs,
Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
@@ -200,7 +201,7 @@ class SchemaTool
} else if (isset($class->associationMappings[$identifierField])) {
/* @var $assoc \Doctrine\ORM\Mapping\OneToOne */
$assoc = $class->associationMappings[$identifierField];
- foreach ($assoc->joinColumns AS $joinColumn) {
+ foreach ($assoc['joinColumns'] AS $joinColumn) {
$pkColumns[] = $joinColumn['name'];
}
}
@@ -370,24 +371,28 @@ class SchemaTool
private function _gatherRelationsSql($class, $table, $schema)
{
foreach ($class->associationMappings as $fieldName => $mapping) {
- if ($mapping->inherited) {
+ if (isset($mapping['inherited'])) {
continue;
}
- $foreignClass = $this->_em->getClassMetadata($mapping->targetEntityName);
+ $foreignClass = $this->_em->getClassMetadata($mapping['targetEntity']);
- if ($mapping->isOneToOne() && $mapping->isOwningSide) {
- $primaryKeyColumns = $uniqueConstraints = array(); // unnecessary for this relation-type
+ if ($mapping['type'] & ClassMetadata::TO_ONE && $mapping['isOwningSide']) {
+ $primaryKeyColumns = $uniqueConstraints = array(); // PK is unnecessary for this relation-type
- $this->_gatherRelationJoinColumns($mapping->joinColumns, $table, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints);
- } else if ($mapping->isOneToMany() && $mapping->isOwningSide) {
+ $this->_gatherRelationJoinColumns($mapping['joinColumns'], $table, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints);
+
+ foreach($uniqueConstraints AS $indexName => $unique) {
+ $table->addUniqueIndex($unique['columns'], is_numeric($indexName) ? null : $indexName);
+ }
+ } else if ($mapping['type'] == ClassMetadata::ONE_TO_MANY && $mapping['isOwningSide']) {
//... create join table, one-many through join table supported later
throw ORMException::notSupported();
- } else if ($mapping->isManyToMany() && $mapping->isOwningSide) {
+ } else if ($mapping['type'] == ClassMetadata::MANY_TO_MANY && $mapping['isOwningSide']) {
// create join table
- $joinTable = $mapping->joinTable;
+ $joinTable = $mapping['joinTable'];
- $theJoinTable = $schema->createTable($mapping->getQuotedJoinTableName($this->_platform));
+ $theJoinTable = $schema->createTable($foreignClass->getQuotedJoinTableName($mapping, $this->_platform));
$primaryKeyColumns = $uniqueConstraints = array();
@@ -397,13 +402,11 @@ class SchemaTool
// Build second FK constraint (relation table => target table)
$this->_gatherRelationJoinColumns($joinTable['inverseJoinColumns'], $theJoinTable, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints);
- foreach($uniqueConstraints AS $indexName => $unique) {
- $theJoinTable->addUniqueIndex(
- $unique['columns'], is_numeric($indexName) ? null : $indexName
- );
- }
-
$theJoinTable->setPrimaryKey($primaryKeyColumns);
+
+ foreach($uniqueConstraints AS $indexName => $unique) {
+ $theJoinTable->addUniqueIndex($unique['columns'], is_numeric($indexName) ? null : $indexName);
+ }
}
}
}
@@ -431,7 +434,7 @@ class SchemaTool
if ( ! $class->hasField($referencedFieldName)) {
throw new \Doctrine\ORM\ORMException(
"Column name `".$joinColumn['referencedColumnName']."` referenced for relation from ".
- "$mapping->sourceEntityName towards $mapping->targetEntityName does not exist."
+ $mapping['sourceEntity'] . " towards ". $mapping['targetEntity'] . " does not exist."
);
}
@@ -619,8 +622,8 @@ class SchemaTool
$calc->addClass($class);
foreach ($class->associationMappings as $assoc) {
- if ($assoc->isOwningSide) {
- $targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
+ if ($assoc['isOwningSide']) {
+ $targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
if ( ! $calc->hasClass($targetClass->name)) {
$calc->addClass($targetClass);
@@ -641,7 +644,7 @@ class SchemaTool
foreach ($classes as $class) {
foreach ($class->associationMappings as $assoc) {
- if ($assoc->isOwningSide && $assoc->isManyToMany()) {
+ if ($assoc['isOwningSide'] && $assoc['type'] == ClassMetadata::MANY_TO_MANY) {
$associationTables[] = $assoc->joinTable['name'];
}
}
diff --git a/lib/Doctrine/ORM/Tools/SchemaValidator.php b/lib/Doctrine/ORM/Tools/SchemaValidator.php
index d109832a9..8acaa0b54 100644
--- a/lib/Doctrine/ORM/Tools/SchemaValidator.php
+++ b/lib/Doctrine/ORM/Tools/SchemaValidator.php
@@ -20,8 +20,7 @@
namespace Doctrine\ORM\Tools;
use Doctrine\ORM\EntityManager;
-use Doctrine\ORM\Mapping\ManyToManyMapping;
-use Doctrine\ORM\Mapping\OneToOneMapping;
+use Doctrine\ORM\Mapping\ClassMetadataInfo;
/**
* Performs strict validation of the mapping schema
@@ -73,60 +72,60 @@ class SchemaValidator
$ce = array();
/* @var $class ClassMetadata */
foreach ($class->associationMappings AS $fieldName => $assoc) {
- if (!$cmf->hasMetadataFor($assoc->targetEntityName)) {
- $ce[] = "The target entity '" . $assoc->targetEntityName . "' specified on " . $class->name . '#' . $fieldName . ' is unknown.';
+ if (!$cmf->hasMetadataFor($assoc['targetEntity'])) {
+ $ce[] = "The target entity '" . $assoc['targetEntity'] . "' specified on " . $class->name . '#' . $fieldName . ' is unknown.';
}
- if ($assoc->mappedBy && $assoc->inversedBy) {
+ if ($assoc['mappedBy'] && $assoc['inversedBy']) {
$ce[] = "The association " . $class . "#" . $fieldName . " cannot be defined as both inverse and owning.";
}
- $targetMetadata = $cmf->getMetadataFor($assoc->targetEntityName);
+ $targetMetadata = $cmf->getMetadataFor($assoc['targetEntity']);
/* @var $assoc AssociationMapping */
- if ($assoc->mappedBy) {
- if ($targetMetadata->hasField($assoc->mappedBy)) {
+ if ($assoc['mappedBy']) {
+ if ($targetMetadata->hasField($assoc['mappedBy'])) {
$ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the owning side ".
- "field " . $assoc->targetEntityName . "#" . $assoc->mappedBy . " which is not defined as association.";
+ "field " . $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " which is not defined as association.";
}
- if (!$targetMetadata->hasAssociation($assoc->mappedBy)) {
+ if (!$targetMetadata->hasAssociation($assoc['mappedBy'])) {
$ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the owning side ".
- "field " . $assoc->targetEntityName . "#" . $assoc->mappedBy . " which does not exist.";
- } else if ($targetMetadata->associationMappings[$assoc->mappedBy]->inversedBy == null) {
+ "field " . $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " which does not exist.";
+ } else if ($targetMetadata->associationMappings[$assoc['mappedBy']]['inversedBy'] == null) {
$ce[] = "The field " . $class->name . "#" . $fieldName . " is on the inverse side of a ".
"bi-directional relationship, but the specified mappedBy association on the target-entity ".
- $assoc->targetEntityName . "#" . $assoc->mappedBy . " does not contain the required ".
+ $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " does not contain the required ".
"'inversedBy' attribute.";
- } else if ($targetMetadata->associationMappings[$assoc->mappedBy]->inversedBy != $fieldName) {
+ } else if ($targetMetadata->associationMappings[$assoc['mappedBy']]['inversedBy'] != $fieldName) {
$ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " .
- $assoc->targetEntityName . "#" . $assoc->mappedBy . " are ".
+ $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " are ".
"incosistent with each other.";
}
}
- if ($assoc->inversedBy) {
- if ($targetMetadata->hasField($assoc->inversedBy)) {
+ if ($assoc['inversedBy']) {
+ if ($targetMetadata->hasField($assoc['inversedBy'])) {
$ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the inverse side ".
- "field " . $assoc->targetEntityName . "#" . $assoc->inversedBy . " which is not defined as association.";
+ "field " . $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " which is not defined as association.";
}
- if (!$targetMetadata->hasAssociation($assoc->inversedBy)) {
+ if (!$targetMetadata->hasAssociation($assoc['inversedBy'])) {
$ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the inverse side ".
- "field " . $assoc->targetEntityName . "#" . $assoc->inversedBy . " which does not exist.";
- } else if ($targetMetadata->associationMappings[$assoc->inversedBy]->mappedBy == null) {
+ "field " . $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " which does not exist.";
+ } else if ($targetMetadata->associationMappings[$assoc['inversedBy']]['mappedBy'] == null) {
$ce[] = "The field " . $class->name . "#" . $fieldName . " is on the owning side of a ".
"bi-directional relationship, but the specified mappedBy association on the target-entity ".
- $assoc->targetEntityName . "#" . $assoc->mappedBy . " does not contain the required ".
+ $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " does not contain the required ".
"'inversedBy' attribute.";
- } else if ($targetMetadata->associationMappings[$assoc->inversedBy]->mappedBy != $fieldName) {
+ } else if ($targetMetadata->associationMappings[$assoc['inversedBy']]['mappedBy'] != $fieldName) {
$ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " .
- $assoc->targetEntityName . "#" . $assoc->inversedBy . " are ".
+ $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " are ".
"incosistent with each other.";
}
}
- if ($assoc->isOwningSide) {
- if ($assoc instanceof ManyToManyMapping) {
- foreach ($assoc->joinTable['joinColumns'] AS $joinColumn) {
+ if ($assoc['isOwningSide']) {
+ if ($assoc['type'] == ClassMetadataInfo::MANY_TO_MANY) {
+ foreach ($assoc['joinTable']['joinColumns'] AS $joinColumn) {
if (!isset($class->fieldNames[$joinColumn['referencedColumnName']])) {
$ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' does not " .
"have a corresponding field with this column name on the class '" . $class->name . "'.";
@@ -139,8 +138,8 @@ class SchemaValidator
"has to be a primary key column.";
}
}
- foreach ($assoc->joinTable['inverseJoinColumns'] AS $inverseJoinColumn) {
- $targetClass = $cmf->getMetadataFor($assoc->targetEntityName);
+ foreach ($assoc['joinTable']['inverseJoinColumns'] AS $inverseJoinColumn) {
+ $targetClass = $cmf->getMetadataFor($assoc['targetEntity']);
if (!isset($targetClass->fieldNames[$inverseJoinColumn['referencedColumnName']])) {
$ce[] = "The inverse referenced column name '" . $inverseJoinColumn['referencedColumnName'] . "' does not " .
"have a corresponding field with this column name on the class '" . $targetClass->name . "'.";
@@ -153,9 +152,9 @@ class SchemaValidator
"has to be a primary key column.";
}
}
- } else if ($assoc instanceof OneToOneMapping) {
- foreach ($assoc->joinColumns AS $joinColumn) {
- $targetClass = $cmf->getMetadataFor($assoc->targetEntityName);
+ } else if ($assoc['type'] & ClassMetadataInfo::TO_ONE) {
+ foreach ($assoc['joinColumns'] AS $joinColumn) {
+ $targetClass = $cmf->getMetadataFor($assoc['targetEntity']);
if (!isset($targetClass->fieldNames[$joinColumn['referencedColumnName']])) {
$ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' does not " .
"have a corresponding field with this column name on the class '" . $targetClass->name . "'.";
@@ -171,9 +170,9 @@ class SchemaValidator
}
}
- if (isset($assoc->orderBy) && $assoc->orderBy !== null) {
- $targetClass = $cmf->getMetadataFor($assoc->targetEntityName);
- foreach ($assoc->orderBy AS $orderField => $orientation) {
+ if (isset($assoc['orderBy']) && $assoc['orderBy'] !== null) {
+ $targetClass = $cmf->getMetadataFor($assoc['targetEntity']);
+ foreach ($assoc['orderBy'] AS $orderField => $orientation) {
if (!$targetClass->hasField($orderField)) {
$ce[] = "The association " . $class->name."#".$fieldName." is ordered by a foreign field " .
$orderField . " that is not a field on the target entity " . $targetClass->name;
diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php
index 57d19056c..039f51516 100644
--- a/lib/Doctrine/ORM/UnitOfWork.php
+++ b/lib/Doctrine/ORM/UnitOfWork.php
@@ -25,6 +25,7 @@ use Exception, InvalidArgumentException, UnexpectedValueException,
Doctrine\Common\NotifyPropertyChanged,
Doctrine\Common\PropertyChangedListener,
Doctrine\ORM\Event\LifecycleEventArgs,
+ Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\ORM\Proxy\Proxy;
/**
@@ -388,7 +389,7 @@ class UnitOfWork implements PropertyChangedListener
* @param ClassMetadata $class The class descriptor of the entity.
* @param object $entity The entity for which to compute the changes.
*/
- public function computeChangeSet(Mapping\ClassMetadata $class, $entity)
+ public function computeChangeSet(ClassMetadata $class, $entity)
{
if ( ! $class->isInheritanceTypeNone()) {
$class = $this->em->getClassMetadata(get_class($entity));
@@ -410,7 +411,7 @@ class UnitOfWork implements PropertyChangedListener
// Inject PersistentCollection
$coll = new PersistentCollection(
$this->em,
- $this->em->getClassMetadata($assoc->targetEntityName),
+ $this->em->getClassMetadata($assoc['targetEntity']),
$value
);
@@ -431,7 +432,7 @@ class UnitOfWork implements PropertyChangedListener
foreach ($actualData as $propName => $actualValue) {
if (isset($class->associationMappings[$propName])) {
$assoc = $class->associationMappings[$propName];
- if ($assoc->isOwningSide && $assoc->isOneToOne()) {
+ if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
$changeSet[$propName] = array(null, $actualValue);
}
} else {
@@ -450,11 +451,11 @@ class UnitOfWork implements PropertyChangedListener
$orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null;
if (isset($class->associationMappings[$propName])) {
$assoc = $class->associationMappings[$propName];
- if ($assoc->isOneToOne() && $orgValue !== $actualValue) {
- if ($assoc->isOwningSide) {
+ if ($assoc['type'] & ClassMetadata::TO_ONE && $orgValue !== $actualValue) {
+ if ($assoc['isOwningSide']) {
$changeSet[$propName] = array($orgValue, $actualValue);
}
- if ($orgValue !== null && $assoc->orphanRemoval) {
+ if ($orgValue !== null && $assoc['orphanRemoval']) {
$this->scheduleOrphanRemoval($orgValue);
}
} else if ($orgValue instanceof PersistentCollection && $orgValue !== $actualValue) {
@@ -539,7 +540,7 @@ class UnitOfWork implements PropertyChangedListener
private function computeAssociationChanges($assoc, $value)
{
if ($value instanceof PersistentCollection && $value->isDirty()) {
- if ($assoc->isOwningSide) {
+ if ($assoc['isOwningSide']) {
$this->collectionUpdates[] = $value;
}
$this->visitedCollections[] = $value;
@@ -547,7 +548,7 @@ class UnitOfWork implements PropertyChangedListener
// Look through the entities, and in any of their associations, for transient (new)
// enities, recursively. ("Persistence by reachability")
- if ($assoc->isOneToOne()) {
+ if ($assoc['type'] & ClassMetadata::TO_ONE) {
if ($value instanceof Proxy && ! $value->__isInitialized__) {
return; // Ignore uninitialized proxy objects
}
@@ -557,12 +558,12 @@ class UnitOfWork implements PropertyChangedListener
$value = $value->unwrap();
}
- $targetClass = $this->em->getClassMetadata($assoc->targetEntityName);
+ $targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
foreach ($value as $entry) {
$state = $this->getEntityState($entry, self::STATE_NEW);
$oid = spl_object_hash($entry);
if ($state == self::STATE_NEW) {
- if ( ! $assoc->isCascadePersist) {
+ if ( ! $assoc['isCascadePersist']) {
throw new InvalidArgumentException("A new entity was found through a relationship that was not"
. " configured to cascade persist operations: " . self::objToStr($entry) . "."
. " Explicitly persist the new entity or configure cascading persist operations"
@@ -833,8 +834,8 @@ class UnitOfWork implements PropertyChangedListener
// Calculate dependencies for new nodes
foreach ($newNodes as $class) {
foreach ($class->associationMappings as $assoc) {
- if ($assoc->isOwningSide && $assoc->isOneToOne()) {
- $targetClass = $this->em->getClassMetadata($assoc->targetEntityName);
+ if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
+ $targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
if ( ! $calc->hasClass($targetClass->name)) {
$calc->addClass($targetClass);
}
@@ -1400,20 +1401,20 @@ class UnitOfWork implements PropertyChangedListener
}
} else {
$assoc2 = $class->associationMappings[$name];
- if ($assoc2->isOneToOne()) {
+ if ($assoc2['type'] & ClassMetadata::TO_ONE) {
$other = $prop->getValue($entity);
if ($other === null) {
$prop->setValue($managedCopy, null);
} else if ($other instanceof Proxy && !$other->__isInitialized__) {
// do not merge fields marked lazy that have not been fetched.
continue;
- } else if ( ! $assoc2->isCascadeMerge) {
+ } else if ( ! $assoc2['isCascadeMerge']) {
if ($this->getEntityState($other, self::STATE_DETACHED) == self::STATE_MANAGED) {
$prop->setValue($managedCopy, $other);
} else {
- $targetClass = $this->em->getClassMetadata($assoc2->targetEntityName);
+ $targetClass = $this->em->getClassMetadata($assoc2['targetEntity']);
$id = $targetClass->getIdentifierValues($other);
- $proxy = $this->em->getProxyFactory()->getProxy($assoc2->targetEntityName, $id);
+ $proxy = $this->em->getProxyFactory()->getProxy($assoc2['targetEntity'], $id);
$prop->setValue($managedCopy, $proxy);
$this->registerManaged($proxy, $id, array());
}
@@ -1426,13 +1427,17 @@ class UnitOfWork implements PropertyChangedListener
continue;
}
- $coll = new PersistentCollection($this->em,
- $this->em->getClassMetadata($assoc2->targetEntityName),
- new ArrayCollection
- );
- $coll->setOwner($managedCopy, $assoc2);
- $coll->setInitialized($assoc2->isCascadeMerge);
- $prop->setValue($managedCopy, $coll);
+ $managedCol = $prop->getValue($managedCopy);
+ if (!$managedCol) {
+ $managedCol = new PersistentCollection($this->em,
+ $this->em->getClassMetadata($assoc2['targetEntity']),
+ new ArrayCollection
+ );
+ $managedCol->setOwner($managedCopy, $assoc2);
+ $prop->setValue($managedCopy, $managedCol);
+ $this->originalEntityData[$oid][$name] = $managedCol;
+ }
+ $managedCol->setInitialized($assoc2['isCascadeMerge']);
}
}
if ($class->isChangeTrackingNotify()) {
@@ -1446,14 +1451,14 @@ class UnitOfWork implements PropertyChangedListener
}
if ($prevManagedCopy !== null) {
- $assocField = $assoc->sourceFieldName;
+ $assocField = $assoc['fieldName'];
$prevClass = $this->em->getClassMetadata(get_class($prevManagedCopy));
- if ($assoc->isOneToOne()) {
+ if ($assoc['type'] & ClassMetadata::TO_ONE) {
$prevClass->reflFields[$assocField]->setValue($prevManagedCopy, $managedCopy);
} else {
$prevClass->reflFields[$assocField]->getValue($prevManagedCopy)->unwrap()->add($managedCopy);
- if ($assoc->isOneToMany()) {
- $class->reflFields[$assoc->mappedBy]->setValue($managedCopy, $prevManagedCopy);
+ if ($assoc['type'] == ClassMetadata::ONE_TO_MANY) {
+ $class->reflFields[$assoc['mappedBy']]->setValue($managedCopy, $prevManagedCopy);
}
}
}
@@ -1560,10 +1565,10 @@ class UnitOfWork implements PropertyChangedListener
{
$class = $this->em->getClassMetadata(get_class($entity));
foreach ($class->associationMappings as $assoc) {
- if ( ! $assoc->isCascadeRefresh) {
+ if ( ! $assoc['isCascadeRefresh']) {
continue;
}
- $relatedEntities = $class->reflFields[$assoc->sourceFieldName]->getValue($entity);
+ $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
if ($relatedEntities instanceof Collection) {
if ($relatedEntities instanceof PersistentCollection) {
// Unwrap so that foreach() does not initialize
@@ -1588,10 +1593,10 @@ class UnitOfWork implements PropertyChangedListener
{
$class = $this->em->getClassMetadata(get_class($entity));
foreach ($class->associationMappings as $assoc) {
- if ( ! $assoc->isCascadeDetach) {
+ if ( ! $assoc['isCascadeDetach']) {
continue;
}
- $relatedEntities = $class->reflFields[$assoc->sourceFieldName]->getValue($entity);
+ $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
if ($relatedEntities instanceof Collection) {
if ($relatedEntities instanceof PersistentCollection) {
// Unwrap so that foreach() does not initialize
@@ -1617,10 +1622,10 @@ class UnitOfWork implements PropertyChangedListener
{
$class = $this->em->getClassMetadata(get_class($entity));
foreach ($class->associationMappings as $assoc) {
- if ( ! $assoc->isCascadeMerge) {
+ if ( ! $assoc['isCascadeMerge']) {
continue;
}
- $relatedEntities = $class->reflFields[$assoc->sourceFieldName]->getValue($entity);
+ $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
if ($relatedEntities instanceof Collection) {
if ($relatedEntities instanceof PersistentCollection) {
// Unwrap so that foreach() does not initialize
@@ -1646,10 +1651,10 @@ class UnitOfWork implements PropertyChangedListener
{
$class = $this->em->getClassMetadata(get_class($entity));
foreach ($class->associationMappings as $assoc) {
- if ( ! $assoc->isCascadePersist) {
+ if ( ! $assoc['isCascadePersist']) {
continue;
}
- $relatedEntities = $class->reflFields[$assoc->sourceFieldName]->getValue($entity);
+ $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
if (($relatedEntities instanceof Collection || is_array($relatedEntities))) {
if ($relatedEntities instanceof PersistentCollection) {
// Unwrap so that foreach() does not initialize
@@ -1674,11 +1679,11 @@ class UnitOfWork implements PropertyChangedListener
{
$class = $this->em->getClassMetadata(get_class($entity));
foreach ($class->associationMappings as $assoc) {
- if ( ! $assoc->isCascadeRemove) {
+ if ( ! $assoc['isCascadeRemove']) {
continue;
}
//TODO: If $entity instanceof Proxy => Initialize ?
- $relatedEntities = $class->reflFields[$assoc->sourceFieldName]->getValue($entity);
+ $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
if ($relatedEntities instanceof Collection || is_array($relatedEntities)) {
// If its a PersistentCollection initialization is intended! No unwrap!
foreach ($relatedEntities as $relatedEntity) {
@@ -1822,7 +1827,7 @@ class UnitOfWork implements PropertyChangedListener
$id = array();
foreach ($class->identifier as $fieldName) {
if (isset($class->associationMappings[$fieldName])) {
- $id[$fieldName] = $data[$class->associationMappings[$fieldName]->joinColumns[0]['name']];
+ $id[$fieldName] = $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']];
} else {
$id[$fieldName] = $data[$fieldName];
}
@@ -1830,7 +1835,7 @@ class UnitOfWork implements PropertyChangedListener
$idHash = implode(' ', $id);
} else {
if (isset($class->associationMappings[$class->identifier[0]])) {
- $idHash = $data[$class->associationMappings[$class->identifier[0]]->joinColumns[0]['name']];
+ $idHash = $data[$class->associationMappings[$class->identifier[0]]['joinColumns'][0]['name']];
} else {
$idHash = $data[$class->identifier[0]];
}
@@ -1878,12 +1883,12 @@ class UnitOfWork implements PropertyChangedListener
continue;
}
- $targetClass = $this->em->getClassMetadata($assoc->targetEntityName);
+ $targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
- if ($assoc->isOneToOne()) {
- if ($assoc->isOwningSide) {
+ if ($assoc['type'] & ClassMetadata::TO_ONE) {
+ if ($assoc['isOwningSide']) {
$associatedId = array();
- foreach ($assoc->targetToSourceKeyColumns as $targetColumn => $srcColumn) {
+ foreach ($assoc['targetToSourceKeyColumns'] as $targetColumn => $srcColumn) {
$joinColumnValue = $data[$srcColumn];
if ($joinColumnValue !== null) {
$associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue;
@@ -1904,14 +1909,15 @@ class UnitOfWork implements PropertyChangedListener
} else {
if ($targetClass->subClasses) {
// If it might be a subtype, it can not be lazy
- $newValue = $assoc->load($entity, null, $this->em, $associatedId);
+ $newValue = $this->getEntityPersister($assoc['targetEntity'])
+ ->loadOneToOneEntity($assoc, $entity, null, $associatedId);
} else {
- if ($assoc->fetchMode == Mapping\AssociationMapping::FETCH_EAGER) {
+ if ($assoc['fetch'] == ClassMetadata::FETCH_EAGER) {
// TODO: Maybe it could be optimized to do an eager fetch with a JOIN inside
// the persister instead of this rather unperformant approach.
- $newValue = $this->em->find($assoc->targetEntityName, $associatedId);
+ $newValue = $this->em->find($assoc['targetEntity'], $associatedId);
} else {
- $newValue = $this->em->getProxyFactory()->getProxy($assoc->targetEntityName, $associatedId);
+ $newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId);
}
// PERF: Inlined & optimized code from UnitOfWork#registerManaged()
$newValueOid = spl_object_hash($newValue);
@@ -1926,7 +1932,8 @@ class UnitOfWork implements PropertyChangedListener
}
} else {
// Inverse side of x-to-one can never be lazy
- $class->reflFields[$field]->setValue($entity, $assoc->load($entity, null, $this->em));
+ $class->reflFields[$field]->setValue($entity, $this->getEntityPersister($assoc['targetEntity'])
+ ->loadOneToOneEntity($assoc, $entity, null));
}
} else {
// Inject collection
@@ -1938,10 +1945,10 @@ class UnitOfWork implements PropertyChangedListener
);
$pColl->setOwner($entity, $assoc);
$reflField->setValue($entity, $pColl);
- if ($assoc->isLazilyFetched()) {
+ if ($assoc['fetch'] == ClassMetadata::FETCH_LAZY) {
$pColl->setInitialized(false);
} else {
- $assoc->load($entity, $pColl, $this->em);
+ $this->loadCollection($pColl);
}
$this->originalEntityData[$oid][$field] = $pColl;
}
@@ -1960,6 +1967,27 @@ class UnitOfWork implements PropertyChangedListener
return $entity;
}
+ /**
+ * Initializes (loads) an uninitialized persistent collection of an entity.
+ *
+ * @param PeristentCollection $collection The collection to initialize.
+ * @todo Maybe later move to EntityManager#initialize($proxyOrCollection). See DDC-733.
+ */
+ public function loadCollection(PersistentCollection $collection)
+ {
+ $assoc = $collection->getMapping();
+ switch ($assoc['type']) {
+ case ClassMetadata::ONE_TO_MANY:
+ $this->getEntityPersister($assoc['targetEntity'])->loadOneToManyCollection(
+ $assoc, $collection->getOwner(), $collection);
+ break;
+ case ClassMetadata::MANY_TO_MANY:
+ $this->getEntityPersister($assoc['targetEntity'])->loadManyToManyCollection(
+ $assoc, $collection->getOwner(), $collection);
+ break;
+ }
+ }
+
/**
* Gets the identity map of the UnitOfWork.
*
@@ -2107,13 +2135,13 @@ class UnitOfWork implements PropertyChangedListener
* @param AssociationMapping $association
* @return AbstractCollectionPersister
*/
- public function getCollectionPersister($association)
+ public function getCollectionPersister(array $association)
{
- $type = get_class($association);
+ $type = $association['type'];
if ( ! isset($this->collectionPersisters[$type])) {
- if ($association instanceof Mapping\OneToManyMapping) {
+ if ($type == ClassMetadata::ONE_TO_MANY) {
$persister = new Persisters\OneToManyPersister($this->em);
- } else if ($association instanceof Mapping\ManyToManyMapping) {
+ } else if ($type == ClassMetadata::MANY_TO_MANY) {
$persister = new Persisters\ManyToManyPersister($this->em);
}
$this->collectionPersisters[$type] = $persister;
diff --git a/tests/Doctrine/Tests/ORM/AllTests.php b/tests/Doctrine/Tests/ORM/AllTests.php
index 9b8e06dd6..fd7c25d7f 100644
--- a/tests/Doctrine/Tests/ORM/AllTests.php
+++ b/tests/Doctrine/Tests/ORM/AllTests.php
@@ -26,7 +26,6 @@ class AllTests
$suite->addTest(Query\AllTests::suite());
$suite->addTest(Hydration\AllTests::suite());
$suite->addTest(Entity\AllTests::suite());
- $suite->addTest(Associations\AllTests::suite());
$suite->addTest(Mapping\AllTests::suite());
$suite->addTest(Functional\AllTests::suite());
$suite->addTest(Id\AllTests::suite());
diff --git a/tests/Doctrine/Tests/ORM/Associations/AllTests.php b/tests/Doctrine/Tests/ORM/Associations/AllTests.php
deleted file mode 100644
index 9f443976d..000000000
--- a/tests/Doctrine/Tests/ORM/Associations/AllTests.php
+++ /dev/null
@@ -1,30 +0,0 @@
-addTestSuite('Doctrine\Tests\ORM\Associations\OneToOneMappingTest');
-
- return $suite;
- }
-}
-
-if (PHPUnit_MAIN_METHOD == 'Orm_Associations_AllTests::main') {
- AllTests::main();
-}
\ No newline at end of file
diff --git a/tests/Doctrine/Tests/ORM/Associations/OneToOneMappingTest.php b/tests/Doctrine/Tests/ORM/Associations/OneToOneMappingTest.php
deleted file mode 100644
index ea8a028df..000000000
--- a/tests/Doctrine/Tests/ORM/Associations/OneToOneMappingTest.php
+++ /dev/null
@@ -1,40 +0,0 @@
- 'address',
- 'targetEntity' => 'Address',
- 'joinColumns' => array(array('name' => 'address_id', 'referencedColumnName' => 'id')),
- 'sourceEntity' => 'Person', // This is normally filled by ClassMetadata
- );
-
- $oneToOneMapping = new \Doctrine\ORM\Mapping\OneToOneMapping($owningSideMapping);
-
- $this->assertEquals(array('address_id' => 'id'), $oneToOneMapping->sourceToTargetKeyColumns);
- $this->assertEquals(array('id' => 'address_id'), $oneToOneMapping->targetToSourceKeyColumns);
- $this->assertEquals('Address', $oneToOneMapping->targetEntityName);
- $this->assertEquals('Person', $oneToOneMapping->sourceEntityName);
- $this->assertEquals('address', $oneToOneMapping->sourceFieldName);
- $this->assertTrue($oneToOneMapping->isOwningSide);
-
- $inverseSideMapping = array(
- 'fieldName' => 'person',
- 'sourceEntity' => 'Address',
- 'targetEntity' => 'Person',
- 'mappedBy' => 'address'
- );
-
- $oneToOneMapping = new \Doctrine\ORM\Mapping\OneToOneMapping($inverseSideMapping);
- $this->assertEquals('address', $oneToOneMapping->mappedBy);
- $this->assertEquals('Address', $oneToOneMapping->sourceEntityName);
- $this->assertEquals('Person', $oneToOneMapping->targetEntityName);
- $this->assertTrue( ! $oneToOneMapping->isOwningSide);
- }
-}
\ No newline at end of file
diff --git a/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php b/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php
index d12a183d9..97414ab4e 100644
--- a/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php
@@ -105,6 +105,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testBasicOneToOne()
{
+ //$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
$user = new CmsUser;
$user->name = 'Roman';
$user->username = 'romanb';
@@ -129,7 +130,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->clear();
- $user2 = $this->_em->createQuery('select u from Doctrine\Tests\Models\CMS\CmsUser u where u.id=?1')
+ $user2 = $this->_em->createQuery('select u from \Doctrine\Tests\Models\CMS\CmsUser u where u.id=?1')
->setParameter(1, $userId)
->getSingleResult();
@@ -440,7 +441,9 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->clear();
- $articleNew = $this->_em->find('Doctrine\Tests\Models\CMS\CmsArticle', $articleId);
+ // test find() with leading backslash at the same time
+ $articleNew = $this->_em->find('\Doctrine\Tests\Models\CMS\CmsArticle', $articleId);
+ $this->assertTrue($this->_em->contains($articleNew));
$this->assertEquals("Lorem ipsum dolor sunt.", $articleNew->text);
$this->assertNotSame($article, $articleNew);
@@ -702,6 +705,10 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->flush();
$this->assertEquals(1, $this->_em->getConnection()->fetchColumn("select count(*) from cms_addresses"));
+ // remove $address to free up unique key id
+ $this->_em->remove($address);
+ $this->_em->flush();
+
$newAddress = new CmsAddress();
$newAddress->city = "NewBonn";
$newAddress->zip = "12354";
diff --git a/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php b/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php
index a492444f1..86075e854 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php
@@ -325,4 +325,32 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertNull($this->_em->find(get_class($employee1), $employee1Id));
}
+
+ /**
+ * @group DDC-728
+ */
+ public function testQueryForInheritedSingleValuedAssociation()
+ {
+ $manager = new CompanyManager();
+ $manager->setName('gblanco');
+ $manager->setSalary(1234);
+ $manager->setTitle('Awesome!');
+ $manager->setDepartment('IT');
+
+ $person = new CompanyPerson();
+ $person->setName('spouse');
+
+ $manager->setSpouse($person);
+
+ $this->_em->persist($manager);
+ $this->_em->persist($person);
+ $this->_em->flush();
+ $this->_em->clear();
+
+ $dql = "SELECT m FROM Doctrine\Tests\Models\Company\CompanyManager m WHERE m.spouse = ?1";
+ $dqlManager = $this->_em->createQuery($dql)->setParameter(1, $person->getId())->getSingleResult();
+
+ $this->assertEquals($manager->getId(), $dqlManager->getId());
+ $this->assertEquals($person->getId(), $dqlManager->getSpouse()->getId());
+ }
}
diff --git a/tests/Doctrine/Tests/ORM/Functional/DatabaseDriverTest.php b/tests/Doctrine/Tests/ORM/Functional/DatabaseDriverTest.php
index 6f02328dc..964c57119 100644
--- a/tests/Doctrine/Tests/ORM/Functional/DatabaseDriverTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/DatabaseDriverTest.php
@@ -84,7 +84,7 @@ class DatabaseDriverTest extends \Doctrine\Tests\OrmFunctionalTestCase
$bazMetadata->associationMappings = \array_change_key_case($bazMetadata->associationMappings, \CASE_LOWER);
$this->assertArrayHasKey('bar', $bazMetadata->associationMappings);
- $this->assertType('Doctrine\ORM\Mapping\OneToOneMapping', $bazMetadata->associationMappings['bar']);
+ $this->assertEquals(ClassMetadataInfo::MANY_TO_ONE, $bazMetadata->associationMappings['bar']['type']);
}
public function testDetectManyToManyTables()
diff --git a/tests/Doctrine/Tests/ORM/Functional/ManyToManyBasicAssociationTest.php b/tests/Doctrine/Tests/ORM/Functional/ManyToManyBasicAssociationTest.php
index efb15d2d9..1fee14767 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ManyToManyBasicAssociationTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ManyToManyBasicAssociationTest.php
@@ -235,6 +235,18 @@ class ManyToManyBasicAssociationTest extends \Doctrine\Tests\OrmFunctionalTestCa
$this->assertEquals(0, count($newUser->getGroups()));
}
+ public function testDereferenceCollectionDelete()
+ {
+ $user = $this->addCmsUserGblancoWithGroups(2);
+ $user->groups = null;
+
+ $this->_em->flush();
+ $this->_em->clear();
+
+ $newUser = $this->_em->find(get_class($user), $user->getId());
+ $this->assertEquals(0, count($newUser->getGroups()));
+ }
+
/**
* @param int $groupCount
* @return CmsUser
diff --git a/tests/Doctrine/Tests/ORM/Functional/ManyToManySelfReferentialAssociationTest.php b/tests/Doctrine/Tests/ORM/Functional/ManyToManySelfReferentialAssociationTest.php
index ac691d220..020e77aec 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ManyToManySelfReferentialAssociationTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ManyToManySelfReferentialAssociationTest.php
@@ -4,6 +4,7 @@ namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
use Doctrine\ORM\Mapping\AssociationMapping;
+use Doctrine\ORM\Mapping\ClassMetadata;
require_once __DIR__ . '/../../TestInit.php';
@@ -74,7 +75,7 @@ class ManyToManySelfReferentialAssociationTest extends AbstractManyToManyAssocia
$this->_createLoadingFixture();
$metadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceProduct');
- $metadata->getAssociationMapping('related')->fetchMode = AssociationMapping::FETCH_LAZY;
+ $metadata->associationMappings['related']['fetch'] = ClassMetadata::FETCH_LAZY;
$query = $this->_em->createQuery('SELECT p FROM Doctrine\Tests\Models\ECommerce\ECommerceProduct p');
$products = $query->getResult();
diff --git a/tests/Doctrine/Tests/ORM/Functional/ManyToManyUnidirectionalAssociationTest.php b/tests/Doctrine/Tests/ORM/Functional/ManyToManyUnidirectionalAssociationTest.php
index 6510f4f69..d6c38fc54 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ManyToManyUnidirectionalAssociationTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ManyToManyUnidirectionalAssociationTest.php
@@ -5,6 +5,7 @@ namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\ECommerce\ECommerceCart;
use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
use Doctrine\ORM\Mapping\AssociationMapping;
+use Doctrine\ORM\Mapping\ClassMetadata;
require_once __DIR__ . '/../../TestInit.php';
@@ -79,7 +80,7 @@ class ManyToManyUnidirectionalAssociationTest extends AbstractManyToManyAssociat
{
$this->_createFixture();
$metadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceCart');
- $metadata->getAssociationMapping('products')->fetchMode = AssociationMapping::FETCH_LAZY;
+ $metadata->associationMappings['products']['fetch'] = ClassMetadata::FETCH_LAZY;
$query = $this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\ECommerce\ECommerceCart c');
$result = $query->getResult();
diff --git a/tests/Doctrine/Tests/ORM/Functional/OneToManySelfReferentialAssociationTest.php b/tests/Doctrine/Tests/ORM/Functional/OneToManySelfReferentialAssociationTest.php
index 4aa94a3ce..5d6c182ab 100644
--- a/tests/Doctrine/Tests/ORM/Functional/OneToManySelfReferentialAssociationTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/OneToManySelfReferentialAssociationTest.php
@@ -4,6 +4,7 @@ namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\ECommerce\ECommerceCategory;
use Doctrine\ORM\Mapping\AssociationMapping;
+use Doctrine\ORM\Mapping\ClassMetadata;
require_once __DIR__ . '/../../TestInit.php';
@@ -90,7 +91,7 @@ class OneToManySelfReferentialAssociationTest extends \Doctrine\Tests\OrmFunctio
{
$this->_createFixture();
$metadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceCategory');
- $metadata->getAssociationMapping('children')->fetchMode = AssociationMapping::FETCH_LAZY;
+ $metadata->associationMappings['children']['fetch'] = ClassMetadata::FETCH_LAZY;
$query = $this->_em->createQuery('select c from Doctrine\Tests\Models\ECommerce\ECommerceCategory c order by c.id asc');
$result = $query->getResult();
diff --git a/tests/Doctrine/Tests/ORM/Functional/OneToOneBidirectionalAssociationTest.php b/tests/Doctrine/Tests/ORM/Functional/OneToOneBidirectionalAssociationTest.php
index 73363547c..93e30cbc0 100644
--- a/tests/Doctrine/Tests/ORM/Functional/OneToOneBidirectionalAssociationTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/OneToOneBidirectionalAssociationTest.php
@@ -5,6 +5,7 @@ namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\ECommerce\ECommerceCart;
use Doctrine\Tests\Models\ECommerce\ECommerceCustomer;
use Doctrine\ORM\Mapping\AssociationMapping;
+use Doctrine\ORM\Mapping\ClassMetadata;
require_once __DIR__ . '/../../TestInit.php';
@@ -68,7 +69,7 @@ class OneToOneBidirectionalAssociationTest extends \Doctrine\Tests\OrmFunctional
public function testLazyLoadsObjectsOnTheOwningSide() {
$this->_createFixture();
$metadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceCart');
- $metadata->getAssociationMapping('customer')->fetchMode = AssociationMapping::FETCH_LAZY;
+ $metadata->associationMappings['customer']['fetchMode'] = ClassMetadata::FETCH_LAZY;
$query = $this->_em->createQuery('select c from Doctrine\Tests\Models\ECommerce\ECommerceCart c');
$result = $query->getResult();
@@ -82,7 +83,7 @@ class OneToOneBidirectionalAssociationTest extends \Doctrine\Tests\OrmFunctional
{
$this->_createFixture();
$metadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceCustomer');
- $metadata->getAssociationMapping('mentor')->fetchMode = AssociationMapping::FETCH_EAGER;
+ $metadata->associationMappings['mentor']['fetch'] = ClassMetadata::FETCH_EAGER;
$query = $this->_em->createQuery('select c from Doctrine\Tests\Models\ECommerce\ECommerceCustomer c');
$result = $query->getResult();
diff --git a/tests/Doctrine/Tests/ORM/Functional/OneToOneSelfReferentialAssociationTest.php b/tests/Doctrine/Tests/ORM/Functional/OneToOneSelfReferentialAssociationTest.php
index a58384b7e..321f66340 100644
--- a/tests/Doctrine/Tests/ORM/Functional/OneToOneSelfReferentialAssociationTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/OneToOneSelfReferentialAssociationTest.php
@@ -4,6 +4,7 @@ namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\ECommerce\ECommerceCustomer;
use Doctrine\ORM\Mapping\AssociationMapping;
+use Doctrine\ORM\Mapping\ClassMetadata;
require_once __DIR__ . '/../../TestInit.php';
@@ -67,7 +68,7 @@ class OneToOneSelfReferentialAssociationTest extends \Doctrine\Tests\OrmFunction
$this->_createFixture();
$metadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceCustomer');
- $metadata->getAssociationMapping('mentor')->fetchMode = AssociationMapping::FETCH_LAZY;
+ $metadata->associationMappings['mentor']['fetch'] = ClassMetadata::FETCH_LAZY;
$query = $this->_em->createQuery("select c from Doctrine\Tests\Models\ECommerce\ECommerceCustomer c where c.name='Luke Skywalker'");
$result = $query->getResult();
diff --git a/tests/Doctrine/Tests/ORM/Functional/OneToOneUnidirectionalAssociationTest.php b/tests/Doctrine/Tests/ORM/Functional/OneToOneUnidirectionalAssociationTest.php
index af1ff2362..01b2d00f9 100644
--- a/tests/Doctrine/Tests/ORM/Functional/OneToOneUnidirectionalAssociationTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/OneToOneUnidirectionalAssociationTest.php
@@ -5,6 +5,7 @@ namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
use Doctrine\Tests\Models\ECommerce\ECommerceShipping;
use Doctrine\ORM\Mapping\AssociationMapping;
+use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query;
require_once __DIR__ . '/../../TestInit.php';
@@ -62,7 +63,7 @@ class OneToOneUnidirectionalAssociationTest extends \Doctrine\Tests\OrmFunctiona
public function testLazyLoadsObjects() {
$this->_createFixture();
$metadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceProduct');
- $metadata->getAssociationMapping('shipping')->fetchMode = AssociationMapping::FETCH_LAZY;
+ $metadata->associationMappings['shipping']['fetch'] = ClassMetadata::FETCH_LAZY;
$query = $this->_em->createQuery('select p from Doctrine\Tests\Models\ECommerce\ECommerceProduct p');
$result = $query->getResult();
diff --git a/tests/Doctrine/Tests/ORM/Functional/SchemaTool/MySqlSchemaToolTest.php b/tests/Doctrine/Tests/ORM/Functional/SchemaTool/MySqlSchemaToolTest.php
index 194f7109e..e3117b48e 100644
--- a/tests/Doctrine/Tests/ORM/Functional/SchemaTool/MySqlSchemaToolTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/SchemaTool/MySqlSchemaToolTest.php
@@ -26,8 +26,7 @@ class MySqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
$tool = new SchemaTool($this->_em);
$sql = $tool->getCreateSchemaSql($classes);
- $this->assertEquals(8, count($sql));
- $this->assertEquals("CREATE TABLE cms_addresses (id INT AUTO_INCREMENT NOT NULL, user_id INT DEFAULT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB", $sql[0]);
+ $this->assertEquals("CREATE TABLE cms_addresses (id INT AUTO_INCREMENT NOT NULL, user_id INT DEFAULT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, UNIQUE INDEX cms_addresses_user_id_uniq (user_id), PRIMARY KEY(id)) ENGINE = InnoDB", $sql[0]);
$this->assertEquals("CREATE TABLE cms_users (id INT AUTO_INCREMENT NOT NULL, status VARCHAR(50) NOT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX cms_users_username_uniq (username), PRIMARY KEY(id)) ENGINE = InnoDB", $sql[1]);
$this->assertEquals("CREATE TABLE cms_users_groups (user_id INT NOT NULL, group_id INT NOT NULL, PRIMARY KEY(user_id, group_id)) ENGINE = InnoDB", $sql[2]);
$this->assertEquals("CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(phonenumber)) ENGINE = InnoDB", $sql[3]);
@@ -35,6 +34,8 @@ class MySqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals("ALTER TABLE cms_users_groups ADD FOREIGN KEY (user_id) REFERENCES cms_users(id)", $sql[5]);
$this->assertEquals("ALTER TABLE cms_users_groups ADD FOREIGN KEY (group_id) REFERENCES cms_groups(id)", $sql[6]);
$this->assertEquals("ALTER TABLE cms_phonenumbers ADD FOREIGN KEY (user_id) REFERENCES cms_users(id)", $sql[7]);
+
+ $this->assertEquals(8, count($sql));
}
public function testGetCreateSchemaSql2()
diff --git a/tests/Doctrine/Tests/ORM/Functional/SchemaTool/PostgreSqlSchemaToolTest.php b/tests/Doctrine/Tests/ORM/Functional/SchemaTool/PostgreSqlSchemaToolTest.php
index 8646068f0..fcdfb0c2a 100644
--- a/tests/Doctrine/Tests/ORM/Functional/SchemaTool/PostgreSqlSchemaToolTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/SchemaTool/PostgreSqlSchemaToolTest.php
@@ -32,19 +32,21 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
$tool = new SchemaTool($this->_em);
$sql = $tool->getCreateSchemaSql($classes);
- $this->assertEquals(count($sql), 11);
$this->assertEquals("CREATE TABLE cms_addresses (id INT NOT NULL, user_id INT DEFAULT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, PRIMARY KEY(id))", $sql[0]);
- $this->assertEquals("CREATE TABLE cms_users (id INT NOT NULL, status VARCHAR(50) NOT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))", $sql[1]);
- $this->assertEquals("CREATE UNIQUE INDEX cms_users_username_uniq ON cms_users (username)", $sql[2]);
- $this->assertEquals("CREATE TABLE cms_users_groups (user_id INT NOT NULL, group_id INT NOT NULL, PRIMARY KEY(user_id, group_id))", $sql[3]);
- $this->assertEquals("CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(phonenumber))", $sql[4]);
- $this->assertEquals("CREATE SEQUENCE cms_addresses_id_seq INCREMENT BY 10 MINVALUE 1 START 1", $sql[5]);
- $this->assertEquals("CREATE SEQUENCE cms_users_id_seq INCREMENT BY 10 MINVALUE 1 START 1", $sql[6]);
- $this->assertEquals("ALTER TABLE cms_addresses ADD FOREIGN KEY (user_id) REFERENCES cms_users(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[7]);
- $this->assertEquals("ALTER TABLE cms_users_groups ADD FOREIGN KEY (user_id) REFERENCES cms_users(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[8]);
- $this->assertEquals("ALTER TABLE cms_users_groups ADD FOREIGN KEY (group_id) REFERENCES cms_groups(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[9]);
- $this->assertEquals("ALTER TABLE cms_phonenumbers ADD FOREIGN KEY (user_id) REFERENCES cms_users(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[10]);
+ $this->assertEquals("CREATE UNIQUE INDEX cms_addresses_user_id_uniq ON cms_addresses (user_id)", $sql[1]);
+ $this->assertEquals("CREATE TABLE cms_users (id INT NOT NULL, status VARCHAR(50) NOT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))", $sql[2]);
+ $this->assertEquals("CREATE UNIQUE INDEX cms_users_username_uniq ON cms_users (username)", $sql[3]);
+ $this->assertEquals("CREATE TABLE cms_users_groups (user_id INT NOT NULL, group_id INT NOT NULL, PRIMARY KEY(user_id, group_id))", $sql[4]);
+ $this->assertEquals("CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(phonenumber))", $sql[5]);
+ $this->assertEquals("CREATE SEQUENCE cms_addresses_id_seq INCREMENT BY 10 MINVALUE 1 START 1", $sql[6]);
+ $this->assertEquals("CREATE SEQUENCE cms_users_id_seq INCREMENT BY 10 MINVALUE 1 START 1", $sql[7]);
+ $this->assertEquals("ALTER TABLE cms_addresses ADD FOREIGN KEY (user_id) REFERENCES cms_users(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[8]);
+ $this->assertEquals("ALTER TABLE cms_users_groups ADD FOREIGN KEY (user_id) REFERENCES cms_users(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[9]);
+ $this->assertEquals("ALTER TABLE cms_users_groups ADD FOREIGN KEY (group_id) REFERENCES cms_groups(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[10]);
+ $this->assertEquals("ALTER TABLE cms_phonenumbers ADD FOREIGN KEY (user_id) REFERENCES cms_users(id) NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[11]);
+
+ $this->assertEquals(count($sql), 12);
}
public function testGetCreateSchemaSql2()
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC599Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC599Test.php
index d9f9a82be..b342796cc 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC599Test.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC599Test.php
@@ -66,7 +66,7 @@ class DDC599Test extends \Doctrine\Tests\OrmFunctionalTestCase
$class = $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC599Subitem');
$this->assertArrayHasKey('children', $class->associationMappings);
- $this->assertTrue($class->associationMappings['children']->isCascadeRemove);
+ $this->assertTrue($class->associationMappings['children']['isCascadeRemove']);
}
}
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC729Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC729Test.php
new file mode 100644
index 000000000..c2be27b11
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC729Test.php
@@ -0,0 +1,182 @@
+_em);
+ $schemaTool->createSchema(array(
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC729A'),
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC729B'),
+ ));
+ } catch(\Exception $e) {
+
+ }
+ }
+
+ public function testMergeManyToMany()
+ {
+ $a = new DDC729A();
+ $b = new DDC729B();
+ $a->related[] = $b;
+
+ $this->_em->persist($a);
+ $this->_em->persist($b);
+ $this->_em->flush();
+ $this->_em->clear();
+ $aId = $a->id;
+
+ $a = new DDC729A();
+ $a->id = $aId;
+
+ $this->assertType('Doctrine\Common\Collections\ArrayCollection', $a->related);
+
+ $a = $this->_em->merge($a);
+
+ $this->assertType('Doctrine\ORM\PersistentCollection', $a->related);
+
+ $this->assertFalse($a->related->isInitialized(), "Collection should not be marked initialized.");
+ $this->assertFalse($a->related->isDirty(), "Collection should not be marked as dirty.");
+
+ $this->_em->flush();
+ $this->_em->clear();
+
+ $a = $this->_em->find(__NAMESPACE__ . '\DDC729A', $aId);
+ $this->assertEquals(1, count($a->related));
+ }
+
+ public function testUnidirectionalMergeManyToMany()
+ {
+ $a = new DDC729A();
+ $b1 = new DDC729B();
+ $b2 = new DDC729B();
+ $a->related[] = $b1;
+
+ $this->_em->persist($a);
+ $this->_em->persist($b1);
+ $this->_em->persist($b2);
+ $this->_em->flush();
+ $this->_em->clear();
+ $aId = $a->id;
+
+ $a = new DDC729A();
+ $a->id = $aId;
+
+ $a = $this->_em->merge($a);
+
+ $a->related->set(0, $this->_em->merge($b1));
+
+ $a->related->set(1, $this->_em->merge($b2));
+
+ $this->_em->flush();
+ $this->_em->clear();
+
+ $a = $this->_em->find(__NAMESPACE__ . '\DDC729A', $aId);
+ $this->assertEquals(2, count($a->related));
+ }
+
+ public function testBidirectionalMergeManyToMany()
+ {
+ $a = new DDC729A();
+ $b1 = new DDC729B();
+ $b2 = new DDC729B();
+ $a->related[] = $b1;
+
+ $this->_em->persist($a);
+ $this->_em->persist($b1);
+ $this->_em->persist($b2);
+ $this->_em->flush();
+ $this->_em->clear();
+ $aId = $a->id;
+
+ $a = new DDC729A();
+ $a->id = $aId;
+
+ $a = $this->_em->merge($a);
+
+ $a->related->set(0, $this->_em->merge($b1));
+ $b1->related->set(0, $a);
+
+ $a->related->set(1, $this->_em->merge($b2));
+ $b2->related->set(0, $a);
+
+ $this->_em->flush();
+ $this->_em->clear();
+
+ $a = $this->_em->find(__NAMESPACE__ . '\DDC729A', $aId);
+ $this->assertEquals(2, count($a->related));
+ }
+
+ public function testBidirectionalMultiMergeManyToMany()
+ {
+ $a = new DDC729A();
+ $b1 = new DDC729B();
+ $b2 = new DDC729B();
+ $a->related[] = $b1;
+
+ $this->_em->persist($a);
+ $this->_em->persist($b1);
+ $this->_em->persist($b2);
+ $this->_em->flush();
+ $this->_em->clear();
+ $aId = $a->id;
+
+ $a = new DDC729A();
+ $a->id = $aId;
+
+ $a = $this->_em->merge($a);
+
+ $a->related->set(0, $this->_em->merge($b1));
+ $b1->related->set(0, $this->_em->merge($a));
+
+ $a->related->set(1, $this->_em->merge($b2));
+ $b2->related->set(0, $this->_em->merge($a));
+
+ $this->_em->flush();
+ $this->_em->clear();
+
+ $a = $this->_em->find(__NAMESPACE__ . '\DDC729A', $aId);
+ $this->assertEquals(2, count($a->related));
+ }
+}
+
+/**
+ * @Entity
+ */
+class DDC729A
+{
+ /** @Id @GeneratedValue @Column(type="integer") */
+ public $id;
+
+ /** @ManyToMany(targetEntity="DDC729B", inversedBy="related") */
+ public $related;
+
+ public function __construct()
+ {
+ $this->related = new \Doctrine\Common\Collections\ArrayCollection();
+ }
+}
+
+/**
+ * @Entity
+ */
+class DDC729B
+{
+ /** @Id @GeneratedValue @Column(type="integer") */
+ public $id;
+
+ /** @ManyToMany(targetEntity="DDC729B", mappedBy="related") */
+ public $related;
+
+ public function __construct()
+ {
+ $this->related = new \Doctrine\Common\Collections\ArrayCollection();
+ }
+}
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC735Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC735Test.php
new file mode 100644
index 000000000..76d3720c9
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC735Test.php
@@ -0,0 +1,121 @@
+_schemaTool->createSchema(array(
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC735Product'),
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC735Review')
+ ));
+ } catch(\Exception $e) {
+
+ }
+ }
+
+ public function testRemoveElement_AppliesOrphanRemoval()
+ {
+ // Create a product and its first review
+ $product = new DDC735Product;
+ $review = new DDC735Review($product);
+
+ // Persist and flush
+ $this->_em->persist($product);
+ $this->_em->flush();
+
+ // Now you see it
+ $this->assertEquals(1, count($product->getReviews()));
+
+ // Remove the review
+ $product->removeReview($review);
+ $this->_em->flush();
+
+ // Now you don't
+ $this->assertEquals(0, count($product->getReviews()), 'count($reviews) should be 0 after removing its only Review');
+
+ // Refresh
+ $this->_em->refresh($product);
+
+ // It should still be 0
+ $this->assertEquals(0, count($product->getReviews()), 'count($reviews) should still be 0 after the refresh');
+
+ // Review should also not be available anymore
+ $this->assertNull($this->_em->find(__NAMESPACE__.'\DDC735Review', $review->getId()));
+ }
+}
+
+/**
+ * @Entity
+ */
+class DDC735Product
+{
+ /**
+ * @Id @Column(type="integer") @GeneratedValue
+ */
+ protected $id;
+
+ /**
+ * @OneToMany(
+ * targetEntity="DDC735Review",
+ * mappedBy="product",
+ * cascade={"persist"},
+ * orphanRemoval=true
+ * )
+ */
+ protected $reviews;
+
+ public function __construct()
+ {
+ $this->reviews = new ArrayCollection;
+ }
+
+ public function getReviews()
+ {
+ return $this->reviews;
+ }
+
+ public function addReview(DDC735Review $review)
+ {
+ $this->reviews->add($review);
+ }
+
+ public function removeReview(DDC735Review $review)
+ {
+ $this->reviews->removeElement($review);
+ }
+}
+
+/**
+ * @Entity
+ */
+class DDC735Review
+{
+ /**
+ * @Id @Column(type="integer") @GeneratedValue
+ */
+ protected $id;
+
+ /**
+ * @ManyToOne(targetEntity="DDC735Product", inversedBy="reviews")
+ */
+ protected $product;
+
+ public function __construct(DDC735Product $product)
+ {
+ $this->product = $product;
+ $product->addReview($this);
+ }
+
+ public function getId()
+ {
+ return $this->id;
+ }
+}
\ No newline at end of file
diff --git a/tests/Doctrine/Tests/ORM/Hydration/ObjectHydratorTest.php b/tests/Doctrine/Tests/ORM/Hydration/ObjectHydratorTest.php
index d3bda1e5b..442961266 100644
--- a/tests/Doctrine/Tests/ORM/Hydration/ObjectHydratorTest.php
+++ b/tests/Doctrine/Tests/ORM/Hydration/ObjectHydratorTest.php
@@ -6,6 +6,7 @@ use Doctrine\Tests\Mocks\HydratorMockStatement;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\ORM\Proxy\ProxyFactory;
use Doctrine\ORM\Mapping\AssociationMapping;
+use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query;
use Doctrine\Tests\Models\CMS\CmsUser;
@@ -164,7 +165,7 @@ class ObjectHydratorTest extends HydrationTestCase
// configuring lazy loading
$metadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceProduct');
- $metadata->getAssociationMapping('shipping')->fetchMode = AssociationMapping::FETCH_LAZY;
+ $metadata->associationMappings['shipping']['fetch'] = ClassMetadata::FETCH_LAZY;
$stmt = new HydratorMockStatement($resultSet);
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
diff --git a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php
index b279905ce..653cff7d7 100644
--- a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php
+++ b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php
@@ -155,16 +155,15 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
*/
public function testOwningOneToOneAssocation($class)
{
- $this->assertTrue($class->associationMappings['address'] instanceof \Doctrine\ORM\Mapping\OneToOneMapping);
$this->assertTrue(isset($class->associationMappings['address']));
- $this->assertTrue($class->associationMappings['address']->isOwningSide);
- $this->assertEquals('user', $class->associationMappings['address']->inversedBy);
+ $this->assertTrue($class->associationMappings['address']['isOwningSide']);
+ $this->assertEquals('user', $class->associationMappings['address']['inversedBy']);
// Check cascading
- $this->assertTrue($class->associationMappings['address']->isCascadeRemove);
- $this->assertFalse($class->associationMappings['address']->isCascadePersist);
- $this->assertFalse($class->associationMappings['address']->isCascadeRefresh);
- $this->assertFalse($class->associationMappings['address']->isCascadeDetach);
- $this->assertFalse($class->associationMappings['address']->isCascadeMerge);
+ $this->assertTrue($class->associationMappings['address']['isCascadeRemove']);
+ $this->assertFalse($class->associationMappings['address']['isCascadePersist']);
+ $this->assertFalse($class->associationMappings['address']['isCascadeRefresh']);
+ $this->assertFalse($class->associationMappings['address']['isCascadeDetach']);
+ $this->assertFalse($class->associationMappings['address']['isCascadeMerge']);
return $class;
}
@@ -175,17 +174,16 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
*/
public function testInverseOneToManyAssociation($class)
{
- $this->assertTrue($class->associationMappings['phonenumbers'] instanceof \Doctrine\ORM\Mapping\OneToManyMapping);
$this->assertTrue(isset($class->associationMappings['phonenumbers']));
- $this->assertFalse($class->associationMappings['phonenumbers']->isOwningSide);
- $this->assertTrue($class->associationMappings['phonenumbers']->isCascadePersist);
- $this->assertFalse($class->associationMappings['phonenumbers']->isCascadeRemove);
- $this->assertFalse($class->associationMappings['phonenumbers']->isCascadeRefresh);
- $this->assertFalse($class->associationMappings['phonenumbers']->isCascadeDetach);
- $this->assertFalse($class->associationMappings['phonenumbers']->isCascadeMerge);
+ $this->assertFalse($class->associationMappings['phonenumbers']['isOwningSide']);
+ $this->assertTrue($class->associationMappings['phonenumbers']['isCascadePersist']);
+ $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeRemove']);
+ $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeRefresh']);
+ $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeDetach']);
+ $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeMerge']);
// Test Order By
- $this->assertEquals(array('number' => 'ASC'), $class->associationMappings['phonenumbers']->orderBy);
+ $this->assertEquals(array('number' => 'ASC'), $class->associationMappings['phonenumbers']['orderBy']);
return $class;
}
@@ -196,17 +194,16 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
*/
public function testManyToManyAssociationWithCascadeAll($class)
{
- $this->assertTrue($class->associationMappings['groups'] instanceof \Doctrine\ORM\Mapping\ManyToManyMapping);
$this->assertTrue(isset($class->associationMappings['groups']));
- $this->assertTrue($class->associationMappings['groups']->isOwningSide);
+ $this->assertTrue($class->associationMappings['groups']['isOwningSide']);
// Make sure that cascade-all works as expected
- $this->assertTrue($class->associationMappings['groups']->isCascadeRemove);
- $this->assertTrue($class->associationMappings['groups']->isCascadePersist);
- $this->assertTrue($class->associationMappings['groups']->isCascadeRefresh);
- $this->assertTrue($class->associationMappings['groups']->isCascadeDetach);
- $this->assertTrue($class->associationMappings['groups']->isCascadeMerge);
+ $this->assertTrue($class->associationMappings['groups']['isCascadeRemove']);
+ $this->assertTrue($class->associationMappings['groups']['isCascadePersist']);
+ $this->assertTrue($class->associationMappings['groups']['isCascadeRefresh']);
+ $this->assertTrue($class->associationMappings['groups']['isCascadeDetach']);
+ $this->assertTrue($class->associationMappings['groups']['isCascadeMerge']);
- $this->assertNull($class->associationMappings['groups']->orderBy);
+ $this->assertFalse(isset($class->associationMappings['groups']['orderBy']));
return $class;
}
@@ -243,8 +240,8 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
public function testJoinColumnUniqueAndNullable($class)
{
// Non-Nullability of Join Column
- $this->assertFalse($class->associationMappings['groups']->joinTable['joinColumns'][0]['nullable']);
- $this->assertFalse($class->associationMappings['groups']->joinTable['joinColumns'][0]['unique']);
+ $this->assertFalse($class->associationMappings['groups']['joinTable']['joinColumns'][0]['nullable']);
+ $this->assertFalse($class->associationMappings['groups']['joinTable']['joinColumns'][0]['unique']);
return $class;
}
@@ -256,7 +253,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
public function testColumnDefinition($class)
{
$this->assertEquals("CHAR(32) NOT NULL", $class->fieldMappings['email']['columnDefinition']);
- $this->assertEquals("INT NULL", $class->associationMappings['groups']->joinTable['inverseJoinColumns'][0]['columnDefinition']);
+ $this->assertEquals("INT NULL", $class->associationMappings['groups']['joinTable']['inverseJoinColumns'][0]['columnDefinition']);
return $class;
}
@@ -267,8 +264,8 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
*/
public function testJoinColumnOnDeleteAndOnUpdate($class)
{
- $this->assertEquals('CASCADE', $class->associationMappings['address']->joinColumns[0]['onDelete']);
- $this->assertEquals('CASCADE', $class->associationMappings['address']->joinColumns[0]['onUpdate']);
+ $this->assertEquals('CASCADE', $class->associationMappings['address']['joinColumns'][0]['onDelete']);
+ $this->assertEquals('CASCADE', $class->associationMappings['address']['joinColumns'][0]['onUpdate']);
return $class;
}
diff --git a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php
index 620838a6b..b51d34831 100644
--- a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php
+++ b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php
@@ -29,7 +29,6 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$cm->setCustomRepositoryClass("UserRepository");
$cm->setDiscriminatorColumn(array('name' => 'disc', 'type' => 'integer'));
$cm->mapOneToOne(array('fieldName' => 'phonenumbers', 'targetEntity' => 'Bar', 'mappedBy' => 'foo'));
- $this->assertTrue($cm->getAssociationMapping('phonenumbers') instanceof \Doctrine\ORM\Mapping\OneToOneMapping);
$this->assertEquals(1, count($cm->associationMappings));
$serialized = serialize($cm);
@@ -45,12 +44,12 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals(array('UserParent'), $cm->parentClasses);
$this->assertEquals('UserRepository', $cm->customRepositoryClassName);
$this->assertEquals(array('name' => 'disc', 'type' => 'integer', 'fieldName' => 'disc'), $cm->discriminatorColumn);
- $this->assertTrue($cm->getAssociationMapping('phonenumbers') instanceof \Doctrine\ORM\Mapping\OneToOneMapping);
+ $this->assertTrue($cm->associationMappings['phonenumbers']['type'] == ClassMetadata::ONE_TO_ONE);
$this->assertEquals(1, count($cm->associationMappings));
$oneOneMapping = $cm->getAssociationMapping('phonenumbers');
- $this->assertTrue($oneOneMapping->fetchMode == \Doctrine\ORM\Mapping\AssociationMapping::FETCH_LAZY);
- $this->assertEquals('phonenumbers', $oneOneMapping->sourceFieldName);
- $this->assertEquals('Doctrine\Tests\Models\CMS\Bar', $oneOneMapping->targetEntityName);
+ $this->assertTrue($oneOneMapping['fetch'] == ClassMetadata::FETCH_LAZY);
+ $this->assertEquals('phonenumbers', $oneOneMapping['fieldName']);
+ $this->assertEquals('Doctrine\Tests\Models\CMS\Bar', $oneOneMapping['targetEntity']);
}
public function testFieldIsNullable()
@@ -88,7 +87,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
),
));
- $this->assertEquals("DoctrineGlobal_User", $cm->associationMappings['author']->targetEntityName);
+ $this->assertEquals("DoctrineGlobal_User", $cm->associationMappings['author']['targetEntity']);
}
public function testMapManyToManyJoinTableDefaults()
@@ -101,13 +100,13 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
));
$assoc = $cm->associationMappings['groups'];
- $this->assertTrue($assoc instanceof \Doctrine\ORM\Mapping\ManyToManyMapping);
+ //$this->assertTrue($assoc instanceof \Doctrine\ORM\Mapping\ManyToManyMapping);
$this->assertEquals(array(
'name' => 'CmsUser_CmsGroup',
'joinColumns' => array(array('name' => 'CmsUser_id', 'referencedColumnName' => 'id', 'onDelete' => 'CASCADE')),
'inverseJoinColumns' => array(array('name' => 'CmsGroup_id', 'referencedColumnName' => 'id', 'onDelete' => 'CASCADE'))
- ), $assoc->joinTable);
- $this->assertTrue($assoc->isOnDeleteCascade);
+ ), $assoc['joinTable']);
+ $this->assertTrue($assoc['isOnDeleteCascade']);
}
public function testSerializeManyToManyJoinTableCascade()
@@ -123,7 +122,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$assoc = $cm->associationMappings['groups'];
$assoc = unserialize(serialize($assoc));
- $this->assertTrue($assoc->isOnDeleteCascade);
+ $this->assertTrue($assoc['isOnDeleteCascade']);
}
/**
@@ -180,8 +179,8 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
public function testDuplicateAssociationMappingException()
{
$cm = new ClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
- $a1 = new \Doctrine\ORM\Mapping\OneToOneMapping(array('fieldName' => 'foo', 'sourceEntity' => 'stdClass', 'targetEntity' => 'stdClass', 'mappedBy' => 'foo'));
- $a2 = new \Doctrine\ORM\Mapping\OneToOneMapping(array('fieldName' => 'foo', 'sourceEntity' => 'stdClass', 'targetEntity' => 'stdClass', 'mappedBy' => 'foo'));
+ $a1 = array('fieldName' => 'foo', 'sourceEntity' => 'stdClass', 'targetEntity' => 'stdClass', 'mappedBy' => 'foo');
+ $a2 = array('fieldName' => 'foo', 'sourceEntity' => 'stdClass', 'targetEntity' => 'stdClass', 'mappedBy' => 'foo');
$cm->addInheritedAssociationMapping($a1);
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException');
diff --git a/tests/Doctrine/Tests/ORM/PersistentCollectionTest.php b/tests/Doctrine/Tests/ORM/PersistentCollectionTest.php
index 79a7443c7..47eeb8b9a 100644
--- a/tests/Doctrine/Tests/ORM/PersistentCollectionTest.php
+++ b/tests/Doctrine/Tests/ORM/PersistentCollectionTest.php
@@ -32,22 +32,6 @@ class PersistentCollectionTest extends \Doctrine\Tests\OrmTestCase
$class = $this->_emMock->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceProduct');
$collection = new PersistentCollection($this->_emMock, $class, new ArrayCollection);
$collection->setInitialized(false);
- }
-
- public function testQueriesAssociationToLoadItself()
- {
- $class = $this->_emMock->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceProduct');
- $collection = new PersistentCollection($this->_emMock, $class, new ArrayCollection);
- $collection->setInitialized(false);
-
- $association = $this->getMock('Doctrine\ORM\Mapping\OneToManyMapping', array('load'), array(), '', false, false, false);
- $association->targetEntityName = 'Doctrine\Tests\Models\ECommerce\ECommerceFeature';
- $product = new ECommerceProduct();
- $association->expects($this->once())
- ->method('load')
- ->with($product, $this->isInstanceOf($collection), $this->isInstanceOf($this->_emMock));
- $collection->setOwner($product, $association);
-
- count($collection);
+ $this->assertFalse($collection->isInitialized());
}
}
diff --git a/tests/Doctrine/Tests/ORM/Tools/ConvertDoctrine1SchemaTest.php b/tests/Doctrine/Tests/ORM/Tools/ConvertDoctrine1SchemaTest.php
index 94856b831..eafe63d1f 100644
--- a/tests/Doctrine/Tests/ORM/Tools/ConvertDoctrine1SchemaTest.php
+++ b/tests/Doctrine/Tests/ORM/Tools/ConvertDoctrine1SchemaTest.php
@@ -91,8 +91,8 @@ class ConvertDoctrine1SchemaTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('test_alias', $userClass->fieldMappings['theAlias']['columnName']);
$this->assertEquals('theAlias', $userClass->fieldMappings['theAlias']['fieldName']);
- $this->assertEquals('Profile', $profileClass->associationMappings['User']->sourceEntityName);
- $this->assertEquals('User', $profileClass->associationMappings['User']->targetEntityName);
+ $this->assertEquals('Profile', $profileClass->associationMappings['User']['sourceEntity']);
+ $this->assertEquals('User', $profileClass->associationMappings['User']['targetEntity']);
$this->assertEquals('username', $userClass->table['uniqueConstraints']['username']['columns'][0]);
diff --git a/tests/Doctrine/Tests/ORM/Tools/Export/AbstractClassMetadataExporterTest.php b/tests/Doctrine/Tests/ORM/Tools/Export/AbstractClassMetadataExporterTest.php
index 0fa781285..95759c539 100644
--- a/tests/Doctrine/Tests/ORM/Tools/Export/AbstractClassMetadataExporterTest.php
+++ b/tests/Doctrine/Tests/ORM/Tools/Export/AbstractClassMetadataExporterTest.php
@@ -210,18 +210,18 @@ abstract class AbstractClassMetadataExporterTest extends \Doctrine\Tests\OrmTest
public function testOneToOneAssociationsAreExported($class)
{
$this->assertTrue(isset($class->associationMappings['address']));
- $this->assertTrue($class->associationMappings['address'] instanceof \Doctrine\ORM\Mapping\OneToOneMapping);
- $this->assertEquals('Doctrine\Tests\ORM\Tools\Export\Address', $class->associationMappings['address']->targetEntityName);
- $this->assertEquals('address_id', $class->associationMappings['address']->joinColumns[0]['name']);
- $this->assertEquals('id', $class->associationMappings['address']->joinColumns[0]['referencedColumnName']);
- $this->assertEquals('CASCADE', $class->associationMappings['address']->joinColumns[0]['onDelete']);
- $this->assertEquals('CASCADE', $class->associationMappings['address']->joinColumns[0]['onUpdate']);
+ //$this->assertTrue($class->associationMappings['address'] instanceof \Doctrine\ORM\Mapping\OneToOneMapping);
+ $this->assertEquals('Doctrine\Tests\ORM\Tools\Export\Address', $class->associationMappings['address']['targetEntity']);
+ $this->assertEquals('address_id', $class->associationMappings['address']['joinColumns'][0]['name']);
+ $this->assertEquals('id', $class->associationMappings['address']['joinColumns'][0]['referencedColumnName']);
+ $this->assertEquals('CASCADE', $class->associationMappings['address']['joinColumns'][0]['onDelete']);
+ $this->assertEquals('CASCADE', $class->associationMappings['address']['joinColumns'][0]['onUpdate']);
- $this->assertTrue($class->associationMappings['address']->isCascadeRemove);
- $this->assertFalse($class->associationMappings['address']->isCascadePersist);
- $this->assertFalse($class->associationMappings['address']->isCascadeRefresh);
- $this->assertFalse($class->associationMappings['address']->isCascadeMerge);
- $this->assertFalse($class->associationMappings['address']->isCascadeDetach);
+ $this->assertTrue($class->associationMappings['address']['isCascadeRemove']);
+ $this->assertFalse($class->associationMappings['address']['isCascadePersist']);
+ $this->assertFalse($class->associationMappings['address']['isCascadeRefresh']);
+ $this->assertFalse($class->associationMappings['address']['isCascadeMerge']);
+ $this->assertFalse($class->associationMappings['address']['isCascadeDetach']);
return $class;
}
@@ -233,16 +233,16 @@ abstract class AbstractClassMetadataExporterTest extends \Doctrine\Tests\OrmTest
public function testOneToManyAssociationsAreExported($class)
{
$this->assertTrue(isset($class->associationMappings['phonenumbers']));
- $this->assertTrue($class->associationMappings['phonenumbers'] instanceof \Doctrine\ORM\Mapping\OneToManyMapping);
- $this->assertEquals('Doctrine\Tests\ORM\Tools\Export\Phonenumber', $class->associationMappings['phonenumbers']->targetEntityName);
- $this->assertEquals('user', $class->associationMappings['phonenumbers']->mappedBy);
- $this->assertEquals(array('number' => 'ASC'), $class->associationMappings['phonenumbers']->orderBy);
+ //$this->assertTrue($class->associationMappings['phonenumbers'] instanceof \Doctrine\ORM\Mapping\OneToManyMapping);
+ $this->assertEquals('Doctrine\Tests\ORM\Tools\Export\Phonenumber', $class->associationMappings['phonenumbers']['targetEntity']);
+ $this->assertEquals('user', $class->associationMappings['phonenumbers']['mappedBy']);
+ $this->assertEquals(array('number' => 'ASC'), $class->associationMappings['phonenumbers']['orderBy']);
- $this->assertFalse($class->associationMappings['phonenumbers']->isCascadeRemove);
- $this->assertTrue($class->associationMappings['phonenumbers']->isCascadePersist);
- $this->assertFalse($class->associationMappings['phonenumbers']->isCascadeRefresh);
- $this->assertFalse($class->associationMappings['phonenumbers']->isCascadeMerge);
- $this->assertFalse($class->associationMappings['phonenumbers']->isCascadeDetach);
+ $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeRemove']);
+ $this->assertTrue($class->associationMappings['phonenumbers']['isCascadePersist']);
+ $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeRefresh']);
+ $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeMerge']);
+ $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeDetach']);
return $class;
}
@@ -254,22 +254,22 @@ abstract class AbstractClassMetadataExporterTest extends \Doctrine\Tests\OrmTest
public function testManyToManyAssociationsAreExported($class)
{
$this->assertTrue(isset($class->associationMappings['groups']));
- $this->assertTrue($class->associationMappings['groups'] instanceof \Doctrine\ORM\Mapping\ManyToManyMapping);
- $this->assertEquals('Doctrine\Tests\ORM\Tools\Export\Group', $class->associationMappings['groups']->targetEntityName);
- $this->assertEquals('cms_users_groups', $class->associationMappings['groups']->joinTable['name']);
+ //$this->assertTrue($class->associationMappings['groups'] instanceof \Doctrine\ORM\Mapping\ManyToManyMapping);
+ $this->assertEquals('Doctrine\Tests\ORM\Tools\Export\Group', $class->associationMappings['groups']['targetEntity']);
+ $this->assertEquals('cms_users_groups', $class->associationMappings['groups']['joinTable']['name']);
- $this->assertEquals('user_id', $class->associationMappings['groups']->joinTable['joinColumns'][0]['name']);
- $this->assertEquals('id', $class->associationMappings['groups']->joinTable['joinColumns'][0]['referencedColumnName']);
+ $this->assertEquals('user_id', $class->associationMappings['groups']['joinTable']['joinColumns'][0]['name']);
+ $this->assertEquals('id', $class->associationMappings['groups']['joinTable']['joinColumns'][0]['referencedColumnName']);
- $this->assertEquals('group_id', $class->associationMappings['groups']->joinTable['inverseJoinColumns'][0]['name']);
- $this->assertEquals('id', $class->associationMappings['groups']->joinTable['inverseJoinColumns'][0]['referencedColumnName']);
- $this->assertEquals('INT NULL', $class->associationMappings['groups']->joinTable['inverseJoinColumns'][0]['columnDefinition']);
+ $this->assertEquals('group_id', $class->associationMappings['groups']['joinTable']['inverseJoinColumns'][0]['name']);
+ $this->assertEquals('id', $class->associationMappings['groups']['joinTable']['inverseJoinColumns'][0]['referencedColumnName']);
+ $this->assertEquals('INT NULL', $class->associationMappings['groups']['joinTable']['inverseJoinColumns'][0]['columnDefinition']);
- $this->assertTrue($class->associationMappings['groups']->isCascadeRemove);
- $this->assertTrue($class->associationMappings['groups']->isCascadePersist);
- $this->assertTrue($class->associationMappings['groups']->isCascadeRefresh);
- $this->assertTrue($class->associationMappings['groups']->isCascadeMerge);
- $this->assertTrue($class->associationMappings['groups']->isCascadeDetach);
+ $this->assertTrue($class->associationMappings['groups']['isCascadeRemove']);
+ $this->assertTrue($class->associationMappings['groups']['isCascadePersist']);
+ $this->assertTrue($class->associationMappings['groups']['isCascadeRefresh']);
+ $this->assertTrue($class->associationMappings['groups']['isCascadeMerge']);
+ $this->assertTrue($class->associationMappings['groups']['isCascadeDetach']);
return $class;
}
@@ -298,10 +298,10 @@ abstract class AbstractClassMetadataExporterTest extends \Doctrine\Tests\OrmTest
*/
public function testCascadeIsExported($class)
{
- $this->assertTrue($class->associationMappings['phonenumbers']->isCascadePersist);
- $this->assertFalse($class->associationMappings['phonenumbers']->isCascadeMerge);
- $this->assertFalse($class->associationMappings['phonenumbers']->isCascadeRemove);
- $this->assertFalse($class->associationMappings['phonenumbers']->isCascadeRefresh);
+ $this->assertTrue($class->associationMappings['phonenumbers']['isCascadePersist']);
+ $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeMerge']);
+ $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeRemove']);
+ $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeRefresh']);
return $class;
}
@@ -312,7 +312,7 @@ abstract class AbstractClassMetadataExporterTest extends \Doctrine\Tests\OrmTest
*/
public function testInversedByIsExported($class)
{
- $this->assertEquals('user', $class->associationMappings['address']->inversedBy);
+ $this->assertEquals('user', $class->associationMappings['address']['inversedBy']);
}
public function __destruct()