Commit 71338c3d authored by zYne's avatar zYne

drafting the new relation model, still a lot of work

parent b3b1f617
...@@ -257,10 +257,11 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module ...@@ -257,10 +257,11 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
} }
} }
/** /**
* update
* updates the given record * updates the given record
* *
* @param Doctrine_Record $record * @param Doctrine_Record $record record to be updated
* @return boolean * @return boolean whether or not the update was successful
*/ */
public function update(Doctrine_Record $record) public function update(Doctrine_Record $record)
{ {
...@@ -301,7 +302,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module ...@@ -301,7 +302,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
. ' WHERE ' . implode(' = ? AND ', $record->getTable()->getPrimaryKeys()) . ' WHERE ' . implode(' = ? AND ', $record->getTable()->getPrimaryKeys())
. ' = ?'; . ' = ?';
$stmt = $this->conn->getDBH()->prepare($sql); $stmt = $this->conn->getDbh()->prepare($sql);
$stmt->execute($params); $stmt->execute($params);
$record->assignIdentifier(true); $record->assignIdentifier(true);
......
...@@ -205,7 +205,11 @@ class Doctrine_Db_Statement implements Doctrine_Adapter_Statement_Interface ...@@ -205,7 +205,11 @@ class Doctrine_Db_Statement implements Doctrine_Adapter_Statement_Interface
$skip = $this->adapter->getListener()->onPreExecute($event); $skip = $this->adapter->getListener()->onPreExecute($event);
if ( ! $skip) { if ( ! $skip) {
$this->stmt->execute($params); if (isset($params[0]) && is_array($params[0])) {
print_r($params);
throw new Exception();
}
$this->stmt->execute((array) $params);
$this->adapter->incrementQueryCount(); $this->adapter->incrementQueryCount();
} }
......
...@@ -66,6 +66,13 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable ...@@ -66,6 +66,13 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
* @var array $_enumParams an array containing the keys of the parameters that should be enumerated * @var array $_enumParams an array containing the keys of the parameters that should be enumerated
*/ */
protected $_enumParams = array(); protected $_enumParams = array();
/**
* @var array $_options an array of options
*/
protected $_options = array(
'fetchMode' => Doctrine::FETCH_RECORD,
'cacheMode' => null,
);
/** /**
* @var array $_dqlParts an array containing all DQL query parts * @var array $_dqlParts an array containing all DQL query parts
*/ */
...@@ -483,7 +490,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable ...@@ -483,7 +490,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
$q = 'UPDATE '; $q = 'UPDATE ';
break; break;
case self::SELECT: case self::SELECT:
$distinct = ($this->isDistinct()) ? 'DISTINCT ' : ''; $distinct = ($this->parts['distinct']) ? 'DISTINCT ' : '';
$q = 'SELECT ' . $distinct . implode(', ', $this->parts['select']) . ' FROM '; $q = 'SELECT ' . $distinct . implode(', ', $this->parts['select']) . ' FROM ';
break; break;
...@@ -565,11 +572,6 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable ...@@ -565,11 +572,6 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
// build the basic query // build the basic query
$str = '';
if ($this->isDistinct()) {
$str = 'DISTINCT ';
}
$q = $this->getQueryBase(); $q = $this->getQueryBase();
$q .= $this->buildFromPart(); $q .= $this->buildFromPart();
......
...@@ -901,8 +901,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -901,8 +901,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
} }
foreach ($saveLater as $fk) { foreach ($saveLater as $fk) {
$table = $fk->getTable(); $alias = $fk->getAlias();
$alias = $this->_table->getAlias($table->getComponentName());
if (isset($this->_references[$alias])) { if (isset($this->_references[$alias])) {
$obj = $this->_references[$alias]; $obj = $this->_references[$alias];
...@@ -1011,8 +1010,9 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -1011,8 +1010,9 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
$a[$v] = $this->_table->enumIndex($v,$this->_data[$v]); $a[$v] = $this->_table->enumIndex($v,$this->_data[$v]);
break; break;
default: default:
if ($this->_data[$v] instanceof Doctrine_Record) if ($this->_data[$v] instanceof Doctrine_Record) {
$this->_data[$v] = $this->_data[$v]->getIncremented(); $this->_data[$v] = $this->_data[$v]->getIncremented();
}
$a[$v] = $this->_data[$v]; $a[$v] = $this->_data[$v];
} }
...@@ -1273,48 +1273,61 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -1273,48 +1273,61 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
} }
} }
/** /**
* ownsOne
* binds One-to-One composite relation * binds One-to-One composite relation
* *
* @param string $objTableName * @param string $componentName the name of the related component
* @param string $fkField * @param string $options relation options
* @return void * @see Doctrine_Relation::_$definition
* @return Doctrine_Record this object
*/ */
final public function ownsOne($componentName, $foreignKey, $options = null) public function ownsOne()
{ {
$this->_table->bind($componentName, $foreignKey, Doctrine_Relation::ONE_COMPOSITE, $options); $this->_table->bind(func_get_args(), Doctrine_Relation::ONE_COMPOSITE);
return $this;
} }
/** /**
* binds One-to-Many composite relation * ownsMany
* binds One-to-Many / Many-to-Many composite relation
* *
* @param string $objTableName * @param string $componentName the name of the related component
* @param string $fkField * @param string $options relation options
* @return void * @see Doctrine_Relation::_$definition
* @return Doctrine_Record this object
*/ */
final public function ownsMany($componentName, $foreignKey, $options = null) public function ownsMany()
{ {
$this->_table->bind($componentName, $foreignKey, Doctrine_Relation::MANY_COMPOSITE, $options); $this->_table->bind(func_get_args(), Doctrine_Relation::MANY_COMPOSITE);
return $this;
} }
/** /**
* hasOne
* binds One-to-One aggregate relation * binds One-to-One aggregate relation
* *
* @param string $objTableName * @param string $componentName the name of the related component
* @param string $fkField * @param string $options relation options
* @return void * @see Doctrine_Relation::_$definition
* @return Doctrine_Record this object
*/ */
final public function hasOne($componentName, $foreignKey, $options = null) public function hasOne()
{ {
$this->_table->bind($componentName, $foreignKey, Doctrine_Relation::ONE_AGGREGATE, $options); $this->_table->bind(func_get_args(), Doctrine_Relation::ONE_AGGREGATE);
return $this;
} }
/** /**
* binds One-to-Many aggregate relation * hasMany
* binds One-to-Many / Many-to-Many aggregate relation
* *
* @param string $objTableName * @param string $componentName the name of the related component
* @param string $fkField * @param string $options relation options
* @return void * @see Doctrine_Relation::_$definition
* @return Doctrine_Record this object
*/ */
final public function hasMany($componentName, $foreignKey, $options = null) public function hasMany()
{ {
$this->_table->bind($componentName, $foreignKey, Doctrine_Relation::MANY_AGGREGATE, $options); $this->_table->bind(func_get_args(), Doctrine_Relation::MANY_AGGREGATE);
return $this;
} }
/** /**
* hasColumn * hasColumn
......
...@@ -62,7 +62,7 @@ abstract class Doctrine_Relation ...@@ -62,7 +62,7 @@ abstract class Doctrine_Relation
'class' => true, 'class' => true,
'type' => true, 'type' => true,
'name' => false, 'name' => false,
'assocTable' => false, 'refTable' => false,
'onDelete' => false, 'onDelete' => false,
'onUpdate' => false, 'onUpdate' => false,
'deferred' => false, 'deferred' => false,
...@@ -80,7 +80,7 @@ abstract class Doctrine_Relation ...@@ -80,7 +80,7 @@ abstract class Doctrine_Relation
* *
* table the foreign table object * table the foreign table object
* *
* assocTable the association table object (if any) * refTable the reference table object (if any)
* *
* onDelete referential delete action * onDelete referential delete action
* *
......
...@@ -40,11 +40,11 @@ class Doctrine_Relation_Association extends Doctrine_Relation ...@@ -40,11 +40,11 @@ class Doctrine_Relation_Association extends Doctrine_Relation
*/ */
public function getAssociationFactory() public function getAssociationFactory()
{ {
return $this->definition['assocTable']; return $this->definition['refTable'];
} }
public function getAssociationTable() public function getAssociationTable()
{ {
return $this->definition['assocTable']; return $this->definition['refTable'];
} }
/** /**
* getRelationDql * getRelationDql
...@@ -54,7 +54,7 @@ class Doctrine_Relation_Association extends Doctrine_Relation ...@@ -54,7 +54,7 @@ class Doctrine_Relation_Association extends Doctrine_Relation
*/ */
public function getRelationDql($count, $context = 'record') public function getRelationDql($count, $context = 'record')
{ {
$component = $this->definition['assocTable']->getComponentName(); $component = $this->definition['refTable']->getComponentName();
switch ($context) { switch ($context) {
case "record": case "record":
$sub = 'SQL:SELECT ' . $this->definition['foreign']. $sub = 'SQL:SELECT ' . $this->definition['foreign'].
......
...@@ -43,17 +43,17 @@ class Doctrine_Relation_Association_Self extends Doctrine_Relation_Association ...@@ -43,17 +43,17 @@ class Doctrine_Relation_Association_Self extends Doctrine_Relation_Association
switch ($context) { switch ($context) {
case 'record': case 'record':
$sub = 'SELECT '.$this->definition['foreign'] $sub = 'SELECT '.$this->definition['foreign']
. ' FROM '.$this->definition['assocTable']->getTableName() . ' FROM '.$this->definition['refTable']->getTableName()
. ' WHERE '.$this->definition['local'] . ' WHERE '.$this->definition['local']
. ' = ?'; . ' = ?';
$sub2 = 'SELECT '.$this->definition['local'] $sub2 = 'SELECT '.$this->definition['local']
. ' FROM '.$this->definition['assocTable']->getTableName() . ' FROM '.$this->definition['refTable']->getTableName()
. ' WHERE '.$this->definition['foreign'] . ' WHERE '.$this->definition['foreign']
. ' = ?'; . ' = ?';
$dql = 'FROM ' . $this->definition['table']->getComponentName() $dql = 'FROM ' . $this->definition['table']->getComponentName()
. '.' . $this->definition['assocTable']->getComponentName() . '.' . $this->definition['refTable']->getComponentName()
. ' WHERE ' . $this->definition['table']->getComponentName() . ' WHERE ' . $this->definition['table']->getComponentName()
. '.' . $this->definition['table']->getIdentifier() . '.' . $this->definition['table']->getIdentifier()
. ' IN (' . $sub . ')' . ' IN (' . $sub . ')'
...@@ -63,9 +63,9 @@ class Doctrine_Relation_Association_Self extends Doctrine_Relation_Association ...@@ -63,9 +63,9 @@ class Doctrine_Relation_Association_Self extends Doctrine_Relation_Association
break; break;
case 'collection': case 'collection':
$sub = substr(str_repeat('?, ', $count),0,-2); $sub = substr(str_repeat('?, ', $count),0,-2);
$dql = 'FROM '.$this->definition['assocTable']->getComponentName() $dql = 'FROM '.$this->definition['refTable']->getComponentName()
. '.' . $this->definition['table']->getComponentName() . '.' . $this->definition['table']->getComponentName()
. ' WHERE '.$this->definition['assocTable']->getComponentName() . ' WHERE '.$this->definition['refTable']->getComponentName()
. '.' . $this->definition['local'] . ' IN (' . $sub . ')'; . '.' . $this->definition['local'] . ' IN (' . $sub . ')';
}; };
......
...@@ -45,7 +45,7 @@ class Doctrine_Relation_ForeignKey extends Doctrine_Relation ...@@ -45,7 +45,7 @@ class Doctrine_Relation_ForeignKey extends Doctrine_Relation
{ {
$id = array(); $id = array();
foreach ((array) $this->definition['local'] as $local) { foreach ((array) $this->definition['local'] as $local) {
$id = $record->get($local); $id[] = $record->get($local);
} }
if ($this->isOneToOne()) { if ($this->isOneToOne()) {
if (empty($id)) { if (empty($id)) {
...@@ -54,7 +54,7 @@ class Doctrine_Relation_ForeignKey extends Doctrine_Relation ...@@ -54,7 +54,7 @@ class Doctrine_Relation_ForeignKey extends Doctrine_Relation
$dql = 'FROM ' . $this->getTable()->getComponentName() $dql = 'FROM ' . $this->getTable()->getComponentName()
. ' WHERE ' . $this->getCondition(); . ' WHERE ' . $this->getCondition();
$coll = $this->getTable()->getConnection()->query($dql, array($id)); $coll = $this->getTable()->getConnection()->query($dql, $id);
$related = $coll[0]; $related = $coll[0];
} }
...@@ -66,7 +66,7 @@ class Doctrine_Relation_ForeignKey extends Doctrine_Relation ...@@ -66,7 +66,7 @@ class Doctrine_Relation_ForeignKey extends Doctrine_Relation
$related = new Doctrine_Collection($this->getTable()); $related = new Doctrine_Collection($this->getTable());
} else { } else {
$query = $this->getRelationDql(1); $query = $this->getRelationDql(1);
$related = $this->getTable()->getConnection()->query($query, array($id)); $related = $this->getTable()->getConnection()->query($query, $id);
} }
$related->setReference($record, $this); $related->setReference($record, $this);
} }
......
...@@ -126,6 +126,8 @@ class Doctrine_Relation_Parser ...@@ -126,6 +126,8 @@ class Doctrine_Relation_Parser
if (isset($this->_pending[$alias])) { if (isset($this->_pending[$alias])) {
$def = $this->_pending[$alias]; $def = $this->_pending[$alias];
// check if reference class name exists
// if it does we are dealing with association relation
if (isset($def['refClass'])) { if (isset($def['refClass'])) {
$def = $this->completeAssocDefinition($def); $def = $this->completeAssocDefinition($def);
$localClasses = array_merge($this->_table->getOption('parents'), array($this->_table->getComponentName())); $localClasses = array_merge($this->_table->getOption('parents'), array($this->_table->getComponentName()));
...@@ -134,7 +136,10 @@ class Doctrine_Relation_Parser ...@@ -134,7 +136,10 @@ class Doctrine_Relation_Parser
! isset($this->_relations[$def['refClass']])) { ! isset($this->_relations[$def['refClass']])) {
$def['refTable']->getRelationParser()->bind($this->_table->getComponentName(), $def['refTable']->getRelationParser()->bind($this->_table->getComponentName(),
array('type' => Doctrine_Relation::ONE)); array('type' => Doctrine_Relation::ONE,
'local' => $def['local'],
'foreign' => $this->_table->getIdentifier(),
));
$this->bind($def['refClass'], array('type' => Doctrine_Relation::MANY, $this->bind($def['refClass'], array('type' => Doctrine_Relation::MANY,
'foreign' => $def['local'])); 'foreign' => $def['local']));
...@@ -145,15 +150,20 @@ class Doctrine_Relation_Parser ...@@ -145,15 +150,20 @@ class Doctrine_Relation_Parser
$rel = new Doctrine_Relation_Association($def); $rel = new Doctrine_Relation_Association($def);
} }
} else { } else {
// simple foreign key relation
$def = $this->completeDefinition($def); $def = $this->completeDefinition($def);
if ( ! isset($def['foreign'])) {
Doctrine::dump($def); if (isset($def['localKey'])) {
} $rel = new Doctrine_Relation_LocalKey($def);
} else {
$rel = new Doctrine_Relation_ForeignKey($def); $rel = new Doctrine_Relation_ForeignKey($def);
} }
}
if (isset($rel)) { if (isset($rel)) {
unset($this->_pending[$name]); // unset pending relation
unset($this->_pending[$alias]);
$this->_relations[$alias] = $rel;
return $rel; return $rel;
} }
} }
...@@ -288,6 +298,7 @@ class Doctrine_Relation_Parser ...@@ -288,6 +298,7 @@ class Doctrine_Relation_Parser
// the foreign field is likely to be the // the foreign field is likely to be the
// identifier of the foreign class // identifier of the foreign class
$def['foreign'] = $def['table']->getIdentifier(); $def['foreign'] = $def['table']->getIdentifier();
$def['localKey'] = true;
} }
} }
} else { } else {
...@@ -295,6 +306,7 @@ class Doctrine_Relation_Parser ...@@ -295,6 +306,7 @@ class Doctrine_Relation_Parser
// local key not set, but foreign key is set // local key not set, but foreign key is set
// try to guess the local key // try to guess the local key
if ($def['foreign'] === $def['table']->getIdentifier()) { if ($def['foreign'] === $def['table']->getIdentifier()) {
$def['localKey'] = true;
$def['local'] = $this->guessColumns($foreignClasses, $this->_table); $def['local'] = $this->guessColumns($foreignClasses, $this->_table);
} else { } else {
$def['local'] = $this->_table->getIdentifier(); $def['local'] = $this->_table->getIdentifier();
...@@ -316,6 +328,7 @@ class Doctrine_Relation_Parser ...@@ -316,6 +328,7 @@ class Doctrine_Relation_Parser
if ($table2->hasColumn($column)) { if ($table2->hasColumn($column)) {
$def['foreign'] = $column; $def['foreign'] = $column;
$def['local'] = $table->getIdentifier(); $def['local'] = $table->getIdentifier();
$def['localKey'] = true;
return $def; return $def;
} }
} }
...@@ -334,7 +347,7 @@ class Doctrine_Relation_Parser ...@@ -334,7 +347,7 @@ class Doctrine_Relation_Parser
return $def; return $def;
} }
} }
} Doctrine::dump($this->_table->getComponentName()); }
Doctrine::dump($def); Doctrine::dump($def);
throw new Doctrine_Relation_Parser_Exception("Couldn't complete relation definition."); throw new Doctrine_Relation_Parser_Exception("Couldn't complete relation definition.");
} }
......
...@@ -37,10 +37,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable ...@@ -37,10 +37,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
* @var array $data temporary data which is then loaded into Doctrine_Record::$data * @var array $data temporary data which is then loaded into Doctrine_Record::$data
*/ */
private $data = array(); private $data = array();
/**
* @var array $relations an array containing all the Doctrine_Relation objects for this table
*/
private $relations = array();
/** /**
* @var array $primaryKeys an array containing all primary key column names * @var array $primaryKeys an array containing all primary key column names
*/ */
...@@ -96,14 +92,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable ...@@ -96,14 +92,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
* keys as column aliases and values as column names * keys as column aliases and values as column names
*/ */
protected $columnAliases = array(); protected $columnAliases = array();
/**
* @var array $bound bound relations
*/
private $bound = array();
/**
* @var array $boundAliases bound relation aliases
*/
private $boundAliases = array();
/** /**
* @var integer $columnCount cached column count, Doctrine_Record uses this column count in when * @var integer $columnCount cached column count, Doctrine_Record uses this column count in when
* determining its state * determining its state
...@@ -161,6 +149,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable ...@@ -161,6 +149,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
'treeImpl' => null, 'treeImpl' => null,
'treeOptions' => null, 'treeOptions' => null,
'indexes' => array(), 'indexes' => array(),
'parents' => array(),
); );
/** /**
* @var Doctrine_Tree $tree tree object associated with this table * @var Doctrine_Tree $tree tree object associated with this table
...@@ -207,6 +196,9 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable ...@@ -207,6 +196,9 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
// reverse names // reverse names
$names = array_reverse($names); $names = array_reverse($names);
// save parents
array_pop($names);
$this->options['parents'] = $names;
// create database table // create database table
if (method_exists($record, 'setTableDefinition')) { if (method_exists($record, 'setTableDefinition')) {
...@@ -303,11 +295,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable ...@@ -303,11 +295,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
if ($this->isTree()) { if ($this->isTree()) {
$this->getTree()->setUp(); $this->getTree()->setUp();
} }
// save parents
array_pop($names);
$this->options['parents'] = $names;
$this->repository = new Doctrine_Table_Repository($this); $this->repository = new Doctrine_Table_Repository($this);
} }
/** /**
...@@ -472,6 +459,61 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable ...@@ -472,6 +459,61 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
return false; return false;
} }
public function bind($args, $type)
{
$options = array();
$options['type'] = $type;
// the following is needed for backwards compatibility
if (is_string($args[1])) {
if ( ! isset($args[2])) {
$args[2] = array();
} elseif (is_string($args[2])) {
$args[2] = (array) $args[2];
}
$classes = array_merge($this->options['parents'], array($this->getComponentName()));
$e = explode('.', $args[1]);
if (in_array($e[0], $classes)) {
$options['local'] = $e[1];
} else {
$e2 = explode(' as ', $args[0]);
if ($e[0] !== $e2[0] && ( ! isset($e2[1]) || $e[0] !== $e2[1])) {
$options['refClass'] = $e[0];
}
$options['foreign'] = $e[1];
}
$options = array_merge($args[2], $options);
$this->_parser->bind($args[0], $options);
} else {
$options = array_merge($args[1], $options);
$this->_parser->bind($args[0], $options);
}
}
/**
* getRelation
*
* @param string $alias relation alias
*/
public function getRelation($alias, $recursive = true)
{
return $this->_parser->getRelation($alias, $recursive);
}
/**
* getRelations
* returns an array containing all relation objects
*
* @return array an array of Doctrine_Relation objects
*/
public function getRelations()
{
return $this->_parser->getRelations();
}
/** /**
* createQuery * createQuery
* creates a new Doctrine_Query object and adds the component name * creates a new Doctrine_Query object and adds the component name
...@@ -683,148 +725,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable ...@@ -683,148 +725,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
{ {
return in_array($key,$this->primaryKeys); return in_array($key,$this->primaryKeys);
} }
/**
* returns all bound relations
*
* @return array
*/
public function getBounds()
{
return $this->bound;
}
/**
* returns a bound relation array
*
* @param string $name
* @return array
*/
public function getBound($name)
{
if ( ! isset($this->bound[$name])) {
throw new Doctrine_Table_Exception('Unknown bound ' . $name);
}
return $this->bound[$name];
}
/**
* returns a bound relation array
*
* @param string $name
* @return array
*/
public function getBoundForName($name, $component)
{
foreach ($this->bound as $k => $bound) {
$e = explode('.', $bound['field']);
if ($bound['class'] == $name && $e[0] == $component) {
return $this->bound[$k];
}
}
throw new Doctrine_Table_Exception('Unknown bound ' . $name);
}
/**
* returns the alias for given component name
*
* @param string $name
* @return string
*/
public function getAlias($name)
{
if (isset($this->boundAliases[$name])) {
return $this->boundAliases[$name];
}
return $name;
}
/**
* returns component name for given alias
*
* @param string $alias
* @return string
*/
public function getAliasName($alias)
{
if ($name = array_search($alias, $this->boundAliases)) {
return $name;
}
return $alias;
}
/**
* unbinds all relations
*
* @return void
*/
public function unbindAll()
{
$this->bound = array();
$this->relations = array();
$this->boundAliases = array();
}
/**
* unbinds a relation
* returns true on success, false on failure
*
* @param $name
* @return boolean
*/
public function unbind($name)
{
if ( ! isset($this->bound[$name])) {
return false;
}
unset($this->bound[$name]);
if (isset($this->relations[$name])) {
unset($this->relations[$name]);
}
if (isset($this->boundAliases[$name])) {
unset($this->boundAliases[$name]);
}
return true;
}
/**
* binds a relation
*
* @param string $name
* @param string $field
* @return void
*/
public function bind($name, $field, $type, $options = null)
{
if (isset($this->relations[$name])) {
unset($this->relations[$name]);
}
$lower = strtolower($name);
if (isset($this->columns[$lower])) {
throw new Doctrine_Table_Exception("Couldn't bind relation. Column with name " . $lower . ' already exists!');
}
$e = explode(' as ', $name);
$name = $e[0];
if (isset($e[1])) {
$alias = $e[1];
$this->boundAliases[$name] = $alias;
} else {
$alias = $name;
}
$this->bound[$alias] = array('field' => $field,
'type' => $type,
'class' => $name,
'alias' => $alias);
if ($options !== null) {
$opt = array();
if (is_string($options)) {
$opt['local'] = $options;
} else {
$opt = (array) $options;
}
$this->bound[$alias] = array_merge($this->bound[$alias], $opt);
}
}
/** /**
* @return Doctrine_Connection * @return Doctrine_Connection
*/ */
...@@ -832,212 +732,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable ...@@ -832,212 +732,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
{ {
return $this->conn; return $this->conn;
} }
/**
* hasRelatedComponent
* @return boolean
*/
public function hasRelatedComponent($name, $component)
{
return (strpos($this->bound[$name]['field'], $component . '.') !== false);
}
/**
* @param string $name component name of which a foreign key object is bound
* @return boolean
*/
final public function hasRelation($name)
{
if (isset($this->bound[$name])) {
return true;
}
foreach ($this->bound as $k=>$v) {
if ($this->hasRelatedComponent($k, $name)) {
return true;
}
}
return false;
}
/**
* getRelation
*
* @param string $name component name of which a foreign key object is bound
* @return Doctrine_Relation
*/
public function getRelation($name, $recursive = true)
{
if (isset($this->relations[$name])) {
return $this->relations[$name];
}
if ( ! $this->conn->hasTable($this->options['name'])) {
$allowExport = true;
} else {
$allowExport = false;
}
if (isset($this->bound[$name])) {
$definition = $this->bound[$name];
list($component, $tmp) = explode('.', $definition['field']);
if ( ! isset($definition['foreign'])) {
$definition['foreign'] = $tmp;
}
unset($definition['field']);
$definition['table'] = $this->conn->getTable($definition['class'], $allowExport);
$definition['constraint'] = false;
if ($component == $this->options['name'] || in_array($component, $this->options['parents'])) {
// ONE-TO-ONE
if ($definition['type'] == Doctrine_Relation::ONE_COMPOSITE ||
$definition['type'] == Doctrine_Relation::ONE_AGGREGATE) {
// tree structure parent relation found
if ( ! isset($definition['local'])) {
$definition['local'] = $definition['foreign'];
$definition['foreign'] = $definition['table']->getIdentifier();
}
$relation = new Doctrine_Relation_LocalKey($definition);
} else {
// tree structure children relation found
if ( ! isset($definition['local'])) {
$tmp = $definition['table']->getIdentifier();
$definition['local'] = $tmp;
}
//$definition['foreign'] = $tmp;
$definition['constraint'] = true;
$relation = new Doctrine_Relation_ForeignKey($definition);
}
} elseif ($component == $definition['class'] ||
($component == $definition['alias'])) { // && ($name == $this->options['name'] || in_array($name,$this->parents))
if ( ! isset($defintion['local'])) {
$definition['local'] = $this->identifier;
}
$definition['constraint'] = true;
// ONE-TO-MANY or ONE-TO-ONE
$relation = new Doctrine_Relation_ForeignKey($definition);
} else {
// MANY-TO-MANY
// only aggregate relations allowed
if ($definition['type'] != Doctrine_Relation::MANY_AGGREGATE) {
throw new Doctrine_Table_Exception("Only aggregate relations are allowed for many-to-many relations");
}
$classes = array_merge($this->options['parents'], array($this->options['name']));
foreach (array_reverse($classes) as $class) {
try {
$bound = $definition['table']->getBoundForName($class, $component);
break;
} catch(Doctrine_Table_Exception $exc) { }
}
if ( ! isset($bound)) {
throw new Doctrine_Table_Exception("Couldn't map many-to-many relation for "
. $this->options['name'] . " and $name. Components use different join tables.");
}
if ( ! isset($definition['local'])) {
$definition['local'] = $this->identifier;
}
$e2 = explode('.', $bound['field']);
$fields = explode('-', $e2[1]);
if ($e2[0] != $component) {
throw new Doctrine_Table_Exception($e2[0] . ' doesn\'t match ' . $component);
}
$associationTable = $this->conn->getTable($e2[0], $allowExport);
if (count($fields) > 1) {
// SELF-REFERENCING THROUGH JOIN TABLE
$def['table'] = $associationTable;
$def['local'] = $this->identifier;
$def['foreign'] = $fields[0];
$def['alias'] = $e2[0];
$def['class'] = $e2[0];
$def['type'] = Doctrine_Relation::MANY_COMPOSITE;
$this->relations[$e2[0]] = new Doctrine_Relation_ForeignKey($def);
$definition['assocTable'] = $associationTable;
$definition['local'] = $fields[0];
$definition['foreign'] = $fields[1];
$relation = new Doctrine_Relation_Association_Self($definition);
} else {
if($definition['table'] === $this) {
} else {
// auto initialize a new one-to-one relationships for association table
$associationTable->bind($this->getComponentName(),
$associationTable->getComponentName(). '.' . $e2[1],
Doctrine_Relation::ONE_AGGREGATE
);
$associationTable->bind($definition['table']->getComponentName(),
$associationTable->getComponentName(). '.' . $definition['foreign'],
Doctrine_Relation::ONE_AGGREGATE
);
// NORMAL MANY-TO-MANY RELATIONSHIP
$def['table'] = $associationTable;
$def['foreign'] = $e2[1];
$def['local'] = $definition['local'];
$def['alias'] = $e2[0];
$def['class'] = $e2[0];
$def['type'] = Doctrine_Relation::MANY_COMPOSITE;
$this->relations[$e2[0]] = new Doctrine_Relation_ForeignKey($def);
$definition['local'] = $e2[1];
$definition['assocTable'] = $associationTable;
$relation = new Doctrine_Relation_Association($definition);
}
}
}
$this->relations[$name] = $relation;
return $this->relations[$name];
}
// load all relations
$this->getRelations();
if ($recursive) {
return $this->getRelation($name, false);
} else {
throw new Doctrine_Table_Exception($this->options['name'] . " doesn't have a relation to " . $name);
}
}
/**
* returns an array containing all foreign key objects
*
* @return array
*/
final public function getRelations()
{
foreach ($this->bound as $k => $v) {
$this->getRelation($k);
}
return $this->relations;
}
/** /**
* create * create
* creates a new record * creates a new record
......
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