diff --git a/src/Models/Model.php b/src/Models/Model.php index 7a1ad02a..e1bae6d2 100644 --- a/src/Models/Model.php +++ b/src/Models/Model.php @@ -997,11 +997,13 @@ public function deleteAttribute($attributes, $sync = true) * Throws a ModelNotFoundException if the current model does * not exist or does not contain a distinguished name. * + * @param bool $recursive Whether to recursively delete leaf nodes (models that are children). + * * @throws ModelDoesNotExistException * * @return bool */ - public function delete() + public function delete($recursive = false) { $dn = $this->getDn(); @@ -1013,9 +1015,17 @@ public function delete() $this->fireModelEvent(new Events\Deleting($this)); + if ($recursive) { + // If recursive is requested, we'll retrieve all direct leaf nodes + // by executing a 'listing' and delete each resulting model. + $this->newQuery()->listing()->in($this->getDn())->get()->each(function (Model $model) use ($recursive) { + $model->delete($recursive); + }); + } + if ($this->query->getConnection()->delete($dn)) { - // We'll set the exists property to false on delete - // so the dev can run create operations. + // If the deletion was successful, we'll mark the model + // as non-existing and fire the deleted event. $this->exists = false; $this->fireModelEvent(new Events\Deleted($this)); diff --git a/tests/Models/ModelTest.php b/tests/Models/ModelTest.php index a10190d1..084f4674 100644 --- a/tests/Models/ModelTest.php +++ b/tests/Models/ModelTest.php @@ -4,6 +4,8 @@ use Adldap\Adldap; use Adldap\Tests\TestCase; +use Adldap\Query\Builder; +use Adldap\Query\Collection; use Adldap\Models\Entry; use Adldap\Models\Model; use Adldap\Models\BatchModification; @@ -22,17 +24,21 @@ protected function newModel(array $attributes = [], $builder = null, $schema = n { $builder = $builder ?: $this->newBuilder(); - return new Entry($attributes, $builder, $schema); + if ($schema) { + $builder->setSchema($schema); + } + + return new Entry($attributes, $builder); } - public function test_construct() + public function test_construct_with_attributes() { $attributes = [ 'cn' => ['Common Name'], 'samaccountname' => ['Account Name'], ]; - $entry = $this->newModel($attributes, $this->newBuilder()); + $entry = $this->newModel($attributes); $this->assertEquals($attributes, $entry->getAttributes()); } @@ -435,12 +441,25 @@ public function test_save_for_update_with_attributes() $this->assertTrue($entry->save($attributes)); } - public function test_delete_failure() + public function test_delete_fails_when_model_does_not_exist() { $this->expectException(\Adldap\AdldapException::class); $entry = $this->newModel(); + $this->assertFalse($entry->exists); + + $entry->delete(); + } + + public function test_delete_fails_when_model_does_not_have_dn() + { + $this->expectException(\Adldap\AdldapException::class); + + $entry = $this->newModel()->setRawAttributes(['cn' => 'John Doe']); + + $this->assertTrue($entry->exists); + $entry->delete(); } @@ -460,6 +479,41 @@ public function test_delete() $this->assertTrue($entry->delete()); } + public function test_delete_recursive() + { + $connection = $this->newConnectionMock(); + + $dn = 'cn=Testing,ou=Accounting,dc=corp,dc=org'; + + $connection + ->shouldReceive('listing')->once() + ->shouldReceive('getEntries')->once() + ->shouldReceive('delete')->once()->withArgs([$dn])->andReturn(true) + ->shouldReceive('close')->once()->andReturn(true); + + $builder = $this->mock(Builder::class); + + $builder->shouldReceive('getSchema')->once()->andReturn(new ActiveDirectory()); + + $entry = $this->newModel([], $builder); + + $childEntry = $this->mock(Model::class); + + $childEntry->shouldReceive('delete')->once()->withArgs([true])->andReturn(true); + + $builder + ->shouldReceive('newQuery')->once()->andReturnSelf() + ->shouldReceive('newInstance')->once()->andReturnSelf() + ->shouldReceive('listing')->once()->andReturnSelf() + ->shouldReceive('in')->once()->withArgs([$dn])->andReturnSelf() + ->shouldReceive('get')->once()->andReturn(new Collection([$childEntry])) + ->shouldReceive('getConnection')->once()->andReturn($connection); + + $entry->setRawAttributes(['dn' => $dn]); + + $this->assertTrue($entry->delete($recursive = true)); + } + public function test_created_and_updated_at() { $date = '20150519034950.0Z';