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

RonasIT / laravel-entity-generator / 16143130415

08 Jul 2025 12:24PM UTC coverage: 100.0%. Remained the same
16143130415

Pull #164

github

web-flow
Merge 8c78f97eb into befbe86b8
Pull Request #164: feat: test with php8.4

905 of 905 relevant lines covered (100.0%)

11.41 hits per line

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

100.0
/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\Facades\Event;
9
use Illuminate\Support\Str;
10
use RonasIT\Support\DTO\RelationsDTO;
11
use RonasIT\Support\Events\SuccessCreateMessage;
12
use RonasIT\Support\Events\WarningEvent;
13
use RonasIT\Support\Exceptions\ClassNotExistsException;
14
use Exception;
15
use RonasIT\Support\Generators\ControllerGenerator;
16
use RonasIT\Support\Generators\EntityGenerator;
17
use RonasIT\Support\Generators\FactoryGenerator;
18
use RonasIT\Support\Generators\MigrationGenerator;
19
use RonasIT\Support\Generators\ModelGenerator;
20
use RonasIT\Support\Generators\NovaResourceGenerator;
21
use RonasIT\Support\Generators\NovaTestGenerator;
22
use RonasIT\Support\Generators\RepositoryGenerator;
23
use RonasIT\Support\Generators\RequestsGenerator;
24
use RonasIT\Support\Generators\ResourceGenerator;
25
use RonasIT\Support\Generators\ServiceGenerator;
26
use RonasIT\Support\Generators\TestsGenerator;
27
use RonasIT\Support\Generators\TranslationsGenerator;
28
use RonasIT\Support\Generators\SeederGenerator;
29
use UnexpectedValueException;
30

