Mercurial > packages > magicforger
view src/Generator/Model/ModelGenerator.php @ 24:31109c61ce02 codex
Refactor RelationshipNavigator formatting and implement belongsTo, hasMany, belongsToMany injection in ModelGenerator
| author | Luka Sitas <sitas.luka.97@gmail.com> |
|---|---|
| date | Tue, 22 Apr 2025 21:37:44 -0400 |
| parents | 827efbf4d73c |
| children | 555bfaa500ac |
line wrap: on
line source
<?php namespace Wizard\MagicForger\Generator\Model; use Symfony\Component\Console\Attribute\AsCommand; use Wizard\MagicForger\Generator\BaseGenerator; use Wizard\MagicForger\Helpers\RelationshipNavigator; use Illuminate\Support\Str; #[AsCommand(name: 'mf:model')] class ModelGenerator extends BaseGenerator { /** * The name and signature of the console command. * * @var string */ protected $name = 'mf:model'; /** * The console command description. * * @var string */ protected $description = 'Generates the Model File for a table.'; /** * The type of class being generated. * * @var string */ protected $type = 'Model'; protected static $cached_snippets = []; /** * Execute the console command. * * @return mixed */ public function handle() { // Delegate to parent handler (includes replacements and insertions) return parent::handle(); } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { if (! is_null(RelationshipNavigator::isPivot($this->getCurrentTable()))) { return $this->resolveStubPath('/stubs/model.pivot.stub'); } return $this->resolveStubPath('/stubs/model.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return is_file($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } protected function getClassName($name) { return $this->model_name($name); } /** * Get the stub file for the generator. * * @return string */ protected function getPath($name = null) { return str_replace(['App\\', '\\'], ['app/', '/'], $this->getModelNamespace().'/'.$this->model_name($this->getTableInput()).'.php'); } protected function getSnippet($snippet_name) { // Cache snippet contents to avoid re-reading files if (! isset(self::$cached_snippets[$snippet_name])) { self::$cached_snippets[$snippet_name] = $this->files->get( $this->resolveStubPath("/snippets/$snippet_name.stub")); } return self::$cached_snippets[$snippet_name]; } protected function gatherRelations() { $relations = RelationshipNavigator::getRelations($this->getCurrentTable()); return renderRelations($relations); } protected function renderRelations($relations) { $renders = [ 'belongsTo' => [], 'hasMany' => [], 'belongsToMany' => [], ]; // Render belongsTo relations foreach (($relations['belongsTo'] ?? []) as $relation) { $renders['belongsTo'][] = $this->renderBelongsTo($relation); } // Render hasMany relations foreach (($relations['hasMany'] ?? []) as $relation) { $renders['hasMany'][] = $this->renderHasMany($relation); } // Render belongsToMany (many-to-many) via hasManyThrough pivot relations foreach (($relations['hasManyThrough'] ?? []) as $relation) { $renders['belongsToMany'][] = $this->renderBelongsToMany($relation); } return $renders; } protected function renderBelongsTo($relationship) { $snippet = $this->getSnippet('belongs_to_relation'); $relationName = Str::singular($relationship['table']); $relatedModel = $this->getClassName($relationship['table']); $columnName = $relationship['column']; // Replace placeholders with actual values $string = str_replace( ['{{relationName}}', '{{relatedModel}}', '{{columnName}}'], [$relationName, $relatedModel, $columnName], $snippet ); return $string; } /** * Render a hasMany relation. * * @param array $relationship * @return string */ protected function renderHasMany($relationship) { $snippet = $this->getSnippet('has_many_relation'); // Method name uses camel case for plural relation $relationName = Str::camel($relationship['table']); $relatedModel = $this->getClassName($relationship['table']); $columnName = $relationship['column']; // Replace placeholders with actual values $string = str_replace( ['{{relationName}}', '{{relatedModel}}', '{{columnName}}'], [$relationName, $relatedModel, $columnName], $snippet ); return $string; } protected function renderBelongsToMany($relationship) { $snippet = $this->getSnippet('belongs_to_many_relation'); $relationName = $relationship['table']; $relatedModel = $this->getClassName($relationship['table']); $pivotTable = $relationship['through']['table']; $foreignPivotKey = $relationship['through']['external_column']; $relatedPivotKey = $relationship['through']['internal_column']; // Replace placeholders with actual values $string = str_replace( ['{{relationName}}', '{{relatedModel}}', '{{pivotTable}}', '{{foreignPivotKey}}', '{{relatedPivotKey}}'], [$relationName, $relatedModel, $pivotTable, $foreignPivotKey, $relatedPivotKey], $snippet ); return $string; } /** * Get available insertions including model relationships. * * @return array */ public function get_available_inserts(): array { // Merge parent insertions (attributes, fillable, etc.) $inserts = parent::get_available_inserts(); // Gather and render relationships for this model $relations = RelationshipNavigator::getRelations($this->getCurrentTable()); $rendered = $this->renderRelations($relations); // Build code blocks for each relation type $belongs = !empty($rendered['belongsTo']) ? implode("\n ", $rendered['belongsTo']) : ''; $hasMany = !empty($rendered['hasMany']) ? implode("\n ", $rendered['hasMany']) : ''; $belongsMany = !empty($rendered['belongsToMany']) ? implode("\n ", $rendered['belongsToMany']) : ''; // Assign to stub placeholders $inserts['# {{ belongs_to_relationships }}'] = $belongs; $inserts['# {{ has_many_relationships }}'] = $hasMany; $inserts['# {{ has_many_through_relationships }}'] = $belongsMany; return $inserts; } }
