Skip to content

Commit 49f5115

Browse files
authored
Slow queries fix and article improvements (#1354)
1 parent cb7d95b commit 49f5115

File tree

10 files changed

+54
-116
lines changed

10 files changed

+54
-116
lines changed

app/Http/Controllers/Articles/ArticlesController.php

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,30 +45,27 @@ public function index(Request $request)
4545
->latest('approved_at')
4646
->{$filter}();
4747

48-
$tags = Tag::whereHas('articles', function ($query) {
49-
$query->published();
50-
})->orderBy('name')->get();
48+
$tags = Tag::whereHas('articles', fn ($query) => $query->published())
49+
->orderBy('name')
50+
->get();
5151

5252
if ($activeTag = Tag::where('slug', $request->tag)->first()) {
5353
$articles->forTag($activeTag->slug());
5454
}
5555

56-
$moderators = Cache::remember('moderators', now()->addMinutes(30), function () {
57-
return User::moderators()->get();
58-
});
59-
6056
$canonical = canonical('articles', ['filter' => $filter, 'tag' => $activeTag?->slug()]);
61-
$topAuthors = Cache::remember('topAuthors', now()->addMinutes(30), function () {
62-
return User::mostSubmissionsInLastDays(365)->take(5)->get();
63-
});
57+
$topAuthors = Cache::remember(
58+
'topAuthors',
59+
now()->addMinutes(30),
60+
fn () => User::mostSubmissionsInLastDays(365)->take(5)->get()
61+
);
6462

6563
return view('articles.overview', [
6664
'pinnedArticles' => $pinnedArticles,
6765
'articles' => $articles->paginate(10),
6866
'tags' => $tags,
6967
'activeTag' => $activeTag,
7068
'filter' => $filter,
71-
'moderators' => $moderators,
7269
'canonical' => $canonical,
7370
'topAuthors' => $topAuthors,
7471
]);
@@ -155,7 +152,7 @@ public function update(ArticleRequest $request, Article $article)
155152

156153
$article = $article->fresh();
157154

158-
if ($wasNotPreviouslySubmitted && $request->shouldBeSubmitted()) {
155+
if ($wasNotPreviouslySubmitted && $request->shouldBeSubmitted() && $article->isNotApproved()) {
159156
$this->success('Thank you for submitting, unfortunately we can\'t accept every submission. You\'ll only hear back from us when we accept your article.');
160157
} else {
161158
$this->success('Article successfully updated!');

app/Http/Controllers/HomeController.php

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,34 @@ class HomeController extends Controller
1313
{
1414
public function show()
1515
{
16-
$communityMembers = Cache::remember('communityMembers', now()->addMinutes(5), function () {
17-
return User::withCounts()
18-
->hasActivity()
19-
->notBanned()
20-
->inRandomOrder()
21-
->take(100)
22-
->get()
23-
->chunk(20);
24-
});
16+
$communityMembers = Cache::remember(
17+
'communityMembers',
18+
now()->addMinutes(5),
19+
fn () => User::notBanned()->inRandomOrder()->take(100)->get()->chunk(20)
20+
);
2521

26-
$totalUsers = Cache::remember('totalUsers', now()->addDay(), function () {
27-
return number_format(User::notBanned()->count());
28-
});
22+
$totalUsers = Cache::remember('totalUsers', now()->addDay(), fn () => number_format(User::notBanned()->count()));
2923

30-
$totalThreads = Cache::remember('totalThreads', now()->addDay(), function () {
31-
return number_format(Thread::count());
32-
});
24+
$totalThreads = Cache::remember('totalThreads', now()->addDay(), fn () => number_format(Thread::count()));
3325

34-
$totalReplies = Cache::remember('totalReplies', now()->addDay(), function () {
35-
return number_format(Reply::count());
36-
});
26+
$totalReplies = Cache::remember('totalReplies', now()->addDay(), fn () => number_format(Reply::count()));
3727

38-
$latestThreads = Cache::remember('latestThreads', now()->addHour(), function () {
39-
return Thread::whereNull('solution_reply_id')
28+
$latestThreads = Cache::remember(
29+
'latestThreads',
30+
now()->addHour(),
31+
fn () => Thread::whereNull('solution_reply_id')
4032
->whereBetween('threads.created_at', [now()->subMonth(), now()])
4133
->unlocked()
4234
->inRandomOrder()
4335
->limit(3)
44-
->get();
45-
});
36+
->get()
37+
);
4638

47-
$latestArticles = Cache::remember('latestArticles', now()->addHour(), function () {
48-
return Article::published()
49-
->recent()
50-
->limit(4)
51-
->get();
52-
});
39+
$latestArticles = Cache::remember(
40+
'latestArticles',
41+
now()->addHour(),
42+
fn () => Article::published()->recent()->limit(4)->get()
43+
);
5344

5445
return view('home', [
5546
'communityMembers' => $communityMembers,

app/Jobs/CreateArticle.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,6 @@ public function handle(): void
6969

7070
private function canBeAutoApproved(): bool
7171
{
72-
return $this->shouldBeSubmitted && $this->author->canVerifiedAuthorPublishMoreArticleToday();
72+
return $this->shouldBeSubmitted && $this->author->canVerifiedAuthorPublishMoreArticlesToday();
7373
}
7474
}

app/Jobs/UpdateArticle.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,12 @@ public function handle(): void
5353

5454
if ($this->shouldUpdateSubmittedAt()) {
5555
$this->article->submitted_at = now();
56+
$this->article->approved_at = $this->canBeAutoApproved() ? now() : null;
5657
$this->article->save();
5758

58-
event(new ArticleWasSubmittedForApproval($this->article));
59+
if ($this->article->isAwaitingApproval()) {
60+
event(new ArticleWasSubmittedForApproval($this->article));
61+
}
5962
}
6063

6164
$this->article->syncTags($this->tags);
@@ -69,4 +72,9 @@ private function shouldUpdateSubmittedAt(): bool
6972
{
7073
return $this->shouldBeSubmitted && $this->article->isNotSubmitted();
7174
}
75+
76+
private function canBeAutoApproved(): bool
77+
{
78+
return $this->article->author()->canVerifiedAuthorPublishMoreArticlesToday();
79+
}
7280
}

app/Models/Article.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ public function isShared(): bool
196196

197197
public function isAwaitingApproval(): bool
198198
{
199-
return $this->isSubmitted() && $this->isNotApproved() && $this->isNotDeclined() && ! $this->author()->canVerifiedAuthorPublishMoreArticleToday();
199+
return $this->isSubmitted() && $this->isNotApproved() && $this->isNotDeclined();
200200
}
201201

202202
public function isNotAwaitingApproval(): bool

app/Models/User.php

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ public function isVerifiedAuthor(): bool
317317
return ! is_null($this->author_verified_at) || $this->isAdmin();
318318
}
319319

320-
public function canVerifiedAuthorPublishMoreArticleToday(): bool
320+
public function canVerifiedAuthorPublishMoreArticlesToday(): bool
321321
{
322322
if ($this->isAdmin()) {
323323
return true;
@@ -364,13 +364,19 @@ public function scopeMostSolutions(Builder $query, ?int $inLastDays = null)
364364

365365
public function scopeMostSubmissions(Builder $query, ?int $inLastDays = null)
366366
{
367-
return $query->withCount(['articles as articles_count' => function ($query) use ($inLastDays) {
368-
if ($inLastDays) {
369-
$query->where('articles.approved_at', '>', now()->subDays($inLastDays));
370-
}
367+
return $query
368+
->selectRaw('users.*, COUNT(DISTINCT articles.id) AS articles_count')
369+
->join('articles', 'articles.author_id', '=', 'users.id')
370+
->where(function ($query) use ($inLastDays) {
371+
if ($inLastDays) {
372+
$query->where('articles.approved_at', '>', now()->subDays($inLastDays));
373+
}
371374

372-
return $query;
373-
}])->orderBy('articles_count', 'desc');
375+
return $query;
376+
})
377+
->groupBy('users.id')
378+
->having('articles_count', '>', 0)
379+
->orderBy('articles_count', 'desc');
374380
}
375381

376382
public function scopeMostSolutionsInLastDays(Builder $query, int $days)
@@ -397,26 +403,6 @@ public function toSearchableArray(): array
397403
];
398404
}
399405

400-
public function scopeWithCounts(Builder $query)
401-
{
402-
return $query->withCount([
403-
'threadsRelation as threads_count',
404-
'replyAble as replies_count',
405-
'replyAble as solutions_count' => function (Builder $query) {
406-
return $query->join('threads', 'threads.solution_reply_id', '=', 'replies.id')
407-
->where('replyable_type', 'threads');
408-
},
409-
]);
410-
}
411-
412-
public function scopeHasActivity(Builder $query)
413-
{
414-
return $query->where(function ($query) {
415-
$query->has('threadsRelation')
416-
->orHas('replyAble');
417-
});
418-
}
419-
420406
public function scopeModerators(Builder $query)
421407
{
422408
return $query->whereIn('type', [

resources/css/app.css

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,6 @@ svg .secondary {
103103
@apply outline-hidden bg-gray-100;
104104
}
105105

106-
.member:after {
107-
bottom: -1rem;
108-
content: ' ';
109-
display: block;
110-
left: 7rem;
111-
position: absolute;
112-
border-color: #f9fafb transparent transparent transparent;
113-
border-style: solid;
114-
border-width: 0.5rem;
115-
}
116-
117106
/** Choices.js **/
118107
.choices__input.choices__input--cloned {
119108
@apply hidden;

resources/views/components/community-member.blade.php

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
11
<div class="shrink-0 mr-8 my-2 cursor-pointer">
2-
<x-stat-popout
3-
x-cloak
4-
x-show="active == '{{ $member->id }}'"
5-
class="w-64 absolute -mt-40 -ml-20"
6-
:user="$member"
7-
/>
8-
92
<x-avatar
103
:user="$member"
11-
class="inset-0"
4+
class="inset-0 hover:scale-120 transition-transform duration-300 ease-in-out"
125
x-on:mouseover="active = {{ $member->id }}"
136
x-on:mouseout="active = false"
147
size="xl"

resources/views/components/stat-popout.blade.php

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,6 @@
33
])
44

55
<div {{ $attributes->merge(['class' => 'member w-64 shadow-xl rounded-sm']) }}>
6-
<div class="flex justify-between border-b border-gray-200 p-3 bg-white rounded-t">
7-
<div class="flex flex-col items-center text-lio-500 text-center">
8-
<span class="flex min-w-8 h-8 px-2 bg-lio-100 font-bold rounded-sm items-center justify-center mb-1.5">
9-
{{ $user->solutions_count }}
10-
</span>
11-
12-
<span class="text-sm">Solutions</span>
13-
</div>
14-
15-
<div class="flex flex-col items-center text-lio-500 text-center">
16-
<span class="flex min-w-8 h-8 px-2 bg-lio-100 font-bold rounded-sm items-center justify-center mb-1.5">
17-
{{ $user->threads_count }}
18-
</span>
19-
20-
<span class="text-sm">Threads</span>
21-
</div>
22-
23-
<div class="flex flex-col items-center text-lio-500 text-center">
24-
<span class="flex min-w-8 h-8 px-2 bg-lio-100 font-bold rounded-sm items-center justify-center mb-1.5">
25-
{{ $user->replies_count }}
26-
</span>
27-
28-
<span class="text-sm">Replies</span>
29-
</div>
30-
</div>
31-
326
<div class="flex flex-col bg-gray-100 p-3 text-sm rounded-b">
337
<span>{{ $user->username() }}</span>
348

tests/Feature/ArticleTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@
594594
'submitted_at' => now()->addMinutes(1), // after verification
595595
]);
596596

597-
expect($author->canVerifiedAuthorPublishMoreArticleToday())->toBeFalse();
597+
expect($author->canVerifiedAuthorPublishMoreArticlesToday())->toBeFalse();
598598
});
599599

600600
test('verified authors skip the approval message when submitting new article', function () {

0 commit comments

Comments
 (0)