• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

RonasIT / laravel-entity-generator / 13150891945

05 Feb 2025 05:29AM UTC coverage: 90.022% (+1.6%) from 88.395%
13150891945

Pull #81

github

web-flow
Merge dff470277 into 882d04c57
Pull Request #81: Add service provider tests

830 of 922 relevant lines covered (90.02%)

4.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

15.31
/src/Commands/MakeEntityCommand.php
1
<?php
2

3
namespace RonasIT\Support\Commands;
4

5
use Illuminate\Console\Command;
6
use Illuminate\Support\Arr;
7
use Illuminate\Support\Facades\Config;
8
use Illuminate\Support\Str;
9
use RonasIT\Support\Events\SuccessCreateMessage;
10
use RonasIT\Support\Events\WarningEvent;
11
use RonasIT\Support\Exceptions\ClassNotExistsException;
12
use RonasIT\Support\Exceptions\EntityCreateException;
13
use RonasIT\Support\Generators\ControllerGenerator;
14
use RonasIT\Support\Generators\EntityGenerator;
15
use RonasIT\Support\Generators\FactoryGenerator;
16
use RonasIT\Support\Generators\MigrationGenerator;
17
use RonasIT\Support\Generators\ModelGenerator;
18
use RonasIT\Support\Generators\NovaResourceGenerator;
19
use RonasIT\Support\Generators\NovaTestGenerator;
20
use RonasIT\Support\Generators\RepositoryGenerator;
21
use RonasIT\Support\Generators\RequestsGenerator;
22
use RonasIT\Support\Generators\ResourceGenerator;
23
use RonasIT\Support\Generators\ServiceGenerator;
24
use RonasIT\Support\Generators\TestsGenerator;
25
use RonasIT\Support\Generators\TranslationsGenerator;
26
use RonasIT\Support\Generators\SeederGenerator;
27
use Illuminate\Contracts\Events\Dispatcher as EventDispatcher;
28
use UnexpectedValueException;
29

30
/**
31
 * @property ControllerGenerator $controllerGenerator
32
 * @property MigrationGenerator $migrationGenerator
33
 * @property ModelGenerator $modelGenerator
34
 * @property RepositoryGenerator $repositoryGenerator
35
 * @property RequestsGenerator $requestsGenerator
36
 * @property ServiceGenerator $serviceGenerator
37
 * @property FactoryGenerator $factoryGenerator
38
 * @property TestsGenerator $testGenerator
39
 * @property TranslationsGenerator $translationsGenerator
40
 * @property SeederGenerator $seederGenerator
41
 * @property ResourceGenerator $resourceGenerator
42
 * @property NovaResourceGenerator $novaResourceGenerator
43
 * @property NovaTestGenerator $novaTestGenerator
44
 * @property EventDispatcher $eventDispatcher
45
 */
