Skip to content

Commit

Permalink
feat: frontend content flexible order priorities (#3765)
Browse files Browse the repository at this point in the history
* Fix frontend factory so it includes controller content
* chore: more readable parameter passing
* feat: add priorities to frontend content
  • Loading branch information
garygreen authored Oct 29, 2023
1 parent 577fc3e commit 7c885c7
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 22 deletions.
2 changes: 1 addition & 1 deletion framework/core/src/Admin/AdminServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public function register(): void
/** @var \Flarum\Frontend\Frontend $frontend */
$frontend = $container->make('flarum.frontend.factory')('admin');

$frontend->content($container->make(Content\AdminPayload::class));
$frontend->content($container->make(Content\AdminPayload::class), 100);

return $frontend;
});
Expand Down
9 changes: 5 additions & 4 deletions framework/core/src/Extend/Frontend.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,13 @@ public function removeRoute(string $name): self
* - \Psr\Http\Message\ServerRequestInterface $request
*
* The callable should return void.
* @param int $priority: The priority of the content. Higher priorities are executed first.
*
* @return self
*/
public function content(callable|string|null $callback): self
public function content(callable|string|null $callback, int $priority = 0): self
{
$this->content[] = $callback;
$this->content[] = compact('callback', 'priority');

return $this;
}
Expand Down Expand Up @@ -303,7 +304,7 @@ private function registerContent(Container $container): void
"flarum.frontend.$this->frontend",
function (ActualFrontend $frontend, Container $container) {
foreach ($this->content as $content) {
$frontend->content(ContainerUtil::wrapCallback($content, $container));
$frontend->content(ContainerUtil::wrapCallback($content['callback'], $container), $content['priority']);
}
}
);
Expand All @@ -323,7 +324,7 @@ function (ActualFrontend $frontend, Container $container) {
$preloads = is_callable($preloadArr) ? ContainerUtil::wrapCallback($preloadArr, $container)($document) : $preloadArr;
$document->preloads = array_merge($document->preloads, $preloads);
}
});
}, 110);
}
);
}
Expand Down
12 changes: 10 additions & 2 deletions framework/core/src/Forum/ForumServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Flarum\Frontend\AddTranslations;
use Flarum\Frontend\Assets;
use Flarum\Frontend\Compiler\Source\SourceCollector;
use Flarum\Frontend\Frontend;
use Flarum\Frontend\RecompileFrontendAssets;
use Flarum\Http\Middleware as HttpMiddleware;
use Flarum\Http\RouteCollection;
Expand Down Expand Up @@ -127,8 +128,15 @@ public function register(): void
return $assets;
});

$this->container->bind('flarum.frontend.forum', function (Container $container) {
return $container->make('flarum.frontend.factory')('forum');
$this->container->bind('flarum.frontend.forum', function (Container $container, array $parameters = []) {
/** @var Frontend $frontend */
$frontend = $container->make('flarum.frontend.factory')('forum');

if (isset($parameters['content'])) {
$frontend->content(is_callable($parameters['content']) ? $parameters['content'] : $container->make($parameters['content']), 100);
}

return $frontend;
});

$this->container->singleton('flarum.forum.discussions.sortmap', function () {
Expand Down
16 changes: 11 additions & 5 deletions framework/core/src/Frontend/Frontend.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
class Frontend
{
/**
* @var callable[]
* @var array<array{callback: callable, priority: int}>
*/
protected array $content = [];

Expand All @@ -27,9 +27,9 @@ public function __construct(
) {
}

public function content(callable $content): void
public function content(callable $callback, int $priority): void
{
$this->content[] = $content;
$this->content[] = compact('callback', 'priority');
}

public function document(Request $request): Document
Expand All @@ -45,8 +45,14 @@ public function document(Request $request): Document

protected function populate(Document $document, Request $request): void
{
foreach ($this->content as $content) {
$content($document, $request);
$content = $this->content;

usort($content, function ($a, $b) {
return $b['priority'] <=> $a['priority'];
});

foreach ($content as $item) {
$item['callback']($document, $request);
}
}

Expand Down
11 changes: 6 additions & 5 deletions framework/core/src/Frontend/FrontendServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,16 @@ public function register(): void

$this->container->singleton('flarum.frontend.factory', function (Container $container) {
return function (string $name) use ($container) {
/** @var Frontend $frontend */
$frontend = $container->make(Frontend::class);

$frontend->content(function (Document $document) use ($name) {
$document->layoutView = 'flarum::frontend.'.$name;
});
}, 200);

$frontend->content($container->make(Content\Assets::class)->forFrontend($name));
$frontend->content($container->make(Content\CorePayload::class));
$frontend->content($container->make(Content\Meta::class));
$frontend->content($container->make(Content\Assets::class)->forFrontend($name), 190);
$frontend->content($container->make(Content\CorePayload::class), 180);
$frontend->content($container->make(Content\Meta::class), 170);

$frontend->content(function (Document $document) use ($container) {
$default_preloads = $container->make('flarum.frontend.default_preloads');
Expand Down Expand Up @@ -90,7 +91,7 @@ public function register(): void
$default_preloads,
$document->preloads,
);
});
}, 160);

return $frontend;
};
Expand Down
6 changes: 1 addition & 5 deletions framework/core/src/Http/RouteHandlerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,7 @@ public function toController(callable|string $controller): Closure
public function toFrontend(string $frontend, callable|string|null $content = null): Closure
{
return $this->toController(function (Container $container) use ($frontend, $content) {
$frontend = $container->make("flarum.frontend.$frontend");

if ($content) {
$frontend->content(is_callable($content) ? $content : $container->make($content));
}
$frontend = $container->make("flarum.frontend.$frontend", compact('content'));

return new FrontendController($frontend);
});
Expand Down
89 changes: 89 additions & 0 deletions framework/core/tests/integration/extenders/FrontendContentTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/

namespace Flarum\Tests\integration\extenders;

use Flarum\Extend\Frontend;
use Flarum\Frontend\Document;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;

class FrontendContentTest extends TestCase
{
use RetrievesAuthorizedUsers;

/**
* @test
*/
public function content_added_with_low_priority_by_default()
{
$title = null;

$this->extend(
(new Frontend('forum'))
->content(function (Document $document) use (&$title) {
$title = $document->title;
}),
);

$body = $this->send(
$this->request('GET', '/')
)->getBody()->getContents();

$this->assertNotNull($title, $body);
}

/**
* @test
*/
public function content_can_be_added_with_high_priority()
{
$title = 1;

$this->extend(
(new Frontend('forum'))
->content(function (Document $document) use (&$title) {
$title = $document->title;
}, 110),
);

$body = $this->send(
$this->request('GET', '/')
)->getBody()->getContents();

$this->assertNull($title, $body);
}

/**
* @test
*/
public function contents_can_be_added_with_different_priorities()
{
$test = [];

$this->extend(
(new Frontend('forum'))
->content(function (Document $document) use (&$test) {
$test[] = 1;
}, 110)
->content(function (Document $document) use (&$test) {
$test[] = 3;
}, 90)
->content(function (Document $document) use (&$test) {
$test[] = 2;
}, 100),
);

$body = $this->send(
$this->request('GET', '/')
)->getBody()->getContents();

$this->assertEquals([1, 2, 3], $test, $body);
}
}

0 comments on commit 7c885c7

Please sign in to comment.