Passed
Pull Request — main (#8)
by Mohammad
13:44
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
    function resourceProperty(): string
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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
    function requestProperty(): string
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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
    function policyProperty(): string
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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