mirror of
https://github.com/flarum/framework.git
synced 2024-11-27 19:13:37 +08:00
Finish client action refactoring. closes flarum/core#126
This commit is contained in:
parent
8a54b362c7
commit
38c2ff0306
|
@ -1,5 +1,6 @@
|
||||||
<?php namespace Flarum\Core\Users;
|
<?php namespace Flarum\Core\Users;
|
||||||
|
|
||||||
|
use Flarum\Core;
|
||||||
use Flarum\Core\Groups\Group;
|
use Flarum\Core\Groups\Group;
|
||||||
use Flarum\Core\Model;
|
use Flarum\Core\Model;
|
||||||
use Flarum\Core\Notifications\Notification;
|
use Flarum\Core\Notifications\Notification;
|
||||||
|
@ -282,7 +283,21 @@ class User extends Model
|
||||||
*/
|
*/
|
||||||
public function getAvatarUrlAttribute()
|
public function getAvatarUrlAttribute()
|
||||||
{
|
{
|
||||||
return $this->avatar_path ? app('Flarum\Http\UrlGeneratorInterface')->toAsset('assets/avatars/'.$this->avatar_path) : null;
|
$urlGenerator = app('Flarum\Http\UrlGeneratorInterface');
|
||||||
|
|
||||||
|
return $this->avatar_path ? $urlGenerator->toAsset('assets/avatars/'.$this->avatar_path) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the user's locale, falling back to the forum's default if they
|
||||||
|
* haven't set one.
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLocaleAttribute($value)
|
||||||
|
{
|
||||||
|
return $value ?: Core::config('locale', 'en');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,134 +1,16 @@
|
||||||
<?php namespace Flarum\Forum\Actions;
|
<?php namespace Flarum\Forum\Actions;
|
||||||
|
|
||||||
use Flarum\Api\Client;
|
use Flarum\Support\ClientAction as BaseClientAction;
|
||||||
use Flarum\Assets\AssetManager;
|
|
||||||
use Flarum\Assets\JsCompiler;
|
|
||||||
use Flarum\Assets\LessCompiler;
|
|
||||||
use Flarum\Core;
|
|
||||||
use Flarum\Core\Users\User;
|
|
||||||
use Flarum\Forum\Events\RenderView;
|
|
||||||
use Flarum\Locale\JsCompiler as LocaleJsCompiler;
|
|
||||||
use Flarum\Locale\LocaleManager;
|
|
||||||
use Flarum\Support\ClientView;
|
|
||||||
use Flarum\Support\HtmlAction;
|
|
||||||
use Illuminate\Database\ConnectionInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
|
||||||
|
|
||||||
abstract class ClientAction extends HtmlAction
|
abstract class ClientAction extends BaseClientAction
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var Client
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
protected $apiClient;
|
protected $clientName = 'forum';
|
||||||
|
|
||||||
protected $locales;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Client $apiClient
|
* {@inheritdoc}
|
||||||
* @param LocaleManager $locales
|
|
||||||
*/
|
*/
|
||||||
public function __construct(Client $apiClient, LocaleManager $locales)
|
protected $layout = 'flarum.forum::forum';
|
||||||
{
|
|
||||||
$this->apiClient = $apiClient;
|
|
||||||
$this->locales = $locales;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @param array $routeParams
|
|
||||||
* @return \Flarum\Support\ClientView
|
|
||||||
*/
|
|
||||||
public function render(Request $request, array $routeParams = [])
|
|
||||||
{
|
|
||||||
$actor = app('flarum.actor');
|
|
||||||
|
|
||||||
$assets = $this->getAssets();
|
|
||||||
$locale = $this->getLocaleCompiler($actor);
|
|
||||||
|
|
||||||
$layout = 'flarum.forum::forum';
|
|
||||||
|
|
||||||
$view = new ClientView(
|
|
||||||
$request,
|
|
||||||
$actor,
|
|
||||||
$this->apiClient,
|
|
||||||
$layout,
|
|
||||||
$assets,
|
|
||||||
$locale
|
|
||||||
);
|
|
||||||
|
|
||||||
return $view;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getAssets()
|
|
||||||
{
|
|
||||||
$public = $this->getAssetDirectory();
|
|
||||||
|
|
||||||
$assets = new AssetManager(
|
|
||||||
new JsCompiler($public, 'forum.js'),
|
|
||||||
new LessCompiler($public, 'forum.css')
|
|
||||||
);
|
|
||||||
|
|
||||||
$root = __DIR__.'/../../..';
|
|
||||||
$assets->addFile($root.'/js/forum/dist/app.js');
|
|
||||||
$assets->addFile($root.'/less/forum/app.less');
|
|
||||||
|
|
||||||
foreach ($this->getLessVariables() as $name => $value) {
|
|
||||||
$assets->addLess("@$name: $value;");
|
|
||||||
}
|
|
||||||
|
|
||||||
$assets->addLess(Core::config('custom_less'));
|
|
||||||
|
|
||||||
return $assets;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getLessVariables()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'fl-primary-color' => Core::config('theme_primary_color', '#000'),
|
|
||||||
'fl-secondary-color' => Core::config('theme_secondary_color', '#000'),
|
|
||||||
'fl-dark-mode' => Core::config('theme_dark_mode') ? 'true' : 'false',
|
|
||||||
'fl-colored-header' => Core::config('theme_colored_header') ? 'true' : 'false'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getLocaleCompiler(User $actor)
|
|
||||||
{
|
|
||||||
$locale = $actor->locale ?: Core::config('locale', 'en');
|
|
||||||
|
|
||||||
// $translations = $this->locales->getTranslations($locale);
|
|
||||||
$jsFiles = $this->locales->getJsFiles($locale);
|
|
||||||
|
|
||||||
$compiler = new LocaleJsCompiler($this->getAssetDirectory(), 'locale-'.$locale.'.js');
|
|
||||||
// $compiler->setTranslations(static::filterTranslations($translations));
|
|
||||||
array_walk($jsFiles, [$compiler, 'addFile']);
|
|
||||||
|
|
||||||
return $compiler;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getAssetDirectory()
|
|
||||||
{
|
|
||||||
return public_path().'/assets';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $translations
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
// protected static function filterTranslations($translations)
|
|
||||||
// {
|
|
||||||
// $filtered = [];
|
|
||||||
//
|
|
||||||
// foreach (static::$translations as $key) {
|
|
||||||
// $parts = explode('.', $key);
|
|
||||||
// $level = &$filtered;
|
|
||||||
//
|
|
||||||
// foreach ($parts as $part) {
|
|
||||||
// $level = &$level[$part];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// $level = array_get($translations, $key);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return $filtered;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,18 +4,21 @@ use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
|
|
||||||
class DiscussionAction extends ClientAction
|
class DiscussionAction extends ClientAction
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function render(Request $request, array $routeParams = [])
|
public function render(Request $request, array $routeParams = [])
|
||||||
{
|
{
|
||||||
$view = parent::render($request, $routeParams);
|
$view = parent::render($request, $routeParams);
|
||||||
|
|
||||||
$actor = app('flarum.actor');
|
|
||||||
$action = 'Flarum\Api\Actions\Discussions\ShowAction';
|
|
||||||
$params = [
|
$params = [
|
||||||
'id' => $routeParams['id'],
|
'id' => array_get($routeParams, 'id'),
|
||||||
'page.near' => $routeParams['near']
|
'page.near' => array_get($routeParams, 'near')
|
||||||
];
|
];
|
||||||
|
|
||||||
$document = $this->apiClient->send($actor, $action, $params)->getBody();
|
// FIXME: make sure this is extensible. 404s, pagination.
|
||||||
|
|
||||||
|
$document = $this->preload($params);
|
||||||
|
|
||||||
$view->setTitle($document->data->attributes->title);
|
$view->setTitle($document->data->attributes->title);
|
||||||
$view->setDocument($document);
|
$view->setDocument($document);
|
||||||
|
@ -23,4 +26,18 @@ class DiscussionAction extends ClientAction
|
||||||
|
|
||||||
return $view;
|
return $view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the result of an API request to show a discussion.
|
||||||
|
*
|
||||||
|
* @param array $params
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
|
protected function preload(array $params)
|
||||||
|
{
|
||||||
|
$actor = app('flarum.actor');
|
||||||
|
$action = 'Flarum\Api\Actions\Discussions\ShowAction';
|
||||||
|
|
||||||
|
return $this->apiClient->send($actor, $action, $params)->getBody();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
<?php namespace Flarum\Forum\Actions;
|
<?php namespace Flarum\Forum\Actions;
|
||||||
|
|
||||||
use Flarum\Api\Client;
|
|
||||||
use Flarum\Assets\AssetManager;
|
|
||||||
use Flarum\Assets\JsCompiler;
|
|
||||||
use Flarum\Assets\LessCompiler;
|
|
||||||
use Flarum\Core;
|
|
||||||
use Flarum\Forum\Events\RenderView;
|
|
||||||
use Flarum\Locale\JsCompiler as LocaleJsCompiler;
|
|
||||||
use Flarum\Support\HtmlAction;
|
|
||||||
use Illuminate\Database\ConnectionInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
|
|
||||||
class IndexAction extends ClientAction
|
class IndexAction extends ClientAction
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
* A map of sort query param values to their API sort param.
|
||||||
* @param array $routeParams
|
*
|
||||||
* @return \Illuminate\Contracts\View\View
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $sortMap = [
|
||||||
|
'recent' => '-lastTime',
|
||||||
|
'replies' => '-commentsCount',
|
||||||
|
'newest' => '-startTime',
|
||||||
|
'oldest' => '+startTime'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function render(Request $request, array $routeParams = [])
|
public function render(Request $request, array $routeParams = [])
|
||||||
{
|
{
|
||||||
|
@ -24,18 +25,35 @@ class IndexAction extends ClientAction
|
||||||
|
|
||||||
$queryParams = $request->getQueryParams();
|
$queryParams = $request->getQueryParams();
|
||||||
|
|
||||||
// Only preload data if we're viewing the default index with no filters,
|
$sort = array_pull($queryParams, 'sort');
|
||||||
// otherwise we have to do all kinds of crazy stuff
|
$q = array_pull($queryParams, 'q');
|
||||||
if (! count($queryParams) && $request->getUri()->getPath() === '/') {
|
|
||||||
$actor = app('flarum.actor');
|
|
||||||
$action = 'Flarum\Api\Actions\Discussions\IndexAction';
|
|
||||||
|
|
||||||
$document = $this->apiClient->send($actor, $action)->getBody();
|
$params = [
|
||||||
|
'sort' => $sort ? $this->sortMap[$sort] : '',
|
||||||
|
'q' => $q
|
||||||
|
];
|
||||||
|
|
||||||
$view->setDocument($document);
|
// FIXME: make sure this is extensible. Support pagination.
|
||||||
$view->setContent(app('view')->make('flarum.forum::index', compact('document')));
|
|
||||||
}
|
$document = $this->preload($params);
|
||||||
|
|
||||||
|
$view->setDocument($document);
|
||||||
|
$view->setContent(app('view')->make('flarum.forum::index', compact('document')));
|
||||||
|
|
||||||
return $view;
|
return $view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the result of an API request to list discussions.
|
||||||
|
*
|
||||||
|
* @param array $params
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
|
protected function preload(array $params)
|
||||||
|
{
|
||||||
|
$actor = app('flarum.actor');
|
||||||
|
$action = 'Flarum\Api\Actions\Discussions\IndexAction';
|
||||||
|
|
||||||
|
return $this->apiClient->send($actor, $action, $params)->getBody();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ class LocaleServiceProvider extends ServiceProvider
|
||||||
|
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
$this->app->singleton('flarum.localeManager', 'Flarum\Locale\LocaleManager');
|
$this->app->singleton('Flarum\Locale\LocaleManager');
|
||||||
|
|
||||||
|
$this->app->alias('Flarum\Locale\LocaleManager', 'flarum.localeManager');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
231
src/Support/ClientAction.php
Normal file
231
src/Support/ClientAction.php
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
<?php namespace Flarum\Support;
|
||||||
|
|
||||||
|
use Flarum\Api\Client;
|
||||||
|
use Flarum\Assets\AssetManager;
|
||||||
|
use Flarum\Assets\JsCompiler;
|
||||||
|
use Flarum\Assets\LessCompiler;
|
||||||
|
use Flarum\Core;
|
||||||
|
use Flarum\Core\Users\User;
|
||||||
|
use Flarum\Locale\JsCompiler as LocaleJsCompiler;
|
||||||
|
use Flarum\Locale\LocaleManager;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This action sets up a ClientView, and preloads it with the assets necessary
|
||||||
|
* to boot a Flarum client.
|
||||||
|
*
|
||||||
|
* Subclasses should set a $clientName, $layout, and $translationKeys. The
|
||||||
|
* client name will be used to locate the client assets (or alternatively,
|
||||||
|
* subclasses can overwrite the addAssets method), and set up asset compilers
|
||||||
|
* which write to the assets directory. Configured LESS customizations will be
|
||||||
|
* appended.
|
||||||
|
*
|
||||||
|
* A locale compiler is set up for the actor's locale, including the
|
||||||
|
* translations specified in $translationKeys. Additionally, an event is fired
|
||||||
|
* before the ClientView is returned, giving extensions an opportunity to add
|
||||||
|
* assets, translations, or alter the view.
|
||||||
|
*/
|
||||||
|
abstract class ClientAction extends HtmlAction
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name of the client. This is used to locate assets within the js/
|
||||||
|
* and less/ directories. It is also used as the filename of the compiled
|
||||||
|
* asset files.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $clientName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the view to include as the page layout.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $layout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The keys of the translations that should be included in the compiled
|
||||||
|
* locale file.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $translationKeys = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Client
|
||||||
|
*/
|
||||||
|
protected $apiClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var LocaleManager
|
||||||
|
*/
|
||||||
|
protected $locales;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Client $apiClient
|
||||||
|
* @param LocaleManager $locales
|
||||||
|
*/
|
||||||
|
public function __construct(Client $apiClient, LocaleManager $locales)
|
||||||
|
{
|
||||||
|
$this->apiClient = $apiClient;
|
||||||
|
$this->locales = $locales;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @return ClientView
|
||||||
|
*/
|
||||||
|
public function render(Request $request, array $routeParams = [])
|
||||||
|
{
|
||||||
|
$actor = app('flarum.actor');
|
||||||
|
$assets = $this->getAssets();
|
||||||
|
$locale = $this->getLocaleCompiler($actor);
|
||||||
|
|
||||||
|
$view = new ClientView(
|
||||||
|
$this->apiClient,
|
||||||
|
$request,
|
||||||
|
$actor,
|
||||||
|
$assets,
|
||||||
|
$locale,
|
||||||
|
$this->layout
|
||||||
|
);
|
||||||
|
|
||||||
|
// Now that we've set up the ClientView instance, we can fire an event
|
||||||
|
// to give extensions the opportunity to add their own assets and
|
||||||
|
// translations. We will pass an array to the event which specifies
|
||||||
|
// which translations should be included in the locale file. Afterwards,
|
||||||
|
// we will filter all of the translations for the actor's locale and
|
||||||
|
// compile only the ones we need.
|
||||||
|
$translations = $this->locales->getTranslations($actor->locale);
|
||||||
|
$keys = $this->translationKeys;
|
||||||
|
|
||||||
|
// TODO: event($this, $view, $keys)
|
||||||
|
|
||||||
|
$translations = $this->filterTranslations($translations, $keys);
|
||||||
|
|
||||||
|
$locale->setTranslations($translations);
|
||||||
|
|
||||||
|
return $view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the asset manager, preloaded with a JavaScript compiler and a LESS
|
||||||
|
* compiler. Automatically add the files necessary to boot a Flarum client,
|
||||||
|
* as well as any configured LESS customizations.
|
||||||
|
*
|
||||||
|
* @return AssetManager
|
||||||
|
*/
|
||||||
|
protected function getAssets()
|
||||||
|
{
|
||||||
|
$public = $this->getAssetDirectory();
|
||||||
|
|
||||||
|
$assets = new AssetManager(
|
||||||
|
new JsCompiler($public, "$this->clientName.js"),
|
||||||
|
new LessCompiler($public, "$this->clientName.css")
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->addAssets($assets);
|
||||||
|
$this->addCustomizations($assets);
|
||||||
|
|
||||||
|
return $assets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the assets necessary to boot a Flarum client, found within the
|
||||||
|
* directory specified by the $clientName property.
|
||||||
|
*
|
||||||
|
* @param AssetManager $assets
|
||||||
|
*/
|
||||||
|
protected function addAssets(AssetManager $assets)
|
||||||
|
{
|
||||||
|
$root = __DIR__.'/../..';
|
||||||
|
|
||||||
|
$assets->addFile("$root/js/$this->clientName/dist/app.js");
|
||||||
|
$assets->addFile("$root/less/$this->clientName/app.less");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add any configured JS/LESS customizations to the asset manager.
|
||||||
|
*
|
||||||
|
* @param AssetManager $assets
|
||||||
|
*/
|
||||||
|
protected function addCustomizations(AssetManager $assets)
|
||||||
|
{
|
||||||
|
foreach ($this->getLessVariables() as $name => $value) {
|
||||||
|
$assets->addLess("@$name: $value;");
|
||||||
|
}
|
||||||
|
|
||||||
|
$assets->addLess(Core::config('custom_less'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the values of any LESS variables to compile into the CSS, based on
|
||||||
|
* the forum's configuration.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getLessVariables()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'fl-primary-color' => Core::config('theme_primary_color', '#000'),
|
||||||
|
'fl-secondary-color' => Core::config('theme_secondary_color', '#000'),
|
||||||
|
'fl-dark-mode' => Core::config('theme_dark_mode') ? 'true' : 'false',
|
||||||
|
'fl-colored-header' => Core::config('theme_colored_header') ? 'true' : 'false'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the locale compiler for the given user's locale.
|
||||||
|
*
|
||||||
|
* @param User $actor
|
||||||
|
* @return LocaleJsCompiler
|
||||||
|
*/
|
||||||
|
protected function getLocaleCompiler(User $actor)
|
||||||
|
{
|
||||||
|
$locale = $actor->locale;
|
||||||
|
|
||||||
|
$compiler = new LocaleJsCompiler($this->getAssetDirectory(), "$this->clientName-$locale.js");
|
||||||
|
|
||||||
|
foreach ($this->locales->getJsFiles($locale) as $file) {
|
||||||
|
$compiler->addFile($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $compiler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path to the directory where assets should be written.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getAssetDirectory()
|
||||||
|
{
|
||||||
|
return public_path().'/assets';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take a selection of keys from a collection of translations.
|
||||||
|
*
|
||||||
|
* @param array $translations
|
||||||
|
* @param array $keys
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function filterTranslations(array $translations, array $keys)
|
||||||
|
{
|
||||||
|
$filtered = [];
|
||||||
|
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
$parts = explode('.', $key);
|
||||||
|
$level = &$filtered;
|
||||||
|
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
$level = &$level[$part];
|
||||||
|
}
|
||||||
|
|
||||||
|
$level = array_get($translations, $key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $filtered;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,61 +3,174 @@
|
||||||
use Flarum\Api\Client;
|
use Flarum\Api\Client;
|
||||||
use Flarum\Assets\AssetManager;
|
use Flarum\Assets\AssetManager;
|
||||||
use Flarum\Core\Users\User;
|
use Flarum\Core\Users\User;
|
||||||
|
use Illuminate\Contracts\Support\Renderable;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
use Flarum\Locale\JsCompiler;
|
use Flarum\Locale\JsCompiler;
|
||||||
|
|
||||||
class ClientView
|
/**
|
||||||
|
* This class represents a view which boots up Flarum's client.
|
||||||
|
*/
|
||||||
|
class ClientView implements Renderable
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The user who is using the client.
|
||||||
|
*
|
||||||
|
* @var User
|
||||||
|
*/
|
||||||
protected $actor;
|
protected $actor;
|
||||||
|
|
||||||
protected $apiClient;
|
/**
|
||||||
|
* The title of the document, displayed in the <title> tag.
|
||||||
|
*
|
||||||
|
* @var null|string
|
||||||
|
*/
|
||||||
protected $title;
|
protected $title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An API response that should be preloaded into the page.
|
||||||
|
*
|
||||||
|
* @var null|array|object
|
||||||
|
*/
|
||||||
protected $document;
|
protected $document;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SEO content of the page, displayed in <noscript> tags.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $content;
|
protected $content;
|
||||||
|
|
||||||
protected $request;
|
/**
|
||||||
|
* The name of the client layout view to display.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $layout;
|
protected $layout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of strings to append to the page's <head>.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $headStrings = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of strings to prepend before the page's </body>.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $footStrings = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Client
|
||||||
|
*/
|
||||||
|
protected $apiClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Request
|
||||||
|
*/
|
||||||
|
protected $request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var AssetManager
|
||||||
|
*/
|
||||||
|
protected $assets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var JsCompiler
|
||||||
|
*/
|
||||||
|
protected $locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Client $apiClient
|
||||||
|
* @param Request $request
|
||||||
|
* @param User $actor
|
||||||
|
* @param AssetManager $assets
|
||||||
|
* @param JsCompiler $locale
|
||||||
|
* @param string $layout
|
||||||
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
Client $apiClient,
|
||||||
Request $request,
|
Request $request,
|
||||||
User $actor,
|
User $actor,
|
||||||
Client $apiClient,
|
|
||||||
$layout,
|
|
||||||
AssetManager $assets,
|
AssetManager $assets,
|
||||||
JsCompiler $locale
|
JsCompiler $locale,
|
||||||
|
$layout
|
||||||
) {
|
) {
|
||||||
|
$this->apiClient = $apiClient;
|
||||||
$this->request = $request;
|
$this->request = $request;
|
||||||
$this->actor = $actor;
|
$this->actor = $actor;
|
||||||
$this->apiClient = $apiClient;
|
|
||||||
$this->layout = $layout;
|
|
||||||
$this->assets = $assets;
|
$this->assets = $assets;
|
||||||
$this->locale = $locale;
|
$this->locale = $locale;
|
||||||
|
$this->layout = $layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setActor(User $actor)
|
/**
|
||||||
{
|
* The title of the document, to be displayed in the <title> tag.
|
||||||
$this->actor = $actor;
|
*
|
||||||
}
|
* @param null|string $title
|
||||||
|
*/
|
||||||
public function setTitle($title)
|
public function setTitle($title)
|
||||||
{
|
{
|
||||||
$this->title = $title;
|
$this->title = $title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an API response to be preloaded into the page. This should be a
|
||||||
|
* JSON-API document.
|
||||||
|
*
|
||||||
|
* @param null|array|object $document
|
||||||
|
*/
|
||||||
public function setDocument($document)
|
public function setDocument($document)
|
||||||
{
|
{
|
||||||
$this->document = $document;
|
$this->document = $document;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the SEO content of the page, to be displayed in <noscript> tags.
|
||||||
|
*
|
||||||
|
* @param null|string $content
|
||||||
|
*/
|
||||||
public function setContent($content)
|
public function setContent($content)
|
||||||
{
|
{
|
||||||
$this->content = $content;
|
$this->content = $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a string to be appended to the page's <head>.
|
||||||
|
*
|
||||||
|
* @param string $string
|
||||||
|
*/
|
||||||
|
public function addHeadString($string)
|
||||||
|
{
|
||||||
|
$this->headStrings[] = $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a string to be prepended before the page's </body>.
|
||||||
|
*
|
||||||
|
* @param string $string
|
||||||
|
*/
|
||||||
|
public function addFootString($string)
|
||||||
|
{
|
||||||
|
$this->footStrings[] = $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the view's asset manager.
|
||||||
|
*
|
||||||
|
* @return AssetManager
|
||||||
|
*/
|
||||||
|
public function getAssets()
|
||||||
|
{
|
||||||
|
return $this->assets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the string contents of the view.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
$view = app('view')->file(__DIR__.'/../../views/app.blade.php');
|
$view = app('view')->file(__DIR__.'/../../views/app.blade.php');
|
||||||
|
@ -81,25 +194,43 @@ class ClientView
|
||||||
$view->styles = [$this->assets->getCssFile()];
|
$view->styles = [$this->assets->getCssFile()];
|
||||||
$view->scripts = [$this->assets->getJsFile(), $this->locale->getFile()];
|
$view->scripts = [$this->assets->getJsFile(), $this->locale->getFile()];
|
||||||
|
|
||||||
|
$view->head = implode("\n", $this->headStrings);
|
||||||
|
$view->foot = implode("\n", $this->footStrings);
|
||||||
|
|
||||||
return $view->render();
|
return $view->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the string contents of the view.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
return $this->render();
|
return $this->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the result of an API request to show the forum.
|
||||||
|
*
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
protected function getForumDocument()
|
protected function getForumDocument()
|
||||||
{
|
{
|
||||||
return $this->apiClient->send($this->actor, 'Flarum\Api\Actions\Forum\ShowAction')->getBody();
|
return $this->apiClient->send($this->actor, 'Flarum\Api\Actions\Forum\ShowAction')->getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the result of an API request to show the current user.
|
||||||
|
*
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
protected function getUserDocument()
|
protected function getUserDocument()
|
||||||
{
|
{
|
||||||
// TODO: calling on the API here results in an extra query to get
|
// TODO: calling on the API here results in an extra query to get
|
||||||
// the user + their groups, when we already have this information on
|
// the user + their groups, when we already have this information on
|
||||||
// $this->actor. Can we simply run the CurrentUserSerializer
|
// $this->actor. Can we simply run the CurrentUserSerializer
|
||||||
// manually?
|
// manually? Or can we somehow inject this data into the ShowAction?
|
||||||
$document = $this->apiClient->send(
|
$document = $this->apiClient->send(
|
||||||
$this->actor,
|
$this->actor,
|
||||||
'Flarum\Api\Actions\Users\ShowAction',
|
'Flarum\Api\Actions\Users\ShowAction',
|
||||||
|
@ -109,6 +240,13 @@ class ClientView
|
||||||
return $document;
|
return $document;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an array of data by merging the 'data' and 'included' keys of a
|
||||||
|
* JSON-API document.
|
||||||
|
*
|
||||||
|
* @param object $document
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
protected function getDataFromDocument($document)
|
protected function getDataFromDocument($document)
|
||||||
{
|
{
|
||||||
$data[] = $document->data;
|
$data[] = $document->data;
|
||||||
|
@ -120,11 +258,16 @@ class ClientView
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get information about the current session.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
protected function getSession()
|
protected function getSession()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'userId' => $this->actor->id,
|
'userId' => $this->actor->id,
|
||||||
'token' => $this->request->getCookieParams()['flarum_remember'],
|
'token' => array_get($this->request->getCookieParams(), 'flarum_remember'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
@foreach ($styles as $file)
|
@foreach ($styles as $file)
|
||||||
<link rel="stylesheet" href="{{ str_replace(public_path(), '', $file) }}">
|
<link rel="stylesheet" href="{{ str_replace(public_path(), '', $file) }}">
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
|
{!! $head !!}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -37,5 +39,7 @@
|
||||||
{!! $content !!}
|
{!! $content !!}
|
||||||
</noscript>
|
</noscript>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
{!! $foot !!}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,21 +1,56 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Forum Client Template
|
||||||
|
*
|
||||||
|
* NOTE: You shouldn't edit this file directly. Your changes will be overwritten
|
||||||
|
* when you update Flarum. See flarum.org/docs/templates to learn how to
|
||||||
|
* customize your forum's layout.
|
||||||
|
*
|
||||||
|
* Flarum's JavaScript client mounts various components into key elements in
|
||||||
|
* this template. They are distinguished by their ID attributes:
|
||||||
|
*
|
||||||
|
* - #page
|
||||||
|
* - #page-back-button
|
||||||
|
* - #header
|
||||||
|
* - #header-back-button
|
||||||
|
* - #home-link
|
||||||
|
* - #header-primary-controls
|
||||||
|
* - #header-secondary-controls
|
||||||
|
* - #footer
|
||||||
|
* - #footer-primary-controls
|
||||||
|
* - #footer-secondary-controls
|
||||||
|
* - #content
|
||||||
|
* - #composer
|
||||||
|
*/
|
||||||
|
?>
|
||||||
<div class="global-page" id="page">
|
<div class="global-page" id="page">
|
||||||
|
|
||||||
<div id="back-control"></div>
|
<div id="back-control"></div>
|
||||||
|
|
||||||
<div class="global-drawer">
|
<div class="global-drawer">
|
||||||
|
|
||||||
<header class="global-header" id="header">
|
<header class="global-header" id="header">
|
||||||
<div id="back-button"></div>
|
<div id="back-button"></div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 class="header-title"><a href="{{ $forum->attributes->baseUrl }}" id="home-link">{{ $forum->attributes->title }}</a></h1>
|
<h1 class="header-title">
|
||||||
|
<a href="{{ $forum->attributes->baseUrl }}" id="home-link">
|
||||||
|
{{ $forum->attributes->title }}
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
<div id="header-primary" class="header-primary"></div>
|
<div id="header-primary" class="header-primary"></div>
|
||||||
<div id="header-secondary" class="header-secondary"></div>
|
<div id="header-secondary" class="header-secondary"></div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<footer class="global-footer" id="footer">
|
<footer class="global-footer" id="footer">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div id="footer-primary" class="footer-primary"></div>
|
<div id="footer-primary" class="footer-primary"></div>
|
||||||
<div id="footer-secondary" class="footer-secondary"></div>
|
<div id="footer-secondary" class="footer-secondary"></div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main class="global-content">
|
<main class="global-content">
|
||||||
<div id="content"></div>
|
<div id="content"></div>
|
||||||
<div class="composer-container">
|
<div class="composer-container">
|
||||||
|
@ -24,4 +59,5 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user