Skip to content

Commit

Permalink
Merge pull request #10 from plank/source-layouts-from-filesystem
Browse files Browse the repository at this point in the history
Source Layouts from Filesystem
  • Loading branch information
kfriars authored Nov 22, 2023
2 parents acc4c64 + fef0f91 commit c973f8e
Show file tree
Hide file tree
Showing 52 changed files with 1,008 additions and 124 deletions.
5 changes: 1 addition & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,7 @@
"laravel": {
"providers": [
"Plank\\Contentable\\ContentableServiceProvider"
],
"aliases": {
"Contentable": "Plank\\Contentable\\Facades\\Contentable"
}
]
}
},
"minimum-stability": "dev",
Expand Down
11 changes: 7 additions & 4 deletions config/contentable.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
<?php

return [

'model' => \Plank\Contentable\Models\Content::class,
'cache' => [
'ttl' => 10800,
'content' => [
'model' => \Plank\Contentable\Models\Content::class,
],
'layouts' => [
'folder' => 'layouts',
'mode' => \Plank\Contentable\Enums\LayoutMode::Blade,
'model' => \Plank\Contentable\Models\Layout::class,
],
'cache' => [
'ttl' => 10800,
],
];
7 changes: 5 additions & 2 deletions database/migrations/create_layouts_table.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
public function up()
{
Schema::create('layouts', function (Blueprint $table) {
$table->id();
$table->string('identifier')->unique()->nullable();
$table->id()->primary();
$table->string('key')->unique();
$table->string('name')->unique()->nullable();
$table->string('layoutable')->nullable();
$table->string('type');
$table->timestamps();
});
}
Expand Down
167 changes: 167 additions & 0 deletions src/Commands/SyncLayouts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<?php

namespace Plank\Contentable\Commands;

use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\File;
use Plank\Contentable\Contracts\Layout;
use Plank\Contentable\Contracts\Layoutable;
use Plank\Contentable\Enums\LayoutType;
use SplFileInfo;

class SyncLayouts extends Command
{
protected $signature = 'contentable:sync';

protected $description = 'Ensure defined layout files exist as Layout Models.';

public function handle(): void
{
foreach ($this->globalKeys() as $key) {
$this->ensureGlobalLayoutExists($key);
}

foreach ($this->layoutableKeys() as $key) {
$this->ensureModelLayoutExists($key);
}
}

/**
* Get the Layout keys available to all Layoutables
*/
protected function globalKeys(): array
{
$layoutModel = static::layoutModel();

return array_map(function (SplFileInfo $layout) use ($layoutModel): string {
return $layout->getBasename($layoutModel::extension());
}, File::files($layoutModel::folder()));
}

/**
* Get the class specific Layout keys
*/
protected function layoutableKeys(): array
{
$layoutModel = static::layoutModel();

$keys = [];

foreach (File::directories($layoutModel::folder()) as $path) {
$keys = array_merge($keys, $this->keysForPath($path));
}

return $keys;
}

protected function keysForPath(string $path): array
{
$layoutModel = static::layoutModel();

$key = (string) str($path)->afterLast(DIRECTORY_SEPARATOR);

return array_map(function (SplFileInfo $layout) use ($layoutModel, $key): string {
return str($key)
->append($layoutModel::separator())
->append($layout->getBasename($layoutModel::extension()));
}, File::files($path));
}

protected function ensureGlobalLayoutExists(string $key): void
{
$layoutModel = static::layoutModel();

$layout = $layoutModel::query()
->where($layoutModel::getLayoutKeyColumn(), $key)
->first();

if ($layout !== null) {
return;
}

$layoutModel::query()->create([
$layoutModel::getLayoutKeyColumn() => $key,
$layoutModel::getNameColumn() => $this->globalKeyToName($key),
$layoutModel::getTypeColumn() => LayoutType::Global,
]);
}

protected function ensureModelLayoutExists(string $key): void
{
$layoutModel = static::layoutModel();

$layout = $layoutModel::query()
->where($layoutModel::getLayoutKeyColumn(), $key)
->first();

if ($layout !== null) {
return;
}

[$layoutableKey, $layoutKey] = explode($layoutModel::separator(), $key);

$type = match (strtolower($layoutKey)) {
'index' => LayoutType::Index,
'show' => LayoutType::Show,
default => LayoutType::Custom,
};

$layoutModel::query()->create([
$layoutModel::getLayoutKeyColumn() => $key,
$layoutModel::getNameColumn() => $this->layoutableKeyToName($layoutableKey, $layoutKey, $type),
$layoutModel::getTypeColumn() => $type,
$layoutModel::getLayoutableColumn() => $layoutableKey,
]);
}

/**
* Create a layout name for the given key
*/
protected function globalKeyToName(string $key): string
{
$layoutModel = static::layoutModel();

return str($key)
->replace($layoutModel::separator(), '_')
->snake()
->replace('_', ' ')
->title();
}

/**
* Create a layout name for the given key
*
* @param class-string<Layoutable> $layoutable
*/
protected function layoutableKeyToName(string $layoutableKey, string $layoutKey, LayoutType $type): string
{
$layoutModel = static::layoutModel();

$modelName = str($layoutableKey)
->singular()
->snake()
->replace('_', ' ')
->title();

$name = str($layoutKey)
->replace($layoutModel::separator(), '_')
->snake()
->replace('_', ' ')
->title();

return match ($type) {
LayoutType::Index => "$modelName Index",
LayoutType::Show => "$modelName Details",
default => "$name $modelName",
};
}

/**
* @return class-string<Layout&Model>
*/
protected static function layoutModel(): string
{
return config()->get('contentable.layouts.model');
}
}
2 changes: 1 addition & 1 deletion src/Concerns/CanRender.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public static function bootCanRender()

public function content(): MorphOne
{
$contentModel = config('contentable.model');
$contentModel = config('contentable.content.model');

return $this->morphOne($contentModel, 'renderable');
}
Expand Down
2 changes: 1 addition & 1 deletion src/Concerns/HasContent.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ trait HasContent
{
public function contents(): MorphMany
{
$contentModel = config('contentable.model');
$contentModel = config('contentable.content.model');

return $this->morphMany($contentModel, 'contentable');
}
Expand Down
Loading

0 comments on commit c973f8e

Please sign in to comment.