diff --git a/framework/core/src/Post/CommentPost.php b/framework/core/src/Post/CommentPost.php
index c1b150ddb3..b5d9066aab 100644
--- a/framework/core/src/Post/CommentPost.php
+++ b/framework/core/src/Post/CommentPost.php
@@ -28,6 +28,8 @@ class CommentPost extends Post
public static string $type = 'comment';
protected static Formatter $formatter;
+ protected $observables = ['hidden'];
+
public static function reply(int $discussionId, string $content, int $userId, ?string $ipAddress, ?User $actor = null): static
{
$post = new static;
@@ -69,6 +71,12 @@ public function hide(?User $actor = null): static
$this->hidden_user_id = $actor?->id;
$this->raise(new Hidden($this));
+
+ $this->saved(function (self $model) {
+ if ($model === $this) {
+ $model->fireModelEvent('hidden', false);
+ }
+ });
}
return $this;
@@ -81,6 +89,12 @@ public function restore(): static
$this->hidden_user_id = null;
$this->raise(new Restored($this));
+
+ $this->saved(function (self $model) {
+ if ($model === $this) {
+ $model->fireModelEvent('restored', false);
+ }
+ });
}
return $this;
diff --git a/framework/core/tests/integration/extenders/SimpleFlarumSearchTest.php b/framework/core/tests/integration/extenders/SearchDriverTest.php
similarity index 97%
rename from framework/core/tests/integration/extenders/SimpleFlarumSearchTest.php
rename to framework/core/tests/integration/extenders/SearchDriverTest.php
index 28c706ac87..8c8d8ea3b3 100644
--- a/framework/core/tests/integration/extenders/SimpleFlarumSearchTest.php
+++ b/framework/core/tests/integration/extenders/SearchDriverTest.php
@@ -24,7 +24,7 @@
use Flarum\Testing\integration\TestCase;
use Flarum\User\User;
-class SimpleFlarumSearchTest extends TestCase
+class SearchDriverTest extends TestCase
{
use RetrievesAuthorizedUsers;
@@ -73,8 +73,7 @@ public function searchDiscussions($query, $limit = null, array $filters = [])
return $this->app()
->getContainer()
->make(SearchManager::class)
- ->for(Discussion::class)
- ->search(new SearchCriteria($actor, $filters, $limit))
+ ->query(Discussion::class, new SearchCriteria($actor, $filters, $limit))
->getResults();
}
diff --git a/framework/core/tests/integration/extenders/SearchIndexTest.php b/framework/core/tests/integration/extenders/SearchIndexTest.php
new file mode 100644
index 0000000000..acbb3ead43
--- /dev/null
+++ b/framework/core/tests/integration/extenders/SearchIndexTest.php
@@ -0,0 +1,222 @@
+prepareDatabase([
+ 'discussions' => [
+ ['id' => 1, 'title' => 'DISCUSSION 1', 'created_at' => Carbon::now()->subDays(1)->toDateTimeString(), 'hidden_at' => null, 'comment_count' => 1, 'user_id' => 1, 'first_post_id' => 1],
+ ['id' => 2, 'title' => 'DISCUSSION 2', 'created_at' => Carbon::now()->subDays(2)->toDateTimeString(), 'hidden_at' => Carbon::now(), 'comment_count' => 1, 'user_id' => 1],
+ ],
+ 'posts' => [
+ ['id' => 1, 'number' => 1, 'discussion_id' => 1, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => 'content
', 'hidden_at' => null],
+ ['id' => 2, 'number' => 2, 'discussion_id' => 1, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => 'content
', 'hidden_at' => Carbon::now()],
+ ],
+ ]);
+ }
+
+ public static function modelProvider(): array
+ {
+ return [
+ ['discussions', Discussion::class, 'title'],
+ ['posts', CommentPost::class, 'content'],
+ ];
+ }
+
+ /** @dataProvider modelProvider */
+ public function test_indexer_triggered_on_create(string $type, string $modelClass, string $attribute)
+ {
+ $this->extend(
+ (new Extend\SearchIndex())
+ ->indexer($modelClass, TestIndexer::class)
+ );
+
+ // Create discussion
+ $response = $this->send(
+ $this->request('POST', "/api/$type", [
+ 'authenticatedAs' => 1,
+ 'json' => [
+ 'data' => [
+ 'attributes' => [
+ $attribute => 'test',
+ ],
+ 'relationships' =>
+ ($type === 'posts' ? [
+ 'discussion' => [
+ 'data' => [
+ 'type' => 'discussions',
+ 'id' => 1,
+ ],
+ ],
+ ] : null),
+ ]
+ ],
+ ]),
+ );
+
+ Assert::assertEquals('save', TestIndexer::$triggered, $response->getBody()->getContents());
+ }
+
+ /** @dataProvider modelProvider */
+ public function test_indexer_triggered_on_save(string $type, string $modelClass, string $attribute)
+ {
+ $this->extend(
+ (new Extend\SearchIndex())
+ ->indexer($modelClass, TestIndexer::class)
+ );
+
+ // Rename discussion
+ $response = $this->send(
+ $this->request('PATCH', "/api/$type/1", [
+ 'authenticatedAs' => 1,
+ 'json' => [
+ 'data' => [
+ 'attributes' => [
+ $attribute => 'changed'
+ ]
+ ]
+ ],
+ ]),
+ );
+
+ Assert::assertEquals('save', TestIndexer::$triggered, $response->getBody()->getContents());
+ }
+
+ /** @dataProvider modelProvider */
+ public function test_indexer_triggered_on_delete(string $type, string $modelClass, string $attribute)
+ {
+ $this->extend(
+ (new Extend\SearchIndex())
+ ->indexer($modelClass, TestIndexer::class)
+ );
+
+ // Delete discussion
+ $response = $this->send(
+ $this->request('DELETE', "/api/$type/1", [
+ 'authenticatedAs' => 1,
+ 'json' => [],
+ ]),
+ );
+
+ Assert::assertEquals('delete', TestIndexer::$triggered, $response->getBody()->getContents());
+ }
+
+ /** @dataProvider modelProvider */
+ public function test_indexer_triggered_on_hide(string $type, string $modelClass, string $attribute)
+ {
+ $this->extend(
+ (new Extend\SearchIndex())
+ ->indexer($modelClass, TestIndexer::class)
+ );
+
+ // Hide discussion
+ $response = $this->send(
+ $this->request('PATCH', "/api/$type/1", [
+ 'authenticatedAs' => 1,
+ 'json' => [
+ 'data' => [
+ 'attributes' => [
+ 'isHidden' => true
+ ]
+ ]
+ ],
+ ]),
+ );
+
+ Assert::assertEquals('delete', TestIndexer::$triggered, $response->getBody()->getContents());
+ }
+
+ /** @dataProvider modelProvider */
+ public function test_indexer_triggered_on_restore(string $type, string $modelClass, string $attribute)
+ {
+ $this->extend(
+ (new Extend\SearchIndex())
+ ->indexer($modelClass, TestIndexer::class)
+ );
+
+ // Restore discussion
+ $response = $this->send(
+ $this->request('PATCH', "/api/$type/2", [
+ 'authenticatedAs' => 1,
+ 'json' => [
+ 'data' => [
+ 'attributes' => [
+ 'isHidden' => false
+ ]
+ ]
+ ],
+ ]),
+ );
+
+ Assert::assertEquals('save', TestIndexer::$triggered, $response->getBody()->getContents());
+ }
+
+ protected function tearDown(): void
+ {
+ TestIndexer::$triggered = null;
+
+ parent::tearDown();
+ }
+}
+
+class TestIndexer implements IndexerInterface
+{
+ public static ?string $triggered = null;
+
+ public static function index(): string
+ {
+ return 'test';
+ }
+
+ public function save(array $models): void
+ {
+ self::$triggered = 'save';
+ }
+
+ public function delete(array $models): void
+ {
+ self::$triggered = 'delete';
+ }
+
+ public function build(): void
+ {
+ //
+ }
+
+ public function flush(): void
+ {
+ //
+ }
+}