mirror of
https://github.com/flarum/core.git
synced 2025-08-16 13:24:11 +02:00
Add view & frontend documents for tags & tag discussion list (#64)
Refs flarum/core#1820. Fixes flarum/core#1134.
This commit is contained in:
committed by
Franz Liedke
parent
d403bedab3
commit
ebf8345dba
@@ -14,15 +14,17 @@ use Flarum\Discussion\Event\Saving;
|
||||
use Flarum\Extend;
|
||||
use Flarum\Tags\Access;
|
||||
use Flarum\Tags\Api\Controller;
|
||||
use Flarum\Tags\Content;
|
||||
use Flarum\Tags\Listener;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
|
||||
return [
|
||||
(new Extend\Frontend('forum'))
|
||||
->js(__DIR__.'/js/dist/forum.js')
|
||||
->css(__DIR__.'/less/forum.less')
|
||||
->route('/t/{slug}', 'tag')
|
||||
->route('/tags', 'tags'),
|
||||
->route('/t/{slug}', 'tag', Content\Tag::class)
|
||||
->route('/tags', 'tags', Content\Tags::class),
|
||||
|
||||
(new Extend\Frontend('admin'))
|
||||
->js(__DIR__.'/js/dist/admin.js')
|
||||
@@ -35,7 +37,7 @@ return [
|
||||
->patch('/tags/{id}', 'tags.update', Controller\UpdateTagController::class)
|
||||
->delete('/tags/{id}', 'tags.delete', Controller\DeleteTagController::class),
|
||||
|
||||
function (Dispatcher $events) {
|
||||
function (Dispatcher $events, Factory $view) {
|
||||
$events->subscribe(Listener\AddDiscussionTagsRelationship::class);
|
||||
|
||||
$events->subscribe(Listener\AddForumTagsRelationship::class);
|
||||
@@ -51,5 +53,7 @@ return [
|
||||
$events->subscribe(Access\DiscussionPolicy::class);
|
||||
$events->subscribe(Access\TagPolicy::class);
|
||||
$events->subscribe(Access\FlagPolicy::class);
|
||||
|
||||
$view->addNamespace('tags', __DIR__.'/views');
|
||||
},
|
||||
];
|
||||
|
108
extensions/tags/src/Content/Tag.php
Normal file
108
extensions/tags/src/Content/Tag.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Content;
|
||||
|
||||
use Flarum\Api\Client;
|
||||
use Flarum\Api\Controller\ListDiscussionsController;
|
||||
use Flarum\Frontend\Document;
|
||||
use Flarum\Tags\TagRepository;
|
||||
use Flarum\User\User;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Support\Arr;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class Tag
|
||||
{
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
protected $api;
|
||||
|
||||
/**
|
||||
* @var Factory
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* @var TagRepository
|
||||
*/
|
||||
protected $tags;
|
||||
|
||||
/**
|
||||
* @param Client $api
|
||||
* @param Factory $view
|
||||
*/
|
||||
public function __construct(Client $api, Factory $view, TagRepository $tags)
|
||||
{
|
||||
$this->api = $api;
|
||||
$this->view = $view;
|
||||
$this->tags = $tags;
|
||||
}
|
||||
|
||||
public function __invoke(Document $document, Request $request)
|
||||
{
|
||||
$queryParams = $request->getQueryParams();
|
||||
$actor = $request->getAttribute('actor');
|
||||
|
||||
$slug = Arr::pull($queryParams, 'slug');
|
||||
$sort = Arr::pull($queryParams, 'sort');
|
||||
$q = Arr::pull($queryParams, 'q', '');
|
||||
$page = Arr::pull($queryParams, 'page', 1);
|
||||
|
||||
$sortMap = $this->getSortMap();
|
||||
|
||||
$tagId = $this->tags->getIdForSlug($slug);
|
||||
$tag = $this->tags->findOrFail($tagId, $actor);
|
||||
|
||||
$params = [
|
||||
'sort' => $sort && isset($sortMap[$sort]) ? $sortMap[$sort] : '',
|
||||
'filter' => [
|
||||
'q' => "$q tag:$slug"
|
||||
],
|
||||
'page' => ['offset' => ($page - 1) * 20, 'limit' => 20]
|
||||
];
|
||||
|
||||
$apiDocument = $this->getApiDocument($actor, $params);
|
||||
|
||||
$document->content = $this->view->make('tags::frontend.content.tag', compact('apiDocument', 'page', 'tag'));
|
||||
$document->payload['apiDocument'] = $apiDocument;
|
||||
|
||||
return $document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of sort query param values and their API sort params.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getSortMap()
|
||||
{
|
||||
return [
|
||||
'latest' => '-lastPostedAt',
|
||||
'top' => '-commentCount',
|
||||
'newest' => '-createdAt',
|
||||
'oldest' => 'createdAt'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result of an API request to list discussions.
|
||||
*
|
||||
* @param User $actor
|
||||
* @param array $params
|
||||
* @return object
|
||||
*/
|
||||
private function getApiDocument(User $actor, array $params)
|
||||
{
|
||||
return json_decode($this->api->send(ListDiscussionsController::class, $actor, $params)->getBody());
|
||||
}
|
||||
}
|
87
extensions/tags/src/Content/Tags.php
Normal file
87
extensions/tags/src/Content/Tags.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Content;
|
||||
|
||||
use Flarum\Api\Client;
|
||||
use Flarum\Frontend\Document;
|
||||
use Flarum\Http\UrlGenerator;
|
||||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
use Flarum\Tags\TagRepository;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Support\Arr;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class Tags
|
||||
{
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
protected $api;
|
||||
|
||||
/**
|
||||
* @var Factory
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* @var TagRepository
|
||||
*/
|
||||
protected $tags;
|
||||
|
||||
/**
|
||||
* @var SettingsRepositoryInterface
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* @var UrlGenerator
|
||||
*/
|
||||
protected $url;
|
||||
|
||||
/**
|
||||
* @param Client $api
|
||||
* @param Factory $view
|
||||
* @param TagRepository $tags
|
||||
* @param SettingsRepositoryInterface $settings
|
||||
* @param UrlGenerator $url
|
||||
*/
|
||||
public function __construct(Client $api, Factory $view, TagRepository $tags, SettingsRepositoryInterface $settings, UrlGenerator $url)
|
||||
{
|
||||
$this->api = $api;
|
||||
$this->view = $view;
|
||||
$this->tags = $tags;
|
||||
$this->settings = $settings;
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
public function __invoke(Document $document, Request $request)
|
||||
{
|
||||
$tags = collect($document->payload['resources'])->where('type', 'tags');
|
||||
$childTags = $tags->where('attributes.isChild', true);
|
||||
$primaryTags = $tags->where('attributes.isChild', false)->where('attributes.position', '!==', null)->sortBy('attributes.position');
|
||||
$secondaryTags = $tags->where('attributes.isChild', false)->where('attributes.position', '===', null)->sortBy('attributes.name');
|
||||
$defaultRoute = $this->settings->get('default_route');
|
||||
|
||||
$children = $primaryTags->mapWithKeys(function ($tag) use ($childTags) {
|
||||
$id = Arr::get($tag, 'id');
|
||||
|
||||
return [
|
||||
$id => $childTags->where('relationships.parent.data.id', $id)->pluck('attributes')->sortBy('position')
|
||||
];
|
||||
});
|
||||
|
||||
$document->content = $this->view->make('tags::frontend.content.tags', compact('primaryTags', 'secondaryTags', 'children'));
|
||||
$document->canonicalUrl = $defaultRoute === '/tags' ? $this->url->to('forum')->base() : $request->getUri()->withQuery('');
|
||||
|
||||
return $document;
|
||||
}
|
||||
}
|
26
extensions/tags/views/frontend/content/tag.blade.php
Normal file
26
extensions/tags/views/frontend/content/tag.blade.php
Normal file
@@ -0,0 +1,26 @@
|
||||
@inject('url', 'Flarum\Http\UrlGenerator')
|
||||
|
||||
<div class="container">
|
||||
<h2>{{ $tag->name }}</h2>
|
||||
<p>{{ $tag->description }}</p>
|
||||
|
||||
<ul>
|
||||
@foreach ($apiDocument->data as $discussion)
|
||||
<li>
|
||||
<a href="{{ $url->to('forum')->route('discussion', [
|
||||
'id' => $discussion->id . (trim($discussion->attributes->slug) ? '-' . $discussion->attributes->slug : '')
|
||||
]) }}">
|
||||
{{ $discussion->attributes->title }}
|
||||
</a>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
|
||||
@if (isset($apiDocument->links->prev))
|
||||
<a href="{{ $url->to('forum')->route('tag', ['slug' => $tag->slug]) }}?page={{ $page - 1 }}">« {{ $translator->trans('core.views.index.previous_page_button') }}</a>
|
||||
@endif
|
||||
|
||||
@if (isset($apiDocument->links->next))
|
||||
<a href="{{ $url->to('forum')->route('tag', ['slug' => $tag->slug]) }}?page={{ $page + 1 }}">{{ $translator->trans('core.views.index.next_page_button') }} »</a>
|
||||
@endif
|
||||
</div>
|
33
extensions/tags/views/frontend/content/tags.blade.php
Normal file
33
extensions/tags/views/frontend/content/tags.blade.php
Normal file
@@ -0,0 +1,33 @@
|
||||
@inject('url', 'Flarum\Http\UrlGenerator')
|
||||
|
||||
<div class="container">
|
||||
<h2>{{ $translator->trans('flarum-tags.forum.index.tags_link') }}</h2>
|
||||
|
||||
@foreach ([$primaryTags, $secondaryTags] as $category)
|
||||
<ul>
|
||||
@foreach ($category->pluck('attributes', 'id') as $id => $tag)
|
||||
<li>
|
||||
<a href="{{ $url->to('forum')->route('tag', [
|
||||
'slug' => $tag['slug']
|
||||
]) }}">
|
||||
{{ $tag['name'] }}
|
||||
</a>
|
||||
|
||||
@if ($children->has($id))
|
||||
<ul>
|
||||
@foreach ($children->get($id) as $child)
|
||||
<li>
|
||||
<a href="{{ $url->to('forum')->route('tag', [
|
||||
'slug' => $child['slug']
|
||||
]) }}">
|
||||
{{ $child['name'] }}
|
||||
</a>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endforeach
|
||||
</div>
|
Reference in New Issue
Block a user