Skip to content

Commit 775e7de

Browse files
Store sites in eloquent (#322)
* wip * Use bound model * Add some tests * Import / exports * 🍺 * Missing import * Remove token repository mistake (thanks @edalzell) * Fix tests (against dev-main) * We renamed this to `getFallbackConfig()`. Sorry! 🇨🇦 * Bump core requirement * Update import test * 🍺 * Hmm? * Hmm again --------- Co-authored-by: Jesse Leite <[email protected]>
1 parent 3dc1223 commit 775e7de

File tree

11 files changed

+354
-2
lines changed

11 files changed

+354
-2
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
},
2626
"require": {
2727
"php": "^8.1",
28-
"statamic/cms": "^5.14"
28+
"statamic/cms": "^5.16"
2929
},
3030
"require-dev": {
3131
"doctrine/dbal": "^3.8",

config/eloquent-driver.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,9 @@
9797
'driver' => 'file',
9898
'model' => \Statamic\Eloquent\Tokens\TokenModel::class,
9999
],
100+
101+
'sites' => [
102+
'driver' => 'file',
103+
'model' => \Statamic\Eloquent\Sites\SiteModel::class,
104+
],
100105
];
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
use Illuminate\Database\Schema\Blueprint;
4+
use Illuminate\Support\Facades\Schema;
5+
use Statamic\Eloquent\Database\BaseMigration as Migration;
6+
7+
return new class extends Migration
8+
{
9+
public function up()
10+
{
11+
Schema::create($this->prefix('sites'), function (Blueprint $table) {
12+
$table->id();
13+
$table->string('handle')->unique();
14+
$table->string('name');
15+
$table->string('url');
16+
$table->string('locale');
17+
$table->string('lang');
18+
$table->jsonb('attributes');
19+
$table->timestamps();
20+
});
21+
}
22+
23+
public function down()
24+
{
25+
Schema::dropIfExists($this->prefix('sites'));
26+
}
27+
};

src/Commands/ExportSites.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
namespace Statamic\Eloquent\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use Statamic\Console\RunsInPlease;
7+
use Statamic\Eloquent\Sites\SiteModel;
8+
use Statamic\Sites\Sites;
9+
10+
class ExportSites extends Command
11+
{
12+
use RunsInPlease;
13+
14+
/**
15+
* The name and signature of the console command.
16+
*
17+
* @var string
18+
*/
19+
protected $signature = 'statamic:eloquent:export-sites';
20+
21+
/**
22+
* The console command description.
23+
*
24+
* @var string
25+
*/
26+
protected $description = 'Exports eloquent sites to flat files.';
27+
28+
/**
29+
* Execute the console command.
30+
*
31+
* @return int
32+
*/
33+
public function handle()
34+
{
35+
$sites = SiteModel::all()
36+
->mapWithKeys(function ($model) {
37+
return [
38+
$model->handle => [
39+
'name' => $model->name,
40+
'lang' => $model->lang,
41+
'locale' => $model->locale,
42+
'url' => $model->url,
43+
'attributes' => $model->attributes ?? [],
44+
],
45+
];
46+
});
47+
48+
(new Sites)->setSites($sites)->save();
49+
50+
$this->newLine();
51+
$this->info('Sites exported');
52+
53+
return 0;
54+
}
55+
}

src/Commands/ImportSites.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace Statamic\Eloquent\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use Statamic\Console\RunsInPlease;
7+
use Statamic\Eloquent\Sites\Sites as EloquentSites;
8+
use Statamic\Sites\Sites;
9+
10+
class ImportSites extends Command
11+
{
12+
use RunsInPlease;
13+
14+
/**
15+
* The name and signature of the console command.
16+
*
17+
* @var string
18+
*/
19+
protected $signature = 'statamic:eloquent:import-sites';
20+
21+
/**
22+
* The console command description.
23+
*
24+
* @var string
25+
*/
26+
protected $description = 'Imports file-based sites into the database.';
27+
28+
/**
29+
* Execute the console command.
30+
*/
31+
public function handle(): int
32+
{
33+
$sites = (new Sites)->config();
34+
35+
(new EloquentSites)->setSites($sites)->save();
36+
37+
$this->components->info('Sites imported successfully.');
38+
39+
return 0;
40+
}
41+
}

