Skip to content

Instantly share code, notes, and snippets.

@n1215
Created November 21, 2019 06:21
Show Gist options
  • Save n1215/5c2640c68b52a30f1e6940e745224280 to your computer and use it in GitHub Desktop.
Save n1215/5c2640c68b52a30f1e6940e745224280 to your computer and use it in GitHub Desktop.
Laravel Middleware for time travel debugging
<?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