Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store sites in eloquent #322

Merged
merged 14 commits into from
Jul 18, 2024
5 changes: 5 additions & 0 deletions config/eloquent-driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,9 @@
'driver' => 'file',
'model' => \Statamic\Eloquent\Tokens\TokenModel::class,
],

'sites' => [
'driver' => 'file',
'model' => \Statamic\Eloquent\Sites\SiteModel::class,
],
];
26 changes: 26 additions & 0 deletions database/migrations/2024_07_16_100000_create_sites_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Statamic\Eloquent\Database\BaseMigration as Migration;

return new class extends Migration
{
public function up()
{
Schema::create($this->prefix('sites'), function (Blueprint $table) {
$table->id();
$table->string('handle')->unique();
$table->string('url');
$table->string('locale');
$table->string('lang');
$table->jsonb('attributes');
$table->timestamps();
});
}

public function down()
{
Schema::dropIfExists($this->prefix('sites'));
}
};
55 changes: 55 additions & 0 deletions src/Commands/ExportSites.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Statamic\Eloquent\Commands;

use Illuminate\Console\Command;
use Statamic\Console\RunsInPlease;
use Statamic\Eloquent\Sites\SiteModel;
use Statamic\Sites\Sites;

class ExportSites extends Command
{
use RunsInPlease;

/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'statamic:eloquent:export-sites';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Exports eloquent sites to flat files.';

/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$sites = SiteModel::all()
->mapWithKeys(function ($model) {
return [
$model->handle => [
'name' => $model->name,
'lang' => $model->lang,
'locale' => $model->locale,
'url' => $model->url,
'attributes' => $model->attributes ?? [],
],
];
});

(new Sites)->setSites($sites)->save();

$this->newLine();
$this->info('Sites exported');

return 0;
}
}
39 changes: 39 additions & 0 deletions src/Commands/ImportSites.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Statamic\Eloquent\Commands;

use Illuminate\Console\Command;
use Statamic\Console\RunsInPlease;
use Statamic\Eloquent\Sites\Sites as EloquentSites;
use Statamic\Sites\Sites;

class ImportSites extends Command
{
use RunsInPlease;

/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'statamic:eloquent:import-sites';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Imports file-based sites into the database.';

/**
* Execute the console command.
*/
public function handle(): int
{
$sites = (new Sites)->getConfig();

(new EloquentSites)->setSites($sites)->save();

$this->components->info('Sites imported successfully.');
}
}
24 changes: 23 additions & 1 deletion src/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ private function publishMigrations(): void
__DIR__.'/../database/migrations/2024_03_07_100000_create_tokens_table.php' => database_path('migrations/2024_03_07_100000_create_tokens_table.php'),
], 'statamic-eloquent-token-migrations');

$this->publishes($siteMigrations = [
__DIR__.'/../database/migrations/2024_07_16_100000_create_sites_table.php' => database_path('migrations/2024_07_16_100000_create_sites_table.php'),
], 'statamic-eloquent-site-migrations');

$this->publishes(
array_merge(
$taxonomyMigrations,
Expand All @@ -177,7 +181,8 @@ private function publishMigrations(): void
$assetContainerMigrations,
$assetMigrations,
$revisionMigrations,
$tokenMigrations
$tokenMigrations,
$siteMigrations,
),
'migrations'
);
Expand Down Expand Up @@ -210,6 +215,7 @@ public function register()
$this->registerTaxonomies();
$this->registerTerms();
$this->registerTokens();
$this->registerSites();
}

private function registerAssetContainers()
Expand Down Expand Up @@ -517,6 +523,21 @@ public function registerTokens()
Statamic::repository(TokenRepositoryContract::class, TokenRepository::class);
}

public function registerSites()
{
if (config('statamic.eloquent-driver.sites.driver', 'file') != 'eloquent') {
return;
}

$this->app->bind('statamic.eloquent.sites.model', function () {
return config('statamic.eloquent-driver.sites.model');
});

$this->app->singleton(\Statamic\Sites\Sites::class, \Statamic\Eloquent\Sites\Sites::class);

Statamic::repository(TokenRepositoryContract::class, TokenRepository::class);
ryanmitchell marked this conversation as resolved.
Show resolved Hide resolved
}

protected function addAboutCommandInfo()
{
if (! class_exists(AboutCommand::class)) {
Expand All @@ -539,6 +560,7 @@ protected function addAboutCommandInfo()
'Taxonomies' => config('statamic.eloquent-driver.taxonomies.driver', 'file'),
'Terms' => config('statamic.eloquent-driver.terms.driver', 'file'),
'Tokens' => config('statamic.eloquent-driver.tokens.driver', 'file'),
'Sites' => config('statamic.eloquent-driver.sites.driver', 'file'),
])->map(fn ($value) => $this->applyAboutCommandFormatting($value))->all());
}

Expand Down
22 changes: 22 additions & 0 deletions src/Sites/SiteModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Statamic\Eloquent\Sites;