src/ServiceProvider.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public function boot()
8383
Commands\ExportNavs::class,
8484
Commands\ExportRevisions::class,
8585
Commands\ExportTaxonomies::class,
86+
Commands\ExportSites::class,
8687
Commands\ImportAssets::class,
8788
Commands\ImportBlueprints::class,
8889
Commands\ImportCollections::class,
@@ -92,6 +93,7 @@ public function boot()
9293
Commands\ImportNavs::class,
9394
Commands\ImportRevisions::class,
9495
Commands\ImportTaxonomies::class,
96+
Commands\ImportSites::class,
9597
Commands\SyncAssets::class,
9698
]);
9799

@@ -161,6 +163,10 @@ private function publishMigrations(): void
161163
__DIR__.'/../database/migrations/2024_03_07_100000_create_tokens_table.php' => database_path('migrations/2024_03_07_100000_create_tokens_table.php'),
162164
], 'statamic-eloquent-token-migrations');
163165

166+
$this->publishes($siteMigrations = [
167+
__DIR__.'/../database/migrations/2024_07_16_100000_create_sites_table.php' => database_path('migrations/2024_07_16_100000_create_sites_table.php'),
168+
], 'statamic-eloquent-site-migrations');
169+
164170
$this->publishes(
165171
array_merge(
166172
$taxonomyMigrations,
@@ -177,7 +183,8 @@ private function publishMigrations(): void
177183
$assetContainerMigrations,
178184
$assetMigrations,
179185
$revisionMigrations,
180-
$tokenMigrations
186+
$tokenMigrations,
187+
$siteMigrations,
181188
),
182189
'migrations'
183190
);
@@ -210,6 +217,7 @@ public function register()
210217
$this->registerTaxonomies();
211218
$this->registerTerms();
212219
$this->registerTokens();
220+
$this->registerSites();
213221
}
214222

215223
private function registerAssetContainers()
@@ -517,6 +525,19 @@ public function registerTokens()
517525
Statamic::repository(TokenRepositoryContract::class, TokenRepository::class);
518526
}
519527

528+
public function registerSites()
529+
{
530+
if (config('statamic.eloquent-driver.sites.driver', 'file') != 'eloquent') {
531+
return;
532+
}
533+
534+
$this->app->bind('statamic.eloquent.sites.model', function () {
535+
return config('statamic.eloquent-driver.sites.model');
536+
});
537+
538+
$this->app->singleton(\Statamic\Sites\Sites::class, \Statamic\Eloquent\Sites\Sites::class);
539+
}
540+
520541
protected function addAboutCommandInfo()
521542
{
522543
if (! class_exists(AboutCommand::class)) {
@@ -539,6 +560,7 @@ protected function addAboutCommandInfo()
539560
'Taxonomies' => config('statamic.eloquent-driver.taxonomies.driver', 'file'),
540561
'Terms' => config('statamic.eloquent-driver.terms.driver', 'file'),
541562
'Tokens' => config('statamic.eloquent-driver.tokens.driver', 'file'),
563+
'Sites' => config('statamic.eloquent-driver.sites.driver', 'file'),
542564
])->map(fn ($value) => $this->applyAboutCommandFormatting($value))->all());
543565
}
544566

src/Sites/SiteModel.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Statamic\Eloquent\Sites;
4+
5+
use Illuminate\Support\Arr;
6+
use Statamic\Eloquent\Database\BaseModel;
7+
8+
class SiteModel extends BaseModel
9+
{
10+
protected $guarded = [];
11+
12+
protected $table = 'sites';
13+
14+
protected $casts = [
15+
'attributes' => 'json',
16+
];
17+
18+
public function getAttribute($key)
19+
{
20+
return Arr::get($this->getAttributeValue('attributes'), $key, parent::getAttribute($key));
21+
}
22+
}

