diff --git a/Plugin.php b/Plugin.php index 537cc53..9559e52 100644 --- a/Plugin.php +++ b/Plugin.php @@ -2,9 +2,8 @@ use Backend\Classes\Controller as BackendController; use Backend\Models\UserRole; -use Barryvdh\Debugbar\Facades\Debugbar; -use Barryvdh\Debugbar\LaravelDebugbar; -use Barryvdh\Debugbar\SymfonyHttpDriver; +use Fruitcake\LaravelDebugbar\Facades\Debugbar; +use Fruitcake\LaravelDebugbar\LaravelDebugbar; use Cms\Classes\Controller as CmsController; use Cms\Classes\Layout; use Cms\Classes\Page; @@ -12,7 +11,6 @@ use Event; use Illuminate\Contracts\Http\Kernel as HttpKernelContract; use Illuminate\Foundation\AliasLoader; -use Illuminate\Session\SessionManager; use System\Classes\CombineAssets; use System\Classes\PluginBase; use Twig\Extension\ProfilerExtension; @@ -61,16 +59,12 @@ public function register() $this->app->register(\Winter\Debugbar\Classes\ServiceProvider::class); // Replace the LaravelDebugbar with the WinterDebugbar + // Laravel Debugbar 4 configures its own HTTP driver (LaravelHttpDriver), so we only + // need to swap in Winter's Debugbar subclass for the custom JavascriptRenderer styling. + // Resolve through the container so the constructor (Application $app, Request $request) + // dependencies are injected (Laravel Debugbar 4 requires both). $this->app->singleton(LaravelDebugbar::class, function ($app) { - $debugbar = new WinterDebugbar($app); - - if ($app->bound(SessionManager::class)) { - $sessionManager = $app->make(SessionManager::class); - $httpDriver = new SymfonyHttpDriver($sessionManager); - $debugbar->setHttpDriver($httpDriver); - } - - return $debugbar; + return $app->make(WinterDebugbar::class); }); // Register alias @@ -118,10 +112,12 @@ public function addGlobalCollectors() // Disable original models collector because it will be replaced Config::set('debugbar.collectors.models', false); - /** @var \Barryvdh\Debugbar\LaravelDebugbar $debugBar */ - $debugBar = $this->app->make(\Barryvdh\Debugbar\LaravelDebugbar::class); + /** @var \Fruitcake\LaravelDebugbar\LaravelDebugbar $debugBar */ + $debugBar = $this->app->make(\Fruitcake\LaravelDebugbar\LaravelDebugbar::class); $modelsCollector = $this->app->make(ModelsCollector::class); - $debugBar->addCollector($modelsCollector); + if (!$debugBar->hasCollector($modelsCollector->getName())) { + $debugBar->addCollector($modelsCollector); + } } } @@ -130,8 +126,8 @@ public function addGlobalCollectors() */ public function addFrontendCollectors() { - /** @var \Barryvdh\Debugbar\LaravelDebugbar $debugBar */ - $debugBar = $this->app->make(\Barryvdh\Debugbar\LaravelDebugbar::class); + /** @var \Fruitcake\LaravelDebugbar\LaravelDebugbar $debugBar */ + $debugBar = $this->app->make(\Fruitcake\LaravelDebugbar\LaravelDebugbar::class); if (Config::get('debugbar.collectors.cms', true)) { // Disable route collector as the CMS collector presents this info instead @@ -164,8 +160,8 @@ public function addFrontendCollectors() */ public function addBackendCollectors() { - /** @var \Barryvdh\Debugbar\LaravelDebugbar $debugBar */ - $debugBar = $this->app->make(\Barryvdh\Debugbar\LaravelDebugbar::class); + /** @var \Fruitcake\LaravelDebugbar\LaravelDebugbar $debugBar */ + $debugBar = $this->app->make(\Fruitcake\LaravelDebugbar\LaravelDebugbar::class); if (Config::get('debugbar.collectors.backend', true)) { Event::listen('backend.page.beforeDisplay', function (BackendController $controller, $action, array $params) use ($debugBar) { @@ -183,7 +179,7 @@ public function addBackendCollectors() protected function registerCmsTwigExtensions() { $profile = new Profile; - $debugBar = $this->app->make(\Barryvdh\Debugbar\LaravelDebugbar::class); + $debugBar = $this->app->make(\Fruitcake\LaravelDebugbar\LaravelDebugbar::class); Event::listen('cms.page.beforeDisplay', function ($controller, $url, $page) use ($profile, $debugBar) { $twig = $controller->getTwig(); @@ -197,9 +193,11 @@ protected function registerCmsTwigExtensions() } }); + // php-debugbar 2.x (shipped with Laravel Debugbar 4) no longer bundles a Twig profile + // collector, so only register one when the bridge class is actually available. if (class_exists(\DebugBar\Bridge\NamespacedTwigProfileCollector::class)) { $debugBar->addCollector(new \DebugBar\Bridge\NamespacedTwigProfileCollector($profile)); - } else { + } elseif (class_exists(\DebugBar\Bridge\TwigProfileCollector::class)) { $debugBar->addCollector(new \DebugBar\Bridge\TwigProfileCollector($profile)); } } diff --git a/classes/JavascriptRenderer.php b/classes/JavascriptRenderer.php deleted file mode 100644 index 036410c..0000000 --- a/classes/JavascriptRenderer.php +++ /dev/null @@ -1,19 +0,0 @@ -cssFiles['winter'] = __DIR__ . '/../assets/css/debugbar.css'; - } -} diff --git a/classes/ServiceProvider.php b/classes/ServiceProvider.php index 374fd0d..f3b5360 100644 --- a/classes/ServiceProvider.php +++ b/classes/ServiceProvider.php @@ -1,6 +1,7 @@ registerMiddleware(InjectDebugbar::class); + } + /** * Register the Debugbar Middleware * * @param string $middleware */ - protected function registerMiddleware($middleware) + protected function registerMiddleware(string $middleware): void { $kernel = $this->app[Kernel::class]; - $kernel->pushMiddleware(InjectDebugbar::class); + $kernel->pushMiddleware($middleware); } } diff --git a/classes/WinterDebugbar.php b/classes/WinterDebugbar.php index 2a7c25a..78c960d 100644 --- a/classes/WinterDebugbar.php +++ b/classes/WinterDebugbar.php @@ -1,21 +1,28 @@ jsRenderer === null) { - $this->jsRenderer = new JavascriptRenderer($this, $baseUrl, $basePath); + $alreadyBuilt = $this->jsRenderer !== null; + + $renderer = parent::getJavascriptRenderer($baseUrl, $basePath); + + if (!$alreadyBuilt) { + $renderer->addAssets(cssFiles: ['debugbar.css'], basePath: __DIR__ . '/../assets/css'); } - return $this->jsRenderer; + + return $renderer; } } diff --git a/collectors/BackendCollector.php b/collectors/BackendCollector.php index 5b6429b..27e3c4f 100644 --- a/collectors/BackendCollector.php +++ b/collectors/BackendCollector.php @@ -25,7 +25,7 @@ public function __construct(Controller $controller, $action, array $params = []) /** * {@inheritDoc} */ - public function collect() + public function collect(): array { $ajaxHandler = $this->controller->getAjaxHandler(); @@ -100,7 +100,7 @@ protected function getReflector($handler) /** * {@inheritDoc} */ - public function getName() + public function getName(): string { return 'backend'; } @@ -108,7 +108,7 @@ public function getName() /** * {@inheritDoc} */ - public function getWidgets() + public function getWidgets(): array { return [ 'route' => [ diff --git a/collectors/CmsCollector.php b/collectors/CmsCollector.php index 1523c33..4df4459 100644 --- a/collectors/CmsCollector.php +++ b/collectors/CmsCollector.php @@ -26,7 +26,7 @@ public function __construct(Controller $controller, $url, Page $page) /** * {@inheritDoc} */ - public function collect() + public function collect(): array { $ajaxHandler = $this->controller->getAjaxHandler(); @@ -103,7 +103,7 @@ protected function getReflector($handler) /** * {@inheritDoc} */ - public function getName() + public function getName(): string { return 'cms'; } @@ -111,7 +111,7 @@ public function getName() /** * {@inheritDoc} */ - public function getWidgets() + public function getWidgets(): array { return [ 'route' => [ diff --git a/collectors/ComponentsCollector.php b/collectors/ComponentsCollector.php index ca9d333..d87bbe6 100644 --- a/collectors/ComponentsCollector.php +++ b/collectors/ComponentsCollector.php @@ -28,7 +28,7 @@ public function __construct(Controller $controller, Page $page, Layout $layout) /** * {@inheritDoc} */ - public function collect() + public function collect(): array { /** @var ComponentBase[]|object $components */ $components = []; @@ -58,7 +58,7 @@ protected function makeComponentDetails($componentObj): array /** * {@inheritDoc} */ - public function getName() + public function getName(): string { return 'components'; } @@ -66,7 +66,7 @@ public function getName() /** * {@inheritDoc} */ - public function getWidgets() + public function getWidgets(): array { return [ 'components' => [ diff --git a/composer.json b/composer.json index bf72003..e821af9 100644 --- a/composer.json +++ b/composer.json @@ -23,9 +23,9 @@ "source": "https://github.com/wintercms/wn-debugbar-plugin" }, "require": { - "php": ">=7.0", + "php": ">=8.3", "composer/installers": "~1.0", - "barryvdh/laravel-debugbar": "^3.15.0" + "barryvdh/laravel-debugbar": "^4.2" }, "replace": { "rainlab/debugbar-plugin": ">=1.0.5" diff --git a/middleware/InjectDebugbar.php b/middleware/InjectDebugbar.php index 4e6ab64..00ecdaa 100644 --- a/middleware/InjectDebugbar.php +++ b/middleware/InjectDebugbar.php @@ -3,14 +3,51 @@ namespace Winter\Debugbar\Middleware; use Backend\Facades\BackendAuth; -use Barryvdh\Debugbar\Middleware\InjectDebugbar as BaseMiddleware; use Closure; +use Fruitcake\LaravelDebugbar\LaravelDebugbar; +use Illuminate\Foundation\Application; use Symfony\Component\HttpFoundation\Request; use Throwable; use Winter\Storm\Support\Facades\Config; -class InjectDebugbar extends BaseMiddleware +/** + * Injects the Debugbar into the response, gated by the winter.debugbar permissions. + * + * Laravel Debugbar 4 removed its own InjectDebugbar middleware in favour of a + * RequestHandled event listener (registered by the base ServiceProvider) that injects + * the Debugbar unconditionally. This middleware replicates the legacy behaviour: it boots + * the Debugbar, restricts request storage and injection to authorised users, and performs + * the response handling itself via LaravelDebugbar::handleResponse(). Because handleResponse() + * flags the response as modified, the base event listener becomes a no-op for this request. + */ +class InjectDebugbar { + /** + * The Laravel Application + * + * @var Application + */ + protected $app; + + /** + * The Debugbar instance + * + * @var LaravelDebugbar + */ + protected $debugbar; + + /** + * Create a new middleware instance. + * + * @param Application $app + * @param LaravelDebugbar $debugbar + */ + public function __construct(Application $app, LaravelDebugbar $debugbar) + { + $this->app = $app; + $this->debugbar = $debugbar; + } + /** * Handle an incoming request. * @@ -20,18 +57,14 @@ class InjectDebugbar extends BaseMiddleware */ public function handle($request, Closure $next) { - if (!$this->debugbar->isEnabled() || $this->inExceptArray($request)) { + if (!$this->debugbar->isEnabled() || $this->debugbar->requestIsExcluded($request)) { return $next($request); } $this->debugbar->boot(); - try { - /** @var \Illuminate\Http\Response $response */ - $response = $next($request); - } catch (Throwable $e) { - $response = $this->handleException($request, $e); - } + /** @var \Illuminate\Http\Response $response */ + $response = $next($request); // Database table might not exist yet try { @@ -49,14 +82,21 @@ public function handle($request, Closure $next) $this->debugbar->setStorage(null); } - // Modify the response to add the Debugbar if allowed + // Only inject the Debugbar into the response if the user is allowed to view it if ( - ($user && $user->hasAccess('winter.debugbar.access_debugbar')) || - Config::get('winter.debugbar::allow_public_access', false) + !($user && $user->hasAccess('winter.debugbar.access_debugbar')) && + !Config::get('winter.debugbar::allow_public_access', false) ) { - $this->debugbar->modifyResponse($request, $response); + // Prevent the visual Debugbar from being injected while still allowing + // permitted requests to be stored (handled by setStorage above) + Config::set('debugbar.inject', false); } + // Modify the response to add the Debugbar (and store the request, when permitted). + // This flags the response as modified, so the base ServiceProvider's RequestHandled + // listener will skip re-processing it. + $this->debugbar->handleResponse($request, $response); + return $response; } } diff --git a/middleware/InterpretsAjaxExceptions.php b/middleware/InterpretsAjaxExceptions.php index f4a858a..961a38d 100644 --- a/middleware/InterpretsAjaxExceptions.php +++ b/middleware/InterpretsAjaxExceptions.php @@ -38,7 +38,7 @@ public function __construct(Application $app) */ public function handle($request, Closure $next) { - /** @var \Barryvdh\Debugbar\LaravelDebugbar $debugbar */ + /** @var \Fruitcake\LaravelDebugbar\LaravelDebugbar $debugbar */ $debugbar = $this->app['debugbar']; try { diff --git a/twig/extension/Debug.php b/twig/extension/Debug.php index d9ebd57..39e2709 100644 --- a/twig/extension/Debug.php +++ b/twig/extension/Debug.php @@ -13,7 +13,7 @@ class Debug extends TwigExtension { /** - * @var \Barryvdh\Debugbar\LaravelDebugbar + * @var \Fruitcake\LaravelDebugbar\LaravelDebugbar */ protected $debugbar; diff --git a/twig/extension/Stopwatch.php b/twig/extension/Stopwatch.php index e886d44..e8c0988 100644 --- a/twig/extension/Stopwatch.php +++ b/twig/extension/Stopwatch.php @@ -13,7 +13,7 @@ class Stopwatch extends TwigExtension { /** - * @var \Barryvdh\Debugbar\LaravelDebugbar + * @var \Fruitcake\LaravelDebugbar\LaravelDebugbar */ protected $debugbar;