use Illuminate\Support\Arr;
use Statamic\Eloquent\Database\BaseModel;

class SiteModel extends BaseModel
{
protected $guarded = [];

protected $table = 'sites';

protected $casts = [
'attributes' => 'json',
];

public function getAttribute($key)
{
return Arr::get($this->getAttributeValue('attributes'), $key, parent::getAttribute($key));
}
}
40 changes: 40 additions & 0 deletions src/Sites/Sites.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Statamic\Eloquent\Sites;

class Sites extends \Statamic\Sites\Sites
{
protected function getSavedSites()
{
$sites = app('statamic.eloquent.sites.model')::all();

return $sites->isEmpty() ? $this->getDefaultSite() : $sites->mapWithKeys(function ($model) {
return [
$model->handle => [
'name' => $model->name,
'lang' => $model->lang,
'locale' => $model->locale,
'url' => $model->url,
'attributes' => $model->attributes ?? [],
],
];
});
}

protected function saveToStore()
{
foreach ($this->config() as $handle => $config) {
app('statamic.eloquent.sites.model')::firstOrNew(['handle' => $handle])
->fill([
'name' => $config['name'] ?? '',
'lang' => $config['lang'] ?? '',
'locale' => $config['locale'] ?? '',
'url' => $config['url'] ?? '',
'attributes' => $config['attributes'] ?? [],
])
->save();
}

app('statamic.eloquent.sites.model')::whereNotIn('handle', array_keys($this->config()))->get()->each->delete();
}
}
29 changes: 29 additions & 0 deletions tests/Commands/ImportSitesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Commands;

use PHPUnit\Framework\Attributes\Test;
use Statamic\Testing\Concerns\PreventsSavingStacheItemsToDisk;
use Tests\TestCase;

class ImportSitesTest extends TestCase
{
use PreventsSavingStacheItemsToDisk;

#[Test]
public function it_imports_sites()
{
$this->assertCount(0, SiteModel::all());

$this->artisan('statamic:eloquent:import-sites')
->expectsOutputToContain('Sites imported successfully.')
->assertExitCode(0);

$this->assertCount(1, SiteModel::all());

$this->assertDatabaseHas('sites', [
'handle' => 'en',
'name' => 'English',
]);
}
}
71 changes: 71 additions & 0 deletions tests/Sites/SitesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace Tests\Sites;

use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Statamic\Eloquent\Sites\SiteModel;
use Statamic\Facades\Sites;
use Tests\TestCase;

class SitesTest extends TestCase
{
use RefreshDatabase;

public function setUp(): void
{
parent::setUp();

$this->app->bind('statamic.eloquent.sites.model', function () {
return SiteModel::class;
});

$this->app->singleton(
'Statamic\Sites\Sites',
'Statamic\Eloquent\Sites\Sites'
);
}

#[Test]
public function it_saves_sites()
{
$this->assertCount(0, Sites: all());

$this->setSites([
'en' => ['name' => 'English', 'locale' => 'en_US', 'url' => 'http://test.com/'],
'fr' => ['name' => 'French', 'locale' => 'fr_FR', 'url' => 'http://fr.test.com/'],
'es' => ['name' => 'Spanish', 'locale' => 'es_ES', 'url' => 'http://test.com/es/'],
'de' => ['name' => 'German', 'locale' => 'de_DE', 'url' => 'http://test.com/de/'],
]);

Sites::save();

$this->assertCount(4, Sites: all());
$this->assertCount(4, SiteModel::all());
}

#[Test]
public function it_deletes_sites()
{
$this->assertCount(0, Sites: all());

$this->setSites([
'en' => ['name' => 'English', 'locale' => 'en_US', 'url' => 'http://test.com/'],
'fr' => ['name' => 'French', 'locale' => 'fr_FR', 'url' => 'http://fr.test.com/'],
'es' => ['name' => 'Spanish', 'locale' => 'es_ES', 'url' => 'http://test.com/es/'],
'de' => ['name' => 'German', 'locale' => 'de_DE', 'url' => 'http://test.com/de/'],
]);

Sites::save();

$this->setSites([
'en' => ['name' => 'English', 'locale' => 'en_US', 'url' => 'http://test.com/'],
'fr' => ['name' => 'French', 'locale' => 'fr_FR', 'url' => 'http://fr.test.com/'],
'es' => ['name' => 'Spanish', 'locale' => 'es_ES', 'url' => 'http://test.com/es/'],
]);

$this->assertCount(3, Sites: all());
$this->assertCount(3, SiteModel::all());
$this->assertSame(['en', 'fr', 'es'], SiteModel::all()->pluck('handle')->all());
}
}
1 change: 1 addition & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ protected function resolveApplicationConfiguration($app)

collect(config('statamic.eloquent-driver'))
->filter(fn ($config) => isset($config['driver']))
->reject(fn ($config, $key) => $key === 'sites')
->each(fn ($config, $key) => $app['config']->set("statamic.eloquent-driver.{$key}.driver", 'eloquent'));
}

Expand Down
Loading