Passed
Push — main ( a4aaf2...4acb8c )
by Mohammad
05:43 queued 02:51
created

Generator::resourceProperty()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 10
rs 10
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
    const REPOSITORY_OPTION = 'repository';
18
    const CONTROLLER_OPTION = 'controller';
19
    const MODEL_OPTION = 'model';
20
    const RESOURCE_OPTION = 'transformer';
21
    const POLICY_OPTION = 'policy';
22
    const REQUEST_OPTION = 'input';
23
24
    /**
25
     * The name and signature of the console command.
26
     *
27
     * @var string
28
     */
29
    protected $signature = 'generate:repository
30
    {name : Class (singular) for example User}
31
    {--base= : Base path to inject the files\folders in}
32
    {--f|force : force overwrite files}
33
    {--no-override : don\'t override any file}
34
    {--m|model : model only}
35
    {--c|controller : controller only}
36
    {--r|repository : repository only}
37
    {--t|transformer : transformers (API resources) only}
38
    {--p|policy : policy only}
39
    {--i|input : input validation (request file) only}';
40
41
    protected $description = 'Create repository files';
42
43
    protected string $modelName;
44
    protected string $userPath;
45
    // relative to project directory
46
    protected string $basePath;
47
    private GeneratorService $generator;
48
49
    private PathResolver $pathResolver;
50
51
    /**
52
     * Create a new command instance.
53
     */
54
    public function __construct(GeneratorService $generator)
55
    {
56
        parent::__construct();
57
        $this->generator = $generator;
58
    }
59
60
    /**
61
     * Execute the console command.
62
     */
63
    public function handle(): int
64
    {
65
        // if no file is specified, then generate them all
66
        if (!$this->option(self::REQUEST_OPTION) && !$this->option(self::CONTROLLER_OPTION)
67
            && !$this->option(self::REPOSITORY_OPTION) && !$this->option(self::RESOURCE_OPTION)
68
            && !$this->option(self::MODEL_OPTION) && !$this->option(self::POLICY_OPTION)
69
        ) {
70
            $this->input->setOption(self::MODEL_OPTION, true);
71
            $this->input->setOption(self::CONTROLLER_OPTION, true);
72
            $this->input->setOption(self::RESOURCE_OPTION, true);
73
            $this->input->setOption(self::REQUEST_OPTION, true);
74
            $this->input->setOption(self::REPOSITORY_OPTION, true);
75
            $this->input->setOption(self::POLICY_OPTION, true);
76
        }
77
78
        $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

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