diff --git a/components/Tag/Controller/Tag.php b/components/Tag/Controller/Tag.php index 172a91f83e..eea9eed65d 100644 --- a/components/Tag/Controller/Tag.php +++ b/components/Tag/Controller/Tag.php @@ -8,77 +8,70 @@ use App\Core\Cache; use App\Core\Controller; use App\Util\Common; use Component\Tag\Tag as CompTag; -use Functional as F; class Tag extends Controller { - private function process(string|array $tag_or_tags, callable $key, string $query, string $template) + private function process(string|array $canon_single_or_multi, null|string|array $tag_single_or_multi, string $key, string $query, string $template) { $actor = Common::actor(); $page = $this->int('page') ?: 1; $lang = $this->string('lang'); - if (\is_null($lang)) { - $langs = $actor->getPreferredLanguageChoices(); - $lang = $langs[array_key_first($langs)]; - } - if (\is_string($tag_or_tags)) { - $canonical = CompTag::canonicalTag($tag_or_tags, $lang); - } else { - $canonical = F\map($tag_or_tags, fn ($t) => CompTag::canonicalTag($t, $lang)); - } + $results = Cache::pagedStream( - key: $key($canonical), + key: $key, query: $query, - query_args: ['canon' => $canonical], + query_args: ['canon' => $canon_single_or_multi], actor: $actor, page: $page, ); return [ '_template' => $template, - 'tag_name' => $canonical, + 'tag_name' => $tag_single_or_multi, 'results' => $results, 'page' => $page, ]; } - public function single_note_tag(string $tag) + public function single_note_tag(string $canon) { return $this->process( - tag_or_tags: $tag, - key: fn ($canonical) => "note-tag-feed-{$canonical}", + canon_single_or_multi: $canon, + tag_single_or_multi: $this->string('tag'), + key: CompTag::cacheKeys($canon)['note_single'], query: 'select n from note n join note_tag nt with n.id = nt.note_id where nt.canonical = :canon order by nt.created DESC, nt.note_id DESC', template: 'note_tag_feed.html.twig', ); } - public function multi_note_tags(string $tags) + public function multi_note_tags(string $canons) { - $tags = explode(',', $tags); return $this->process( - tag_or_tags: $tags, - key: fn ($canonical) => 'note-tags-feed-' . implode('-', $canonical), + canon_single_or_multi: explode(',', $canons), + tag_single_or_multi: !\is_null($this->string('tags')) ? explode(',', $this->string('tags')) : null, + key: CompTag::cacheKeys(str_replace(',', '-', $canons))['note_multi'], query: 'select n from note n join note_tag nt with n.id = nt.note_id where nt.canonical in (:canon) order by nt.created DESC, nt.note_id DESC', template: 'note_tag_feed.html.twig', ); } - public function single_actor_tag(string $tag) + public function single_actor_tag(string $canon) { return $this->process( - tag_or_tags: $tag, - key: fn ($canonical) => "actor-tag-feed-{$canonical}", + canon_single_or_multi: $canon, + tag_single_or_multi: $this->string('tag'), + key: CompTag::cacheKeys($canon)['actor_single'], query: 'select a from actor a join actor_tag at with a.id = at.tagged where at.canonical = :canon order by at.modified DESC', template: 'actor_tag_feed.html.twig', ); } - public function multi_actor_tag(string $tags) + public function multi_actor_tag(string $canons) { - $tags = explode(',', $tags); return $this->process( - tag_or_tags: $tags, - key: fn ($canonical) => 'actor-tags-feed-' . implode('-', $canonical), + canon_single_or_multi: explode(',', $canons), + tag_single_or_multi: !\is_null($this->string('tags')) ? explode(',', $this->string('tags')) : null, + key: CompTag::cacheKeys(str_replace(',', '-', $canons))['actor_multi'], query: 'select a from actor a join actor_tag at with a.id = at.tagged where at.canonical = :canon order by at.modified DESC', template: 'actor_tag_feed.html.twig', ); diff --git a/components/Tag/Tag.php b/components/Tag/Tag.php index d5abfff274..63b5d64013 100644 --- a/components/Tag/Tag.php +++ b/components/Tag/Tag.php @@ -57,10 +57,10 @@ class Tag extends Component public function onAddRoute($r): bool { - $r->connect('single_note_tag', '/note-tag/{tag<' . self::TAG_SLUG_REGEX . '>}', [Controller\Tag::class, 'single_note_tag']); - $r->connect('multiple_note_tags', '/note-tags/{tags<(' . self::TAG_SLUG_REGEX . ',)+' . self::TAG_SLUG_REGEX . '>}', [Controller\Tag::class, 'multi_note_tags']); - $r->connect('single_actor_tag', '/actor-tag/{tag<' . self::TAG_SLUG_REGEX . '>}', [Controller\Tag::class, 'single_actor_tag']); - $r->connect('multiple_actor_tags', '/actor-tags/{tags<(' . self::TAG_SLUG_REGEX . ',)+' . self::TAG_SLUG_REGEX . '>}', [Controller\Tag::class, 'multi_actor_tags']); + $r->connect('single_note_tag', '/note-tag/{canon<' . self::TAG_SLUG_REGEX . '>}', [Controller\Tag::class, 'single_note_tag']); + $r->connect('multi_note_tags', '/note-tags/{canons<(' . self::TAG_SLUG_REGEX . ',)+' . self::TAG_SLUG_REGEX . '>}', [Controller\Tag::class, 'multi_note_tags']); + $r->connect('single_actor_tag', '/actor-tag/{canon<' . self::TAG_SLUG_REGEX . '>}', [Controller\Tag::class, 'single_actor_tag']); + $r->connect('multi_actor_tags', '/actor-tags/{canons<(' . self::TAG_SLUG_REGEX . ',)+' . self::TAG_SLUG_REGEX . '>}', [Controller\Tag::class, 'multi_actor_tags']); return Event::next; } @@ -83,6 +83,9 @@ class Tag extends Component ])); Cache::pushList("tag-{$canonical_tag}", $note); $processed_tags = true; + foreach (self::cacheKeys($canonical_tag) as $key) { + Cache::delete($key); + } } if ($processed_tags) { DB::flush(); @@ -96,11 +99,21 @@ class Tag extends Component return Event::next; } + public static function cacheKeys(string $canon_single_or_multi): array + { + return [ + 'note_single' => "note-tag-feed-{$canon_single_or_multi}", + 'note_multi' => "note-tags-feed-{$canon_single_or_multi}", + 'actor_single' => "actor-tag-feed-{$canon_single_or_multi}", + 'actor_multi' => "actor-tags-feed-{$canon_single_or_multi}", + ]; + } + private static function tagLink(string $tag, ?string $language): string { $tag = self::ensureLength($tag); $canonical = self::canonicalTag($tag, $language); - $url = Router::url('single_note_tag', !\is_null($language) ? ['tag' => $canonical, 'lang' => $language] : ['tag' => $canonical]); + $url = Router::url('single_note_tag', !\is_null($language) ? ['canon' => $canonical, 'lang' => $language, 'tag' => $tag] : ['canon' => $canonical, 'tag' => $tag]); return HTML::html(['a' => ['attrs' => ['href' => $url, 'title' => $tag, 'rel' => 'tag'], $tag]], options: ['indent' => false]); } diff --git a/components/Tag/templates/actor_tag_feed.html.twig b/components/Tag/templates/actor_tag_feed.html.twig index b7c06eebfd..54d001927f 100644 --- a/components/Tag/templates/actor_tag_feed.html.twig +++ b/components/Tag/templates/actor_tag_feed.html.twig @@ -1,22 +1,29 @@ {% extends 'base.html.twig' %} {% block stylesheets %} - {{ parent() }} - + {{ parent() }} + {% endblock stylesheets %} {% block body %} -