Skip to content

Commit 4e19a9b

Browse files
[5.x] Nocache database driver (#10671)
Co-authored-by: Duncan McClean <duncan@duncanmcclean.com>
1 parent 46894b9 commit 4e19a9b

File tree

9 files changed

+170
-7
lines changed

9 files changed

+170
-7
lines changed

config/static_caching.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,21 @@
102102

103103
'ignore_query_strings' => false,
104104

105+
/*
106+
|--------------------------------------------------------------------------
107+
| Nocache
108+
|--------------------------------------------------------------------------
109+
|
110+
| Here you may define where the nocache data is stored.
111+
|
112+
| https://statamic.dev/tags/nocache#database
113+
|
114+
| Supported drivers: "cache", "database"
115+
|
116+
*/
117+
118+
'nocache' => 'cache',
119+
105120
/*
106121
|--------------------------------------------------------------------------
107122
| Replacers
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Statamic\Console\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use Illuminate\Support\Carbon;
7+
use Illuminate\Support\Composer;
8+
use Statamic\Console\RunsInPlease;
9+
use Statamic\Facades\File;
10+
11+
class NocacheMigration extends Command
12+
{
13+
use RunsInPlease;
14+
15+
protected $composer;
16+
protected $signature = 'statamic:nocache:migration {--path=}';
17+
protected $description = 'Generate Nocache Migrations';
18+
19+
public function __construct(Composer $composer)
20+
{
21+
parent::__construct();
22+
23+
$this->composer = $composer;
24+
}
25+
26+
public function handle()
27+
{
28+
$from = __DIR__.'/stubs/statamic_nocache_tables.php.stub';
29+
$file = Carbon::now()->format('Y_m_d_His').'_statamic_nocache_tables';
30+
$to = ($path = $this->option('path')) ? $path."/{$file}.php" : database_path("migrations/{$file}.php");
31+
32+
$contents = File::get($from);
33+
34+
$contents = str_replace('NOCACHE_TABLE', 'nocache_regions', $contents);
35+
36+
File::put($to, $contents);
37+
38+
$this->components->info("Migration [$file] created successfully.");
39+
40+
$this->composer->dumpAutoloads();
41+
}
42+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
use Illuminate\Support\Facades\Schema;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Database\Migrations\Migration;
6+
7+
class StatamicNocacheTables extends Migration
8+
{
9+
public function up()
10+
{
11+
Schema::create('NOCACHE_TABLE', function (Blueprint $table) {
12+
$table->string('key')->index()->primary();
13+
$table->string('url')->index();
14+
$table->longText('region');
15+
$table->timestamps();
16+
});
17+
}
18+
19+
public function down()
20+
{
21+
Schema::dropIfExists('nocache_regions');
22+
}
23+
}

src/Providers/ConsoleServiceProvider.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class ConsoleServiceProvider extends ServiceProvider
4545
Commands\SupportZipBlueprint::class,
4646
Commands\AuthMigration::class,
4747
Commands\Multisite::class,
48+
Commands\NocacheMigration::class,
4849
Commands\SiteClear::class,
4950
Commands\UpdatesRun::class,
5051
Commands\ImportGroups::class,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Statamic\StaticCaching\NoCache;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
class DatabaseRegion extends Model
8+
{
9+
protected $table = 'nocache_regions';
10+
11+
protected $guarded = [];
12+
13+
protected $primaryKey = 'key';
14+
15+
protected $casts = [
16+
'key' => 'string',
17+
];
18+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace Statamic\StaticCaching\NoCache;
4+
5+
class DatabaseSession extends Session
6+
{
7+
public function write()
8+
{
9+
// Nothing to write. Session gets compiled by querying regions.
10+
}
11+
12+
public function restore()
13+
{
14+
$regions = DatabaseRegion::where('url', $this->url)->get(['key']);
15+
16+
$this->regions = $regions->map->key;
17+
18+
$this->cascade = $this->restoreCascade();
19+
20+
$this->resolvePageAndPathForPagination();
21+
22+
return $this;
23+
}
24+
25+
public function region(string $key): Region
26+
{
27+
$region = DatabaseRegion::where('key', $key)->first();
28+
29+
if (! $region) {
30+
throw new RegionNotFound($key);
31+
}
32+
33+
return unserialize($region->region);
34+
}
35+
36+
protected function cacheRegion(Region $region)
37+
{
38+
DatabaseRegion::updateOrCreate([
39+
'key' => $region->key(),
40+
], [
41+
'url' => $this->url,
42+
'region' => serialize($region),
43+
]);
44+
}
45+
}

src/StaticCaching/NoCache/Session.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,15 @@ public function restore()
131131
return $this;
132132
}
133133

134-
private function restoreCascade()
134+
protected function restoreCascade()
135135
{
136136
return Cascade::instance()
137137
->withContent(Data::findByRequestUrl($this->url))
138138
->hydrate()
139139
->toArray();
140140
}
141141

142-
private function resolvePageAndPathForPagination(): void
142+
protected function resolvePageAndPathForPagination(): void
143143
{
144144
AbstractPaginator::currentPathResolver(fn () => Str::before($this->url, '?'));
145145

@@ -148,7 +148,7 @@ private function resolvePageAndPathForPagination(): void
148148
});
149149
}
150150

151-
private function cacheRegion(Region $region)
151+
protected function cacheRegion(Region $region)
152152
{
153153
StaticCache::cacheStore()->forever('nocache::region.'.$region->key(), $region);
154154
}

src/StaticCaching/ServiceProvider.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Illuminate\Support\Facades\Event;
88
use Illuminate\Support\ServiceProvider as LaravelServiceProvider;
99
use Statamic\Facades\Cascade;
10+
use Statamic\StaticCaching\NoCache\DatabaseSession;
1011
use Statamic\StaticCaching\NoCache\Session;
1112

1213
class ServiceProvider extends LaravelServiceProvider
@@ -41,7 +42,11 @@ public function register()
4142
$uri = explode('?', $uri)[0];
4243
}
4344

44-
return new Session($uri);
45+
return match ($driver = config('statamic.static_caching.nocache', 'cache')) {
46+
'cache' => new Session($uri),
47+
'database' => new DatabaseSession($uri),
48+
default => throw new \Exception('Nocache driver ['.$driver.'] is not supported.'),
49+
};
4550
});
4651

4752
$this->app->bind(UrlExcluder::class, function ($app) {

src/StaticCaching/StaticCacheManager.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Statamic\StaticCaching\Cachers\FileCacher;
1111
use Statamic\StaticCaching\Cachers\NullCacher;
1212
use Statamic\StaticCaching\Cachers\Writer;
13+
use Statamic\StaticCaching\NoCache\DatabaseRegion;
1314
use Statamic\Support\Manager;
1415

1516
class StaticCacheManager extends Manager
@@ -66,11 +67,26 @@ public function flush()
6667
{
6768
$this->driver()->flush();
6869

70+
$this->flushNocache();
71+
6972
if ($this->hasCustomStore()) {
7073
$this->cacheStore()->flush();
74+
}
75+
76+
StaticCacheCleared::dispatch();
77+
}
78+
79+
private function flushNocache()
80+
{
81+
if (config('statamic.static_caching.nocache', 'cache') === 'database') {
82+
DatabaseRegion::truncate();
7183

72-
StaticCacheCleared::dispatch();
84+
return;
85+
}
7386

87+
// No need to do any looping if there's a custom
88+
// store because the entire store will be flushed.
89+
if ($this->hasCustomStore()) {
7490
return;
7591
}
7692

@@ -81,8 +97,6 @@ public function flush()
8197
});
8298

8399
$this->cacheStore()->forget('nocache::urls');
84-
85-
StaticCacheCleared::dispatch();
86100
}
87101

88102
public function nocacheJs(string $js)

0 commit comments

Comments
 (0)