mirror of
https://github.com/jbcr/core.git
synced 2026-04-01 22:02:16 +02:00
Merge pull request #430 from bolt/stopwatch-trait-for-widgets
Stopwatch trait for widgets
This commit is contained in:
@@ -55,6 +55,6 @@ trait CacheTrait
|
||||
|
||||
private function createKey()
|
||||
{
|
||||
return $this->getName() . $this->getTarget() . $this->getZone() . $this->getPriority();
|
||||
return sprintf('%s-%s-%s', $this->getSlug(), $this->getZone(), $this->getCacheDuration());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace Bolt\Widget\Injector;
|
||||
|
||||
use Bolt\Widget\CacheAware;
|
||||
use Bolt\Widget\RequestAware;
|
||||
use Bolt\Widget\ResponseAware;
|
||||
use Bolt\Widget\WidgetInterface;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
@@ -44,7 +46,7 @@ class QueueProcessor
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function process(Response $response, Request $request, Collection $queue, string $zone): void
|
||||
public function process(Response $response, Request $request, Collection $queue, CacheInterface $cache, string $zone): void
|
||||
{
|
||||
/** @var WidgetInterface $widget */
|
||||
foreach ($queue as $widget) {
|
||||
@@ -55,6 +57,9 @@ class QueueProcessor
|
||||
if ($widget instanceof ResponseAware) {
|
||||
$widget->setResponse($response);
|
||||
}
|
||||
if ($widget instanceof CacheAware) {
|
||||
$widget->setCache($cache);
|
||||
}
|
||||
$this->injector->inject($widget, $response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,10 @@ use Bolt\Widget\Injector\RequestZone;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
|
||||
class NewsWidget extends BaseWidget implements TwigAware, RequestAware, CacheAware
|
||||
class NewsWidget extends BaseWidget implements TwigAware, RequestAware, CacheAware, StopwatchAware
|
||||
{
|
||||
use CacheTrait;
|
||||
use StopwatchTrait;
|
||||
|
||||
protected $name = 'News Widget';
|
||||
protected $target = AdditionalTarget::WIDGET_BACK_DASHBOARD_ASIDE_TOP;
|
||||
|
||||
@@ -9,6 +9,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
trait RequestTrait
|
||||
{
|
||||
/** @var Request */
|
||||
private $request;
|
||||
|
||||
public function setRequest(Request $request): self
|
||||
|
||||
@@ -9,6 +9,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
trait ResponseTrait
|
||||
{
|
||||
/** @var Response */
|
||||
private $response;
|
||||
|
||||
public function setResponse(Response $response): self
|
||||
|
||||
18
src/Widget/StopwatchAware.php
Normal file
18
src/Widget/StopwatchAware.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Bolt\Widget;
|
||||
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
|
||||
/**
|
||||
* Interface StopwatchAware - Widgets that implement this interface, will have
|
||||
* their execution time show up in Symfony's Profiler
|
||||
*/
|
||||
interface StopwatchAware extends WidgetInterface
|
||||
{
|
||||
public function startStopwatch(Stopwatch $stopwatch);
|
||||
|
||||
public function stopStopwatch();
|
||||
}
|
||||
25
src/Widget/StopwatchTrait.php
Normal file
25
src/Widget/StopwatchTrait.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Bolt\Widget;
|
||||
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
|
||||
trait StopwatchTrait
|
||||
{
|
||||
/** @var Stopwatch */
|
||||
private $stopwatch;
|
||||
|
||||
public function startStopwatch(Stopwatch $stopwatch): void
|
||||
{
|
||||
$this->stopwatch = $stopwatch;
|
||||
|
||||
$this->stopwatch->start('widget.' . $this->getSlug());
|
||||
}
|
||||
|
||||
public function stopStopwatch(): void
|
||||
{
|
||||
$this->stopwatch->stop('widget.' . $this->getSlug());
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ use Twig\Environment;
|
||||
|
||||
trait TwigTrait
|
||||
{
|
||||
/** @var Environment */
|
||||
private $twig;
|
||||
|
||||
public function setTwig(Environment $twig): self
|
||||
|
||||
@@ -9,13 +9,17 @@ use Bolt\Widget\Injector\RequestZone;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
|
||||
class WeatherWidget extends BaseWidget implements TwigAware
|
||||
class WeatherWidget extends BaseWidget implements TwigAware, CacheAware, StopwatchAware
|
||||
{
|
||||
use CacheTrait;
|
||||
use StopwatchTrait;
|
||||
|
||||
protected $name = 'Weather Widget';
|
||||
protected $target = AdditionalTarget::WIDGET_BACK_DASHBOARD_ASIDE_TOP;
|
||||
protected $priority = 200;
|
||||
protected $template = '@bolt/widgets/weather.twig';
|
||||
protected $zone = RequestZone::BACKEND;
|
||||
protected $cacheDuration = 3600;
|
||||
|
||||
/** @var string Open API key, don't use more than once per second */
|
||||
public const KEY = '0acbdeea56dfafe244ac87707c5fdcb2';
|
||||
|
||||
@@ -8,12 +8,14 @@ use Bolt\Widget\CacheAware;
|
||||
use Bolt\Widget\Injector\QueueProcessor;
|
||||
use Bolt\Widget\Injector\RequestZone;
|
||||
use Bolt\Widget\RequestAware;
|
||||
use Bolt\Widget\StopwatchAware;
|
||||
use Bolt\Widget\TwigAware;
|
||||
use Bolt\Widget\WidgetInterface;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
use Twig\Environment;
|
||||
|
||||
@@ -37,13 +39,22 @@ class Widgets
|
||||
/** @var CacheInterface */
|
||||
private $cache;
|
||||
|
||||
public function __construct(RequestStack $requestStack, QueueProcessor $queueProcessor, Environment $twig, CacheInterface $cache)
|
||||
{
|
||||
/** @var Stopwatch */
|
||||
private $stopwatch;
|
||||
|
||||
public function __construct(
|
||||
RequestStack $requestStack,
|
||||
QueueProcessor $queueProcessor,
|
||||
Environment $twig,
|
||||
CacheInterface $cache,
|
||||
Stopwatch $stopwatch
|
||||
) {
|
||||
$this->queue = new Collection([]);
|
||||
$this->requestStack = $requestStack;
|
||||
$this->queueProcessor = $queueProcessor;
|
||||
$this->twig = $twig;
|
||||
$this->cache = $cache;
|
||||
$this->stopwatch = $stopwatch;
|
||||
}
|
||||
|
||||
public function registerWidget(WidgetInterface $widget): void
|
||||
@@ -85,6 +96,10 @@ class Widgets
|
||||
|
||||
private function invokeWidget(WidgetInterface $widget, array $params = []): string
|
||||
{
|
||||
if ($widget instanceof StopwatchAware) {
|
||||
$widget->startStopwatch($this->stopwatch);
|
||||
}
|
||||
|
||||
if ($widget instanceof RequestAware) {
|
||||
$widget->setRequest($this->requestStack->getCurrentRequest());
|
||||
}
|
||||
@@ -94,7 +109,13 @@ class Widgets
|
||||
}
|
||||
|
||||
// Call the magic `__invoke` method on the $widget object
|
||||
return $widget($params);
|
||||
$renderedWidget = $widget($params);
|
||||
|
||||
if ($widget instanceof StopwatchAware) {
|
||||
$widget->stopStopwatch();
|
||||
}
|
||||
|
||||
return $renderedWidget;
|
||||
}
|
||||
|
||||
public function processQueue(Response $response): Response
|
||||
@@ -111,11 +132,12 @@ class Widgets
|
||||
}
|
||||
|
||||
$queue = $this->queue;
|
||||
$cache = $this->cache;
|
||||
|
||||
return $this->queueProcessor->guardResponse(
|
||||
$response,
|
||||
function (Response $response) use ($request, $queue, $zone): void {
|
||||
$this->queueProcessor->process($response, $request, $queue, $zone);
|
||||
function (Response $response) use ($request, $queue, $cache, $zone): void {
|
||||
$this->queueProcessor->process($response, $request, $queue, $cache, $zone);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,26 +19,34 @@ use Symfony\Component\Cache\Simple\Psr6Cache;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
|
||||
class WidgetsTest extends StringTestCase
|
||||
{
|
||||
public function testProcessWidgetsInQueue(): void
|
||||
private function getWidgetsObject(array $templates = ['weather.twig' => '[Hello, weather!]'], $zone = RequestZone::BACKEND): Widgets
|
||||
{
|
||||
$queueProcessor = new QueueProcessor(new HtmlInjector());
|
||||
$requestStack = new RequestStack();
|
||||
|
||||
$request = Request::createFromGlobals();
|
||||
RequestZone::setToRequest($request, RequestZone::BACKEND);
|
||||
RequestZone::setToRequest($request, $zone);
|
||||
$requestStack->push($request);
|
||||
|
||||
$loader = new ArrayLoader(['weather.twig' => '[Hello, weather!]']);
|
||||
$loader = new ArrayLoader($templates);
|
||||
$twig = new Environment($loader);
|
||||
|
||||
$cache = new Psr6Cache(new TraceableAdapter(new FilesystemAdapter()));
|
||||
$stopwatch = new Stopwatch();
|
||||
|
||||
return new Widgets($requestStack, $queueProcessor, $twig, $cache, $stopwatch);
|
||||
}
|
||||
|
||||
public function testProcessWidgetsInQueue(): void
|
||||
{
|
||||
$widgets = $this->getWidgetsObject();
|
||||
|
||||
$widgets = new Widgets($requestStack, $queueProcessor, $twig, $cache);
|
||||
$response = new Response('<html><body>foo</body></html>');
|
||||
|
||||
$snippet = (new SnippetWidget())
|
||||
@@ -54,16 +62,7 @@ class WidgetsTest extends StringTestCase
|
||||
|
||||
public function testRenderWidget(): void
|
||||
{
|
||||
$queueProcessor = new QueueProcessor(new HtmlInjector());
|
||||
$requestStack = new RequestStack();
|
||||
$requestStack->push(Request::createFromGlobals());
|
||||
|
||||
$loader = new ArrayLoader(['weather.twig' => '[Hello, weather!]']);
|
||||
$twig = new Environment($loader);
|
||||
|
||||
$cache = new Psr6Cache(new TraceableAdapter(new FilesystemAdapter()));
|
||||
|
||||
$widgets = new Widgets($requestStack, $queueProcessor, $twig, $cache);
|
||||
$widgets = $this->getWidgetsObject();
|
||||
|
||||
$weatherWidget = new WeatherWidget();
|
||||
$weatherWidget->setTemplate('weather.twig');
|
||||
@@ -79,16 +78,7 @@ class WidgetsTest extends StringTestCase
|
||||
|
||||
public function testRenderWidgetWithExtraParameters(): void
|
||||
{
|
||||
$queueProcessor = new QueueProcessor(new HtmlInjector());
|
||||
$requestStack = new RequestStack();
|
||||
$requestStack->push(Request::createFromGlobals());
|
||||
|
||||
$loader = new ArrayLoader(['dummy.twig' => '[Hello, {{ foo }}!]']);
|
||||
$twig = new Environment($loader);
|
||||
|
||||
$cache = new Psr6Cache(new TraceableAdapter(new FilesystemAdapter()));
|
||||
|
||||
$widgets = new Widgets($requestStack, $queueProcessor, $twig, $cache);
|
||||
$widgets = $this->getWidgetsObject(['dummy.twig' => '[Hello, {{ foo }}!]']);
|
||||
|
||||
$widget = new DummyWidget();
|
||||
$widget->setTemplate('dummy.twig');
|
||||
@@ -103,17 +93,7 @@ class WidgetsTest extends StringTestCase
|
||||
|
||||
public function testProcessHeaderWidget(): void
|
||||
{
|
||||
$request = new Request();
|
||||
RequestZone::setToRequest($request, RequestZone::FRONTEND);
|
||||
$requestStack = new RequestStack();
|
||||
$requestStack->push($request);
|
||||
|
||||
$queueProcessor = new QueueProcessor(new HtmlInjector());
|
||||
$twig = new Environment(new ArrayLoader());
|
||||
|
||||
$cache = new Psr6Cache(new TraceableAdapter(new FilesystemAdapter()));
|
||||
|
||||
$widgets = new Widgets($requestStack, $queueProcessor, $twig, $cache);
|
||||
$widgets = $this->getWidgetsObject([], RequestZone::FRONTEND);
|
||||
|
||||
$response = new Response('<html><body>foo</body></html>');
|
||||
|
||||
@@ -127,18 +107,7 @@ class WidgetsTest extends StringTestCase
|
||||
|
||||
public function testProcessWeatherWidgetInTarget(): void
|
||||
{
|
||||
$request = new Request();
|
||||
RequestZone::setToRequest($request, RequestZone::BACKEND);
|
||||
$requestStack = new RequestStack();
|
||||
$requestStack->push($request);
|
||||
|
||||
$queueProcessor = new QueueProcessor(new HtmlInjector());
|
||||
$loader = new ArrayLoader(['weather.twig' => '[Hello, weather!]']);
|
||||
$twig = new Environment($loader);
|
||||
|
||||
$cache = new Psr6Cache(new TraceableAdapter(new FilesystemAdapter()));
|
||||
|
||||
$widgets = new Widgets($requestStack, $queueProcessor, $twig, $cache);
|
||||
$widgets = $this->getWidgetsObject();
|
||||
|
||||
$response = new Response('<html><body>foo</body></html>');
|
||||
|
||||
@@ -159,18 +128,7 @@ class WidgetsTest extends StringTestCase
|
||||
|
||||
public function testProcessWeatherWidgetInTarget2(): void
|
||||
{
|
||||
$request = new Request();
|
||||
RequestZone::setToRequest($request, RequestZone::BACKEND);
|
||||
$requestStack = new RequestStack();
|
||||
$requestStack->push($request);
|
||||
|
||||
$queueProcessor = new QueueProcessor(new HtmlInjector());
|
||||
$loader = new ArrayLoader(['weather.twig' => '[Hello, weather!]']);
|
||||
$twig = new Environment($loader);
|
||||
|
||||
$cache = new Psr6Cache(new TraceableAdapter(new FilesystemAdapter()));
|
||||
|
||||
$widgets = new Widgets($requestStack, $queueProcessor, $twig, $cache);
|
||||
$widgets = $this->getWidgetsObject();
|
||||
|
||||
$response = new Response('<html><body>foo</body></html>');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user