httpClient = new Client([ 'timeout' => 30, 'headers' => [ 'User-Agent' => 'MediaCollector/1.0', 'Authorization' => 'Bearer ' . $source['api_key'] ] ]); $this->apiKey = $source['api_key']; $this->baseUrl = rtrim($source['api_url'] ?? 'https://api.exophase.com', '/'); } protected function executeSync(string $syncType): void { if (empty($this->apiKey)) { throw new Exception('Exophase API key not configured'); } $this->logProgress('Starting Exophase gaming data sync...'); // Sync games from all supported platforms $this->syncGames(); $this->logProgress("Processed {$this->processedCount} Exophase gaming items"); } private function syncGames(): void { try { $games = $this->getExophaseGames(); foreach ($games as $gameData) { $this->syncGame($gameData); $this->processedCount++; } } catch (Exception $e) { $this->logProgress('Error syncing games: ' . $e->getMessage()); } } private function getExophaseGames(): array { try { // Exophase API endpoint for user's games $response = $this->httpClient->get("{$this->baseUrl}/v1/user/games"); $data = json_decode($response->getBody(), true); if (!isset($data['games'])) { throw new Exception('No games found in Exophase'); } return $data['games']; } catch (Exception $e) { throw new Exception('Failed to fetch Exophase games: ' . $e->getMessage()); } } private function syncGame(array $gameData): void { $gameModel = new Game($this->pdo); // Check if game already exists $existingGame = $gameModel->findAll([ 'source_id' => $this->sourceId ]); // Find existing game by platform-specific ID or title foreach ($existingGame as $game) { $metadata = json_decode($game['metadata'], true); if (isset($metadata['exophase_game_id']) && $metadata['exophase_game_id'] === $gameData['id']) { $existingGame = [$game]; break; } } $gameData = [ 'title' => $gameData['title'] ?: 'Untitled Game', 'game_key' => Game::generateGameKey($gameData['title'], $gameData['platform'] ?? null), 'platform' => $this->mapPlatform($gameData['platform'] ?? 'unknown'), 'playtime_minutes' => $gameData['playtime_minutes'] ?? 0, 'completion_percentage' => $gameData['completion_percentage'] ?? 0, 'source_id' => $this->sourceId, 'last_played_at' => isset($gameData['last_played']) ? date('Y-m-d H:i:s', strtotime($gameData['last_played'])) : null, 'metadata' => json_encode([ 'exophase_game_id' => $gameData['id'], 'exophase_platform' => $gameData['platform'] ?? null, 'achievements_earned' => $gameData['achievements_earned'] ?? 0, 'achievements_total' => $gameData['achievements_total'] ?? 0, 'trophies_earned' => $gameData['trophies_earned'] ?? 0, 'trophies_total' => $gameData['trophies_total'] ?? 0, 'gamerscore_earned' => $gameData['gamerscore_earned'] ?? 0, 'gamerscore_total' => $gameData['gamerscore_total'] ?? 0, 'last_achievement' => $gameData['last_achievement'] ?? null, 'first_achievement' => $gameData['first_achievement'] ?? null, 'rating' => $gameData['rating'] ?? null, 'genre' => $gameData['genre'] ?? null, 'developer' => $gameData['developer'] ?? null, 'publisher' => $gameData['publisher'] ?? null, 'release_date' => $gameData['release_date'] ?? null ]) ]; if (empty($existingGame)) { $gameModel->create($gameData); $this->newCount++; } else { $gameModel->update($existingGame[0]['id'], $gameData); $this->updatedCount++; } } private function mapPlatform(string $platform): string { $platformMap = [ 'steam' => 'PC', 'psn' => 'PlayStation', 'ps4' => 'PlayStation 4', 'ps5' => 'PlayStation 5', 'xbox' => 'Xbox', 'xbox360' => 'Xbox 360', 'xboxone' => 'Xbox One', 'xboxseries' => 'Xbox Series X/S', 'nintendo' => 'Nintendo', 'switch' => 'Nintendo Switch', 'epic' => 'Epic Games', 'gog' => 'GOG', 'origin' => 'Origin', 'uplay' => 'Ubisoft Connect', 'battlenet' => 'Battle.net' ]; return $platformMap[$platform] ?? ucfirst($platform); } protected function getProcessedCount(): int { return $this->processedCount; } protected function getNewCount(): int { return $this->newCount; } protected function getUpdatedCount(): int { return $this->updatedCount; } protected function getDeletedCount(): int { return 0; // Exophase doesn't provide deletion info in this context } }