diff --git a/app/Console/Commands/SyncMissingQuestionHashtags.php b/app/Console/Commands/SyncMissingQuestionHashtags.php new file mode 100644 index 000000000..eb00a68eb --- /dev/null +++ b/app/Console/Commands/SyncMissingQuestionHashtags.php @@ -0,0 +1,69 @@ +argument('runtime'); + $runUntil = now()->addSeconds($runtime); + $halted = false; + + $questions = Question::query() + ->whereDoesntHave('hashtags') + ->where(fn (Builder $where): Builder => $where + ->where('content', 'like', '%#%') + ->orWhere('answer', 'like', '%#%') + ) + ->lazyByIdDesc(); + + $bar = $this->output->createProgressBar(count($questions)); + + $bar->start(); + + foreach ($questions as $question) { + if (now()->isAfter($runUntil)) { + $halted = true; + break; + } + + (new UpdateQuestionHashtags($question))->handle(); + + $bar->advance(); + } + + if ($halted) { + $this->newLine(); + $this->info('Halting process to limit runtime.'); + + return; + } + + $bar->finish(); + } +} diff --git a/tests/Console/SyncMissingQuestionHashtagsTest.php b/tests/Console/SyncMissingQuestionHashtagsTest.php new file mode 100644 index 000000000..3c02d4524 --- /dev/null +++ b/tests/Console/SyncMissingQuestionHashtagsTest.php @@ -0,0 +1,25 @@ +create(['answer' => 'has a #hashtag']); + $withoutHashtags = App\Models\Question::factory(10)->create(['answer' => 'no hashtags here']); + + Illuminate\Support\Facades\DB::table('hashtag_question')->truncate(); + + $this->artisan('app:sync-missing-hashtags')->assertSuccessful(); + + $withHashtags->load('hashtags'); + $withoutHashtags->load('hashtags'); + + expect($withHashtags->every( + fn (App\Models\Question $question): bool => $question->hashtags->pluck('name')->all() === ['hashtag']) + ) + ->toBeTrue(); + expect($withoutHashtags->every( + fn (App\Models\Question $question): bool => $question->hashtags->isEmpty()) + ) + ->toBeTrue(); +});