From 62648bec4e13c8d53e0e62e01dac76591c810a64 Mon Sep 17 00:00:00 2001 From: Ryan Chandler Date: Mon, 2 Oct 2023 23:24:19 +0100 Subject: [PATCH] wip --- TODO.md | 4 +- composer.json | 4 +- config/orbit.php | 10 +++ src/Actions/InitialiseOrbitalTable.php | 39 +++++++++++ src/Actions/MaybeCreateOrbitDirectories.php | 26 +++++++ src/Actions/SaveCompiledAttributesToFile.php | 20 ++++++ src/Concerns/Orbital.php | 71 ++++++++++++++++++++ src/Contracts/Driver.php | 5 ++ src/Contracts/{Orbital.php => Orbit.php} | 4 +- src/Drivers/Markdown.php | 5 ++ src/Exceptions/InvalidDriverException.php | 13 ++++ src/OrbitServiceProvider.php | 13 ++-- src/Support/ModelAttributeFormatter.php | 26 +++++++ testbench.yaml | 2 + tests/Feature/Orbital/CreateTest.php | 17 +++++ tests/Fixtures/Models/Post.php | 22 ++++++ tests/Pest.php | 43 +----------- tests/TestCase.php | 5 +- 18 files changed, 272 insertions(+), 57 deletions(-) create mode 100644 config/orbit.php create mode 100644 src/Actions/InitialiseOrbitalTable.php create mode 100644 src/Actions/MaybeCreateOrbitDirectories.php create mode 100644 src/Actions/SaveCompiledAttributesToFile.php create mode 100644 src/Concerns/Orbital.php rename src/Contracts/{Orbital.php => Orbit.php} (80%) create mode 100644 src/Exceptions/InvalidDriverException.php create mode 100644 src/Support/ModelAttributeFormatter.php create mode 100644 testbench.yaml create mode 100644 tests/Feature/Orbital/CreateTest.php create mode 100644 tests/Fixtures/Models/Post.php diff --git a/TODO.md b/TODO.md index 64f0fed..2ca701c 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,7 @@ # Todo -* [ ] Model database initialisation. -* [ ] Create new file for new models. +* [x] Model database initialisation. +* [x] Create new file for new models. * [ ] Update file when updating a model. * [ ] Delete file when deleting a model. * [ ] Add support for soft deletes. diff --git a/composer.json b/composer.json index 0783070..0f585f3 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "laravel/pint": "^1.13", "laravel/scout": "^9.4", "nunomaduro/larastan": "^2.0", - "orchestra/testbench": "^8.0", + "orchestra/testbench": "^8.12", "pestphp/pest": "^2.20", "pestphp/pest-plugin-laravel": "^2.2", "phpstan/extension-installer": "^1.1", @@ -48,7 +48,7 @@ }, "autoload-dev": { "psr-4": { - "Orbit\\Tests\\": "tests/" + "Tests\\": "tests/" } }, "minimum-stability": "dev", diff --git a/config/orbit.php b/config/orbit.php new file mode 100644 index 0000000..7899fe0 --- /dev/null +++ b/config/orbit.php @@ -0,0 +1,10 @@ + [ + 'database' => base_path('framework/cache/orbit/database.sqlite'), + 'content' => base_path('content'), + ], + +]; diff --git a/src/Actions/InitialiseOrbitalTable.php b/src/Actions/InitialiseOrbitalTable.php new file mode 100644 index 0000000..8c1b795 --- /dev/null +++ b/src/Actions/InitialiseOrbitalTable.php @@ -0,0 +1,39 @@ +resolveConnection()->getSchemaBuilder(); + + return $schemaBuilder->hasTable($model->getTable()); + } + + public function migrate(Orbit & Model $model): void + { + $table = $model->getTable(); + $schemaBuilder = $model->resolveConnection()->getSchemaBuilder(); + + if ($schemaBuilder->hasTable($table)) { + $schemaBuilder->drop($table); + } + + $blueprint = null; + + $schemaBuilder->create($table, static function (Blueprint $table) use (&$blueprint, $model) { + $blueprint = $table; + + $model->schema($blueprint); + + if ($model->usesTimestamps()) { + $blueprint->timestamps(); + } + }); + } +} diff --git a/src/Actions/MaybeCreateOrbitDirectories.php b/src/Actions/MaybeCreateOrbitDirectories.php new file mode 100644 index 0000000..0fe063a --- /dev/null +++ b/src/Actions/MaybeCreateOrbitDirectories.php @@ -0,0 +1,26 @@ +ensureDirectoryExists(config('orbit.paths.content')); + $fs->ensureDirectoryExists(dirname(config('orbit.paths.database'))); + + if (! $fs->exists(config('orbit.paths.database'))) { + $fs->put(config('orbit.paths.database'), ''); + } + + $modelDirectory = config('orbit.paths.content') . DIRECTORY_SEPARATOR . $model->getTable(); + + $fs->ensureDirectoryExists($modelDirectory); + } +} diff --git a/src/Actions/SaveCompiledAttributesToFile.php b/src/Actions/SaveCompiledAttributesToFile.php new file mode 100644 index 0000000..5487b34 --- /dev/null +++ b/src/Actions/SaveCompiledAttributesToFile.php @@ -0,0 +1,20 @@ +getTable(); + $filename = "{$model->getKey()}.{$driver->extension()}"; + + $fs = new Filesystem(); + $fs->put($directory . DIRECTORY_SEPARATOR . $filename, $compiledAttributes); + } +} diff --git a/src/Concerns/Orbital.php b/src/Concerns/Orbital.php new file mode 100644 index 0000000..3b7e7c2 --- /dev/null +++ b/src/Concerns/Orbital.php @@ -0,0 +1,71 @@ +execute($model); + + $driver = $model->getOrbitDriver(); + + if (!class_exists($driver)) { + throw InvalidDriverException::make($driver); + } + + $driver = app($driver); + + if (!$driver instanceof Driver) { + throw InvalidDriverException::make($driver::class); + } + + $initialiseOrbitTable = new InitialiseOrbitalTable(); + + if (! $initialiseOrbitTable->hasTable($model)) { + $initialiseOrbitTable->migrate($model); + } + + $saveCompiledAttributesToFile = new SaveCompiledAttributesToFile(); + + static::created(function (Orbit & Model $model) use ($driver, $saveCompiledAttributesToFile) { + $model->refresh(); + + $attributes = ModelAttributeFormatter::format($model, $model->getAttributes()); + $compiledAttributes = $driver->compile($attributes); + + $saveCompiledAttributesToFile->execute($model, $compiledAttributes, $driver); + }); + } + + public static function resolveConnection($connection = null) + { + return static::$resolver->connection('orbit'); + } + + public function getConnectionName() + { + return 'orbit'; + } + + public function getOrbitDriver(): string + { + return Markdown::class; + } +} diff --git a/src/Contracts/Driver.php b/src/Contracts/Driver.php index 0fbe134..d8f7d54 100644 --- a/src/Contracts/Driver.php +++ b/src/Contracts/Driver.php @@ -13,4 +13,9 @@ public function parse(string $fileContents): array; * Use the given array of attributes to generate the contents of a file. */ public function compile(array $attributes): string; + + /** + * Specify the file extension used by this driver. + */ + public function extension(): string; } diff --git a/src/Contracts/Orbital.php b/src/Contracts/Orbit.php similarity index 80% rename from src/Contracts/Orbital.php rename to src/Contracts/Orbit.php index e7765a2..018e32d 100644 --- a/src/Contracts/Orbital.php +++ b/src/Contracts/Orbit.php @@ -4,12 +4,12 @@ use Illuminate\Database\Schema\Blueprint; -interface Orbital +interface Orbit { /** * Define the structure of your Orbital model. */ - public static function schema(Blueprint $table): void; + public function schema(Blueprint $table): void; /** * Declare which driver the Orbital should use. diff --git a/src/Drivers/Markdown.php b/src/Drivers/Markdown.php index 07aeece..77b3085 100644 --- a/src/Drivers/Markdown.php +++ b/src/Drivers/Markdown.php @@ -25,4 +25,9 @@ public function compile(array $attributes): string return sprintf("---\n%s\n---\n\n%s", Yaml::dump($attributes), $content); } + + public function extension(): string + { + return 'md'; + } } diff --git a/src/Exceptions/InvalidDriverException.php b/src/Exceptions/InvalidDriverException.php new file mode 100644 index 0000000..abc8a3d --- /dev/null +++ b/src/Exceptions/InvalidDriverException.php @@ -0,0 +1,13 @@ +hasInstallCommand(function (InstallCommand $command) { $command ->startWith(function () { - $fs = new Filesystem(); - - $fs->ensureDirectoryExists(base_path('content')); - $fs->ensureDirectoryExists(storage_path('framework/cache/orbit')); - $fs->ensureDirectoryExists(storage_path('framework/cache/orbit/database.sqlite')); + $maybeCreateOrbitDirectories = new MaybeCreateOrbitDirectories(); + $maybeCreateOrbitDirectories->execute(); }) ->askToStarRepoOnGitHub('ryangjchandler/orbit'); - }); + }) + ->hasConfigFile(); } public function packageRegistered() @@ -33,7 +32,7 @@ public function packageRegistered() $config->set('database.connections.orbit', [ 'driver' => 'sqlite', - 'database' => base_path('framework/cache/orbit/database.sqlite'), + 'database' => $config->get('orbit.paths.database'), 'foreign_key_constraints' => false, ]); } diff --git a/src/Support/ModelAttributeFormatter.php b/src/Support/ModelAttributeFormatter.php new file mode 100644 index 0000000..39975a8 --- /dev/null +++ b/src/Support/ModelAttributeFormatter.php @@ -0,0 +1,26 @@ + $value) { + $value = $model->{$key}; + + $formatted[$key] = match (true) { + $value instanceof BackedEnum => $value->value, + default => $value, + }; + } + + return $formatted; + } +} 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 diff --git a/tests/Feature/Orbital/CreateTest.php b/tests/Feature/Orbital/CreateTest.php new file mode 100644 index 0000000..fe46528 --- /dev/null +++ b/tests/Feature/Orbital/CreateTest.php @@ -0,0 +1,17 @@ + 'Example Post', + ]); + + expect(base_path("content/posts/{$post->id}.md")) + ->toBeFile() + ->and(file_get_contents(base_path("content/posts/{$post->id}.md"))) + ->toContain(<<id + title: 'Example Post' + MD); +}); diff --git a/tests/Fixtures/Models/Post.php b/tests/Fixtures/Models/Post.php new file mode 100644 index 0000000..c881d9f --- /dev/null +++ b/tests/Fixtures/Models/Post.php @@ -0,0 +1,22 @@ +id(); + $table->string('title'); + $table->longText('content')->nullable(); + } +} diff --git a/tests/Pest.php b/tests/Pest.php index 5949c61..14d24b3 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,45 +1,4 @@ in('Feature'); - -/* -|-------------------------------------------------------------------------- -| Expectations -|-------------------------------------------------------------------------- -| -| When you're writing tests, you often need to check that values meet certain conditions. The -| "expect()" function gives you access to a set of "expectations" methods that you can use -| to assert different things. Of course, you may extend the Expectation API at any time. -| -*/ - -expect()->extend('toBeOne', function () { - return $this->toBe(1); -}); - -/* -|-------------------------------------------------------------------------- -| Functions -|-------------------------------------------------------------------------- -| -| While Pest is very powerful out-of-the-box, you may have some testing code specific to your -| project that you don't want to repeat in every file. Here you can also expose helpers as -| global functions to help you to reduce the number of lines of code in your test files. -| -*/ - -function something() -{ - // .. -} +uses(Tests\TestCase::class)->in('Feature'); diff --git a/tests/TestCase.php b/tests/TestCase.php index cfb05b6..612af18 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,9 +2,10 @@ namespace Tests; -use PHPUnit\Framework\TestCase as BaseTestCase; +use Orchestra\Testbench\Concerns\WithWorkbench; +use Orchestra\Testbench\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase { - // + use WithWorkbench; }