| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- <?php
- namespace App\Http\Controllers\Admin;
- use App\Services\WorldCup\WorldCupScheduleUpdateService;
- use Illuminate\Http\Request;
- class WorldCupScheduleController extends BaseController
- {
- private $service;
- public function __construct(WorldCupScheduleUpdateService $service)
- {
- $this->service = $service;
- }
- public function index(Request $request)
- {
- $scheduleDate = (string)$request->input('schedule_date', '');
- $matches = $scheduleDate !== ''
- ? $this->service->matchesByDate($scheduleDate)
- : $this->service->allMatches();
- return view('admin.world_cup.schedule', [
- 'scheduleDate' => $scheduleDate,
- 'matches' => $matches,
- 'result' => $request->session()->get('world_cup_schedule_update_result'),
- 'scheduleUrls' => $this->scheduleUrls(),
- ]);
- }
- public function update(Request $request)
- {
- $scheduleDate = (string)$request->input('schedule_date', '');
- $matches = $this->parseMatches($request);
- if ($matches === null) {
- $result = [
- 'success' => false,
- 'message' => 'Invalid matches payload',
- 'data' => [
- 'updated' => 0,
- 'skipped' => 0,
- 'errors' => [],
- ],
- ];
- return $this->respond($request, $result, $scheduleDate);
- }
- $result = $this->service->updateMatches($matches, $this->actor($request));
- return $this->respond($request, $result, $scheduleDate);
- }
- public function import(Request $request)
- {
- $rows = $this->parseCsvRows($request);
- $result = $rows === null
- ? [
- 'success' => false,
- 'message' => 'Invalid CSV file',
- 'data' => [
- 'updated' => 0,
- 'skipped' => 0,
- 'errors' => [],
- ],
- ]
- : $this->service->importExistingMatches($rows, $this->actor($request));
- return $this->respond($request, $result, (string)$request->input('schedule_date', ''));
- }
- private function parseMatches(Request $request): ?array
- {
- $matches = $request->input('matches');
- if (is_array($matches)) {
- return $matches;
- }
- return [];
- }
- private function respond(Request $request, array $result, string $scheduleDate)
- {
- if ($request->ajax() || $request->expectsJson() || $request->input('format') === 'json') {
- return $this->json($result['success'] ? 200 : 400, $result['message'], $result['data']);
- }
- $url = '/admin/world-cup/schedule';
- if ($scheduleDate !== '') {
- $url .= '?schedule_date=' . urlencode($scheduleDate);
- }
- return redirect($url)
- ->with('world_cup_schedule_update_result', $result);
- }
- private function actor(Request $request): string
- {
- return (string)($request->session()->get('admin.username') ?: 'admin');
- }
- private function scheduleUrls(): array
- {
- return [
- 'FIFA 官方赛程' => 'https://www.fifa.com/en/tournaments/mens/worldcup/canadamexicousa2026/articles/match-schedule-fixtures-results-teams-stadiums',
- 'FIFA 赛程更新时间公告' => 'https://vod.fifa.com/media-releases/updated-world-cup-2026-match-schedule-venues-kick-off-times-104-matches',
- '可读赛程 PDF' => 'https://www.kickoffclock.com/downloads/world-cup-2026-schedule.pdf',
- ];
- }
- private function parseCsvRows(Request $request): ?array
- {
- if (!$request->hasFile('csv_file') || !$request->file('csv_file')->isValid()) {
- return null;
- }
- $handle = fopen($request->file('csv_file')->getRealPath(), 'r');
- if ($handle === false) {
- return null;
- }
- $headers = null;
- $rows = [];
- while (($data = fgetcsv($handle)) !== false) {
- if ($headers === null) {
- $headers = $this->normalizeCsvHeaders($data);
- continue;
- }
- if ($this->isEmptyCsvRow($data)) {
- continue;
- }
- $values = array_slice(array_pad($data, count($headers), ''), 0, count($headers));
- $rows[] = array_combine($headers, $values);
- }
- fclose($handle);
- return $headers === null ? null : $rows;
- }
- private function normalizeCsvHeaders(array $headers): array
- {
- return array_map(function ($header) {
- return trim(str_replace("\xEF\xBB\xBF", '', (string)$header));
- }, $headers);
- }
- private function isEmptyCsvRow(array $row): bool
- {
- foreach ($row as $value) {
- if (trim((string)$value) !== '') {
- return false;
- }
- }
- return true;
- }
- }
|