mirror of
https://github.com/flarum/framework.git
synced 2025-02-18 22:12:50 +08:00
Initial refactor of client actions, data preloading, SEO
An initial stab at flarum/core#126. Still WIP. Preliminary implementation of flarum/core#128 and flarum/core#13.
This commit is contained in:
parent
fcc5aa17ea
commit
99876e9e36
|
@ -70,7 +70,7 @@ export default class AvatarEditor extends Component {
|
|||
m.redraw();
|
||||
m.request({
|
||||
method: 'POST',
|
||||
url: app.config['api_url']+'/users/'+user.id()+'/avatar',
|
||||
url: app.forum.attribute('apiUrl')+'/users/'+user.id()+'/avatar',
|
||||
data: data,
|
||||
serialize: data => data,
|
||||
background: true,
|
||||
|
@ -91,7 +91,7 @@ export default class AvatarEditor extends Component {
|
|||
m.redraw();
|
||||
m.request({
|
||||
method: 'DELETE',
|
||||
url: app.config['api_url']+'/users/'+user.id()+'/avatar',
|
||||
url: app.forum.attribute('apiUrl')+'/users/'+user.id()+'/avatar',
|
||||
config: app.session.authorize.bind(app.session)
|
||||
}).then(function(data) {
|
||||
self.loading(false);
|
||||
|
|
|
@ -20,7 +20,7 @@ export default class ChangePasswordModal extends FormModal {
|
|||
|
||||
m.request({
|
||||
method: 'POST',
|
||||
url: app.config['api_url']+'/forgot',
|
||||
url: app.forum.attribute('apiUrl')+'/forgot',
|
||||
data: {email: app.session.user().email()},
|
||||
background: true
|
||||
}).then(response => {
|
||||
|
|
|
@ -64,9 +64,9 @@ export default class DiscussionList extends Component {
|
|||
}
|
||||
|
||||
loadResults(offset) {
|
||||
if (app.preload.response) {
|
||||
var discussions = app.store.pushPayload(app.preload.response);
|
||||
app.preload.response = null;
|
||||
const discussions = app.preloadedDocument();
|
||||
|
||||
if (discussions) {
|
||||
return m.deferred().resolve(discussions).promise;
|
||||
} else {
|
||||
var params = this.params();
|
||||
|
|
|
@ -43,17 +43,13 @@ export default class DiscussionPage extends mixin(Component, evented) {
|
|||
var params = this.params();
|
||||
params.include = params.include.join(',');
|
||||
|
||||
var discussion;
|
||||
if (app.preload.response) {
|
||||
const discussion = app.preloadedDocument();
|
||||
if (discussion) {
|
||||
// We must wrap this in a setTimeout because if we are mounting this
|
||||
// component for the first time on page load, then any calls to m.redraw
|
||||
// will be ineffective and thus any configs (scroll code) will be run
|
||||
// before stuff is drawn to the page.
|
||||
setTimeout(() => {
|
||||
var discussion = app.store.pushPayload(app.preload.response);
|
||||
app.preload.response = null;
|
||||
this.setupDiscussion(discussion);
|
||||
});
|
||||
setTimeout(this.setupDiscussion.bind(this, discussion));
|
||||
} else {
|
||||
app.store.find('discussions', m.route.param('id'), params).then(this.setupDiscussion.bind(this));
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ export default class ForgotPasswordModal extends FormModal {
|
|||
|
||||
m.request({
|
||||
method: 'POST',
|
||||
url: app.config['api_url']+'/forgot',
|
||||
url: app.forum.attribute('apiUrl')+'/forgot',
|
||||
data: {email: this.email()},
|
||||
background: true,
|
||||
extract: xhr => {
|
||||
|
|
|
@ -61,7 +61,7 @@ export default class NotificationList extends Component {
|
|||
badges && badges.length ? m('ul.badges', listItems(badges)) : '',
|
||||
group.discussion.title()
|
||||
)
|
||||
: m('div.notification-group-header', app.config['forum_title']),
|
||||
: m('div.notification-group-header', app.forum.attribute('title')),
|
||||
m('ul.notification-group-list', group.notifications.map(notification => {
|
||||
var NotificationComponent = app.notificationComponentRegistry[notification.contentType()];
|
||||
return NotificationComponent ? m('li', NotificationComponent.component({notification})) : '';
|
||||
|
|
|
@ -45,7 +45,7 @@ export default class UserDropdown extends Component {
|
|||
ActionButton.component({
|
||||
icon: 'wrench',
|
||||
label: 'Administration',
|
||||
href: app.config['base_url']+'/admin'
|
||||
href: app.forum.attribute('baseUrl')+'/admin'
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@ export default class WelcomeHero extends Component {
|
|||
m('div.container', [
|
||||
m('button.close.btn.btn-icon.btn-link', {onclick: () => this.$().slideUp(this.hide.bind(this))}, m('i.fa.fa-times')),
|
||||
m('div.container-narrow', [
|
||||
m('h2', app.config['welcome_title']),
|
||||
m('div.subtitle', m.trust(app.config['welcome_message']))
|
||||
m('h2', app.forum.attribute('welcomeTitle')),
|
||||
m('div.subtitle', m.trust(app.forum.attribute('welcomeMessage')))
|
||||
])
|
||||
])
|
||||
])
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
export default function(app) {
|
||||
if (app.preload.data) {
|
||||
app.store.pushPayload({data: app.preload.data});
|
||||
}
|
||||
app.store.pushPayload({data: app.preload.data});
|
||||
app.forum = app.store.getById('forums', 1);
|
||||
|
||||
if (app.preload.session) {
|
||||
app.session.token(app.preload.session.token);
|
||||
app.session.user(app.store.getById('users', app.preload.session.userId));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Store from 'flarum/store';
|
||||
import Forum from 'flarum/models/forum';
|
||||
import User from 'flarum/models/user';
|
||||
import Discussion from 'flarum/models/discussion';
|
||||
import Post from 'flarum/models/post';
|
||||
|
@ -9,10 +10,13 @@ import Notification from 'flarum/models/notification';
|
|||
export default function(app) {
|
||||
app.store = new Store();
|
||||
|
||||
app.store.models['users'] = User;
|
||||
app.store.models['discussions'] = Discussion;
|
||||
app.store.models['posts'] = Post;
|
||||
app.store.models['groups'] = Group;
|
||||
app.store.models['activity'] = Activity;
|
||||
app.store.models['notifications'] = Notification;
|
||||
};
|
||||
app.store.models = {
|
||||
forums: Forum,
|
||||
users: User,
|
||||
discussions: Discussion,
|
||||
posts: Post,
|
||||
groups: Group,
|
||||
activity: Activity,
|
||||
notifications: Notification
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,6 +10,10 @@ export default class Model {
|
|||
return this.data().id;
|
||||
}
|
||||
|
||||
attribute(attribute) {
|
||||
return this.data().attributes[attribute];
|
||||
}
|
||||
|
||||
pushData(newData) {
|
||||
var data = this.data();
|
||||
|
||||
|
@ -90,7 +94,7 @@ export default class Model {
|
|||
|
||||
return app.request({
|
||||
method: this.exists ? 'PATCH' : 'POST',
|
||||
url: app.config['api_url']+'/'+this.data().type+(this.exists ? '/'+this.data().id : ''),
|
||||
url: app.forum.attribute('apiUrl')+'/'+this.data().type+(this.exists ? '/'+this.data().id : ''),
|
||||
data: {data},
|
||||
background: true,
|
||||
config: app.session.authorize.bind(app.session)
|
||||
|
@ -108,7 +112,7 @@ export default class Model {
|
|||
|
||||
return app.request({
|
||||
method: 'DELETE',
|
||||
url: app.config['api_url']+'/'+this.data().type+'/'+this.data().id,
|
||||
url: app.forum.attribute('apiUrl')+'/'+this.data().type+'/'+this.data().id,
|
||||
background: true,
|
||||
config: app.session.authorize.bind(app.session)
|
||||
}).then(() => this.exists = false);
|
||||
|
|
5
js/lib/models/forum.js
Normal file
5
js/lib/models/forum.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import Model from 'flarum/model';
|
||||
|
||||
class Forum extends Model {}
|
||||
|
||||
export default Forum;
|
|
@ -13,7 +13,7 @@ export default class Session extends mixin(class {}, evented) {
|
|||
var self = this;
|
||||
m.request({
|
||||
method: 'POST',
|
||||
url: app.config['base_url']+'/login',
|
||||
url: app.forum.attribute('baseUrl')+'/login',
|
||||
data: {identification, password},
|
||||
background: true
|
||||
}).then(function(response) {
|
||||
|
@ -32,7 +32,7 @@ export default class Session extends mixin(class {}, evented) {
|
|||
}
|
||||
|
||||
logout() {
|
||||
window.location = app.config['base_url']+'/logout';
|
||||
window.location = app.forum.attribute('baseUrl')+'/logout?token='+this.token();
|
||||
}
|
||||
|
||||
authorize(xhr) {
|
||||
|
|
|
@ -38,7 +38,7 @@ export default class Store {
|
|||
}
|
||||
return app.request({
|
||||
method: 'GET',
|
||||
url: app.config['api_url']+'/'+endpoint,
|
||||
url: app.forum.attribute('apiUrl')+'/'+endpoint,
|
||||
data: params,
|
||||
background: true,
|
||||
config: app.session.authorize.bind(app.session)
|
||||
|
|
|
@ -15,8 +15,17 @@ class App {
|
|||
this.initializers.toArray().forEach((initializer) => initializer(this));
|
||||
}
|
||||
|
||||
preloadedDocument() {
|
||||
if (app.preload.document) {
|
||||
const results = app.store.pushPayload(app.preload.document);
|
||||
app.preload.document = null;
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
setTitle(title) {
|
||||
document.title = (title ? title+' - ' : '')+this.config['forum_title'];
|
||||
document.title = (title ? title+' - ' : '')+this.forum.attribute('title');
|
||||
}
|
||||
|
||||
request(options) {
|
||||
|
|
|
@ -33,6 +33,6 @@ class Client
|
|||
|
||||
$response = $action->handle(new Request($input, $actor));
|
||||
|
||||
return json_decode($response->getBody());
|
||||
return new Response($response);
|
||||
}
|
||||
}
|
||||
|
|
16
src/Api/Response.php
Normal file
16
src/Api/Response.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php namespace Flarum\Api;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class Response
|
||||
{
|
||||
public function __construct(ResponseInterface $response)
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
public function getBody()
|
||||
{
|
||||
return json_decode($this->response->getBody());
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
<?php namespace Flarum\Api\Serializers;
|
||||
|
||||
use Flarum\Core;
|
||||
|
||||
class ForumSerializer extends Serializer
|
||||
{
|
||||
/**
|
||||
|
@ -21,7 +23,12 @@ class ForumSerializer extends Serializer
|
|||
protected function getDefaultAttributes($forum)
|
||||
{
|
||||
return [
|
||||
'title' => $forum->title
|
||||
'title' => $forum->title,
|
||||
'baseUrl' => Core::config('base_url'),
|
||||
'apiUrl' => Core::config('api_url'),
|
||||
'welcomeTitle' => Core::config('welcome_title'),
|
||||
'welcomeMessage' => Core::config('welcome_message'),
|
||||
'themePrimaryColor' => Core::config('theme_primary_color')
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
134
src/Forum/Actions/ClientAction.php
Normal file
134
src/Forum/Actions/ClientAction.php
Normal file
|
@ -0,0 +1,134 @@
|
|||
<?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\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
|
||||
{
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
protected $apiClient;
|
||||
|
||||
protected $locales;
|
||||
|
||||
/**
|
||||
* @param Client $apiClient
|
||||
* @param LocaleManager $locales
|
||||
*/
|
||||
public function __construct(Client $apiClient, LocaleManager $locales)
|
||||
{
|
||||
$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;
|
||||
// }
|
||||
}
|
|
@ -2,19 +2,25 @@
|
|||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class DiscussionAction extends IndexAction
|
||||
class DiscussionAction extends ClientAction
|
||||
{
|
||||
protected function getDetails(Request $request, array $routeParams)
|
||||
public function render(Request $request, array $routeParams = [])
|
||||
{
|
||||
$response = $this->apiClient->send(app('flarum.actor'), 'Flarum\Api\Actions\Discussions\ShowAction', [
|
||||
$view = parent::render($request, $routeParams);
|
||||
|
||||
$actor = app('flarum.actor');
|
||||
$action = 'Flarum\Api\Actions\Discussions\ShowAction';
|
||||
$params = [
|
||||
'id' => $routeParams['id'],
|
||||
'page.near' => $routeParams['near']
|
||||
]);
|
||||
|
||||
// TODO: return an object instead of an array?
|
||||
return [
|
||||
'title' => $response->data->attributes->title,
|
||||
'response' => $response
|
||||
];
|
||||
|
||||
$document = $this->apiClient->send($actor, $action, $params)->getBody();
|
||||
|
||||
$view->setTitle($document->data->attributes->title);
|
||||
$view->setDocument($document);
|
||||
$view->setContent(app('view')->make('flarum.forum::discussion', compact('document')));
|
||||
|
||||
return $view;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,33 +11,8 @@ use Flarum\Support\HtmlAction;
|
|||
use Illuminate\Database\ConnectionInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class IndexAction extends HtmlAction
|
||||
class IndexAction extends ClientAction
|
||||
{
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
protected $apiClient;
|
||||
|
||||
/**
|
||||
* @var ConnectionInterface
|
||||
*/
|
||||
protected $database;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public static $translations = [];
|
||||
|
||||
/**
|
||||
* @param Client $apiClient
|
||||
* @param ConnectionInterface $database
|
||||
*/
|
||||
public function __construct(Client $apiClient, ConnectionInterface $database)
|
||||
{
|
||||
$this->apiClient = $apiClient;
|
||||
$this->database = $database;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param array $routeParams
|
||||
|
@ -45,135 +20,22 @@ class IndexAction extends HtmlAction
|
|||
*/
|
||||
public function render(Request $request, array $routeParams = [])
|
||||
{
|
||||
$config = $this->database->table('config')
|
||||
->whereIn('key', ['base_url', 'api_url', 'forum_title', 'welcome_title', 'welcome_message', 'theme_primary_color'])
|
||||
->lists('value', 'key');
|
||||
$session = [];
|
||||
$view = parent::render($request, $routeParams);
|
||||
|
||||
$actor = app('flarum.actor');
|
||||
|
||||
$response = $this->apiClient->send($actor, 'Flarum\Api\Actions\Forum\ShowAction');
|
||||
|
||||
$data = [$response->data];
|
||||
if (isset($response->included)) {
|
||||
$data = array_merge($data, $response->included);
|
||||
}
|
||||
|
||||
if ($actor->exists) {
|
||||
$session = [
|
||||
'userId' => $actor->id,
|
||||
'token' => $request->getCookieParams()['flarum_remember'],
|
||||
];
|
||||
|
||||
// TODO: calling on the API here results in an extra query to get
|
||||
// the user + their groups, when we already have this information on
|
||||
// $this->actor. Can we simply run the CurrentUserSerializer
|
||||
// manually?
|
||||
$response = $this->apiClient->send($actor, 'Flarum\Api\Actions\Users\ShowAction', ['id' => $actor->id]);
|
||||
|
||||
$data[] = $response->data;
|
||||
if (isset($response->included)) {
|
||||
$data = array_merge($data, $response->included);
|
||||
}
|
||||
}
|
||||
|
||||
$details = $this->getDetails($request, $routeParams);
|
||||
|
||||
$data = array_merge($data, array_get($details, 'data', []));
|
||||
$response = array_get($details, 'response');
|
||||
$title = array_get($details, 'title');
|
||||
|
||||
$view = view('flarum.forum::index')
|
||||
->with('title', ($title ? $title.' - ' : '').Core::config('forum_title'))
|
||||
->with('config', $config)
|
||||
->with('layout', 'flarum.forum::forum')
|
||||
->with('data', $data)
|
||||
->with('response', $response)
|
||||
->with('session', $session);
|
||||
|
||||
$root = __DIR__.'/../../..';
|
||||
$public = public_path().'/assets';
|
||||
|
||||
$assets = new AssetManager(
|
||||
new JsCompiler($public, 'forum.js'),
|
||||
new LessCompiler($public, 'forum.css')
|
||||
);
|
||||
|
||||
$assets->addFile($root.'/js/forum/dist/app.js');
|
||||
$assets->addFile($root.'/less/forum/app.less');
|
||||
|
||||
$variables = [
|
||||
'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'
|
||||
];
|
||||
foreach ($variables as $name => $value) {
|
||||
$assets->addLess("@$name: $value;");
|
||||
}
|
||||
|
||||
$locale = $actor->locale ?: Core::config('locale', 'en');
|
||||
|
||||
$localeManager = app('flarum.localeManager');
|
||||
$translations = $localeManager->getTranslations($locale);
|
||||
$jsFiles = $localeManager->getJsFiles($locale);
|
||||
|
||||
$localeCompiler = new LocaleJsCompiler($public, 'locale-'.$locale.'.js');
|
||||
$localeCompiler->setTranslations(static::filterTranslations($translations));
|
||||
array_walk($jsFiles, [$localeCompiler, 'addFile']);
|
||||
|
||||
event(new RenderView($view, $assets, $this));
|
||||
|
||||
return $view
|
||||
->with('styles', [$assets->getCssFile()])
|
||||
->with('scripts', [$assets->getJsFile(), $localeCompiler->getFile()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param array $routeParams
|
||||
* @return array
|
||||
*/
|
||||
protected function getDetails(Request $request, array $routeParams)
|
||||
{
|
||||
$queryParams = $request->getQueryParams();
|
||||
|
||||
// Only preload data if we're viewing the default index with no filters,
|
||||
// otherwise we have to do all kinds of crazy stuff
|
||||
if (!count($queryParams) && $request->getUri()->getPath() === '/') {
|
||||
$response = $this->apiClient->send(app('flarum.actor'), 'Flarum\Api\Actions\Discussions\IndexAction');
|
||||
if (! count($queryParams) && $request->getUri()->getPath() === '/') {
|
||||
$actor = app('flarum.actor');
|
||||
$action = 'Flarum\Api\Actions\Discussions\IndexAction';
|
||||
|
||||
return [
|
||||
'response' => $response
|
||||
];
|
||||
$document = $this->apiClient->send($actor, $action)->getBody();
|
||||
|
||||
$view->setDocument($document);
|
||||
$view->setContent(app('view')->make('flarum.forum::index', compact('document')));
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $translations
|
||||
* @return array
|
||||
*/
|
||||
protected static function filterTranslations($translations)
|
||||
{
|
||||
$filtered = [];
|
||||
|
||||
foreach (static::$translations as $key) {
|
||||
$parts = explode('.', $key);
|
||||
$level = &$filtered;
|
||||
|
||||
foreach ($parts as $part) {
|
||||
if (! isset($level[$part])) {
|
||||
$level[$part] = [];
|
||||
}
|
||||
|
||||
$level = &$level[$part];
|
||||
}
|
||||
|
||||
$level = array_get($translations, $key);
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
return $view;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,19 +58,13 @@ class ForumServiceProvider extends ServiceProvider
|
|||
);
|
||||
|
||||
$routes->get(
|
||||
'/d/{id:\d+}/{slug}',
|
||||
'/d/{id:\d+}/{slug}[/{near}]',
|
||||
'flarum.forum.discussion',
|
||||
$this->action('Flarum\Forum\Actions\DiscussionAction')
|
||||
);
|
||||
|
||||
$routes->get(
|
||||
'/d/{id:\d+}/{slug}/{near}',
|
||||
'flarum.forum.discussion.near',
|
||||
$this->action('Flarum\Forum\Actions\DiscussionAction')
|
||||
);
|
||||
|
||||
$routes->get(
|
||||
'/u/{username}',
|
||||
'/u/{username}[/{filter}]',
|
||||
'flarum.forum.user',
|
||||
$this->action('Flarum\Forum\Actions\IndexAction')
|
||||
);
|
||||
|
|
130
src/Support/ClientView.php
Normal file
130
src/Support/ClientView.php
Normal file
|
@ -0,0 +1,130 @@
|
|||
<?php namespace Flarum\Support;
|
||||
|
||||
use Flarum\Api\Client;
|
||||
use Flarum\Assets\AssetManager;
|
||||
use Flarum\Core\Users\User;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Flarum\Locale\JsCompiler;
|
||||
|
||||
class ClientView
|
||||
{
|
||||
protected $actor;
|
||||
|
||||
protected $apiClient;
|
||||
|
||||
protected $title;
|
||||
|
||||
protected $document;
|
||||
|
||||
protected $content;
|
||||
|
||||
protected $request;
|
||||
|
||||
protected $layout;
|
||||
|
||||
public function __construct(
|
||||
Request $request,
|
||||
User $actor,
|
||||
Client $apiClient,
|
||||
$layout,
|
||||
AssetManager $assets,
|
||||
JsCompiler $locale
|
||||
) {
|
||||
$this->request = $request;
|
||||
$this->actor = $actor;
|
||||
$this->apiClient = $apiClient;
|
||||
$this->layout = $layout;
|
||||
$this->assets = $assets;
|
||||
$this->locale = $locale;
|
||||
}
|
||||
|
||||
public function setActor(User $actor)
|
||||
{
|
||||
$this->actor = $actor;
|
||||
}
|
||||
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
public function setDocument($document)
|
||||
{
|
||||
$this->document = $document;
|
||||
}
|
||||
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$view = app('view')->file(__DIR__.'/../../views/app.blade.php');
|
||||
|
||||
$forum = $this->getForumDocument();
|
||||
$data = $this->getDataFromDocument($forum);
|
||||
|
||||
if ($this->actor->exists) {
|
||||
$user = $this->getUserDocument();
|
||||
$data = array_merge($data, $this->getDataFromDocument($user));
|
||||
}
|
||||
|
||||
$view->data = $data;
|
||||
$view->session = $this->getSession();
|
||||
$view->title = ($this->title ? $this->title . ' - ' : '') . $forum->data->attributes->title;
|
||||
$view->document = $this->document;
|
||||
$view->forum = $forum->data;
|
||||
$view->layout = $this->layout;
|
||||
$view->content = $this->content;
|
||||
|
||||
$view->styles = [$this->assets->getCssFile()];
|
||||
$view->scripts = [$this->assets->getJsFile(), $this->locale->getFile()];
|
||||
|
||||
return $view->render();
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->render();
|
||||
}
|
||||
|
||||
protected function getForumDocument()
|
||||
{
|
||||
return $this->apiClient->send($this->actor, 'Flarum\Api\Actions\Forum\ShowAction')->getBody();
|
||||
}
|
||||
|
||||
protected function getUserDocument()
|
||||
{
|
||||
// TODO: calling on the API here results in an extra query to get
|
||||
// the user + their groups, when we already have this information on
|
||||
// $this->actor. Can we simply run the CurrentUserSerializer
|
||||
// manually?
|
||||
$document = $this->apiClient->send(
|
||||
$this->actor,
|
||||
'Flarum\Api\Actions\Users\ShowAction',
|
||||
['id' => $this->actor->id]
|
||||
)->getBody();
|
||||
|
||||
return $document;
|
||||
}
|
||||
|
||||
protected function getDataFromDocument($document)
|
||||
{
|
||||
$data[] = $document->data;
|
||||
|
||||
if (isset($document->included)) {
|
||||
$data = array_merge($data, $document->included);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getSession()
|
||||
{
|
||||
return [
|
||||
'userId' => $this->actor->id,
|
||||
'token' => $this->request->getCookieParams()['flarum_remember'],
|
||||
];
|
||||
}
|
||||
}
|
41
views/app.blade.php
Normal file
41
views/app.blade.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>{{ $title }}</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
|
||||
<meta name="theme-color" content="{{ $forum->attributes->themePrimaryColor }}">
|
||||
|
||||
@foreach ($styles as $file)
|
||||
<link rel="stylesheet" href="{{ str_replace(public_path(), '', $file) }}">
|
||||
@endforeach
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@include($layout)
|
||||
|
||||
<div id="modal"></div>
|
||||
<div id="alerts"></div>
|
||||
|
||||
@foreach ($scripts as $file)
|
||||
<script src="{{ str_replace(public_path(), '', $file) }}"></script>
|
||||
@endforeach
|
||||
<script>
|
||||
var app = require('flarum/app')['default'];
|
||||
app.preload = {
|
||||
data: {!! json_encode($data) !!},
|
||||
document: {!! json_encode($document) !!},
|
||||
session: {!! json_encode($session) !!}
|
||||
};
|
||||
app.boot();
|
||||
</script>
|
||||
|
||||
@if ($content)
|
||||
<noscript>
|
||||
{!! $content !!}
|
||||
</noscript>
|
||||
@endif
|
||||
</body>
|
||||
</html>
|
1
views/discussion.blade.php
Normal file
1
views/discussion.blade.php
Normal file
|
@ -0,0 +1 @@
|
|||
discussion SEO content
|
|
@ -4,7 +4,7 @@
|
|||
<header class="global-header" id="header">
|
||||
<div id="back-button"></div>
|
||||
<div class="container">
|
||||
<h1 class="header-title"><a href="{{ $config['base_url'] }}" id="home-link">{{ $config['forum_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-secondary" class="header-secondary"></div>
|
||||
</div>
|
||||
|
|
|
@ -1,38 +1 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>{{ $title }}</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
|
||||
|
||||
<!-- Theme color for Android phones -->
|
||||
<meta name="theme-color" content="{{ $config['theme_primary_color'] }}">
|
||||
|
||||
@foreach ($styles as $file)
|
||||
<link rel="stylesheet" href="{{ str_replace(public_path(), '', $file) }}">
|
||||
@endforeach
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@include($layout)
|
||||
|
||||
<div id="modal"></div>
|
||||
<div id="alerts"></div>
|
||||
|
||||
@foreach ($scripts as $file)
|
||||
<script src="{{ str_replace(public_path(), '', $file) }}"></script>
|
||||
@endforeach
|
||||
<script>
|
||||
var app = require('flarum/app')['default'];
|
||||
app.config = {!! json_encode($config) !!};
|
||||
app.preload = {
|
||||
data: {!! json_encode($data) !!},
|
||||
response: {!! json_encode($response) !!},
|
||||
session: {!! json_encode($session) !!}
|
||||
};
|
||||
app.boot();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
index SEO content
|
||||
|
|
Loading…
Reference in New Issue
Block a user