Skip to content

Commit

Permalink
Remove deleted items from a collection that contain that instance.
Browse files Browse the repository at this point in the history
  • Loading branch information
Bob Fanger committed Apr 25, 2013
1 parent 6e79c06 commit ed4c76b
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 7 deletions.
36 changes: 35 additions & 1 deletion classes/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ class Repository extends Object {
*/
protected $created = array();

/**
* References to instances that have been deleted
* @var array
*/
protected $deleted = array();

/**
* The unique identifier of this repository
* @var string
Expand Down Expand Up @@ -513,6 +519,19 @@ function resolveProperties($instance, $options = array()) {
*/
function delete($model, $mixed) {
$config = $this->_getConfig($model);
if (isset($this->deleted[$model])) {
$isDeleted = false;
if (is_object($mixed)) {
$isDeleted = collection($this->deleted[$model])->find($mixed, true);
} else { // $mixed is an id
$index = $this->resolveIndex($mixed, $config);
$isDeleted = isset($this->deleted[$model][$index]);
}
if ($isDeleted) {
// notice('Already deleted');
return;
}
}
$index = $this->resolveIndex($mixed, $config);
$object = @$this->objects[$model][$index];
if ($object === null) {
Expand Down Expand Up @@ -550,7 +569,22 @@ function delete($model, $mixed) {
unset($instance->$property);
}
}
// @todo Unload the hasMany objects from memory, they might have been deleted through an CASCADE relation in MySQL.
// Remove the instances from connected collections
foreach ($this->configs as $connectedConfig) {
foreach ($connectedConfig->hasMany as $hasManyPath => $hasManyConfig) {
if ($hasManyConfig['model'] === $model && isset($this->objects[$connectedConfig->name])) {
foreach ($this->objects[$connectedConfig->name] as $connectedObject) {
$collection = PropertyPath::get($hasManyPath, $connectedObject['instance']);
if ($collection instanceof Collection) {
$collection->remove($instance, true); // Remove the item from the collection (if it's there)
}
// @todo Remove the reference from $connectedObject['hadMany'][$hasManyPath]? Could cause issues with many2many relations?
}
}
}
// @todo Set the belongsTo to null?
}
$this->deleted[$model][$index] = $instance; // Register as deleted
unset($this->objects[$model][$index]); // Remove the object from the repository
}

Expand Down
20 changes: 14 additions & 6 deletions tests/RepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ function test_hasManyArrayAccessInterface() {
$this->assertEquals(count($c2->orders), 1, 'Unset by array offset');
$this->assertInstanceOf('Sledgehammer\Collection', $c2->orders, 'The orders property should be replaced with an Collection');

// $this->setExpectedException('PHPUnit_Framework_Error_Notice', 'This placeholder is already replaced');
// $this->setExpectedException('PHPUnit_Framework_Error_Notice', 'This placeholder is already replaced');
// $this->assertEquals($clone->orders[1]->product, 'Spycam');
// $this->fail('clone doesn\'t work with PlaceHolders, but the placeholder should complain');
}
Expand All @@ -264,14 +264,22 @@ function test_removeWildcard() {
$repo = new RepositoryTester();
$repo->registerBackend(new DatabaseRepositoryBackend($this->dbLink));

$order1 = $repo->getOrder(1);
// remove by instance
$repo->deleteOrder($order1);
$this->assertRelativeQueryCount(2);
$this->assertLastQuery('DELETE FROM orders WHERE id = 1');
// remove by id
$repo->deleteOrder('2');
$this->assertLastQuery('DELETE FROM orders WHERE id = 2');
$this->assertRelativeQueryCount(1);

// remove by instance
$order1 = $repo->getOrder(1);
$this->assertCount(1, $order1->customer->orders->toArray());
$customer = $order1->customer;
$this->assertRelativeQueryCount(4, 'Sanity check');
$repo->deleteOrder($order1);
$this->assertRelativeQueryCount(5);
$this->assertLastQuery('DELETE FROM orders WHERE id = 1');
$this->assertCount(0, $customer->orders->toArray());
$repo->saveCustomer($customer);
$this->assertRelativeQueryCount(5, 'Saving a connected item should not trigger another DELETE query');
}

function test_saveWildcard() {
Expand Down

0 comments on commit ed4c76b

Please sign in to comment.