comparison src/Generator/Model/ModelGenerator.php @ 34:f65ab84ee47f default

merge with codex
author luka
date Wed, 10 Sep 2025 21:00:47 -0400
parents 010ace248d14
children
comparison
equal deleted inserted replaced
10:a9ff874afdbd 34:f65ab84ee47f
1 <?php 1 <?php
2 2
3 namespace Wizzard\MagicForger\Generator\Model; 3 namespace Wizard\MagicForger\Generator\Model;
4 4
5 use Symfony\Component\Console\Attribute\AsCommand; 5 use Symfony\Component\Console\Attribute\AsCommand;
6 use Wizzard\MagicForger\Generator\BaseGenerator; 6 use Wizard\MagicForger\Generator\BaseGenerator;
7 use Wizard\MagicForger\Helpers\RelationshipNavigator;
8 use Illuminate\Support\Str;
7 9
8 #[AsCommand(name: 'mf:model')] 10 #[AsCommand(name: 'mf:model')]
9 class ModelGenerator extends BaseGenerator 11 class ModelGenerator extends BaseGenerator
10 { 12 {
11 /** 13 /**
27 * 29 *
28 * @var string 30 * @var string
29 */ 31 */
30 protected $type = 'Model'; 32 protected $type = 'Model';
31 33
34 protected static $cached_snippets = [];
35
32 /** 36 /**
33 * Execute the console command. 37 * Execute the console command.
38 *
39 * @return mixed
34 */ 40 */
35 public function handle() 41 public function handle()
36 { 42 {
37 parent::handle(); 43 // Delegate to parent handler (includes replacements and insertions)
44 return parent::handle();
38 } 45 }
39 46
40 /** 47 /**
41 * Get the stub file for the generator. 48 * Get the stub file for the generator.
42 * 49 *
43 * @return string 50 * @return string
44 */ 51 */
45 protected function getStub() 52 protected function getStub()
46 { 53 {
54 if (! is_null(RelationshipNavigator::isPivot($this->getCurrentTable()))) {
55 return $this->resolveStubPath('/stubs/model.pivot.stub');
56 }
57
47 return $this->resolveStubPath('/stubs/model.stub'); 58 return $this->resolveStubPath('/stubs/model.stub');
48 } 59 }
49 60
50 /** 61 /**
51 * Resolve the fully-qualified path to the stub. 62 * Resolve the fully-qualified path to the stub.
52 * 63 *
53 * @param string $stub 64 * @param string $stub
54 *
55 * @return string 65 * @return string
56 */ 66 */
57 protected function resolveStubPath($stub) 67 protected function resolveStubPath($stub)
58 { 68 {
59 return is_file($customPath = $this->laravel->basePath(trim($stub, '/'))) 69 return is_file($customPath = $this->laravel->basePath(trim($stub, '/')))
73 */ 83 */
74 protected function getPath($name = null) 84 protected function getPath($name = null)
75 { 85 {
76 return str_replace(['App\\', '\\'], ['app/', '/'], $this->getModelNamespace().'/'.$this->model_name($this->getTableInput()).'.php'); 86 return str_replace(['App\\', '\\'], ['app/', '/'], $this->getModelNamespace().'/'.$this->model_name($this->getTableInput()).'.php');
77 } 87 }
88
89 protected function gatherRelations() {
90 $relations = RelationshipNavigator::getRelations($this->getCurrentTable());
91
92 return $relations;
93
94 }
95
96 protected function renderFilters() {
97 $insert = '';
98 foreach ($this->get_columns() as $column) {
99 if (in_array($column['name'], $this->columns_to_ignore)) {
100 continue;
101 }
102 $snippet = $this->getSnippet('filter');
103 $tableName = $this->getCurrentTable();
104 $value = 'value'; // TODO: this should be determined based on column type
105 $columnName = $column['name'];
106 $columnDisplay = Str::headline($columnName);
107
108 // Replace placeholders with actual values
109 $string = str_replace(
110 ['{{value}}', '{{columnDisplay}}', '{{tableName}}', '{{columnName}}'],
111 [$value, $columnDisplay, $tableName, $columnName],
112 $snippet
113 );
114 $insert .= sprintf("%s", $string);
115 }
116
117 return $insert;
118 }
119
120 protected function renderRelations($relations) {
121 $renders = [
122 'belongsTo' => [],
123 'hasMany' => [],
124 'belongsToMany' => [],
125 ];
126 // Render belongsTo relations
127 foreach (($relations['belongsTo'] ?? []) as $relation) {
128 $renders['belongsTo'][] = $this->renderBelongsTo($relation);
129 }
130
131 // Render hasMany relations
132 foreach (($relations['hasMany'] ?? []) as $relation) {
133 $renders['hasMany'][] = $this->renderHasMany($relation);
134 }
135
136 // Render belongsToMany (many-to-many) via hasManyThrough pivot relations
137 foreach (($relations['hasManyThrough'] ?? []) as $relation) {
138 $renders['belongsToMany'][] = $this->renderBelongsToMany($relation);
139 }
140 return $renders;
141 }
142
143 protected function renderBelongsTo($relationship)
144 {
145 $snippet = $this->getSnippet('belongs_to_relation');
146 $relationName = Str::singular($relationship['table']);
147 $relatedModel = $this->getClassName($relationship['table']);
148 $columnName = $relationship['column'];
149
150 // Replace placeholders with actual values
151 $string = str_replace(
152 ['{{relationName}}', '{{relatedModel}}', '{{columnName}}'],
153 [$relationName, $relatedModel, $columnName],
154 $snippet
155 );
156
157 return $string;
158 }
159
160 /**
161 * Render a hasMany relation.
162 *
163 * @param array $relationship
164 * @return string
165 */
166 protected function renderHasMany($relationship)
167 {
168 $snippet = $this->getSnippet('has_many_relation');
169 // Method name uses camel case for plural relation
170 $relationName = Str::camel($relationship['table']);
171 $relatedModel = $this->getClassName($relationship['table']);
172 $columnName = $relationship['column'];
173
174 // Replace placeholders with actual values
175 $string = str_replace(
176 ['{{relationName}}', '{{relatedModel}}', '{{columnName}}'],
177 [$relationName, $relatedModel, $columnName],
178 $snippet
179 );
180
181 return $string;
182 }
183
184 protected function renderBelongsToMany($relationship)
185 {
186 $snippet = $this->getSnippet('belongs_to_many_relation');
187 $relationName = $relationship['table'];
188 $relatedModel = $this->getClassName($relationship['table']);
189 $pivotTable = $relationship['through']['table'];
190 $foreignPivotKey = $relationship['through']['external_column'];
191 $relatedPivotKey = $relationship['through']['internal_column'];
192
193 // Replace placeholders with actual values
194 $string = str_replace(
195 ['{{relationName}}', '{{relatedModel}}', '{{pivotTable}}', '{{foreignPivotKey}}', '{{relatedPivotKey}}'],
196 [$relationName, $relatedModel, $pivotTable, $foreignPivotKey, $relatedPivotKey],
197 $snippet
198 );
199
200 return $string;
201 }
202
203 /**
204 * Get available insertions including model relationships.
205 *
206 * @return array
207 */
208 public function get_available_inserts(): array
209 {
210 // Merge parent insertions (attributes, fillable, etc.)
211 $inserts = parent::get_available_inserts();
212
213 // Gather and render relationships for this model
214 $relations = $this->gatherRelations();
215 $rendered = $this->renderRelations($relations);
216 $filters = $this->renderFilters();
217
218 // Build code blocks for each relation type
219 $belongs = !empty($rendered['belongsTo']) ? implode("\n ", $rendered['belongsTo']) : '';
220 $hasMany = !empty($rendered['hasMany']) ? implode("\n ", $rendered['hasMany']) : '';
221 $belongsMany = !empty($rendered['belongsToMany']) ? implode("\n ", $rendered['belongsToMany']) : '';
222
223 // Default relations are based on the belongsTo relationship
224 $default_relations = implode(", \n", array_map(function ($rel) {return '\'' . Str::singular($rel['table']) . '\''; }, $relations['belongsTo']));
225
226 // Assign to stub placeholders
227 $inserts['# {{ belongs_to_relationships }}'] = $belongs;
228 $inserts['# {{ has_many_relationships }}'] = $hasMany;
229 $inserts['# {{ has_many_through_relationships }}'] = $belongsMany;
230 $inserts['# {{ defaultRelationsInsertPoint }}'] = $default_relations;
231 $inserts['# {{ defaultFiltersInsertPoint }}'] = $filters;
232
233 return $inserts;
234 }
78 } 235 }