85 - Fix keyword matching to include title and description, add PHPStan type annotations
This commit is contained in:
parent
f3406b1713
commit
5e571babda
6 changed files with 40 additions and 3 deletions
|
|
@ -62,9 +62,12 @@ private function createRouteArticles(Article $article, string $content): void
|
|||
->get()
|
||||
->groupBy('platform_channel_id');
|
||||
|
||||
// Match keywords against full article content, title, and description
|
||||
$searchableContent = $content.' '.$article->title.' '.$article->description;
|
||||
|
||||
foreach ($activeRoutes as $route) {
|
||||
$routeKeywords = $keywordsByChannel->get($route->platform_channel_id, collect());
|
||||
$status = $this->evaluateKeywords($routeKeywords, $content);
|
||||
$status = $this->evaluateKeywords($routeKeywords, $searchableContent);
|
||||
|
||||
if ($status === ApprovalStatusEnum::PENDING && $this->shouldAutoApprove($route)) {
|
||||
$status = ApprovalStatusEnum::APPROVED;
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@ public function test_validate_article_listener_processes_new_article(): void
|
|||
Setting::setBool('enable_publishing_approvals', false);
|
||||
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var \App\Models\Route $route */
|
||||
$route = \App\Models\Route::factory()->active()->create(['feed_id' => $feed->id]);
|
||||
\App\Models\Keyword::factory()->active()->create([
|
||||
'feed_id' => $feed->id,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ protected function tearDown(): void
|
|||
public function test_listener_validates_article_and_creates_route_articles(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create(['feed_id' => $feed->id]);
|
||||
Keyword::factory()->active()->create([
|
||||
'feed_id' => $feed->id,
|
||||
|
|
|
|||
|
|
@ -33,15 +33,23 @@ protected function setUp(): void
|
|||
$this->notificationService = new NotificationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $articleOverrides
|
||||
* @param array<string, mixed> $routeOverrides
|
||||
*/
|
||||
private function createApprovedRouteArticle(array $articleOverrides = [], array $routeOverrides = []): RouteArticle
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create(array_merge(['feed_id' => $feed->id], $routeOverrides));
|
||||
$article = Article::factory()->create(array_merge(['feed_id' => $feed->id], $articleOverrides));
|
||||
|
||||
return RouteArticle::factory()->forRoute($route)->approved()->create([
|
||||
/** @var RouteArticle $routeArticle */
|
||||
$routeArticle = RouteArticle::factory()->forRoute($route)->approved()->create([
|
||||
'article_id' => $article->id,
|
||||
]);
|
||||
|
||||
return $routeArticle;
|
||||
}
|
||||
|
||||
public function test_constructor_sets_correct_queue(): void
|
||||
|
|
@ -112,6 +120,7 @@ public function test_handle_returns_early_when_no_unpublished_approved_route_art
|
|||
public function test_handle_skips_non_approved_route_articles(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create(['feed_id' => $feed->id]);
|
||||
$article = Article::factory()->create(['feed_id' => $feed->id]);
|
||||
|
||||
|
|
@ -129,6 +138,7 @@ public function test_handle_skips_non_approved_route_articles(): void
|
|||
public function test_handle_publishes_oldest_approved_route_article(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create(['feed_id' => $feed->id]);
|
||||
|
||||
$olderArticle = Article::factory()->create(['feed_id' => $feed->id]);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ class RouteArticleTest extends TestCase
|
|||
|
||||
public function test_route_article_belongs_to_article(): void
|
||||
{
|
||||
/** @var RouteArticle $routeArticle */
|
||||
$routeArticle = RouteArticle::factory()->create();
|
||||
|
||||
$this->assertInstanceOf(Article::class, $routeArticle->article);
|
||||
|
|
@ -24,6 +25,7 @@ public function test_route_article_belongs_to_article(): void
|
|||
|
||||
public function test_route_article_belongs_to_feed(): void
|
||||
{
|
||||
/** @var RouteArticle $routeArticle */
|
||||
$routeArticle = RouteArticle::factory()->create();
|
||||
|
||||
$this->assertInstanceOf(Feed::class, $routeArticle->feed);
|
||||
|
|
@ -31,6 +33,7 @@ public function test_route_article_belongs_to_feed(): void
|
|||
|
||||
public function test_route_article_belongs_to_platform_channel(): void
|
||||
{
|
||||
/** @var RouteArticle $routeArticle */
|
||||
$routeArticle = RouteArticle::factory()->create();
|
||||
|
||||
$this->assertInstanceOf(PlatformChannel::class, $routeArticle->platformChannel);
|
||||
|
|
@ -38,6 +41,7 @@ public function test_route_article_belongs_to_platform_channel(): void
|
|||
|
||||
public function test_route_article_has_default_pending_status(): void
|
||||
{
|
||||
/** @var RouteArticle $routeArticle */
|
||||
$routeArticle = RouteArticle::factory()->create();
|
||||
|
||||
$this->assertEquals(ApprovalStatusEnum::PENDING, $routeArticle->approval_status);
|
||||
|
|
@ -48,15 +52,16 @@ public function test_route_article_has_default_pending_status(): void
|
|||
|
||||
public function test_route_article_can_be_approved(): void
|
||||
{
|
||||
/** @var RouteArticle $routeArticle */
|
||||
$routeArticle = RouteArticle::factory()->create();
|
||||
|
||||
$routeArticle->approve();
|
||||
|
||||
$this->assertEquals(ApprovalStatusEnum::APPROVED, $routeArticle->fresh()->approval_status);
|
||||
}
|
||||
|
||||
public function test_route_article_can_be_rejected(): void
|
||||
{
|
||||
/** @var RouteArticle $routeArticle */
|
||||
$routeArticle = RouteArticle::factory()->create();
|
||||
|
||||
$routeArticle->reject();
|
||||
|
|
@ -66,7 +71,9 @@ public function test_route_article_can_be_rejected(): void
|
|||
|
||||
public function test_article_has_many_route_articles(): void
|
||||
{
|
||||
/** @var Route $route1 */
|
||||
$route1 = Route::factory()->active()->create();
|
||||
/** @var Route $route2 */
|
||||
$route2 = Route::factory()->active()->create();
|
||||
$article = Article::factory()->create(['feed_id' => $route1->feed_id]);
|
||||
|
||||
|
|
@ -78,6 +85,7 @@ public function test_article_has_many_route_articles(): void
|
|||
|
||||
public function test_route_has_many_route_articles(): void
|
||||
{
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create();
|
||||
$article1 = Article::factory()->create(['feed_id' => $route->feed_id]);
|
||||
$article2 = Article::factory()->create(['feed_id' => $route->feed_id]);
|
||||
|
|
@ -90,6 +98,7 @@ public function test_route_has_many_route_articles(): void
|
|||
|
||||
public function test_unique_constraint_prevents_duplicate_route_articles(): void
|
||||
{
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create();
|
||||
$article = Article::factory()->create(['feed_id' => $route->feed_id]);
|
||||
|
||||
|
|
@ -102,6 +111,7 @@ public function test_unique_constraint_prevents_duplicate_route_articles(): void
|
|||
|
||||
public function test_route_article_cascade_deletes_when_article_deleted(): void
|
||||
{
|
||||
/** @var RouteArticle $routeArticle */
|
||||
$routeArticle = RouteArticle::factory()->create();
|
||||
$articleId = $routeArticle->article_id;
|
||||
|
||||
|
|
@ -112,6 +122,7 @@ public function test_route_article_cascade_deletes_when_article_deleted(): void
|
|||
|
||||
public function test_route_article_cascade_deletes_when_route_deleted(): void
|
||||
{
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create();
|
||||
$article = Article::factory()->create(['feed_id' => $route->feed_id]);
|
||||
RouteArticle::factory()->forRoute($route)->create(['article_id' => $article->id]);
|
||||
|
|
@ -128,8 +139,10 @@ public function test_route_article_cascade_deletes_when_route_deleted(): void
|
|||
|
||||
public function test_route_article_belongs_to_route(): void
|
||||
{
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create();
|
||||
$article = Article::factory()->create(['feed_id' => $route->feed_id]);
|
||||
/** @var RouteArticle $routeArticle */
|
||||
$routeArticle = RouteArticle::factory()->forRoute($route)->create(['article_id' => $article->id]);
|
||||
|
||||
$loadedRoute = $routeArticle->route;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ private function mockFetchReturning(Article $article, ?string $content, ?string
|
|||
public function test_validate_sets_validated_at_on_article(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create(['feed_id' => $feed->id]);
|
||||
Keyword::factory()->active()->create([
|
||||
'feed_id' => $feed->id,
|
||||
|
|
@ -106,6 +107,7 @@ public function test_validate_skips_inactive_routes(): void
|
|||
public function test_validate_sets_pending_when_keywords_match(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create(['feed_id' => $feed->id]);
|
||||
Keyword::factory()->active()->create([
|
||||
'feed_id' => $feed->id,
|
||||
|
|
@ -125,6 +127,7 @@ public function test_validate_sets_pending_when_keywords_match(): void
|
|||
public function test_validate_sets_rejected_when_no_keywords_match(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create(['feed_id' => $feed->id]);
|
||||
Keyword::factory()->active()->create([
|
||||
'feed_id' => $feed->id,
|
||||
|
|
@ -200,6 +203,7 @@ public function test_validate_auto_approves_when_global_setting_off_and_keywords
|
|||
Setting::setBool('enable_publishing_approvals', false);
|
||||
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create(['feed_id' => $feed->id]);
|
||||
Keyword::factory()->active()->create([
|
||||
'feed_id' => $feed->id,
|
||||
|
|
@ -221,6 +225,7 @@ public function test_validate_route_auto_approve_overrides_global_setting(): voi
|
|||
Setting::setBool('enable_publishing_approvals', true);
|
||||
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'auto_approve' => true,
|
||||
|
|
@ -245,6 +250,7 @@ public function test_validate_route_auto_approve_false_overrides_global_off(): v
|
|||
Setting::setBool('enable_publishing_approvals', false);
|
||||
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'auto_approve' => false,
|
||||
|
|
@ -269,6 +275,7 @@ public function test_validate_does_not_auto_approve_rejected_articles(): void
|
|||
Setting::setBool('enable_publishing_approvals', false);
|
||||
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create(['feed_id' => $feed->id]);
|
||||
Keyword::factory()->active()->create([
|
||||
'feed_id' => $feed->id,
|
||||
|
|
@ -334,6 +341,7 @@ public function test_validate_sets_validated_at_on_route_articles(): void
|
|||
public function test_validate_keyword_matching_is_case_insensitive(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create(['feed_id' => $feed->id]);
|
||||
Keyword::factory()->active()->create([
|
||||
'feed_id' => $feed->id,
|
||||
|
|
@ -353,6 +361,7 @@ public function test_validate_keyword_matching_is_case_insensitive(): void
|
|||
public function test_validate_only_uses_active_keywords(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
/** @var Route $route */
|
||||
$route = Route::factory()->active()->create(['feed_id' => $feed->id]);
|
||||
Keyword::factory()->inactive()->create([
|
||||
'feed_id' => $feed->id,
|
||||
|
|
|
|||
Loading…
Reference in a new issue