31
class MakeEntityCommand extends Command
32
{
33
    const CRUD_OPTIONS = [
34
        'C', 'R', 'U', 'D'
35
    ];
36

37
    /**
38
     * The name and signature of the console command.
39
     *
40
     * @var string
41
     */
42
    protected $signature = 'make:entity {name : The name of the entity. This name will use as name of models class.}
43
        
44
        {--only-api : Set this flag if you want to create resource, controller, route, requests, tests.}
45
        {--only-entity : Set this flag if you want to create migration, model, repository, service, factory, seeder.}
46
        {--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.} 
47
        {--only-repository : Set this flag if you want to create only repository. This flag is a higher priority than --only-tests and --only-migration.}
48
        {--only-service : Set this flag if you want to create only service.}
49
        {--only-resource : Set this flag if you want to create only resource.}
50
        {--only-controller : Set this flag if you want to create only controller.}
51
        {--only-requests : Set this flag if you want to create only requests.}
52
        {--only-migration : Set this flag if you want to create only repository. This flag is a higher priority than --only-tests.}
53
        {--only-factory : Set this flag if you want to create only factory.}
54
        {--only-tests : Set this flag if you want to create only tests.}
55
        {--only-seeder : Set this flag if you want to create only seeder.}
56
        {--only-nova-resource : Set this flag if you want to create only nova resource.}
57
        {--only-nova-tests : Set this flag if you want to create only nova resource tests.}
58

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

61
        {--i|integer=* : Add integer field to entity.}
62
        {--I|integer-required=* : Add required integer field to entity. If you want to specify default value you have to do it manually.}
63
        {--f|float=* : Add float field to entity.}
64
        {--F|float-required=* : Add required float field to entity. If you want to specify default value you have to do it manually.}
65
        {--s|string=* : Add string field to entity. Default type is VARCHAR(255) but you can change it manually in migration.}
66
        {--S|string-required=* : Add required string field to entity. If you want to specify default value ir size you have to do it manually.}
67
        {--b|boolean=* : Add boolean field to entity.}
68
        {--B|boolean-required=* : Add boolean field to entity. If you want to specify default value you have to do it manually.}
69
        {--t|timestamp=* : Add timestamp field to entity.}
70
        {--T|timestamp-required=* : Add timestamp field to entity. If you want to specify default value you have to do it manually.}
71
        {--j|json=* : Add json field to entity.}
72
        
73
        {--a|has-one=* : Set hasOne relations between you entity and existed entity.}
74
        {--A|has-many=* : Set hasMany relations between you entity and existed entity.}
75
        {--e|belongs-to=* : Set belongsTo relations between you entity and existed entity.}
76
        {--E|belongs-to-many=* : Set belongsToMany relations between you entity and existed entity.}';
77

78
    /**
79
     * The console command description.
80
     *
81
     * @var string
82
     */
83
    protected $description = 'Make entity with Model, Repository, Service, Migration, Controller, Resource and Nova Resource.';
84

85
    protected $rules = [
86
        'only' => [
87
            'only-api' => [ResourceGenerator::class, ControllerGenerator::class, RequestsGenerator::class, TestsGenerator::class],
88
            'only-entity' => [MigrationGenerator::class, ModelGenerator::class, ServiceGenerator::class, RepositoryGenerator::class, FactoryGenerator::class, SeederGenerator::class],
89
            'only-model' => [ModelGenerator::class],
90
            'only-repository' => [RepositoryGenerator::class],
91
            'only-service' => [ServiceGenerator::class],
92
            'only-resource' => [ResourceGenerator::class],
93
            'only-controller' => [ControllerGenerator::class],
94
            'only-requests' => [RequestsGenerator::class],
95
            'only-migration' => [MigrationGenerator::class],
96
            'only-factory' => [FactoryGenerator::class],
97
            'only-tests' => [FactoryGenerator::class, TestsGenerator::class],
98
            'only-seeder' => [SeederGenerator::class],
99
            'only-nova-resource' => [NovaResourceGenerator::class],
100
            'only-nova-tests' => [NovaTestGenerator::class]
101
        ]
102
    ];
103

104
    public $generators = [
105
        ModelGenerator::class, RepositoryGenerator::class, ServiceGenerator::class, RequestsGenerator::class,
106
        ResourceGenerator::class, ControllerGenerator::class, MigrationGenerator::class, FactoryGenerator::class,
107
        TestsGenerator::class, TranslationsGenerator::class, SeederGenerator::class, NovaResourceGenerator::class,
108
        NovaTestGenerator::class
109
    ];
110

111
    /**
112
     * Execute the console command.
113
     *
114
     * @return void
115
     */
116
    public function handle(): void
117
    {
118
        $this->validateInput();
10✔
119
        $this->checkConfigs();
6✔
120
        $this->listenEvents();
6✔
121

122
        try {
123
            $this->generate();
6✔
124
        } catch (Exception $e) {
2✔
125
            $this->error($e->getMessage());
2✔
126
        }
127
    }
128

129
    protected function checkConfigs()
130
    {
131
        $packageConfigPath = __DIR__ . '/../../config/entity-generator.php';
6✔
132
        $packageConfigs = require $packageConfigPath;
6✔
133

134
        $projectConfigs = config('entity-generator');
6✔
135

136
        $newConfig = $this->outputNewConfig($packageConfigs, $projectConfigs);
6✔
137

138
        if ($newConfig !== $projectConfigs) {
6✔
139
            $this->comment('Config has been updated');
2✔
140
            Config::set('entity-generator', $newConfig);
2✔
141
            file_put_contents(config_path('entity-generator.php'), "<?php\n\nreturn" . $this->customVarExport($newConfig) . ';');
2✔
142
        }
143
    }
144

145
    protected function outputNewConfig($packageConfigs, $projectConfigs)
146
    {
147
        $flattenedPackageConfigs = Arr::dot($packageConfigs);
6✔
148
        $flattenedProjectConfigs = Arr::dot($projectConfigs);
6✔
149

150
        $newConfig = array_merge($flattenedPackageConfigs, $flattenedProjectConfigs);
6✔
151

152
        $differences = array_diff_key($newConfig, $flattenedProjectConfigs);
6✔
153

154
        foreach ($differences as $differenceKey => $differenceValue) {
6✔
155
            $this->comment("Key '{$differenceKey}' was missing in your config, we added it with the value '{$differenceValue}'");
2✔
156
        }
157

158
        return array_undot($newConfig);
6✔
159
    }
160

161
    protected function customVarExport($expression)
162
    {
163
        $defaultExpression = var_export($expression, true);
2✔
164

165
        $patterns = [
2✔
166
            '/array/' => '',
2✔
167
            '/\(/' => '[',
2✔
168
            '/\)/' => ']',
2✔
169
            '/=> \\n/' => '=>',
2✔
170
            '/=>.+\[/' => '=> [',
2✔
171
            '/^ {8}/m' => str_repeat(' ', 10),
2✔
172
            '/^ {6}/m' => str_repeat(' ', 8),
2✔
173
            '/^ {4}/m' => str_repeat(' ', 6),
2✔
174
            '/^ {2}/m' => str_repeat(' ', 4),
2✔
175
        ];
2✔
176

177
        return preg_replace(array_keys($patterns), array_values($patterns), $defaultExpression);
2✔
178
    }
179

180
    protected function classExists($path, $name)
181
    {
182
        $paths = config('entity-generator.paths');
2✔
183

184
        $entitiesPath = $paths[$path];
2✔
185

186
        $classPath = base_path("{$entitiesPath}/{$name}.php");
2✔
187

188
        return file_exists($classPath);
2✔
189
    }
190

191
    protected function validateInput()
192
    {
193
        $this->validateOnlyApiOption();
10✔
194
        $this->validateCrudOptions();
8✔
195
    }
196

197
    protected function generate()
198
    {
199
        foreach ($this->rules['only'] as $option => $generators) {
6✔
200
            if ($this->option($option)) {
6✔
201
                foreach ($generators as $generator) {
2✔
202
                    $this->runGeneration($generator);
2✔
203
                }
204

205
                return;
2✔
206
            }
207
        }
208

209
        foreach ($this->generators as $generator) {
4✔
210
            $this->runGeneration($generator);
4✔
211
        }
212
    }
213

214
    protected function runGeneration($generator)
215
    {
216
        app($generator)
6✔
217
            ->setModel($this->argument('name'))
6✔
218
            ->setFields($this->getFields())
6✔
219
            ->setRelations($this->getRelations())
6✔
220
            ->setCrudOptions($this->getCrudOptions())
6✔
221
            ->generate();
6✔
222
    }
223

224
    protected function getCrudOptions()
225
    {
226
        return str_split($this->option('methods'));
8✔
227
    }
228

229
    protected function getRelations()
230
    {
231
        return new RelationsDTO(
6✔
232
            hasOne: $this->option('has-one'),
6✔
233
            hasMany: $this->option('has-many'),
6✔
234
            belongsTo: $this->option('belongs-to'),
6✔
235
            belongsToMany: $this->option('belongs-to-many'),
6✔
236
        );
6✔
237
    }
238

239
    protected function getFields()
240
    {
241
        return Arr::only($this->options(), EntityGenerator::AVAILABLE_FIELDS);
6✔
242
    }
243

244
    protected function validateCrudOptions()
245
    {
246
        $crudOptions = $this->getCrudOptions();
8✔
247

248
        foreach ($crudOptions as $crudOption) {
8✔
249
            if (!in_array($crudOption, MakeEntityCommand::CRUD_OPTIONS)) {
8✔
250
                throw new UnexpectedValueException("Invalid method {$crudOption}.");
2✔
251
            }
252
        }
253
    }
254

255
    protected function validateOnlyApiOption()
256
    {
257
        if ($this->option('only-api')) {
10✔
258
            $modelName = Str::studly($this->argument('name'));
2✔
259
            if (!$this->classExists('services', "{$modelName}Service")) {
2✔
260
                throw new ClassNotExistsException('Cannot create API without entity.');
2✔
261
            }
262
        }
263
    }
264

265
    protected function listenEvents(): void
266
    {
267
        Event::listen(
6✔
268
            events: SuccessCreateMessage::class,
6✔
269
            listener: fn (SuccessCreateMessage $event) => $this->info($event->message),
6✔
270
        );
6✔
271

272
        Event::listen(
6✔
273
            events: WarningEvent::class,
6✔
274
            listener: fn (WarningEvent $event) => $this->warn($event->message),
6✔
275
        );
6✔
276
    }
277
}
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