changeset 13:7ee152c22478 main-dev

Merging
author luka
date Wed, 24 Apr 2024 20:11:52 -0400
parents 3426c7e91c24 (diff) 4bb4daa9e3f1 (current diff)
children c969ed13c570
files .php-cs-fixer.cache src/Generator/Generator.php
diffstat 24 files changed, 1041 insertions(+), 361 deletions(-) [+]
line wrap: on
line diff
--- a/.php-cs-fixer.cache	Wed Apr 24 19:52:35 2024 -0400
+++ b/.php-cs-fixer.cache	Wed Apr 24 20:11:52 2024 -0400
@@ -1,1 +1,1 @@
-{"php":"8.3.6","version":"3.50.0","indent":"    ","lineEnding":"\n","rules":{"binary_operator_spaces":{"default":"at_least_single_space"},"blank_line_after_opening_tag":true,"blank_line_between_import_groups":true,"blank_lines_before_namespace":true,"braces_position":{"allow_single_line_empty_anonymous_classes":true},"class_definition":{"inline_constructor_arguments":false,"space_before_parenthesis":true},"compact_nullable_type_declaration":true,"declare_equal_normalize":true,"lowercase_cast":true,"lowercase_static_reference":true,"new_with_parentheses":true,"no_blank_lines_after_class_opening":true,"no_leading_import_slash":true,"no_whitespace_in_blank_line":true,"ordered_class_elements":{"order":["use_trait"]},"ordered_imports":{"imports_order":["class","function","const"],"sort_algorithm":"none"},"return_type_declaration":true,"short_scalar_cast":true,"single_import_per_statement":{"group_to_single_imports":false},"single_trait_insert_per_statement":true,"ternary_operator_spaces":true,"unary_operator_spaces":{"only_dec_inc":true},"visibility_required":true,"blank_line_after_namespace":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"attribute_placement":"ignore","on_multiline":"ensure_fully_multiline"},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_line_after_imports":true,"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"encoding":true,"full_opening_tag":true},"hashes":{"src\/Generator\/Controller\/ControllerGenerator.php":"075e65a43e5ecc55fbc4dcd7636dfcc1","src\/Generator\/Model\/ModelGenerator.php":"e78c07fc13bd9c379991e8b01b13c672","src\/Generator\/Replacer.php":"5a7f98d22504edb6aba92b061ddd9803","src\/Generator\/Generator.php":"794271f48bed8f156878fc36a25ff60f","src\/Generator\/BaseGenerator.php":"409aadd181fbd4f216fe31f4f42ca3e2","src\/Replacer.php":"c6b5f421259f41016014c00270ca001c","src\/MagicForgerServiceProvider.php":"302d8a09dd351d150ee6cc7988dc447f","src\/Helpers\/FileModifier.php":"13d8f773a55604641ce1e89b28de2922","src\/Test.php":"bac04f2095478ff481ad176918e42db2"}}
\ No newline at end of file
+{"php":"8.2.7","version":"3.19.1","indent":"    ","lineEnding":"\n","rules":{"blank_line_after_opening_tag":true,"blank_line_between_import_groups":true,"blank_lines_before_namespace":true,"class_definition":{"inline_constructor_arguments":false,"space_before_parenthesis":true},"compact_nullable_typehint":true,"curly_braces_position":{"allow_single_line_empty_anonymous_classes":true},"declare_equal_normalize":true,"lowercase_cast":true,"lowercase_static_reference":true,"new_with_braces":true,"no_blank_lines_after_class_opening":true,"no_leading_import_slash":true,"no_whitespace_in_blank_line":true,"ordered_class_elements":{"order":["use_trait"]},"ordered_imports":{"imports_order":["class","function","const"],"sort_algorithm":"none"},"return_type_declaration":true,"short_scalar_cast":true,"single_import_per_statement":{"group_to_single_imports":false},"single_trait_insert_per_statement":true,"ternary_operator_spaces":true,"visibility_required":true,"blank_line_after_namespace":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"on_multiline":"ensure_fully_multiline"},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_spaces_inside_parenthesis":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_line_after_imports":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"encoding":true,"full_opening_tag":true},"hashes":{"src\/Generator\/BaseGenerator.php":"409aadd181fbd4f216fe31f4f42ca3e2","src\/Replacer.php":"c6b5f421259f41016014c00270ca001c","src\/MagicForgerServiceProvider.php":"e56f92adc0181e9b7681de8ca8aca6eb","src\/Generator\/Controller\/ControllerGenerator.php":"075e65a43e5ecc55fbc4dcd7636dfcc1","src\/Generator\/Generator.php":"794271f48bed8f156878fc36a25ff60f","src\/Generator\/Replacer.php":"5a7f98d22504edb6aba92b061ddd9803","src\/Generator\/Model\/ModelGenerator.php":"e78c07fc13bd9c379991e8b01b13c672"}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.php-cs-fixer.dist.php	Wed Apr 24 20:11:52 2024 -0400
@@ -0,0 +1,14 @@
+<?php
+
+$finder = PhpCsFixer\Finder::create()
+    ->in(__DIR__)
+		->exclude('.hg')
+;
+
+$config = new PhpCsFixer\Config();
+return $config->setRules([
+        '@Symfony' => true,
+        'full_opening_tag' => false,
+    ])
+    ->setFinder($finder)
+;
--- a/composer.json	Wed Apr 24 19:52:35 2024 -0400
+++ b/composer.json	Wed Apr 24 20:11:52 2024 -0400
@@ -9,7 +9,8 @@
     },
     "minimum-stability": "stable",
     "require": {
-        "laravel/framework": ">=10.3"
+        "laravel/framework": ">=10.3",
+        "doctrine/dbal": "^3.6"
     },
 		"extra": {
     	"laravel": {
--- a/examples/ExampleGenerator.php.stub	Wed Apr 24 19:52:35 2024 -0400
+++ b/examples/ExampleGenerator.php.stub	Wed Apr 24 20:11:52 2024 -0400
@@ -1,6 +1,6 @@
 <?php
 
-namespace Wizzard\MagicForger\Generator\Controller;
+namespace Wizzard\MagicForger\Generator\{{ Class Name }};
 
 use Symfony\Component\Console\Attribute\AsCommand;
 use Wizzard\MagicForger\Generator\BaseGenerator;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ConfigHelper.php	Wed Apr 24 20:11:52 2024 -0400
@@ -0,0 +1,200 @@
+<?php
+
+namespace Wizzard\MagicForger;
+
+use Illuminate\Support\Collection;
+
+class ConfigHelper
+{
+    // Config array
+    public static $config = [];
+
+    // Config file name constant
+    public const CONFIG_FILE_NAME = 'mf_config.php';
+
+    // Config path variable
+    public static string $config_path;
+
+    /**
+     * Set up configuration path.
+     * @return void
+     */
+    public static function setup_config_path(string $base_path): void
+    {
+        self::$config_path = $base_path.'/'.self::CONFIG_FILE_NAME;
+    }
+
+    /**
+     * Get configuration path.
+     *
+     * @return string
+     */
+    protected static function get_config_path(): string
+    {
+        return self::$config_path;
+    }
+
+    /**
+     * Write configuration into a file.
+     * @return void
+     */
+    public static function write_config(): void
+    {
+        $path = self::get_config_path();
+        $str = '<?php
+                        return '.self::varexport(self::$config, true).';';
+
+        file_put_contents($path, $str);
+        // After writing the file, format it
+        self::format_file($path);
+    }
+
+    /**
+     * Read configuration from a file.
+     * @return void
+     */
+    public static function read_config(): void
+    {
+        $path = self::get_config_path();
+        self::$config = include $path;
+    }
+
+    /**
+     * Print configuration.
+     * @return void
+     */
+    public static function print_config(): void
+    {
+        self::varexport(self::$config);
+    }
+
+    /**
+     * PHP var_export() function with short array syntax (square brackets) indented 2 spaces.
+     *
+     * NOTE: The only issue is when a string value has `=>\n[`, it will get converted to `=> [`
+     *
+     * @see https://www.php.net/manual/en/function.var-export.php
+     *
+     * @param bool $return
+     * @return string|string[]|null
+     */
+    public static function varexport(mixed $expression, $return = false): string|array|null
+    {
+        $export = var_export($expression, true);
+        $patterns = [
+            "/array \(/" => '[',
+            "/^([ ]*)\)(,?)$/m" => '$1]$2',
+            "/=>[ ]?\n[ ]+\[/" => '=> [',
+            "/([ ]*)(\'[^\']+\') => ([\[\'])/" => '$1$2 => $3',
+        ];
+        $export = preg_replace(array_keys($patterns), array_values($patterns), $export);
+        if ((bool) $return) {
+            return $export;
+        } else {
+            echo $export;
+        }
+				return null;
+    }
+
+    /**
+     * Format the given file.
+     * @return void
+     */
+    protected static function format_file(string $path): void
+    {
+        exec('php-cs-fixer fix '.$path);
+    }
+
+    /**
+     * Set up tables.
+     */
+		public static function set_up_tables(): Collection	
+    {
+        $schema = \DB::connection()->getDoctrineSchemaManager();
+        $tables = collect($schema->listTableNames())->all();
+        $table_foreign_keys = [];
+        foreach ($tables as $table) {
+            $table_foreign_keys[$table] = $schema->listTableForeignKeys($table);
+        }
+
+        $insert_tables = [];
+        foreach ($tables as $table) {
+            $columns = [];
+            $table_columns = $schema->listTableColumns($table);
+
+            // Initiate new arrays for foreign keys
+            $foreign_keys = [];
+            $foreign_keys_reverse = [];
+
+            // Check foreign key references from this table
+            $foreign_keys_list = $table_foreign_keys[$table];
+            foreach ($foreign_keys_list as $fk) {
+                $foreign_keys[$fk->getLocalColumns()[0]] = [
+                            'foreign_table' => $fk->getForeignTableName(),
+                            'foreign_column' => $fk->getForeignColumns()[0],
+                          ];
+            }
+
+            foreach ($table_columns as $column) {
+                $full_class = get_class($column->getType());
+                $class_parts = explode('\\', $full_class);
+                $class_name = end($class_parts);
+
+                $columns[$column->getName()] = [
+                                'type' => $class_name,
+                                'should_insert' => [
+                                        'controller' => true,
+                                        'model' => true,
+                                        'requests' => true,
+                                        'views' => true,
+                                      ],
+                                ];
+            }
+            // Check foreign key references to this table
+            foreach ($tables as $other_table) {
+                if ($other_table != $table) {
+                    $foreign_keys_list = $table_foreign_keys[$other_table];
+                    foreach ($foreign_keys_list as $fk) {
+                        if ($fk->getForeignTableName() == $table) {
+                            $foreign_keys_reverse[] = [
+                                               'table' => $other_table,
+                                               'column' => $fk->getLocalColumns()[0],
+                                          ];
+                        }
+                    }
+                }
+            }
+            $insert_tables[$table] = [];
+            $insert_tables[$table]['columns'] = $columns;
+            $insert_tables[$table]['foreign_keys'] = $foreign_keys; // Foreign keys FROM this table
+            $insert_tables[$table]['foreign_keys_reverse'] = $foreign_keys_reverse; // Foreign keys TO this table
+            $insert_tables[$table]['type'] = 'default';
+        }
+
+        self::merge_array_priority(self::$config['tables'], $insert_tables);
+
+        return $tables;
+    }
+
+    /**
+     * Merge two arrays and ensure priority values do not get overwritten.
+     *
+     * @param array $priority
+     * @param array $merged
+     * @return void
+     */
+    private static function merge_array_priority(&$priority, $merged): void
+    {
+        foreach ($merged as $key => $value) {
+            // if the priority key is not set, automatically add the merged values
+            if (!isset($priority[$key])) {
+                $priority[$key] = $value;
+            } else {
+                // if the value is an array recursively merge with priority
+                if (is_array($value) && is_array($priority[$key])) {
+                    self::merge_array_priority($priority[$key], $value);
+                }
+            }
+        }
+    }
+}
--- a/src/Generator/BaseGenerator.php	Wed Apr 24 19:52:35 2024 -0400
+++ b/src/Generator/BaseGenerator.php	Wed Apr 24 20:11:52 2024 -0400
@@ -3,58 +3,67 @@
 namespace Wizzard\MagicForger\Generator;
 
 use DB;
-
 use Illuminate\Console\GeneratorCommand;
-use Illuminate\Support\Str;
-use Symfony\Component\Console\Attribute\AsCommand;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Input\InputOption;
 use Symfony\Component\Console\Output\OutputInterface;
-
-use Wizzard\MagicForger\Generator\Replacer;
+use Wizzard\MagicForger\Replacer\Replacer;
+use Wizzard\MagicForger\Replacer\TableReplacer;
 
 abstract class BaseGenerator extends GeneratorCommand
 {
     use Replacer;
+    use TableReplacer;
 
     /**
-     * The console command description.
+     * The schema of the database.
      *
      * @var string
      */
     protected $schema;
 
     /**
-     * The console command description.
+     * The tables available in the schema.
      *
-     * @var string
+     * @var array
      */
     protected $tables;
 
     /**
+     * The current Table being used.
+     *
+     * @var table
+     */
+    protected $currentTable;
+
+    /**
      * Execute the console command.
      */
     public function handle()
     {
-
-
         // First we need to ensure that the table exists, then we can
-        if (! $this->tableExists($this->getTableInput())) {
+        if (!$this->tableExists($this->getTableInput())) {
             $this->components->error('The table: "'.$this->getTableInput().'" does not exist in the database.');
 
             return false;
         }
 
+        $this->setCurrentTable($this->getTableInput());
+
         $path = $this->getPath();
 
         $file = $this->getFile($path);
 
         $file = $this->apply_replacements($file);
 
+        $file = $this->apply_inserts($file);
+
         $this->makeDirectory($path);
 
         $this->files->put($path, $this->sortImports($file));
 
+        $this->format_file($path);
+
         $info = $this->type;
 
         $this->components->info(sprintf('%s [%s] created successfully.', $info, $path));
@@ -62,15 +71,14 @@
 
     /**
      * Override the original so that we can prompt for a table with autocomplete.
-     *
      */
     protected function promptForMissingArguments(InputInterface $input, OutputInterface $output)
     {
         $prompted = false;
-        if(is_null($input->getArgument('table'))) {
+        if (is_null($input->getArgument('table'))) {
             $prompted = true;
             $table = null;
-            while ($table === null) {
+            while (null === $table) {
                 $table = $this->components->askWithCompletion(
                     'What Table should we use?',
                     $this->possibleTables()
@@ -83,7 +91,7 @@
         parent::promptForMissingArguments($input, $output);
 
         // This will get missed if we prompt here but not in the parent
-        if($prompted) {
+        if ($prompted) {
             $this->afterPromptingForMissingArguments($input, $output);
         }
     }
@@ -133,7 +141,7 @@
     }
 
     /**
-     * Determines if the file exists
+     * Determines if the file exists.
      */
     protected function fileExists(string $path): bool
     {
@@ -144,18 +152,17 @@
      * Gets the file that will be worked on. If there is already an existing file
      * then we can open that. However if we are forcing the operation, then we
      * will start with an empty stub.
-     *
      */
     protected function getFile($name)
     {
-        if ((! $this->hasOption('fresh') ||
-             ! $this->option('fresh')) &&
-             $this->fileExists($name)) {
-            //Working with an existing file
+        if (!($this->hasOption('fresh')
+             && $this->option('fresh'))
+             && $this->fileExists($name)) {
+            // Working with an existing file
             return $this->files->get($name);
         }
 
-        //Working with a stub
+        // Working with a stub
         return $this->files->get($this->getStub());
     }
 
@@ -169,9 +176,8 @@
         return trim($this->argument('table'));
     }
 
-
     /**
-     * Determines if the table exists in the current database
+     * Determines if the table exists in the current database.
      */
     protected function tableExists(string $table_name): bool
     {
@@ -187,7 +193,7 @@
     }
 
     /**
-     * Get the tables in the schema
+     * Get the tables in the schema.
      */
     protected function getTables()
     {
@@ -199,14 +205,38 @@
     }
 
     /**
-     * Get the database schema for DB interactions
+     * Get the database schema for DB interactions.
      */
     protected function getSchema()
     {
         if (is_null($this->schema)) {
-            $this->schema = DB::connection()->getDoctrineSchemaManager();
+            $this->schema = \DB::connection()->getDoctrineSchemaManager();
         }
 
         return $this->schema;
     }
+
+    protected function getTable(string $table_name)
+    {
+        return $this->getSchema()->introspectTable($table_name);
+    }
+
+    protected function getCurrentTable()
+    {
+        return $this->currentTable;
+    }
+
+    protected function setCurrentTable(string $table_name)
+    {
+        $table = null;
+        if (!is_null($table_name) && '' !== trim($table_name)) {
+            $table = $this->getTable($table_name);
+        }
+        $this->currentTable = $table;
+    }
+
+    protected function format_file(string $path)
+    {
+        exec('php-cs-fixer fix '.$path);
+    }
 }
--- a/src/Generator/Controller/ControllerGenerator.php	Wed Apr 24 19:52:35 2024 -0400
+++ b/src/Generator/Controller/ControllerGenerator.php	Wed Apr 24 20:11:52 2024 -0400
@@ -4,8 +4,6 @@
 
 use Symfony\Component\Console\Attribute\AsCommand;
 use Wizzard\MagicForger\Generator\BaseGenerator;
-use Wizzard\MagicForger\Replacer;
-use Illuminate\Support\Str;
 
 #[AsCommand(name: 'mf:controller')]
 class ControllerGenerator extends BaseGenerator
@@ -52,7 +50,8 @@
     /**
      * Resolve the fully-qualified path to the stub.
      *
-     * @param  string  $stub
+     * @param string $stub
+     *
      * @return string
      */
     protected function resolveStubPath($stub)
@@ -74,6 +73,6 @@
      */
     protected function getPath($name = null)
     {
-        return str_replace(['App\\', '\\'], ['app/', '/'], $this->getControllerNamespace() . '/' . $this->controller_name($this->getTableInput()) . '.php');
+        return str_replace(['App\\', '\\'], ['app/', '/'], $this->getControllerNamespace().'/'.$this->controller_name($this->getTableInput()).'.php');
     }
 }
--- a/src/Generator/Controller/stubs/controller.stub	Wed Apr 24 19:52:35 2024 -0400
+++ b/src/Generator/Controller/stubs/controller.stub	Wed Apr 24 20:11:52 2024 -0400
@@ -35,10 +35,13 @@
      */
     public function store({{ storeRequest }} $request)
     {
+				$validated = $request->validated();
+
         //
 				${{ modelVariable }} = new {{ model }}();
 
 				//insert the values into the model
+        ${{ modelVariable }}->map_values($validated);
 
 				${{ modelVariable }}->save();
 
@@ -74,7 +77,11 @@
      */
     public function update({{ updateRequest }} $request, {{ model }} ${{ modelVariable }})
     {
+				$validated = $request->validated();
+
         // Set the variables
+        ${{ modelVariable }}->map_values($validated);
+
 				${{ modelVariable }}->save();
 
 				return redirect()->route('{{ tableName }}.index');
--- a/src/Generator/Generator.php	Wed Apr 24 19:52:35 2024 -0400
+++ b/src/Generator/Generator.php	Wed Apr 24 20:11:52 2024 -0400
@@ -2,16 +2,10 @@
 
 namespace Wizzard\MagicForger\Generator;
 
-use DB;
-
 use Symfony\Component\Console\Attribute\AsCommand;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Input\InputOption;
 use Symfony\Component\Console\Output\OutputInterface;
-use Illuminate\Support\Str;
-
-use Wizzard\MagicForger\Generator\BaseGenerator;
-use Wizzard\MagicForger\Replacer;
 
 #[AsCommand(name: 'mf')]
 class Generator extends BaseGenerator
@@ -30,13 +24,11 @@
      */
     protected $description = 'Generates any (or all) of the available files.';
 
-
     /**
      * Execute the console command.
      */
     public function handle()
     {
-
         // First we need to ensure that the table exists, then we can
         if (!$this->tableExists($this->getTableInput())) {
             $this->components->error('The table: "'.$this->getTableInput().'" does not exist in the database.');
@@ -44,12 +36,17 @@
             return false;
         }
 
+        /* $this->setCurrentTable($this->getTableInput()); */
+        /* dd($this->getCurrentTable()->getForeignKeys()); */
+
         if ($this->option('all')) {
             /* $this->input->setOption('factory', true); */
             /* $this->input->setOption('seed', true); */
             /* $this->input->setOption('migration', true); */
             $this->input->setOption('controller', true);
             $this->input->setOption('model', true);
+            $this->input->setOption('request', true);
+            $this->input->setOption('route', true);
         }
 
         /* if ($this->option('factory')) { */
@@ -72,6 +69,13 @@
             $this->createModel();
         }
 
+        if ($this->option('request')) {
+            $this->createRequest();
+        }
+
+        if ($this->option('route')) {
+            $this->createRoute();
+        }
     }
 
     /**
@@ -81,11 +85,13 @@
      */
     protected function getOptions()
     {
-        return [
+        return array_merge(parent::getOptions(), [
             ['all', 'a', InputOption::VALUE_NONE, 'Generate a migration, seeder, factory, policy, resource controller, and form request classes for the table.'],
             ['controller', 'c', InputOption::VALUE_NONE, 'Generate a controller class for the table.'],
-            ['model', 'm', InputOption::VALUE_NONE, 'Generate a controller class for the table.'],
-        ];
+            ['model', 'm', InputOption::VALUE_NONE, 'Generate a model class for the table.'],
+            ['request', 'r', InputOption::VALUE_NONE, 'Generate base request classes for the table.'],
+            ['route', 'w', InputOption::VALUE_NONE, 'Generate base routes classes for the table.'],
+        ]);
     }
 
     /**
@@ -103,6 +109,21 @@
 
     protected function createController()
     {
-        $this->call('mf:controller', ['table' => $this->getTableInput()]);
+        $this->call('mf:controller', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh')]);
+    }
+
+    protected function createModel()
+    {
+        $this->call('mf:model', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh')]);
+    }
+
+    protected function createRequest()
+    {
+        $this->call('mf:request', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh'), '--all' => true]);
+    }
+
+    protected function createRoute()
+    {
+        $this->call('mf:route', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh')]);
     }
 }
--- a/src/Generator/Model/ModelGenerator.php	Wed Apr 24 19:52:35 2024 -0400
+++ b/src/Generator/Model/ModelGenerator.php	Wed Apr 24 20:11:52 2024 -0400
@@ -1,11 +1,9 @@
 <?php
 
-namespace Wizzard\MagicForger\Generator\Controller;
+namespace Wizzard\MagicForger\Generator\Model;
 
 use Symfony\Component\Console\Attribute\AsCommand;
 use Wizzard\MagicForger\Generator\BaseGenerator;
-use Wizzard\MagicForger\Replacer;
-use Illuminate\Support\Str;
 
 #[AsCommand(name: 'mf:model')]
 class ModelGenerator extends BaseGenerator
@@ -52,7 +50,8 @@
     /**
      * Resolve the fully-qualified path to the stub.
      *
-     * @param  string  $stub
+     * @param string $stub
+    *
      * @return string
      */
     protected function resolveStubPath($stub)
@@ -74,6 +73,6 @@
      */
     protected function getPath($name = null)
     {
-        return str_replace(['App\\', '\\'], ['app/', '/'], $this->getModelNamespace() . '/' . $this->model_name($this->getTableInput()) . '.php');
+        return str_replace(['App\\', '\\'], ['app/', '/'], $this->getModelNamespace().'/'.$this->model_name($this->getTableInput()).'.php');
     }
 }
--- a/src/Generator/Model/stubs/model.pivot.stub	Wed Apr 24 19:52:35 2024 -0400
+++ b/src/Generator/Model/stubs/model.pivot.stub	Wed Apr 24 20:11:52 2024 -0400
@@ -7,4 +7,15 @@
 class {{ class }} extends Pivot
 {
     //
+
+    /**
+     * Indicates if the model should be timestamped.
+		 * By default our pivots will not use timestamps
+     *
+     * @var bool
+     */
+    public $timestamps = false;
+
+
+
 }
--- a/src/Generator/Model/stubs/model.stub	Wed Apr 24 19:52:35 2024 -0400
+++ b/src/Generator/Model/stubs/model.stub	Wed Apr 24 20:11:52 2024 -0400
@@ -4,8 +4,49 @@
 
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
 
 class {{ class }} extends Model
 {
-    use HasFactory;
+    //use HasFactory;
+    use SoftDeletes;
+
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected $table = '{{ tableName }}';
+
+		/**
+     * The model's default values for attributes.
+     *
+     * @var array
+     */
+    protected $attributes = [
+			# {{ atributeInsertPoint }}
+    ];
+
+
+		public static function boot() : void {
+			parent::boot();
+
+			self::creating(function ($item) {
+				$item->created_by = \Auth::user()->id;
+				$item->updated_by = \Auth::user()->id;
+			});
+
+			self::saving(function ($item) {
+				$item->updated_by = \Auth::user()->id;
+			});
+		}
+
+
+		//relations
+
+		// BelongsTo
+
+		// HasMany
+		
+
 }
--- a/src/Generator/Replacer.php	Wed Apr 24 19:52:35 2024 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-<?php
-
-namespace Wizzard\MagicForger\Generator;
-
-use Illuminate\Support\Str;
-
-trait Replacer
-{
-    /**
-     * Prefix and Suffix for controller.
-     * Usage is up to the user.
-     *
-     * @var string
-     */
-    protected $controller_prefix = "";
-
-
-    /**
-     * Prefix and Suffix for controller.
-     * Usage is up to the user.
-     *
-     * @var string
-     */
-    protected $controller_suffix = "Controller";
-
-
-    /**
-     * Finds all places in a string that could be replaced.
-     * Returns an array of all potential replacements as they
-     * appear in the target.
-     */
-    public function get_all_inserts(string $target): array
-    {
-        //find all the matches to our expected syntax
-        $matches = [];
-        preg_match_all('/{{[\sa-zA-Z\-_]+}}/', $target, $matches);
-        // sort the array and return unique values
-        sort($matches[0]);
-        return array_values(array_unique($matches[0]));
-    }
-
-
-    public function apply_replacements(string $target): string
-    {
-        $inserts = $this->get_all_inserts($target);
-        $available_replacements = $this->get_available_replacements();
-
-        $target = str_replace(
-            array_keys($available_replacements),
-            $available_replacements,
-            $target
-        );
-
-        return $target;
-    }
-    /**
-     * @return array<string,mixed>
-     */
-    public function get_available_replacements()
-    {
-        $table_name = $this->getTableInput();
-        $replacements = [
-                    "{{ class }}" => $this->getClassName($table_name),
-                    "{{ model }}" => $this->model_name($table_name),
-                    "{{ modelVariable }}" => $this->model_variable($table_name),
-                    "{{ namespace }}" => $this->{'get' . $this->type . 'Namespace'}(),
-                    "{{ namespacedModel }}" => $this->getModelNamespace(),
-                    "{{ requestUses }}" => $this->getRequestUses($table_name),
-                    "{{ rootNamespace }}" => $this->getRootNamespace(),
-                    "{{ storeRequest }}" => $this->store_request_name($table_name),
-                    "{{ tableName }}" => $table_name,
-                    "{{ updateRequest }}" => $this->update_request_name($table_name),
-        ];
-
-        return $replacements;
-    }
-
-    ////////////////////////////////////////////
-    //				Internals and Classes   				//
-    ////////////////////////////////////////////
-
-    /**
-     * Model names are generated in uppercase first Camel case
-     */
-    public function model_name(string $name): string
-    {
-        return Str::singular(Str::studly($name));
-    }
-
-    /**
-     * Model variable is standardly just a singular version of the table name
-     */
-    public function model_variable(string $name): string
-    {
-        return Str::singular($name);
-    }
-
-    /**
-     * Controller names are generated in uppercase first Camel case
-     * and wrapped in the prefix and suffix
-     */
-    public function controller_name(string $name): string
-    {
-        return $this->controller_prefix .
-            $this->model_name($name) .
-            $this->controller_suffix;
-    }
-
-    public function store_request_name(string $name): string
-    {
-        return 'Store' . $this->model_name($name);
-    }
-
-    public function update_request_name(string $name): string
-    {
-        return 'Update' . $this->model_name($name);
-    }
-
-
-    ////////////////////////////////////////////
-    //							Namespaces			   				//
-    ////////////////////////////////////////////
-
-    public function getRootNamespace()
-    {
-        return $this->laravel->getNamespace();
-    }
-
-    public function getModelNamespace()
-    {
-        return $this->getRootNamespace() . 'Models';
-    }
-
-    public function getControllerNamespace()
-    {
-        return $this->getRootNamespace() . 'Http\\Controllers';
-    }
-
-    public function getRequestNamespace(string $name)
-    {
-        return $this->getRootNamespace() . 'Http\\Requests\\' . $this->model_name($name);
-    }
-    /**
-     * @return string
-     */
-    public function getRequestUses(string $name)
-    {
-        return implode("\n", [
-            "use " . $this->getRequestNamespace($name) . '\\' . $this->store_request_name($name),
-            "use " . $this->getRequestNamespace($name) . '\\' . $this->update_request_name($name),
-        ]);
-    }
-
-
-    ////////////////////////////////////////////
-    //				Language and Presentables				//
-    ////////////////////////////////////////////
-
-    /**
-     * Breaks up a string and makes it human readable
-     *
-     * This function assumes that the inputted name is camel case
-     */
-    public function human_readable(string $name): string
-    {
-        return Str::title(Str::replace('_', ' ', $name));
-    }
-
-    /**
-     * Breaks up a string and makes it human readable and lowecase
-     *
-     * This function assumes that the inputted name is camel case
-     */
-    public function human_readable_lc(string $name): string
-    {
-        return Str::lower($this->human_readable($name));
-    }
-}
-
-class Replacer
-{
-    /**
-     * @return void
-     */
-    public function get_available_replacements(): array
-    {
-    }
-
-    public function getRequestUses(): string
-    {
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/Requests/RequestGenerator.php	Wed Apr 24 20:11:52 2024 -0400
@@ -0,0 +1,102 @@
+<?php
+
+namespace Wizzard\MagicForger\Generator\Requests;
+
+use Symfony\Component\Console\Attribute\AsCommand;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Wizzard\MagicForger\Generator\BaseGenerator;
+
+#[AsCommand(name: 'mf:request')]
+class RequestGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:request';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the Request File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'Request';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        // First we need to ensure that the table exists, then we can
+        if (!$this->tableExists($this->getTableInput())) {
+            $this->components->error('The table: "'.$this->getTableInput().'" does not exist in the database.');
+
+            return false;
+        }
+
+        if ($this->option('all')) {
+            $this->input->setOption('store_request', true);
+            $this->input->setOption('update_request', true);
+        }
+
+        if ($this->option('store_request')) {
+            $this->createStoreRequest();
+        }
+
+        if ($this->option('update_request')) {
+            $this->createUpdateRequest();
+        }
+    }
+
+    /**
+     * Get the console command options.
+     *
+     * @return array
+     */
+    protected function getOptions()
+    {
+        return array_merge(parent::getOptions(), [
+            ['all', 'a', InputOption::VALUE_NONE, 'Generate all request classes for the table.'],
+            ['store_request', 's', InputOption::VALUE_NONE, 'Generate store request class for the table.'],
+            ['update_request', 'u', InputOption::VALUE_NONE, 'Generate update request class for the table.'],
+        ]);
+    }
+
+    /**
+     * Interact further with the user if they were prompted for missing arguments.
+     *
+     * @return void
+     */
+    protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output)
+    {
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub()
+    {
+    }
+
+    protected function createStoreRequest()
+    {
+        $this->call('mf:store_request', ['table' => $this->getTableInput()]);
+    }
+
+    protected function createUpdateRequest()
+    {
+        $this->call('mf:update_request', ['table' => $this->getTableInput()]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/Requests/StoreRequestGenerator.php	Wed Apr 24 20:11:52 2024 -0400
@@ -0,0 +1,78 @@
+<?php
+
+namespace Wizzard\MagicForger\Generator\Requests;
+
+use Symfony\Component\Console\Attribute\AsCommand;
+use Wizzard\MagicForger\Generator\BaseGenerator;
+
+#[AsCommand(name: 'mf:store_request')]
+class StoreRequestGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:store_request';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the StoreRequest File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'StoreRequest';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        parent::handle();
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub()
+    {
+        return $this->resolveStubPath('/stubs/request.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->store_request_name($name);
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getPath($name = null)
+    {
+        return str_replace(['App\\', '\\'], ['app/', '/'], $this->getRequestNamespace($this->getTableInput()).'/'.$this->store_request_name($this->getTableInput()).'.php');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/Requests/UpdateRequestGenerator.php	Wed Apr 24 20:11:52 2024 -0400
@@ -0,0 +1,78 @@
+<?php
+
+namespace Wizzard\MagicForger\Generator\Requests;
+
+use Symfony\Component\Console\Attribute\AsCommand;
+use Wizzard\MagicForger\Generator\BaseGenerator;
+
+#[AsCommand(name: 'mf:update_request')]
+class UpdateRequestGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:update_request';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the UpdateRequest File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'UpdateRequest';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        parent::handle();
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub()
+    {
+        return $this->resolveStubPath('/stubs/request.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->update_request_name($name);
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getPath($name = null)
+    {
+        return str_replace(['App\\', '\\'], ['app/', '/'], $this->getRequestNamespace($this->getTableInput()).'/'.$this->update_request_name($this->getTableInput()).'.php');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/Requests/stubs/request.stub	Wed Apr 24 20:11:52 2024 -0400
@@ -0,0 +1,28 @@
+<?php
+
+namespace {{ namespace }};
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class {{ class }} extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     */
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array|string>
+     */
+    public function rules(): array
+    {
+        return [
+            // {{ valuesForValidation }} 
+        ];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/Route/RouteGenerator.php	Wed Apr 24 20:11:52 2024 -0400
@@ -0,0 +1,78 @@
+<?php
+
+namespace Wizzard\MagicForger\Generator\Route;
+
+use Symfony\Component\Console\Attribute\AsCommand;
+use Wizzard\MagicForger\Generator\BaseGenerator;
+
+#[AsCommand(name: 'mf:routes')]
+class RouteGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:routes';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the Route File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'Route';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        parent::handle();
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub()
+    {
+        return $this->resolveStubPath('/stubs/routes.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->routes_name($name);
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getPath($name = null)
+    {
+        return str_replace(['App\\', '\\'], ['app/', '/'], $this->getRouteNamespace().'/'.$this->routes_name($this->getTableInput()).'.php');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/Route/stubs/route.stub	Wed Apr 24 20:11:52 2024 -0400
@@ -0,0 +1,13 @@
+<?php
+Route::controller({{ controllerName }}::class)
+	->prefix('{{ tableName }}') 
+	->alias('{{ tableName }}.')
+	->group( function () {
+		Route::get('/', 'index')->name('index');
+		Route::get('/create', 'create')->name('create');
+		Route::get('/edit', 'edit')->name('edit');
+
+		Route::post('/store', 'store')->name('store');
+		Route::put('/udpate/{id}', 'update')->name('update');
+		Route::delete('/delete/{id}', 'delete')->name('delete');
+	});
--- a/src/Helpers/Replacer.php	Wed Apr 24 19:52:35 2024 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-<?php
-
-namespace Magicforger\Helpers;
-
-
-/*
- * Replacer
- *
- * A class that handles all replacements necessary
- *
- * General flow:
- * Read a line looking for a replacement string
- * 
- * A replacement string will consist of 2 values
- * Reference Object, and Replacement Function
- *
- * After the replacement is made, the Object, function
- * are stored in an array to be cached for future replacements
- *
- * Basically lazy loading the replacements.
- * */
-class Replacer {
-
-
-/*
- * The array of cached replacements 
- *
- * Object name => [
- * 	function => replacement text,
- * ]
- *
- * */
-protected $replacement_cache [];
-
-
-/*
- * Static instance of inflector for 
- * string manipulation.
- *
- * */
-private static $inflector = null;
-
-public function __construct() {
-	if(is_null(self::$inflector)) {
-		self::$inflector = InflectorFactory::create()->build();
-	}
-}
-
-
-
-
-protected function extract_replacement_values(string $replacement_string): string {
-	$matches = [];
-	preg_match('/o:([^\s]+)\s+f:([^\s]+)/', $replacement_string, $matches);
-	$name = $matches[1];
-	$function = $matches[2];
-
-	return ['name' => $name, 'function' => $function];
-}
-
-protected function get_replacement(string $replacement_string): string {
-
-	
-
-
-	return $replacement;
-}
-
-
-
-
-}
--- a/src/MagicForgerServiceProvider.php	Wed Apr 24 19:52:35 2024 -0400
+++ b/src/MagicForgerServiceProvider.php	Wed Apr 24 20:11:52 2024 -0400
@@ -3,9 +3,13 @@
 namespace Wizzard\MagicForger;
 
 use Illuminate\Support\ServiceProvider;
+use Wizzard\MagicForger\Generator\Controller\ControllerGenerator;
 use Wizzard\MagicForger\Generator\Generator;
-use Wizzard\MagicForger\Generator\Controller\ControllerGenerator;
 use Wizzard\MagicForger\Generator\Model\ModelGenerator;
+use Wizzard\MagicForger\Generator\Requests\RequestGenerator;
+use Wizzard\MagicForger\Generator\Requests\StoreRequestGenerator;
+use Wizzard\MagicForger\Generator\Requests\UpdateRequestGenerator;
+use Wizzard\MagicForger\Generator\Route\RouteGenerator;
 
 class MagicForgerServiceProvider extends ServiceProvider
 {
@@ -19,7 +23,18 @@
                 Generator::class,
                 ControllerGenerator::class,
                 ModelGenerator::class,
+                RequestGenerator::class,
+                StoreRequestGenerator::class,
+                UpdateRequestGenerator::class,
+                RouteGenerator::class,
             ]);
         }
+
+        $this->register_config_helper();
+    }
+
+    public function register_config_helper()
+    {
+        ConfigHelper::setup_config_path(base_path());
     }
 }
--- a/src/Replacer.php	Wed Apr 24 19:52:35 2024 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<?php
-
-namespace Wizzard\MagicForger;
-
-use Illuminate\Support\Str;
-
-class Replacer
-{
-    /**
-     * Cached replacements for re-use.
-     *
-     * @var array
-     */
-    protected $replacement_cache = [];
-
-
-
-
-    /**
-     * The lowest level to show log outputs.
-     *
-     * @var int
-     */
-    private $log_level = 1;
-
-
-    public function __construct()
-    {
-        /* parent::__construct(); */
-    }
-
-
-    /**
-     * Outputs a log for the replacements based on log level.
-     */
-    public function log(string $str, int $log_level = 1): void
-    {
-
-        if($this->log_level <= $log_level) {
-            print($str . "\n");
-        }
-
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Replacer/Replacer.php	Wed Apr 24 20:11:52 2024 -0400
@@ -0,0 +1,192 @@
+<?php
+
+namespace Wizzard\MagicForger\Replacer;
+
+use Illuminate\Support\Str;
+
+trait Replacer
+{
+    /**
+     * Prefix and Suffix for controller.
+     * Usage is up to the user.
+     *
+     * @var string
+     */
+    protected $controller_prefix = '';
+
+    /**
+     * Prefix and Suffix for controller.
+     * Usage is up to the user.
+     *
+     * @var string
+     */
+    protected $controller_suffix = 'Controller';
+
+    /**
+     * Finds all places in a string that could be replaced.
+     * Returns an array of all potential replacements as they
+     * appear in the target.
+     */
+    public function get_all_keywords(string $target): array
+    {
+        // find all the matches to our expected syntax
+        $matches = [];
+        preg_match_all('/{{[\sa-zA-Z\-_]+}}/', $target, $matches);
+        // sort the array and return unique values
+        sort($matches[0]);
+
+        return array_values(array_unique($matches[0]));
+    }
+
+    public function apply_replacements(string $target): string
+    {
+        $inserts = $this->get_all_keywords($target);
+        $available_replacements = $this->get_available_replacements();
+
+        $target = str_replace(
+            array_keys($available_replacements),
+            $available_replacements,
+            $target
+        );
+
+        return $target;
+    }
+
+    public function get_available_replacements()
+    {
+        $table_name = $this->getTableInput();
+        $replacements = [
+                    '{{ class }}' => $this->getClassName($table_name),
+                    '{{ controllerName }}' => $this->controller_name($table_name),
+                    '{{ model }}' => $this->model_name($table_name),
+                    '{{ modelVariable }}' => $this->model_variable($table_name),
+                    '{{ namespace }}' => $this->{'get'.$this->type.'Namespace'}($table_name),
+                    '{{ namespacedModel }}' => $this->getNamespacedModel($table_name),
+                    '{{ requestUses }}' => $this->getRequestUses($table_name),
+                    '{{ rootNamespace }}' => $this->getRootNamespace(),
+                    '{{ storeRequest }}' => $this->store_request_name($table_name),
+                    '{{ tableName }}' => $table_name,
+                    '{{ updateRequest }}' => $this->update_request_name($table_name),
+        ];
+
+        return $replacements;
+    }
+
+    // //////////////////////////////////////////
+    //				Internals and Classes   				//
+    // //////////////////////////////////////////
+
+    /**
+     * Model names are generated in uppercase first Camel case.
+     */
+    public function model_name(string $name): string
+    {
+        return Str::singular(Str::studly($name));
+    }
+
+    /**
+     * Model variable is standardly just a singular version of the table name.
+     */
+    public function model_variable(string $name): string
+    {
+        return Str::singular($name);
+        /* return 'item'; */
+    }
+
+    /**
+     * Controller names are generated in uppercase first Camel case
+     * and wrapped in the prefix and suffix.
+     */
+    public function controller_name(string $name): string
+    {
+        return $this->controller_prefix.
+            $this->model_name($name).
+            $this->controller_suffix;
+    }
+
+    public function store_request_name(string $name): string
+    {
+        return 'Store'.$this->model_name($name).'Request';
+    }
+
+    public function update_request_name(string $name): string
+    {
+        return 'Update'.$this->model_name($name).'Request';
+    }
+
+    // //////////////////////////////////////////
+    //							Namespaces			   				//
+    // //////////////////////////////////////////
+
+    public function getRootNamespace()
+    {
+        return $this->laravel->getNamespace();
+    }
+
+    public function getModelNamespace(string $name = '')
+    {
+        return $this->getRootNamespace().'Models';
+    }
+
+    public function getNamespacedModel(string $name = '')
+    {
+        return $this->getModelNamespace().'\\'.$this->model_name($name);
+    }
+
+    public function getControllerNamespace(string $name = '')
+    {
+        return $this->getRootNamespace().'Http\\Controllers';
+    }
+
+    public function getRequestNamespace(string $name)
+    {
+        return $this->getRootNamespace().'Http\\Requests\\'.$this->model_name($name);
+    }
+
+    public function getStoreRequestNamespace(string $name)
+    {
+        return $this->getRequestNamespace($name);
+    }
+
+    public function getUpdateRequestNamespace(string $name)
+    {
+        return $this->getRequestNamespace($name);
+    }
+
+    public function getRequestUses(string $name)
+    {
+        return implode("\n", [
+            'use '.$this->getRequestNamespace($name).'\\'.$this->store_request_name($name).';',
+            'use '.$this->getRequestNamespace($name).'\\'.$this->update_request_name($name).';',
+        ]);
+    }
+
+    public function getRouteNamespace(string $name = '')
+    {
+        return $this->getRootNamespace().'Http\\Controllers';
+    }
+
+    // //////////////////////////////////////////
+    //				Language and Presentables				//
+    // //////////////////////////////////////////
+
+    /**
+     * Breaks up a string and makes it human readable.
+     *
+     * This function assumes that the inputted name is camel case
+     */
+    public function human_readable(string $name): string
+    {
+        return Str::title(Str::replace('_', ' ', $name));
+    }
+
+    /**
+     * Breaks up a string and makes it human readable and lowecase.
+     *
+     * This function assumes that the inputted name is camel case
+     */
+    public function human_readable_lc(string $name): string
+    {
+        return Str::lower($this->human_readable($name));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Replacer/TableReplacer.php	Wed Apr 24 20:11:52 2024 -0400
@@ -0,0 +1,81 @@
+<?php
+
+namespace Wizzard\MagicForger\Replacer;
+
+trait TableReplacer
+{
+    protected $columns;
+
+    protected function get_columns()
+    {
+        if (is_null($this->columns)) {
+            $this->columns = $this->getCurrentTable()->getColumns();
+        }
+
+        return $this->columns;
+    }
+
+    protected function get_attributes()
+    {
+    }
+
+    protected function getValuesForCreation()
+    {
+        $insert = '';
+        foreach ($this->get_columns() as $column) {
+            $insert .= '$item->'.$column->getName().' = $validated["'.$column->getName().'"] ?? NULL;'."\n";
+        }
+
+        return $insert;
+    }
+
+    protected function getAttributes()
+    {
+        $insert = '';
+        foreach ($this->get_columns() as $column) {
+            $insert .= "'".$column->getName()."' => '',\n";
+        }
+
+        return $insert;
+    }
+
+    protected function getValuesForValidation()
+    {
+        $insert = '';
+        foreach ($this->get_columns() as $column) {
+            $insert .= "'".$column->getName()."' => 'nullable',\n";
+        }
+
+        return $insert;
+    }
+
+    public function apply_inserts(string $target): string
+    {
+        $inserts = $this->get_all_keywords($target);
+        $available_replacements = $this->get_available_inserts();
+
+        $target = str_replace(
+            array_keys($available_replacements),
+            $available_replacements,
+            $target
+        );
+
+        return $target;
+    }
+
+    public function get_available_inserts()
+    {
+        $table_name = $this->getTableInput();
+        $replacements = [
+                        '// {{ valuesForCreation }}' => self::getValuesForCreation(),
+                        '# {{ atributeInsertPoint }}' => self::getAttributes(),
+            						'// {{ valuesForValidation }}' => self::getValuesForValidation(),
+			        ];
+
+        foreach ($replacements as $key => &$replacement) {
+            $replacement = $replacement."\n".$key;
+        }
+
+        return $replacements;
+    }
+}