src/Sites/Sites.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Statamic\Eloquent\Sites;
4+
5+
class Sites extends \Statamic\Sites\Sites
6+
{
7+
protected function getSavedSites()
8+
{
9+
$sites = app('statamic.eloquent.sites.model')::all();
10+
11+
return $sites->isEmpty() ? $this->getFallbackConfig() : $sites->mapWithKeys(function ($model) {
12+
return [
13+
$model->handle => [
14+
'name' => $model->name,
15+
'lang' => $model->lang,
16+
'locale' => $model->locale,
17+
'url' => $model->url,
18+
'attributes' => $model->attributes ?? [],
19+
],
20+
];
21+
});
22+
}
23+
24+
protected function saveToStore()
25+
{
26+
foreach ($this->config() as $handle => $config) {
27+
app('statamic.eloquent.sites.model')::firstOrNew(['handle' => $handle])
28+
->fill([
29+
'name' => $config['name'] ?? '',
30+
'lang' => $config['lang'] ?? '',
31+
'locale' => $config['locale'] ?? '',
32+
'url' => $config['url'] ?? '',
33+
'attributes' => $config['attributes'] ?? [],
34+
])
35+
->save();
36+
}
37+
38+
app('statamic.eloquent.sites.model')::whereNotIn('handle', array_keys($this->config()))->get()->each->delete();
39+
}
40+
}

tests/Commands/ImportSitesTest.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace Commands;
4+
5+
use PHPUnit\Framework\Attributes\Test;
6+
use Statamic\Eloquent\Sites\SiteModel;
7+
use Statamic\Testing\Concerns\PreventsSavingStacheItemsToDisk;
8+
use Tests\TestCase;
9+
10+
class ImportSitesTest extends TestCase
11+
{
12+
use PreventsSavingStacheItemsToDisk;
13+
14+
public function setUp(): void
15+
{
16+
parent::setUp();
17+
18+
$this->app->bind('statamic.eloquent.sites.model', function () {
19+
return SiteModel::class;
20+
});
21+
}
22+
23+
#[Test]
24+
public function it_imports_sites()
25+
{
26+
$this->assertCount(0, SiteModel::all());
27+
28+
$this->setSites([
29+
'en' => ['name' => 'English', 'locale' => 'en_US', 'url' => 'http://test.com/'],
30+
'fr' => ['name' => 'French', 'locale' => 'fr_FR', 'url' => 'http://fr.test.com/'],
31+
'es' => ['name' => 'Spanish', 'locale' => 'es_ES', 'url' => 'http://test.com/es/'],
32+
'de' => ['name' => 'German', 'locale' => 'de_DE', 'url' => 'http://test.com/de/'],
33+
]);
34+
35+
\Statamic\Facades\Site::save();
36+
37+
$this->artisan('statamic:eloquent:import-sites')
38+
->expectsOutputToContain('Sites imported successfully.')
39+
->assertExitCode(0);
40+
41+
$this->assertCount(4, SiteModel::all());
42+
43+
$this->assertDatabaseHas('sites', [
44+
'handle' => 'en',
45+
'name' => 'English',
46+
]);
47+
48+
$this->assertDatabaseHas('sites', [
49+
'handle' => 'fr',
50+
'name' => 'French',
51+
]);
52+
53+
$this->assertDatabaseHas('sites', [
54+
'handle' => 'de',
55+
'name' => 'German',
56+
]);
57+
58+
$this->assertDatabaseHas('sites', [
59+
'handle' => 'es',
60+
'name' => 'Spanish',
61+
]);
62+
}
63+
}

0 commit comments

Comments
 (0)