Commit d8b76a54 authored by romanb's avatar romanb

continued refactorings.

parent 3e20fc6a
......@@ -34,8 +34,7 @@
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @todo Consider making Collection & Entity implement ArrayAccess directly.
* This base class is not really a huge benefit.
* @todo Remove.
*/
abstract class Doctrine_Access implements ArrayAccess
{
......
......@@ -24,8 +24,8 @@
/**
* Base class for association mappings.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
* @todo Rename to AssociationMapping.
*/
class Doctrine_Association implements Serializable
......@@ -52,6 +52,9 @@ class Doctrine_Association implements Serializable
protected $_isCascadeSave;
protected $_isCascadeRefresh;
protected $_customAccessor;
protected $_customMutator;
/**
* The fetch mode used for the association.
*
......@@ -67,6 +70,14 @@ class Doctrine_Association implements Serializable
*/
protected $_isOwningSide = true;
/**
* Whether the association is optional (0..X) or not (1..X).
* By default all associations are optional.
*
* @var boolean
*/
protected $_isOptional = true;
/**
* The name of the source Entity (the Entity that defines this mapping).
*
......@@ -84,7 +95,8 @@ class Doctrine_Association implements Serializable
/**
* Identifies the field on the source class (the class this AssociationMapping
* belongs to) that represents the association.
* belongs to) that represents the association and stores the reference to the
* other entity/entities.
*
* @var string
*/
......@@ -106,12 +118,13 @@ class Doctrine_Association implements Serializable
*/
public function __construct(array $mapping)
{
$this->_validateMapping($mapping);
if ($this->_isOwningSide) {
$this->_sourceEntityName = $mapping['sourceEntity'];
$this->_targetEntityName = $mapping['targetEntity'];
$this->_sourceFieldName = $mapping['fieldName'];
} else {
$this->_validateAndCompleteMapping($mapping);
$this->_sourceEntityName = $mapping['sourceEntity'];
$this->_targetEntityName = $mapping['targetEntity'];
$this->_sourceFieldName = $mapping['fieldName'];
if ( ! $this->_isOwningSide) {
$this->_mappedByFieldName = $mapping['mappedBy'];
}
}
......@@ -122,23 +135,50 @@ class Doctrine_Association implements Serializable
* @param array $mapping
* @return array The validated & completed mapping.
*/
protected function _validateMapping(array $mapping)
{
protected function _validateAndCompleteMapping(array $mapping)
{
if (isset($mapping['mappedBy'])) {
// Inverse side, mapping can be found on the owning side.
$this->_isOwningSide = false;
} else {
// Owning side
}
if ($this->_isOwningSide) {
if ( ! isset($mapping['targetEntity'])) {
throw Doctrine_MappingException::missingTargetEntity();
} else if ( ! isset($mapping['fieldName'])) {
throw Doctrine_MappingException::missingFieldName();
}
// Mandatory attributes
if ( ! isset($mapping['fieldName'])) {
throw Doctrine_MappingException::missingFieldName();
}
if ( ! isset($mapping['sourceEntity'])) {
throw Doctrine_MappingException::missingSourceEntity($mapping['fieldName']);
}
if ( ! isset($mapping['targetEntity'])) {
throw Doctrine_MappingException::missingTargetEntity($mapping['fieldName']);
}
// Optional attributes
$this->_customAccessor = isset($mapping['accessor']) ? $mapping['accessor'] : null;
$this->_customMutator = isset($mapping['mutator']) ? $mapping['mutator'] : null;
$this->_isOptional = isset($mapping['isOptional']) ? (bool)$mapping['isOptional'] : true;
return $mapping;
}
protected function _validateAndCompleteInverseSideMapping()
{
}
protected function _validateAndCompleteOwningSideMapping()
{
}
/**
* Whether the association cascades delete() operations from the source entity
* to the target entity/entities.
*
* @return boolean
*/
public function isCascadeDelete()
{
if (is_null($this->_isCascadeDelete)) {
......@@ -147,6 +187,12 @@ class Doctrine_Association implements Serializable
return $this->_isCascadeDelete;
}
/**
* Whether the association cascades save() operations from the source entity
* to the target entity/entities.
*
* @return boolean
*/
public function isCascadeSave()
{
if (is_null($this->_isCascadeSave)) {
......@@ -155,6 +201,12 @@ class Doctrine_Association implements Serializable
return $this->_isCascadeSave;
}
/**
* Whether the association cascades refresh() operations from the source entity
* to the target entity/entities.
*
* @return boolean
*/
public function isCascadeRefresh()
{
if (is_null($this->_isCascadeRefresh)) {
......@@ -163,36 +215,81 @@ class Doctrine_Association implements Serializable
return $this->_isCascadeRefresh;
}
/**
* 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 target entity/entities of the association are manually fetched.
*
* @return boolean
*/
public function isManuallyFetched()
{
return $this->_fetchMode == self::FETCH_MANUAL;
}
/**
* Whether the source entity of this association represents the owning side.
*
* @return boolean
*/
public function isOwningSide()
{
return $this->_isOwningSide;
}
/**
* Whether the source entity of this association represents the inverse side.
*
* @return boolean
*/
public function isInverseSide()
{
return ! $this->_isOwningSide;
}
/**
* Whether the association is optional (0..X), or not (1..X).
*
* @return boolean TRUE if the association is optional, FALSE otherwise.
*/
public function isOptional()
{
return $this->_isOptional;
}
/**
* Gets the name of the source entity class.
*
* @return string
*/
public function getSourceEntityName()
{
return $this->_sourceEntityName;
}
/**
* Gets the name of the target entity class.
*
* @return string
*/
public function getTargetEntityName()
{
return $this->_targetEntityName;
......@@ -201,17 +298,80 @@ class Doctrine_Association implements Serializable
/**
* Get the name of the field the association is mapped into.
*
* @return string
*/
public function getSourceFieldName()
{
return $this->_sourceFieldName;
}
/**
* Gets the field name of the owning side in a bi-directional association.
*
* @return string
*/
public function getMappedByFieldName()
{
return $this->_mappedByFieldName;
}
/**
* Whether the source field of the association has a custom accessor.
*
* @return boolean TRUE if the source field of the association has a custom accessor,
* FALSE otherwise.
*/
public function hasCustomAccessor()
{
return isset($this->_customAccessor);
}
/**
* Gets the name of the custom accessor method of the source field.
*
* @return string The name of the accessor method or NULL.
*/
public function getCustomAccessor()
{
return $this->_customAccessor;
}
/**
* Whether the source field of the association has a custom mutator.
*
* @return boolean TRUE if the source field of the association has a custom mutator,
* FALSE otherwise.
*/
public function hasCustomMutator()
{
return isset($this->_customMutator);
}
/**
* Gets the name of the custom mutator method of the source field.
*
* @return string The name of the mutator method or NULL.
*/
public function getCustomMutator()
{
return $this->_customMutator;
}
public function isOneToOne()
{
return false;
}
public function isOneToMany()
{
return false;
}
public function isManyToMany()
{
return false;
}
/* Serializable implementation */
public function serialize()
......
......@@ -105,6 +105,17 @@ class Doctrine_Association_OneToOne extends Doctrine_Association
return $this->_targetToSourceKeyColumns;
}
/**
* Whether the association is one-to-one.
*
* @return boolean
* @override
*/
public function isOneToOne()
{
return true;
}
/**
* Lazy-loads the associated entity for a given entity.
*
......
This diff is collapsed.
......@@ -23,7 +23,7 @@
/**
* The metadata factory is used to create ClassMetadata objects that contain all the
* metadata of a class.
* metadata mapping informations of a class.
*
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Roman Borschel <roman@code-factory.org>
......@@ -45,7 +45,7 @@ class Doctrine_ClassMetadata_Factory
/**
* Constructor.
* Creates a new factory instance that uses the given connection and metadata driver
* Creates a new factory instance that uses the given EntityManager and metadata driver
* implementations.
*
* @param $conn The connection to use.
......@@ -129,6 +129,12 @@ class Doctrine_ClassMetadata_Factory
}
}
/**
* Adds inherited fields to the subclass mapping.
*
* @param unknown_type $subClass
* @param unknown_type $parentClass
*/
protected function _addInheritedFields($subClass, $parentClass)
{
foreach ($parentClass->getFieldMappings() as $fieldName => $mapping) {
......@@ -138,6 +144,12 @@ class Doctrine_ClassMetadata_Factory
}
}
/**
* Adds inherited associations to the subclass mapping.
*
* @param unknown_type $subClass
* @param unknown_type $parentClass
*/
protected function _addInheritedRelations($subClass, $parentClass)
{
foreach ($parentClass->getRelationParser()->getRelationDefinitions() as $name => $definition) {
......@@ -177,7 +189,7 @@ class Doctrine_ClassMetadata_Factory
// save parents
$class->setParentClasses($names);
// load further metadata
// load user-specified mapping metadata through the driver
$this->_driver->loadMetadataForClass($name, $class);
// set default table name, if necessary
......
This diff is collapsed.
<?php
class Doctrine_CollectionPersister_Abstract
{
public function recreate(Doctrine_Collection $coll)
{
if ($coll->getRelation()->isInverseSide()) {
return;
}
//...
}
public function delete(Doctrine_Collection $coll)
{
if ($coll->getRelation()->isInverseSide()) {
return;
}
//...
if ($coll->getRelation() instanceof Doctrine_Association_OneToManyMapping) {
//...
} else if ($coll->getRelation() instanceof Doctrine_Association_ManyToManyMapping) {
//...
}
}
/* collection update actions */
public function deleteRows()
{
}
public function updateRows()
{
}
public function insertRows()
{
}
}
?>
\ No newline at end of file
<?php
class Doctrine_CollectionPersister_OneToManyPersister extends Doctrine_CollectionPersister_Abstract
{
}
?>
\ No newline at end of file
......@@ -77,6 +77,27 @@ class Doctrine_Connection_UnitOfWork
* @todo Rename to _deletions?
*/
protected $_deletedEntities = array();
/**
* All collection deletions.
*
* @var array
*/
protected $_collectionDeletions = array();
/**
* All collection creations.
*
* @var array
*/
protected $_collectionCreations = array();
/**
* All collection updates.
*
* @var array
*/
protected $_collectionUpdates = array();
/**
* The EntityManager the UnitOfWork belongs to.
......@@ -115,16 +136,16 @@ class Doctrine_Connection_UnitOfWork
public function commit()
{
// Detect changes in managed entities (mark dirty)
//TODO: Consider using registerDirty() in Entity#set() instead if its
// more performant.
foreach ($this->_identityMap as $entities) {
//TODO: Consider using registerDirty() in Entity#_set() instead if its
// more performant (SEE THERE).
/*foreach ($this->_identityMap as $entities) {
foreach ($entities as $entity) {
if ($entity->_state() == Doctrine_Entity::STATE_MANAGED
&& $entity->isModified()) {
$this->registerDirty($entity);
}
}
}
}*/
if (empty($this->_newEntities) &&
empty($this->_deletedEntities) &&
......@@ -141,8 +162,12 @@ class Doctrine_Connection_UnitOfWork
$this->_executeInserts($class);
$this->_executeUpdates($class);
}
//TODO: collection deletions
//TODO: collection updates (deleteRows, updateRows, insertRows)
//TODO: collection recreations
// Deletions come last and need to be in reverse commit order
// Entity deletions come last and need to be in reverse commit order
for ($count = count($commitOrder), $i = $count - 1; $i >= 0; $i--) {
$this->_executeDeletions($commitOrder[$i]);
}
......@@ -232,7 +257,7 @@ class Doctrine_Connection_UnitOfWork
foreach ($node->getClass()->getAssociationMappings() as $assocMapping) {
//TODO: should skip target classes that are not in the changeset.
if ($assocMapping->isOwningSide()) {
$targetClass = $assocMapping->getTargetClass();
$targetClass = $this->_em->getClassMetadata($assocMapping->getTargetEntityName());
$targetClassName = $targetClass->getClassName();
// if the target class does not yet have a node, create it
if ( ! $this->_commitOrderCalculator->hasNodeWithKey($targetClassName)) {
......@@ -711,6 +736,38 @@ class Doctrine_Connection_UnitOfWork
$this->_commitOrderCalculator->clear();
}
public function scheduleCollectionUpdate(Doctrine_Collection $coll)
{
$this->_collectionUpdates[] = $coll;
}
public function isCollectionScheduledForUpdate(Doctrine_Collection $coll)
{
//...
}
public function scheduleCollectionDeletion(Doctrine_Collection $coll)
{
//TODO: if $coll is already scheduled for recreation ... what to do?
// Just remove $coll from the scheduled recreations?
$this->_collectionDeletions[] = $coll;
}
public function isCollectionScheduledForDeletion(Doctrine_Collection $coll)
{
//...
}
public function scheduleCollectionRecreation(Doctrine_Collection $coll)
{
$this->_collectionRecreations[] = $coll;
}
public function isCollectionScheduledForRecreation(Doctrine_Collection $coll)
{
//...
}
// Stuff from 0.11/1.0 that we will need later (need to modify it though)
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
#namespace Doctrine::DBAL::Platforms;
......@@ -9,6 +28,7 @@
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
*/
abstract class Doctrine_DatabasePlatform
{
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
/**
* The MySqlPlatform provides the behavior, features and SQL dialect of the
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
/**
* Base class for all DatabasePlatforms. The DatabasePlatforms are the central
* point of abstraction of platform-specific behaviors, features and SQL dialects.
* They are a passive source of information.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
*/
class Doctrine_DatabasePlatform_OraclePlatform extends Doctrine_DatabasePlatform
{
/**
......
This diff is collapsed.
......@@ -29,7 +29,6 @@
#use Doctrine::ORM::Internal::UnitOfWork;
#use Doctrine::ORM::Mapping::ClassMetadata;
/**
* The EntityManager is the central access point to ORM functionality.
*
......@@ -38,12 +37,28 @@
* @since 2.0
* @version $Revision$
* @author Roman Borschel <roman@code-factory.org>
* @todo package:orm
*/
class Doctrine_EntityManager
{
/**
* IMMEDIATE: Flush occurs automatically after each operation that issues database
* queries. No operations are queued.
*/
const FLUSHMODE_IMMEDIATE = 'immediated';
/**
* AUTO: Flush occurs automatically in the following situations:
* - Before any query executions (to prevent getting stale data)
* - On EntityManager#commit()
*/
const FLUSHMODE_AUTO = 'auto';
/**
* COMMIT: Flush occurs automatically only on EntityManager#commit().
*/
const FLUSHMODE_COMMIT = 'commit';
/**
* MANUAL: Flush occurs never automatically. The only way to flush is
* through EntityManager#flush().
*/
const FLUSHMODE_MANUAL = 'manual';
/**
......@@ -68,19 +83,6 @@ class Doctrine_EntityManager
*/
private $_conn;
/**
* Flush modes enumeration.
*/
private static $_flushModes = array(
// auto: Flush occurs automatically after each operation that issues database
// queries. No operations are queued.
self::FLUSHMODE_AUTO,
// commit: Flush occurs automatically at transaction commit.
self::FLUSHMODE_COMMIT,
// manual: Flush occurs never automatically.
self::FLUSHMODE_MANUAL
);
/**
* The metadata factory, used to retrieve the metadata of entity classes.
*
......@@ -160,7 +162,6 @@ class Doctrine_EntityManager
* Gets the metadata for a class. Alias for getClassMetadata().
*
* @return Doctrine_Metadata
* @todo package:orm
*/
public function getMetadata($className)
{
......@@ -324,12 +325,20 @@ class Doctrine_EntityManager
*/
public function setFlushMode($flushMode)
{
if ( ! in_array($flushMode, self::$_flushModes)) {
if ( ! $this->_isFlushMode($flushMode)) {
throw Doctrine_EntityManager_Exception::invalidFlushMode();
}
$this->_flushMode = $flushMode;
}
private function _isFlushMode($value)
{
return $value == self::FLUSHMODE_AUTO ||
$value == self::FLUSHMODE_COMMIT ||
$value == self::FLUSHMODE_IMMEDIATE ||
$value == self::FLUSHMODE_MANUAL;
}
/**
* Gets the currently used flush mode.
*
......@@ -365,10 +374,9 @@ class Doctrine_EntityManager
}
/**
* getResultCacheDriver
* Gets the result cache driver used by the EntityManager.
*
* @return Doctrine_Cache_Interface
* @todo package:orm
* @return Doctrine::ORM::Cache::CacheDriver The cache driver.
*/
public function getResultCacheDriver()
{
......@@ -383,7 +391,6 @@ class Doctrine_EntityManager
* getQueryCacheDriver
*
* @return Doctrine_Cache_Interface
* @todo package:orm
*/
public function getQueryCacheDriver()
{
......@@ -396,31 +403,45 @@ class Doctrine_EntityManager
/**
* Saves the given entity, persisting it's state.
*
* @param Doctrine::ORM::Entity $entity
* @return void
*/
public function save(Doctrine_Entity $entity)
{
$this->_unitOfWork->save($entity);
if ($this->_flushMode == self::FLUSHMODE_AUTO) {
if ($this->_flushMode == self::FLUSHMODE_IMMEDIATE) {
$this->flush();
}
}
/**
* Removes the given entity from the persistent store.
*
* @param Doctrine::ORM::Entity $entity
* @return void
*/
public function delete(Doctrine_Entity $entity)
{
$this->_unitOfWork->delete($entity);
if ($this->_flushMode == self::FLUSHMODE_IMMEDIATE) {
$this->flush();
}
}
/**
* Refreshes the persistent state of the entity from the database.
* Refreshes the persistent state of the entity from the database,
* overriding any local changes that have not yet been persisted.
*
* @param Doctrine_Entity $entity
* @param Doctrine::ORM::Entity $entity
* @return void
* @todo FIX Impl
*/
public function refresh(Doctrine_Entity $entity)
{
//...
$this->_mergeData($entity, $entity->getRepository()->find(
$entity->identifier(), Doctrine_Query::HYDRATE_ARRAY),
true);
}
/**
......@@ -463,7 +484,7 @@ class Doctrine_EntityManager
*
* @param string $className The name of the entity class.
* @param array $data The data for the entity.
* @return Doctrine_Entity
* @return Doctrine::ORM::Entity
*/
public function createEntity($className, array $data)
{
......@@ -488,6 +509,7 @@ class Doctrine_EntityManager
$idHash = $this->_unitOfWork->getIdentifierHash($id);
if ($entity = $this->_unitOfWork->tryGetByIdHash($idHash,
$classMetadata->getRootClassName())) {
$this->_mergeData($entity, $data);
return $entity;
} else {
$entity = new $className;
......@@ -501,10 +523,35 @@ class Doctrine_EntityManager
return $entity;
}
/**
* Merges the given data into the given entity, optionally overriding
* local changes.
*
* @param Doctrine::ORM::Entity $entity
* @param array $data
* @param boolean $overrideLocalChanges
* @return void
*/
private function _mergeData(Doctrine_Entity $entity, array $data, $overrideLocalChanges = false) {
if ($overrideLocalChanges) {
foreach ($data as $field => $value) {
$entity->_internalSetField($field, $value);
}
} else {
foreach ($data as $field => $value) {
if ( ! $entity->contains($field) || $entity->_internalGetField($field) === null) {
$entity->_internalSetField($field, $value);
}
}
}
}
/**
* Checks if the instance is managed by the EntityManager.
*
* @return boolean
* @param Doctrine::ORM::Entity $entity
* @return boolean TRUE if this EntityManager currently manages the given entity
* (and has it in the identity map), FALSE otherwise.
*/
public function contains(Doctrine_Entity $entity)
{
......@@ -513,8 +560,11 @@ class Doctrine_EntityManager
}
/**
* INTERNAL:
* For internal hydration purposes only.
* INTERNAL: For internal hydration purposes only.
*
* Gets the temporarily stored entity data.
*
* @return array
*/
public function _getTmpEntityData()
{
......@@ -528,6 +578,8 @@ class Doctrine_EntityManager
* class to instantiate. If no discriminator column is found, the given
* classname will be returned.
*
* @param array $data
* @param string $className
* @return string The name of the class to instantiate.
*/
private function _inferCorrectClassName(array $data, $className)
......@@ -562,6 +614,7 @@ class Doctrine_EntityManager
* Sets the EventManager used by the EntityManager.
*
* @param Doctrine::Common::EventManager $eventManager
* @return void
*/
public function setEventManager(Doctrine_EventManager $eventManager)
{
......@@ -572,6 +625,7 @@ class Doctrine_EntityManager
* Sets the Configuration used by the EntityManager.
*
* @param Doctrine::Common::Configuration $config
* @return void
*/
public function setConfiguration(Doctrine_Configuration $config)
{
......
......@@ -55,7 +55,7 @@ abstract class Doctrine_EntityPersister_Abstract
/**
* The Doctrine_Connection object that the database connection of this mapper.
*
* @var Doctrine_Connection $conn
* @var Doctrine::DBAL::Connection $conn
*/
protected $_conn;
......@@ -85,17 +85,58 @@ abstract class Doctrine_EntityPersister_Abstract
public function insert(Doctrine_Entity $entity)
{
//...
$insertData = array();
$dataChangeSet = $entity->_getDataChangeSet();
$referenceChangeSet = $entity->_getReferenceChangeSet();
foreach ($referenceChangeSet as $field => $change) {
list($old, $new) = each($change);
$assocMapping = $entity->getClass()->getAssociationMapping($field);
if ($assocMapping->isOneToOne()) {
if ($assocMapping->isInverseSide()) {
//echo "INVERSE!";
continue; // ignore inverse side
}
foreach ($assocMapping->getSourceToTargetKeyColumns() as $localColumn => $foreignColumn) {
//echo "$localColumn -- $foreignColumn<br/>";
//$insertData[$localColumn] = 1; //FIX
}
// ... set the foreign key column to the id of the related entity ($new)
}
//...
}
foreach ($dataChangeSet as $field => $change) {
$insertData[$entity->getClass()->getColumnName($field)] = current($change);
}
//TODO: perform insert
$this->_conn->insert($entity->getClass()->getTableName(), $insertData);
}
public function update(Doctrine_Entity $entity)
{
//...
$dataChangeSet = $entity->_getDataChangeSet();
$referenceChangeSet = $entity->_getReferenceChangeSet();
foreach ($referenceChangeSet as $field => $change) {
$assocMapping = $entity->getClass()->getAssociationMapping($field);
if ($assocMapping instanceof Doctrine_Association_OneToOneMapping) {
if ($assocMapping->isInverseSide()) {
continue; // ignore inverse side
}
// ... null out the foreign key
}
//...
}
//TODO: perform update
}
public function delete(Doctrine_Entity $entity)
{
//TODO: perform delete
}
/**
......@@ -182,6 +223,64 @@ abstract class Doctrine_EntityPersister_Abstract
return $converted;
}
/**
* Returns an array of modified fields and values with data preparation
* adds column aggregation inheritance and converts Records into primary key values
*
* @param array $array
* @return array
* @todo Move to EntityPersister. There call _getChangeSet() and apply this logic.
*/
public function prepareData(array $data = array())
{
$dataSet = array();
$modifiedFields = $fields;
foreach ($data as $field => $value) {
$type = $this->_classMetadata->getTypeOfField($field);
if ($value === Doctrine_Null::$INSTANCE) {
$dataSet[$field] = null;
continue;
}
switch ($type) {
case 'array':
case 'object':
$dataSet[$field] = serialize($value);
break;
case 'gzip':
$dataSet[$field] = gzcompress($value, 5);
break;
case 'boolean':
$dataSet[$field] = $this->_em->getConnection()
->convertBooleans($value);
break;
case 'enum':
$dataSet[$field] = $this->_class->enumIndex($field, $value);
break;
default:
$dataSet[$field] = $value;
}
}
// @todo cleanup
// populates the discriminator field in Single & Class Table Inheritance
if ($this->_classMetadata->getInheritanceType() == Doctrine_ClassMetadata::INHERITANCE_TYPE_JOINED ||
$this->_class->getInheritanceType() == Doctrine_ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE) {
$discCol = $this->_classMetadata->getInheritanceOption('discriminatorColumn');
$discMap = $this->_classMetadata->getInheritanceOption('discriminatorMap');
$old = $this->get($discCol, false);
$discValue = array_search($this->_entityName, $discMap);
if ((string) $old !== (string) $discValue || $old === null) {
$dataSet[$discCol] = $discValue;
//$this->_data[$discCol] = $discValue;
}
}
return $dataSet;
}
......@@ -226,75 +325,6 @@ abstract class Doctrine_EntityPersister_Abstract
return $this->_em;
}
/**
* prepareValue
* this method performs special data preparation depending on
* the type of the given column
*
* 1. It unserializes array and object typed columns
* 2. Uncompresses gzip typed columns
* 3. Gets the appropriate enum values for enum typed columns
* 4. Initializes special null object pointer for null values (for fast column existence checking purposes)
*
* example:
* <code type='php'>
* $field = 'name';
* $value = null;
* $table->prepareValue($field, $value); // Doctrine_Null
* </code>
*
* @throws Doctrine_Table_Exception if unserialization of array/object typed column fails or
* @throws Doctrine_Table_Exception if uncompression of gzip typed column fails *
* @param string $field the name of the field
* @param string $value field value
* @param string $typeHint A hint on the type of the value. If provided, the type lookup
* for the field can be skipped. Used i.e. during hydration to
* improve performance on large and/or complex results.
* @return mixed prepared value
* @todo To EntityManager. Make private and use in createEntity().
* .. Or, maybe better: Move to hydrator for performance reasons.
*/
/*public function prepareValue($fieldName, $value, $typeHint = null)
{
if ($value === $this->_nullObject) {
return $this->_nullObject;
} else if ($value === null) {
return null;
} else {
$type = is_null($typeHint) ? $this->_classMetadata->getTypeOf($fieldName) : $typeHint;
switch ($type) {
case 'integer':
case 'string';
// don't do any casting here PHP INT_MAX is smaller than what the databases support
break;
case 'enum':
return $this->_classMetadata->enumValue($fieldName, $value);
break;
case 'boolean':
return (boolean) $value;
break;
case 'array':
case 'object':
if (is_string($value)) {
$value = unserialize($value);
if ($value === false) {
throw new Doctrine_Mapper_Exception('Unserialization of ' . $fieldName . ' failed.');
}
return $value;
}
break;
case 'gzip':
$value = gzuncompress($value);
if ($value === false) {
throw new Doctrine_Mapper_Exception('Uncompressing of ' . $fieldName . ' failed.');
}
return $value;
break;
}
}
return $value;
}*/
/**
* getComponentName
*
......
......@@ -24,8 +24,6 @@
* as is the case in Single Table Inheritance & Concrete Table Inheritance.
*
* @author Roman Borschel <roman@code-factory.org>
* @package Doctrine
* @subpackage Abstract
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version $Revision$
* @link www.phpdoctrine.org
......@@ -72,7 +70,6 @@ class Doctrine_EntityPersister_Standard extends Doctrine_EntityPersister_Abstrac
return false;
}
//$class = $record->getClassMetadata();
$class = $this->_classMetadata;
$identifier = $class->getIdentifier();
$fields = $this->_convertFieldToColumnNames($fields, $class);
......
......@@ -19,11 +19,11 @@
* <http://www.phpdoctrine.org>.
*/
#namespace Doctrine::Common;
#namespace Doctrine::Common::Event;
/**
* The EventManager is the central point of Doctrine's event listener system.
* Listeners are registered on the manager and events are dispatch through the
* Listeners are registered on the manager and events are dispatched through the
* manager.
*
* @author Roman Borschel <roman@code-factory.org>
......@@ -100,6 +100,17 @@ class Doctrine_EventManager
$this->_listeners[$event] = $listener;
}
}
/**
* Adds an EventSubscriber. The subscriber is asked for all the events he is
* interested in and added as a listener for these events.
*
* @param Doctrine::Common::Event::EventSubscriber $subscriber The subscriber.
*/
public function addEventSubscriber(Doctrine_EventSubscriber $subscriber)
{
$this->addEventListener($subscriber->getSubscribedEvents(), $subscriber);
}
}
?>
\ No newline at end of file
......@@ -49,7 +49,7 @@ class Doctrine_Exception extends Exception
return $this->_innerException;
}
public static function notImplemented($method, $class)
public static function notYetImplemented($method, $class)
{
return new self("The method '$method' is not implemented in the class '$class'.");
}
......
......@@ -70,8 +70,8 @@ class Doctrine_Hydrator_RecordDriver
public function initRelatedCollection(Doctrine_Entity $entity, $name)
{
if ( ! isset($this->_initializedRelations[$entity->getOid()][$name])) {
$relation = $entity->getClass()->getRelation($name);
$relatedClass = $relation->getTable();
$relation = $entity->getClass()->getAssociationMapping($name);
$relatedClass = $this->_em->getClassMetadata($relation->getTargetEntityName());
$coll = $this->getElementCollection($relatedClass->getClassName());
$coll->setReference($entity, $relation);
$entity->_internalSetReference($name, $coll);
......
......@@ -49,8 +49,6 @@
* That's why the performance of the _gatherRowData() methods which are responsible
* for the "numRowsInResult * numColumnsInResult" part is crucial to fast hydration.
*
* @package Doctrine
* @subpackage Hydrator
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
......@@ -212,7 +210,7 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract
$entityName = $map['metadata']->getClassName();
$parent = $map['parent'];
$relation = $map['relation'];
$relationAlias = $relation->getAlias();
$relationAlias = $relation->getSourceFieldName();//$relation->getAlias();
$path = $parent . '.' . $dqlAlias;
// pick the right element that will get the associated element attached
......
......@@ -9,8 +9,8 @@ class Doctrine_MappingException extends Doctrine_Exception
{
public static function identifierRequired($entityName)
{
return new self("No identifier specified for Entity '$entityName'."
. " Every Entity must have an identifier.");
return new self("No identifier/primary key specified for Entity '$entityName'."
. " Every Entity must have an identifier/primary key.");
}
public static function invalidInheritanceType($type)
......@@ -28,6 +28,25 @@ class Doctrine_MappingException extends Doctrine_Exception
return new self("Id generators can't be used with a composite id.");
}
public static function missingFieldName()
{
return new self("The association mapping misses the 'fieldName' attribute.");
}
public static function missingTargetEntity($fieldName)
{
return new self("The association mapping '$fieldName' misses the 'targetEntity' attribute.");
}
public static function missingSourceEntity($fieldName)
{
return new self("The association mapping '$fieldName' misses the 'sourceEntity' attribute.");
}
public static function mappingNotFound($fieldName)
{
return new self("No mapping found for field '$fieldName'.");
}
}
?>
\ No newline at end of file
......@@ -20,10 +20,6 @@
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Query_AbstractResult');
Doctrine::autoload('Doctrine_Query_ParserResult');
Doctrine::autoload('Doctrine_Query_QueryResult');
/**
* Doctrine_Query_CacheHandler
*
......@@ -136,8 +132,8 @@ abstract class Doctrine_Query_CacheHandler
$queryComponents[$alias]['table'] = $queryComponents[$alias]['mapper']->getTable();
} else {
$queryComponents[$alias]['parent'] = $e[0];
$queryComponents[$alias]['relation'] = $queryComponents[$e[0]]['table']->getRelation($e[1]);
$queryComponents[$alias]['mapper'] = $query->getConnection()->getMapper($queryComponents[$alias]['relation']->getForeignComponentName());
$queryComponents[$alias]['relation'] = $queryComponents[$e[0]]['table']->getAssociation($e[1]);
$queryComponents[$alias]['mapper'] = $query->getConnection()->getMapper($queryComponents[$alias]['relation']->getTargetEntityName());
$queryComponents[$alias]['table'] = $queryComponents[$alias]['mapper']->getTable();
}
......
......@@ -50,7 +50,7 @@ class Doctrine_Query_Production_Join extends Doctrine_Query_Production
$this->_parser->match(Doctrine_Query_Token::T_LEFT);
$this->_joinType = 'LEFT';
} elseif ($this->_isNextToken(Doctrine_Query_Token::T_INNER)) {
} else if ($this->_isNextToken(Doctrine_Query_Token::T_INNER)) {
$this->_parser->match(Doctrine_Query_Token::T_INNER);
}
......@@ -64,7 +64,7 @@ class Doctrine_Query_Production_Join extends Doctrine_Query_Production
$this->_whereType = 'ON';
$this->_conditionalExpression = $this->AST('ConditionalExpression', $paramHolder);
} elseif ($this->_isNextToken(Doctrine_Query_Token::T_WITH)) {
} else if ($this->_isNextToken(Doctrine_Query_Token::T_WITH)) {
$this->_parser->match(Doctrine_Query_Token::T_WITH);
$this->_conditionalExpression = $this->AST('ConditionalExpression', $paramHolder);
......
......@@ -93,7 +93,7 @@ class Doctrine_Query_Production_PathExpression extends Doctrine_Query_Production
$relationName = $this->_identifiers[$i];
$path .= '.' . $relationName;
if ( ! $classMetadata->hasRelation($relationName)) {
if ( ! $classMetadata->hasAssociation($relationName)) {
$className = $classMetadata->getClassName();
$this->_parser->semanticalError(
......
......@@ -73,7 +73,7 @@ class Doctrine_Query_Production_PathExpressionEndingWithAsterisk extends Doctrin
$relationName = $this->_identifiers[$i];
$path .= '.' . $relationName;
if ( ! $classMetadata->hasRelation($relationName)) {
if ( ! $classMetadata->hasAssociation($relationName)) {
$className = $classMetadata->getClassName();
$this->_parser->semanticalError(
......
......@@ -191,7 +191,7 @@ class Doctrine_Query_Production_RangeVariableDeclaration extends Doctrine_Query_
}
} else {
// We don't have the query component yet
if ( ! $classMetadata->hasRelation($relationName)) {
if ( ! $classMetadata->hasAssociation($relationName)) {
$className = $classMetadata->getClassName();
$this->_parser->semanticalError("Relation '{$relationName}' does not exist in component '{$className}'");
......@@ -199,13 +199,13 @@ class Doctrine_Query_Production_RangeVariableDeclaration extends Doctrine_Query_
return;
}
// Retrieving ClassMetadata and Mapper
// Retrieving ClassMetadata
try {
$relation = $classMetadata->getRelation($relationName);
$classMetadata = $relation->getClassMetadata();
$relation = $classMetadata->getAssociationMapping($relationName);
$targetClassMetadata = $this->_em->getClassMetadata($relation->getTargetEntityName());
$queryComponent = array(
'metadata' => $classMetadata,
'metadata' => $targetClassMetadata,
'parent' => $parent,
'relation' => $relation,
'map' => null,
......@@ -226,7 +226,7 @@ class Doctrine_Query_Production_RangeVariableDeclaration extends Doctrine_Query_
$this->_identificationVariable = $path;
}
$tableAlias = $parserResult->generateTableAlias($classMetadata->getClassName());
$tableAlias = $parserResult->generateTableAlias($targetClassMetadata->getClassName());
//echo "Table alias: " . $tableAlias . "\n";
......
......@@ -154,7 +154,7 @@ abstract class Doctrine_Relation implements ArrayAccess
}
}
$this->definition = $def;
$this->_foreignMapper = $this->getTable()->getConnection()->getEntityPersister($def['class']);
$this->_foreignMapper = $this->getTable()->getEntityManager()->getEntityPersister($def['class']);
}
/**
......
......@@ -410,7 +410,7 @@ class Doctrine_Relation_Parser
*/
public function completeDefinition($def)
{
$conn = $this->_table->getConnection();
$conn = $this->_table->getEntityManager();
$def['table'] = $this->getImpl($def, 'class');
$def['localTable'] = $this->_table;
......
......@@ -187,7 +187,7 @@ class Doctrine_Schema_MsSqlSchemaManager extends Doctrine_Schema_SchemaManager
if ($query) {
$query .= ', ';
}
$query .= 'ADD ' . $this->conn->getDeclaration($fieldName, $field);
$query .= 'ADD ' . $this->getDeclaration($fieldName, $field);
}
}
......
......@@ -15,6 +15,8 @@ require_once 'Orm/Entity/AllTests.php';
// Tests
require_once 'Orm/UnitOfWorkTest.php';
require_once 'Orm/EntityManagerFactoryTest.php';
require_once 'Orm/EntityManagerTest.php';
require_once 'Orm/EntityPersisterTest.php';
class Orm_AllTests
{
......@@ -29,7 +31,8 @@ class Orm_AllTests
$suite->addTestSuite('Orm_UnitOfWorkTest');
$suite->addTestSuite('Orm_EntityManagerFactoryTest');
//$suite->addTestSuite('Orm_ConfigurableTestCase');
$suite->addTestSuite('Orm_EntityManagerTest');
$suite->addTestSuite('Orm_EntityPersisterTest');
$suite->addTest(Orm_Component_AllTests::suite());
$suite->addTest(Orm_Query_AllTests::suite());
......
......@@ -9,7 +9,7 @@ class Orm_Associations_OneToOneMappingTest extends Doctrine_OrmTestCase
'fieldName' => 'address',
'targetEntity' => 'Address',
'joinColumns' => array('address_id' => 'id'),
'sourceEntity' => 'Person' // This is normally filled by ClassMetadata
'sourceEntity' => 'Person', // This is normally filled by ClassMetadata
);
$oneToOneMapping = new Doctrine_Association_OneToOne($owningSideMapping);
......@@ -23,11 +23,16 @@ class Orm_Associations_OneToOneMappingTest extends Doctrine_OrmTestCase
$inverseSideMapping = array(
'fieldName' => 'person',
'sourceEntity' => 'Address',
'targetEntity' => 'Person',
'mappedBy' => 'address'
);
$oneToOneMapping = new Doctrine_Association_OneToOne($inverseSideMapping);
$this->assertEquals('address', $oneToOneMapping->getMappedByFieldName());
$this->assertEquals('Address', $oneToOneMapping->getSourceEntityName());
$this->assertEquals('Person', $oneToOneMapping->getTargetEntityName());
$this->assertTrue($oneToOneMapping->isInverseSide());
}
......
......@@ -26,7 +26,7 @@
* @author Bjarte Stien Karlsen <doctrine@bjartek.org>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @since 2.0
* @version $Revision: 3754 $
*/
require_once 'lib/DoctrineTestInit.php';
......@@ -95,23 +95,6 @@ class Orm_Component_AccessTest extends Doctrine_OrmTestCase
}
/**
* @test
*/
public function shouldSetArrayOfValusInRecord()
{
$this->user->setArray(array(
'username' => 'meus',
'id' => 22));
$this->assertEquals('meus', $this->user->username);
$this->assertEquals('meus', $this->user['username']);
$this->assertEquals(22, $this->user->id);
$this->assertEquals(22, $this->user['id']);
}
/**
* @test
* @expectedException Doctrine_Entity_Exception
......@@ -130,17 +113,6 @@ class Orm_Component_AccessTest extends Doctrine_OrmTestCase
$this->user['rat'] = 'meus';
}
/**
* @test
* @expectedException Doctrine_Entity_Exception
*/
public function shouldNotBeAbleToSetNonExistantFieldAsPartInSetArray()
{
$this->user->setArray(array(
'rat' => 'meus',
'id' => 22));
}
/**
* @test
......@@ -176,18 +148,6 @@ class Orm_Component_AccessTest extends Doctrine_OrmTestCase
$this->assertFalse(isset($col->test));
}
/**
*
* @test
* @expectedException Doctrine_Exception
*/
public function shouldNotBeAbleToSetNullFieldInRecord()
{
$this->user->offsetSet(null, 'test');
}
/**
* @test
* @expectedException Doctrine_Exception
......
<?php
require_once 'lib/DoctrineTestInit.php';
#namespace Doctrine::Tests::ORM;
/**
* EntityManager tests.
*/
class Orm_EntityManagerTest extends Doctrine_OrmTestCase
{
public function testSettingInvalidFlushModeThrowsException()
{
$prev = $this->_em->getFlushMode();
try {
$this->_em->setFlushMode('foobar');
$this->fail("Setting invalid flushmode did not trigger exception.");
} catch (Doctrine_EntityManager_Exception $expected) {}
$this->_em->setFlushMode($prev);
}
}
\ No newline at end of file
<?php
require_once 'lib/DoctrineTestInit.php';
require_once 'lib/mocks/Doctrine_EntityManagerMock.php';
require_once 'lib/mocks/Doctrine_ConnectionMock.php';
/**
* EntityPersister tests.
*/
class Orm_EntityPersisterTest extends Doctrine_OrmTestCase
{
private $_persister; // SUT
private $_connMock;
private $_emMock;
protected function setUp() {
parent::setUp();
$this->_connMock = new Doctrine_ConnectionMock(array());
$this->_emMock = new Doctrine_EntityManagerMock($this->_connMock);
$this->_connMock->setDatabasePlatform(new Doctrine_DatabasePlatformMock());
$this->_persister = new Doctrine_EntityPersister_Standard(
$this->_emMock, $this->_emMock->getClassMetadata("ForumUser"));
}
public function testTest() {
$user = new ForumUser();
$user->username = "romanb";
$user->avatar = new ForumAvatar();
$this->_persister->insert($user);
$inserts = $this->_connMock->getInserts();
//var_dump($inserts);
$this->assertTrue(isset($inserts['forum_user']));
$this->assertEquals(1, count($inserts['forum_user']));
$this->assertEquals(1, count($inserts['forum_user'][0]));
$this->assertTrue(isset($inserts['forum_user'][0]['username']));
$this->assertEquals('romanb', $inserts['forum_user'][0]['username']);
}
}
\ No newline at end of file
......@@ -123,7 +123,7 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
'p' => array(
'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'),
'map' => null
)
);
......@@ -226,7 +226,7 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
'p' => array(
'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'),
'map' => null,
'agg' => array('0' => 'numPhones')
)
......@@ -311,7 +311,7 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
'p' => array(
'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'),
'map' => 'phonenumber'
)
);
......@@ -415,13 +415,13 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
'p' => array(
'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'),
'map' => null
),
'a' => array(
'metadata' => $this->_em->getClassMetadata('CmsArticle'),
'parent' => 'u',
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('articles'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('articles'),
'map' => null
),
);
......@@ -571,19 +571,19 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
'p' => array(
'metadata' => $this->_em->getClassMetadata('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('phonenumbers'),
'map' => null
),
'a' => array(
'metadata' => $this->_em->getClassMetadata('CmsArticle'),
'parent' => 'u',
'relation' => $this->_em->getClassMetadata('CmsUser')->getRelation('articles'),
'relation' => $this->_em->getClassMetadata('CmsUser')->getAssociationMapping('articles'),
'map' => null
),
'c' => array(
'metadata' => $this->_em->getClassMetadata('CmsComment'),
'parent' => 'a',
'relation' => $this->_em->getClassMetadata('CmsArticle')->getRelation('comments'),
'relation' => $this->_em->getClassMetadata('CmsArticle')->getAssociationMapping('comments'),
'map' => null
),
);
......@@ -779,7 +779,7 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
'b' => array(
'metadata' => $this->_em->getClassMetadata('ForumBoard'),
'parent' => 'c',
'relation' => $this->_em->getClassMetadata('ForumCategory')->getRelation('boards'),
'relation' => $this->_em->getClassMetadata('ForumCategory')->getAssociationMapping('boards'),
'map' => null
),
);
......
......@@ -84,7 +84,7 @@ class Orm_Query_IdentifierRecognitionTest extends Doctrine_OrmTestCase
$decl = $parserResult->getQueryComponent('p');
$this->assertTrue($decl['metadata'] instanceof Doctrine_ClassMetadata);
$this->assertTrue($decl['relation'] instanceof Doctrine_Relation);
$this->assertTrue($decl['relation'] instanceof Doctrine_Association);
$this->assertEquals('u', $decl['parent']);
$this->assertEquals(null, $decl['scalar']);
$this->assertEquals(null, $decl['map']);
......@@ -108,7 +108,7 @@ class Orm_Query_IdentifierRecognitionTest extends Doctrine_OrmTestCase
$decl = $parserResult->getQueryComponent('a');
$this->assertTrue($decl['metadata'] instanceof Doctrine_ClassMetadata);
$this->assertTrue($decl['relation'] instanceof Doctrine_Relation);
$this->assertTrue($decl['relation'] instanceof Doctrine_Association);
$this->assertEquals('u', $decl['parent']);
$this->assertEquals(null, $decl['scalar']);
$this->assertEquals(null, $decl['map']);
......@@ -116,7 +116,7 @@ class Orm_Query_IdentifierRecognitionTest extends Doctrine_OrmTestCase
$decl = $parserResult->getQueryComponent('pn');
$this->assertTrue($decl['metadata'] instanceof Doctrine_ClassMetadata);
$this->assertTrue($decl['relation'] instanceof Doctrine_Relation);
$this->assertTrue($decl['relation'] instanceof Doctrine_Association);
$this->assertEquals('u', $decl['parent']);
$this->assertEquals(null, $decl['scalar']);
$this->assertEquals('phonenumber', $decl['map']);
......
......@@ -8,6 +8,7 @@ class Doctrine_ConnectionMock extends Doctrine_Connection
protected $_driverName = 'Mock';
private $_sequenceModuleMock;
private $_platformMock;
private $_inserts = array();
public function __construct(array $params)
{
......@@ -30,6 +31,14 @@ class Doctrine_ConnectionMock extends Doctrine_Connection
return $this->_platformMock;
}
/**
* @override
*/
public function insert($tableName, array $data)
{
$this->_inserts[$tableName][] = $data;
}
/* Mock API */
public function setDatabasePlatform($platform)
......@@ -41,6 +50,16 @@ class Doctrine_ConnectionMock extends Doctrine_Connection
{
$this->_sequenceModuleMock = $seqManager;
}
public function getInserts()
{
return $this->_inserts;
}
public function reset()
{
$this->_inserts = array();
}
}
?>
\ No newline at end of file
......@@ -34,7 +34,18 @@ class CmsArticle extends Doctrine_Entity
'type' => 'integer',
'length' => 4
));
$mapping->hasMany('CmsComment as comments', array(
'local' => 'id', 'foreign' => 'article_id'));
/*$mapping->hasMany('CmsComment as comments', array(
'local' => 'id', 'foreign' => 'article_id'));*/
$mapping->mapOneToMany(array(
'fieldName' => 'comments',
'targetEntity' => 'CmsComment',
));
/*$mapping->mapManyToOne(array(
'fieldName' => 'author',
'joinColumns' => array('user_id' => 'id')
));*/
}
}
......@@ -36,9 +36,21 @@ class CmsUser extends Doctrine_Entity
'length' => 255
));
$mapping->hasMany('CmsPhonenumber as phonenumbers', array(
/*$mapping->hasMany('CmsPhonenumber as phonenumbers', array(
'local' => 'id', 'foreign' => 'user_id'));
$mapping->hasMany('CmsArticle as articles', array(
'local' => 'id', 'foreign' => 'user_id'));
'local' => 'id', 'foreign' => 'user_id'));*/
$mapping->mapOneToMany(array(
'fieldName' => 'phonenumbers',
'targetEntity' => 'CmsPhonenumber',
));
$mapping->mapOneToMany(array(
'fieldName' => 'articles',
'targetEntity' => 'CmsArticle',
));
}
}
<?php
class ForumAvatar extends Doctrine_Entity
{
public static function initMetadata($mapping)
{
$mapping->mapField(array(
'fieldName' => 'id',
'type' => 'integer',
'length' => 4,
'id' => true,
'idGenerator' => 'auto'
));
}
}
?>
\ No newline at end of file
......@@ -25,14 +25,13 @@ class ForumBoard extends Doctrine_Entity
'type' => 'integer'
));
$mapping->hasOne('ForumCategory as category',
array('local' => 'category_id', 'foreign' => 'id'));
/*
$metadata->mapOneToOne(array(
'fieldName' => 'category', // optional, defaults to targetEntity
/*$mapping->hasOne('ForumCategory as category',
array('local' => 'category_id', 'foreign' => 'id'));*/
$mapping->mapOneToOne(array(
'fieldName' => 'category',
'targetEntity' => 'ForumCategory',
'joinColumns' => array('category_id' => 'id')
));
*/
));
}
}
......@@ -20,7 +20,12 @@ class ForumCategory extends Doctrine_Entity
'length' => 255
));
$mapping->hasMany('ForumBoard as boards', array(
'local' => 'id' , 'foreign' => 'category_id'));
/*$mapping->hasMany('ForumBoard as boards', array(
'local' => 'id' , 'foreign' => 'category_id'));*/
$mapping->mapOneToMany(array(
'fieldName' => 'boards',
'targetEntity' => 'ForumBoard'
));
}
}
......@@ -6,9 +6,9 @@
class ForumUser extends Doctrine_Entity
{
#protected $dtype;
#protected $id;
#protected $username;
#protected $avatar;
public static function initMetadata($mapping)
{
......@@ -42,6 +42,12 @@ class ForumUser extends Doctrine_Entity
'length' => 50
));
$mapping->mapOneToOne(array(
'fieldName' => 'avatar',
'targetEntity' => 'ForumAvatar',
'joinColumns' => array('avatar_id' => 'id'),
));
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment