Commit ab65ad5b authored by romanb's avatar romanb

Refactorings. Started with new hydrator for 2.0.

parent ff112209
<?php
<?php
/*
* $Id$
*
......@@ -29,14 +29,14 @@
* @since 2.0
*/
class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializable
{
{
/**
* The name of the entity class that is mapped to the database with this metadata.
*
*
* @var string
*/
protected $_entityName;
/**
* The name of the entity class that is at the root of the entity inheritance
* hierarchy. If the entity is not part of an inheritance hierarchy this is the same
......@@ -45,31 +45,31 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
* @var string
*/
protected $_rootEntityName;
/**
* The name of the custom mapper class used for the entity class.
* (Optional).
*
* @var string
*/
protected $_customMapperClassName;
protected $_customRepositoryClassName;
/**
*
* @var Doctrine_Connection
*/
protected $_conn;
/**
* The names of the parent classes (ancestors).
*/
protected $_parentClasses = array();
/**
* The names of all subclasses
*/
protected $_subClasses = array();
/**
* The field names of all fields that are part of the identifier/primary key
* of the described entity class.
......@@ -77,7 +77,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
* @var array
*/
protected $_identifier = array();
/**
* The identifier type of the class.
*
......@@ -85,24 +85,24 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
* @var integer
*/
protected $_identifierType;
/**
* The inheritance mapping type used by the class.
*
*
*
* @var integer
*/
protected $_inheritanceType = Doctrine::INHERITANCE_TYPE_NONE;
/**
* An array containing all behaviors attached to the class.
*
* @see Doctrine_Template
* @var array $_templates
* @todo Unify under 'Behaviors'.
* @todo Unify under 'Behaviors'.
*/
protected $_behaviors = array();
/**
* An array containing all behavior generators attached to the class.
*
......@@ -116,10 +116,10 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
* An array containing all filters attached to the class.
*
* @see Doctrine_Record_Filter
* @var array $_filters
* @var array $_filters
*/
protected $_filters = array();
/**
* The mapped columns and their mapping definitions.
* Keys are column names and values are mapping definitions.
......@@ -132,7 +132,6 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
* additional keys:
* -- notnull whether or not the column is marked as notnull
* -- values enum values
* -- notblank notblank validator + notnull constraint
* ... many more
*
* @var array $columns
......@@ -147,30 +146,30 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
* @var array
*/
protected $_fieldNames = array();
/**
* An array of column names. Keys are field names and values column names.
* Used to look up column names from field names.
* This is the reverse lookup map of $_fieldNames.
*
* @var array
*
* @var array
*/
protected $_columnNames = array();
/**
* Caches enum value mappings. Keys are field names and values arrays with the
* mapping.
*/
protected $_enumValues = array();
/**
* Tree object associated with the class.
*
* @var Doctrine_Tree
* @todo Belongs to the NestedSet Behavior plugin.
* @todo Belongs to the NestedSet Behavior plugin.
*/
protected $_tree;
/**
* Cached column count, Doctrine_Record uses this column count when
* determining its state.
......@@ -178,28 +177,28 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
* @var integer
*/
protected $_columnCount;
/**
* Whether or not this class has default values.
*
* @var boolean
* @var boolean
*/
protected $_hasDefaultValues;
/**
* Relation parser object. Manages the relations for the class.
*
* @var Doctrine_Relation_Parser $_parser
* @var Doctrine_Relation_Parser $_parser
*/
protected $_parser;
/**
* Enum value arrays.
* Enum value arrays.
*/
protected $_enumMap = array();
/**
* @var array $options an array containing all options
* @var array $options an array containing all options
*
* -- treeImpl the tree implementation of this table (if any)
*
......@@ -211,24 +210,24 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
'treeImpl' => null,
'treeOptions' => null,
'queryParts' => array()
);
);
/**
* Inheritance options.
*/
protected $_inheritanceOptions = array(
// JOINED & TABLE_PER_CLASS options
// JOINED & TABLE_PER_CLASS options
'discriminatorColumn' => null,
'discriminatorMap' => array(),
// JOINED options
// JOINED options
'joinSubclasses' => true
);
);
/**
* Specific options that can be set for the database table the class is mapped to.
* Some of them are dbms specific and they are only used if the table is generated
* by Doctrine (NOT when using Migrations).
*
*
* -- type table type (mysql example: INNODB)
*
* -- charset character set
......@@ -252,29 +251,29 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
'collate' => null,
'indexes' => array(),
'checks' => array()
);
);
/**
* @var array $_invokedMethods method invoker cache
*/
protected $_invokedMethods = array();
/**
* Constructs a new ClassMetadata instance.
*
* @param string $entityName Name of the entity class the metadata info is used for.
*/
public function __construct($entityName, Doctrine_Connection $conn)
{
{
$this->_entityName = $entityName;
$this->_rootEntityName = $entityName;
$this->_conn = $conn;
$this->_parser = new Doctrine_Relation_Parser($this);
$this->_filters[] = new Doctrine_Record_Filter_Standard();
$this->setConfigurableParent($this->_conn);
$this->setConfigurableParent($this->_conn);
}
/**
*
*/
......@@ -282,7 +281,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_conn;
}
/**
* getComponentName
*
......@@ -292,7 +291,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_entityName;
}
/**
* Gets the name of the root class of the entity hierarchy. If the entity described
* by the ClassMetadata is not participating in a hierarchy, this is the same as the
......@@ -304,7 +303,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_rootEntityName;
}
/**
* @deprecated
*/
......@@ -312,19 +311,22 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->getClassName();
}
/**
* Checks whether a field is part of the identifier/primary key field(s).
*
* @param string $fieldName The field name
* @return boolean TRUE if the field is part of the table identifier/primary key field(s),
* @return boolean TRUE if the field is part of the table identifier/primary key field(s),
* FALSE otherwise.
*/
public function isIdentifier($fieldName)
{
return in_array($fieldName, $this->getIdentifier());
if ($this->_identifierType != Doctrine::IDENTIFIER_COMPOSITE) {
return $fieldName === $this->_identifier[0];
}
return in_array($fieldName, $this->_identifier);
}
/**
* addIndex
*
......@@ -350,7 +352,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
return false;
}
/**
* setOption
* sets an option and returns this object in order to
......@@ -365,21 +367,21 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
public function setOption($name, $value)
{
/*switch ($name) {
case 'tableName':
case 'index':
case 'sequenceName':
case 'type':
case 'charset':
case 'collation':
case 'collate':
return $this->setTableOption($name, $value);
case 'enumMap':
$this->_enumMap = $value;
return;
}*/
case 'tableName':
case 'index':
case 'sequenceName':
case 'type':
case 'charset':
case 'collation':
case 'collate':
return $this->setTableOption($name, $value);
case 'enumMap':
$this->_enumMap = $value;
return;
}*/
$this->_options[$name] = $value;
}
/**
* Sets a table option.
*/
......@@ -388,9 +390,9 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
if ( ! array_key_exists($name, $this->_tableOptions)) {
throw new Doctrine_ClassMetadata_Exception("Unknown table option: '$name'.");
}
$this->_tableOptions[$name] = $value;
$this->_tableOptions[$name] = $value;
}
/**
* Gets a table option.
*/
......@@ -399,16 +401,16 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
if ( ! array_key_exists($name, $this->_tableOptions)) {
throw new Doctrine_ClassMetadata_Exception("Unknown table option: '$name'.");
}
return $this->_tableOptions[$name];
}
public function getBehaviorForMethod($method)
{
return (isset($this->_invokedMethods[$method])) ?
$this->_invokedMethods[$method] : false;
$this->_invokedMethods[$method] : false;
}
public function addBehaviorMethod($method, $behavior)
{
$this->_invokedMethods[$method] = $class;
......@@ -430,7 +432,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
}
return null;
}
/**
* getOptions
* returns all options of this table and the associated values
......@@ -441,7 +443,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_options;
}
/**
* getTableOptions
* returns all table options.
......@@ -452,7 +454,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_tableOptions;
}
/**
* getColumnName
*
......@@ -466,9 +468,9 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
public function getColumnName($fieldName)
{
return isset($this->_columnNames[$fieldName]) ?
$this->_columnNames[$fieldName] : $fieldName;
$this->_columnNames[$fieldName] : $fieldName;
}
/**
* @deprecated
*/
......@@ -476,17 +478,17 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->getColumnMapping($columnName);
}
public function getColumnMapping($columnName)
{
return isset($this->_mappedColumns[$columnName]) ?
$this->_mappedColumns[$columnName] : false;
$this->_mappedColumns[$columnName] : false;
}
/**
* getFieldName
*
* returns the field name for a column name
*
* returns the field name for a column name
* if no field name can be found the column name is returned.
*
* @param string $columnName column name
......@@ -495,9 +497,9 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
public function getFieldName($columnName)
{
return isset($this->_fieldNames[$columnName]) ?
$this->_fieldNames[$columnName] : $columnName;
$this->_fieldNames[$columnName] : $columnName;
}
/**
* @deprecated
*/
......@@ -507,12 +509,12 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
$this->setColumn($name, $options['type'], $options['length'], $options);
}
}
/**
* Maps a column of the class' database table to a field of the entity.
*
* @param string $name The name of the column to map. Syntax: columnName [as propertyName].
* The property name is optional. If not used the column will be
* The property name is optional. If not used the column will be
* mapped to a property with the same name.
* @param string $type The type of the column.
* @param integer $length The length of the column.
......@@ -524,6 +526,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
*/
public function mapColumn($name, $type, $length = null, $options = array(), $prepend = false)
{
// converts 0 => 'primary' to 'primary' => true etc.
foreach ($options as $k => $option) {
if (is_numeric($k)) {
if ( ! empty($option) && $option !== false) {
......@@ -532,7 +535,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
unset($options[$k]);
}
}
// extract column name & field name
$parts = explode(' as ', $name);
if (count($parts) > 1) {
......@@ -541,11 +544,11 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
$fieldName = $parts[0];
}
$name = strtolower($parts[0]);
if (isset($this->_columnNames[$fieldName])) {
return;
}
if ($prepend) {
$this->_columnNames = array_merge(array($fieldName => $name), $this->_columnNames);
$this->_fieldNames = array_merge(array($name => $fieldName), $this->_fieldNames);
......@@ -553,56 +556,68 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
$this->_columnNames[$fieldName] = $name;
$this->_fieldNames[$name] = $fieldName;
}
// Inspect & fill $options
if ($length == null) {
switch ($type) {
case 'string':
case 'clob':
case 'float':
case 'integer':
case 'array':
case 'object':
case 'blob':
case 'gzip':
// use php int max
$length = 2147483647;
break;
case 'boolean':
$length = 1;
case 'date':
// YYYY-MM-DD ISO 8601
$length = 10;
case 'time':
// HH:NN:SS+00:00 ISO 8601
$length = 14;
case 'timestamp':
// YYYY-MM-DDTHH:MM:SS+00:00 ISO 8601
$length = 25;
break;
}
$length = $this->_getDefaultLength($type);
}
$options['type'] = $type;
$options['length'] = $length;
if ($prepend) {
$this->_mappedColumns = array_merge(array($name => $options), $this->_mappedColumns);
} else {
$this->_mappedColumns[$name] = $options;
if ( ! $this->_hasDefaultValues && isset($options['default'])) {
$this->_hasDefaultValues = true;
}
if ( ! empty($options['primary'])) {
if ( ! in_array($fieldName, $this->_identifier)) {
$this->_identifier[] = $fieldName;
}
/*if (isset($options['autoincrement']) && $options['autoincrement'] === true) {
}*/
}
if (isset($options['default'])) {
$this->_hasDefaultValues = true;
/*
if ( ! isset($options['immutable'])) {
$options['immutable'] = false;
}*/
if ($prepend) {
$this->_mappedColumns = array_merge(array($name => $options), $this->_mappedColumns);
} else {
$this->_mappedColumns[$name] = $options;
}
$this->_columnCount++;
}
private function _getDefaultLength($type)
{
switch ($type) {
case 'string':
case 'clob':
case 'float':
case 'integer':
case 'array':
case 'object':
case 'blob':
case 'gzip':
// use php int max
return 2147483647;
case 'boolean':
return 1;
case 'date':
// YYYY-MM-DD ISO 8601
return 10;
case 'time':
// HH:NN:SS+00:00 ISO 8601
return 14;
case 'timestamp':
// YYYY-MM-DDTHH:MM:SS+00:00 ISO 8601
return 25;
}
}
/**
* setColumn
*
......@@ -620,7 +635,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->mapColumn($name, $type, $length, $options, $prepend);
}
/**
* Gets the names of all validators that are applied on a field.
*
......@@ -631,9 +646,9 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
$columnName = $this->getColumnName($fieldName);
return isset($this->_mappedColumns[$columnName]['validators']) ?
$this->_mappedColumns[$columnName]['validators'] : array();
$this->_mappedColumns[$columnName]['validators'] : array();
}
/**
* Checks whether the class mapped class has a default value on any field.
*
......@@ -663,7 +678,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
return null;
}
}
/**
* Gets the identifier (primary key) field(s) of the mapped class.
*
......@@ -674,7 +689,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_identifier;
}
/**
* Gets the identifier (primary key) field(s) of the mapped class.
*
......@@ -684,7 +699,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_identifier;
}
public function setIdentifier(array $identifier)
{
$this->_identifier = $identifier;
......@@ -694,14 +709,14 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
* Gets the type of the identifier (primary key) used by the mapped class. The type
* can be either <tt>Doctrine::IDENTIFIER_NATURAL</tt>, <tt>Doctrine::IDENTIFIER_AUTOINCREMENT</tt>,
* <tt>Doctrine::IDENTIFIER_SEQUENCE</tt> or <tt>Doctrine::IDENTIFIER_COMPOSITE</tt>.
*
*
* @return integer
*/
public function getIdentifierType()
{
return $this->_identifierType;
}
/**
* Sets the identifier type used by the mapped class.
*/
......@@ -719,12 +734,12 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return isset($this->_mappedColumns[$columnName]);
}
public function hasMappedColumn($columnName)
{
return isset($this->_mappedColumns[$columnName]);
}
/**
* hasField
* @return boolean
......@@ -733,7 +748,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return isset($this->_columnNames[$fieldName]);
}
/**
* @param string $fieldName
* @return array
......@@ -756,24 +771,24 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
* @return mixed
*/
public function enumValue($fieldName, $index)
{
{
if ($index instanceof Doctrine_Null) {
return $index;
}
if (isset($this->_enumValues[$fieldName][$index])) {
return $this->_enumValues[$fieldName][$index];
}
$columnName = $this->getColumnName($fieldName);
if ( ! $this->_conn->getAttribute(Doctrine::ATTR_USE_NATIVE_ENUM) &&
isset($this->_mappedColumns[$columnName]['values'][$index])) {
isset($this->_mappedColumns[$columnName]['values'][$index])) {
$enumValue = $this->_mappedColumns[$columnName]['values'][$index];
} else {
$enumValue = $index;
}
$this->_enumValues[$fieldName][$index] = $enumValue;
return $enumValue;
}
......@@ -791,10 +806,10 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
if ($index === false || ! $this->_conn->getAttribute(Doctrine::ATTR_USE_NATIVE_ENUM)) {
return $index;
}
return $value;
}
/**
* getColumnCount
*
......@@ -805,7 +820,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_columnCount;
}
/**
* getMappedColumnCount
*
......@@ -815,9 +830,9 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_columnCount;
}
/**
*
*
* @return string The name of the accessor (getter) method or NULL if the field does
* not have a custom accessor.
*/
......@@ -825,11 +840,11 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
$columnName = $this->getColumnName($fieldName);
return isset($this->_mappedColumns[$columnName]['accessor']) ?
$this->_mappedColumns[$columnName]['accessor'] : null;
$this->_mappedColumns[$columnName]['accessor'] : null;
}
/**
*
*
* @return string The name of the mutator (setter) method or NULL if the field does
* not have a custom mutator.
*/
......@@ -837,7 +852,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
$columnName = $this->getColumnName($fieldName);
return isset($this->_mappedColumns[$columnName]['mutator']) ?
$this->_mappedColumns[$columnName]['mutator'] : null;
$this->_mappedColumns[$columnName]['mutator'] : null;
}
/**
......@@ -850,7 +865,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_mappedColumns;
}
/**
* Gets all mapped columns and their mapping definitions.
*
......@@ -869,7 +884,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
*/
public function removeColumn($fieldName)
{
$columnName = array_search($fieldName, $this->_fieldNames);
$columnName = array_search($fieldName, $this->_fieldNames);
unset($this->_fieldNames[$columnName]);
......@@ -878,7 +893,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
return true;
}
$this->_columnCount--;
return false;
}
......@@ -892,15 +907,15 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
if ($fieldNames === null) {
return array_keys($this->_mappedColumns);
} else {
$columnNames = array();
foreach ($fieldNames as $fieldName) {
$columnNames[] = $this->getColumnName($fieldName);
}
return $columnNames;
$columnNames = array();
foreach ($fieldNames as $fieldName) {
$columnNames[] = $this->getColumnName($fieldName);
}
return $columnNames;
}
}
/**
* returns an array with all the identifier column names.
*
......@@ -910,7 +925,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->getColumnNames((array) $this->getIdentifier());
}
/**
* returns an array containing all the field names.
*
......@@ -930,14 +945,14 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
public function getDefinitionOf($fieldName)
{
$columnName = $this->getColumnName($fieldName);
return $this->getColumnDefinition($columnName);
}
public function getMappingForField($fieldName)
{
$columnName = $this->getColumnName($fieldName);
return $this->getColumnDefinition($columnName);
}
......@@ -951,12 +966,12 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->getTypeOfColumn($this->getColumnName($fieldName));
}
public function getTypeOfField($fieldName)
{
return $this->getTypeOfColumn($this->getColumnName($fieldName));
}
/**
* getTypeOfColumn
*
......@@ -966,7 +981,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return isset($this->_mappedColumns[$columnName]) ? $this->_mappedColumns[$columnName]['type'] : false;
}
/**
* Gets the (maximum) length of a field.
*/
......@@ -974,7 +989,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_mappedColumns[$this->getColumnName($fieldName)]['length'];
}
/**
* getTableName
*
......@@ -984,12 +999,12 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->getTableOption('tableName');
}
public function getInheritedFields()
{
}
/**
* Adds a named query.
*
......@@ -999,15 +1014,15 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
*/
public function addNamedQuery($name, $query)
{
}
public function bindRelation($args, $type)
{
return $this->bind($args, $type);
}
/**
/**
* DESCRIBE WHAT THIS METHOD DOES, PLEASE!
*
* @todo Name proposal: addRelation
......@@ -1030,7 +1045,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
$options = array_merge($args[1], $options);
$this->_parser->bind($args[0], $options);
}
/**
* hasRelation
*
......@@ -1051,7 +1066,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_parser->getRelation($alias, $recursive);
}
public function getRelationParser()
{
return $this->_parser;
......@@ -1067,7 +1082,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_parser->getRelations();
}
/**
* getBehaviors
* returns all behaviors attached to the class.
......@@ -1079,7 +1094,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_behaviors;
}
/**
* Gets the inheritance type used by the class.
*
......@@ -1089,7 +1104,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_inheritanceType;
}
/**
* Sets the subclasses of the class.
* All entity classes that participate in a hierarchy and have subclasses
......@@ -1099,9 +1114,9 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
*/
public function setSubclasses(array $subclasses)
{
$this->_subClasses = $subclasses;
$this->_subClasses = $subclasses;
}
/**
* Gets the names of all subclasses.
*
......@@ -1111,7 +1126,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_subClasses;
}
/**
* Checks whether the class has any persistent subclasses.
*
......@@ -1121,7 +1136,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return ! $this->_subClasses;
}
/**
* Gets the names of all parent classes.
*
......@@ -1131,7 +1146,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_parentClasses;
}
/**
* Sets the parent class names.
*/
......@@ -1142,7 +1157,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
$this->_rootEntityName = array_pop($classNames);
}
}
/**
* Checks whether the class has any persistent parent classes.
*
......@@ -1152,7 +1167,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return ! $this->_parentClasses;
}
/**
* Sets the inheritance type used by the class and it's subclasses.
*
......@@ -1163,26 +1178,26 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
if ($parentClassNames = $this->getParentClasses()) {
if ($this->_conn->getClassMetadata($parentClassNames[0])->getInheritanceType() != $type) {
throw new Doctrine_ClassMetadata_Exception("All classes in an inheritance hierarchy"
. " must share the same inheritance mapping type. Mixing is not allowed.");
. " must share the same inheritance mapping type. Mixing is not allowed.");
}
}
if ($type == Doctrine::INHERITANCE_TYPE_SINGLE_TABLE) {
$this->_checkRequiredDiscriminatorOptions($options);
} else if ($type == Doctrine::INHERITANCE_TYPE_JOINED) {
$this->_checkRequiredDiscriminatorOptions($options);
} else if ($type == Doctrine::INHERITANCE_TYPE_TABLE_PER_CLASS) {
;
} else {
} else {
throw new Doctrine_ClassMetadata_Exception("Invalid inheritance type '$type'.");
}
$this->_inheritanceType = $type;
foreach ($options as $name => $value) {
$this->setInheritanceOption($name, $value);
}
}
/**
* Checks if the 2 options 'discriminatorColumn' and 'discriminatorMap' are present.
* If either of them is missing an exception is thrown.
......@@ -1195,13 +1210,13 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
if ( ! isset($options['discriminatorColumn'])) {
throw new Doctrine_ClassMetadata_Exception("Missing option 'discriminatorColumn'."
. " Inheritance types JOINED and SINGLE_TABLE require this option.");
. " Inheritance types JOINED and SINGLE_TABLE require this option.");
} else if ( ! isset($options['discriminatorMap'])) {
throw new Doctrine_ClassMetadata_Exception("Missing option 'discriminatorMap'."
. " Inheritance types JOINED and SINGLE_TABLE require this option.");
. " Inheritance types JOINED and SINGLE_TABLE require this option.");
}
}
/**
* Gets an inheritance option.
*
......@@ -1211,10 +1226,10 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
if ( ! array_key_exists($name, $this->_inheritanceOptions)) {
throw new Doctrine_ClassMetadata_Exception("Unknown inheritance option: '$name'.");
}
return $this->_inheritanceOptions[$name];
}
/**
* Gets all inheritance options.
*/
......@@ -1222,7 +1237,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_inheritanceOptions;
}
/**
* Sets an inheritance option.
*/
......@@ -1231,25 +1246,25 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
if ( ! array_key_exists($name, $this->_inheritanceOptions)) {
throw new Doctrine_ClassMetadata_Exception("Unknown inheritance option: '$name'.");
}
switch ($name) {
case 'discriminatorColumn':
if ($value !== null && ! is_string($value)) {
throw new Doctrine_ClassMetadata_Exception("Invalid value '$value' for option"
. " 'discriminatorColumn'.");
. " 'discriminatorColumn'.");
}
break;
case 'discriminatorMap':
if ( ! is_array($value)) {
throw new Doctrine_ClassMetadata_Exception("Value for option 'discriminatorMap'"
. " must be an array.");
. " must be an array.");
}
break;
}
$this->_inheritanceOptions[$name] = $value;
}
/**
* export
* exports this class to the database based on its mapping.
......@@ -1276,7 +1291,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
$columns = array();
$primary = array();
$allColumns = $this->getColumns();
// If the class is part of a Single Table Inheritance hierarchy, collect the fields
// of all classes in the hierarchy.
if ($this->_inheritanceType == Doctrine::INHERITANCE_TYPE_SINGLE_TABLE) {
......@@ -1337,11 +1352,11 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
$primary[] = $name;
}
}
// Collect foreign keys from the relations
$options['foreignKeys'] = array();
if ($parseForeignKeys && $this->getAttribute(Doctrine::ATTR_EXPORT)
& Doctrine::EXPORT_CONSTRAINTS) {
& Doctrine::EXPORT_CONSTRAINTS) {
$constraints = array();
$emptyIntegrity = array('onUpdate' => null, 'onDelete' => null);
foreach ($this->getRelations() as $name => $relation) {
......@@ -1380,16 +1395,16 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
}
$options['primary'] = $primary;
return array('tableName' => $this->getTableOption('tableName'),
'columns' => $columns,
'options' => array_merge($options, $this->getTableOptions()));
}
/**
* getTemplate
*
* @param string $template
* @param string $template
* @return void
* @todo Unify under 'Behaviors'.
*/
......@@ -1401,7 +1416,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
return $this->_behaviors[$behaviorName];
}
/**
* @todo Unify under 'Behaviors'.
*/
......@@ -1409,7 +1424,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return isset($this->_behaviors[$behaviorName]);
}
/**
* @todo Unify under 'Behaviors'.
*/
......@@ -1419,7 +1434,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
return $this;
}
/**
* @todo Unify under 'Behaviors'.
*/
......@@ -1427,7 +1442,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_generators;
}
/**
* @todo Unify under 'Behaviors'.
*/
......@@ -1439,7 +1454,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
return $this->_generators[$plugin];
}
/**
* @todo Unify under 'Behaviors'.
*/
......@@ -1447,20 +1462,20 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return isset($this->_generators[$generator]);
}
/**
* @todo Unify under 'Behaviors'.
*/
public function addGenerator(Doctrine_Record_Generator $generator, $name = null)
{
if ($name === null) {
if ($name === null) {
$this->_generators[] = $generator;
} else {
$this->_generators[$name] = $generator;
}
return $this;
}
/**
* loadBehavior
*
......@@ -1471,16 +1486,16 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
$this->actAs($behavior, $options);
}
/**
* @todo Unify under 'Behaviors'.
*/
public function loadGenerator(Doctrine_Record_Generator $generator)
{
$generator->initialize($this->_table);
$generator->initialize($this->_table);
$this->addGenerator($generator, get_class($generator));
}
/**
* unshiftFilter
*
......@@ -1492,10 +1507,10 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
$filter->setTable($this);
array_unshift($this->_filters, $filter);
return $this;
}
/**
* getTree
*
......@@ -1510,13 +1525,13 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
if ( ! $this->_tree) {
$options = $this->getOption('treeOptions') ? $this->getOption('treeOptions') : array();
$this->_tree = Doctrine_Tree::factory($this,
$this->getOption('treeImpl'), $options);
$this->getOption('treeImpl'), $options);
}
return $this->_tree;
}
return false;
}
/**
* isTree
*
......@@ -1529,7 +1544,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return ( ! is_null($this->getOption('treeImpl'))) ? true : false;
}
/**
* getFilters
*
......@@ -1540,7 +1555,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return $this->_filters;
}
/**
* Checks whether a persistent field is inherited from a superclass.
*
......@@ -1550,7 +1565,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return isset($this->_mappedColumns[$this->getColumnName($fieldName)]['inherited']);
}
/**
* bindQueryParts
* binds query parts to given component
......@@ -1560,7 +1575,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
*/
public function bindQueryParts(array $queryParts)
{
$this->_options['queryParts'] = $queryParts;
$this->_options['queryParts'] = $queryParts;
return $this;
}
......@@ -1574,14 +1589,14 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
*/
public function bindQueryPart($queryPart, $value)
{
$this->_options['queryParts'][$queryPart] = $value;
$this->_options['queryParts'][$queryPart] = $value;
return $this;
}
/**
* getBoundQueryPart
*
* @param string $queryPart
* @param string $queryPart
* @return string $queryPart
*/
public function getBoundQueryPart($queryPart)
......@@ -1601,7 +1616,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
$this->setTableOption('tableName', $this->_conn->formatter->getTableName($tableName));
}
/**
* Serializes the metadata.
*
......@@ -1616,7 +1631,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
//return serialize($contents);
return "";
}
/**
* Reconstructs the metadata class from it's serialized representation.
*
......@@ -1628,37 +1643,37 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return true;
}
/**
* @todo Implementation.
*/
public function oneToOne($targetEntity, $definition)
{
}
/**
* @todo Implementation.
*/
public function oneToMany($targetEntity, $definition)
{
}
/**
* @todo Implementation.
*/
public function manyToOne($targetEntity, $definition)
{
}
/**
* @todo Implementation.
*/
public function manyToMany($targetEntity, $definition)
{
}
/**
......@@ -1697,7 +1712,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
return $this;
}
/**
* check
* adds a check constraint
......@@ -1716,10 +1731,10 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
} else {
$this->_addCheckConstraint($constraint, $name);
}
return $this;
}
protected function _addCheckConstraint($definition, $name)
{
if (is_string($name)) {
......@@ -1728,53 +1743,75 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
$this->_tableOptions['checks'][] = $definition;
}
}
/**
* Registers a custom mapper for the entity class.
*
* @param string $mapperClassName The class name of the custom mapper.
* @deprecated
*/
public function setCustomMapperClass($mapperClassName)
{
if ( ! is_subclass_of($mapperClassName, 'Doctrine_Mapper')) {
throw new Doctrine_ClassMetadata_Exception("The custom mapper must be a subclass"
. " of Doctrine_Mapper.");
. " of Doctrine_Mapper.");
}
$this->_customMapperClassName = $mapperClassName;
$this->_customRepositoryClassName = $mapperClassName;
}
/**
* Registers a custom mapper for the entity class.
*
* @param string $mapperClassName The class name of the custom mapper.
* @deprecated
*/
public function setCustomRepositoryClass($repositoryClassName)
{
if ( ! is_subclass_of($repositoryClassName, 'Doctrine_EntityRepository')) {
throw new Doctrine_ClassMetadata_Exception("The custom repository must be a subclass"
. " of Doctrine_EntityRepository.");
}
$this->_customRepositoryClassName = $repositoryClassName;
}
/**
* Gets the name of the custom mapper class used for the entity class.
*
* @return string|null The name of the custom mapper class or NULL if the entity
* class does not have a custom mapper class.
* @deprecated
*/
public function getCustomMapperClass()
{
return $this->_customMapperClassName;
return $this->_customRepositoryClassName;
}
public function getCustomRepositoryClass()
{
return $this->_customRepositoryClassName;
}
/**
* @todo Thoughts & Implementation.
*/
public function setType($type)
public function setEntityType($type)
{
//Doctrine::CLASSTYPE_ENTITY
//Doctrine::CLASSTYPE_MAPPED_SUPERCLASS
//Doctrine::CLASSTYPE_TRANSIENT
}
/**
*
*
* @todo Implementation. Replaces the bindComponent() methods on the old Doctrine_Manager.
* Binding an Entity to a specific EntityManager in 2.0 is the same as binding
* it to a Connection in 1.0.
*/
public function bindToEntityManager($emName)
{
}
/**
* @todo Implementation. Immutable entities can not be updated or deleted once
* they are created. This means the entity can only be modified as long as it's
......@@ -1784,12 +1821,12 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
{
return false;
}
public function isDiscriminatorColumn($columnName)
{
return $columnName === $this->_inheritanceOptions['discriminatorColumn'];
}
/**
* hasOne
* binds One-to-One aggregate relation
......@@ -1821,7 +1858,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
return $this;
}
public function hasAttribute($key)
{
switch ($key) {
......@@ -1837,7 +1874,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
}
}
/**
*
*/
......
......@@ -449,7 +449,8 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
}
} else {
// @todo does not take composite keys into account
$list[] = $record->getIncremented();
$ids = $record->identifier();
$list[] = count($ids) > 0 ? array_pop($ids) : null;
}
}
......@@ -564,7 +565,9 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
if ( ! isset($name)) {
foreach ($this->data as $record) {
$value = $record->getIncremented();
// FIXME: composite key support
$ids = $record->identifier();
$value = count($ids) > 0 ? array_pop($ids) : null;
if ($value !== null) {
$list[] = $value;
}
......@@ -583,7 +586,8 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
}
} else {
foreach ($this->data as $record) {
$value = $record->getIncremented();
$ids = $record->identifier();
$value = count($ids) > 0 ? array_pop($ids) : null;
if ($value !== null) {
$list[] = $value;
}
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Configurable');
/**
* Doctrine_Connection
*
......@@ -56,32 +56,20 @@ Doctrine::autoload('Doctrine_Configurable');
* @todo Split up into Doctrine::DBAL::Connection & Doctrine::ORM::EntityManager.
* Doctrine::DBAL::Connection must have no dependencies on ORM components since
* it sits one layer below.
* Right now, this is the unification of these two classes.
*/
abstract class Doctrine_Connection extends Doctrine_Configurable implements Countable, IteratorAggregate
{
/*
* ----------- Connection attributes ---------------
*/
/**
* The PDO database handle.
*
* @var PDO
*/
protected $dbh;
/**
* The metadata factory is used to retrieve the metadata of entity classes.
*
* @var Doctrine_ClassMetadata_Factory
* @todo package:orm
*/
protected $_metadataFactory;
/**
* An array of mapper objects currently maintained by this connection.
*
* @var array
* @todo package:orm
*/
protected $_mappers = array();
/**
* $_name
*
......@@ -90,29 +78,99 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
* @var string $_name
*/
protected $_name;
/**
* The name of this connection driver.
*
* @var string $driverName
*/
protected $driverName;
/**
* Whether or not a connection has been established.
*
* @var boolean $isConnected
*/
protected $isConnected = false;
/**
* An array containing all features this driver supports, keys representing feature
* names and values as one of the following (true, false, 'emulated').
*
* @var array $supported
*/
protected $supported = array();
protected $supported = array();
/**
* @var array $properties an array of connection properties
*/
protected $properties = array(
'sql_comments' => array(array('start' => '--', 'end' => "\n", 'escape' => false),
array('start' => '/*', 'end' => '*/', 'escape' => false)),
'identifier_quoting' => array('start' => '"', 'end' => '"','escape' => '"'),
'string_quoting' => array('start' => "'", 'end' => "'", 'escape' => false,
'escape_pattern' => false),
'wildcards' => array('%', '_'),
'varchar_max_length' => 255,
);
/**
* @var array $serverInfo
*/
protected $serverInfo = array();
/**
*
*/
protected $options = array();
/**
* List of all available drivers.
*
* @var array $availableDrivers
*/
private static $availableDrivers = array(
'Mysql', 'Pgsql', 'Oracle', 'Informix', 'Mssql', 'Sqlite', 'Firebird'
);
/**
* The query count. Represents the number of executed database queries by the connection.
*
* @var integer
*/
protected $_count = 0;
/*
* ----------- EntityManager attributes ---------------
*/
/**
* The metadata factory is used to retrieve the metadata of entity classes.
*
* @var Doctrine_ClassMetadata_Factory
* @todo package:orm
*/
protected $_metadataFactory;
/**
* An array of mapper objects currently maintained by this connection.
*
* @var array
* @todo package:orm
*/
protected $_mappers = array();
/**
* The EntityRepository instances.
*
* @var array
*/
private $_repositories = array();
/*
* ----------- Mixed attributes (need to split up) ---------------
*/
/**
* @var array $pendingAttributes An array of pending attributes. When setting attributes
* no connection is needed. When connected all the pending
......@@ -158,50 +216,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
'formatter' => false,
'util' => false,
);
/**
* @var array $properties an array of connection properties
*/
protected $properties = array('sql_comments' => array(array('start' => '--', 'end' => "\n", 'escape' => false),
array('start' => '/*', 'end' => '*/', 'escape' => false)),
'identifier_quoting' => array('start' => '"', 'end' => '"','escape' => '"'),
'string_quoting' => array('start' => "'",
'end' => "'",
'escape' => false,
'escape_pattern' => false),
'wildcards' => array('%', '_'),
'varchar_max_length' => 255,
);
/**
* @var array $serverInfo
*/
protected $serverInfo = array();
/**
*
*/
protected $options = array();
/**
* @var array $availableDrivers an array containing all available drivers
*/
private static $availableDrivers = array(
'Mysql',
'Pgsql',
'Oracle',
'Informix',
'Mssql',
'Sqlite',
'Firebird'
);
/**
* The query count. Represents the number of executed database queries by the connection.
*
* @var integer
*/
protected $_count = 0;
/**
* the constructor
......@@ -239,7 +254,11 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
$this->getAttribute(Doctrine::ATTR_LISTENER)->onOpen($this);
}
/*
* ----------- Connection methods ---------------
*/
/**
* getOption
*
......@@ -267,39 +286,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
{
return $this->options[$option] = $value;
}
/**
* getAttribute
* retrieves a database connection attribute
*
* @param integer $attribute
* @return mixed
*/
public function getAttribute($attribute)
{
if ($attribute >= 100) {
if ( ! isset($this->_attributes[$attribute])) {
return parent::getAttribute($attribute);
}
return $this->_attributes[$attribute];
}
if ($this->isConnected) {
try {
return $this->dbh->getAttribute($attribute);
} catch (Exception $e) {
throw new Doctrine_Connection_Exception('Attribute ' . $attribute . ' not found.');
}
} else {
if ( ! isset($this->pendingAttributes[$attribute])) {
$this->connect();
$this->getAttribute($attribute);
}
return $this->pendingAttributes[$attribute];
}
}
/**
* returns an array of available PDO drivers
*/
......@@ -307,32 +294,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
{
return PDO::getAvailableDrivers();
}
/**
* setAttribute
* sets an attribute
*
* @todo why check for >= 100? has this any special meaning when creating
* attributes?
*
* @param integer $attribute
* @param mixed $value
* @return boolean
*/
public function setAttribute($attribute, $value)
{
if ($attribute >= 100) {
parent::setAttribute($attribute, $value);
} else {
if ($this->isConnected) {
$this->dbh->setAttribute($attribute, $value);
} else {
$this->pendingAttributes[$attribute] = $value;
}
}
return $this;
}
/**
* getName
* returns the name of this driver
......@@ -343,7 +305,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
{
return $this->_name;
}
/**
* setName
*
......@@ -368,56 +330,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
{
return $this->driverName;
}
/**
* __get
* lazy loads given module and returns it
*
* @see Doctrine_DataDict
* @see Doctrine_Expression
* @see Doctrine_Export
* @see Doctrine_Transaction
* @see Doctrine_Connection::$modules all availible modules
* @param string $name the name of the module to get
* @throws Doctrine_Connection_Exception if trying to get an unknown module
* @return Doctrine_Connection_Module connection module
*/
public function __get($name)
{
if (isset($this->properties[$name])) {
return $this->properties[$name];
}
if ( ! isset($this->modules[$name])) {
throw new Doctrine_Connection_Exception('Unknown module / property ' . $name);
}
if ($this->modules[$name] === false) {
switch ($name) {
case 'unitOfWork':
$this->modules[$name] = new Doctrine_Connection_UnitOfWork($this);
break;
case 'formatter':
$this->modules[$name] = new Doctrine_Formatter($this);
break;
default:
$class = 'Doctrine_' . ucwords($name) . '_' . $this->getDriverName();
$this->modules[$name] = new $class($this);
}
}
return $this->modules[$name];
}
/**
* returns the manager that created this connection
*
* @return Doctrine_Manager
*/
public function getManager()
{
return $this->getParent();
}
/**
* returns the database handler which this connection uses
*
......@@ -429,7 +342,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
return $this->dbh;
}
/**
* Establishes the connection with the database.
*
......@@ -510,7 +423,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
&& ($this->supported[$feature] === 'emulated'
|| $this->supported[$feature]));
}
/**
* Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
* query, except that if there is already a row in the table with the same
......@@ -849,32 +762,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
{
return $this->execute($statement, $params)->fetchAll(Doctrine::FETCH_BOTH);
}
/**
* query
* queries the database using Doctrine Query Language
* returns a collection of Doctrine_Record objects
*
* <code>
* $users = $conn->query('SELECT u.* FROM User u');
*
* $users = $conn->query('SELECT u.* FROM User u WHERE u.name LIKE ?', array('someone'));
* </code>
*
* @param string $query DQL query
* @param array $params query parameters
* @param int $hydrationMode Doctrine::FETCH_ARRAY or Doctrine::FETCH_RECORD
* @see Doctrine_Query
* @return Doctrine_Collection Collection of Doctrine_Record objects
* @todo package:orm
*/
public function query($query, array $params = array(), $hydrationMode = null)
{
$parser = new Doctrine_Query($this);
return $parser->query($query, $params, $hydrationMode);
}
/**
* prepare
*
......@@ -903,37 +791,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
$this->rethrowException($e, $this);
}
/**
* query
* queries the database using Doctrine Query Language and returns
* the first record found
*
* <code>
* $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.id = ?', array(1));
*
* $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.name LIKE ? AND u.password = ?',
* array('someone', 'password')
* );
* </code>
*
* @param string $query DQL query
* @param array $params query parameters
* @see Doctrine_Query
* @return Doctrine_Record|false Doctrine_Record object on success,
* boolean false on failure
*/
public function queryOne($query, array $params = array())
{
$parser = new Doctrine_Query($this);
$coll = $parser->query($query, $params);
if ( ! $coll->contains(0)) {
return false;
}
return $coll[0];
}
/**
* queries the database with limit and offset
* added to the query and returns a Doctrine_Connection_Statement object
......@@ -977,7 +835,6 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
try {
if ( ! empty($params)) {
//echo $query . "<br />";
$stmt = $this->prepare($query);
$stmt->execute($params);
return $stmt;
......@@ -987,14 +844,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
$this->getAttribute(Doctrine::ATTR_LISTENER)->preQuery($event);
if ( ! $event->skipOperation) {
//try {
$stmt = $this->dbh->query($query);
/*} catch (Exception $e) {
if (strstr($e->getMessage(), 'no such column')) {
echo $query . "<br /><br />";
}
}*/
$stmt = $this->dbh->query($query);
$this->_count++;
}
$this->getAttribute(Doctrine::ATTR_LISTENER)->postQuery($event);
......@@ -1021,6 +871,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
if ( ! empty($params)) {
$stmt = $this->prepare($query);
$stmt->execute($params);
return $stmt->rowCount();
} else {
$event = new Doctrine_Event($this, Doctrine_Event::CONN_EXEC, $query, $params);
......@@ -1052,7 +903,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
$this->getListener()->preError($event);
$name = 'Doctrine_Connection_' . $this->driverName . '_Exception';
$exc = new $name($e->getMessage(), (int) $e->getCode());
if ( ! is_array($e->errorInfo)) {
$e->errorInfo = array(null, null, null, null);
......@@ -1065,151 +916,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
$this->getListener()->postError($event);
}
/**
* hasTable
* whether or not this connection has table $name initialized
*
* @param mixed $name
* @return boolean
* @deprecated
* @todo package:orm
*/
public function hasTable($name)
{
return isset($this->tables[$name]);
}
/**
* Returns the metadata for a class.
*
* @return Doctrine_Metadata
* @deprecated Use getClassMetadata()
* @todo package:orm
*/
public function getMetadata($className)
{
return $this->getClassMetadata($className);
}
/**
* Returns the metadata for a class.
*
* @return Doctrine_Metadata
* @todo package:orm
*/
public function getClassMetadata($className)
{
if ( ! $this->_metadataFactory) {
$this->_metadataFactory = new Doctrine_ClassMetadata_Factory($this,
new Doctrine_ClassMetadata_CodeDriver());
}
return $this->_metadataFactory->getMetadataFor($className);
}
/**
* Sets the driver that is used to obtain metadata informations about entity
* classes.
*
* @param $driver The driver to use.
* @todo package:orm
*/
public function setClassMetadataDriver($driver)
{
$this->_metadataFactory->setDriver($driver);
}
/**
* Gets a mapper for the specified domain class that is used to map instances of
* the class between the relational database and their object representation.
*
* @param string $entityClassName The name of the entity class.
* @return Doctrine_Mapper The mapper object.
* @todo package:orm
*/
/*public function getMapper($entityName)
{
if (isset($this->_mappers[$entityName])) {
return $this->_mappers[$entityName];
}
$metadata = $this->getClassMetadata($entityName);
$customMapperClassName = $metadata->getCustomMapperClass();
if ($customMapperClassName !== null) {
$mapper = new $customMapperClassName($entityName, $metadata);
} else {
// instantiate correct mapper type
$inheritanceType = $metadata->getInheritanceType();
if ($inheritanceType == Doctrine::INHERITANCE_TYPE_JOINED) {
$mapper = new Doctrine_Mapper_Joined($entityName, $metadata);
} else if ($inheritanceType == Doctrine::INHERITANCE_TYPE_SINGLE_TABLE) {
$mapper = new Doctrine_Mapper_SingleTable($entityName, $metadata);
} else if ($inheritanceType == Doctrine::INHERITANCE_TYPE_TABLE_PER_CLASS) {
$mapper = new Doctrine_Mapper_TablePerClass($entityName, $metadata);
} else {
throw new Doctrine_Connection_Exception("Unknown inheritance type '$inheritanceType'. Can't create mapper.");
}
}
$this->_mappers[$entityName] = $mapper;
return $mapper;
}*/
/**
* Gets a mapper for the specified domain class that is used to map instances of
* the class between the relational database and their object representation.
*
* @param string $entityClassName The name of the entity class.
* @return Doctrine_Mapper The mapper object.
* @todo package:orm
*/
public function getMapper($entityName)
{
if (isset($this->_mappers[$entityName])) {
return $this->_mappers[$entityName];
}
$metadata = $this->getClassMetadata($entityName);
$customMapperClassName = $metadata->getCustomMapperClass();
if ($customMapperClassName !== null) {
$mapper = new $customMapperClassName($entityName, $metadata);
} else {
$mapper = new Doctrine_Mapper($entityName, $metadata);
}
$this->_mappers[$entityName] = $mapper;
return $mapper;
}
/**
* Gets all mappers that are currently maintained by the connection.
*
* @todo package:orm
*/
public function getMappers()
{
return $this->_mappers;
}
/**
* returns an iterator that iterates through all
* initialized table objects
*
* <code>
* foreach ($conn as $index => $table) {
* print $table; // get a string representation of each table object
* }
* </code>
*
* @return ArrayIterator SPL ArrayIterator object
*/
public function getIterator()
{
return new ArrayIterator($this->_mappers);
}
/**
* Returns the number of queries executed by the connection.
*
......@@ -1220,85 +927,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
{
return $this->_count;
}
/**
* create
* creates a record
*
* create creates a record
* @param string $name component name
* @return Doctrine_Record Doctrine_Record object
* @todo Any strong reasons why this should not be removed?
* @todo package:orm
*/
public function create($name)
{
return $this->getMapper($name)->create();
}
/**
* Creates a new Doctrine_Query object that operates on this connection.
*
* @return Doctrine_Query
* @todo package:orm
*/
public function createQuery($dql = "")
{
$query = new Doctrine_Query($this);
if ( ! empty($dql)) {
$query->parseQuery($dql);
}
return $query;
}
/**
* flush
* saves all the records from all tables
* this operation is isolated using a transaction
*
* @throws PDOException if something went wrong at database level
* @return void
* @todo package:orm
*/
public function flush()
{
$this->beginInternalTransaction();
$this->unitOfWork->flush();
$this->commit();
}
/**
* clear
* clears all repositories
*
* @return void
* @todo package:orm
*/
public function clear()
{
$this->unitOfWork->detachAll();
foreach ($this->_mappers as $mapper) {
$mapper->clear(); // clear identity map of each mapper
}
}
/**
* evictTables
* evicts all tables
*
* @return void
* @todo package:orm
* @deprecated
*/
public function evictTables()
{
$this->clear();
$this->tables = array();
$this->_mappers = array();
$this->exported = array();
}
/**
* Closes the connection.
*
......@@ -1326,18 +955,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
{
return $this->transaction->getTransactionLevel();
}
/**
* Returns the current internal transaction nesting level.
*
* @return integer The nesting level. A value of 0 means theres no active transaction.
* @todo package:orm???
*/
public function getInternalTransactionLevel()
{
return $this->transaction->getInternalTransactionLevel();
}
/**
* errorCode
* Fetch the SQLSTATE associated with the last operation on the database handle
......@@ -1363,50 +981,9 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
return $this->dbh->errorInfo();
}
/**
* getCacheDriver
*
* @return Doctrine_Cache_Interface
* @deprecated Use getResultCacheDriver()
*/
public function getCacheDriver()
{
return $this->getResultCacheDriver();
}
/**
* getResultCacheDriver
*
* @return Doctrine_Cache_Interface
* @todo package:orm
*/
public function getResultCacheDriver()
{
if ( ! $this->getAttribute(Doctrine::ATTR_RESULT_CACHE)) {
throw new Doctrine_Exception('Result Cache driver not initialized.');
}
return $this->getAttribute(Doctrine::ATTR_RESULT_CACHE);
}
/**
* getQueryCacheDriver
*
* @return Doctrine_Cache_Interface
* @todo package:orm
*/
public function getQueryCacheDriver()
{
if ( ! $this->getAttribute(Doctrine::ATTR_QUERY_CACHE)) {
throw new Doctrine_Exception('Query Cache driver not initialized.');
}
return $this->getAttribute(Doctrine::ATTR_QUERY_CACHE);
}
/**
* lastInsertId
* lastInsertId
*
* Returns the ID of the last inserted row, or the last value from a sequence object,
* depending on the underlying driver.
......@@ -1439,20 +1016,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
{
return $this->transaction->beginTransaction($savepoint);
}
/**
* Initiates a transaction.
*
* This method must only be used by Doctrine itself to initiate transactions.
* Userland-code must use {@link beginTransaction()}.
*
* @todo package:orm???
*/
public function beginInternalTransaction($savepoint = null)
{
return $this->transaction->beginInternalTransaction($savepoint);
}
/**
* commit
* Commit the database changes done during a transaction that is in
......@@ -1564,47 +1128,491 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
return Doctrine_Lib::getConnectionAsString($this);
}
public function hasAttribute($key)
{
switch ($key) {
case Doctrine::ATTR_COLL_KEY:
case Doctrine::ATTR_LISTENER:
case Doctrine::ATTR_RECORD_LISTENER:
case Doctrine::ATTR_QUOTE_IDENTIFIER:
case Doctrine::ATTR_SEQCOL_NAME:
case Doctrine::ATTR_FIELD_CASE:
case Doctrine::ATTR_IDXNAME_FORMAT:
case Doctrine::ATTR_SEQNAME_FORMAT:
case Doctrine::ATTR_DBNAME_FORMAT:
case Doctrine::ATTR_TBLCLASS_FORMAT:
case Doctrine::ATTR_TBLNAME_FORMAT:
case Doctrine::ATTR_EXPORT:
case Doctrine::ATTR_DECIMAL_PLACES:
case Doctrine::ATTR_PORTABILITY:
case Doctrine::ATTR_VALIDATE:
case Doctrine::ATTR_QUERY_LIMIT:
case Doctrine::ATTR_DEFAULT_TABLE_TYPE:
case Doctrine::ATTR_DEF_TEXT_LENGTH:
case Doctrine::ATTR_DEF_VARCHAR_LENGTH:
case Doctrine::ATTR_DEF_TABLESPACE:
case Doctrine::ATTR_EMULATE_DATABASE:
case Doctrine::ATTR_USE_NATIVE_ENUM:
case Doctrine::ATTR_CREATE_TABLES:
case Doctrine::ATTR_COLL_LIMIT:
case Doctrine::ATTR_CACHE: // deprecated
case Doctrine::ATTR_RESULT_CACHE:
case Doctrine::ATTR_CACHE_LIFESPAN: // deprecated
case Doctrine::ATTR_RESULT_CACHE_LIFESPAN:
case Doctrine::ATTR_LOAD_REFERENCES:
case Doctrine::ATTR_THROW_EXCEPTIONS:
case Doctrine::ATTR_QUERY_CACHE:
case Doctrine::ATTR_QUERY_CACHE_LIFESPAN:
case Doctrine::ATTR_MODEL_LOADING:
case Doctrine::ATTR_METADATA_CACHE:
case Doctrine::ATTR_METADATA_CACHE_LIFESPAN:
return true;
default:
return false;
/*
* ----------- EntityManager methods ---------------
*/
/**
* query
* queries the database using Doctrine Query Language
* returns a collection of Doctrine_Record objects
*
* <code>
* $users = $conn->query('SELECT u.* FROM User u');
*
* $users = $conn->query('SELECT u.* FROM User u WHERE u.name LIKE ?', array('someone'));
* </code>
*
* @param string $query DQL query
* @param array $params query parameters
* @param int $hydrationMode Doctrine::FETCH_ARRAY or Doctrine::FETCH_RECORD
* @see Doctrine_Query
* @return Doctrine_Collection Collection of Doctrine_Record objects
* @todo package:orm
*/
public function query($query, array $params = array(), $hydrationMode = null)
{
$parser = new Doctrine_Query($this);
return $parser->query($query, $params, $hydrationMode);
}
/**
* query
* queries the database using Doctrine Query Language and returns
* the first record found
*
* <code>
* $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.id = ?', array(1));
*
* $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.name LIKE ? AND u.password = ?',
* array('someone', 'password')
* );
* </code>
*
* @param string $query DQL query
* @param array $params query parameters
* @see Doctrine_Query
* @return Doctrine_Record|false Doctrine_Record object on success,
* boolean false on failure
*/
public function queryOne($query, array $params = array())
{
$parser = new Doctrine_Query($this);
$coll = $parser->query($query, $params);
if ( ! $coll->contains(0)) {
return false;
}
return $coll[0];
}
/**
* hasTable
* whether or not this connection has table $name initialized
*
* @param mixed $name
* @return boolean
* @deprecated
* @todo package:orm
*/
public function hasTable($name)
{
return isset($this->tables[$name]);
}
/**
* Returns the metadata for a class.
*
* @return Doctrine_Metadata
* @deprecated Use getClassMetadata()
* @todo package:orm
*/
public function getMetadata($className)
{
return $this->getClassMetadata($className);
}
/**
* Returns the metadata for a class.
*
* @return Doctrine_Metadata
* @todo package:orm
*/
public function getClassMetadata($className)
{
if ( ! $this->_metadataFactory) {
$this->_metadataFactory = new Doctrine_ClassMetadata_Factory($this,
new Doctrine_ClassMetadata_CodeDriver());
}
return $this->_metadataFactory->getMetadataFor($className);
}
/**
* Sets the driver that is used to obtain metadata informations about entity
* classes.
*
* @param $driver The driver to use.
* @todo package:orm
*/
public function setClassMetadataDriver($driver)
{
$this->_metadataFactory->setDriver($driver);
}
/**
* Gets a mapper for the specified domain class that is used to map instances of
* the class between the relational database and their object representation.
*
* @param string $entityClassName The name of the entity class.
* @return Doctrine_Mapper The mapper object.
* @todo package:orm
*/
public function getMapper($entityName)
{
if (isset($this->_mappers[$entityName])) {
return $this->_mappers[$entityName];
}
$metadata = $this->getClassMetadata($entityName);
$customMapperClassName = $metadata->getCustomMapperClass();
if ($customMapperClassName !== null) {
$mapper = new $customMapperClassName($entityName, $metadata);
} else {
$mapper = new Doctrine_Mapper($entityName, $metadata);
}
$this->_mappers[$entityName] = $mapper;
return $mapper;
}
/**
* Gets all mappers that are currently maintained by the connection.
*
* @todo package:orm
*/
public function getMappers()
{
return $this->_mappers;
}
/**
* returns an iterator that iterates through all
* initialized table objects
*
* <code>
* foreach ($conn as $index => $table) {
* print $table; // get a string representation of each table object
* }
* </code>
*
* @return ArrayIterator SPL ArrayIterator object
*/
public function getIterator()
{
return new ArrayIterator($this->_mappers);
}
/**
* create
* creates a record
*
* create creates a record
* @param string $name component name
* @return Doctrine_Record Doctrine_Record object
* @todo Any strong reasons why this should not be removed?
* @todo package:orm
*/
public function create($name)
{
return $this->getMapper($name)->create();
}
/**
* Creates a new Doctrine_Query object that operates on this connection.
*
* @return Doctrine_Query
* @todo package:orm
*/
public function createQuery($dql = "")
{
$query = new Doctrine_Query($this);
if ( ! empty($dql)) {
$query->parseQuery($dql);
}
return $query;
}
/**
* flush
* saves all the records from all tables
* this operation is isolated using a transaction
*
* @throws PDOException if something went wrong at database level
* @return void
* @todo package:orm
*/
public function flush()
{
$this->beginInternalTransaction();
$this->unitOfWork->flush();
$this->commit();
}
/**
* clear
* clears all repositories
*
* @return void
* @todo package:orm
*/
public function clear($entityName = null)
{
if ($entityName === null) {
$this->unitOfWork->detachAll();
foreach ($this->_mappers as $mapper) {
$mapper->clear(); // clear identity map of each mapper
}
} else {
$this->getMapper($entityName)->clear();
}
}
/**
* evictTables
* evicts all tables
*
* @return void
* @todo package:orm
* @deprecated
*/
public function evictTables()
{
$this->clear();
$this->tables = array();
$this->_mappers = array();
$this->exported = array();
}
public function save(Doctrine_Record $entity, $conn = null)
{
$this->getMapper($entity->getClassName())->save($entity, $conn);
}
public function remove(Doctrine_Record $entity, $conn = null)
{
$this->getMapper($entity->getClassName())->delete($entity, $conn);
}
public function createEntity($entityName, array $data = array())
{
return $this->getMapper($entityName)->create($data);
}
public function detach(Doctrine_Record $entity)
{
$this->getMapper($entity->getClassName())->detach($entity);
}
public function removeRecord(Doctrine_Record $entity)
{
$this->getMapper($entity->getClassName())->removeRecord($entity);
}
public function manage(Doctrine_Record $entity)
{
$this->getMapper($entity->getClassName())->manage($entity);
}
public function executeNamedQuery($name, $params = array(), $hydrationMode = Doctrine::HYDRATE_RECORD)
{
return Doctrine_Manager::getInstance()
->createNamedQuery($name)
->execute($params, $hydrationMode);
}
/**
* Returns the current internal transaction nesting level.
*
* @return integer The nesting level. A value of 0 means theres no active transaction.
* @todo package:orm???
*/
public function getInternalTransactionLevel()
{
return $this->transaction->getInternalTransactionLevel();
}
/**
* getCacheDriver
*
* @return Doctrine_Cache_Interface
* @deprecated Use getResultCacheDriver()
*/
public function getCacheDriver()
{
return $this->getResultCacheDriver();
}
/**
* getResultCacheDriver
*
* @return Doctrine_Cache_Interface
* @todo package:orm
*/
public function getResultCacheDriver()
{
if ( ! $this->getAttribute(Doctrine::ATTR_RESULT_CACHE)) {
throw new Doctrine_Exception('Result Cache driver not initialized.');
}
return $this->getAttribute(Doctrine::ATTR_RESULT_CACHE);
}
/**
* getQueryCacheDriver
*
* @return Doctrine_Cache_Interface
* @todo package:orm
*/
public function getQueryCacheDriver()
{
if ( ! $this->getAttribute(Doctrine::ATTR_QUERY_CACHE)) {
throw new Doctrine_Exception('Query Cache driver not initialized.');
}
return $this->getAttribute(Doctrine::ATTR_QUERY_CACHE);
}
/**
* Initiates a transaction.
*
* This method must only be used by Doctrine itself to initiate transactions.
* Userland-code must use {@link beginTransaction()}.
*
* @todo package:orm???
*/
public function beginInternalTransaction($savepoint = null)
{
return $this->transaction->beginInternalTransaction($savepoint);
}
/**
* Enter description here...
*
* @todo To EntityManager
*/
public function getRepository($entityName)
{
if (isset($this->_repositories[$entityName])) {
return $this->_repositories[$entityName];
}
$metadata = $this->getClassMetadata($entityName);
$customRepositoryClassName = $metadata->getCustomRepositoryClass();
if ($customRepositoryClassName !== null) {
$repository = new $customRepositoryClassName($entityName, $metadata);
} else {
$repository = new Doctrine_EntityRepository($entityName, $metadata);
}
$this->_repositories[$entityName] = $repository;
return $repository;
}
/*
* ----------- Mixed methods (need to figure out where they go) ---------------
*/
/**
* getAttribute
* retrieves a database connection attribute
*
* @param integer $attribute
* @return mixed
*/
public function getAttribute($attribute)
{
if ($attribute >= 100) {
if ( ! isset($this->_attributes[$attribute])) {
return parent::getAttribute($attribute);
}
return $this->_attributes[$attribute];
}
if ($this->isConnected) {
try {
return $this->dbh->getAttribute($attribute);
} catch (Exception $e) {
throw new Doctrine_Connection_Exception('Attribute ' . $attribute . ' not found.');
}
} else {
if ( ! isset($this->pendingAttributes[$attribute])) {
$this->connect();
$this->getAttribute($attribute);
}
return $this->pendingAttributes[$attribute];
}
}
/**
* setAttribute
* sets an attribute
*
* @todo why check for >= 100? has this any special meaning when creating
* attributes?
*
* @param integer $attribute
* @param mixed $value
* @return boolean
*/
public function setAttribute($attribute, $value)
{
if ($attribute >= 100) {
parent::setAttribute($attribute, $value);
} else {
if ($this->isConnected) {
$this->dbh->setAttribute($attribute, $value);
} else {
$this->pendingAttributes[$attribute] = $value;
}
}
return $this;
}
/**
* __get
* lazy loads given module and returns it
*
* @see Doctrine_DataDict
* @see Doctrine_Expression
* @see Doctrine_Export
* @see Doctrine_Transaction
* @see Doctrine_Connection::$modules all availible modules
* @param string $name the name of the module to get
* @throws Doctrine_Connection_Exception if trying to get an unknown module
* @return Doctrine_Connection_Module connection module
*/
public function __get($name)
{
if (isset($this->properties[$name])) {
return $this->properties[$name];
}
if ( ! isset($this->modules[$name])) {
throw new Doctrine_Connection_Exception('Unknown module / property ' . $name);
}
if ($this->modules[$name] === false) {
switch ($name) {
case 'unitOfWork':
$this->modules[$name] = new Doctrine_Connection_UnitOfWork($this);
break;
case 'formatter':
$this->modules[$name] = new Doctrine_Formatter($this);
break;
default:
$class = 'Doctrine_' . ucwords($name) . '_' . $this->getDriverName();
$this->modules[$name] = new $class($this);
}
}
return $this->modules[$name];
}
/**
* returns the manager that created this connection
*
* @return Doctrine_Manager
*/
public function getManager()
{
return $this->getParent();
}
}
......@@ -20,7 +20,23 @@
*/
/**
* Doctrine_Connection_UnitOfWork
* The UnitOfWork is responsible for writing out changes to the database at
* the correct time and in the correct order.
*
* Some terminology:
*
* <b>New entity</b>: From the point of view of the unitOfWork is an entity that
* already has an identity but is not yet persisted into the database. This
* is usually the case for all newly saved entities that use a SEQUENCE id
* generator. Entities with an IDENTITY id generator get persisted as soon
* as they're saved in order to obtain the identifier. Therefore entities that
* use an IDENTITY id generator never appear in the list of new entities of the UoW.
*
* <b>Dirty entity</b>: ...
*
* <b>Removed entity</b>: ...
*
* <b>Clean entity</b>: ...
*
* @package Doctrine
* @subpackage Connection
......@@ -105,12 +121,19 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
*/
public function registerNew(Doctrine_Record $entity)
{
if (isset($this->_dirtyEntities[$entity->getOid()])) {
if ( ! $entity->identifier()) {
throw new Doctrine_Connection_Exception("Entity without identity "
. "can't be registered as new.");
}
$oid = $entity->getOid();
if (isset($this->_dirtyEntities[$oid])) {
throw new Doctrine_Connection_Exception("Dirty object can't be registered as new.");
} else if (isset($this->_removedEntities[$entity->getOid()])) {
} else if (isset($this->_removedEntities[$oid])) {
throw new Doctrine_Connection_Exception("Removed object can't be registered as new.");
} else if (isset($this->_newEntities[$oid])) {
throw new Doctrine_Connection_Exception("Object already registered as new. Can't register twice.");
}
$this->_newEntities[$entity->getOid()] = $entity;
$this->_newEntities[$oid] = $entity;
}
public function isRegisteredNew(Doctrine_Record $entity)
......@@ -131,12 +154,17 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
*/
public function registerDirty(Doctrine_Record $entity)
{
if ( ! $entity->identifier()) {
throw new Doctrine_Connection_Exception("Entity without identity "
. "can't be registered as dirty.");
}
$oid = $entity->getOid();
if (isset($this->_removedEntities[$entity->getOid()])) {
throw new Doctrine_Connection_Exception("Removed object can't be registered as dirty.");
} else if (isset($this->_newEntities[$entity->getOid()])) {
throw new Doctrine_Connection_Exception("");
}
$this->_dirtyEntities[$entity->getOid()] = $entity;
if ( ! isset($this->_dirtyEntities[$oid], $this->_newEntities[$oid])) {
$this->_dirtyEntities[$entity->getOid()] = $entity;
}
}
public function isRegisteredDirty(Doctrine_Record $entity)
......@@ -149,8 +177,21 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
*/
public function registerRemoved(Doctrine_Record $entity)
{
if ($entity->isTransient()) {
return;
}
$this->unregisterIdentity($entity);
$this->_removedEntities[$entity->getOid()] = $entity;
$oid = $entity->getOid();
if (isset($this->_newEntities[$oid])) {
unset($this->_newEntities[$oid]);
return;
}
if (isset($this->_dirtyEntities[$oid])) {
unset($this->_dirtyEntities[$oid]);
}
if ( ! isset($this->_removedEntities[$oid])) {
$this->_removedEntities[$oid] = $entity;
}
}
public function isRegisteredRemoved(Doctrine_Record $entity)
......
<?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 custom user-defined repositories.
* Provides basic finder methods, common to all repositories.
*
* @package Doctrine
* @subpackage EntityRepository
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 2.0
* @version $Revision$
* @author Roman Borschel <roman@code-factory.org>
* @todo package:orm
*/
class Doctrine_EntityRepository
{
protected $_entityName;
protected $_conn;
protected $_classMetadata;
public function __construct($entityName, Doctrine_ClassMetadata $classMetadata)
{
$this->_entityName = $entityName;
$this->_conn = $classMetadata->getConnection();
$this->_classMetadata = $classMetadata;
}
/**
* createQuery
* creates a new Doctrine_Query object and adds the component name
* of this table as the query 'from' part
*
* @param string Optional alias name for component aliasing.
*
* @return Doctrine_Query
*/
protected function _createQuery($alias = '')
{
if ( ! empty($alias)) {
$alias = ' ' . trim($alias);
}
return Doctrine_Query::create($this->_conn)->from($this->_entityName . $alias);
}
/**
* clear
* clears the first level cache (identityMap)
*
* @return void
* @todo what about a more descriptive name? clearIdentityMap?
*/
public function clear()
{
$this->_conn->unitOfWork->clearIdentitiesForEntity($this->_classMetadata->getRootClassName());
}
/**
* Finds an entity by its primary key.
*
* @param $id database row id
* @param int $hydrationMode Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
* @return mixed Array or Doctrine_Record or false if no result
* @todo Remove. Move to EntityRepository.
*/
public function find($id, $hydrationMode = null)
{
if (is_null($id)) {
return false;
}
if (is_array($id) && count($id) > 1) {
// it's a composite key. keys = field names, values = values.
$values = array_values($id);
$keys = array_keys($id);
} else {
$values = is_array($id) ? array_values($id) : array($id);
$keys = $this->_classMetadata->getIdentifier();
}
return $this->_createQuery()
->where(implode(' = ? AND ', $keys) . ' = ?')
->fetchOne($values, $hydrationMode);
}
/**
* Finds all entities of the mapper's class.
* Use with care.
*
* @param int $hydrationMode Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
* @return Doctrine_Collection
*/
public function findAll($hydrationMode = null)
{
return $this->_createQuery()->execute(array(), $hydrationMode);
}
/**
* findBy
*
* @param string $column
* @param string $value
* @param string $hydrationMode
* @return void
*/
protected function findBy($fieldName, $value, $hydrationMode = null)
{
return $this->_createQuery()->where($fieldName . ' = ?')->execute(array($value), $hydrationMode);
}
/**
* findOneBy
*
* @param string $column
* @param string $value
* @param string $hydrationMode
* @return void
*/
protected function findOneBy($fieldName, $value, $hydrationMode = null)
{
$results = $this->_createQuery()->where($fieldName . ' = ?')->limit(1)->execute(
array($value), $hydrationMode);
return $hydrationMode === Doctrine::HYDRATE_ARRAY ? array_shift($results) : $results->getFirst();
}
/**
* findBySql
* finds records with given SQL where clause
* returns a collection of records
*
* @param string $dql DQL after WHERE clause
* @param array $params query parameters
* @param int $hydrationMode Doctrine::FETCH_ARRAY or Doctrine::FETCH_RECORD
* @return Doctrine_Collection
*
* @todo This actually takes DQL, not SQL, but it requires column names
* instead of field names. This should be fixed to use raw SQL instead.
*/
public function findBySql($dql, array $params = array(), $hydrationMode = null)
{
return $this->_createQuery()->where($dql)->execute($params, $hydrationMode);
}
/**
* findByDql
* finds records with given DQL where clause
* returns a collection of records
*
* @param string $dql DQL after WHERE clause
* @param array $params query parameters
* @param int $hydrationMode Doctrine::FETCH_ARRAY or Doctrine::FETCH_RECORD
* @return Doctrine_Collection
*/
public function findByDql($dql, array $params = array(), $hydrationMode = null)
{
$query = new Doctrine_Query($this->_conn);
$component = $this->getComponentName();
$dql = 'FROM ' . $component . ' WHERE ' . $dql;
return $query->query($dql, $params, $hydrationMode);
}
/**
* Adds support for magic finders.
* findByColumnName, findByRelationAlias
* findById, findByContactId, etc.
*
* @return void
* @throws Doctrine_Mapper_Exception If the method called is an invalid find* method
* or no find* method at all and therefore an invalid
* method call.
*/
public function __call($method, $arguments)
{
if (substr($method, 0, 6) == 'findBy') {
$by = substr($method, 6, strlen($method));
$method = 'findBy';
} else if (substr($method, 0, 9) == 'findOneBy') {
$by = substr($method, 9, strlen($method));
$method = 'findOneBy';
} else {
throw new Doctrine_Mapper_Exception("Undefined method '$method'.");
}
if (isset($by)) {
if ( ! isset($arguments[0])) {
throw new Doctrine_Mapper_Exception('You must specify the value to findBy.');
}
$fieldName = Doctrine::tableize($by);
$hydrationMode = isset($arguments[1]) ? $arguments[1]:null;
if ($this->_classMetadata->hasField($fieldName)) {
return $this->$method($fieldName, $arguments[0], $hydrationMode);
} else if ($this->_classMetadata->hasRelation($by)) {
$relation = $this->_classMetadata->getRelation($by);
if ($relation['type'] === Doctrine_Relation::MANY) {
throw new Doctrine_Mapper_Exception('Cannot findBy many relationship.');
}
return $this->$method($relation['local'], $arguments[0], $hydrationMode);
} else {
throw new Doctrine_Mapper_Exception('Cannot find by: ' . $by . '. Invalid field or relationship alias.');
}
}
}
}
\ No newline at end of file
......@@ -52,13 +52,14 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
* 'table' => Table object,
* 'parent' => Parent DQL alias (if any),
* 'relation' => Relation object (if any),
* 'map' => Custom index to use as the key in the result (if any)
* 'map' => Custom index to use as the key in the result (if any),
* 'agg' => List of aggregate values (sql alias => dql alias)
* )
* )
* @return mixed The created object/array graph.
*/
public function hydrateResultSet($stmt, $tableAliases, $hydrationMode = null)
{
{
if ($hydrationMode === null) {
$hydrationMode = $this->_hydrationMode;
}
......@@ -82,7 +83,7 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
// Used variables during hydration
reset($this->_queryComponents);
$rootAlias = key($this->_queryComponents);
$rootComponentName = $this->_queryComponents[$rootAlias]['mapper']->getComponentName();
$rootComponentName = $this->_queryComponents[$rootAlias]['table']->getComponentName();
// if only one component is involved we can make our lives easier
$isSimpleQuery = count($this->_queryComponents) <= 1;
// Holds hydration listeners that get called during hydration
......@@ -110,7 +111,7 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
foreach ($this->_queryComponents as $dqlAlias => $component) {
// disable lazy-loading of related elements during hydration
$component['table']->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, false);
$componentName = $component['mapper']->getComponentName();
$componentName = $component['table']->getClassName();
$listeners[$componentName] = $component['table']->getRecordListener();
$identifierMap[$dqlAlias] = array();
$prev[$dqlAlias] = array();
......@@ -127,9 +128,8 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
//
// hydrate the data of the root entity from the current row
//
$table = $this->_queryComponents[$rootAlias]['table'];
$mapper = $this->_queryComponents[$rootAlias]['mapper'];
$componentName = $mapper->getComponentName();
$class = $this->_queryComponents[$rootAlias]['table'];
$componentName = $class->getComponentName();
// just event stuff
$event->set('data', $rowData[$rootAlias]);
......@@ -175,9 +175,7 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
foreach ($rowData as $dqlAlias => $data) {
$index = false;
$map = $this->_queryComponents[$dqlAlias];
$table = $map['table'];
$mapper = $map['mapper'];
$componentName = $mapper->getComponentName();
$componentName = $map['table']->getComponentName();
// just event stuff
$event->set('data', $data);
......@@ -186,7 +184,7 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
$parent = $map['parent'];
$relation = $map['relation'];
$relationAlias = $map['relation']->getAlias();
$relationAlias = $relation->getAlias();
$path = $parent . '.' . $dqlAlias;
......@@ -195,16 +193,19 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
}
// check the type of the relation
if ( ! $relation->isOneToOne() && $driver->initRelated($prev[$parent], $relationAlias)) {
if ( ! $relation->isOneToOne()) {
$oneToOne = false;
// append element
if (isset($nonemptyComponents[$dqlAlias])) {
$driver->initRelated($prev[$parent], $relationAlias);
if ( ! isset($identifierMap[$path][$id[$parent]][$id[$dqlAlias]])) {
$element = $driver->getElement($data, $componentName);
// just event stuff
$event->set('data', $element);
$listeners[$componentName]->postHydrate($event);
//--
if ($field = $this->_getCustomIndexField($dqlAlias)) {
// TODO: we should check this earlier. Fields used in INDEXBY
// must be unique. Then this can be removed here.
......@@ -223,7 +224,7 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
$index = $identifierMap[$path][$id[$parent]][$id[$dqlAlias]];
}
// register collection for later snapshots
$driver->registerCollection($prev[$parent][$relationAlias]);
//$driver->registerCollection($prev[$parent][$relationAlias]);
}
} else {
// 1-1 relation
......@@ -315,11 +316,17 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
if ( ! isset($cache[$key])) {
// cache general information like the column name <-> field name mapping
$e = explode('__', $key);
$columnName = strtolower(array_pop($e));
$columnName = strtolower(array_pop($e));
$cache[$key]['dqlAlias'] = $this->_tableAliases[strtolower(implode('__', $e))];
$mapper = $this->_queryComponents[$cache[$key]['dqlAlias']]['mapper'];
$classMetadata = $mapper->getClassMetadata();
$fieldName = $mapper->getFieldName($columnName);
// check whether it's an aggregate value or a regular field
if (isset($this->_queryComponents[$cache[$key]['dqlAlias']]['agg'][$columnName])) {
$fieldName = $this->_queryComponents[$cache[$key]['dqlAlias']]['agg'][$columnName];
} else {
$fieldName = $mapper->getFieldName($columnName);
}
$cache[$key]['fieldName'] = $fieldName;
// cache identifier information
......@@ -343,10 +350,6 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
$dqlAlias = $cache[$key]['dqlAlias'];
$fieldName = $cache[$key]['fieldName'];
if (isset($this->_queryComponents[$dqlAlias]['agg'][$fieldName])) {
$fieldName = $this->_queryComponents[$dqlAlias]['agg'][$fieldName];
}
if ($cache[$key]['isIdentifier']) {
$id[$dqlAlias] .= '|' . $value;
}
......
......@@ -71,8 +71,6 @@ class Doctrine_Hydrator_ArrayDriver
if ( ! isset($data[$name])) {
$data[$name] = array();
}
return true;
}
/**
......
......@@ -20,7 +20,7 @@
*/
/**
* Doctrine_Hydrate_RecordDriver
* Doctrine_Hydrator_RecordDriver
* Hydration strategy used for creating graphs of entity objects.
*
* @package Doctrine
......@@ -34,8 +34,13 @@
*/
class Doctrine_Hydrator_RecordDriver
{
/** Collections initialized by the driver */
protected $_collections = array();
/** Mappers */
protected $_mappers = array();
/** Memory for initialized relations */
private $_initializedRelations = array();
/** Null object */
private $_nullObject;
public function __construct()
......@@ -53,54 +58,32 @@ class Doctrine_Hydrator_RecordDriver
public function getLastKey($coll)
{
$coll->end();
return $coll->key();
// check needed because of mixed results
if (is_array($coll)) {
end($coll);
return key($coll);
} else {
$coll->end();
return $coll->key();
}
}
public function initRelated($record, $name)
public function initRelated(Doctrine_Record $record, $name)
{
return true;
/*
if ( ! is_array($record)) {
$record[$name];
return true;
if ( ! isset($this->_initializedRelations[$record->getOid()][$name])) {
$relation = $record->getClassMetadata()->getRelation($name);
$relatedClass = $relation->getTable();
$coll = $this->getElementCollection($relatedClass->getClassName());
$coll->setReference($record, $relation);
$record[$name] = $coll;
$this->_initializedRelations[$record->getOid()][$name] = true;
}
return false;
*/
}
public function registerCollection(Doctrine_Collection $coll)
{
$this->_collections[] = $coll;
}
/**
* isIdentifiable
* returns whether or not a given data row is identifiable (it contains
* all primary key fields specified in the second argument)
*
* @param array $row
* @param Doctrine_Table $table
* @return boolean
*/
/*public function isIdentifiable(array $row, Doctrine_Table $table)
{
$primaryKeys = $table->getIdentifierColumnNames();
if (is_array($primaryKeys)) {
foreach ($primaryKeys as $id) {
if ( ! isset($row[$id])) {
return false;
}
}
} else {
if ( ! isset($row[$primaryKeys])) {
return false;
}
}
return true;
}*/
public function getNullPointer()
{
......@@ -127,6 +110,7 @@ class Doctrine_Hydrator_RecordDriver
}
$this->_collections = array();
$this->_mappers = array();
$this->_initializedRelations = array();
}
/**
......
<?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 hydrator has the tedious task to construct object or array graphs out of
* a database result set.
*
* @package Doctrine
* @subpackage Hydrator
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision: 3192 $
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Roman Borschel <roman@code-factory.org>
*/
class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract
{
/**
* hydrateResultSet
* parses the data returned by statement object
*
* This is method defines the core of Doctrine's object population algorithm.
*
* The key idea is the loop over the rowset only once doing all the needed operations
* within this massive loop.
*
* @todo: Detailed documentation. Refactor (too long & nesting level).
*
* @param mixed $stmt
* @param array $tableAliases Array that maps table aliases (SQL alias => DQL alias)
* @param array $aliasMap Array that maps DQL aliases to their components
* (DQL alias => array(
* 'table' => Table object,
* 'parent' => Parent DQL alias (if any),
* 'relation' => Relation object (if any),
* 'map' => Custom index to use as the key in the result (if any),
* 'agg' => List of aggregate value names (sql alias => dql alias)
* )
* )
* @return mixed The created object/array graph.
*/
public function hydrateResultSet($stmt, $tableAliases, $hydrationMode = null)
{
if ($hydrationMode === null) {
$hydrationMode = $this->_hydrationMode;
}
if ($hydrationMode == Doctrine::HYDRATE_NONE) {
return $stmt->fetchAll(PDO::FETCH_NUM);
}
$this->_tableAliases = $tableAliases;
if ($hydrationMode == Doctrine::HYDRATE_ARRAY) {
$driver = new Doctrine_Hydrator_ArrayDriver();
} else {
$driver = new Doctrine_Hydrator_RecordDriver();
}
$event = new Doctrine_Event(null, Doctrine_Event::HYDRATE, null);
//$s = microtime(true);
// Used variables during hydration
reset($this->_queryComponents);
$rootAlias = key($this->_queryComponents);
$rootComponentName = $this->_queryComponents[$rootAlias]['table']->getClassName();
// if only one class is involved we can make our lives easier
$isSimpleQuery = count($this->_queryComponents) <= 1;
// Holds hydration listeners that get called during hydration
$listeners = array();
// Lookup map to quickly discover/lookup existing records in the result
// It's the identifier "memory"
$identifierMap = array();
// Holds for each class a pointer to the last previously seen element in the result set
$resultPointers = array();
// holds the values of the identifier/primary key fields of components,
// separated by a pipe '|' and grouped by component alias (r, u, i, ... whatever)
// the $idTemplate is a prepared template. $id is set to a fresh template when
// starting to process a row.
$id = array();
$idTemplate = array();
// Holds the resulting hydrated data structure
if ($this->_isResultMixed) {
$result = array();
} else {
$result = $driver->getElementCollection($rootComponentName);
}
if ($stmt === false || $stmt === 0) {
return $result;
}
// Initialize
foreach ($this->_queryComponents as $dqlAlias => $component) {
// disable lazy-loading of related elements during hydration
$component['table']->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, false);
$componentName = $component['table']->getClassName();
$listeners[$componentName] = $component['table']->getRecordListener();
$identifierMap[$dqlAlias] = array();
$resultPointers[$dqlAlias] = array();
$idTemplate[$dqlAlias] = '';
}
// Process result set
$cache = array();
while ($data = $stmt->fetch(Doctrine::FETCH_ASSOC)) {
$id = $idTemplate; // initialize the id-memory
$nonemptyComponents = array();
$rowData = $this->_gatherRowData($data, $cache, $id, $nonemptyComponents);
//
// hydrate the data of the root entity from the current row
//
$class = $this->_queryComponents[$rootAlias]['table'];
$componentName = $class->getComponentName();
// just event stuff
$event->set('data', $rowData[$rootAlias]);
$listeners[$componentName]->preHydrate($event);
//--
// Check for an existing element
$index = false;
if ($isSimpleQuery || ! isset($identifierMap[$rootAlias][$id[$rootAlias]])) {
$element = $driver->getElement($rowData[$rootAlias], $componentName);
// just event stuff
$event->set('data', $element);
$listeners[$componentName]->postHydrate($event);
//--
// do we need to index by a custom field?
if ($field = $this->_getCustomIndexField($rootAlias)) {
if (isset($result[$field])) {
throw new Doctrine_Hydrator_Exception("Couldn't hydrate. Found non-unique key mapping.");
} else if ( ! isset($element[$field])) {
throw new Doctrine_Hydrator_Exception("Couldn't hydrate. Found a non-existent key.");
}
if ($this->_isResultMixed) {
$result[] = array($element[$field] => $element);
} else {
$result[$element[$field]] = $element;
}
} else {
if ($this->_isResultMixed) {
$result[] = array($element);
} else {
$result[] = $element;
}
}
$identifierMap[$rootAlias][$id[$rootAlias]] = $driver->getLastKey($result);
} else {
$index = $identifierMap[$rootAlias][$id[$rootAlias]];
}
$this->_setLastElement($resultPointers, $result, $index, $rootAlias, false);
unset($rowData[$rootAlias]);
// end hydrate data of the root component for the current row
// Check for scalar values
if (isset($rowData['scalars'])) {
$scalars = $rowData['scalars'];
unset($rowData['scalars']);
}
// $prev[$rootAlias] now points to the last element in $result.
// now hydrate the rest of the data found in the current row, that belongs to other
// (related) components.
foreach ($rowData as $dqlAlias => $data) {
$index = false;
$map = $this->_queryComponents[$dqlAlias];
$componentName = $map['table']->getComponentName();
// just event stuff
$event->set('data', $data);
$listeners[$componentName]->preHydrate($event);
//--
$parent = $map['parent'];
$relation = $map['relation'];
$relationAlias = $relation->getAlias();
$path = $parent . '.' . $dqlAlias;
$key = key(reset($resultPointers));
if ($this->_isResultMixed && $parent == $rootAlias && isset($resultPointers[$parent][$key])) {
$baseElement =& $resultPointers[$parent][$key];
} else if (isset($resultPointers[$parent])) {
$baseElement =& $resultPointers[$parent];
} else {
continue;
}
// check the type of the relation (many or single-valued)
if ( ! $relation->isOneToOne()) {
// x-many relation
$oneToOne = false;
if (isset($nonemptyComponents[$dqlAlias])) {
$driver->initRelated($baseElement, $relationAlias);
if ( ! isset($identifierMap[$path][$id[$parent]][$id[$dqlAlias]])) {
$element = $driver->getElement($data, $componentName);
// just event stuff
$event->set('data', $element);
$listeners[$componentName]->postHydrate($event);
//--
if ($field = $this->_getCustomIndexField($dqlAlias)) {
// TODO: we should check this earlier. Fields used in INDEXBY
// must be unique. Then this can be removed here.
if (isset($baseElement[$relationAlias][$field])) {
throw Doctrine_Hydrator_Exception::nonUniqueKeyMapping();
} else if ( ! isset($element[$field])) {
throw Doctrine_Hydrator_Exception::nonExistantFieldUsedAsIndex($field);
}
$baseElement[$relationAlias][$element[$field]] = $element;
} else {
$baseElement[$relationAlias][] = $element;
}
$identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = $driver->getLastKey($baseElement[$relationAlias]);
} else {
$index = $identifierMap[$path][$id[$parent]][$id[$dqlAlias]];
}
}
} else {
// x-1 relation
$oneToOne = true;
if ( ! isset($nonemptyComponents[$dqlAlias])) {
$baseElement[$relationAlias] = $driver->getNullPointer();
} else if ( ! isset($baseElement[$relationAlias])) {
$baseElement[$relationAlias] = $driver->getElement($data, $componentName);
}
}
$coll =& $baseElement[$relationAlias];
$this->_setLastElement($resultPointers, $coll, $index, $dqlAlias, $oneToOne);
}
// append scalar values
if (isset($scalars)) {
$rowNumber = count($result) - 1;
foreach ($scalars as $name => $value) {
$result[$rowNumber][$name] = $value;
}
}
}
$stmt->closeCursor();
$driver->flush();
// re-enable lazy loading
foreach ($this->_queryComponents as $dqlAlias => $data) {
$data['table']->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, true);
}
//$e = microtime(true);
//echo 'Hydration took: ' . ($e - $s) . ' for '.count($result).' records<br />';
return $result;
}
/**
* _setLastElement
*
* sets the last element of given data array / collection
* as previous element
*
* @param array $prev The array that contains the pointers to the latest element of each class.
* @param array|Collection The object collection.
* @param boolean|integer $index Index of the element in the collection.
* @param string $dqlAlias
* @param boolean $oneToOne Whether it is a single-valued association or not.
* @return void
* @todo Detailed documentation
*/
protected function _setLastElement(&$resultPointers, &$coll, $index, $dqlAlias, $oneToOne)
{
if ($coll === $this->_nullObject) {
return false;
}
if ($index !== false) {
// Link element at $index to previous element for the component
// identified by the DQL alias $alias
$resultPointers[$dqlAlias] =& $coll[$index];
return;
}
if (is_array($coll) && $coll) {
if ($oneToOne) {
$resultPointers[$dqlAlias] =& $coll;
} else {
end($coll);
$resultPointers[$dqlAlias] =& $coll[key($coll)];
}
} else if ($coll instanceof Doctrine_Record) {
$resultPointers[$dqlAlias] = $coll;
} else if (count($coll) > 0) {
$resultPointers[$dqlAlias] = $coll->getLast();
} else if (isset($resultPointers[$dqlAlias])) {
unset($resultPointers[$dqlAlias]);
}
}
/**
* Puts the fields of a data row into a new array, grouped by the component
* they belong to. The column names in the result set are mapped to their
* field names during this procedure.
*
* @return array An array with all the fields (name => value) of the data row,
* grouped by their component (alias).
*/
protected function _gatherRowData(&$data, &$cache, &$id, &$nonemptyComponents)
{
$rowData = array();
foreach ($data as $key => $value) {
// Parse each column name only once. Cache the results.
if ( ! isset($cache[$key])) {
// cache general information like the column name <-> field name mapping
$e = explode('__', $key);
$columnName = strtolower(array_pop($e));
$cache[$key]['dqlAlias'] = $this->_tableAliases[strtolower(implode('__', $e))];
$mapper = $this->_queryComponents[$cache[$key]['dqlAlias']]['mapper'];
$classMetadata = $mapper->getClassMetadata();
// check whether it's an aggregate value or a regular field
if (isset($this->_queryComponents[$cache[$key]['dqlAlias']]['agg'][$columnName])) {
$fieldName = $this->_queryComponents[$cache[$key]['dqlAlias']]['agg'][$columnName];
$cache[$key]['isScalar'] = true;
} else {
$fieldName = $mapper->getFieldName($columnName);
$cache[$key]['isScalar'] = false;
}
$cache[$key]['fieldName'] = $fieldName;
// cache identifier information
if ($classMetadata->isIdentifier($fieldName)) {
$cache[$key]['isIdentifier'] = true;
} else {
$cache[$key]['isIdentifier'] = false;
}
// cache type information
$type = $classMetadata->getTypeOfColumn($columnName);
if ($type == 'integer' || $type == 'string') {
$cache[$key]['isSimpleType'] = true;
} else {
$cache[$key]['type'] = $type;
$cache[$key]['isSimpleType'] = false;
}
}
$mapper = $this->_queryComponents[$cache[$key]['dqlAlias']]['mapper'];
$dqlAlias = $cache[$key]['dqlAlias'];
$fieldName = $cache[$key]['fieldName'];
if ($cache[$key]['isScalar']) {
$rowData['scalars'][$fieldName] = $value;
continue;
}
if ($cache[$key]['isIdentifier']) {
$id[$dqlAlias] .= '|' . $value;
}
if ($cache[$key]['isSimpleType']) {
$rowData[$dqlAlias][$fieldName] = $value;
} else {
$rowData[$dqlAlias][$fieldName] = $mapper->prepareValue(
$fieldName, $value, $cache[$key]['type']);
}
if ( ! isset($nonemptyComponents[$dqlAlias]) && $value !== null) {
$nonemptyComponents[$dqlAlias] = true;
}
}
return $rowData;
}
/**
* Gets the custom field used for indexing for the specified component alias.
*
* @return string The field name of the field used for indexing or NULL
* if the component does not use any custom field indices.
*/
protected function _getCustomIndexField($alias)
{
return isset($this->_queryComponents[$alias]['map']) ? $this->_queryComponents[$alias]['map'] : null;
}
private $_isResultMixed = false;
public function setResultMixed($bool)
{
$this->_isResultMixed = $bool;
}
}
......@@ -90,23 +90,6 @@ class Doctrine_Mapper
}
}
/**
* createQuery
* creates a new Doctrine_Query object and adds the component name
* of this table as the query 'from' part
*
* @param string Optional alias name for component aliasing.
*
* @return Doctrine_Query
*/
public function createQuery($alias = '')
{
if ( ! empty($alias)) {
$alias = ' ' . trim($alias);
}
return Doctrine_Query::create($this->_conn)->from($this->getComponentName() . $alias);
}
/**
* sets the connection for this class
*
......@@ -139,7 +122,7 @@ class Doctrine_Mapper
*/
public function create(array $array = array())
{
$record = new $this->_domainClassName($this, true);
$record = new $this->_domainClassName();
$record->fromArray($array);
return $record;
......@@ -177,79 +160,6 @@ class Doctrine_Mapper
{
return $this->_conn->unitOfWork->detach($entity);
}
/**
* Finds an entity by its primary key.
*
* @param $id database row id
* @param int $hydrationMode Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
* @return mixed Array or Doctrine_Record or false if no result
* @todo Remove. Move to EntityRepository.
*/
public function find($id, $hydrationMode = null)
{
if (is_null($id)) {
return false;
}
$id = is_array($id) ? array_values($id) : array($id);
return $this->createQuery()
->where(implode(' = ? AND ', (array) $this->_classMetadata->getIdentifier()) . ' = ?')
->fetchOne($id, $hydrationMode);
}
/**
* Finds all entities of the mapper's class.
* Use with care.
*
* @param int $hydrationMode Doctrine::HYDRATE_ARRAY or Doctrine::HYDRATE_RECORD
* @return Doctrine_Collection
* @todo Remove. Move to EntityRepository.
*/
public function findAll($hydrationMode = null)
{
return $this->createQuery()->execute(array(), $hydrationMode);
}
/**
* findBySql
* finds records with given SQL where clause
* returns a collection of records
*
* @param string $dql DQL after WHERE clause
* @param array $params query parameters
* @param int $hydrationMode Doctrine::FETCH_ARRAY or Doctrine::FETCH_RECORD
* @return Doctrine_Collection
*
* @todo This actually takes DQL, not SQL, but it requires column names
* instead of field names. This should be fixed to use raw SQL instead.
* @todo Remove. Move to EntityRepository.
*/
public function findBySql($dql, array $params = array(), $hydrationMode = null)
{
return $this->createQuery()->where($dql)->execute($params, $hydrationMode);
}
/**
* findByDql
* finds records with given DQL where clause
* returns a collection of records
*
* @param string $dql DQL after WHERE clause
* @param array $params query parameters
* @param int $hydrationMode Doctrine::FETCH_ARRAY or Doctrine::FETCH_RECORD
* @return Doctrine_Collection
* @todo Remove. Move to EntityRepository.
*/
public function findByDql($dql, array $params = array(), $hydrationMode = null)
{
$query = new Doctrine_Query($this->_conn);
$component = $this->getComponentName();
$dql = 'FROM ' . $component . ' WHERE ' . $dql;
return $query->query($dql, $params, $hydrationMode);
}
/**
* Executes a named query.
......@@ -349,9 +259,7 @@ class Doctrine_Mapper
}
if ($found) {
$record = new $this->_domainClassName($this, true, $data);
$data = array();
return $record;
return new $this->_domainClassName(true, $data);
}
$idHash = $this->_conn->unitOfWork->getIdentifierHash($id);
......@@ -360,12 +268,12 @@ class Doctrine_Mapper
$this->_classMetadata->getRootClassName())) {
$record->hydrate($data);
} else {
$record = new $this->_domainClassName($this, false, $data);
$record = new $this->_domainClassName(false, $data);
$this->_conn->unitOfWork->registerIdentity($record);
}
$data = array();
} else {
$record = new $this->_domainClassName($this, true, $data);
$record = new $this->_domainClassName(true, $data);
}
return $record;
......@@ -545,83 +453,6 @@ class Doctrine_Mapper
return $this->_domainClassName;
}
/**
* findBy
*
* @param string $column
* @param string $value
* @param string $hydrationMode
* @return void
* @todo Remove. Move to EntityRepository.
*/
protected function findBy($fieldName, $value, $hydrationMode = null)
{
return $this->createQuery()->where($fieldName . ' = ?')->execute(array($value), $hydrationMode);
}
/**
* findOneBy
*
* @param string $column
* @param string $value
* @param string $hydrationMode
* @return void
* @todo Remove. Move to EntityRepository.
*/
protected function findOneBy($fieldName, $value, $hydrationMode = null)
{
$results = $this->createQuery()->where($fieldName . ' = ?')->limit(1)->execute(
array($value), $hydrationMode);
return $hydrationMode === Doctrine::HYDRATE_ARRAY ? array_shift($results) : $results->getFirst();
}
/**
* __call
*
* Adds support for magic finders.
* findByColumnName, findByRelationAlias
* findById, findByContactId, etc.
*
* @return void
* @throws Doctrine_Mapper_Exception If the method called is an invalid find* method
* or no find* method at all and therefore an invalid
* method call.
* @todo Remove. Move to EntityRepository.
*/
public function __call($method, $arguments)
{
if (substr($method, 0, 6) == 'findBy') {
$by = substr($method, 6, strlen($method));
$method = 'findBy';
} else if (substr($method, 0, 9) == 'findOneBy') {
$by = substr($method, 9, strlen($method));
$method = 'findOneBy';
} else {
throw new Doctrine_Mapper_Exception("Undefined method '$method'.");
}
if (isset($by)) {
if ( ! isset($arguments[0])) {
throw new Doctrine_Mapper_Exception('You must specify the value to findBy.');
}
$fieldName = Doctrine::tableize($by);
$hydrationMode = isset($arguments[1]) ? $arguments[1]:null;
if ($this->_classMetadata->hasField($fieldName)) {
return $this->$method($fieldName, $arguments[0], $hydrationMode);
} else if ($this->_classMetadata->hasRelation($by)) {
$relation = $this->_classMetadata->getRelation($by);
if ($relation['type'] === Doctrine_Relation::MANY) {
throw new Doctrine_Mapper_Exception('Cannot findBy many relationship.');
}
return $this->$method($relation['local'], $arguments[0], $hydrationMode);
} else {
throw new Doctrine_Mapper_Exception('Cannot find by: ' . $by . '. Invalid field or relationship alias.');
}
}
}
/**
* Saves an entity and all it's related entities.
*
......@@ -795,7 +626,12 @@ class Doctrine_Mapper
$query = 'DELETE FROM ' . $assocTable->getTableName()
. ' WHERE ' . $rel->getForeign() . ' = ?'
. ' AND ' . $rel->getLocal() . ' = ?';
$this->_conn->execute($query, array($r->getIncremented(), $record->getIncremented()));
// FIXME: composite key support
$ids1 = $r->identifier();
$id1 = count($ids1) > 0 ? array_pop($ids1) : null;
$ids2 = $record->identifier();
$id2 = count($ids2) > 0 ? array_pop($ids2) : null;
$this->_conn->execute($query, array($id1, $id2));
}
$assocMapper = $this->_conn->getMapper($assocTable->getComponentName());
......@@ -804,7 +640,6 @@ class Doctrine_Mapper
$assocRecord->set($assocTable->getFieldName($rel->getForeign()), $r);
$assocRecord->set($assocTable->getFieldName($rel->getLocal()), $record);
$assocMapper->save($assocRecord);
//$this->saveSingleRecord($assocRecord);
}
}
}
......@@ -890,19 +725,6 @@ class Doctrine_Mapper
return true;
}
public function hasAttribute($key)
{
switch ($key) {
case Doctrine::ATTR_LOAD_REFERENCES:
case Doctrine::ATTR_QUERY_LIMIT:
case Doctrine::ATTR_COLL_KEY:
case Doctrine::ATTR_VALIDATE:
return true;
default:
return false;
}
}
public function executeQuery(Doctrine_Query $query)
{
......
......@@ -111,7 +111,8 @@ class Doctrine_Mapper_JoinedStrategy extends Doctrine_Mapper_Strategy
if ( ! $value->exists()) {
$value->save();
}
$record->set($field, $value->getIncremented());
$idValues = $value->identifier();
$record->set($field, $idValues[0]);
}
}
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Query_Abstract');
/**
* Doctrine_Query
* A Doctrine_Query object represents a DQL query. It is used to query databases for
......
......@@ -117,12 +117,6 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* @var Doctrine_ClassMetadata
*/
protected $_class;
/**
*
* @var Doctrine_Mapper
*/
protected $_mapper;
/**
*
......@@ -186,6 +180,13 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* @var array
*/
protected $_references = array();
/**
* The EntityManager that is responsible for the persistence of the entity.
*
* @var Doctrine_EntityManager
*/
protected $_em;
/**
* The object identifier of the object. Each object has a unique identifier during runtime.
......@@ -206,23 +207,13 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* open connections
* @throws Doctrine_Record_Exception if the cleanData operation fails somehow
*/
public function __construct($mapper = null, $isNewEntry = false, array $data = array())
public function __construct($isNewEntry = true, array $data = array())
{
if (isset($mapper) && $mapper instanceof Doctrine_Mapper) {
$class = get_class($this);
$this->_mapper = $mapper;
$this->_class = $this->_mapper->getClassMetadata();
$exists = ! $isNewEntry;
} else {
$this->_mapper = Doctrine_Manager::getInstance()->getMapper(get_class($this));
$this->_class = $this->_mapper->getClassMetadata();
$exists = false;
}
$this->_entityName = $this->_mapper->getMappedClassName();
$this->_oid = self::$_index;
$this->_entityName = get_class($this);
$this->_em = Doctrine_Manager::getInstance()->getCurrentConnection();
$this->_class = $this->_em->getClassMetadata($this->_entityName);
self::$_index++;
$this->_oid = self::$_index++;
// get the data array
$this->_data = $data;
......@@ -232,9 +223,9 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
$this->_values = $this->cleanData($this->_data);
$this->_extractIdentifier($exists);
$this->_extractIdentifier( ! $isNewEntry);
if ( ! $exists) {
if ($isNewEntry) {
if ($count > count($this->_values)) {
$this->_state = Doctrine_Record::STATE_TDIRTY;
} else {
......@@ -252,7 +243,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
}
self::$_useAutoAccessorOverride = false; // @todo read from attribute the first time
$this->_mapper->manage($this);
$this->_em->manage($this);
$this->construct();
}
......@@ -510,13 +501,13 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
$tmp = $data;
$data = array();
$fieldNames = $this->_mapper->getFieldNames();
$fieldNames = $this->_em->getMapper($this->_entityName)->getFieldNames();
foreach ($fieldNames as $fieldName) {
if (isset($tmp[$fieldName])) {
$data[$fieldName] = $tmp[$fieldName];
} else if (array_key_exists($fieldName, $tmp)) {
$data[$fieldName] = Doctrine_Null::$INSTANCE;
} else if (!isset($this->_data[$fieldName])) {
} else if ( ! isset($this->_data[$fieldName])) {
$data[$fieldName] = Doctrine_Null::$INSTANCE;
}
unset($tmp[$fieldName]);
......@@ -554,7 +545,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
case Doctrine::IDENTIFIER_AUTOINC:
case Doctrine::IDENTIFIER_SEQUENCE:
case Doctrine::IDENTIFIER_NATURAL:
$name = (array)$this->_class->getIdentifier();
$name = $this->_class->getIdentifier();
$name = $name[0];
if ($exists) {
if (isset($this->_data[$name]) && $this->_data[$name] !== Doctrine_Null::$INSTANCE) {
......@@ -563,7 +554,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
}
break;
case Doctrine::IDENTIFIER_COMPOSITE:
$names = (array)$this->_class->getIdentifier();
$names = $this->_class->getIdentifier();
foreach ($names as $name) {
if ($this->_data[$name] === Doctrine_Null::$INSTANCE) {
......@@ -575,6 +566,14 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
break;
}
}
/**
* INTERNAL:
*/
final public function setIdentifier(array $identifier)
{
$this->_id = $identifier;
}
/**
* Serializes the entity.
......@@ -596,6 +595,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
unset($vars['_errorStack']);
unset($vars['_filter']);
unset($vars['_node']);
unset($vars['_em']);
//$name = (array)$this->_table->getIdentifier();
$this->_data = array_merge($this->_data, $this->_id);
......@@ -642,13 +642,13 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
$this->preUnserialize($event);
$manager = Doctrine_Manager::getInstance();
$manager = Doctrine_Manager::getInstance();
$connection = $manager->getConnectionForComponent(get_class($this));
$this->_oid = self::$_index;
self::$_index++;
$this->_mapper = $connection->getMapper(get_class($this));
$this->_em = $connection;
$array = unserialize($serialized);
......@@ -656,7 +656,8 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
$this->$k = $v;
}
$this->_class = $this->_mapper->getTable();
$this->_entityName = get_class($this);
$this->_class = $this->_em->getClassMetadata($this->_entityName);
foreach ($this->_data as $k => $v) {
switch ($this->_class->getTypeOf($k)) {
......@@ -674,7 +675,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
}
}
$this->_mapper->manage($this);
$this->_em->manage($this);
$this->cleanData($this->_data);
$this->_extractIdentifier($this->exists());
......@@ -749,7 +750,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
$id = array_values($id);
if ($deep) {
$query = $this->_mapper->createQuery();
$query = $this->_class->getConnection()->createQuery()->from($this->_entityName);
foreach (array_keys($this->_references) as $name) {
$query->leftJoin(get_class($this) . '.' . $name);
}
......@@ -758,7 +759,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
$record = $query->fetchOne($id);
} else {
// Use FETCH_ARRAY to avoid clearing object relations
$record = $this->_mapper->find($id, Doctrine::HYDRATE_ARRAY);
$record = $this->getRepository()->find($this->identifier(), Doctrine::HYDRATE_ARRAY);
if ($record) {
$this->hydrate($record);
}
......@@ -929,8 +930,8 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
}
return $this->_references[$fieldName];
} catch (Doctrine_Relation_Exception $e) {
echo $e->getTraceAsString();
echo "<br/><br/>";
//echo $e->getTraceAsString();
//echo "<br/><br/>";
foreach ($this->_class->getFilters() as $filter) {
if (($value = $filter->filterGet($this, $fieldName, $value)) !== null) {
return $value;
......@@ -979,7 +980,9 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
if (isset($this->_data[$fieldName])) {
if ($value instanceof Doctrine_Record) {
$type = $this->_class->getTypeOf($fieldName);
$id = $value->getIncremented();
// FIXME: composite key support
$ids = $value->identifier();
$id = count($ids) > 0 ? array_pop($ids) : null;
if ($id !== null && $type !== 'object') {
$value = $id;
}
......@@ -998,6 +1001,13 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
$this->_data[$fieldName] = $value;
$this->_modified[] = $fieldName;
/* We can't do this currently because there are tests that change
* the primary key of already persisted entities (ugh). */
if ($this->isTransient() && $this->_class->isIdentifier($fieldName)) {
$this->_id[$fieldName] = $value;
}
switch ($this->_state) {
case Doctrine_Record::STATE_CLEAN:
$this->_state = Doctrine_Record::STATE_DIRTY;
......@@ -1011,8 +1021,8 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
try {
$this->_coreSetRelated($fieldName, $value);
} catch (Doctrine_Relation_Exception $e) {
echo $e->getTraceAsString();
echo "<br/><br/>";
//echo $e->getTraceAsString();
//echo "<br/><br/>";
foreach ($this->_class->getFilters() as $filter) {
if (($value = $filter->filterSet($this, $fieldName, $value)) !== null) {
return $value;
......@@ -1131,7 +1141,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
public function save(Doctrine_Connection $conn = null)
{
// TODO: Forward to EntityManager. There: registerNew() OR registerDirty() on UnitOfWork.
$this->_mapper->save($this, $conn);
$this->_em->save($this, $conn);
}
/**
......@@ -1175,7 +1185,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
public function replace(Doctrine_Connection $conn = null)
{
if ($conn === null) {
$conn = $this->_mapper->getConnection();
$conn = $this->_em;
}
return $conn->replace($this->_class, $this->getPrepared(), $this->_id);
......@@ -1249,7 +1259,10 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
break;
default:
if ($this->_data[$field] instanceof Doctrine_Record) {
$this->_data[$field] = $this->_data[$field]->getIncremented();
// FIXME: composite key support
$ids = $this->_data[$field]->identifier();
$id = count($ids) > 0 ? array_pop($ids) : null;
$this->_data[$field] = $id;
}
/** TODO:
if ($this->_data[$v] === null) {
......@@ -1313,8 +1326,12 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
if ($this->_class->getIdentifierType() == Doctrine::IDENTIFIER_AUTOINC) {
$idFieldNames = (array)$this->_class->getIdentifier();
$id = $idFieldNames[0];
$a[$id] = $this->getIncremented();
$idFieldName = $idFieldNames[0];
$ids = $this->identifier();
$id = count($ids) > 0 ? array_pop($ids) : null;
$a[$idFieldName] = $id;
}
if ($deep) {
......@@ -1460,17 +1477,41 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* Checks whether the entity already has a persistent state.
*
* @return boolean TRUE if the object is new, FALSE otherwise.
* @deprecated Use isTransient()
*/
public function isNew()
{
return $this->_state == self::STATE_TCLEAN || $this->_state == self::STATE_TDIRTY;
}
/**
* Checks whether the entity already has a persistent state.
*
* @return boolean TRUE if the object is new, FALSE otherwise.
*/
public function isTransient()
{
return $this->_state == self::STATE_TCLEAN || $this->_state == self::STATE_TDIRTY;
}
/**
* Checks whether the entity has been modified since it was last synchronized
* with the database.
*
* @return boolean TRUE if the object has been modified, FALSE otherwise.
*/
public function isDirty()
{
return ($this->_state === Doctrine_Record::STATE_DIRTY ||
$this->_state === Doctrine_Record::STATE_TDIRTY);
}
/**
* Checks whether the entity has been modified since it was last synchronized
* with the database.
*
* @return boolean TRUE if the object has been modified, FALSE otherwise.
* @deprecated Use isDirty()
*/
public function isModified()
{
......@@ -1496,6 +1537,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
/**
* getIterator
* @return Doctrine_Record_Iterator a Doctrine_Record_Iterator that iterates through the data
* @todo Really needed/useful?
*/
public function getIterator()
{
......@@ -1513,7 +1555,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
public function delete(Doctrine_Connection $conn = null)
{
// TODO: Forward to EntityManager. There: registerRemoved() on UnitOfWork
return $this->_mapper->delete($this, $conn);
return $this->_em->remove($this, $conn);
}
/**
......@@ -1532,7 +1574,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
unset($data[$id]);
}
$ret = $this->_mapper->create($data);
$ret = $this->_em->createEntity($this->_entityName, $data);
$modified = array();
foreach ($data as $key => $val) {
......@@ -1581,7 +1623,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
$this->_data[$fieldName] = $value;
}
} else {
$idFieldNames = (array)$this->_class->getIdentifier();
$idFieldNames = $this->_class->getIdentifier();
$name = $idFieldNames[0];
$this->_id[$name] = $id;
$this->_data[$name] = $id;
......@@ -1601,23 +1643,6 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
return $this->_id;
}
/**
* returns the value of autoincremented primary key of this object (if any)
*
* @return integer
* @todo Better name? Not sure this is the right place here.
* @todo Plays against full composite key support..
*/
final public function getIncremented()
{
$id = current($this->_id);
if ($id === false) {
return null;
}
return $id;
}
/**
* hasRefence
* @param string $name
......@@ -1964,15 +1989,15 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
{
return $this->_class;
}
/**
* Returns the mapper of the entity.
*
* @return Doctrine_Mapper
*/
public function getMapper()
public function getEntityManager()
{
return $this->_em;
}
public function getRepository()
{
return $this->_mapper;
return $this->_class->getConnection()->getRepository($this->_entityName);
}
/**
......@@ -2002,8 +2027,8 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
public function free($deep = false)
{
if ($this->_state != self::STATE_LOCKED) {
$this->_mapper->detach($this);
$this->_mapper->removeRecord($this);
$this->_em->detach($this);
$this->_em->removeRecord($this);
$this->_data = array();
$this->_id = array();
......
......@@ -93,18 +93,15 @@ class Doctrine_Relation_Association extends Doctrine_Relation
* @return Doctrine_Record|Doctrine_Collection
*/
public function fetchRelatedFor(Doctrine_Record $record)
{
$id = $record->getIncremented();
//var_dump($id);
//echo "<br /><br />";
{
// FIXME: composite key support
$ids = $record->identifier();
$id = count($ids) > 0 ? array_pop($ids) : null;
if (empty($id) || ! $this->_foreignMapper->getClassMetadata()->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) {
//echo "here" . $this->_foreignMapper->getAttribute(Doctrine::ATTR_LOAD_REFERENCES);
$coll = new Doctrine_Collection($this->getForeignComponentName());
} else {
$query = Doctrine_Query::create()->parseQuery($this->getRelationDql(1));
//echo $query->getDql() . "<br />";
//echo $query->getSql() . "<br />";
//echo "<br /><br />";
$coll = Doctrine_Query::create()->query($this->getRelationDql(1), array($id));
}
$coll->setReference($record, $this);
......
......@@ -18,7 +18,7 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
Doctrine::autoload('Doctrine_Relation_Association');
/**
* Doctrine_Relation_Association_Self
*
......@@ -75,8 +75,10 @@ class Doctrine_Relation_Association_Self extends Doctrine_Relation_Association
}
public function fetchRelatedFor(Doctrine_Record $record)
{
$id = $record->getIncremented();
{
// FIXME: composite key support
$ids = $record->identifier();
$id = count($ids) > 0 ? array_pop($ids) : null;
$q = new Doctrine_RawSql();
......
......@@ -74,35 +74,11 @@ class Doctrine_Relation_Nest extends Doctrine_Relation_Association
return $dql;
}
/**
public function fetchRelatedFor(Doctrine_Record $record)
{
$id = $record->getIncremented();
if (empty($id) || ! $this->definition['table']->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) {
return new Doctrine_Collection($this->getTable());
} else {
$q = new Doctrine_Query();
$c = $this->getTable()->getComponentName();
$a = substr($c, 0, 1);
$c2 = $this->getAssociationTable()->getComponentName();
$a2 = substr($c2, 0, 1);
$q->from($c)
->innerJoin($c . '.' . $c2)
$sub = 'SELECT ' . $this->getForeign()
. ' FROM ' . $c2
. ' WHERE ' . $this->getLocal()
. ' = ?';
}
}
*/
public function fetchRelatedFor(Doctrine_Record $record)
{
$id = $record->getIncremented();
// FIXME: composite key support
$ids = $record->identifier();
$id = count($ids) > 0 ? array_pop($ids) : null;
if (empty($id) || ! $this->_foreignMapper->getClassMetadata()->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) {
......
......@@ -147,12 +147,6 @@ class Doctrine_Relation_Parser
$this->getRelations();
return $this->getRelation($alias, false);
} else {
/*try {
throw new Exception();
} catch (Exception $e) {
//echo "" . "<br />";
///echo $e->getTraceAsString() . "<br /><br /><br />";
}*/
throw new Doctrine_Relation_Exception("Unknown relation '$alias'.");
}
}
......
......@@ -84,7 +84,8 @@ class Doctrine_Validator
if ($value === Doctrine_Null::$INSTANCE) {
$value = null;
} else if ($value instanceof Doctrine_Record) {
$value = $value->getIncremented();
$ids = $value->identifier();
$value = count($ids) > 0 ? array_pop($ids) : null;
}
$dataType = $classMetadata->getTypeOf($fieldName);
......
......@@ -9,11 +9,22 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
parent::setUp();
}
/** The data of the hydration mode dataProvider */
protected static $hydrationModeProviderData = array(
array('hydrationMode' => Doctrine::HYDRATE_RECORD),
array('hydrationMode' => Doctrine::HYDRATE_ARRAY)
);
/** Getter for the hydration mode dataProvider */
public static function hydrationModeProvider()
{
return self::$hydrationModeProviderData;
}
/**
* Fakes the DQL query: select u.id, u.name from CmsUser u
* Select u.id, u.name from CmsUser u
*
*/
public function testBasic()
public function testBasicHydration()
{
// Faked query components
$queryComponents = array(
......@@ -72,4 +83,285 @@ class Orm_Hydration_BasicHydrationTest extends Doctrine_OrmTestCase
$this->assertEquals('jwage', $objectResult[1]->name);
}
/**
* select u.id, u.status, p.phonenumber, upper(u.name) nameUpper from User u
* join u.phonenumbers p
* =
* select u.id, u.status, p.phonenumber, upper(u.name) as u__0 from USERS u
* INNER JOIN PHONENUMBERS p ON u.id = p.user_id
*
* @dataProvider hydrationModeProvider
*/
public function testNewHydrationMixedQueryFetchJoin($hydrationMode)
{
// Faked query components
$queryComponents = array(
'u' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsUser'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsUser'),
'parent' => null,
'relation' => null,
'map' => null,
'agg' => array('0' => 'nameUpper')
),
'p' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->sharedFixture['connection']->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'map' => null
)
);
// Faked table alias map
$tableAliasMap = array(
'u' => 'u',
'p' => 'p'
);
// Faked result set
$resultSet = array(
//row1
array(
'u__id' => '1',
'u__status' => 'developer',
'u__0' => 'ROMANB',
'p__phonenumber' => '42',
),
array(
'u__id' => '1',
'u__status' => 'developer',
'u__0' => 'ROMANB',
'p__phonenumber' => '43',
),
array(
'u__id' => '2',
'u__status' => 'developer',
'u__0' => 'JWAGE',
'p__phonenumber' => '91'
)
);
$stmt = new Doctrine_HydratorMockStatement($resultSet);
$hydrator = new Doctrine_HydratorNew();
$hydrator->setQueryComponents($queryComponents);
$hydrator->setResultMixed(true);
$result = $hydrator->hydrateResultSet($stmt, $tableAliasMap, $hydrationMode);
//var_dump($result);
$this->assertEquals(2, count($result));
$this->assertTrue(is_array($result));
$this->assertTrue(is_array($result[0]));
$this->assertTrue(is_array($result[1]));
$this->assertEquals(3, count($result[0][0]));
// first user => 2 phonenumbers
$this->assertEquals(2, count($result[0][0]['phonenumbers']));
$this->assertEquals('ROMANB', $result[0]['nameUpper']);
// second user => 1 phonenumber
$this->assertEquals(1, count($result[1][0]['phonenumbers']));
$this->assertEquals('JWAGE', $result[1]['nameUpper']);
$this->assertEquals(42, $result[0][0]['phonenumbers'][0]['phonenumber']);
$this->assertEquals(43, $result[0][0]['phonenumbers'][1]['phonenumber']);
$this->assertEquals(91, $result[1][0]['phonenumbers'][0]['phonenumber']);
if ($hydrationMode == Doctrine::HYDRATE_RECORD) {
$this->assertTrue($result[0][0] instanceof Doctrine_Record);
$this->assertTrue($result[0][0]['phonenumbers'] instanceof Doctrine_Collection);
$this->assertTrue($result[0][0]['phonenumbers'][0] instanceof Doctrine_Record);
$this->assertTrue($result[0][0]['phonenumbers'][1] instanceof Doctrine_Record);
$this->assertTrue($result[1][0] instanceof Doctrine_Record);
$this->assertTrue($result[1][0]['phonenumbers'] instanceof Doctrine_Collection);
}
}
/**
* select u.id, u.status, count(p.phonenumber) numPhones from User u
* join u.phonenumbers p group by u.status, u.id
* =
* select u.id, u.status, count(p.phonenumber) as p__0 from USERS u
* INNER JOIN PHONENUMBERS p ON u.id = p.user_id group by u.id, u.status
*
* @dataProvider hydrationModeProvider
*/
public function testNewHydrationBasicsMixedQueryNormalJoin($hydrationMode)
{
// Faked query components
$queryComponents = array(
'u' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsUser'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsUser'),
'parent' => null,
'relation' => null,
'map' => null
),
'p' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->sharedFixture['connection']->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'map' => null,
'agg' => array('0' => 'numPhones')
)
);
// Faked table alias map
$tableAliasMap = array(
'u' => 'u',
'p' => 'p'
);
// Faked result set
$resultSet = array(
//row1
array(
'u__id' => '1',
'u__status' => 'developer',
'p__0' => '2',
),
array(
'u__id' => '2',
'u__status' => 'developer',
'p__0' => '1',
)
);
$stmt = new Doctrine_HydratorMockStatement($resultSet);
$hydrator = new Doctrine_HydratorNew();
$hydrator->setQueryComponents($queryComponents);
$hydrator->setResultMixed(true);
$result = $hydrator->hydrateResultSet($stmt, $tableAliasMap, $hydrationMode);
//var_dump($result);
$this->assertEquals(2, count($result));
$this->assertTrue(is_array($result));
$this->assertTrue(is_array($result[0]));
$this->assertTrue(is_array($result[1]));
// first user => 2 phonenumbers
$this->assertEquals(2, $result[0]['numPhones']);
// second user => 1 phonenumber
$this->assertEquals(1, $result[1]['numPhones']);
if ($hydrationMode == Doctrine::HYDRATE_RECORD) {
$this->assertTrue($result[0][0] instanceof Doctrine_Record);
$this->assertTrue($result[1][0] instanceof Doctrine_Record);
}
}
/**
* select u.id, u.status, upper(u.name) nameUpper from User u index by u.id
* join u.phonenumbers p indexby p.phonenumber
* =
* select u.id, u.status, upper(u.name) as p__0 from USERS u
* INNER JOIN PHONENUMBERS p ON u.id = p.user_id
*
* @dataProvider hydrationModeProvider
*/
public function testNewHydrationMixedQueryFetchJoinCustomIndex($hydrationMode)
{
// Faked query components
$queryComponents = array(
'u' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsUser'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsUser'),
'parent' => null,
'relation' => null,
'agg' => array('0' => 'nameUpper'),
'map' => 'id'
),
'p' => array(
'table' => $this->sharedFixture['connection']->getClassMetadata('CmsPhonenumber'),
'mapper' => $this->sharedFixture['connection']->getMapper('CmsPhonenumber'),
'parent' => 'u',
'relation' => $this->sharedFixture['connection']->getClassMetadata('CmsUser')->getRelation('phonenumbers'),
'map' => 'phonenumber'
)
);
// Faked table alias map
$tableAliasMap = array(
'u' => 'u',
'p' => 'p'
);
// Faked result set
$resultSet = array(
//row1
array(
'u__id' => '1',
'u__status' => 'developer',
'u__0' => 'ROMANB',
'p__phonenumber' => '42',
),
array(
'u__id' => '1',
'u__status' => 'developer',
'u__0' => 'ROMANB',
'p__phonenumber' => '43',
),
array(
'u__id' => '2',
'u__status' => 'developer',
'u__0' => 'JWAGE',
'p__phonenumber' => '91'
)
);
$stmt = new Doctrine_HydratorMockStatement($resultSet);
$hydrator = new Doctrine_HydratorNew();
$hydrator->setQueryComponents($queryComponents);
// give the hydrator an artificial hint
$hydrator->setResultMixed(true);
$result = $hydrator->hydrateResultSet($stmt, $tableAliasMap, $hydrationMode);
if ($hydrationMode == Doctrine::HYDRATE_ARRAY) {
//var_dump($result);
}
$this->assertEquals(2, count($result));
$this->assertTrue(is_array($result));
$this->assertTrue(is_array($result[0]));
$this->assertTrue(is_array($result[1]));
// first user => 2 phonenumbers. notice the custom indexing by user id
$this->assertEquals(2, count($result[0]['1']['phonenumbers']));
// second user => 1 phonenumber. notice the custom indexing by user id
$this->assertEquals(1, count($result[1]['2']['phonenumbers']));
// test the custom indexing of the phonenumbers
$this->assertTrue(isset($result[0]['1']['phonenumbers']['42']));
$this->assertTrue(isset($result[0]['1']['phonenumbers']['43']));
$this->assertTrue(isset($result[1]['2']['phonenumbers']['91']));
// test the scalar values
$this->assertEquals('ROMANB', $result[0]['nameUpper']);
$this->assertEquals('JWAGE', $result[1]['nameUpper']);
if ($hydrationMode == Doctrine::HYDRATE_RECORD) {
$this->assertTrue($result[0]['1'] instanceof Doctrine_Record);
$this->assertTrue($result[1]['2'] instanceof Doctrine_Record);
$this->assertTrue($result[0]['1']['phonenumbers'] instanceof Doctrine_Collection);
$this->assertEquals(2, count($result[0]['1']['phonenumbers']));
}
}
}
\ No newline at end of file
......@@ -18,6 +18,8 @@ class Orm_UnitOfWorkTestCase extends Doctrine_OrmTestCase
public function testRegisterNew()
{
$this->_user->username = 'romanb';
$this->_user->id = 1;
$this->_unitOfWork->registerNew($this->_user);
$this->assertFalse($this->_unitOfWork->contains($this->_user));
$this->assertTrue($this->_unitOfWork->isRegisteredNew($this->_user));
......@@ -35,7 +37,15 @@ class Orm_UnitOfWorkTestCase extends Doctrine_OrmTestCase
$this->assertTrue($this->_unitOfWork->isRegisteredDirty($this->_user));
$this->assertFalse($this->_unitOfWork->isRegisteredNew($this->_user));
$this->assertFalse($this->_unitOfWork->isRegisteredRemoved($this->_user));
}
public function testRegisterRemovedOnTransientEntityIsIgnored()
{
$this->_user->username = 'romanb';
$this->_user->id = 1;
$this->assertFalse($this->_unitOfWork->isRegisteredRemoved($this->_user));
$this->_unitOfWork->registerRemoved($this->_user);
$this->assertFalse($this->_unitOfWork->isRegisteredRemoved($this->_user));
}
/*public function testSavedEntityHasIdentityAndIsManaged()
......
<?php
class CmsPhonenumber extends Doctrine_Record
{
public static function initMetadata($class)
{
$class->mapColumn('user_id', 'integer', 4);
$class->mapColumn('phonenumber', 'string', 50, array('primary' => true));
}
}
......@@ -6,5 +6,8 @@ class CmsUser extends Doctrine_Record
$class->mapColumn('id', 'integer', 4, array('primary' => true, 'autoincrement' => true));
$class->mapColumn('username', 'string', 255);
$class->mapColumn('name', 'string', 255);
$class->hasMany('CmsPhonenumber as phonenumbers', array(
'local' => 'id', 'foreign' => 'user_id'));
}
}
......@@ -77,7 +77,7 @@ class Doctrine_Access_TestCase extends Doctrine_UnitTestCase
$user->save();
$user = $this->connection->getMapper('User')->find($user->identifier());
$user = $this->connection->getRepository('User')->find($user->identifier());
$this->assertEqual($user->name, 'Jack');
$user['name'] = 'Jack';
......@@ -97,7 +97,7 @@ class Doctrine_Access_TestCase extends Doctrine_UnitTestCase
$user->save();
$user = $this->connection->getMapper('User')->find($user->identifier());
$user = $this->connection->getRepository('User')->find($user->identifier());
$this->assertEqual($user->name, 'Jack');
$user->name = 'Jack';
......@@ -115,7 +115,7 @@ class Doctrine_Access_TestCase extends Doctrine_UnitTestCase
$user->save();
$user = $this->connection->getMapper('User')->find($user->identifier());
$user = $this->connection->getRepository('User')->find($user->identifier());
$this->assertEqual($user->get('name'), 'Jack');
......
......@@ -168,7 +168,7 @@ class Doctrine_ClassTableInheritance_TestCase extends Doctrine_UnitTestCase
$profiler = new Doctrine_Connection_Profiler();
$this->conn->addListener($profiler);
$record = $this->conn->getMapper('CTITest')->find(1);
$record = $this->conn->getRepository('CTITest')->find(1);
$record->age = 11;
$record->name = 'Jack';
......@@ -193,7 +193,7 @@ class Doctrine_ClassTableInheritance_TestCase extends Doctrine_UnitTestCase
{
$this->conn->clear();
$record = $this->conn->getMapper('CTITest')->find(1);
$record = $this->conn->getRepository('CTITest')->find(1);
$this->assertEqual($record->id, 1);
$this->assertEqual($record->name, 'Jack');
......@@ -209,7 +209,7 @@ class Doctrine_ClassTableInheritance_TestCase extends Doctrine_UnitTestCase
$profiler = new Doctrine_Connection_Profiler();
$this->conn->addListener($profiler);
$record = $this->conn->getMapper('CTITest')->find(1);
$record = $this->conn->getRepository('CTITest')->find(1);
$record->delete();
......
......@@ -53,7 +53,7 @@ class Doctrine_CustomPrimaryKey_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($c->identifier(), array('uid' => 1));
$this->connection->clear();
$c = $this->connection->getMapper('CustomPK')->find(1);
$c = $this->connection->getRepository('CustomPK')->find(1);
$this->assertEqual($c->identifier(), array('uid' => 1));
}
......
......@@ -60,7 +60,7 @@ class Doctrine_DataType_Boolean_TestCase extends Doctrine_UnitTestCase {
$this->connection->clear();
$test = $test->getMapper()->find($test->id);
$test = $test->getRepository()->find($test->id);
$this->assertIdentical($test->is_working, true);
}
public function testNormalQuerying() {
......
......@@ -172,7 +172,7 @@ class Doctrine_DataType_Enum_TestCase extends Doctrine_UnitTestCase
public function testFailingRefresh()
{
$enum = $this->connection->getMapper('EnumTest')->find(1);
$enum = $this->connection->getRepository('EnumTest')->find(1);
$this->conn->exec('DELETE FROM enum_test WHERE id = 1');
......
......@@ -197,7 +197,7 @@ class Doctrine_UnitTestCase extends UnitTestCase
//echo "exporting : " . var_dump($this->tables);
//echo "<br /><br />";
$this->conn->export->exportClasses($this->tables);
$this->objTable = $this->connection->getMapper('User');
$this->objTable = $this->connection->getRepository('User');
}
public function prepareData()
......
......@@ -152,7 +152,7 @@ class Doctrine_Inheritance_Joined_TestCase extends Doctrine_UnitTestCase
public function testDqlQueryJoinsTransparentlyAcrossParents()
{
$this->_createManager();
$this->conn->getMapper('CTI_Manager')->clear();
$this->conn->clear('CTI_Manager');
$query = $this->conn->createQuery();
$query->parseQuery("SELECT m.* FROM CTI_Manager m");
......@@ -167,8 +167,8 @@ class Doctrine_Inheritance_Joined_TestCase extends Doctrine_UnitTestCase
public function testQueryingBaseClassOuterJoinsSubClassesAndReturnsSubclassInstances()
{
$this->_createManager();
$this->conn->getMapper('CTI_Manager')->clear();
$this->conn->getMapper('CTI_User')->clear();
$this->conn->clear('CTI_Manager');
$this->conn->clear('CTI_User');
$query = $this->conn->createQuery();
$query->parseQuery("SELECT u.* FROM CTI_User u");
......
......@@ -41,9 +41,9 @@ class Doctrine_Query_JoinCondition2_TestCase extends Doctrine_UnitTestCase
public function prepareData()
{
$this->conn->getMapper('User')->clear();
$this->conn->getMapper('Group')->clear();
$this->conn->getMapper('Groupuser')->clear();
$this->conn->clear('User');
$this->conn->clear('Group');
$this->conn->clear('Groupuser');
$zYne = new User();
$zYne->name = 'zYne';
......
......@@ -43,7 +43,7 @@ class Doctrine_Query_MultiJoin_TestCase extends Doctrine_UnitTestCase
$query = new Doctrine_Query($this->connection);
$user = $this->connection->getMapper('User')->find(4);
$user = $this->connection->getRepository('User')->find(4);
$album = $this->connection->create('Album');
......@@ -73,7 +73,7 @@ class Doctrine_Query_MultiJoin_TestCase extends Doctrine_UnitTestCase
$this->assertEqual(count($user->Album[1]->Song), 4);
$user = $this->connection->getMapper('User')->find(5);
$user = $this->connection->getRepository('User')->find(5);
$user->Album[0]->name = 'Clayman';
$user->Album[1]->name = 'Colony';
......@@ -122,7 +122,7 @@ class Doctrine_Query_MultiJoin_TestCase extends Doctrine_UnitTestCase
public function testInitializeMoreData()
{
$user = $this->connection->getMapper('User')->find(4);
$user = $this->connection->getRepository('User')->find(4);
$user->Book[0]->name = 'The Prince';
$user->Book[0]->Author[0]->name = 'Niccolo Machiavelli';
$user->Book[0]->Author[1]->name = 'Someone';
......@@ -133,7 +133,7 @@ class Doctrine_Query_MultiJoin_TestCase extends Doctrine_UnitTestCase
$user->save();
$user = $this->connection->getMapper('User')->find(5);
$user = $this->connection->getRepository('User')->find(5);
$user->Book[0]->name = 'Zadig';
$user->Book[0]->Author[0]->name = 'Voltaire';
$user->Book[0]->Author[1]->name = 'Someone';
......
......@@ -60,7 +60,7 @@ class Doctrine_Query_ReferenceModel_TestCase extends Doctrine_UnitTestCase {
$this->connection->unitOfWork->saveAll();
$this->connection->clear();
$category = $category->getMapper()->find($category->id);
$category = $category->getRepository()->find($category->id);
$this->assertEqual($category->name, 'Root');
$this->assertEqual($category->Subcategory[0]->name, 'Sub 1');
......
......@@ -62,6 +62,6 @@ class Doctrine_Query_Registry_TestCase extends Doctrine_UnitTestCase
$user = new User();
$user->getMapper()->executeNamedQuery('User.all');
$user->getEntityManager()->executeNamedQuery('User.all');
}
}
......@@ -89,7 +89,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($account->amount, 2000);
$user = $user->getMapper()->find($user->id);
$user = $user->getRepository()->find($user->id);
$this->assertEqual($user->state(), Doctrine_Record::STATE_CLEAN);
......@@ -148,7 +148,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($gzip->gzip, "compressed");
$this->connection->clear();
$gzip = $gzip->getMapper()->find($gzip->id);
$gzip = $gzip->getRepository()->find($gzip->id);
$this->assertEqual($gzip->gzip, "compressed");
$gzip->gzip = "compressed 2";
......@@ -209,7 +209,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
$this->assertTrue(array_key_exists('id', $a));
$this->assertTrue(is_numeric($a['id']));
$this->connection->clear();
$user = $user->getMapper()->find($user->id);
$user = $user->getRepository()->find($user->id);
$a = $user->toArray();
......@@ -231,7 +231,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
public function testUpdatingWithNullValue()
{
$user = $this->connection->getMapper('User')->find(5);
$user = $this->connection->getRepository('User')->find(5);
$user->name = null;
$this->assertEqual($user->name, null);
......@@ -241,7 +241,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
$this->connection->clear();
$user = $this->connection->getMapper('User')->find(5);
$user = $this->connection->getRepository('User')->find(5);
$this->assertEqual($user->name, null);
......@@ -249,7 +249,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
public function testSerialize()
{
$user = $this->connection->getMapper("User")->find(4);
$user = $this->connection->getRepository("User")->find(4);
$str = serialize($user);
$user2 = unserialize($str);
......@@ -279,7 +279,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($record->entity2, 4);
$this->assertEqual($record->entity1, 3);
$this->assertEqual($record->state(), Doctrine_Record::STATE_TDIRTY);
$this->assertEqual($record->identifier(), array("entity1" => null, "entity2" => null));
$this->assertEqual($record->identifier(), array("entity1" => 3, "entity2" => 4));
$record->save();
$this->assertEqual($record->state(), Doctrine_Record::STATE_CLEAN);
......@@ -287,7 +287,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($record->entity1, 3);
$this->assertEqual($record->identifier(), array("entity1" => 3, "entity2" => 4));
$record = $record->getMapper()->find($record->identifier());
$record = $record->getRepository()->find($record->identifier());
$this->assertEqual($record->state(), Doctrine_Record::STATE_CLEAN);
$this->assertEqual($record->entity2, 4);
$this->assertEqual($record->entity1, 3);
......@@ -300,20 +300,21 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($record->entity2, 5);
$this->assertEqual($record->entity1, 2);
$this->assertEqual($record->identifier(), array("entity1" => 3, "entity2" => 4));
$record->save();
$this->assertEqual($record->state(), Doctrine_Record::STATE_CLEAN);
$this->assertEqual($record->entity2, 5);
$this->assertEqual($record->entity1, 2);
$this->assertEqual($record->identifier(), array("entity1" => 2, "entity2" => 5));
$record = $record->getMapper()->find($record->identifier());
$record = $record->getRepository()->find($record->identifier());
$this->assertEqual($record->state(), Doctrine_Record::STATE_CLEAN);
$this->assertEqual($record->entity2, 5);
$this->assertEqual($record->entity1, 2);
$this->assertEqual($record->identifier(), array("entity1" => 2, "entity2" => 5));
$record->refresh();
$this->assertEqual($record->state(), Doctrine_Record::STATE_CLEAN);
$this->assertEqual($record->entity2, 5);
$this->assertEqual($record->entity1, 2);
......@@ -368,7 +369,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
$this->connection->unitOfWork->saveAll();
$task = $task->getMapper()->find($task->identifier());
$task = $task->getRepository()->find($task->identifier());
$this->assertEqual($task->name, "Task 1");
$this->assertEqual($task->ResourceAlias[0]->name, "Resource 1");
......@@ -386,7 +387,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($user->updated, null);
$user->save();
$id = $user->identifier();
$user = $user->getMapper()->find($id);
$user = $user->getRepository()->find($id);
$this->assertEqual($user->name, "Jack Daniels");
$this->assertEqual($user->created, null);
$this->assertEqual($user->updated, null);
......@@ -439,12 +440,12 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
$elements = $this->connection->query("FROM Element");
$this->assertEqual($elements->count(), 5);
$e = $e->getMapper()->find(1);
$e = $e->getRepository()->find(1);
$this->assertEqual($e->name,"parent");
$this->assertEqual($e->Child[0]->name,"child 1");
$c = $e->getMapper()->find(2);
$c = $e->getRepository()->find(2);
$this->assertEqual($c->name, "child 1");
$this->assertEqual($e->Child[0]->parent_id, 1);
......@@ -553,7 +554,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
public function testUpdate()
{
$user = $this->connection->getMapper("User")->find(4);
$user = $this->connection->getRepository("User")->find(4);
$user->set("name","Jack Daniels",true);
......@@ -566,7 +567,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
public function testCopy()
{
$user = $this->connection->getMapper("User")->find(4);
$user = $this->connection->getRepository("User")->find(4);
$new = $user->copy();
$this->assertTrue($new instanceof Doctrine_Record);
......@@ -583,7 +584,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
public function testCopyAndModify()
{
$user = $this->connection->getMapper("User")->find(4);
$user = $this->connection->getRepository("User")->find(4);
$new = $user->copy();
$this->assertTrue($new instanceof Doctrine_Record);
......@@ -604,7 +605,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
public function testReferences()
{
$user = $this->connection->getMapper('User')->find(5);
$user = $this->connection->getRepository('User')->find(5);
$this->assertTrue($user->Phonenumber instanceof Doctrine_Collection);
$this->assertEqual($user->Phonenumber->count(), 3);
......@@ -615,7 +616,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($user->Phonenumber->count(), 0);
$user->save();
$user->getMapper()->clear();
$user->getEntityManager()->clear('User');
$user = $this->objTable->find(5);
......@@ -736,15 +737,11 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
public function testSaveAssociations()
{
$userMapper = $this->connection->getMapper('User');
$userMapper = $this->connection->getRepository('User');
$user = $userMapper->find(5);
$this->assertTrue($userMapper === $user->getMapper());
$this->assertTrue($userMapper->getTable() === $user->getMapper()->getTable());
$this->assertTrue($userMapper->getTable() === $this->conn->getClassMetadata('User'));
$this->assertTrue($this->conn === $userMapper->getConnection());
$userTable = $userMapper->getTable();
$userTable = $this->connection->getClassMetadata('User');
/*echo get_class($rel1) . "<br />";
echo get_class($rel2) . "<br />";
echo get_class($userTable->getRelation('Group'));
......@@ -753,7 +750,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
echo "local:" . $rel2->getLocal() . "---foreign:" . $rel2->getForeign() . "<br />";
echo "........<br />";*/
$gf = $this->connection->getMapper("Group");
$gf = $this->connection->getRepository("Group");
//echo "start";
$this->assertTrue($user->Group instanceof Doctrine_Collection);
//echo "end";
......@@ -865,14 +862,14 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
public function testCount()
{
$user = $this->connection->getMapper("User")->find(4);
$user = $this->connection->getRepository("User")->find(4);
$this->assertTrue(is_integer($user->count()));
}
public function testGetReference()
{
$user = $this->connection->getMapper("User")->find(4);
$user = $this->connection->getRepository("User")->find(4);
$this->assertTrue($user->Email instanceof Doctrine_Record);
$this->assertTrue($user->Phonenumber instanceof Doctrine_Collection);
......@@ -882,13 +879,13 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
}
public function testGetIterator()
{
$user = $this->connection->getMapper("User")->find(4);
$user = $this->connection->getRepository("User")->find(4);
$this->assertTrue($user->getIterator() instanceof ArrayIterator);
}
public function testRefreshRelated()
{
$user = $this->connection->getMapper("User")->find(4);
$user = $this->connection->getRepository("User")->find(4);
$user->Address[0]->address = "Address #1";
$user->Address[1]->address = "Address #2";
$user->save();
......@@ -904,7 +901,7 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
public function testRefreshDeep()
{
$user = $this->connection->getMapper("User")->find(4);
$user = $this->connection->getRepository("User")->find(4);
$user->Address[0]->address = "Address #1";
$user->Address[1]->address = "Address #2";
$user->save();
......
......@@ -117,7 +117,7 @@ class Doctrine_Relation_Nest_TestCase extends Doctrine_UnitTestCase
$this->connection->clear();
$e = $e->getMapper()->find($e->id);
$e = $e->getRepository()->find($e->id);
$count = count($this->conn);
......
......@@ -83,7 +83,7 @@ class Doctrine_Table_TestCase extends Doctrine_UnitTestCase
$this->connection->clear();
$t = $this->connection->getMapper('FieldNameTest')->find(1);
$t = $this->connection->getRepository('FieldNameTest')->find(1);
$this->assertEqual($t->someColumn, 'abc');
$this->assertEqual($t->someEnum, 'php');
......
......@@ -37,7 +37,7 @@ class Doctrine_Ticket_626D_TestCase extends Doctrine_UnitTestCase
$student1 = $this->newStudent('T626D_Student1', '07090002', 'First Student');
try {
$student = $this->conn->getMapper('T626D_Student1')->find('07090002');
$student = $this->conn->getRepository('T626D_Student1')->find('07090002');
$this->pass();
} catch (Exception $e) {
$this->fail($e->__toString());
......
......@@ -140,7 +140,7 @@ class Doctrine_Validator_TestCase extends Doctrine_UnitTestCase
public function testValidate()
{
$this->manager->setAttribute(Doctrine::ATTR_VALIDATE, Doctrine::VALIDATE_ALL);
$user = $this->connection->getMapper('User')->find(4);
$user = $this->connection->getRepository('User')->find(4);
$set = array('password' => 'this is an example of too long password',
'loginname' => 'this is an example of too long loginname',
......@@ -200,7 +200,7 @@ class Doctrine_Validator_TestCase extends Doctrine_UnitTestCase
public function testSave()
{
$this->manager->setAttribute(Doctrine::ATTR_VALIDATE, Doctrine::VALIDATE_ALL);
$user = $this->connection->getMapper("User")->find(4);
$user = $this->connection->getRepository("User")->find(4);
try {
$user->name = "this is an example of too long name not very good example but an example nevertheless";
$user->save();
......@@ -260,7 +260,7 @@ class Doctrine_Validator_TestCase extends Doctrine_UnitTestCase
}
// Tests validateOnUpdate()
$user = $this->connection->getMapper("User")->find(4);
$user = $this->connection->getRepository("User")->find(4);
try {
$user->name = "The Saint"; // Set correct name
$user->password = "Top Secret"; // Set correct password
......@@ -337,7 +337,7 @@ class Doctrine_Validator_TestCase extends Doctrine_UnitTestCase
$r->identifier = '1234';
$r->save();
$r = $this->connection->getMapper('ValidatorTest_Person')->findAll()->getFirst();
$r = $this->connection->getRepository('ValidatorTest_Person')->findAll()->getFirst();
$r->identifier = 1234;
try {
$r->save();
......
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