Repository: ryangjchandler/orbit (php)

Issue:
Add a generator command
While it is useful to jump into tinker or tinkerwell and just `Post::create()` it would be cool if you could have an interactive CLI so you could:

```bash
php artisan orbit:generate ModelName
```

Which would then ask you to give a name/title depending on how the model is routed.

Pull request:
feature: add orbit:generate command
Closes #65.

This pull request introduces a new `orbit:generate` command that will look at the `schema` definition for the model and ask you to enter data for each column.

It can be used like so:

```bash
artisan orbit:generate Post
```

This will look for either an `App\Post` class or `App\Models\Post` class and use the `schema` definition. It will then use `$this->ask()` to get the data.

**Todo**:
* [x] Convert stringy booleans to actual booleans, i.e. `'true` => true`.
* [x] Check if a column is nullable and convert empty string to `null`.

Patch:
diff --git a/src/Commands/GenerateCommand.php b/src/Commands/GenerateCommand.php
new file mode 100644
index 0000000..11007a6
--- /dev/null
+++ b/src/Commands/GenerateCommand.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Orbit\Commands;
+
+use Illuminate\Support\Str;
+use Illuminate\Console\Command;
+use Illuminate\Support\Collection;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Schema\ColumnDefinition;
+
+class GenerateCommand extends Command
+{
+    protected $signature = 'orbit:generate {model}';
+
+    protected $description = 'Quickly create a new Orbit record.';
+
+    public function handle()
+    {
+        $model = $this->qualifyModelClass();
+        $data = $this->getColumnsFromModel($model)->mapWithKeys(function (ColumnDefinition $column, string $name): array {
+            $value = $this->ask(Str::title($name));
+
+            if ($column->get('nullable', false) && ($value === '' || $value === 'null')) {
+                $value = null;
+            } elseif ($value === 'true' && $column->get('type') === 'boolean') {
+                $value = true;
+            } elseif ($value === 'false' && $column->get('type') === 'boolean') {
+                $value = false;
+            }
+
+            return [$name => $value];
+        })->all();
+
+        /**
+         * @psalm-suppress InvalidStringClass
+         */
+        $model::create($data);
+
+        $this->info('Model created successfully.');
+    }
+
+    protected function getColumnsFromModel(string $modelClass): Collection
+    {
+        $blueprint = new Blueprint('__orbit:generate__');
+
+        /**
+         * @psalm-suppress InvalidStringClass
+         */
+        $modelClass::schema($blueprint);
+
+        return collect($blueprint->getColumns())->mapWithKeys(function (ColumnDefinition $column): array {
+            return [
+                $column->getAttributes()['name'] => $column
+            ];
+        });
+    }
+
+    protected function qualifyModelClass(): string
+    {
+        $rootNamespace = app()->getNamespace();
+
+        $prefixes = [
+            $rootNamespace,
+            $rootNamespace.'Models\\',
+        ];
+
+        foreach ($prefixes as $prefix) {
+            $namespaced = $prefix.$this->argument('model');
+
+            if (class_exists($namespaced)) {
+                return $namespaced;
+            }
+        }
+
+        $this->error('Model does not exist.');
+
+        exit(1);
+    }
+}
diff --git a/src/OrbitServiceProvider.php b/src/OrbitServiceProvider.php
index e2c1c79..8f11da7 100644
--- a/src/OrbitServiceProvider.php
+++ b/src/OrbitServiceProvider.php
@@ -54,6 +54,7 @@ class OrbitServiceProvider extends ServiceProvider
                 Commands\FreshCommand::class,
                 Commands\PullCommand::class,
                 Commands\CommitCommand::class,
+                Commands\GenerateCommand::class,
             ]);
 
             $this->publishes([


Test patch:
diff --git a/testbench.yaml b/testbench.yaml
new file mode 100644
index 0000000..a3a85e8
--- /dev/null
+++ b/testbench.yaml
@@ -0,0 +1,2 @@
+providers:
+  - Orbit\OrbitServiceProvider