limitOption(); if ($limit === false) { $this->error('The --limit option must be an integer greater than zero.'); return self::FAILURE; } $query = $this->eligibleUsersQuery(); if ($this->option('dry-run')) { $this->info("{$query->count()} eligible user(s) found."); return self::SUCCESS; } $sent = 0; foreach ($query->lazyById(100) as $user) { if ($limit !== null && $sent >= $limit) { break; } $user->notify( new EngagementReminderNotification(EngagementReminderNotification::randomMessageKey()), ); $sent++; } $this->info("{$sent} engagement reminder notification(s) sent."); return self::SUCCESS; } private function eligibleUsersQuery(): Builder { return User::query() ->select(['id', 'locale', 'suspended_at']) ->whereNull('suspended_at') ->whereHas('deviceTokens') ->whereDoesntHave('mealPosts', fn (Builder $query): Builder => $query ->where('created_at', '>=', now()->subDay())); } private function limitOption(): int|false|null { $limit = $this->option('limit'); if ($limit === null || $limit === '') { return null; } return filter_var($limit, FILTER_VALIDATE_INT, [ 'options' => ['min_range' => 1], ]); } }