BannerVisibilityService.php 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. <?php
  2. namespace App\Services;
  3. use App\Models\Banner;
  4. use Illuminate\Support\Facades\DB;
  5. class BannerVisibilityService
  6. {
  7. /** Positive numeric links are activity IDs; empty/zero and other links are unbound. */
  8. public static function activityId($link): ?string
  9. {
  10. $link = trim((string) $link);
  11. if ($link === '' || !ctype_digit($link)) {
  12. return null;
  13. }
  14. $id = ltrim($link, '0');
  15. return $id === '' ? null : $id;
  16. }
  17. /** Compute display state without overwriting the operator's manual setting. */
  18. public static function decorate(iterable $banners, ?int $now = null): array
  19. {
  20. $now = $now ?? time();
  21. $items = [];
  22. $activityIds = [];
  23. foreach ($banners as $banner) {
  24. $item = $banner instanceof Banner ? $banner->toArray() : $banner;
  25. $item['status'] = (int) $item['status'];
  26. $item['activity_id'] = self::activityId($item['link'] ?? null);
  27. if ($item['activity_id'] !== null) {
  28. $activityIds[$item['activity_id']] = $item['activity_id'];
  29. }
  30. $items[] = $item;
  31. }
  32. // Read raw timestamps; ActivityReward's date accessors discard the time of day.
  33. $activities = empty($activityIds) ? collect() : DB::table('activity_rewards')
  34. ->whereIn('id', array_values($activityIds))
  35. ->get(['id', 'status', 'start_time', 'end_time'])->keyBy('id');
  36. foreach ($items as &$item) {
  37. $activity = $item['activity_id'] === null ? null : $activities->get($item['activity_id']);
  38. $reason = null;
  39. if ($item['status'] !== 1) {
  40. $reason = 'manual';
  41. } elseif ($item['activity_id'] !== null) {
  42. if ($activity === null) {
  43. $reason = 'activity_missing';
  44. } elseif ((int) $activity->status !== 1) {
  45. $reason = 'activity_offline';
  46. } elseif ((int) $activity->start_time > $now) {
  47. $reason = 'activity_not_started';
  48. } elseif ((int) $activity->end_time <= $now) {
  49. $reason = 'activity_ended';
  50. }
  51. }
  52. $item['effective_status'] = $reason === null ? 1 : 0;
  53. $item['offline_reason'] = $reason;
  54. }
  55. unset($item);
  56. return $items;
  57. }
  58. }