<?php
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Routing\RouterInterface;
use App\Entity\GameInfo;
class FrontendApiSubscriber implements EventSubscriberInterface
{
private $em;
private $parameter;
private $router;
public function __construct(ManagerRegistry $doctrine, ParameterBagInterface $parameterBag, RouterInterface $router)
{
$this->em = $doctrine->getManager();
$this->parameter = $parameterBag;
$this->router = $router;
}
public function onKernelRequest(RequestEvent $event): void
{
// 1. 防呆:確保只處理主請求 (Main Request)
if (!$event->isMainRequest()) {
return;
}
$request = $event->getRequest();
$pathInfo = $request->getPathInfo();
// 2. 排除後台 (假設後台路由以 /admin 開頭)
if (str_starts_with($pathInfo, '/admin')) {
return;
}
// 排除開發者工具
if (str_starts_with($pathInfo, '/_profiler') || str_starts_with($pathInfo, '/_wdt')) {
return;
}
// ==========================================
// 這裡寫你的 Frontend 和 API 的專屬邏輯
// ==========================================
// 取得 _route,如果找不到 (例如 404 找不到網頁時),預設給個空字串避免報錯
$_route = $request->attributes->get('_route', '');
// check game info
$repository = $this->em->getRepository(GameInfo::class);
$gameInfo = $repository->findOneBy(
array('name' => $this->parameter->get('info_name'))
);
if ($gameInfo) {
$current = new \DateTime(date('Y-m-d H:i:s'));
$startDate = $gameInfo->getStartDate();
$endDate = $gameInfo->getEndDate();
$prizeEndDate = $gameInfo->getPrizeRedeemEndDate();
if ($current < $startDate || ($current > $endDate && $current > $prizeEndDate)) { // all route redirect to index
if (strpos($_route, 'game_pre_index') !== false || strpos($_route, 'game_pre_checkAgent') !== false) {
return;
} else {
if (strpos($_route, 'game_activity_rule') !== false) {
return;
}
// 2. 使用注入的 router 產生網址 (如果有參數可以放在第二個陣列)
$url = $this->router->generate('game_pre_checkAgent');
// 3. 建立轉址回應物件
$response = new RedirectResponse($url);
// 4. 將回應塞給事件 (Symfony 收到後會立刻中斷後續的 Controller 執行並直接轉址)
$event->setResponse($response);
// 5. (非強制,但建議) 停止事件繼續傳播給其他優先權較低的 Listener
$event->stopPropagation();
return;
}
}
}
// check route
$session = $request->getSession();
if (strpos($_route, 'game_frontend_mission') !== false || strpos($_route, 'app_frontend_question') !== false ||
strpos($_route, 'app_frontend_prize_list') !== false || strpos($_route, 'app_frontend_prize_detail') !== false) {
$session->set('target', $_route);
$session->set('target_param', $this->router->getContext()->getQueryString());
} else if (strpos($_route, 'ctm_game_helpValid') !== false) {
$channel = $event->getRequest()->attributes->get('_route_params')["channel"];
$hash = $event->getRequest()->attributes->get('_route_params')["hash"];
$session->set('target', $_route);
$session->set('target_channel', $channel);
$session->set('target_hash', $hash);
$session->set('target_param', $this->router->getContext()->getQueryString());
}
return;
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => 'onKernelRequest',
];
}
}