Skip to content

Commit

Permalink
Add BarOutput
Browse files Browse the repository at this point in the history
  • Loading branch information
guanguans committed Apr 15, 2022
1 parent c9a6d29 commit 330aa5c
Show file tree
Hide file tree
Showing 9 changed files with 332 additions and 3 deletions.
1 change: 1 addition & 0 deletions config/soar.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
*/
'except' => [
'*telescope*',
'*horizon*',
],

/*
Expand Down
2 changes: 1 addition & 1 deletion src/Bootstrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
namespace Guanguans\LaravelSoar;

use Guanguans\LaravelSoar\Facades\Soar;
use Guanguans\LaravelSoar\Middleware\OutputSoarScoreMiddleware;
use Guanguans\LaravelSoar\Http\Middleware\OutputSoarScoreMiddleware;
use Illuminate\Console\Events\CommandFinished;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Http\Kernel;
Expand Down
77 changes: 77 additions & 0 deletions src/Http/Controllers/AssetController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

/**
* This file is part of the guanguans/laravel-soar.
*
* (c) guanguans <[email protected]>
*
* This source file is subject to the MIT license that is bundled.
*/

namespace Guanguans\LaravelSoar\Http\Controllers;

use DateTime;
use Guanguans\LaravelSoar\SoarDebugBar;
use Illuminate\Http\Response;
use Illuminate\Routing\Controller;

