Completed
Pull Request — master (#13)
by Andrea Marco
05:42
created

MakeTransformerCommand::getDefaultNamespace()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Rexlabs\Laravel\Smokescreen\Console;
4
5
use Illuminate\Console\GeneratorCommand;
6
use Illuminate\Contracts\View\Factory;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Filesystem\Filesystem;
9
10
class MakeTransformerCommand extends GeneratorCommand
11
{
12
    /**
13
     * The name and signature of the console command.
14
     * make:transformer User
15
     *
16
     * @var string
17
     */
18
    protected $signature = 'make:transformer
19
        {model? : The name of the model to transform. e.g. User} 
20
        {--f|force : Overwrite an existing transformer}
21
        {--a|all= : Generate a transformer for all models. You can optionally specify the models directory}';
22
23
    /**
24
     * The console command description.
25
     *
26
     * @var string
27
     */
28
    protected $description = 'Create a new smokescreen transformer class';
29
30
    /**
31
     * The view factory.
32
     *
33
     * @var \Illuminate\Contracts\View\Factory
34
     */
35
    protected $viewFactory;
36
37
    /**
38
     * Inject the dependencies.
39
     *
40
     * @param \Illuminate\Filesystem\Filesystem  $files
41
     * @param \Illuminate\Contracts\View\Factory $viewFactory
42
     */
43
    public function __construct(
44
        Filesystem $files,
45
        Factory $viewFactory
46
    ) {
47
        parent::__construct($files);
48
49
        $this->viewFactory = $viewFactory;
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function handle()
56
    {
57
        $model = $this->getModelName();
58
        $this->type = "{$model} transformer";
59
60
        if (is_null($this->argument('model'))) {
0 ignored issues
show
introduced by
The condition is_null($this->argument('model')) is always false.
Loading history...
61
            $this->generateAllTransformers();
62
        } elseif (!class_exists($this->getModelClass())) {
63
            $this->error("The model [{$model}] does not exist.");
64
        } elseif (class_exists($this->getTransformerClass()) && !$this->option('force')) {
65
            $this->warn("{$this->type} already exists.");
66
        } else {
67
            parent::handle();
68
        }
69
    }
70
71
    /**
72
     * Generate a transformer for every model.
73
     *
74
     * @return void
75
     */
76
    protected function generateAllTransformers() : void
77
    {
78
        $directory = $this->getModelsDirectory();
79
        $models = (new ModelsFinder)->findInDirectory($directory);
80
81
        foreach ($models as $model) {
82
            $this->call('make:transformer', [
83
                'model' => class_basename($model),
84
                '--force' => $this->option('force'),
85
            ]);
86
        }
87
    }
88
89
    /**
90
     * Retrieve the models directory.
91
     *
92
     * @return string
93
     */
94
    protected function getModelsDirectory() : string
95
    {
96
        $relativePath = $this->option('all') ?: config('smokescreen.models_directory');
97
98
        if (!file_exists($absolutePath = base_path($relativePath))) {
99
            exit($this->error("The specified models directory does not exist: {$absolutePath}"));
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return string. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
Bug introduced by
Are you sure the usage of $this->error('The specif...exist: '.$absolutePath) targeting Illuminate\Console\Command::error() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
100
        }
101
102
        return $absolutePath;
103
    }
104
105
    /**
106
     * {@inheritdoc}
107
     */
108
    protected function getStub()
109
    {
110
        return 'smokescreen::transformer';
111
    }
112
113
    /**
114
     * {@inheritdoc}
115
     */
116
    protected function buildClass($name)
117
    {
118
        return $this->viewFactory->make($this->getStub(), $this->getTemplateData())
119
            ->render();
120
    }
121
122
    /**
123
     * @throws \ReflectionException
124
     *
125
     * @return array
126
     */
127
    protected function getTemplateData()
128
    {
129
        $modelInspector = new ModelMapper($this->getModel());
130
131
        return [
132
            'model' => $this->getModel(),
133
            'modelClass' => $this->getModelClass(),
134
            'modelNamespace' => $this->getModelNamespace(),
135
            'modelName' => $this->getModelName(),
136
            'transformerClass' => $this->getTransformerClass(),
137
            'transformerNamespace' => $this->getTransformerNamespace(),
138
            'transformerName' => $this->getTransformerName(),
139
            'includes' => $modelInspector->getIncludes(),
140
            'properties' => $modelInspector->getDeclaredProperties(),
141
            'defaultProperties' => $modelInspector->getDefaultProperties(),
142
        ];
143
    }
144
145
    /**
146
     * {@inheritdoc}
147
     */
148
    protected function getNameInput()
149
    {
150
        return $this->getTransformerClass();
151
    }
152
153
    /**
154
     * Get the transformer class name.
155
     *
156
     * @return string
157
     */
158
    protected function getTransformerName()
159
    {
160
        return preg_replace(
161
            '/{ModelName}/i',
162
            $this->getModelName(),
163
            config('smokescreen.transformer_name', '{ModelName}Transformer')
164
        );
165
    }
166
167
    /**
168
     * Retrieve the transformer namespace.
169
     *
170
     * @return \Illuminate\Config\Repository|mixed
171
     */
172
    protected function getTransformerNamespace()
173
    {
174
        return config('smokescreen.transformer_namespace', 'App\Transformers');
175
    }
176
177
    /**
178
     * Retrieve the transformer class including namespace.
179
     *
180
     * @return string
181
     */
182
    protected function getTransformerClass()
183
    {
184
        return $this->getTransformerNamespace() . '\\' . $this->getTransformerName();
0 ignored issues
show
Bug introduced by
Are you sure $this->getTransformerNamespace() of type Illuminate\Config\Repository|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

184
        return /** @scrutinizer ignore-type */ $this->getTransformerNamespace() . '\\' . $this->getTransformerName();
Loading history...
185
    }
186
187
    /**
188
     * Retrieve the model class including namespace.
189
     *
190
     * @return string
191
     */
192
    protected function getModelClass(): string
193
    {
194
        $directory = config('smokescreen.models_directory', 'app/');
195
        $file = str_finish($directory, '/') . $this->getModelName();
196
        $segments = array_map('ucfirst', explode('/', $file));
197
198
        return implode('\\', $segments);
199
    }
200
201
    /**
202
     * Get the eloquent model instance.
203
     *
204
     * @return Model
205
     */
206
    protected function getModel(): Model
207
    {
208
        $class = $this->getModelClass();
209
210
        return new $class();
211
    }
212
213
    /**
214
     * Retrieve the model class name.
215
     *
216
     * @return string
217
     */
218
    protected function getModelName(): string
219
    {
220
        return ucfirst($this->argument('model'));
0 ignored issues
show
Bug introduced by
It seems like $this->argument('model') can also be of type array; however, parameter $str of ucfirst() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

220
        return ucfirst(/** @scrutinizer ignore-type */ $this->argument('model'));
Loading history...
221
    }
222
223
    /**
224
     * Get the namespace of the model class.
225
     *
226
     * @return string
227
     */
228
    protected function getModelNamespace()
229
    {
230
        return $this->getNamespace($this->getModelClass());
231
    }
232
}
233