Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement MassPrunable without chunks limit #2598

Merged
merged 1 commit into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ All notable changes to this project will be documented in this file.
- Fix Query on `whereDate`, `whereDay`, `whereMonth`, `whereYear`, `whereTime` to use MongoDB operators [#2570](https://github.com/mongodb/laravel-mongodb/pull/2376) by [@Davpyu](https://github.com/Davpyu) and [@GromNaN](https://github.com/GromNaN).
- `Model::unset()` does not persist the change. Call `Model::save()` to persist the change [#2578](https://github.com/mongodb/laravel-mongodb/pull/2578) by [@GromNaN](https://github.com/GromNaN).
- Support delete one document with `Query\Builder::limit(1)->delete()` [#2591](https://github.com/mongodb/laravel-mongodb/pull/2591) by [@GromNaN](https://github.com/GromNaN)
- Add trait `MongoDB\Laravel\Eloquent\MassPrunable` to replace the Eloquent trait on MongoDB models [#2598](https://github.com/mongodb/laravel-mongodb/pull/2598) by [@GromNaN](https://github.com/GromNaN)

## [3.9.2] - 2022-09-01

Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ It is compatible with Laravel 10.x. For older versions of Laravel, please refer
- [Cross-Database Relationships](#cross-database-relationships)
- [Authentication](#authentication)
- [Queues](#queues)
- [Prunable](#prunable)
- [Upgrading](#upgrading)
- [Upgrading from version 2 to 3](#upgrading-from-version-2-to-3)
- [Security contact information](#security-contact-information)
Expand Down Expand Up @@ -1189,14 +1190,35 @@ Add the service provider in `config/app.php`:
MongoDB\Laravel\MongodbQueueServiceProvider::class,
```

### Prunable

`Prunable` and `MassPrunable` traits are Laravel features to automatically remove models from your database. You can use
`Illuminate\Database\Eloquent\Prunable` trait to remove models one by one. If you want to remove models in bulk, you need
to use the `MongoDB\Laravel\Eloquent\MassPrunable` trait instead: it will be more performant but can break links with
other documents as it does not load the models.


```php
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Eloquent\MassPrunable;

class Book extends Model
{
use MassPrunable;
}
```

Upgrading
---------

#### Upgrading from version 3 to 4

Change project name in composer.json to `mongodb/laravel` and run `composer update`.

Change namespace from `Jenssegers\Mongodb` to `MongoDB\Laravel` in your models and config.

Replace `Illuminate\Database\Eloquent\MassPrunable` with `MongoDB\Laravel\Eloquent\MassPrunable` in your models.

## Security contact information

To report a security vulnerability, follow [these steps](https://tidelift.com/security).
28 changes: 28 additions & 0 deletions src/Eloquent/MassPrunable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace MongoDB\Laravel\Eloquent;

use Illuminate\Database\Eloquent\MassPrunable as EloquentMassPrunable;
use Illuminate\Database\Events\ModelsPruned;

trait MassPrunable
{
use EloquentMassPrunable;

/**
* Prune all prunable models in the database.
GromNaN marked this conversation as resolved.
Show resolved Hide resolved
*
* @see \Illuminate\Database\Eloquent\MassPrunable::pruneAll()
*/
public function pruneAll(): int
{
$query = $this->prunable();
$total = in_array(SoftDeletes::class, class_uses_recursive(get_class($this)))
? $query->forceDelete()
: $query->delete();

event(new ModelsPruned(static::class, $total));

return $total;
}
}
63 changes: 63 additions & 0 deletions tests/Eloquent/MassPrunableTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

namespace Eloquent;

use Illuminate\Database\Console\PruneCommand;
use Illuminate\Database\Eloquent\MassPrunable;
use Illuminate\Database\Eloquent\Prunable;
use MongoDB\Laravel\Tests\Models\Soft;
use MongoDB\Laravel\Tests\Models\User;
use MongoDB\Laravel\Tests\TestCase;

class MassPrunableTest extends TestCase
{
public function tearDown(): void
{
User::truncate();
Soft::truncate();
}

public function testPruneWithQuery(): void
{
$this->assertTrue($this->isPrunable(User::class));

User::insert([
['name' => 'John Doe', 'age' => 35],
['name' => 'Jane Doe', 'age' => 32],
['name' => 'Tomy Doe', 'age' => 11],
]);

$model = new User();
$total = $model->pruneAll();
$this->assertEquals(2, $total);
$this->assertEquals(1, User::count());
}

public function testPruneSoftDelete(): void
{
$this->assertTrue($this->isPrunable(Soft::class));

Soft::insert([
['name' => 'John Doe'],
['name' => 'Jane Doe'],
]);

$model = new Soft();
$total = $model->pruneAll();
$this->assertEquals(2, $total);
$this->assertEquals(0, Soft::count());
$this->assertEquals(0, Soft::withTrashed()->count());
}

/**
* @see PruneCommand::isPrunable()
*/
protected function isPrunable($model)
{
$uses = class_uses_recursive($model);

return in_array(Prunable::class, $uses) || in_array(MassPrunable::class, $uses);
}
}
8 changes: 8 additions & 0 deletions tests/Models/Soft.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace MongoDB\Laravel\Tests\Models;

use MongoDB\Laravel\Eloquent\Builder;
use MongoDB\Laravel\Eloquent\MassPrunable;
use MongoDB\Laravel\Eloquent\Model as Eloquent;
use MongoDB\Laravel\Eloquent\SoftDeletes;

Expand All @@ -15,9 +17,15 @@
class Soft extends Eloquent
{
use SoftDeletes;
use MassPrunable;

protected $connection = 'mongodb';
protected $collection = 'soft';
protected static $unguarded = true;
protected $casts = ['deleted_at' => 'datetime'];

public function prunable(): Builder
{
return $this->newQuery();
}
}
8 changes: 8 additions & 0 deletions tests/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Str;
use MongoDB\Laravel\Eloquent\Builder;
use MongoDB\Laravel\Eloquent\HybridRelations;
use MongoDB\Laravel\Eloquent\MassPrunable;
use MongoDB\Laravel\Eloquent\Model as Eloquent;

/**
Expand All @@ -35,6 +37,7 @@ class User extends Eloquent implements AuthenticatableContract, CanResetPassword
use CanResetPassword;
use HybridRelations;
use Notifiable;
use MassPrunable;

protected $connection = 'mongodb';
protected $casts = [
Expand Down Expand Up @@ -106,4 +109,9 @@ protected function username(): Attribute
set: fn ($value) => Str::slug($value)
);
}

public function prunable(): Builder
{
return $this->where('age', '>', 18);
}
}
Loading