/**
* This is modified from the https://github.com/barryvdh/laravel-debugbar.
*
* @see https://github.com/barryvdh/laravel-debugbar/blob/master/src/Controllers/AssetController.php
*/
class AssetController extends Controller
{
public function __construct(SoarDebugBar $debugBar)
{
$this->debugBar = $debugBar;
}

/**
* Return the javascript for the DebugBar.
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function js()
{
$renderer = $this->debugBar->getJavascriptRenderer();
$content = $renderer->dumpAssetsToString('js');
$response = new Response(
$content,
200,
['Content-Type' => 'text/javascript']
);

return $this->cacheResponse($response);
}

/**
* Return the stylesheets for the DebugBar.
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function css()
{
$renderer = $this->debugBar->getJavascriptRenderer();
$content = $renderer->dumpAssetsToString('css');
$response = new Response(
$content,
200,
['Content-Type' => 'text/css']
);

return $this->cacheResponse($response);
}

/**
* Cache the response 1 year (31536000 sec).
*/
protected function cacheResponse(Response $response)
{
$response->setSharedMaxAge(31536000);
$response->setMaxAge(31536000);
$response->setExpires(new DateTime('+1 year'));

return $response;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* This source file is subject to the MIT license that is bundled.
*/

namespace Guanguans\LaravelSoar\Middleware;
namespace Guanguans\LaravelSoar\Http\Middleware;

use Closure;
use Guanguans\LaravelSoar\Bootstrapper;
Expand Down
28 changes: 28 additions & 0 deletions src/Http/routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

/**
* This file is part of the guanguans/laravel-soar.
*
* (c) guanguans <[email protected]>
*
* This source file is subject to the MIT license that is bundled.
*/

$routeOptions = [
'namespace' => 'Guanguans\LaravelSoar\Http\Controllers',
'prefix' => app('config')->get('soar.route_prefix', 'soar-debugbar'),
'domain' => app('config')->get('soar.route_domain', null),
'middleware' => [],
];

app('router')->group($routeOptions, function ($router) {
$router->get('assets/stylesheets', [
'uses' => 'AssetController@css',
'as' => 'soar.debugbar.assets.css',
]);

$router->get('assets/javascript', [
'uses' => 'AssetController@js',
'as' => 'soar.debugbar.assets.js',
]);
});
148 changes: 148 additions & 0 deletions src/JavascriptRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<?php

/**
* This file is part of the guanguans/laravel-soar.
*
* (c) guanguans <[email protected]>
*
* This source file is subject to the MIT license that is bundled.
*/

namespace Guanguans\LaravelSoar;

/**
* This is modified from the https://github.com/barryvdh/laravel-debugbar.
*
* @see https://github.com/barryvdh/laravel-debugbar/blob/master/src/JavascriptRenderer.php
*/
class JavascriptRenderer extends \DebugBar\JavascriptRenderer
{
// Use XHR handler by default, instead of jQuery
protected $ajaxHandlerBindToJquery = false;

protected $ajaxHandlerBindToXHR = true;

/**
* Set the URL Generator.
*
* @param \Illuminate\Routing\UrlGenerator $url
*
* @deprecated
*/
public function setUrlGenerator($url)
{
}

/**
* {@inheritdoc}
*/
public function renderHead()
{
$cssRoute = route('soar.debugbar.assets.css', [
'v' => $this->getModifiedTime('css'),
'theme' => config('debugbar.theme', 'auto'),
]);

$jsRoute = route('soar.debugbar.assets.js', [
'v' => $this->getModifiedTime('js'),
]);

$cssRoute = preg_replace('/\Ahttps?:/', '', $cssRoute);
$jsRoute = preg_replace('/\Ahttps?:/', '', $jsRoute);

$html = "<link rel='stylesheet' type='text/css' property='stylesheet' href='{$cssRoute}'>";
$html .= "<script src='{$jsRoute}'></script>";

if ($this->isJqueryNoConflictEnabled()) {
$html .= '<script>jQuery.noConflict(true);</script>'."\n";
}

$html .= $this->getInlineHtml();

return $html;
}

protected function getInlineHtml()
{
$html = '';

foreach (['head', 'css', 'js'] as $asset) {
foreach ($this->getAssets('inline_'.$asset) as $item) {
$html .= $item."\n";
}
}

return $html;
}

/**
* Get the last modified time of any assets.
*
* @param string $type 'js' or 'css'
*
* @return int
*/
protected function getModifiedTime($type)
{
$files = $this->getAssets($type);

$latest = 0;
foreach ($files as $file) {
$mtime = filemtime($file);
if ($mtime > $latest) {
$latest = $mtime;
}
}

return $latest;
}

/**
* Return assets as a string.
*
* @param string $type 'js' or 'css'
*
* @return string
*/
public function dumpAssetsToString($type)
{
$files = $this->getAssets($type);

$content = '';
foreach ($files as $file) {
$content .= file_get_contents($file)."\n";
}

return $content;
}

/**
* Makes a URI relative to another.
*
* @param string|array $uri
* @param string $root
*
* @return array|string
*/
protected function makeUriRelativeTo($uri, $root)
{
if (! $root) {
return $uri;
}

if (is_array($uri)) {
$uris = [];
foreach ($uri as $u) {
$uris[] = $this->makeUriRelativeTo($u, $root);
}

return $uris;
}

if ('/' === substr($uri ?? '', 0, 1) || preg_match('/^([a-zA-Z]+:\/\/|[a-zA-Z]:\/|[a-zA-Z]:\\\)/', $uri ?? '')) {
return $uri;
}

return rtrim($root, '/')."/$uri";
}
}
44 changes: 43 additions & 1 deletion src/Outputs/BarOutput.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,59 @@

namespace Guanguans\LaravelSoar\Outputs;

use Guanguans\LaravelSoar\SoarDebugBar;
use Illuminate\Support\Collection;

class BarOutput extends Output
{
public function __construct(SoarDebugBar $debugBar)
{
$this->debugBar = $debugBar;
}

/**
* @param \Symfony\Component\HttpFoundation\Response $response
*
* @return mixed
*/
public function output(Collection $scores, $response)
{
// TODO: Implement output() method.
if (! $this->shouldOutputInHtmlResponse($response) || $this->shouldOutputInDebugBar($response)) {
return;
}

$debugBar = $this->debugBar;
$renderer = $debugBar->getJavascriptRenderer();
$scores->each(function (array $score) use ($debugBar) {
$summary = $score['Summary'];
$level = $score['Basic']['Level'];
unset($score['Summary'], $score['Basic']);
$debugBar['messages']->addMessage($summary.PHP_EOL.var_output($score, true), $level, false);
});

$content = $response->getContent();
$head = $renderer->renderHead();
$widget = $renderer->render();

// Try to put the js/css directly before the </head>
$pos = strripos($content, '</head>');
if (false !== $pos) {
$content = substr($content, 0, $pos).$head.substr($content, $pos);
} else {
// Append the head before the widget
$widget = $head.$widget;
}

// Try to put the widget at the end, directly before the </body>
$pos = strripos($content, '</body>');
if (false !== $pos) {
$content = substr($content, 0, $pos).$widget.substr($content, $pos);
} else {
$content = $content.$widget;
}

// Update the new content and reset the content length
$response->setContent($content);
$response->headers->remove('Content-Length');
}
}
27 changes: 27 additions & 0 deletions src/SoarDebugBar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* This file is part of the guanguans/laravel-soar.
*
* (c) guanguans <[email protected]>
*
* This source file is subject to the MIT license that is bundled.
*/

namespace Guanguans\LaravelSoar;

use DebugBar\DataCollector\MemoryCollector;
use DebugBar\DataCollector\MessagesCollector;
use DebugBar\DataCollector\PhpInfoCollector;
use DebugBar\DebugBar;

class SoarDebugBar extends DebugBar
{
public function __construct()
{
$this->addCollector(new PhpInfoCollector());
$this->addCollector(new MessagesCollector());
$this->addCollector(new MemoryCollector());
$this->jsRenderer = new JavascriptRenderer($this);
}
}
6 changes: 6 additions & 0 deletions src/SoarServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public function register()
$this->registerSingletons();
$this->registerSoar();
$this->registerOutputManager();
$this->registerRoutes();
}

public function boot()
Expand Down Expand Up @@ -109,6 +110,11 @@ protected function registerOutputManager(): void
$this->app->alias(OutputManager::class, 'output_manager');
}

protected function registerRoutes(): void
{
$this->loadRoutesFrom(realpath(__DIR__.'/Http/routes.php'));
}

/**
* {@inheritdoc}
*/
Expand Down

0 comments on commit 330aa5c

Please sign in to comment.