Completed
Push — dev ( 1153e7...459fc5 )
by Marc
02:46
created

ModelManager::prepareCurrentModel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 11
rs 9.4285
cc 1
eloc 8
nc 1
nop 0
1
<?php namespace Mascame\Artificer\Model;
2
3
use Illuminate\Contracts\Database\ModelIdentifier;
4
use View;
5
use Route;
6
use \Illuminate\Support\Str as Str;
7
use Mascame\Artificer\Options\AdminOption;
8
9
// Todo: get column type http://stackoverflow.com/questions/18562684/how-to-get-database-field-type-in-laravel
10
class ModelManager
11
{
12
13
    /**
14
     * @var ModelSchema
15
     */
16
    public $schema;
17
18
    /**
19
     * @var array
20
     */
21
    public $models;
22
23
    /**
24
     * @var array
25
     */
26
    public $columns;
27
28
    /**
29
     * @var \Illuminate\Database\Eloquent\Model
30
     */
31
    public $model;
32
33
    /**
34
     * @var string
35
     */
36
    public $class;
37
38
    /**
39
     * @var
40
     */
41
    public $name;
42
43
    /**
44
     * @var string
45
     */
46
    public $keyname;
47
48
    /**
49
     * @var
50
     */
51
    public $table;
52
53
    /**
54
     * @var
55
     */
56
    public $fillable;
57
58
    /**
59
     * @var array|mixed
60
     */
61
    protected $options = [];
62
    protected $defaultOptions = null;
63
64
    /**
65
     * @var array|mixed
66
     */
67
    public $relations = [];
68
69
    /**
70
     * @var
71
     */
72
    public static $current = null;
73
74
    /**
75
     * @param ModelSchema $schema
76
     */
77
    public function __construct(ModelSchema $schema)
78
    {
79
        $this->schema = $schema;
80
        $this->relations = new ModelRelation();
81
82
        if (Str::startsWith(Route::currentRouteName(), 'admin.model.')) {
83
            $this->prepareCurrentModel();
84
        }
85
86
        $this->share();
87
    }
88
89
90
    public function share()
91
    {
92
        View::share('tables', $this->schema->tables);
93
        View::share('models', $this->models = $this->getModelsData());
94
        View::share('model', $this->getCurrentModelData());
95
    }
96
97
    /**
98
     * @return array
99
     */
100
    private function getModelsData()
101
    {
102
        foreach ($this->schema->models as $modelName => $model) {
103
            $this->schema->models[$modelName]['options'] = $this->getOptions($modelName);
104
            $this->schema->models[$modelName]['hidden'] = $this->isHidden($modelName);
105
106
            $title = null;
0 ignored issues
show
Unused Code introduced by
$title is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
107
            if (isset($this->schema->models[$modelName]['title'])) {
108
                $title = $this->schema->models[$modelName]['title'];
109
            } else {
110
                $title = Str::title(
111
                  str_replace('_', ' ', $this->schema->models[$modelName]['table'])
112
                );
113
            }
114
115
            $this->schema->models[$modelName]['title'] = $title;
116
        }
117
118
        return $this->schema->models;
119
    }
120
121
    /**
122
     * @param $modelName
123
     * @return bool
124
     */
125
    public function isHidden($modelName)
126
    {
127
        return in_array($modelName, config('admin.model.hidden'));
128
    }
129
130
    /**
131
     * @return bool
132
     */
133
    public function hasGuarded()
134
    {
135
        return ! empty($this->getGuarded());
136
    }
137
138
    /**
139
     * Look for admin model config, if there is nothing fallback to Model property
140
     *
141
     * @return array|mixed
142
     */
143
    public function getGuarded()
144
    {
145
        return $this->getOption('guarded', $this->model->getGuarded());
146
    }
147
148
    /**
149
     * Look for admin model config, if there is nothing fallback to Model property
150
     *
151
     * @return array|mixed
152
     */
153
    public function getFillable()
154
    {
155
        $fillable = $this->getOption('fillable', $this->model->getFillable());
156
157
        if ($fillable == ['*']) {
158
            $fillable = array_diff($this->columns, $this->getGuarded());
159
        }
160
161
        return $fillable;
162
    }
163
164
    /**
165
     * @return bool
166
     */
167
    public function hasFillable()
168
    {
169
        return ! empty($this->getFillable());
170
    }
171
172
    /**
173
     * @return int|null|string
174
     */
175
    private function getCurrentModelName()
176
    {
177
        if ($this->name) return $this->name;
178
179
        foreach ($this->schema->models as $modelName => $model) {
180
            if ($this->isCurrent($modelName)) {
181
                $this->setCurrent($modelName);
182
183
                return $this->name = $modelName;
184
            }
185
        }
186
187
        return null;
188
    }
189
190
    protected function prepareCurrentModel()
191
    {
192
        $this->name = $this->getCurrentModelName();
193
        $this->class = $this->schema->getClass($this->name);
194
        $this->model = $this->schema->getInstance($this->name);
0 ignored issues
show
Bug introduced by
It seems like $this->name can also be of type integer or string; however, Mascame\Artificer\Model\ModelSchema::getInstance() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
195
        $this->table = $this->model->getTable();
196
        $this->columns = $this->schema->getColumns($this->table);
197
        $this->fillable = $this->model->getFillable();
198
199
        $this->addFieldOptions($this->columns);
200
    }
201
202
    /**
203
     * Fills all fields in config if they are not declared and applies default attributes
204
     *
205
     * @param $columns
206
     * @param null $model
207
     * @return mixed
208
     */
209
    protected function addFieldOptions($columns, $model = null) {
210
        $model = ($model) ? $model : $this->name;
211
212
        $this->getOptions($model);
0 ignored issues
show
Bug introduced by
It seems like $model defined by $model ? $model : $this->name on line 210 can also be of type integer or string; however, Mascame\Artificer\Model\ModelManager::getOptions() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
213
214
        foreach ($columns as $column) {
215
            if (! isset($this->options[$model]['fields'][$column])) {
216
                $this->options[$model]['fields'][$column] = [];
217
            }
218
219
            if (! isset($this->options[$model]['fields'][$column]['attributes'])) {
220
                $this->options[$model]['fields'][$column]['attributes'] = $this->options[$model]['attributes'];
221
            }
222
        }
223
    }
224
225
    /**
226
     * @return array
227
     */
228
    private function getCurrentModelData()
229
    {
230
        return array(
231
            'class' => $this->class,
232
            'name' => $this->getCurrentModelName(),
233
            'route' => $this->getRouteName(),
234
            'table' => $this->table,
235
            'columns' => $this->schema->columns,
236
            'fillable' => $this->fillable,
237
            'hidden' => $this->isHidden($this->name),
238
        );
239
    }
240
241
    /**
242
     * @param $model
243
     * @return bool
244
     */
245
    protected function isCurrent($modelName)
246
    {
247
        if ( ! Route::current()) return null;
248
        
249
        $slug = Route::current()->parameter('slug');
250
251
        return (isset($this->schema->models[$modelName]['route']) && $this->schema->models[$modelName]['route'] == $slug);
252
    }
253
254
    /**
255
     * @return ModelManager
256
     */
257
    public static function getCurrent()
258
    {
259
        return (isset(self::$current)) ? self::$current : null;
260
    }
261
262
    /**
263
     * @param null $model
264
     * @return null
265
     */
266
    public function getRouteName($model = null)
267
    {
268
        if ($model) return $this->schema->models[$model]['route'];
269
270
        return (isset($this->schema->models[self::$current]['route'])) ? $this->schema->models[self::$current]['route'] : null;
271
    }
272
273
    /**
274
     * @param $modelName
275
     */
276
    protected function setCurrent($modelName)
277
    {
278
        self::$current = $modelName;
279
//        ModelOption::set('current', $modelName);
280
    }
281
282
    /**
283
     * @param null $model
284
     * @return mixed
285
     */
286
    public function getOptions($model = null)
287
    {
288
        $model = ($model) ? $model : $this->name;
289
290
        if (isset($this->options[$model])) return $this->options[$model];
291
292
        return $this->options[$model] = array_merge(
293
            $this->getDefaultOptions(),
294
            config('admin.models.' . $model, [])
295
        );
296
    }
297
298
    public function getDefaultOptions()
299
    {
300
        if ($this->defaultOptions) return $this->defaultOptions;
301
302
        return $this->defaultOptions = config('admin.model.default');
303
    }
304
305
    /**
306
     * Take care! This are the options reflected in config files.
307
     * Processed guarded/fillable should used with their own getters.
308
     *
309
     * @param $key
310
     * @param null $model
311
     * @return mixed
312
     */
313
    public function getOption($key, $default = null, $model = null)
314
    {
315
        $model = ($model) ? $model : $this->name;
316
        $options = $this->getOptions($model);
0 ignored issues
show
Bug introduced by
It seems like $model defined by $model ? $model : $this->name on line 315 can also be of type integer or string; however, Mascame\Artificer\Model\ModelManager::getOptions() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
317
318
        return (isset($options[$key])) ? $options[$key] : $default;
319
    }
320
321
    /**
322
     * @return array|mixed
323
     */
324
    public function getRelations()
325
    {
326
        return $this->relations->get();
327
    }
328
329
}