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

RonasIT / laravel-entity-generator / 12802573486

16 Jan 2025 05:16AM UTC coverage: 61.848% (+1.6%) from 60.217%
12802573486

Pull #73

github

web-flow
Merge 40fdcb29a into 3b523a66f
Pull Request #73: Add repository generator tests

1 of 1 new or added line in 1 file covered. (100.0%)

569 of 920 relevant lines covered (61.85%)

2.27 hits per line

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

89.19
/src/Generators/EntityGenerator.php
1
<?php
2

3
namespace RonasIT\Support\Generators;
4

5
use Illuminate\Database\Eloquent\Relations\BelongsTo;
6
use Illuminate\Filesystem\Filesystem;
7
use Illuminate\Support\Arr;
8
use Illuminate\Support\Facades\DB;
9
use Illuminate\Support\Str;
10
use RonasIT\Support\Events\WarningEvent;
11
use RonasIT\Support\Exceptions\ClassNotExistsException;
12
use Throwable;
13
use ReflectionMethod;
14
use ReflectionClass;
15

16
/**
17
 * @property Filesystem $fs
18
 */
19
abstract class EntityGenerator
20
{
21
    const AVAILABLE_FIELDS = [
22
        'integer', 'integer-required', 'string-required', 'string', 'float-required', 'float',
23
        'boolean-required', 'boolean', 'timestamp-required', 'timestamp', 'json'
24
    ];
25

26
    protected $paths = [];
27
    protected $model;
28
    protected $fields;
29
    protected $relations = [];
30
    protected $crudOptions;
31

32
    /**
33
     * @param array $crudOptions
34
     * @return $this
35
     */
36
    public function setCrudOptions($crudOptions)
37
    {
38
        $this->crudOptions = $crudOptions;
5✔
39

40
        return $this;
5✔
41
    }
42

43
    /**
44
     * @param string $model
45
     * @return $this
46
     */
47
    public function setModel($model)
48
    {
49
        $this->model = Str::studly($model);
38✔
50

51
        return $this;
38✔
52
    }
53

54
    /**
55
     * @param array $fields
56
     * @return $this
57
     */
58
    public function setFields($fields)
59
    {
60
        $this->fields = $fields;
12✔
61

62
        return $this;
12✔
63
    }
64

65
    /**
66
     * @param array $relations
67
     * @return $this
68
     */
69
    public function setRelations($relations)
70
    {
71
        $this->relations = $relations;
11✔
72

73
        foreach ($relations['belongsTo'] as $field) {
11✔
74
            $name = Str::snake($field) . '_id';
4✔
75

76
            $this->fields['integer-required'][] = $name;
4✔
77
        }
78

79
        return $this;
11✔
80
    }
81

82
    public function __construct()
83
    {
84
        $this->paths = config('entity-generator.paths');
38✔
85
    }
86

87
    protected function getOrCreateNamespace(string $path): string
88
    {
89
        $path = $this->paths[$path];
15✔
90
        $pathParts = explode('/', $path);
15✔
91

92
        if (Str::endsWith(Arr::last($pathParts), '.php')) {
15✔
93
            array_pop($pathParts);
×
94
        }
95

96
        $namespace = array_map(function (string $part) {
15✔
97
            return ucfirst($part);
15✔
98
        }, $pathParts);
15✔
99

100
        $fullPath = base_path($path);
15✔
101

102
        if (!file_exists($fullPath)) {
15✔
103
            mkdir($fullPath, 0777, true);
11✔
104
        }
105

106
        return implode('\\', $namespace);
15✔
107
    }
108

109
    abstract public function generate(): void;
110

111
    protected function classExists($path, $name): bool
112
    {
113
        $entitiesPath = $this->paths[$path];
22✔
114

115
        $classPath = base_path("{$entitiesPath}/{$name}.php");
22✔
116

117
        return file_exists($classPath);
22✔
118
    }
119

120
    protected function saveClass($path, $name, $content, $additionalEntityFolder = false): string
121
    {
122
        $entitiesPath = base_path($this->paths[$path]);
14✔
123

124
        if ($additionalEntityFolder) {
14✔
125
            $entitiesPath = $entitiesPath . "/{$additionalEntityFolder}";
×
126
        }
127

128
        $classPath = "{$entitiesPath}/{$name}.php";
14✔
129
        $tag = "<?php";
14✔
130

131
        if (!Str::contains($content, $tag)) {
14✔
132
            $content = "{$tag}\n\n{$content}";
14✔
133
        }
134

135
        if (!file_exists($entitiesPath)) {
14✔
136
            mkdir($entitiesPath, 0777, true);
2✔
137
        }
138

139
        return file_put_contents($classPath, $content);
14✔
140
    }
141

142
    protected function getStub($stub, $data = []): string
143
    {
144
        $stubPath = config("entity-generator.stubs.{$stub}");
17✔
145

146
        $data['options'] = $this->crudOptions;
17✔
147

148
        return view($stubPath)->with($data)->render();
17✔
149
    }
150

151
    protected function getTableName($entityName, $delimiter = '_'): string
152
    {
153
        $entityName = Str::snake($entityName, $delimiter);
6✔
154

155
        return $this->getPluralName($entityName);
6✔
156
    }
157

158
    protected function getPluralName($entityName): string
159
    {
160
        return Str::plural($entityName);
7✔
161
    }
162

163
    protected function throwFailureException($exceptionClass, $failureMessage, $recommendedMessage): void
164
    {
165
        throw new $exceptionClass("{$failureMessage} {$recommendedMessage}");
12✔
166
    }
167

168
    protected function getRelatedModels(string $model, string $creatableClass): array
169
    {
170
        $modelClass = $this->getModelClass($model);
2✔
171

172
        if (!class_exists($modelClass)) {
2✔
173
            $this->throwFailureException(
×
174
                exceptionClass: ClassNotExistsException::class,
×
175
                failureMessage: "Cannot create {$creatableClass} cause {$model} Model does not exists.",
×
176
                recommendedMessage: "Create a {$model} Model by himself or run command 'php artisan make:entity {$model} --only-model'.",
×
177
            );
×
178
        }
179

180
        $instance = new $modelClass();
2✔
181

182
        $publicMethods = (new ReflectionClass($modelClass))->getMethods(ReflectionMethod::IS_PUBLIC);
2✔
183

184
        $methods = array_filter($publicMethods, fn ($method) => $method->class === $modelClass && !$method->getParameters());
2✔
185

186
        $relatedModels = [];
2✔
187

188
        DB::beginTransaction();
2✔
189

190
        foreach ($methods as $method) {
2✔
191
            try {
192
                $result = call_user_func([$instance, $method->getName()]);
2✔
193

194
                if (!$result instanceof BelongsTo) {
2✔
195
                    continue;
2✔
196
                }
197
            } catch (Throwable) {
2✔
198
                continue;
2✔
199
            }
200

201
            $relatedModels[] = class_basename(get_class($result->getRelated()));
×
202
        }
203

204
        DB::rollBack();
2✔
205

206
        return $relatedModels;
2✔
207
    }
208

209
    protected function getModelClass(string $model): string
210
    {
211
        $modelNamespace = $this->getOrCreateNamespace('models');
3✔
212

213
        return "{$modelNamespace}\\{$model}";
3✔
214
    }
215

216
    protected function isStubExists(string $stubName, ?string $generationType = null): bool
217
    {
218
        $config = "entity-generator.stubs.{$stubName}";
26✔
219

220
        $stubPath = config($config);
26✔
221

222
        if (!view()->exists($stubPath)) {
26✔
223
            $generationType ??= Str::replace('_', ' ', $stubName);
11✔
224

225
            $message = "Generation of {$generationType} has been skipped cause the view {$stubPath} from the config {$config} is not exists. Please check that config has the correct view name value.";
11✔
226

227
            event(new WarningEvent($message));
11✔
228

229
            return false;
11✔
230
        }
231

232
        return true;
21✔
233
    }
234
}
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