Skip to content

Commit df9ea5d

Browse files
authored
[8.x] Add --pretend option for model:prune command (#38945)
* Add --pretend option for model:prune command * Fix tests * Fix code style
1 parent 74ad9ec commit df9ea5d

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

src/Illuminate/Database/Console/PruneCommand.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ class PruneCommand extends Command
1919
*/
2020
protected $signature = 'model:prune
2121
{--model=* : Class names of the models to be pruned}
22-
{--chunk=1000 : The number of models to retrieve per chunk of models to be deleted}';
22+
{--chunk=1000 : The number of models to retrieve per chunk of models to be deleted}
23+
{--pretend : Display the number of prunable records found instead of deleting them}';
2324

2425
/**
2526
* The console command description.
@@ -44,6 +45,14 @@ public function handle(Dispatcher $events)
4445
return;
4546
}
4647

48+
if ($this->option('pretend')) {
49+
$models->each(function ($model) {
50+
$this->pretendToPrune($model);
51+
});
52+
53+
return;
54+
}
55+
4756
$events->listen(ModelsPruned::class, function ($event) {
4857
$this->info("{$event->count} [{$event->model}] records have been pruned.");
4958
});
@@ -104,4 +113,26 @@ protected function isPrunable($model)
104113

105114
return in_array(Prunable::class, $uses) || in_array(MassPrunable::class, $uses);
106115
}
116+
117+
/**
118+
* Display how many models will be pruned.
119+
*
120+
* @param string $model
121+
* @return void
122+
*/
123+
protected function pretendToPrune($model)
124+
{
125+
$instance = new $model;
126+
127+
$count = $instance->prunable()
128+
->when(in_array(SoftDeletes::class, class_uses_recursive(get_class($instance))), function ($query) {
129+
$query->withTrashed();
130+
})->count();
131+
132+
if ($count === 0) {
133+
$this->info("No prunable [$model] records found.");
134+
} else {
135+
$this->info("{$count} [{$model}] records will be pruned.");
136+
}
137+
}
107138
}

tests/Database/PruneCommandTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44

55
use Illuminate\Container\Container;
66
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
7+
use Illuminate\Database\Capsule\Manager as DB;
8+
use Illuminate\Database\ConnectionResolverInterface;
79
use Illuminate\Database\Console\PruneCommand;
810
use Illuminate\Database\Eloquent\MassPrunable;
911
use Illuminate\Database\Eloquent\Model;
1012
use Illuminate\Database\Eloquent\Prunable;
1113
use Illuminate\Database\Events\ModelsPruned;
1214
use Illuminate\Events\Dispatcher;
15+
use Mockery as m;
1316
use PHPUnit\Framework\TestCase;
1417
use Symfony\Component\Console\Input\ArrayInput;
1518
use Symfony\Component\Console\Output\BufferedOutput;
@@ -60,6 +63,41 @@ public function testNonPrunableTest()
6063
EOF, str_replace("\r", '', $output->fetch()));
6164
}
6265

66+
public function testTheCommandMayBePretended()
67+
{
68+
$db = new DB;
69+
$db->addConnection([
70+
'driver' => 'sqlite',
71+
'database' => ':memory:',
72+
]);
73+
$db->setAsGlobal();
74+
DB::connection('default')->getSchemaBuilder()->create('prunables', function ($table) {
75+
$table->string('name')->nullable();
76+
$table->string('value')->nullable();
77+
});
78+
DB::connection('default')->table('prunables')->insert([
79+
['name' => 'zain', 'value' => 1],
80+
['name' => 'patrice', 'value' => 2],
81+
['name' => 'amelia', 'value' => 3],
82+
['name' => 'stuart', 'value' => 4],
83+
['name' => 'bello', 'value' => 5],
84+
]);
85+
$resolver = m::mock(ConnectionResolverInterface::class, ['connection' => $db->getConnection('default')]);
86+
PrunableTestModelWithPrunableRecords::setConnectionResolver($resolver);
87+
88+
$output = $this->artisan([
89+
'--model' => PrunableTestModelWithPrunableRecords::class,
90+
'--pretend' => true,
91+
]);
92+
93+
$this->assertEquals(<<<'EOF'
94+
3 [Illuminate\Tests\Database\PrunableTestModelWithPrunableRecords] records will be pruned.
95+
96+
EOF, str_replace("\r", '', $output->fetch()));
97+
98+
$this->assertEquals(5, PrunableTestModelWithPrunableRecords::count());
99+
}
100+
63101
protected function artisan($arguments)
64102
{
65103
$input = new ArrayInput($arguments);
@@ -84,13 +122,21 @@ class PrunableTestModelWithPrunableRecords extends Model
84122
{
85123
use MassPrunable;
86124

125+
protected $table = 'prunables';
126+
protected $connection = 'default';
127+
87128
public function pruneAll()
88129
{
89130
event(new ModelsPruned(static::class, 10));
90131
event(new ModelsPruned(static::class, 20));
91132

92133
return 20;
93134
}
135+
136+
public function prunable()
137+
{
138+
return static::where('value', '>=', 3);
139+
}
94140
}
95141

96142
class PrunableTestModelWithoutPrunableRecords extends Model

0 commit comments

Comments
 (0)