1
0
mirror of https://github.com/flarum/core.git synced 2025-08-21 07:41:49 +02:00

perf(core,mentions): limit mentionedBy post relation results (#3780)

* perf(core,mentions): limit `mentionedBy` post relation results

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>

* Apply fixes from StyleCI

* chore: use a static property to allow customization

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>

* chore: use a static property to allow customization

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>

* chore: include count in show post endpoint

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>

* chore: consistent locale key format

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>

* chore: forgot to delete `FilterVisiblePosts`

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>

* test: `mentionedByCount` must not include invisible posts to actor

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>

* fix: visibility scoping on `mentionedByCount`

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>

* fix: `loadAggregates` conflicts with visibility scopers

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>

* Apply fixes from StyleCI

* chore: phpstan

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>

---------

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>
Co-authored-by: StyleCI Bot <bot@styleci.io>
This commit is contained in:
Sami Mazouz
2023-04-19 08:23:08 +01:00
committed by GitHub
parent 13e655aca5
commit fbbece4bda
22 changed files with 552 additions and 141 deletions

View File

@@ -80,9 +80,11 @@ class GroupMentionsTest extends TestCase
$this->request('GET', '/api/posts/4')
);
$this->assertEquals(200, $response->getStatusCode());
$contents = $response->getBody()->getContents();
$response = json_decode($response->getBody(), true);
$this->assertEquals(200, $response->getStatusCode(), $contents);
$response = json_decode($contents, true);
$this->assertStringContainsString('GroupMention', $response['data']['attributes']['contentHtml']);
$this->assertStringContainsString('#80349E', $response['data']['attributes']['contentHtml']);

View File

@@ -7,9 +7,10 @@
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Tests\integration\api\discussions;
namespace Flarum\Mentions\Tests\integration\api\discussions;
use Carbon\Carbon;
use Flarum\Mentions\Api\LoadMentionedByRelationship;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Illuminate\Support\Arr;
@@ -107,4 +108,152 @@ class ListPostsTest extends TestCase
$ids = Arr::pluck($data, 'id');
$this->assertEqualsCanonicalizing(['3', '2'], $ids, 'IDs do not match');
}
protected function prepareMentionedByData(): void
{
$this->prepareDatabase([
'discussions' => [
['id' => 100, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'user_id' => 1, 'first_post_id' => 101, 'comment_count' => 12],
],
'posts' => [
['id' => 101, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
['id' => 102, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
['id' => 103, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>', 'is_private' => 1],
['id' => 104, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
['id' => 105, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
['id' => 106, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
['id' => 107, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
['id' => 108, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
['id' => 109, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
['id' => 110, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
['id' => 111, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
['id' => 112, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
],
'post_mentions_post' => [
['post_id' => 102, 'mentions_post_id' => 101],
['post_id' => 103, 'mentions_post_id' => 101],
['post_id' => 104, 'mentions_post_id' => 101],
['post_id' => 105, 'mentions_post_id' => 101],
['post_id' => 106, 'mentions_post_id' => 101],
['post_id' => 107, 'mentions_post_id' => 101],
['post_id' => 108, 'mentions_post_id' => 101],
['post_id' => 109, 'mentions_post_id' => 101],
['post_id' => 110, 'mentions_post_id' => 101],
['post_id' => 111, 'mentions_post_id' => 101],
['post_id' => 112, 'mentions_post_id' => 101],
['post_id' => 103, 'mentions_post_id' => 112],
],
]);
}
/** @test */
public function mentioned_by_relation_returns_limited_results_and_shows_only_visible_posts_in_show_post_endpoint()
{
$this->prepareMentionedByData();
// List posts endpoint
$response = $this->send(
$this->request('GET', '/api/posts/101', [
'authenticatedAs' => 2,
])->withQueryParams([
'include' => 'mentionedBy',
])
);
$data = json_decode($response->getBody()->getContents(), true)['data'];
$this->assertEquals(200, $response->getStatusCode());
$mentionedBy = $data['relationships']['mentionedBy']['data'];
// Only displays a limited amount of mentioned by posts
$this->assertCount(LoadMentionedByRelationship::$maxMentionedBy, $mentionedBy);
// Of the limited amount of mentioned by posts, they must be visible to the actor
$this->assertEquals([102, 104, 105, 106], Arr::pluck($mentionedBy, 'id'));
}
/** @test */
public function mentioned_by_relation_returns_limited_results_and_shows_only_visible_posts_in_list_posts_endpoint()
{
$this->prepareMentionedByData();
// List posts endpoint
$response = $this->send(
$this->request('GET', '/api/posts', [
'authenticatedAs' => 2,
])->withQueryParams([
'filter' => ['discussion' => 100],
'include' => 'mentionedBy',
])
);
$data = json_decode($response->getBody()->getContents(), true)['data'];
$this->assertEquals(200, $response->getStatusCode());
$mentionedBy = $data[0]['relationships']['mentionedBy']['data'];
// Only displays a limited amount of mentioned by posts
$this->assertCount(LoadMentionedByRelationship::$maxMentionedBy, $mentionedBy);
// Of the limited amount of mentioned by posts, they must be visible to the actor
$this->assertEquals([102, 104, 105, 106], Arr::pluck($mentionedBy, 'id'));
}
/**
* @dataProvider mentionedByIncludeProvider
* @test
*/
public function mentioned_by_relation_returns_limited_results_and_shows_only_visible_posts_in_show_discussion_endpoint(string $include)
{
$this->prepareMentionedByData();
// Show discussion endpoint
$response = $this->send(
$this->request('GET', '/api/discussions/100', [
'authenticatedAs' => 2,
])->withQueryParams([
'include' => $include,
])
);
$included = json_decode($response->getBody()->getContents(), true)['included'];
$mentionedBy = collect($included)
->where('type', 'posts')
->where('id', 101)
->first()['relationships']['mentionedBy']['data'];
// Only displays a limited amount of mentioned by posts
$this->assertCount(LoadMentionedByRelationship::$maxMentionedBy, $mentionedBy);
// Of the limited amount of mentioned by posts, they must be visible to the actor
$this->assertEquals([102, 104, 105, 106], Arr::pluck($mentionedBy, 'id'));
}
public function mentionedByIncludeProvider(): array
{
return [
['posts,posts.mentionedBy'],
['posts.mentionedBy'],
[''],
];
}
/** @test */
public function mentioned_by_count_only_includes_visible_posts_to_actor()
{
$this->prepareMentionedByData();
// List posts endpoint
$response = $this->send(
$this->request('GET', '/api/posts/112', [
'authenticatedAs' => 2,
])
);
$data = json_decode($response->getBody()->getContents(), true)['data'];
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals(0, $data['attributes']['mentionedByCount']);
}
}