mirror of
https://github.com/flarum/core.git
synced 2025-08-02 06:30:53 +02:00
fix(tags): DiscussionTaggedPost
shows tags as deleted
(#3812)
* fix(tags): `DiscussionTaggedPost` shows tags as `deleted` Signed-off-by: Sami Mazouz <sychocouldy@gmail.com> * Apply fixes from StyleCI --------- Signed-off-by: Sami Mazouz <sychocouldy@gmail.com> Co-authored-by: StyleCI Bot <bot@styleci.io>
This commit is contained in:
@@ -128,9 +128,6 @@ return [
|
|||||||
->render(Formatter\FormatTagMentions::class)
|
->render(Formatter\FormatTagMentions::class)
|
||||||
->unparse(Formatter\UnparseTagMentions::class),
|
->unparse(Formatter\UnparseTagMentions::class),
|
||||||
|
|
||||||
(new Extend\Model(Post::class))
|
|
||||||
->belongsToMany('mentionsTags', Tag::class, 'post_mentions_tag', 'post_id', 'mentions_tag_id'),
|
|
||||||
|
|
||||||
(new Extend\ApiSerializer(BasicPostSerializer::class))
|
(new Extend\ApiSerializer(BasicPostSerializer::class))
|
||||||
->hasMany('mentionsTags', TagSerializer::class),
|
->hasMany('mentionsTags', TagSerializer::class),
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use Flarum\Api\Controller as FlarumController;
|
use Flarum\Api\Controller as FlarumController;
|
||||||
|
use Flarum\Api\Serializer\BasicPostSerializer;
|
||||||
use Flarum\Api\Serializer\DiscussionSerializer;
|
use Flarum\Api\Serializer\DiscussionSerializer;
|
||||||
use Flarum\Api\Serializer\ForumSerializer;
|
use Flarum\Api\Serializer\ForumSerializer;
|
||||||
use Flarum\Discussion\Discussion;
|
use Flarum\Discussion\Discussion;
|
||||||
@@ -18,6 +19,7 @@ use Flarum\Extend;
|
|||||||
use Flarum\Flags\Api\Controller\ListFlagsController;
|
use Flarum\Flags\Api\Controller\ListFlagsController;
|
||||||
use Flarum\Http\RequestUtil;
|
use Flarum\Http\RequestUtil;
|
||||||
use Flarum\Post\Filter\PostFilterer;
|
use Flarum\Post\Filter\PostFilterer;
|
||||||
|
use Flarum\Post\Post;
|
||||||
use Flarum\Tags\Access;
|
use Flarum\Tags\Access;
|
||||||
use Flarum\Tags\Api\Controller;
|
use Flarum\Tags\Api\Controller;
|
||||||
use Flarum\Tags\Api\Serializer\TagSerializer;
|
use Flarum\Tags\Api\Serializer\TagSerializer;
|
||||||
@@ -142,4 +144,37 @@ return [
|
|||||||
|
|
||||||
(new Extend\ModelUrl(Tag::class))
|
(new Extend\ModelUrl(Tag::class))
|
||||||
->addSlugDriver('default', Utf8SlugDriver::class),
|
->addSlugDriver('default', Utf8SlugDriver::class),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fixes DiscussionTaggedPost showing tags as deleted because they are not loaded in the store.
|
||||||
|
* @link https://github.com/flarum/framework/issues/3620#issuecomment-1232911734
|
||||||
|
*/
|
||||||
|
|
||||||
|
(new Extend\Model(Post::class))
|
||||||
|
->belongsToMany('mentionsTags', Tag::class, 'post_mentions_tag', 'post_id', 'mentions_tag_id')
|
||||||
|
// We do not wish to include all `mentionsTags` in the API response,
|
||||||
|
// only those related to `discussionTagged` posts.
|
||||||
|
->relationship('eventPostMentionsTags', function (Post $model) {
|
||||||
|
return $model->mentionsTags();
|
||||||
|
}),
|
||||||
|
|
||||||
|
(new Extend\ApiSerializer(BasicPostSerializer::class))
|
||||||
|
->relationship('eventPostMentionsTags', function (BasicPostSerializer $serializer, Post $model) {
|
||||||
|
if ($model instanceof DiscussionTaggedPost) {
|
||||||
|
return $serializer->hasMany($model, TagSerializer::class, 'eventPostMentionsTags');
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
->hasMany('eventPostMentionsTags', TagSerializer::class),
|
||||||
|
|
||||||
|
(new Extend\ApiController(FlarumController\ListPostsController::class))
|
||||||
|
->addInclude('eventPostMentionsTags')
|
||||||
|
// Restricted tags should still appear as `deleted` to unauthorized users.
|
||||||
|
->loadWhere('eventPostMentionsTags', function ($query, ?ServerRequestInterface $request) {
|
||||||
|
if ($request) {
|
||||||
|
$actor = RequestUtil::getActor($request);
|
||||||
|
$query->whereVisibleTo($actor);
|
||||||
|
}
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
@@ -45,6 +45,11 @@ class DiscussionTaggedPost extends AbstractEventPost implements MergeableInterfa
|
|||||||
|
|
||||||
$this->save();
|
$this->save();
|
||||||
|
|
||||||
|
// Create mentions of the tags so that we can load them when rendering.
|
||||||
|
$this->mentionsTags()->sync(
|
||||||
|
array_merge($this->content[0], $this->content[1])
|
||||||
|
);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
137
extensions/tags/tests/integration/api/posts/ListTest.php
Normal file
137
extensions/tags/tests/integration/api/posts/ListTest.php
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed copyright and license information, please view the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Tags\Tests\integration\api\posts;
|
||||||
|
|
||||||
|
use Flarum\Tags\Tests\integration\RetrievesRepresentativeTags;
|
||||||
|
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
|
||||||
|
use Flarum\Testing\integration\TestCase;
|
||||||
|
|
||||||
|
class ListTest extends TestCase
|
||||||
|
{
|
||||||
|
use RetrievesAuthorizedUsers;
|
||||||
|
use RetrievesRepresentativeTags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->extension('flarum-tags');
|
||||||
|
|
||||||
|
$this->prepareDatabase([
|
||||||
|
'tags' => $this->tags(),
|
||||||
|
'users' => [
|
||||||
|
$this->normalUser(),
|
||||||
|
[
|
||||||
|
'id' => 3,
|
||||||
|
'username' => 'normal3',
|
||||||
|
'password' => '$2y$10$LO59tiT7uggl6Oe23o/O6.utnF6ipngYjvMvaxo1TciKqBttDNKim', // BCrypt hash for "too-obscure"
|
||||||
|
'email' => 'normal3@machine.local',
|
||||||
|
'is_email_confirmed' => 1,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'groups' => [
|
||||||
|
['id' => 100, 'name_singular' => 'acme', 'name_plural' => 'acme']
|
||||||
|
],
|
||||||
|
'group_user' => [
|
||||||
|
['group_id' => 100, 'user_id' => 2]
|
||||||
|
],
|
||||||
|
'group_permission' => [
|
||||||
|
['group_id' => 100, 'permission' => 'tag5.viewForum'],
|
||||||
|
],
|
||||||
|
'discussions' => [
|
||||||
|
['id' => 1, 'title' => 'no tags', 'user_id' => 1, 'comment_count' => 1],
|
||||||
|
],
|
||||||
|
'posts' => [
|
||||||
|
['id' => 1, 'discussion_id' => 1, 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p></p></t>', 'number' => 1],
|
||||||
|
['id' => 2, 'discussion_id' => 1, 'user_id' => 1, 'type' => 'discussionTagged', 'content' => '[[1,5],[5]]', 'number' => 2],
|
||||||
|
['id' => 3, 'discussion_id' => 1, 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p></p></t>', 'number' => 3],
|
||||||
|
['id' => 4, 'discussion_id' => 1, 'user_id' => 1, 'type' => 'discussionTagged', 'content' => '[[1,5],[5]]', 'number' => 4],
|
||||||
|
],
|
||||||
|
'discussion_tag' => [
|
||||||
|
['discussion_id' => 1, 'tag_id' => 1],
|
||||||
|
],
|
||||||
|
'post_mentions_tag' => [
|
||||||
|
['post_id' => 2, 'mentions_tag_id' => 1],
|
||||||
|
['post_id' => 2, 'mentions_tag_id' => 5],
|
||||||
|
['post_id' => 4, 'mentions_tag_id' => 1],
|
||||||
|
['post_id' => 4, 'mentions_tag_id' => 5],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider authorizedUsers
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function event_mentioned_tags_are_included_in_response_for_authorized_users(int $userId)
|
||||||
|
{
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/api/posts', [
|
||||||
|
'authenticatedAs' => $userId
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true);
|
||||||
|
|
||||||
|
$tagIds = array_map(function ($tag) {
|
||||||
|
return $tag['id'];
|
||||||
|
}, array_filter($data['included'], function ($item) {
|
||||||
|
return $item['type'] === 'tags';
|
||||||
|
}));
|
||||||
|
|
||||||
|
$this->assertEqualsCanonicalizing([1, 5], $tagIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider unauthorizedUsers
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function event_mentioned_tags_are_not_included_in_response_for_unauthorized_users(?int $userId)
|
||||||
|
{
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/api/posts', [
|
||||||
|
'authenticatedAs' => $userId
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true);
|
||||||
|
|
||||||
|
$tagIds = array_map(function ($tag) {
|
||||||
|
return $tag['id'];
|
||||||
|
}, array_filter($data['included'], function ($item) {
|
||||||
|
return $item['type'] === 'tags';
|
||||||
|
}));
|
||||||
|
|
||||||
|
$this->assertEqualsCanonicalizing([1], $tagIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authorizedUsers()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'admin' => [1],
|
||||||
|
'normal user with permission' => [2],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unauthorizedUsers()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'normal user without permission' => [3],
|
||||||
|
'guest' => [null],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user