Completed
Pull Request — master (#8)
by Jarek
05:19
created

SlugThemAll::rejectExistingColumns()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 11
rs 9.4285
c 1
b 0
f 1
nc 2
cc 2
eloc 7
nop 1
1
<?php
2
3
namespace Spatie\Sluggable;
4
5
use Throwable;
6
use Illuminate\Console\Command;
7
use Illuminate\Support\Composer;
8
use Illuminate\Database\Eloquent\Model;
9
use Illuminate\Database\Migrations\Migrator;
10
11
class SlugThemAll extends Command
12
{
13
    /** @var string */
14
    protected $signature = 'slug-them:all';
15
16
    /** @var string */
17
    protected $description = "Slug'em all, them models";
18
19
    /** @var \App\MigrationCreator */
20
    protected $creator;
21
22
    /** @var \Illuminate\Database\Migrations\Migrator */
23
    protected $migrator;
24
25
    /** @var \Illuminate\Support\Composer */
26
    protected $composer;
27
28
    public function __construct(MigrationCreator $creator, Migrator $migrator, Composer $composer)
29
    {
30
        parent::__construct();
31
        $this->creator = $creator;
0 ignored issues
show
Documentation Bug introduced by
It seems like $creator of type object<Spatie\Sluggable\MigrationCreator> is incompatible with the declared type object<App\MigrationCreator> of property $creator.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
32
        $this->migrator = $migrator;
33
        $this->composer = $composer;
34
    }
35
36
    /**
37
     * @todo - add option for paths/namespaces (filename) to check for the models
38
     * @todo - add option for auto generating slugs for all the migrated tables
39
     */
40
    public function handle()
41
    {
42
        $migrations = $this->collectClasses()
43
                           ->map([$this, 'filterSluggable'])->filter()
44
                           ->map([$this, 'rejectExistingColumns'])->filter()
45
                           ->each(function ($migration) {
46
                               $this->line(
47
                                   "<info>Adding</info> {$migration['column']} "
48
                                  ."<info>column to</info> {$migration['table']} <info>table</info>"
49
                               );
50
                           });
51
52
        if ($migrations->isEmpty()) {
53
            $this->info('Nothing to migrate');
54
            return;
55
        }
56
57
        $file = $this->create($migrations);
58
        $this->line("<info>Migration created: </info>{$file}");
59
60
        $this->composer->dumpAutoloads();
61
62
        $this->migrator->runMigrationList([$file]);
63
        $this->line("<info>Migrated: </info>{$file}");
64
    }
65
66
    /**
67
     * Find all them classes in app/ & app/Models.
68
     *
69
     * @return \Illuminate\Support\Collection
70
     */
71
    protected function collectClasses()
72
    {
73
        return collect(
74
            array_merge(glob(app_path('*.php')), glob(app_path('Models'.DIRECTORY_SEPARATOR.'*.php')))
75
        )->map(function ($file) {
76
            $file = str_replace([base_path(), '.php'], '', $file);
77
            return str_replace(
78
                'app\\',
79
                app()->getNamespace(),
80
                str_replace(DIRECTORY_SEPARATOR, '\\', $file)
81
            );
82
        });
83
    }
84
85
    /**
86
     * Filter only HasSlug trait holders.
87
     *
88
     * @param  string $class
89
     * @return \Illuminate\Database\Eloquent\Model|null
90
     */
91
    public  function filterSluggable($class)
92
    {
93
        try {
94
            $instance = new $class;
95
            if ($instance instanceof Model && in_array(HasSlug::class, class_uses($instance))) {
96
                return $instance;
97
            }
98
        } catch (Throwable $e) {
99
            //
100
        }
101
    }
102
103
    /**
104
     * Get SlugOptions and learn what the slug column name, aye?
105
     * Then do the all-fired job to check column's existence.
106
     *
107
     * @param  \Illuminate\Database\Eloquent\Model $sluggable
108
     * @return array|null
109
     */
110
    public function rejectExistingColumns($sluggable)
111
    {
112
        $table = $sluggable->getTable();
113
        $column = $sluggable->getSlugOptions()->slugField;
114
        $length = $sluggable->getSlugOptions()->maximumLength;
115
        $schema = $sluggable->getConnection()->getSchemaBuilder()->getColumnListing($table);
116
117
        if (!in_array($column, $schema)) {
118
            return compact('table', 'column', 'length');
119
        }
120
    }
121
122
    /**
123
     * Create the migration file.
124
     *
125
     * @param  \Illuminate\Support\Collection $columns
126
     * @return string
127
     */
128
    protected function create($columns)
129
    {
130
        $path = $this->creator->create(
131
            'add_slug_columns_'.time(),
132
            database_path(DIRECTORY_SEPARATOR.'migrations'),
133
            $columns
134
        );
135
136
        require($path);
137
138
        return pathinfo($path, PATHINFO_FILENAME);
139
    }
140
}
141