From 8b00ac5f16622737ad3d357ea2ac4b89fe142143 Mon Sep 17 00:00:00 2001 From: Ryan Chandler Date: Wed, 24 Mar 2021 18:52:03 +0000 Subject: [PATCH 1/4] feature: MarkdownJson driver --- config/orbit.php | 1 + src/Drivers/MarkdownJson.php | 44 ++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/Drivers/MarkdownJson.php diff --git a/config/orbit.php b/config/orbit.php index 211d345..6227bef 100644 --- a/config/orbit.php +++ b/config/orbit.php @@ -8,6 +8,7 @@ 'md' => \Orbit\Drivers\Markdown::class, 'json' => \Orbit\Drivers\Json::class, 'yaml' => \Orbit\Drivers\Yaml::class, + 'md_json' => \Orbit\Drivers\MarkdownJson::class, ], 'paths' => [ diff --git a/src/Drivers/MarkdownJson.php b/src/Drivers/MarkdownJson.php new file mode 100644 index 0000000..0bfcd68 --- /dev/null +++ b/src/Drivers/MarkdownJson.php @@ -0,0 +1,44 @@ +attributesToArray(), function ($value, $key) { + return $key !== 'content' && $value !== null; + }, ARRAY_FILTER_USE_BOTH); + + $json = json_encode($matter, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + + return implode(PHP_EOL, [ + '---', + rtrim($json, PHP_EOL), + '---', + $model->getAttribute('content'), + ]); + } + + protected function parseContent(SplFileInfo $file): array + { + $content = file_get_contents($file->getPathname()); + + $pattern = '/^[\s\r\n]?---[\s\r\n]?$/sm'; + + $parts = preg_split($pattern, PHP_EOL . ltrim($content)); + + $matter = count($parts) < 3 ? [] : json_decode(trim($parts[1]), true); + + $body = implode(PHP_EOL.'---'.PHP_EOL, array_slice($parts, 2)); + + return array_merge( + $matter, + ['content' => trim($body)] + ); + } +} From ce6d0aebf84f5ca16014c8a13f65b242b768f070 Mon Sep 17 00:00:00 2001 From: Ryan Chandler Date: Thu, 25 Mar 2021 09:31:19 +0000 Subject: [PATCH 2/4] tests: markdown json --- tests/AdvancedOrbitalTest.php | 10 +++++++++ tests/BasicOrbitalTest.php | 2 +- tests/Fixtures/MarkdownJsonModel.php | 31 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/Fixtures/MarkdownJsonModel.php diff --git a/tests/AdvancedOrbitalTest.php b/tests/AdvancedOrbitalTest.php index b5f0e38..1d9aa80 100644 --- a/tests/AdvancedOrbitalTest.php +++ b/tests/AdvancedOrbitalTest.php @@ -4,6 +4,7 @@ use Orbit\Tests\Fixtures\CustomKey; use Orbit\Tests\Fixtures\JsonModel; +use Orbit\Tests\Fixtures\MarkdownJsonModel; use Orbit\Tests\Fixtures\YamlModel; class AdvancedOrbitalTest extends TestCase @@ -57,4 +58,13 @@ public function test_it_can_use_yaml_driver() $this->assertFileExists(__DIR__.'/content/yaml_models/'.$yaml->getKey().'.yml'); } + + public function test_it_can_use_markdown_json_driver() + { + $md = MarkdownJsonModel::create([ + 'name' => 'Ryan', + ]); + + $this->assertFileExists(__DIR__.'/content/markdown_json_models/'.$md->getKey().'.md'); + } } diff --git a/tests/BasicOrbitalTest.php b/tests/BasicOrbitalTest.php index 9a82a6f..8895613 100644 --- a/tests/BasicOrbitalTest.php +++ b/tests/BasicOrbitalTest.php @@ -5,7 +5,7 @@ use Orbit\Tests\Fixtures\Post; use Orbit\Tests\Fixtures\Emptiness; -class OrbitalTest extends TestCase +class BasicOrbitalTest extends TestCase { public function tearDown(): void { diff --git a/tests/Fixtures/MarkdownJsonModel.php b/tests/Fixtures/MarkdownJsonModel.php new file mode 100644 index 0000000..399f412 --- /dev/null +++ b/tests/Fixtures/MarkdownJsonModel.php @@ -0,0 +1,31 @@ +string('name'); + } + + public function getKeyName() + { + return 'name'; + } + + public function getIncrementing() + { + return false; + } +} From b9e48c34ad0d1222912c92f9753173c7a8997f55 Mon Sep 17 00:00:00 2001 From: Ryan Chandler Date: Thu, 25 Mar 2021 09:37:00 +0000 Subject: [PATCH 3/4] chore: docs --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 4496f27..9d175e0 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,31 @@ Out of the box, Orbit provides the following drivers: * `md` -> `Orbit\Drivers\Markdown` * `json` => `Orbit\Drivers\Json` * `yaml` => `Orbit\Drivers\Yaml` +* `md_json` => `Orbit\Drivers\MarkdownJson` + +### `md` + +This is a Markdown that is capable of parsing Markdown files, as well as YAML front-matter. + +When Orbit loads files using this driver, it will map each front-matter key into a column in your models `schema`. + +By default, the Markdown driver will also add a `TEXT content` column to your schema. This is used to store the Markdown body from the file. + +> 💡 If you wish to customise the name of the `content` column, you can use the `Markdown::contentColumn()` method and provide a new column name. This is applied to all models that use the `Markdown` driver. + +### `json` + +This is a JSON driver that is capable of parsing `.json` files. Each key in the file is mapped to a column in your schema. + +### `yaml` + +This is a YAML driver that is capable of parsing `.yml` drivers. Each key in the file is mapped to a column in your schema. + +### `md_json` + +This driver is very similar to the `Markdown` / `md` driver, but it supports JSON-based front-matter as opposed to the default YAML format. + +> 💡 If you wish to customise the name of the `content` column, you can use the `MarkdownJson::contentColumn()` method and provide a new column name. This is applied to all models that use the `MarkdownJson` driver. ### Registering drivers From 37424dca8d15668443e954aaaeab4212b9360815 Mon Sep 17 00:00:00 2001 From: Ryan Chandler Date: Thu, 25 Mar 2021 09:40:42 +0000 Subject: [PATCH 4/4] chore: docs --- README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d175e0..a7b6d07 100644 --- a/README.md +++ b/README.md @@ -169,7 +169,7 @@ You can register custom Orbit drivers by using the `Orbit::extend` method. You s }) ``` -All drivers must implement the `Orbit\Contracts\Driver` contract. This enforces drivers to have at least 4 methods: +All drivers must implement the `Orbit\Contracts\Driver` contract, or extend the `Orbit\Drivers\FileDriver` class. This enforces drivers to have at least 4 methods: ```php interface Driver @@ -184,13 +184,21 @@ interface Driver } ``` -Here is what each of the methods are for: +Here is what each method is used for: * `shouldRestoreCache` - used to determine if the file cache should be updated. * `save` - used to persist model changes to a file on disk, or create a new file. * `delete` - used to delete an existing file on disk * `all` - used to retrieve all records from disk and cache. +### Extending `FileDriver` + +Extending the `Orbit\Drivers\FileDriver` class is useful when you want some of the heavy lifting done for you. To work with this base class, you should do the following: + +1. Implement an `extension(): string` method that returns the file extension as a string, i.e. `return 'md'` for `Markdown`. +2. Implement a `dumpContent(Model $model): string` method. This method should return the updated content for the file. +3. Implement a `parseContent(SplFileInfo $file): array` method. This method should return an array of `key => value` pairs, where each `key` is a column in the `schema`. + ### Changing drivers If you wish to use a different driver for one of your models, you can add a `public static $driver` property to your model and set the value to the name of a driver.