Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Database\Console;
4
 
5
use Illuminate\Console\Command;
6
use Illuminate\Contracts\Events\Dispatcher;
7
use Illuminate\Database\Eloquent\MassPrunable;
8
use Illuminate\Database\Eloquent\Prunable;
9
use Illuminate\Database\Eloquent\SoftDeletes;
10
use Illuminate\Database\Events\ModelsPruned;
11
use Illuminate\Support\Str;
12
use InvalidArgumentException;
13
use Symfony\Component\Finder\Finder;
14
 
15
class PruneCommand extends Command
16
{
17
    /**
18
     * The console command name.
19
     *
20
     * @var string
21
     */
22
    protected $signature = 'model:prune
23
                                {--model=* : Class names of the models to be pruned}
24
                                {--except=* : Class names of the models to be excluded from pruning}
25
                                {--chunk=1000 : The number of models to retrieve per chunk of models to be deleted}
26
                                {--pretend : Display the number of prunable records found instead of deleting them}';
27
 
28
    /**
29
     * The console command description.
30
     *
31
     * @var string
32
     */
33
    protected $description = 'Prune models that are no longer needed';
34
 
35
    /**
36
     * Execute the console command.
37
     *
38
     * @param  \Illuminate\Contracts\Events\Dispatcher  $events
39
     * @return void
40
     */
41
    public function handle(Dispatcher $events)
42
    {
43
        $models = $this->models();
44
 
45
        if ($models->isEmpty()) {
46
            $this->components->info('No prunable models found.');
47
 
48
            return;
49
        }
50
 
51
        if ($this->option('pretend')) {
52
            $models->each(function ($model) {
53
                $this->pretendToPrune($model);
54
            });
55
 
56
            return;
57
        }
58
 
59
        $pruning = [];
60
 
61
        $events->listen(ModelsPruned::class, function ($event) use (&$pruning) {
62
            if (! in_array($event->model, $pruning)) {
63
                $pruning[] = $event->model;
64
 
65
                $this->newLine();
66
 
67
                $this->components->info(sprintf('Pruning [%s] records.', $event->model));
68
            }
69
 
70
            $this->components->twoColumnDetail($event->model, "{$event->count} records");
71
        });
72
 
73
        $models->each(function ($model) {
74
            $this->pruneModel($model);
75
        });
76
 
77
        $events->forget(ModelsPruned::class);
78
    }
79
 
80
    /**
81
     * Prune the given model.
82
     *
83
     * @param  string  $model
84
     * @return void
85
     */
86
    protected function pruneModel(string $model)
87
    {
88
        $instance = new $model;
89
 
90
        $chunkSize = property_exists($instance, 'prunableChunkSize')
91
            ? $instance->prunableChunkSize
92
            : $this->option('chunk');
93
 
94
        $total = $this->isPrunable($model)
95
            ? $instance->pruneAll($chunkSize)
96
            : 0;
97
 
98
        if ($total == 0) {
99
            $this->components->info("No prunable [$model] records found.");
100
        }
101
    }
102
 
103
    /**
104
     * Determine the models that should be pruned.
105
     *
106
     * @return \Illuminate\Support\Collection
107
     */
108
    protected function models()
109
    {
110
        if (! empty($models = $this->option('model'))) {
111
            return collect($models)->filter(function ($model) {
112
                return class_exists($model);
113
            })->values();
114
        }
115
 
116
        $except = $this->option('except');
117
 
118
        if (! empty($models) && ! empty($except)) {
119
            throw new InvalidArgumentException('The --models and --except options cannot be combined.');
120
        }
121
 
122
        return collect((new Finder)->in($this->getDefaultPath())->files()->name('*.php'))
123
            ->map(function ($model) {
124
                $namespace = $this->laravel->getNamespace();
125
 
126
                return $namespace.str_replace(
127
                    ['/', '.php'],
128
                    ['\\', ''],
129
                    Str::after($model->getRealPath(), realpath(app_path()).DIRECTORY_SEPARATOR)
130
                );
131
            })->when(! empty($except), function ($models) use ($except) {
132
                return $models->reject(function ($model) use ($except) {
133
                    return in_array($model, $except);
134
                });
135
            })->filter(function ($model) {
136
                return $this->isPrunable($model);
137
            })->filter(function ($model) {
138
                return class_exists($model);
139
            })->values();
140
    }
141
 
142
    /**
143
     * Get the default path where models are located.
144
     *
145
     * @return string|string[]
146
     */
147
    protected function getDefaultPath()
148
    {
149
        return app_path('Models');
150
    }
151
 
152
    /**
153
     * Determine if the given model class is prunable.
154
     *
155
     * @param  string  $model
156
     * @return bool
157
     */
158
    protected function isPrunable($model)
159
    {
160
        $uses = class_uses_recursive($model);
161
 
162
        return in_array(Prunable::class, $uses) || in_array(MassPrunable::class, $uses);
163
    }
164
 
165
    /**
166
     * Display how many models will be pruned.
167
     *
168
     * @param  string  $model
169
     * @return void
170
     */
171
    protected function pretendToPrune($model)
172
    {
173
        $instance = new $model;
174
 
175
        $count = $instance->prunable()
176
            ->when(in_array(SoftDeletes::class, class_uses_recursive(get_class($instance))), function ($query) {
177
                $query->withTrashed();
178
            })->count();
179
 
180
        if ($count === 0) {
181
            $this->components->info("No prunable [$model] records found.");
182
        } else {
183
            $this->components->info("{$count} [{$model}] records will be pruned.");
184
        }
185
    }
186
}