├── src ├── Testing │ └── TestsFilamentPageContext.php ├── CustomFilamentManager.php ├── FilamentPageContextServiceProvider.php └── FilamentPageContext.php ├── CHANGELOG.md ├── LICENSE.md ├── composer.json └── README.md /src/Testing/TestsFilamentPageContext.php: -------------------------------------------------------------------------------- 1 | name(static::$name); 15 | } 16 | 17 | public function packageRegistered(): void 18 | { 19 | app()->extend('filament', function ($filament, $app) { 20 | return new CustomFilamentManager($app); 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `filament-page-context` will be documented in this file. 4 | 5 | ## v1.0.6 - 2025-02-19 6 | 7 | **Full Changelog**: https://github.com/diogogpinto/filament-page-context/compare/v1.0.5...v1.0.6 8 | 9 | ## v1.0.5 - 2024-10-12 10 | 11 | **Full Changelog**: https://github.com/diogogpinto/filament-page-context/compare/v1.0.4...v1.0.5 12 | 13 | ## v1.0.4 - 2024-10-04 14 | 15 | **Full Changelog**: https://github.com/diogogpinto/filament-page-context/compare/v1.0.3...v1.0.4 16 | 17 | ## v1.0.3 - 2024-10-04 18 | 19 | **Full Changelog**: https://github.com/diogogpinto/filament-page-context/compare/v1.0.2...v1.0.3 20 | 21 | ## v1.0.2 - 2024-10-02 22 | 23 | **Full Changelog**: https://github.com/diogogpinto/filament-page-context/compare/v1.0.1...v1.0.2 24 | 25 | ## v1.0.1 - 2024-10-02 26 | 27 | Minor optimizations 28 | 29 | ## 1.0.0 - 202X-XX-XX 30 | 31 | - initial release 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) diogogpinto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "diogogpinto/filament-page-context", 3 | "description": "A Filament plugin that automatically injects current request breadcrumbs and page title into the filament() method, enhancing page context and navigation for Filament admin panels.", 4 | "keywords": [ 5 | "diogogpinto", 6 | "laravel", 7 | "filament-page-context" 8 | ], 9 | "homepage": "https://github.com/diogogpinto/filament-page-context", 10 | "support": { 11 | "issues": "https://github.com/diogogpinto/filament-page-context/issues", 12 | "source": "https://github.com/diogogpinto/filament-page-context" 13 | }, 14 | "license": "MIT", 15 | "authors": [ 16 | { 17 | "name": "Diogo Pinto", 18 | "role": "Developer" 19 | } 20 | ], 21 | "require": { 22 | "php": "^8.1", 23 | "filament/filament": "^3.0", 24 | "spatie/laravel-package-tools": "^1.15.0" 25 | }, 26 | "require-dev": { 27 | "laravel/pint": "^1.0", 28 | "nunomaduro/collision": "^7.9", 29 | "nunomaduro/larastan": "^2.0.1", 30 | "orchestra/testbench": "^8.0", 31 | "pestphp/pest": "^2.1", 32 | "pestphp/pest-plugin-arch": "^2.0", 33 | "pestphp/pest-plugin-laravel": "^2.0", 34 | "phpstan/extension-installer": "^1.1", 35 | "phpstan/phpstan-deprecation-rules": "^1.0", 36 | "phpstan/phpstan-phpunit": "^1.0" 37 | }, 38 | "autoload": { 39 | "psr-4": { 40 | "DiogoGPinto\\FilamentPageContext\\": "src/" 41 | } 42 | }, 43 | "autoload-dev": { 44 | "psr-4": { 45 | "DiogoGPinto\\FilamentPageContext\\Tests\\": "tests/" 46 | } 47 | }, 48 | "scripts": { 49 | "post-autoload-dump": "@php ./vendor/bin/testbench package:discover --ansi", 50 | "analyse": "vendor/bin/phpstan analyse", 51 | "test": "vendor/bin/pest", 52 | "test-coverage": "vendor/bin/pest --coverage", 53 | "format": "vendor/bin/pint" 54 | }, 55 | "config": { 56 | "sort-packages": true, 57 | "allow-plugins": { 58 | "pestphp/pest-plugin": true, 59 | "phpstan/extension-installer": true 60 | } 61 | }, 62 | "extra": { 63 | "laravel": { 64 | "providers": [ 65 | "DiogoGPinto\\FilamentPageContext\\FilamentPageContextServiceProvider" 66 | ] 67 | } 68 | }, 69 | "minimum-stability": "stable", 70 | "prefer-stable": true 71 | } 72 | -------------------------------------------------------------------------------- /src/FilamentPageContext.php: -------------------------------------------------------------------------------- 1 | generateBreadcrumbs(); 22 | $this->setPageTitle(); 23 | } 24 | 25 | public function generateBreadcrumbs(): void 26 | { 27 | $this->resource = $this->getResource(); 28 | $this->addResourceBreadcrumb(); 29 | $this->addRecordBreadcrumb(); 30 | $this->addControllerBreadcrumb(); 31 | $this->addClusterBreadcrumbs(); 32 | } 33 | 34 | protected function addResourceBreadcrumb(): void 35 | { 36 | if ($this->resource) { 37 | $this->breadcrumbs[$this->resource->getUrl()] = $this->resource->getBreadcrumb(); 38 | } 39 | } 40 | 41 | protected function addRecordBreadcrumb(): void 42 | { 43 | if (! $this->resource || ! request()->record) { 44 | return; 45 | } 46 | 47 | $this->resolveRecord(request()->record); 48 | 49 | $url = $this->getRecordUrl(); 50 | $title = $this->getRecordTitle(); 51 | 52 | if ($url) { 53 | $this->breadcrumbs[$url] = $title; 54 | } else { 55 | $this->breadcrumbs[] = $title; 56 | } 57 | } 58 | 59 | protected function addControllerBreadcrumb(): void 60 | { 61 | if (method_exists(request()->route()->controller, 'getBreadcrumb')) { 62 | $this->breadcrumbs[] = request()->route()->controller->getBreadcrumb(); 63 | } 64 | } 65 | 66 | protected function addClusterBreadcrumbs(): void 67 | { 68 | if ($this->resource && ($cluster = $this->resource->getCluster())) { 69 | $this->breadcrumbs = (new $cluster)->unshiftClusterBreadcrumbs($this->breadcrumbs); 70 | } 71 | } 72 | 73 | protected function getRecordUrl(): ?string 74 | { 75 | if ($this->resource::hasPage('view') && $this->resource::canView($this->record)) { 76 | return $this->resource::getUrl('view', ['record' => $this->record]); 77 | } 78 | if ($this->resource::hasPage('edit') && $this->resource::canEdit($this->record)) { 79 | return $this->resource::getUrl('edit', ['record' => $this->record]); 80 | } 81 | 82 | return null; 83 | } 84 | 85 | protected function getResource(): ?Resource 86 | { 87 | if (method_exists(request()->route(), 'getController') && method_exists(request()->route()->getController(), 'getResource')) { 88 | return new (request()->route()->getController()->getResource()); 89 | } 90 | 91 | return null; 92 | } 93 | 94 | protected function getRecordTitle(): string 95 | { 96 | return $this->resource::hasRecordTitle() 97 | ? $this->resource::getRecordTitle($this->record) 98 | : $this->resource::getTitleCaseModelLabel(); 99 | } 100 | 101 | protected function setPageTitle(): void 102 | { 103 | $this->pageTitle = empty($this->record) ? $this->getDefaultTitle() : $this->getRecordTitle(); 104 | } 105 | 106 | protected function getDefaultTitle(): string 107 | { 108 | if (method_exists(request()->route()->controller, 'getTitle')) { 109 | return request()->route()->controller->getTitle(); 110 | } 111 | 112 | return $this->resource::getTitleCaseModelLabel(); 113 | } 114 | 115 | public function resolveRecord(int | string $key): void 116 | { 117 | $this->record = $this->resource::resolveRecordRouteBinding($key); 118 | if ($this->record === null) { 119 | throw (new ModelNotFoundException)->setModel(request()->route()->controller->getModel(), [$key]); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Filament Panel Page Context 2 | 3 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/diogogpinto/filament-page-context.svg?style=flat-square)](https://packagist.org/packages/diogogpinto/filament-page-context) 4 | [![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/diogogpinto/filament-page-context/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/diogogpinto/filament-page-context/actions?query=workflow%3Arun-tests+branch%3Amain) 5 | [![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/diogogpinto/filament-page-context/fix-php-code-style-issues.yml?branch=main&label=code%20style&style=flat-squaresquare)](https://github.com/diogogpinto/filament-page-context/actions?query=workflow%3A"Fix+PHP+code+styling"+branch%3Amain) 6 | [![Total Downloads](https://img.shields.io/packagist/dt/diogogpinto/filament-page-context.svg?style=flat-square)](https://packagist.org/packages/diogogpinto/filament-page-context) 7 | 8 | A Filament plugin that automatically injects current request breadcrumbs and page title into the filament() method, enhancing context and navigation for admin panels. Developed with theme extensibility in mind, it seamlessly integrates with and allows further customization of Filament themes. Created with the purpose to get current request breadcrumbs and pagetitle and inject them anywhere in the panel. 9 | 10 | It currently returns the current request's Filament breadcrumbs (with Filament's structure) and Page Title (can be a Custom Page Title, Resource Related Title or Record Related Title). 11 | 12 | ![Filament Page Context example returned array](screenshots/filament-page-context-array-preview.png) 13 | 14 | ## Installation 15 | 16 | You can install the package via composer: 17 | 18 | ```bash 19 | composer require diogogpinto/filament-page-context 20 | ``` 21 | 22 | ## Usage 23 | 24 | That's it. Once you install this plugin, the FilamentPageContext Service Provider will be injected automatically into Laravel Service Providers and extend your filament() method. 25 | 26 | ### Getting Filament's current request breadcrumbs 27 | 28 | ```php 29 | $breadcrumbs = filament()->pageContext()->breadcrumbs; 30 | ``` 31 | 32 | ### Getting Filament's current request page title 33 | 34 | ```php 35 | $pageTitle = filament()->pageContext()->pageTitle; 36 | ``` 37 | 38 | ### Add Filament's breadcrumbs to your topbar 39 | 40 | ![Filament Breadcrumbs on Topbar](screenshots/filament-breadcrumbs-on-top.png) 41 | 42 | This is a request I've been getting lately that will have its own plugin really soon. Until then, you can follow the guide below: 43 | 44 | 1. Create a new view (resources/views/topbar-breadcrumbs.php) and add the following code: 45 | 46 | ```php 47 | @props([ 48 | 'breadcrumbs' => filament()->pageContext()->breadcrumbs, 49 | ]) 50 | 51 | 52 | ``` 53 | 54 | 2. Add the following snippet to your AppServiceProvider.php 55 | ```php 56 | use Illuminate\View\View; 57 | 58 | /** 59 | * Bootstrap any application services. 60 | * 61 | * @return void 62 | */ 63 | public function boot() 64 | { 65 | // your other methods 66 | FilamentView::registerRenderHook( 67 | PanelsRenderHook::TOPBAR_START, 68 | fn (): View => view('topbar-breadcrumbs'), 69 | ); 70 | } 71 | ``` 72 | 73 | > :warning: **Warning:** This is just an example of how to inject breadcrumbs in the topbar. You should be aware that this code isn't responsive and can mess your mobile functionality. 74 | 75 | ## Testing 76 | 77 | ```bash 78 | composer test 79 | ``` 80 | 81 | ## Changelog 82 | 83 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 84 | 85 | ## Contributing 86 | 87 | Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details. 88 | 89 | ## Security Vulnerabilities 90 | 91 | Please review [our security policy](../../security/policy) on how to report security vulnerabilities. 92 | 93 | ## Credits 94 | 95 | - [Diogo Pinto](https://github.com/diogogpinto) 96 | - [Adam Weston](https://github.com/awcodes) for the mentorship and all the help 97 | - Special thanks to [Tony Partidge](https://github.com/tonypartridge) and [Fady Mondy](https://github.com/3x1io) for all the help over Filament Discord 98 | - [Geridoc](https://www.geridoc.pt) for giving me the opportunity to share our code to the public 99 | - [All Contributors](../../contributors) 100 | 101 | ## License 102 | 103 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 104 | --------------------------------------------------------------------------------