[PLUGINS][RelatedTags] Add related tags plugin and needed infrastructure. Initial work on pinned content
This commit is contained in:
parent
3227018963
commit
3477ad5efc
@ -68,7 +68,7 @@ class Tag extends Component
|
||||
$processed_tags = false;
|
||||
preg_match_all(self::TAG_REGEX, $content, $matched_tags, \PREG_SET_ORDER);
|
||||
foreach ($matched_tags as $match) {
|
||||
$tag = self::ensureLength($match[2]);
|
||||
$tag = str_replace('#', '', self::ensureLength($match[2]));
|
||||
$canonical_tag = self::canonicalTag($tag, Language::getFromId($note->getLanguageId())->getLocale());
|
||||
DB::persist(NoteTag::create(['tag' => $tag, 'canonical' => $canonical_tag, 'note_id' => $note->getId()]));
|
||||
Cache::pushList("tag-{$canonical_tag}", $note);
|
||||
|
@ -1,6 +1,10 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
{% for pinned in handle_event('AddPinnedFeedContent', app.request) %}
|
||||
{% include pinned['template'] with { 'actor_tags': pinned['vars']} only %}
|
||||
{% endfor %}
|
||||
|
||||
{% for actor in results %}
|
||||
{% block profile_view %}{% include 'cards/profile/view.html.twig' %}{% endblock profile_view %}
|
||||
{% endfor %}
|
||||
|
@ -2,9 +2,15 @@
|
||||
{% import '/cards/note/view.html.twig' as noteView %}
|
||||
|
||||
{% block body %}
|
||||
{% for pinned in handle_event('AddPinnedFeedContent', app.request) %}
|
||||
{% include pinned['template'] with { 'note_tags': pinned['vars']} only %}
|
||||
{% endfor %}
|
||||
|
||||
{% for note in results %}
|
||||
{% block current_note %}
|
||||
{{ noteView.macro_note(note) }}
|
||||
<div class="section-widget">
|
||||
{{ noteView.macro_note(note) }}
|
||||
</div>
|
||||
{% endblock current_note %}
|
||||
{% endfor %}
|
||||
|
||||
|
77
plugins/RelatedTags/RelatedTags.php
Normal file
77
plugins/RelatedTags/RelatedTags.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
// {{{ License
|
||||
// This file is part of GNU social - https://www.gnu.org/software/social
|
||||
//
|
||||
// GNU social is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// GNU social is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||
// }}}
|
||||
|
||||
namespace Plugin\RelatedTags;
|
||||
|
||||
use App\Core\Cache;
|
||||
use App\Core\DB\DB;
|
||||
use App\Core\Event;
|
||||
use App\Core\Modules\Plugin;
|
||||
use App\Entity\NoteTag;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class RelatedTags extends Plugin
|
||||
{
|
||||
public function onAddPinnedFeedContent(Request $request, array &$pinned)
|
||||
{
|
||||
$tags = $request->attributes->get('tags');
|
||||
$tags = !\is_null($tags) ? explode('-', $tags) : [$request->attributes->get('tag')];
|
||||
switch ($request->attributes->get('_route')) {
|
||||
case 'single_note_tag':
|
||||
// fall-through
|
||||
case 'multi_note_tag':
|
||||
$related = Cache::getList(
|
||||
'related-note-tags-' . implode('-', $tags),
|
||||
fn () => DB::sql(
|
||||
<<<'EOQ'
|
||||
select {select} from note_tag nt
|
||||
where nt.note_id in (select n.id from note n join note_tag nt on n.id = nt.note_id where nt.canonical in (:tags))
|
||||
and not nt.canonical in (:tags)
|
||||
limit 5
|
||||
EOQ,
|
||||
['tags' => $tags],
|
||||
entities: ['nt' => NoteTag::class],
|
||||
),
|
||||
);
|
||||
$pinned[] = ['template' => 'related_tags/note_tags.html.twig', 'vars' => $related];
|
||||
break;
|
||||
case 'single_actor_tag':
|
||||
// fall-through
|
||||
case 'multi_actor_tag':
|
||||
$related = Cache::getList(
|
||||
'related-actor-tags-' . implode('-', $tags),
|
||||
fn () => DB::sql(
|
||||
<<<'EOQ'
|
||||
select {select} from actor_tag at
|
||||
where at.tagged in (select at.tagged from actor_tag at where at.canonical in (:tags))
|
||||
and not at.canonical in (:tags)
|
||||
limit 5
|
||||
EOQ,
|
||||
['tags' => $tags],
|
||||
),
|
||||
);
|
||||
$pinned[] = ['template' => 'related_tags/actor_tags.html.twig', 'vars' => $related];
|
||||
break;
|
||||
}
|
||||
return Event::next;
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
<div class="section-widget">
|
||||
<p>Related tags:</p>
|
||||
{% for at in actor_tags %}
|
||||
{% include 'cards/tag/actor_tag.html.twig' with { 'tag': at, 'actor': null } %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
@ -0,0 +1,6 @@
|
||||
<div class="section-widget">
|
||||
<p>Related tags:</p>
|
||||
{% for nt in note_tags %}
|
||||
{% include 'cards/tag/note_tag.html.twig' with { 'tag': nt } %}
|
||||
{% endfor %}
|
||||
</div>
|
@ -487,7 +487,7 @@ class Actor extends Entity
|
||||
return array_merge(...F\map($langs, fn ($l) => $l->toChoiceFormat()));
|
||||
}
|
||||
|
||||
public function isVisibleTo(self $other): bool
|
||||
public function isVisibleTo(null|LocalUser|self $other): bool
|
||||
{
|
||||
return true; // TODO
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ declare(strict_types = 1);
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Core\Entity;
|
||||
use App\Core\Router\Router;
|
||||
use Component\Tag\Tag;
|
||||
use DateTimeInterface;
|
||||
|
||||
@ -95,6 +96,15 @@ class NoteTag extends Entity
|
||||
// @codeCoverageIgnoreEnd
|
||||
// }}} Autocode
|
||||
|
||||
public function getUrl(?Actor $actor = null): string
|
||||
{
|
||||
$params = ['tag' => $this->getCanonical()];
|
||||
if (!\is_null($actor)) {
|
||||
$params['lang'] = $actor->getTopLanguage()->getLocale();
|
||||
}
|
||||
return Router::url('single_note_tag', $params);
|
||||
}
|
||||
|
||||
public static function schemaDef(): array
|
||||
{
|
||||
return [
|
||||
|
@ -28,8 +28,8 @@
|
||||
|
||||
<nav class="profile-info-tags">
|
||||
{% if actor_tags %}
|
||||
{% for tag in actor_tags %}
|
||||
<a href="{{ tag.getActorTag().getUrl(actor) }}"><em>#{{ tag.getTag() }}</em></a>
|
||||
{% for tag in actor_tags %} {# Actually a list of actor_circle #}
|
||||
{% include 'cards/tag/actor_tag.html.twig' with { 'tag': tag.getActorTag(), 'actor': actor } %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{{ '(No tags)' | trans }}
|
||||
|
1
templates/cards/tag/actor_tag.html.twig
Normal file
1
templates/cards/tag/actor_tag.html.twig
Normal file
@ -0,0 +1 @@
|
||||
<a href="{{ tag.getUrl(actor) }}" title="{{ tag.getTag() }}" rel="tag"><em>#{{ tag.getTag() }}</em></a>
|
1
templates/cards/tag/note_tag.html.twig
Normal file
1
templates/cards/tag/note_tag.html.twig
Normal file
@ -0,0 +1 @@
|
||||
<a href="{{ tag.getUrl() }}" title="{{ tag.getTag() }}" rel="tag">#{{ tag.getTag() }}</a>
|
Loading…
Reference in New Issue
Block a user