Skip to content

Commit fae93da

Browse files
Merge pull request #350 from spatie/fix-caching-issues
Fix caching issues
2 parents f0fa3ae + b1a83fb commit fae93da

File tree

6 files changed

+70
-63
lines changed

6 files changed

+70
-63
lines changed

src/Events/SettingsLoaded.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66

77
class SettingsLoaded
88
{
9-
public Settings $settings;
10-
11-
public function __construct(Settings $settings)
9+
public function __construct(public Settings $settings, public bool $loadedFromCache)
1210
{
13-
$this->settings = $settings;
1411
}
1512
}

src/Settings.php

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,7 @@ public static function fake(array $values, bool $loadMissingValues = true): self
8686

8787
final public function __construct(array $values = [])
8888
{
89-
$this->ensureConfigIsLoaded();
90-
91-
foreach ($this->config->getReflectedProperties() as $name => $property) {
89+
foreach ($this->settingsConfig()->getReflectedProperties() as $name => $property) {
9290
if (method_exists($property, 'isReadOnly') && $property->isReadOnly()) {
9391
continue;
9492
}
@@ -140,25 +138,28 @@ public function __serialize(): array
140138
/** @var Collection $encrypted */
141139
/** @var Collection $nonEncrypted */
142140
[$encrypted, $nonEncrypted] = $this->toCollection()->partition(
143-
fn ($value, string $name) => $this->config->isEncrypted($name)
141+
fn ($value, string $name) => $this->settingsConfig()->isEncrypted($name)
144142
);
145143

146144
return array_merge(
147145
$encrypted->map(fn ($value) => Crypto::encrypt($value))->all(),
148-
$nonEncrypted->all()
146+
$nonEncrypted->all(),
147+
['_settingsLoadedFromCache' => $this->settingsConfig()->isLoadedFromCache()]
149148
);
150149
}
151150

152151
public function __unserialize(array $data): void
153152
{
154153
$this->loaded = false;
155154

156-
$this->ensureConfigIsLoaded();
155+
$settingsLoadedFromCache = $data['_settingsLoadedFromCache'] ?? null;
156+
unset($data['_settingsLoadedFromCache']);
157+
$this->settingsConfig()->markLoadedFromCache($settingsLoadedFromCache ?? false);
157158

158159
/** @var Collection $encrypted */
159160
/** @var Collection $nonEncrypted */
160161
[$encrypted, $nonEncrypted] = collect($data)->partition(
161-
fn ($value, string $name) => $this->config->isEncrypted($name)
162+
fn ($value, string $name) => $this->settingsConfig()->isEncrypted($name)
162163
);
163164

164165
$data = array_merge(
@@ -201,16 +202,12 @@ public function save(): self
201202

202203
public function lock(string ...$properties)
203204
{
204-
$this->ensureConfigIsLoaded();
205-
206-
$this->config->lock(...$properties);
205+
$this->settingsConfig()->lock(...$properties);
207206
}
208207

209208
public function unlock(string ...$properties)
210209
{
211-
$this->ensureConfigIsLoaded();
212-
213-
$this->config->unlock(...$properties);
210+
$this->settingsConfig()->unlock(...$properties);
214211
}
215212

216213
public function isLocked(string $property): bool
@@ -225,16 +222,12 @@ public function isUnlocked(string $property): bool
225222

226223
public function getLockedProperties(): array
227224
{
228-
$this->ensureConfigIsLoaded();
229-
230-
return $this->config->getLocked()->toArray();
225+
return $this->settingsConfig()->getLocked()->toArray();
231226
}
232227

233228
public function toCollection(): Collection
234229
{
235-
$this->ensureConfigIsLoaded();
236-
237-
return $this->config
230+
return $this->settingsConfig()
238231
->getReflectedProperties()
239232
->mapWithKeys(fn (ReflectionProperty $property) => [
240233
$property->getName() => $this->{$property->getName()},
@@ -258,21 +251,26 @@ public function toResponse($request)
258251

259252
public function getRepository(): SettingsRepository
260253
{
261-
$this->ensureConfigIsLoaded();
262-
263-
return $this->config->getRepository();
254+
return $this->settingsConfig()->getRepository();
264255
}
265256

266257
public function refresh(): self
267258
{
268-
$this->config->clearCachedLockedProperties();
259+
$this->settingsConfig()->clearCachedLockedProperties();
269260

270261
$this->loaded = false;
271262
$this->loadValues();
272263

273264
return $this;
274265
}
275266

267+
public function settingsConfig(): SettingsConfig
268+
{
269+
$this->ensureConfigIsLoaded();
270+
271+
return $this->config;
272+
}
273+
276274
private function loadValues(?array $values = null): self
277275
{
278276
if ($this->loaded) {
@@ -286,7 +284,7 @@ private function loadValues(?array $values = null): self
286284
$this->fill($values);
287285
$this->originalValues = collect($values);
288286

289-
event(new SettingsLoaded($this));
287+
event(new SettingsLoaded($this, $this->settingsConfig()->isLoadedFromCache()));
290288

291289
return $this;
292290
}

src/SettingsCache.php

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,48 @@
22

33
namespace Spatie\LaravelSettings;
44

5+
use DateInterval;
6+
use DateTimeInterface;
57
use Illuminate\Support\Collection;
68
use Illuminate\Support\Facades\Cache;
79
use Spatie\LaravelSettings\Exceptions\CouldNotUnserializeSettings;
810
use Spatie\LaravelSettings\Exceptions\SettingsCacheDisabled;
911

1012
class SettingsCache
1113
{
12-
private bool $enabled;
13-
14-
private ?string $store;
15-
16-
private ?string $prefix;
17-
18-
/** @var \DateTimeInterface|\DateInterval|int|null */
19-
private $ttl;
20-
2114
public function __construct(
22-
bool $enabled,
23-
?string $store,
24-
?string $prefix,
25-
$ttl = null
15+
private bool $enabled,
16+
private ?string $store,
17+
private ?string $prefix,
18+
private DateTimeInterface|DateInterval|int|null $ttl = null
2619
) {
27-
$this->enabled = $enabled;
28-
$this->store = $store;
29-
$this->prefix = $prefix;
30-
$this->ttl = $ttl;
3120
}
3221

3322
public function isEnabled(): bool
3423
{
3524
return $this->enabled;
3625
}
3726

38-
public function has(string $settingsClass): bool
39-
{
40-
if ($this->enabled === false) {
41-
return false;
42-
}
43-
44-
return Cache::store($this->store)->has($this->resolveCacheKey($settingsClass));
45-
}
46-
47-
public function get(string $settingsClass): Settings
27+
public function get(string $settingsClass): ?Settings
4828
{
4929
if ($this->enabled === false) {
5030
throw SettingsCacheDisabled::create();
5131
}
5232

5333
$serialized = Cache::store($this->store)->get($this->resolveCacheKey($settingsClass));
5434

35+
if ($serialized === null) {
36+
return null;
37+
}
38+
5539
$settings = unserialize($serialized);
5640

5741
if (! $settings instanceof Settings) {
5842
throw new CouldNotUnserializeSettings();
5943
}
6044

45+
$settings->settingsConfig()->markLoadedFromCache(true);
46+
6147
return $settings;
6248
}
6349

@@ -67,6 +53,8 @@ public function put(Settings $settings): void
6753
return;
6854
}
6955

56+
$settings->settingsConfig()->markLoadedFromCache(true);
57+
7058
$serialized = serialize($settings);
7159

7260
Cache::store($this->store)->put(

src/SettingsConfig.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class SettingsConfig
3333

3434
private SettingsRepository $repository;
3535

36+
private bool $loadedFromCache = false;
37+
3638
public function __construct(string $settingsClass)
3739
{
3840
if (! is_subclass_of($settingsClass, Settings::class)) {
@@ -151,4 +153,16 @@ public function clearCachedLockedProperties(): self
151153

152154
return $this;
153155
}
156+
157+
public function markLoadedFromCache(bool $loadedFromCache): self
158+
{
159+
$this->loadedFromCache = $loadedFromCache;
160+
161+
return $this;
162+
}
163+
164+
public function isLoadedFromCache(): bool
165+
{
166+
return $this->loadedFromCache;
167+
}
154168
}

src/SettingsContainer.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,18 @@ public function registerBindings(): void
2929
$this->container->scoped($settingClass, function () use ($cacheFactory, $settingClass) {
3030
$cache = $cacheFactory->build($settingClass::repository());
3131

32-
if ($cache->isEnabled() && $cache->has($settingClass)) {
33-
try {
34-
return $cache->get($settingClass);
35-
} catch (CouldNotUnserializeSettings $exception) {
36-
Log::error("Could not unserialize settings class: `{$settingClass}` from cache");
32+
if ($cache->isEnabled() === false) {
33+
return new $settingClass();
34+
}
35+
36+
try {
37+
$settings = $cache->get($settingClass);
38+
39+
if ($settings !== null) {
40+
return $settings;
3741
}
42+
} catch (CouldNotUnserializeSettings $exception) {
43+
Log::error("Could not unserialize settings class: `{$settingClass}` from cache");
3844
}
3945

4046
return new $settingClass();
@@ -48,7 +54,7 @@ public function getSettingClasses(): Collection
4854
return self::$settingsClasses;
4955
}
5056

51-
$cachedDiscoveredSettings = config('settings.discovered_settings_cache_path') . '/settings.php';
57+
$cachedDiscoveredSettings = config('settings.discovered_settings_cache_path').'/settings.php';
5258

5359
if (file_exists($cachedDiscoveredSettings)) {
5460
$classes = require $cachedDiscoveredSettings;

src/SettingsEventSubscriber.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function __construct(SettingsCacheFactory $settingsCacheFactory)
1616
$this->settingsCacheFactory = $settingsCacheFactory;
1717
}
1818

19-
public function subscribe(Dispatcher $dispatcher)
19+
public function subscribe(Dispatcher $dispatcher): void
2020
{
2121
$dispatcher->listen(
2222
SettingsSaved::class,
@@ -34,11 +34,15 @@ function (SettingsSaved $event) {
3434
$dispatcher->listen(
3535
SettingsLoaded::class,
3636
function (SettingsLoaded $event) {
37+
if ($event->loadedFromCache) {
38+
return;
39+
}
40+
3741
$cache = $this->settingsCacheFactory->build(
3842
$event->settings::repository()
3943
);
4044

41-
if ($cache->has(get_class($event->settings))) {
45+
if ($cache->isEnabled() === false) {
4246
return;
4347
}
4448

0 commit comments

Comments
 (0)