diff --git a/app/Http/Controllers/Articles/ArticlesController.php b/app/Http/Controllers/Articles/ArticlesController.php index 920d6becf..efa3a4364 100644 --- a/app/Http/Controllers/Articles/ArticlesController.php +++ b/app/Http/Controllers/Articles/ArticlesController.php @@ -15,6 +15,7 @@ use App\Models\User; use App\Policies\ArticlePolicy; use Illuminate\Auth\Middleware\EnsureEmailIsVerified; +use Illuminate\Contracts\Database\Query\Builder; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cache; @@ -40,8 +41,15 @@ public function index(Request $request) ->take(4) ->get(); + // Grab any articles that are not pinned, or are pinned but not + // in the pinned articles collection. $articles = Article::published() - ->notPinned() + ->where(function (Builder $query) use ($pinnedArticles): void { + $query->notPinned() + ->orWhere( + fn (Builder $query): Builder => $query->pinned()->whereKeyNot($pinnedArticles->pluck('id')) + ); + }) ->{$filter}(); $tags = Tag::whereHas('articles', function ($query) { diff --git a/tests/Feature/ArticleTest.php b/tests/Feature/ArticleTest.php index d47bf7605..a40aa2848 100644 --- a/tests/Feature/ArticleTest.php +++ b/tests/Feature/ArticleTest.php @@ -4,7 +4,9 @@ use App\Models\Article; use App\Models\Tag; use App\Notifications\ArticleApprovedNotification; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Foundation\Testing\DatabaseMigrations; +use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Notification; use Tests\Feature\BrowserKitTestCase; @@ -506,3 +508,44 @@ ->see('My First Article') ->see('10 views'); }); + +test('pinned articles are included with the non-pinned article if there are more than 4 pinned articles', function () { + // Create 5 pinned, approved articles. + $pinned = Article::factory()->count(5)->create(['is_pinned' => true, 'submitted_at' => now(), 'approved_at' => now()]); + + // Create 5 non-pinned, approved articles. + $nonPinned = Article::factory()->count(5)->create(['is_pinned' => false, 'submitted_at' => now(), 'approved_at' => now()]); + + $this->visit('/articles') + ->assertViewHas('pinnedArticles', function (Collection $articles) use ($pinned): bool { + return $articles->pluck('id')->toArray() + === [ + $pinned[0]->id, + $pinned[1]->id, + $pinned[2]->id, + $pinned[3]->id, + ]; + }) + ->assertViewHas('articles', function (LengthAwarePaginator $articles) use ($nonPinned, $pinned): bool { + return $articles->pluck('id')->toArray() + === [ + $pinned[4]->id, + $nonPinned[0]->id, + $nonPinned[1]->id, + $nonPinned[2]->id, + $nonPinned[3]->id, + $nonPinned[4]->id, + ]; + }) + ->see('6 articles') + ->see($pinned[0]->title()) + ->see($pinned[1]->title()) + ->see($pinned[2]->title()) + ->see($pinned[3]->title()) + ->see($pinned[4]->title()) + ->see($nonPinned[0]->title()) + ->see($nonPinned[1]->title()) + ->see($nonPinned[2]->title()) + ->see($nonPinned[3]->title()) + ->see($nonPinned[4]->title()); +});