silverstripe-framework/model/HasManyList.php
Damian Mooyman d8e9af8af8 API New Database abstraction layer. Ticket #7429
Database abstraction broken up into controller, connector, query builder, and schema manager, each independently configurable via YAML / Injector
Creation of new DBQueryGenerator for database specific generation of SQL
Support for parameterised queries, move of code base to use these over escaped conditions
Refactor of SQLQuery into separate query classes for each of INSERT UPDATE DELETE and SELECT
Support for PDO
Installation process upgraded to use new ORM
SS_DatabaseException created to handle database errors, maintaining details of raw sql and parameter details for user code designed interested in that data.
Renamed DB static methods to conform correctly to naming conventions (e.g. DB::getConn -> DB::get_conn)
3.2 upgrade docs
Performance Optimisation and simplification of code to use more concise API
API Ability for database adapters to register extensions to ConfigureFromEnv.php
2014-07-09 18:04:05 +12:00

121 lines
3.1 KiB
PHP

<?php
/**
* Subclass of {@link DataList} representing a has_many relation.
*
* @package framework
* @subpackage model
*/
class HasManyList extends RelationList {
protected $foreignKey;
/**
* Create a new HasManyList object.
* Generation of the appropriate record set is left up to the caller, using the normal
* {@link DataList} methods. Addition arguments are used to support {@@link add()}
* and {@link remove()} methods.
*
* @param string $dataClass The class of the DataObjects that this will list.
* @param string $foreignKey The name of the foreign key field to set the ID filter against.
*/
public function __construct($dataClass, $foreignKey) {
parent::__construct($dataClass);
$this->foreignKey = $foreignKey;
}
/**
* Gets the field name which holds the related object ID.
*
* @return string
*/
public function getForeignKey() {
return $this->foreignKey;
}
protected function foreignIDFilter($id = null) {
if ($id === null) $id = $this->getForeignID();
// Apply relation filter
$key = "\"$this->foreignKey\"";
if(is_array($id)) {
return array("$key IN (".DB::placeholders($id).")" => $id);
} else if($id !== null){
return array($key => $id);
}
}
/**
* Adds the item to this relation.
*
* It does so by setting the relationFilters.
*
* @param $item The DataObject to be added, or its ID
*/
public function add($item) {
if(is_numeric($item)) {
$item = DataObject::get_by_id($this->dataClass, $item);
} else if(!($item instanceof $this->dataClass)) {
user_error("HasManyList::add() expecting a $this->dataClass object, or ID value", E_USER_ERROR);
}
$foreignID = $this->getForeignID();
// Validate foreignID
if(!$foreignID) {
user_error("ManyManyList::add() can't be called until a foreign ID is set", E_USER_WARNING);
return;
}
if(is_array($foreignID)) {
user_error("ManyManyList::add() can't be called on a list linked to mulitple foreign IDs", E_USER_WARNING);
return;
}
$foreignKey = $this->foreignKey;
$item->$foreignKey = $foreignID;
$item->write();
}
/**
* Remove an item from this relation.
*
* Doesn't actually remove the item, it just clears the foreign key value.
*
* @param $itemID The ID of the item to be removed.
*/
public function removeByID($itemID) {
$item = $this->byID($itemID);
return $this->remove($item);
}
/**
* Remove an item from this relation.
* Doesn't actually remove the item, it just clears the foreign key value.
*
* @param $item The DataObject to be removed
* @todo Maybe we should delete the object instead?
*/
public function remove($item) {
if(!($item instanceof $this->dataClass)) {
throw new InvalidArgumentException("HasManyList::remove() expecting a $this->dataClass object, or ID",
E_USER_ERROR);
}
// Don't remove item which doesn't belong to this list
$foreignID = $this->getForeignID();
$foreignKey = $this->getForeignKey();
if( empty($foreignID)
|| (is_array($foreignID) && in_array($item->$foreignKey, $foreignID))
|| $foreignID == $item->$foreignKey
) {
$item->$foreignKey = null;
$item->write();
}
}
}