mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-24 15:42:09 +08:00
fix: Cached configurable resources/pages (#19449)
This commit is contained in:
@@ -122,9 +122,7 @@ trait HasComponents
|
||||
*/
|
||||
public function pages(array $pages): static
|
||||
{
|
||||
if ($this->hasCachedComponents()) {
|
||||
return $this;
|
||||
}
|
||||
$hasCachedComponents = $this->hasCachedComponents();
|
||||
|
||||
foreach ($pages as $page) {
|
||||
if ($page instanceof PageConfiguration) {
|
||||
@@ -142,15 +140,16 @@ trait HasComponents
|
||||
|
||||
$this->pageConfigurations[$page->page][$page->getKey()] = $page;
|
||||
|
||||
$pageClass = $page->page;
|
||||
} else {
|
||||
if (! $hasCachedComponents) {
|
||||
$this->queueLivewireComponentForRegistration($page->page);
|
||||
$this->registerToCluster($page->page);
|
||||
}
|
||||
} elseif (! $hasCachedComponents) {
|
||||
$this->pages[] = $page;
|
||||
|
||||
$pageClass = $page;
|
||||
$this->queueLivewireComponentForRegistration($page);
|
||||
$this->registerToCluster($page);
|
||||
}
|
||||
|
||||
$this->queueLivewireComponentForRegistration($pageClass);
|
||||
$this->registerToCluster($pageClass);
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -161,9 +160,7 @@ trait HasComponents
|
||||
*/
|
||||
public function resources(array $resources): static
|
||||
{
|
||||
if ($this->hasCachedComponents()) {
|
||||
return $this;
|
||||
}
|
||||
$hasCachedComponents = $this->hasCachedComponents();
|
||||
|
||||
foreach ($resources as $resource) {
|
||||
if ($resource instanceof ResourceConfiguration) {
|
||||
@@ -181,14 +178,14 @@ trait HasComponents
|
||||
|
||||
$this->resourceConfigurations[$resource->resource][$resource->getKey()] = $resource;
|
||||
|
||||
$resourceClass = $resource->resource;
|
||||
} else {
|
||||
if (! $hasCachedComponents) {
|
||||
$this->registerToCluster($resource->resource);
|
||||
}
|
||||
} elseif (! $hasCachedComponents) {
|
||||
$this->resources[] = $resource;
|
||||
|
||||
$resourceClass = $resource;
|
||||
$this->registerToCluster($resource);
|
||||
}
|
||||
|
||||
$this->registerToCluster($resourceClass);
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -731,29 +728,11 @@ trait HasComponents
|
||||
'clusterDirectories' => $this->clusterDirectories,
|
||||
'clusterNamespaces' => $this->clusterNamespaces,
|
||||
'pages' => $this->pages,
|
||||
'pageConfigurations' => array_map(
|
||||
static fn (array $configurations): array => array_map(
|
||||
static fn (PageConfiguration $configuration): array => [
|
||||
'page' => $configuration->page,
|
||||
'key' => $configuration->getKey(),
|
||||
],
|
||||
$configurations,
|
||||
),
|
||||
$this->pageConfigurations,
|
||||
),
|
||||
'pageConfigurations' => [],
|
||||
'pageDirectories' => $this->pageDirectories,
|
||||
'pageNamespaces' => $this->pageNamespaces,
|
||||
'resources' => $this->resources,
|
||||
'resourceConfigurations' => array_map(
|
||||
static fn (array $configurations): array => array_map(
|
||||
static fn (ResourceConfiguration $configuration): array => [
|
||||
'resource' => $configuration->resource,
|
||||
'key' => $configuration->getKey(),
|
||||
],
|
||||
$configurations,
|
||||
),
|
||||
$this->resourceConfigurations,
|
||||
),
|
||||
'resourceConfigurations' => [],
|
||||
'resourceDirectories' => $this->resourceDirectories,
|
||||
'resourceNamespaces' => $this->resourceNamespaces,
|
||||
'widgets' => $this->widgets,
|
||||
@@ -779,24 +758,9 @@ trait HasComponents
|
||||
$this->clusterDirectories = $cache['clusterDirectories'] ?? [];
|
||||
$this->clusterNamespaces = $cache['clusterNamespaces'] ?? [];
|
||||
$this->pages = $cache['pages'] ?? [];
|
||||
$this->pageConfigurations = [];
|
||||
|
||||
foreach ($cache['pageConfigurations'] ?? [] as $pageClass => $configurations) {
|
||||
foreach ($configurations as $configuration) {
|
||||
$this->pageConfigurations[$pageClass][$configuration['key']] = $configuration['page']::make($configuration['key']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->pageDirectories = $cache['pageDirectories'] ?? [];
|
||||
$this->pageNamespaces = $cache['pageNamespaces'] ?? [];
|
||||
$this->resources = $cache['resources'] ?? [];
|
||||
$this->resourceConfigurations = [];
|
||||
|
||||
foreach ($cache['resourceConfigurations'] ?? [] as $resourceClass => $configurations) {
|
||||
foreach ($configurations as $configuration) {
|
||||
$this->resourceConfigurations[$resourceClass][$configuration['key']] = $configuration['resource']::make($configuration['key']);
|
||||
}
|
||||
}
|
||||
$this->resourceDirectories = $cache['resourceDirectories'] ?? [];
|
||||
$this->resourceNamespaces = $cache['resourceNamespaces'] ?? [];
|
||||
$this->widgets = $cache['widgets'] ?? [];
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
use Filament\Facades\Filament;
|
||||
use Filament\Tests\Fixtures\Models\User;
|
||||
use Filament\Tests\Fixtures\Pages\ConfigurableSettings;
|
||||
use Filament\Tests\Fixtures\Pages\Settings;
|
||||
use Filament\Tests\Fixtures\Resources\Posts\ConfigurablePostResource;
|
||||
use Filament\Tests\Fixtures\Resources\Posts\PostResource;
|
||||
use Filament\Tests\Fixtures\Resources\Users\UserResource;
|
||||
use Filament\Tests\TestCase;
|
||||
|
||||
uses(TestCase::class);
|
||||
|
||||
beforeEach(function (): void {
|
||||
$this->actingAs(User::factory()->create());
|
||||
});
|
||||
|
||||
afterEach(function (): void {
|
||||
Filament::getPanel('admin')->clearCachedComponents();
|
||||
Filament::getPanel('configuration')->clearCachedComponents();
|
||||
});
|
||||
|
||||
it('can cache and restore resources', function (): void {
|
||||
$panel = Filament::getPanel('admin');
|
||||
|
||||
$resourcesBefore = $panel->getResources();
|
||||
|
||||
$panel->cacheComponents();
|
||||
$panel->restoreCachedComponents();
|
||||
|
||||
$resourcesAfter = $panel->getResources();
|
||||
|
||||
expect($resourcesAfter)->toEqual($resourcesBefore);
|
||||
expect($resourcesAfter)->toContain(PostResource::class);
|
||||
expect($resourcesAfter)->toContain(UserResource::class);
|
||||
});
|
||||
|
||||
it('can cache and restore pages', function (): void {
|
||||
$panel = Filament::getPanel('admin');
|
||||
|
||||
$pagesBefore = $panel->getPages();
|
||||
|
||||
$panel->cacheComponents();
|
||||
$panel->restoreCachedComponents();
|
||||
|
||||
$pagesAfter = $panel->getPages();
|
||||
|
||||
expect($pagesAfter)->toEqual($pagesBefore);
|
||||
expect($pagesAfter)->toContain(Settings::class);
|
||||
});
|
||||
|
||||
it('can cache and restore widgets', function (): void {
|
||||
$panel = Filament::getPanel('admin');
|
||||
|
||||
$widgetsBefore = $panel->getWidgets();
|
||||
|
||||
$panel->cacheComponents();
|
||||
$panel->restoreCachedComponents();
|
||||
|
||||
$widgetsAfter = $panel->getWidgets();
|
||||
|
||||
expect($widgetsAfter)->toEqual($widgetsBefore);
|
||||
});
|
||||
|
||||
it('skips duplicate resource class strings when cached', function (): void {
|
||||
$panel = Filament::getPanel('admin');
|
||||
|
||||
$panel->cacheComponents();
|
||||
$panel->restoreCachedComponents();
|
||||
|
||||
// Calling `resources()` again with cached components should not add duplicates
|
||||
$countBefore = count($panel->getResources());
|
||||
$panel->resources([PostResource::class]);
|
||||
$countAfter = count($panel->getResources());
|
||||
|
||||
expect($countAfter)->toBe($countBefore);
|
||||
});
|
||||
|
||||
it('skips duplicate page class strings when cached', function (): void {
|
||||
$panel = Filament::getPanel('admin');
|
||||
|
||||
$panel->cacheComponents();
|
||||
$panel->restoreCachedComponents();
|
||||
|
||||
// Calling `pages()` again with cached components should not add duplicates
|
||||
$countBefore = count($panel->getPages());
|
||||
$panel->pages([Settings::class]);
|
||||
$countAfter = count($panel->getPages());
|
||||
|
||||
expect($countAfter)->toBe($countBefore);
|
||||
});
|
||||
|
||||
it('can clear cached components', function (): void {
|
||||
$panel = Filament::getPanel('admin');
|
||||
|
||||
$panel->cacheComponents();
|
||||
|
||||
expect(file_exists($panel->getComponentCachePath()))->toBeTrue();
|
||||
|
||||
$panel->clearCachedComponents();
|
||||
|
||||
expect(file_exists($panel->getComponentCachePath()))->toBeFalse();
|
||||
});
|
||||
|
||||
it('preserves resource configurations after caching and restoring components', function (): void {
|
||||
$panel = Filament::getPanel('configuration');
|
||||
|
||||
$panel->cacheComponents();
|
||||
$panel->restoreCachedComponents();
|
||||
|
||||
// Verify configurations still exist
|
||||
$configurations = $panel->getResourceConfigurations();
|
||||
expect($configurations)->toHaveCount(2);
|
||||
|
||||
// Verify configuration properties are preserved (not just class and key)
|
||||
$featuredConfig = $panel->getResourceConfiguration(ConfigurablePostResource::class, 'featured');
|
||||
expect($featuredConfig)->not->toBeNull();
|
||||
expect($featuredConfig->getSlug())->toBe('featured-posts');
|
||||
expect($featuredConfig->getNavigationLabel())->toBe('Featured Posts');
|
||||
expect($featuredConfig->getNavigationGroup())->toBe('Featured Content');
|
||||
expect($featuredConfig->getNavigationSort())->toBe(1);
|
||||
expect($featuredConfig->isFeatured())->toBeTrue();
|
||||
expect($featuredConfig->isArchived())->toBeFalse();
|
||||
|
||||
$archivedConfig = $panel->getResourceConfiguration(ConfigurablePostResource::class, 'archived');
|
||||
expect($archivedConfig)->not->toBeNull();
|
||||
expect($archivedConfig->getSlug())->toBe('archived-posts');
|
||||
expect($archivedConfig->getNavigationLabel())->toBe('Archived Posts');
|
||||
expect($archivedConfig->getNavigationGroup())->toBe('Archive');
|
||||
expect($archivedConfig->getNavigationSort())->toBe(100);
|
||||
expect($archivedConfig->isFeatured())->toBeFalse();
|
||||
expect($archivedConfig->isArchived())->toBeTrue();
|
||||
});
|
||||
|
||||
it('preserves page configurations after caching and restoring components', function (): void {
|
||||
$panel = Filament::getPanel('configuration');
|
||||
|
||||
$panel->cacheComponents();
|
||||
$panel->restoreCachedComponents();
|
||||
|
||||
// Verify configurations still exist
|
||||
$configurations = $panel->getPageConfigurations();
|
||||
expect($configurations)->toHaveCount(2);
|
||||
|
||||
// Verify configuration properties are preserved (not just class and key)
|
||||
$generalConfig = $panel->getPageConfiguration(ConfigurableSettings::class, 'general');
|
||||
expect($generalConfig)->not->toBeNull();
|
||||
expect($generalConfig->getSlug())->toBe('general-settings');
|
||||
expect($generalConfig->getNavigationLabel())->toBe('General Settings');
|
||||
expect($generalConfig->getNavigationGroup())->toBe('Settings');
|
||||
expect($generalConfig->getNavigationSort())->toBe(1);
|
||||
expect($generalConfig->getSettingsCategory())->toBe('general');
|
||||
|
||||
$advancedConfig = $panel->getPageConfiguration(ConfigurableSettings::class, 'advanced');
|
||||
expect($advancedConfig)->not->toBeNull();
|
||||
expect($advancedConfig->getSlug())->toBe('advanced-settings');
|
||||
expect($advancedConfig->getNavigationLabel())->toBe('Advanced Settings');
|
||||
expect($advancedConfig->getNavigationGroup())->toBe('Settings');
|
||||
expect($advancedConfig->getNavigationSort())->toBe(2);
|
||||
expect($advancedConfig->getSettingsCategory())->toBe('advanced');
|
||||
});
|
||||
Reference in New Issue
Block a user