Generate::interfacePath()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 1
1
<?php
2
3
namespace OzanAkman\RepositoryGenerator\Console\Commands;
4
5
use Illuminate\Console\Command;
6
use OzanAkman\RepositoryGenerator\Exceptions\FileException;
7
use OzanAkman\RepositoryGenerator\Exceptions\StubException;
8
9
class Generate extends Command
10
{
11
    /**
12
     * The name and signature of the console command.
13
     *
14
     * @var string
15
     */
16
    protected $signature = 'repositories:generate';
17
18
    /**
19
     * The console command description.
20
     *
21
     * @var string
22
     */
23
    protected $description = 'Quickly generating repository and interfaces from existing model files';
24
25
    /**
26
     * Overriding existing files.
27
     *
28
     * @var bool
29
     */
30
    protected $override = false;
31
32
    /**
33
     * Execute the console command.
34
     *
35
     * @throws FileException
36
     * @return void
37
     */
38
    public function handle()
39
    {
40
        // Check repository folder permissions.
41
        $this->checkRepositoryPermissions();
42
43
        // Create repository folder if it's necessary.
44
        $this->createFolder(config('repository-generator.repository_directory'));
45
46
        // Check interface folder permissions.
47
        $this->checkInterfacePermissions();
48
49
        // Create interface folder if it's necessary.
50
        $this->createFolder(config('repository-generator.interface_directory'));
51
52
        // Get all model file names.
53
        $models = $this->getModels();
54
55
        // Check model files.
56
        if (count($models) === 0) {
57
            $this->noModelsMessage();
58
        }
59
60
        // Get existing repository file names.
61
        $existingRepositoryFiles = glob($this->repositoryPath('*.php'));
62
63
        // Remove main repository file name from array
64
        $existingRepositoryFiles = array_diff(
65
            $existingRepositoryFiles,
66
            [$this->repositoryPath(config('repository-generator.main_repository_file'))]
67
        );
68
69
        // Ask for overriding, If there are files in repository directory.
70
        if (count($existingRepositoryFiles) > 0) {
71
            if ($this->confirm('Do you want to overwrite the existing files? (Yes/No):')) {
72
                $this->override = true;
73
            }
74
        }
75
76
        // Get existing interface file names.
77
        $existingInterfaceFiles = glob($this->interfacePath('*.php'));
78
79
        // Remove main interface file from array
80
        $existingInterfaceFiles = array_diff(
81
            $existingInterfaceFiles,
82
            [$this->repositoryPath(config('repository-generator.main_interface_file'))]
83
        );
84
85
        // Ask for overriding, If there are files in interface repository.
86
        // It could be already asked while checking repository files.
87
        // If so, we won't show this confirm question again.
88
        if (count($existingInterfaceFiles) > 0 && ! $this->override) {
89
            if ($this->confirm('Do you want to overwrite the existing files? (Yes/No):')) {
90
                $this->override = true;
91
            }
92
        }
93
94
        // Get stub file templates.
95
        $repositoryStub = $this->getStub('Repository');
96
        $interfaceStub = $this->getStub('Interface');
97
98
        // Repository stub values those should be changed by command.
99
        $repositoryStubValues = [
100
            '__USE_STATEMENT_FOR_REPOSITORY__',
101
            '__REPOSITORY_NAMESPACE__',
102
            '__MAIN_REPOSITORY__',
103
            '__REPOSITORY__',
104
            '__MODEL_NAMESPACE_',
105
            '__MODEL__',
106
            '__INTERFACE_NAMESPACE_',
107
            '__INTERFACE__',
108
        ];
109
110
        // Interface stub values those should be changed by command.
111
        $interfaceStubValues = [
112
            '__USE_STATEMENT_FOR_INTERFACE__',
113
            '__INTERFACE_NAMESPACE__',
114
            '__MAIN_INTERFACE__',
115
            '__INTERFACE__',
116
        ];
117
118
        foreach ($models as $model) {
119
120
            // Add suffixes
121
            $repository = suffix($model, 'Repository');
122
            $interface = suffix($model, 'RepositoryInterface');
123
124
            // Current repository file name
125
            $repositoryFile = $this->repositoryPath($repository.'.php');
126
127
            // Check main repository file's path to add use
128
            $useStatementForRepository = false;
129
            if (dirname($repositoryFile) !== dirname(config('repository-generator.main_repository_file'))
130
            ) {
131
                $mainRepository = config('repository-generator.main_repository_class');
132
                $useStatementForRepository = 'use '.$mainRepository.';';
133
            }
134
135
            // Fillable repository values for generating real files
136
            $repositoryValues = [
137
                $useStatementForRepository ? $useStatementForRepository : '',
138
                config('repository-generator.repository_namespace'),
139
                str_replace('.php', '', config('repository-generator.main_repository_file')),
140
                $repository,
141
                config('repository-generator.model_namespace'),
142
                $model,
143
                config('repository-generator.interface_namespace'),
144
                $interface,
145
            ];
146
147
            // Generate body of the repository file
148
            $repositoryContent = str_replace(
149
                $repositoryStubValues,
150
                $repositoryValues,
151
                $repositoryStub);
152
153
            if (in_array($repositoryFile, $existingRepositoryFiles)) {
154
                if ($this->override) {
155
                    $this->writeFile($repositoryFile, $repositoryContent);
156
                    $this->info('Overridden repository file: '.$repository);
157
                }
158
            } else {
159
                $this->writeFile($repositoryFile, $repositoryContent);
160
                $this->info('Created repository file: '.$repository);
161
            }
162
163
            // Current interface file name
164
            $interfaceFile = $this->interfacePath($interface.'.php');
165
166
            // Check main repository file's path to add use
167
            $useStatementForInterface = false;
168
            if (dirname($interfaceFile) !== dirname(config('repository-generator.main_interface_file'))
169
            ) {
170
                $mainInterface = config('repository-generator.main_interface_class');
171
                $useStatementForInterface = 'use '.$mainInterface.';';
172
            }
173
174
            // Fillable interface values for generating real files
175
            $interfaceValues = [
176
                $useStatementForInterface ? $useStatementForInterface : '',
177
                config('repository-generator.interface_namespace'),
178
                str_replace('.php', '', config('repository-generator.main_interface_file')),
179
                $interface,
180
            ];
181
182
            // Generate body of the interface file
183
            $interfaceContent = str_replace(
184
                $interfaceStubValues,
185
                $interfaceValues,
186
                $interfaceStub);
187
188
            if (in_array($interfaceFile, $existingInterfaceFiles)) {
189
                if ($this->override) {
190
                    $this->writeFile($interfaceFile, $interfaceContent);
191
                    $this->info('Overridden interface file: '.$interface);
192
                }
193
            } else {
194
                $this->writeFile($interfaceFile, $interfaceContent);
195
                $this->info('Created interface file: '.$interface);
196
            }
197
        }
198
    }
199
200
    /**
201
     * Get all model names from models directory.
202
     *
203
     * @return array|mixed
204
     */
205
    private function getModels()
206
    {
207
        $modelDirectory = config('repository-generator.model_directory');
208
        $models = glob($modelDirectory.'*');
209
        $models = str_replace([$modelDirectory, '.php'], '', $models);
210
211
        return $models;
212
    }
213
214
    /**
215
     * Get stub content.
216
     *
217
     * @param $file
218
     * @return bool|string
219
     * @throws StubException
220
     */
221
    private function getStub($file)
222
    {
223
        $stub = __DIR__.'/../Stubs/'.$file.'.stub';
224
225
        if (file_exists($stub)) {
226
            return file_get_contents($stub);
227
        }
228
229
        throw StubException::fileNotFound($file);
230
    }
231
232
    /**
233
     * Get repository path.
234
     *
235
     * @param null $path
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $path is correct as it would always require null to be passed?
Loading history...
236
     * @return string
237
     */
238
    private function repositoryPath($path = null)
239
    {
240
        return config('repository-generator.repository_directory').$path;
241
    }
242
243
    /**
244
     * Get interface path.
245
     *
246
     * @param null $path
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $path is correct as it would always require null to be passed?
Loading history...
247
     * @return string
248
     */
249
    private function interfacePath($path = null)
250
    {
251
        return config('repository-generator.interface_directory').$path;
252
    }
253
254
    /**
255
     * Get parent path of repository of interface folder.
256
     *
257
     * @param string $child
258
     * @return string
259
     */
260
    private function parentPath($child = 'repository')
261
    {
262
        $childPath = $child.'Path';
263
        $childPath = $this->$childPath();
264
265
        return dirname($childPath);
266
    }
267
268
    /**
269
     * Generate/override a file.
270
     *
271
     * @param $file
272
     * @param $content
273
     */
274
    private function writeFile($file, $content)
275
    {
276
        file_put_contents($file, $content);
277
    }
278
279
    /**
280
     * Check repository folder permissions.
281
     *
282
     * @throws FileException
283
     */
284 View Code Duplication
    private function checkRepositoryPermissions()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
285
    {
286
        // Get full path of repository directory.
287
        $repositoryPath = $this->repositoryPath();
288
289
        // Get parent directory of repository path.
290
        $repositoryParentPath = $this->parentPath('repository');
291
292
        // Check parent of repository directory is writable.
293
        if (! file_exists($repositoryPath) && ! is_writable($repositoryParentPath)) {
294
            throw FileException::notWritableDirectory($repositoryParentPath);
295
        }
296
297
        // Check repository directory permissions.
298
        if (file_exists($repositoryPath) && ! is_writable($repositoryPath)) {
299
            throw FileException::notWritableDirectory($repositoryPath);
300
        }
301
    }
302
303
    /**
304
     * Check interface folder permissions.
305
     *
306
     * @throws FileException
307
     */
308 View Code Duplication
    private function checkInterfacePermissions()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
309
    {
310
        // Get full path of interface directory.
311
        $interfacePath = $this->interfacePath();
312
313
        // Get parent directory of interface path.
314
        $interfaceParentPath = $this->parentPath('interface');
315
316
        // Check parent of interface directory is writable.
317
        if (! file_exists($interfacePath) && ! is_writable($interfaceParentPath)) {
318
            throw FileException::notWritableDirectory($interfaceParentPath);
319
        }
320
321
        // Check repository directory permissions.
322
        if (file_exists($interfacePath) && ! is_writable($interfacePath)) {
323
            throw FileException::notWritableDirectory($interfacePath);
324
        }
325
    }
326
327
    private function createFolder($folder)
328
    {
329
        if (! file_exists($folder)) {
330
            mkdir($folder);
331
        }
332
    }
333
334
    /**
335
     * Show message and stop script, If there are no model files to work.
336
     */
337
    private function noModelsMessage()
338
    {
339
        $this->warn('Repository generator has stopped!');
340
        $this->line(
341
            'There are no model files to use in directory: "'
342
            .config('repository-generator.model_directory')
343
            .'"'
344
        );
345
        exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method noModelsMessage() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
346
    }
347
}
348