2009-11-22 06:29:24 +01:00
|
|
|
<?php
|
|
|
|
|
2016-06-15 06:03:16 +02:00
|
|
|
namespace SilverStripe\ORM;
|
|
|
|
|
|
|
|
use InvalidArgumentException;
|
|
|
|
|
2009-11-22 06:29:24 +01:00
|
|
|
/**
|
2013-05-20 12:18:07 +02:00
|
|
|
* Subclass of {@link DataList} representing a has_many relation.
|
2009-11-22 06:29:24 +01:00
|
|
|
*/
|
|
|
|
class HasManyList extends RelationList {
|
2013-05-20 12:18:07 +02:00
|
|
|
|
2016-08-19 11:37:58 +02:00
|
|
|
/**
|
|
|
|
* @var string
|
|
|
|
*/
|
2009-11-22 06:29:24 +01:00
|
|
|
protected $foreignKey;
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-11-22 06:29:24 +01:00
|
|
|
/**
|
|
|
|
* 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.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2013-07-12 05:18:06 +02:00
|
|
|
* @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.
|
2009-11-22 06:29:24 +01:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function __construct($dataClass, $foreignKey) {
|
2009-11-22 06:29:24 +01:00
|
|
|
parent::__construct($dataClass);
|
2013-05-20 12:18:07 +02:00
|
|
|
|
2009-11-22 06:29:24 +01:00
|
|
|
$this->foreignKey = $foreignKey;
|
|
|
|
}
|
2013-09-27 07:06:55 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the field name which holds the related object ID.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function getForeignKey() {
|
|
|
|
return $this->foreignKey;
|
|
|
|
}
|
|
|
|
|
2016-08-19 11:37:58 +02:00
|
|
|
/**
|
|
|
|
* @param null|int $id
|
|
|
|
* @return array
|
|
|
|
*/
|
2012-12-12 05:22:45 +01:00
|
|
|
protected function foreignIDFilter($id = null) {
|
2016-05-25 07:09:29 +02:00
|
|
|
if ($id === null) {
|
|
|
|
$id = $this->getForeignID();
|
|
|
|
}
|
2012-12-12 05:22:45 +01:00
|
|
|
|
2009-11-22 06:29:24 +01:00
|
|
|
// Apply relation filter
|
2016-05-25 07:09:29 +02:00
|
|
|
$key = DataObject::getSchema()->sqlColumnForField($this->dataClass(), $this->getForeignKey());
|
2012-12-12 05:22:45 +01:00
|
|
|
if(is_array($id)) {
|
2013-06-21 00:32:08 +02:00
|
|
|
return array("$key IN (".DB::placeholders($id).")" => $id);
|
2012-12-12 05:22:45 +01:00
|
|
|
} else if($id !== null){
|
2013-06-21 00:32:08 +02:00
|
|
|
return array($key => $id);
|
2009-11-22 06:29:24 +01:00
|
|
|
}
|
2016-05-25 07:09:29 +02:00
|
|
|
return null;
|
2009-11-22 06:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds the item to this relation.
|
2013-05-20 12:18:07 +02:00
|
|
|
*
|
2009-11-22 06:29:24 +01:00
|
|
|
* It does so by setting the relationFilters.
|
2013-05-20 12:18:07 +02:00
|
|
|
*
|
2016-05-25 07:30:01 +02:00
|
|
|
* @param DataObject|int $item The DataObject to be added, or its ID
|
2009-11-22 06:29:24 +01:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function add($item) {
|
2012-09-26 23:34:00 +02:00
|
|
|
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);
|
|
|
|
}
|
2009-11-22 06:29:24 +01:00
|
|
|
|
2012-12-12 05:22:45 +01:00
|
|
|
$foreignID = $this->getForeignID();
|
|
|
|
|
2009-11-22 06:29:24 +01:00
|
|
|
// Validate foreignID
|
2012-12-12 05:22:45 +01:00
|
|
|
if(!$foreignID) {
|
2009-11-22 06:29:24 +01:00
|
|
|
user_error("ManyManyList::add() can't be called until a foreign ID is set", E_USER_WARNING);
|
|
|
|
return;
|
|
|
|
}
|
2012-12-12 05:22:45 +01:00
|
|
|
if(is_array($foreignID)) {
|
2009-11-22 06:29:24 +01:00
|
|
|
user_error("ManyManyList::add() can't be called on a list linked to mulitple foreign IDs", E_USER_WARNING);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-06-21 00:32:08 +02:00
|
|
|
$foreignKey = $this->foreignKey;
|
|
|
|
$item->$foreignKey = $foreignID;
|
2009-11-22 06:29:24 +01:00
|
|
|
|
|
|
|
$item->write();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove an item from this relation.
|
2013-05-20 12:18:07 +02:00
|
|
|
*
|
2009-11-22 06:29:24 +01:00
|
|
|
* Doesn't actually remove the item, it just clears the foreign key value.
|
2013-05-20 12:18:07 +02:00
|
|
|
*
|
2016-05-25 07:30:01 +02:00
|
|
|
* @param int $itemID The ID of the item to be removed.
|
2011-03-30 03:19:27 +02:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function removeByID($itemID) {
|
2012-12-08 12:20:20 +01:00
|
|
|
$item = $this->byID($itemID);
|
2013-05-20 12:18:07 +02:00
|
|
|
|
2012-12-08 12:20:20 +01:00
|
|
|
return $this->remove($item);
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2011-03-30 03:19:27 +02:00
|
|
|
/**
|
|
|
|
* Remove an item from this relation.
|
|
|
|
* Doesn't actually remove the item, it just clears the foreign key value.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2016-05-25 07:30:01 +02:00
|
|
|
* @param DataObject $item The DataObject to be removed
|
2014-08-15 08:53:05 +02:00
|
|
|
* @todo Maybe we should delete the object instead?
|
2009-11-22 06:29:24 +01:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function remove($item) {
|
2012-12-08 12:20:20 +01:00
|
|
|
if(!($item instanceof $this->dataClass)) {
|
|
|
|
throw new InvalidArgumentException("HasManyList::remove() expecting a $this->dataClass object, or ID",
|
|
|
|
E_USER_ERROR);
|
|
|
|
}
|
2009-11-22 06:29:24 +01:00
|
|
|
|
2013-07-12 05:18:06 +02:00
|
|
|
// 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();
|
|
|
|
}
|
2009-11-22 06:29:24 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|