1: <?php
2:
3: namespace Baril\Bonsai\Console;
4:
5: use Illuminate\Console\Command;
6: use Illuminate\Database\Eloquent\Model;
7:
8: class FixTreeCommand extends Command
9: {
10: protected $signature = 'bonsai:fix {model : The model class.}';
11: protected $description = 'Rebuilds the closures for a given tree';
12:
13: public function handle()
14: {
15: $model = $this->input->getArgument('model');
16: if (
17: !class_exists($model)
18: || !is_subclass_of($model, Model::class)
19: || !method_exists($model, 'getClosureTable')
20: ) {
21: $this->error('{model} must be a valid model class and use the BelongsToTree trait!');
22: return;
23: }
24:
25: $this->rebuildClosures($model);
26: }
27:
28: protected function rebuildClosures($model)
29: {
30: $instance = new $model();
31: $connection = $instance->getConnection();
32: $connection->transaction(function () use ($instance, $connection) {
33: $table = $instance->getTable();
34: $parentKey = $instance->getParentForeignKeyName();
35: $primaryKey = $instance->getKeyName();
36: $closureTable = $instance->getClosureTable();
37:
38: // Delete old closures:
39: $connection->table($closureTable)->delete();
40:
41: // Insert "self-closures":
42: $connection->insert("
43: INSERT INTO $closureTable (ancestor_id, descendant_id, depth)
44: SELECT $primaryKey, $primaryKey, 0 FROM $table");
45:
46: // Increment depth and insert closures until there's nothing left to insert:
47: $depth = 1;
48: $continue = true;
49: while ($continue) {
50: $connection->insert("
51: INSERT INTO $closureTable (ancestor_id, descendant_id, depth)
52: SELECT closure_table.ancestor_id, main_table.$primaryKey, ?
53: FROM $table AS main_table
54: INNER JOIN $closureTable AS closure_table
55: ON main_table.$parentKey = closure_table.descendant_id
56: WHERE closure_table.depth = ?", [$depth, $depth - 1]);
57: $continue = (bool) $connection->table($closureTable)->where('depth', '=', $depth)->exists();
58: $depth++;
59: }
60: });
61:
62: $this->line("<info>Rebuilt the closures for:</info> $model");
63: }
64: }
65: