Passed
Pull Request — main (#11)
by Angel
02:51
created

Generator::getDefaultFileGeneration()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 0
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Shamaseen\Repository\Commands;
4
5
use Illuminate\Console\Command;
6
use Illuminate\Support\Facades\Config;
7
use Illuminate\Support\Str;
8
use Shamaseen\Generator\Generator as GeneratorService;
9
use Shamaseen\Repository\Events\RepositoryFilesGenerated;
10
use Shamaseen\Repository\PathResolver;
11
12
/**
13
 * Class RepositoryGenerator.
14
 */
15
class Generator extends Command
16
{
17
    public const REPOSITORY_OPTION = 'repository';
18
    public const CONTROLLER_OPTION = 'controller';
19
    public const MODEL_OPTION = 'model';
20
    public const RESOURCE_OPTION = 'transformer';
21
    public const POLICY_OPTION = 'policy';
22
    public const REQUEST_OPTION = 'input';
23
    public const TEST_OPTION = 'test';
24
25
    /**
26
     * The name and signature of the console command.
27
     *
28
     * @var string
29
     */
30
    protected $signature = 'generate:repository
31
    {name : Class (singular) for example User}
32
    {--base= : Base path to inject the files\folders in}
33
    {--f|force : force overwrite files}
34
    {--no-override : don\'t override any file}
35
    {--m|model : model only}
36
    {--c|controller : controller only}
37
    {--r|repository : repository only}
38
    {--t|transformer : transformers (API resources) only}
39
    {--p|policy : policy only}
40
    {--test : test only}
41
    {--i|input : input validation (request file) only}';
42
43
    protected $description = 'Create repository files';
44
45
    protected string $modelName;
46
    protected string $userPath;
47
    // relative to project directory
48
    protected string $basePath;
49
    private GeneratorService $generator;
50
51
    private PathResolver $pathResolver;
52
53
    /**
54
     * Create a new command instance.
55
     */
56
    public function __construct(GeneratorService $generator)
57
    {
58
        parent::__construct();
59
        $this->generator = $generator;
60
    }
61
62
    /**
63
     * Execute the console command.
64
     */
65
    public function handle(): int
66
    {
67
        // if no file is specified, then generate them all
68
        if (!$this->option(self::REQUEST_OPTION) && !$this->option(self::CONTROLLER_OPTION)
69
            && !$this->option(self::REPOSITORY_OPTION) && !$this->option(self::RESOURCE_OPTION)
70
            && !$this->option(self::MODEL_OPTION) && !$this->option(self::POLICY_OPTION)
71
            && !$this->option(self::TEST_OPTION)
72
        ) {
73
            $options = $this->getFileGeneration();
74
            foreach ($options as $option) {
75
                $this->input->setOption($option, true);
76
            }
77
        }
78
79
        $paths = preg_split(' ([/\\\]) ', $this->argument('name'));
0 ignored issues
show
Bug introduced by
It seems like $this->argument('name') can also be of type array; however, parameter $subject of preg_split() 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

79
        $paths = preg_split(' ([/\\\]) ', /** @scrutinizer ignore-type */ $this->argument('name'));
Loading history...
80
81
        if (!$paths) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $paths of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
82
            $this->error('Name argument is not correct.');
83
84
            return self::FAILURE;
85
        }
86
87
        $this->modelName = array_pop($paths);
88
        $this->userPath = implode('/', str_replace('\\', '/', $paths));
89
        $this->basePath = $this->option('base') ? $this->option('base') : Config::get('repository.base_path');
90
91
        $this->pathResolver = new PathResolver($this->modelName, $this->userPath, $this->basePath);
92
93
        config(['generator.base_path' => base_path($this->basePath)]);
94
95
        return $this->makeRepositoryPatternFiles();
96
    }
97
98
    public function makeRepositoryPatternFiles(): int
99
    {
100
        // Parent Classes
101
        $modelParent = Config::get('repository.model_parent');
102
        $repositoryParent = Config::get('repository.repository_parent');
103
        $controllerParent = Config::get('repository.controller_parent');
104
        $requestParent = Config::get('repository.request_parent');
105
        $resourceParent = Config::get('repository.resource_parent');
106
        $collectionParent = Config::get('repository.collection_parent');
107
108
        if ($this->option(self::CONTROLLER_OPTION)) {
109
            $this->generate('Controller', $controllerParent);
110
        }
111
112
        if ($this->option(self::MODEL_OPTION)) {
113
            $this->generate('Model', $modelParent);
114
        }
115
116
        if ($this->option(self::REQUEST_OPTION)) {
117
            $this->generate('Request', $requestParent);
118
            $this->generate('Collection', $collectionParent);
119
        }
120
121
        if ($this->option(self::REPOSITORY_OPTION)) {
122
            $this->generate('Repository', $repositoryParent);
123
        }
124
125
        if ($this->option(self::RESOURCE_OPTION)) {
126
            $this->generate('Resource', $resourceParent);
127
        }
128
129
        if ($this->option(self::POLICY_OPTION)) {
130
            $this->generate('Policy');
131
        }
132
133
        if ($this->option(self::POLICY_OPTION)) {
134
            $this->generate('Test');
135
        }
136
137
        RepositoryFilesGenerated::dispatch($this->basePath, $this->userPath, $this->modelName);
138
139
        $this->dumpAutoload();
140
141
        return self::SUCCESS;
142
    }
143
144
    /**
145
     * @param string $type define which kind of files should be generated
146
     */
147
    protected function generate(string $type, string $parentClass = ''): bool
148
    {
149
        $outputPath = $this->pathResolver->outputPath($type);
150
151
        if (!$this->option('force') && $realpath = realpath($this->generator->absolutePath($outputPath))) {
152
            if ($this->option('no-override') || !$this->confirm('File '.$realpath.' exists, do you want to overwrite it?')) {
153
                return false;
154
            }
155
        }
156
157
        $namespace = $this->pathResolver->typeNamespace($type);
158
        $lcModelName = Str::lower($this->modelName);
159
        $lcPluralModelName = Str::plural($lcModelName);
160
        $snackLcPluralModelName = Str::snake($this->modelName);
161
162
        $this->generator->stub($this->pathResolver->getStubPath($type))
163
            ->replace('{{parentClass}}', $parentClass)
164
            ->replace('{{modelName}}', $this->modelName)
165
            ->replace('{{lcModelName}}', $lcModelName)
166
            ->replace('{{lcPluralModelName}}', $lcPluralModelName)
167
            ->replace('{{snackLcPluralModelName}}', $snackLcPluralModelName)
168
            ->replace('{{namespace}}', $namespace)
169
            ->replace('{{RequestsNamespace}}', $this->pathResolver->typeNamespace('Request'))
170
            ->replace('{{RepositoriesNamespace}}', $this->pathResolver->typeNamespace('Repository'))
171
            ->replace('{{ResourcesNamespace}}', $this->pathResolver->typeNamespace('Resource'))
172
            ->replace('{{ModelNamespace}}', $this->pathResolver->typeNamespace('Model'))
173
            ->replace('{{PoliciesNamespace}}', $this->pathResolver->typeNamespace('Policy'))
174
            ->replace('{{ResourcesProperties}}', $this->resourceProperty())
175
            ->replace('{{RequestProperty}}', $this->requestProperty())
176
            ->replace('{{PolicyProperty}}', $this->policyProperty())
177
            ->output($outputPath);
178
179
        return true;
180
    }
181
182
    public function resourceProperty(): string
183
    {
184
        $result = '';
185
186
        if ($this->option(self::RESOURCE_OPTION)) {
187
            $result .= "\n\t".'public ?string $resourceClass = '. $this->modelName .'Resource::class;'."\n";
188
            $result .= "\n\t".'public ?string $collectionClass = '. $this->modelName .'Collection::class;'."\n";
189
        }
190
191
        return $result;
192
    }
193
194
    public function requestProperty(): string
195
    {
196
        $result = '';
197
198
        if ($this->option(self::RESOURCE_OPTION)) {
199
            $result .= "\n\t".'public string $requestClass = '. $this->modelName .'Request::class;'."\n";
200
        }
201
202
        return $result;
203
    }
204
205
    public function policyProperty(): string
206
    {
207
        $result = '';
208
209
        if ($this->option(self::RESOURCE_OPTION)) {
210
            $result .= "\n\t".'public ?string $policyClass = '. $this->modelName .'Policy::class;'."\n";
211
        }
212
213
        return $result;
214
    }
215
216
    private function dumpAutoload(): void
217
    {
218
        shell_exec('composer dump-autoload');
219
    }
220
221
    public function getFileGeneration(): array
222
    {
223
        return config('repository.default_stubs');
224
    }
225
226
    /** @return string[] */
227
    public static function getDefaultFileGeneration(): array
228
    {
229
        return [
230
            self::REPOSITORY_OPTION,
231
            self::CONTROLLER_OPTION,
232
            self::MODEL_OPTION,
233
            self::RESOURCE_OPTION,
234
            self::POLICY_OPTION,
235
            self::REQUEST_OPTION,
236
237
        ];
238
    }
239
}
240