From 51e358cbfde8a8fb5993b1fd88a7b08d42abfb7b Mon Sep 17 00:00:00 2001 From: Italo Date: Fri, 17 Dec 2021 12:23:31 -0300 Subject: [PATCH] [8.x] Adds datetime parsing to `Request` instance (#39945) * Parses datetime from request input. * Fixes style and tests. * Adds support for default value (like "now"). * Style fixes. * Removes default and adds false to invalid datetimes. * Stabilize returns types when dealing with invalid dates. * Minor test formatting to push tests on GitHub. * Shortened function name to `date()`. * Restores exception handling. Trust your instincts. * Style fixes and method fixes. * formatting * Style fixes. Co-authored-by: Taylor Otwell --- .../Http/Concerns/InteractsWithInput.php | 22 ++++++++ tests/Http/HttpRequestTest.php | 51 +++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/src/Illuminate/Http/Concerns/InteractsWithInput.php b/src/Illuminate/Http/Concerns/InteractsWithInput.php index 8685318c1236..a2c18ca0b250 100644 --- a/src/Illuminate/Http/Concerns/InteractsWithInput.php +++ b/src/Illuminate/Http/Concerns/InteractsWithInput.php @@ -4,6 +4,7 @@ use Illuminate\Http\UploadedFile; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\Date; use SplFileInfo; use stdClass; use Symfony\Component\VarDumper\VarDumper; @@ -296,6 +297,27 @@ public function boolean($key = null, $default = false) return filter_var($this->input($key, $default), FILTER_VALIDATE_BOOLEAN); } + /** + * Retrieve input from the request as a Carbon instance. + * + * @param string $key + * @param string|null $format + * @param string|null $tz + * @return \Illuminate\Support\Carbon|null + */ + public function date($key, $format = null, $tz = null) + { + if ($this->isNotFilled($key)) { + return null; + } + + if (is_null($format)) { + return Date::parse($this->input($key), $tz); + } + + return Date::createFromFormat($format, $this->input($key), $tz); + } + /** * Retrieve input from the request as a collection. * diff --git a/tests/Http/HttpRequestTest.php b/tests/Http/HttpRequestTest.php index f32db433d386..3a82b0a2cdf9 100644 --- a/tests/Http/HttpRequestTest.php +++ b/tests/Http/HttpRequestTest.php @@ -6,7 +6,9 @@ use Illuminate\Http\UploadedFile; use Illuminate\Routing\Route; use Illuminate\Session\Store; +use Illuminate\Support\Carbon; use Illuminate\Support\Collection; +use InvalidArgumentException; use Mockery as m; use PHPUnit\Framework\TestCase; use RuntimeException; @@ -532,6 +534,55 @@ public function testCollectMethod() $this->assertEquals(['users' => [1, 2, 3], 'roles' => [4, 5, 6], 'foo' => ['bar', 'baz'], 'email' => 'test@example.com'], $request->collect()->all()); } + public function testDateMethod() + { + $request = Request::create('/', 'GET', [ + 'as_null' => null, + 'as_invalid' => 'invalid', + + 'as_datetime' => '20-01-01 16:30:25', + 'as_format' => '1577896225', + 'as_timezone' => '20-01-01 13:30:25', + + 'as_date' => '2020-01-01', + 'as_time' => '16:30:25', + ]); + + $current = Carbon::create(2020, 1, 1, 16, 30, 25); + + $this->assertNull($request->date('as_null')); + $this->assertNull($request->date('doesnt_exists')); + + $this->assertEquals($current, $request->date('as_datetime')); + $this->assertEquals($current, $request->date('as_format', 'U')); + $this->assertEquals($current, $request->date('as_timezone', null, 'America/Santiago')); + + $this->assertTrue($request->date('as_date')->isSameDay($current)); + $this->assertTrue($request->date('as_time')->isSameSecond('16:30:25')); + } + + public function testDateMethodExceptionWhenValueInvalid() + { + $this->expectException(InvalidArgumentException::class); + + $request = Request::create('/', 'GET', [ + 'date' => 'invalid', + ]); + + $request->date('date'); + } + + public function testDateMethodExceptionWhenFormatInvalid() + { + $this->expectException(InvalidArgumentException::class); + + $request = Request::create('/', 'GET', [ + 'date' => '20-01-01 16:30:25', + ]); + + $request->date('date', 'invalid_format'); + } + public function testArrayAccess() { $request = Request::create('/', 'GET', ['name' => null, 'foo' => ['bar' => null, 'baz' => '']]);