1
0
mirror of synced 2024-12-14 23:26:04 +03:00
doctrine2/lib/Doctrine/Relation.php
2006-12-29 14:40:47 +00:00

291 lines
8.3 KiB
PHP

<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
/**
* Doctrine_Relation
* This class represents a relation between components
*
* @package Doctrine
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @category Object Relational Mapping
* @link www.phpdoctrine.com
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
*/
abstract class Doctrine_Relation
{
/**
* RELATION CONSTANTS
*/
/**
* constant for ONE_TO_ONE and MANY_TO_ONE aggregate relationships
*/
const ONE_AGGREGATE = 0;
/**
* constant for ONE_TO_ONE and MANY_TO_ONE composite relationships
*/
const ONE_COMPOSITE = 1;
/**
* constant for MANY_TO_MANY and ONE_TO_MANY aggregate relationships
*/
const MANY_AGGREGATE = 2;
/**
* constant for MANY_TO_MANY and ONE_TO_MANY composite relationships
*/
const MANY_COMPOSITE = 3;
/**
* @var Doctrine_Table $table foreign factory
*/
protected $table;
/**
* @var string $local local field
*/
protected $local;
/**
* @var string $foreign foreign field
*/
protected $foreign;
/**
* @var integer $type bind type
*/
protected $type;
/**
* @var string $alias relation alias
*/
protected $alias;
/**
* @param Doctrine_Table $table
* @param string $local
* @param string $foreign
* @param integer $type
* @param string $alias
*/
public function __construct(Doctrine_Table $table, $local, $foreign, $type, $alias)
{
$this->table = $table;
$this->local = $local;
$this->foreign = $foreign;
$this->type = $type;
$this->alias = $alias;
}
/**
* getAlias
* returns the relation alias
*
* @return string
*/
final public function getAlias()
{
return $this->alias;
}
/**
* getType
* returns the relation type, either 0 or 1
*
* @see Doctrine_Relation MANY_* and ONE_* constants
* @return integer
*/
final public function getType()
{
return $this->type;
}
/**
* getTable
* returns the foreign table object
*
* @return object Doctrine_Table
*/
final public function getTable()
{
return $this->table;
}
/**
* getLocal
* returns the name of the local column
*
* @return string
*/
final public function getLocal()
{
return $this->local;
}
/**
* getForeign
* returns the name of the foreignkey column where
* the localkey column is pointing at
*
* @return string
*/
final public function getForeign()
{
return $this->foreign;
}
/**
* isComposite
* returns whether or not this relation is a composite relation
*
* @return boolean
*/
final public function isComposite()
{
return ($this->type == Doctrine_Relation::ONE_COMPOSITE ||
$this->type == Doctrine_Relation::MANY_COMPOSITE);
}
/**
* isOneToOne
* returns whether or not this relation is a one-to-one relation
*
* @return boolean
*/
final public function isOneToOne()
{
return ($this->type == Doctrine_Relation::ONE_AGGREGATE ||
$this->type == Doctrine_Relation::ONE_COMPOSITE);
}
/**
* getRelationDql
*
* @param integer $count
* @return string
*/
public function getRelationDql($count)
{
$dql = "FROM ".$this->table->getComponentName().
" WHERE ".$this->table->getComponentName(). '.' . $this->foreign.
" IN (".substr(str_repeat("?, ", $count),0,-2).")";
return $dql;
}
/**
* getDeleteOperations
*
* get the records that need to be deleted in order to change the old collection
* to the new one
*
* The algorithm here is very simple and definitely not
* the fastest one, since we have to iterate through the collections twice.
* the complexity of this algorithm is O(n^2)
*
* We iterate through the old collection and get the records
* that do not exists in the new collection (Doctrine_Records that need to be deleted).
*
* @param Doctrine_Collection $old
* @param Doctrine_Collection $new
* @return array
*/
public static function getDeleteOperations(Doctrine_Collection $old, Doctrine_Collection $new)
{
$r = array();
foreach ($old as $k => $record) {
$id = $record->getIncremented();
if (empty($id)) {
continue;
}
$found = false;
foreach ($new as $k2 => $record2) {
if ($record2->getIncremented() === $record->getIncremented()) {
$found = true;
break;
}
}
if ( ! $found) {
$r[] = $record;
unset($old[$k]);
}
}
return $r;
}
/**
* getInsertOperations
*
* get the records that need to be added in order to change the old collection
* to the new one
*
* The algorithm here is very simple and definitely not
* the fastest one, since we have to iterate through the collections twice.
* the complexity of this algorithm is O(n^2)
*
* We iterate through the old collection and get the records
* that exists only in the new collection (Doctrine_Records that need to be added).
*
* @param Doctrine_Collection $old
* @param Doctrine_Collection $new
* @return array
*/
public static function getInsertOperations(Doctrine_Collection $old, Doctrine_Collection $new)
{
$r = array();
foreach ($new as $k => $record) {
$found = false;
$id = $record->getIncremented();
if ( ! empty($id)) {
foreach ($old as $k2 => $record2) {
if ($record2->getIncremented() === $record->getIncremented()) {
$found = true;
break;
}
}
}
if ( ! $found) {
$old[] = $record;
$r[] = $record;
}
}
return $r;
}
/**
* fetchRelatedFor
*
* fetches a component related to given record
*
* @param Doctrine_Record $record
* @return Doctrine_Record|Doctrine_Collection
*/
abstract public function fetchRelatedFor(Doctrine_Record $record);
/**
* __toString
*
* @return string
*/
public function __toString()
{
$r[] = "<pre>";
$r[] = "Class : ".get_class($this);
$r[] = "Component : ".$this->table->getComponentName();
$r[] = "Table : ".$this->table->getTableName();
$r[] = "Local key : ".$this->local;
$r[] = "Foreign key : ".$this->foreign;
$r[] = "Type : ".$this->type;
$r[] = "</pre>";
return implode("\n", $r);
}
}