46
class MakeEntityCommand extends Command
47
{
48
    const CRUD_OPTIONS = [
49
        'C', 'R', 'U', 'D'
50
    ];
51

52
    /**
53
     * The name and signature of the console command.
54
     *
55
     * @var string
56
     */
57
    protected $signature = 'make:entity {name : The name of the entity. This name will use as name of models class.}
58
        
59
        {--only-api : Set this flag if you want to create resource, controller, route, requests, tests.}
60
        {--only-entity : Set this flag if you want to create migration, model, repository, service, factory, seeder.}
61
        {--only-model : Set this flag if you want to create only model. This flag is a higher priority than --only-migration, --only-tests and --only-repository.} 
62
        {--only-repository : Set this flag if you want to create only repository. This flag is a higher priority than --only-tests and --only-migration.}
63
        {--only-service : Set this flag if you want to create only service.}
64
        {--only-resource : Set this flag if you want to create only resource.}
65
        {--only-controller : Set this flag if you want to create only controller.}
66
        {--only-requests : Set this flag if you want to create only requests.}
67
        {--only-migration : Set this flag if you want to create only repository. This flag is a higher priority than --only-tests.}
68
        {--only-factory : Set this flag if you want to create only factory.}
69
        {--only-tests : Set this flag if you want to create only tests.}
70
        {--only-seeder : Set this flag if you want to create only seeder.}
71
        {--only-nova-resource : Set this flag if you want to create only nova resource.}
72
        {--only-nova-tests : Set this flag if you want to create only nova resource tests.}
73

74
        {--methods=CRUD : Set types of methods to create. Affect on routes, requests classes, controller\'s methods and tests methods.} 
75

76
        {--i|integer=* : Add integer field to entity.}
77
        {--I|integer-required=* : Add required integer field to entity. If you want to specify default value you have to do it manually.}
78
        {--f|float=* : Add float field to entity.}
79
        {--F|float-required=* : Add required float field to entity. If you want to specify default value you have to do it manually.}
80
        {--s|string=* : Add string field to entity. Default type is VARCHAR(255) but you can change it manually in migration.}
81
        {--S|string-required=* : Add required string field to entity. If you want to specify default value ir size you have to do it manually.}
82
        {--b|boolean=* : Add boolean field to entity.}
83
        {--B|boolean-required=* : Add boolean field to entity. If you want to specify default value you have to do it manually.}
84
        {--t|timestamp=* : Add timestamp field to entity.}
85
        {--T|timestamp-required=* : Add timestamp field to entity. If you want to specify default value you have to do it manually.}
86
        {--j|json=* : Add json field to entity.}
87
        
88
        {--a|has-one=* : Set hasOne relations between you entity and existed entity.}
89
        {--A|has-many=* : Set hasMany relations between you entity and existed entity.}
90
        {--e|belongs-to=* : Set belongsTo relations between you entity and existed entity.}
91
        {--E|belongs-to-many=* : Set belongsToMany relations between you entity and existed entity.}';
92

93
    /**
94
     * The console command description.
95
     *
96
     * @var string
97
     */
98
    protected $description = 'Make entity with Model, Repository, Service, Migration, Controller, Resource and Nova Resource.';
99

100
    protected $controllerGenerator;
101
    protected $migrationGenerator;
102
    protected $modelGenerator;
103
    protected $repositoryGenerator;
104
    protected $requestsGenerator;
105
    protected $serviceGenerator;
106
    protected $factoryGenerator;
107
    protected $testGenerator;
108
    protected $translationsGenerator;
109
    protected $seederGenerator;
110
    protected $resourceGenerator;
111
    protected $novaResourceGenerator;
112
    protected $novaTestGenerator;
113
    protected $eventDispatcher;
114

115
    protected $rules = [
116
        'only' => [
117
            'only-api' => [ResourceGenerator::class, ControllerGenerator::class, RequestsGenerator::class, TestsGenerator::class],
118
            'only-entity' => [MigrationGenerator::class, ModelGenerator::class, ServiceGenerator::class, RepositoryGenerator::class, FactoryGenerator::class, SeederGenerator::class],
119
            'only-model' => [ModelGenerator::class],
120
            'only-repository' => [RepositoryGenerator::class],
121
            'only-service' => [ServiceGenerator::class],
122
            'only-resource' => [ResourceGenerator::class],
123
            'only-controller' => [ControllerGenerator::class],
124
            'only-requests' => [RequestsGenerator::class],
125
            'only-migration' => [MigrationGenerator::class],
126
            'only-factory' => [FactoryGenerator::class],
127
            'only-tests' => [FactoryGenerator::class, TestsGenerator::class],
128
            'only-seeder' => [SeederGenerator::class],
129
            'only-nova-resource' => [NovaResourceGenerator::class],
130
            'only-nova-tests' => [NovaTestGenerator::class]
131
        ]
132
    ];
133

134
    public $generators = [
135
        ModelGenerator::class, RepositoryGenerator::class, ServiceGenerator::class, RequestsGenerator::class,
136
        ResourceGenerator::class, ControllerGenerator::class, MigrationGenerator::class, FactoryGenerator::class,
137
        TestsGenerator::class, TranslationsGenerator::class, SeederGenerator::class, NovaResourceGenerator::class,
138
        NovaTestGenerator::class
139
    ];
140

141
    public function __construct()
142
    {
143
        parent::__construct();
1✔
144

145
        $this->controllerGenerator = app(ControllerGenerator::class);
1✔
146
        $this->migrationGenerator = app(MigrationGenerator::class);
1✔
147
        $this->modelGenerator = app(ModelGenerator::class);
1✔
148
        $this->repositoryGenerator = app(RepositoryGenerator::class);
1✔
149
        $this->requestsGenerator = app(RequestsGenerator::class);
1✔
150
        $this->serviceGenerator = app(ServiceGenerator::class);
1✔
151
        $this->factoryGenerator = app(FactoryGenerator::class);
1✔
152
        $this->testGenerator = app(TestsGenerator::class);
1✔
153
        $this->translationsGenerator = app(TranslationsGenerator::class);
1✔
154
        $this->seederGenerator = app(SeederGenerator::class);
1✔
155
        $this->resourceGenerator = app(ResourceGenerator::class);
1✔
156
        $this->novaResourceGenerator = app(NovaResourceGenerator::class);
1✔
157
        $this->novaTestGenerator = app(NovaTestGenerator::class);
1✔
158
        $this->eventDispatcher = app(EventDispatcher::class);
1✔
159
    }
160

161
    /**
162
     * Execute the console command.
163
     *
164
     * @return void
165
     */
166
    public function handle(): void
167
    {
168
        $this->validateInput();
×
169
        $this->checkConfigs();
×
170

171
        $this->eventDispatcher->listen(
×
172
            events: SuccessCreateMessage::class,
×
173
            listener: fn (SuccessCreateMessage $event) => $this->info($event->message),
×
174
        );
×
175

176
        $this->eventDispatcher->listen(
×
177
            events: WarningEvent::class,
×
178
            listener: fn (WarningEvent $event) => $this->warn($event->message),
×
179
        );
×
180

181
        try {
182
            $this->generate();
×
183
        } catch (EntityCreateException $e) {
×
184
            $this->error($e->getMessage());
×
185
        }
186
    }
187

188
    protected function checkConfigs()
189
    {
190
        $packageConfigPath = __DIR__ . '/../../config/entity-generator.php';
×
191
        $packageConfigs = require $packageConfigPath;
×
192

193
        $projectConfigs = config('entity-generator');
×
194

195
        $newConfig = $this->outputNewConfig($packageConfigs, $projectConfigs);
×
196

197
        if ($newConfig !== $projectConfigs) {
×
198
            $this->comment('Config has been updated');
×
199
            Config::set('entity-generator', $newConfig);
×
200
            file_put_contents(config_path('entity-generator.php'), "<?php\n\nreturn" . $this->customVarExport($newConfig) . ';');
×
201
        }
202
    }
203

204
    protected function outputNewConfig($packageConfigs, $projectConfigs)
205
    {
206
        $flattenedPackageConfigs = Arr::dot($packageConfigs);
×
207
        $flattenedProjectConfigs = Arr::dot($projectConfigs);
×
208

209
        $newConfig = array_merge($flattenedPackageConfigs, $flattenedProjectConfigs);
×
210

211
        $translations = 'lang/en/validation.php';
×
212
        $translations = (version_compare(app()->version(), '9', '>=')) ? $translations : "resources/{$translations}";
×
213

214
        if ($newConfig['paths.translations'] !== $translations) {
×
215
            $newConfig['paths.translations'] = $translations;
×
216
        }
217

218
        $factories = 'database/factories';
×
219

220
        if ($newConfig['paths.factories'] !== $factories) {
×
221
            $newConfig['paths.factories'] = $factories;
×
222
        }
223

224
        $differences = array_diff_key($newConfig, $flattenedProjectConfigs);
×
225

226
        foreach ($differences as $differenceKey => $differenceValue) {
×
227
            $this->comment("Key '{$differenceKey}' was missing in your config, we added it with the value '{$differenceValue}'");
×
228
        }
229

230
        return array_undot($newConfig);
×
231
    }
232

233
    protected function customVarExport($expression)
234
    {
235
        $defaultExpression = var_export($expression, true);
×
236

237
        $patterns = [
×
238
            '/array/' => '',
×
239
            '/\(/' => '[',
×
240
            '/\)/' => ']',
×
241
            '/=> \\n/' => '=>',
×
242
            '/=>.+\[/' => '=> [',
×
243
            '/^ {8}/m' => str_repeat(' ', 10),
×
244
            '/^ {6}/m' => str_repeat(' ', 8),
×
245
            '/^ {4}/m' => str_repeat(' ', 6),
×
246
            '/^ {2}/m' => str_repeat(' ', 4),
×
247
        ];
×
248

249
        return preg_replace(array_keys($patterns), array_values($patterns), $defaultExpression);
×
250
    }
251

252
    protected function classExists($path, $name)
253
    {
254
        $paths = config('entity-generator.paths');
×
255

256
        $entitiesPath = $paths[$path];
×
257

258
        $classPath = base_path("{$entitiesPath}/{$name}.php");
×
259

260
        return file_exists($classPath);
×
261
    }
262

263
    protected function validateInput()
264
    {
265
        $this->validateOnlyApiOption();
×
266
        $this->validateCrudOptions();
×
267
    }
268

269
    protected function generate()
270
    {
271
        foreach ($this->rules['only'] as $option => $generators) {
×
272
            if ($this->option($option)) {
×
273
                foreach ($generators as $generator) {
×
274
                    $this->runGeneration($generator);
×
275
                }
276

277
                return;
×
278
            }
279
        }
280

281
        foreach ($this->generators as $generator) {
×
282
            $this->runGeneration($generator);
×
283
        }
284
    }
285

286
    protected function runGeneration($generator)
287
    {
288
        app($generator)
×
289
            ->setModel($this->argument('name'))
×
290
            ->setFields($this->getFields())
×
291
            ->setRelations($this->getRelations())
×
292
            ->setCrudOptions($this->getCrudOptions())
×
293
            ->generate();
×
294
    }
295

296
    protected function getCrudOptions()
297
    {
298
        return str_split($this->option('methods'));
×
299
    }
300

301
    protected function getRelations()
302
    {
303
        return [
×
304
            'hasOne' => $this->option('has-one'),
×
305
            'hasMany' => $this->option('has-many'),
×
306
            'belongsTo' => $this->option('belongs-to'),
×
307
            'belongsToMany' => $this->option('belongs-to-many')
×
308
        ];
×
309
    }
310

311
    protected function getFields()
312
    {
313
        return Arr::only($this->options(), EntityGenerator::AVAILABLE_FIELDS);
×
314
    }
315

316
    protected function validateCrudOptions()
317
    {
318
        $crudOptions = $this->getCrudOptions();
×
319

320
        foreach ($crudOptions as $crudOption) {
×
321
            if (!in_array($crudOption, MakeEntityCommand::CRUD_OPTIONS)) {
×
322
                throw new UnexpectedValueException("Invalid method {$crudOption}.");
×
323
            }
324
        }
325
    }
326

327
    protected function validateOnlyApiOption()
328
    {
329
        if ($this->option('only-api')) {
×
330
            $modelName = Str::studly($this->argument('name'));
×
331
            if (!$this->classExists('services', "{$modelName}Service")) {
×
332
                throw new ClassNotExistsException('Cannot create API without entity.');
×
333
            }
334
        }
335
    }
336
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc