Created
November 21, 2019 06:21
-
-
Save n1215/5c2640c68b52a30f1e6940e745224280 to your computer and use it in GitHub Desktop.
Laravel Middleware for time travel debugging
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace App\Http\Middleware; | |
use Carbon\Carbon; | |
use Closure; | |
use Exception; | |
use Illuminate\Http\Request; | |
use Symfony\Component\HttpFoundation\Cookie; | |
use Symfony\Component\HttpFoundation\Response; | |
/** | |
* Class TimeTravel | |
* | |
* \Illuminate\Session\Middleware\StartSessionより内側に配置する | |
* | |
* @package App\Http\Middleware | |
*/ | |
class TimeTravel | |
{ | |
/** | |
* クエリとCookieのキー | |
*/ | |
private const DATETIME_KEY= 'time_travel'; | |
/** | |
* Handle an incoming request. | |
* | |
* @param Request $request | |
* @param Closure $next | |
* @return mixed | |
*/ | |
public function handle(Request $request, Closure $next) | |
{ | |
if (app()->environment('production') || !config('app.debug')) { | |
return $next($request); | |
} | |
if ($this->shouldReset($request)) { | |
return $this->handleReset($request, $next); | |
} | |
$fakeDateTime = $this->extractFakeDateTime($request); | |
if ($fakeDateTime === null) { | |
return $next($request); | |
} | |
$originalDateTime = Carbon::now(); | |
info( | |
'start time traveling: ' | |
. $originalDateTime->format('Y-m-d H:i:s') | |
.' -> ' | |
. $fakeDateTime->format('Y-m-d H:i:s') | |
); | |
Carbon::setTestNow($fakeDateTime); | |
/** @var Response $response */ | |
$response = $next($request); | |
Carbon::setTestNow(); | |
info( | |
'end time traveling: ' | |
. $fakeDateTime->format('Y-m-d H:i:s') | |
.' -> ' | |
. $originalDateTime->format('Y-m-d H:i:s') | |
); | |
// Cookieに記憶 | |
$response->headers->setCookie(new Cookie( | |
self::DATETIME_KEY, | |
$fakeDateTime->format('Y-m-d\TH:i:s'), | |
$originalDateTime->copy()->addMinutes(config()->get('session.lifetime')), | |
config()->get('session.path'), | |
config()->get('session.domain'), | |
config()->get('session.secure'), | |
config()->get('session.http_only'), | |
false, | |
config()->get('session.same_site') | |
)); | |
return $response; | |
} | |
/** | |
* @param Request $request | |
* @return bool | |
*/ | |
private function shouldReset(Request $request): bool | |
{ | |
$dateTimeString = $request->query(self::DATETIME_KEY); | |
return $dateTimeString === 'off'; | |
} | |
/** | |
* 時間を元に戻す | |
* @param Request $request | |
* @param Closure $next | |
* @return Response | |
*/ | |
private function handleReset(Request $request, Closure $next) | |
{ | |
/** @var Response $response */ | |
$response = $next($request); | |
$response->headers->clearCookie(self::DATETIME_KEY); | |
return $response; | |
} | |
/** | |
* @param Request $request | |
* @return Carbon|null | |
*/ | |
private function extractFakeDateTime(Request $request): ?Carbon | |
{ | |
$dateTimeString = $request->query(self::DATETIME_KEY); | |
if ($dateTimeString !== null) { | |
try { | |
return new Carbon($dateTimeString); | |
} catch (Exception $e) { | |
} | |
} | |
$dateTimeStringInCookie = $request->cookie(self::DATETIME_KEY); | |
if ($dateTimeStringInCookie !== null) { | |
try { | |
return new Carbon($dateTimeStringInCookie); | |
} catch (Exception $e) { | |
return null; | |
} | |
} | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment