ModelGenerator   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 161
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 83
c 1
b 0
f 0
dl 0
loc 161
rs 10
wmc 26

12 Methods

Rating   Name   Duplication   Size   Complexity  
A buildRelationships() 0 21 3
A castableColumns() 0 7 1
A buildProperties() 0 19 4
A castForColumn() 0 14 5
A __construct() 0 9 2
A dateColumns() 0 9 2
A getStub() 0 8 2
A addTraits() 0 9 2
A pretty_print_array() 0 10 2
A populateStub() 0 12 1
A fillableColumns() 0 8 1
A getPath() 0 3 1
1
<?php
2
3
namespace PrismX\Generators\Generators;
4
5
use Illuminate\Support\Str;
6
use Illuminate\Support\Facades\File;
7
use PrismX\Generators\Support\Model;
8
use PrismX\Generators\Support\Column;
9
use PrismX\Generators\Support\AbstractGenerator;
10
11
class ModelGenerator extends AbstractGenerator
12
{
13
    protected $dir;
14
15
    public function __construct(Model $model)
16
    {
17
        parent::__construct($model);
18
        $this->stub = File::get(STUBS_PATH.'/model/class.stub');
19
20
        $this->dir = Str::camel(str_replace('\\', '/', config('generators.model_namespace')));
21
22
        if (! File::isDirectory($this->dir)) {
23
            File::makeDirectory($this->dir);
24
        }
25
    }
26
27
    public function populateStub(): string
28
    {
29
        $stub = $this->stub;
30
        $stub = str_replace('{{Namespace}}', config('generators.model_namespace'), $stub);
31
        $stub = str_replace('{{ClassName}}', $this->model->name(), $stub);
32
        $body = $this->buildProperties();
33
        $body .= PHP_EOL;
34
        $body .= $this->buildRelationships();
35
        $stub = str_replace('{{body}}', trim($body), $stub);
36
        $stub = $this->addTraits($stub);
37
38
        return $stub;
39
    }
40
41
    public function getPath(): string
42
    {
43
        return "{$this->dir}/{$this->model->name()}.php";
44
    }
45
46
    private function buildProperties()
47
    {
48
        $properties = '';
49
        $columns = $this->fillableColumns($this->model->columns());
50
        if (! empty($columns)) {
51
            $properties .= PHP_EOL.str_replace('[]', $this->pretty_print_array($columns, false), $this->getStub('fillable'));
52
        } else {
53
            $properties .= $this->getStub('fillable');
54
        }
55
        $columns = $this->castableColumns($this->model->columns());
56
        if (! empty($columns)) {
57
            $properties .= PHP_EOL.str_replace('[]', $this->pretty_print_array($columns), $this->getStub('casts'));
58
        }
59
        $columns = $this->dateColumns($this->model->columns());
60
        if (! empty($columns)) {
61
            $properties .= PHP_EOL.str_replace('[]', $this->pretty_print_array($columns, false), $this->getStub('dates'));
62
        }
63
64
        return trim($properties);
65
    }
66
67
    private function buildRelationships()
68
    {
69
        $columns = array_filter($this->model->columns(), function (Column $column) {
70
            return Str::endsWith($column->name(), '_id');
71
        });
72
        if (empty($columns)) {
73
            return '';
74
        }
75
        $methods = '';
76
        $template = $this->getStub('method');
77
78
        foreach ($columns as $column) {
79
            $name = Str::substr($column->name(), 0, -3);
80
            $class = Str::studly($column->attributes()[0] ?? $name);
81
            $relationship = sprintf('$this->belongsTo(\\'.config('generators.model_namespace')."\%s::class)", $class);
82
            $method = str_replace('{{MethodName}}', Str::camel($name), $template);
83
            $method = str_replace('null', $relationship, $method);
84
            $methods .= PHP_EOL.$method;
85
        }
86
87
        return $methods;
88
    }
89
90
    private function fillableColumns(array $columns)
91
    {
92
        return array_diff(array_keys($columns), [
93
            'id',
94
            'password',
95
            'deleted_at',
96
            'created_at',
97
            'updated_at',
98
        ]);
99
    }
100
101
    private function castableColumns(array $columns)
102
    {
103
        return array_filter(array_map(
104
            function (Column $column) {
105
                return $this->castForColumn($column);
106
            },
107
            $columns
108
        ));
109
    }
110
111
    private function dateColumns(array $columns)
112
    {
113
        return array_map(
114
            function (Column $column) {
115
                return $column->name();
116
            },
117
            array_filter($columns, function (Column $column) {
118
                return stripos($column->dataType(), 'datetime') !== false
119
                    || stripos($column->dataType(), 'timestamp') !== false;
120
            })
121
        );
122
    }
123
124
    private function castForColumn(Column $column)
125
    {
126
        if (stripos($column->dataType(), 'integer')) {
127
            return 'integer';
128
        }
129
        if (in_array($column->dataType(), ['boolean', 'double', 'float'])) {
130
            return strtolower($column->dataType());
131
        }
132
        if (in_array($column->dataType(), ['decimal', 'unsignedDecimal'])) {
133
            if ($column->attributes()) {
134
                return 'decimal:'.$column->attributes()[1];
135
            }
136
137
            return 'decimal';
138
        }
139
    }
140
141
    private function pretty_print_array(array $data, $assoc = true)
142
    {
143
        $output = var_export($data, true);
144
        $output = preg_replace('/^\s+/m', '        ', $output);
145
        $output = preg_replace(['/^array\s\(/', "/\)$/"], ['[', '    ]'], $output);
146
        if (! $assoc) {
147
            $output = preg_replace('/^(\s+)[^=]+=>\s+/m', '$1', $output);
148
        }
149
150
        return trim($output);
151
    }
152
153
    private function getStub(string $stub)
154
    {
155
        static $stubs = [];
156
        if (empty($stubs[$stub])) {
157
            $stubs[$stub] = File::get(STUBS_PATH.'/model/'.$stub.'.stub');
158
        }
159
160
        return $stubs[$stub];
161
    }
162
163
    private function addTraits($stub)
164
    {
165
        if (! $this->model->usesSoftDeletes()) {
166
            return $stub;
167
        }
168
        $stub = str_replace('use Illuminate\\Database\\Eloquent\\Model;', 'use Illuminate\\Database\\Eloquent\\Model;'.PHP_EOL.'use Illuminate\\Database\\Eloquent\\SoftDeletes;', $stub);
169
        $stub = preg_replace('/^\\{$/m', '{'.PHP_EOL.'    use SoftDeletes;'.PHP_EOL, $stub);
170
171
        return $stub;
172
    }
173
}
174