From 7a9da2d9cbbdd72184333181e4580f5ef41dc08a Mon Sep 17 00:00:00 2001 From: johguentner Date: Sat, 9 Jul 2022 15:41:37 +0200 Subject: [PATCH 1/6] polish/fix: control over 'includeTime' of Date - introduce new methods for actively including time ('include Time') of a Date Properties within a Notion Page - existing init of value for a Date Property will force a date without time - ::valueWithTime(...) in Date Property and ->setDateTime(...) in Page will force the inclusion of time, if pushed to Notion - ! breaking: result of ::value(...) of Date Property and ->setDate(...) of Page are changing (time will not be included) --- src/Entities/Page.php | 13 ++++++++++ src/Entities/Properties/Date.php | 33 +++++++++++++++++++++++++ src/Entities/PropertyItems/RichDate.php | 17 ++++++++++--- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/Entities/Page.php b/src/Entities/Page.php index 7220671..77e6609 100644 --- a/src/Entities/Page.php +++ b/src/Entities/Page.php @@ -344,6 +344,19 @@ public function setDate(string $propertyTitle, DateTime $start, ?DateTime $end = return $this; } + /** + * @param $propertyTitle + * @param $start + * @param $end + * @return Page + */ + public function setDateTime(string $propertyTitle, DateTime $start, ?DateTime $end = null): Page + { + $this->set($propertyTitle, Date::valueWithTime($start, $end)); + + return $this; + } + /** * @param $propertyTitle * @param $relationIds diff --git a/src/Entities/Properties/Date.php b/src/Entities/Properties/Date.php index af46e64..7cfc634 100644 --- a/src/Entities/Properties/Date.php +++ b/src/Entities/Properties/Date.php @@ -26,6 +26,39 @@ public static function value(?DateTime $start, ?DateTime $end = null): Date $dateProperty = new Date(); $dateProperty->content = $richDate; + if ($richDate->isRange()) { + $dateProperty->rawContent = [ + 'date' => [ + 'start' => $start->format('Y-m-d'), + 'end' => $end->format('Y-m-d'), + ], + ]; + } else { + $dateProperty->rawContent = [ + 'date' => [ + 'start' => $start->format('Y-m-d'), + ], + ]; + } + + return $dateProperty; + } + + /** + * @param $start + * @param $end + * @return Date + */ + public static function valueWithTime(?DateTime $start, ?DateTime $end = null): Date + { + $richDate = new RichDate(); + $richDate->setStart($start); + $richDate->setEnd($end); + $richDate->setHasTime(true); + + $dateProperty = new Date(); + $dateProperty->content = $richDate; + if ($richDate->isRange()) { $dateProperty->rawContent = [ 'date' => [ diff --git a/src/Entities/PropertyItems/RichDate.php b/src/Entities/PropertyItems/RichDate.php index 81a3d18..8464938 100644 --- a/src/Entities/PropertyItems/RichDate.php +++ b/src/Entities/PropertyItems/RichDate.php @@ -11,11 +11,9 @@ */ class RichDate extends Entity { - /** - * @var string - */ protected DateTime $start; protected ?DateTime $end = null; + protected bool $hasTime = false; /** * @param array $responseData @@ -70,6 +68,14 @@ public function getEnd(): ?DateTime return $this->end; } + /** + * @return bool + */ + public function getHasTime(): bool + { + return $this->hasTime; + } + public function setStart($start): void { $this->start = $start; @@ -79,4 +85,9 @@ public function setEnd($end): void { $this->end = $end; } + + public function setHasTime($hasTime): void + { + $this->hasTime = $hasTime; + } } From 0283febdf6d85f396d255325bf0f5b9e2fdc9141 Mon Sep 17 00:00:00 2001 From: johguentner Date: Sat, 9 Jul 2022 16:38:47 +0200 Subject: [PATCH 2/6] fix test: breaking-changes in Date prop handling - change date formatting within EndointPagesTest (it_assembles_properties_for_a_new_page) - making sure to use 'Y-m-d' format instead of 'c', to match new Date Property handling --- tests/EndpointPagesTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/EndpointPagesTest.php b/tests/EndpointPagesTest.php index 20f641c..2c5d869 100644 --- a/tests/EndpointPagesTest.php +++ b/tests/EndpointPagesTest.php @@ -182,9 +182,9 @@ public function it_assembles_properties_for_a_new_page() $this->assertArrayHasKey('date', $dateRangeContent); $this->assertCount(2, $dateRangeContent['date']); $this->assertArrayHasKey('start', $dateRangeContent['date']); - $this->assertEquals($dateRangeStartValue->format('c'), $dateRangeContent['date']['start']); + $this->assertEquals($dateRangeStartValue->format('Y-m-d'), $dateRangeContent['date']['start']); $this->assertArrayHasKey('end', $dateRangeContent['date']); - $this->assertEquals($dateRangeEndValue->format('c'), $dateRangeContent['date']['end']); + $this->assertEquals($dateRangeEndValue->format('Y-m-d'), $dateRangeContent['date']['end']); // date $dateProp = $page->getProperty($dateKey); @@ -195,7 +195,7 @@ public function it_assembles_properties_for_a_new_page() $this->assertArrayHasKey('date', $dateContent); $this->assertCount(1, $dateContent['date']); $this->assertArrayHasKey('start', $dateContent['date']); - $this->assertEquals($dateValue->format('c'), $dateContent['date']['start']); + $this->assertEquals($dateValue->format('Y-m-d'), $dateContent['date']['start']); // email $this->assertTrue($this->assertContainsInstanceOf(Email::class, $properties)); From 420c0371d7a722f09c5c891435e52621800e01bc Mon Sep 17 00:00:00 2001 From: johguentner Date: Sat, 9 Jul 2022 16:45:13 +0200 Subject: [PATCH 3/6] add tests: for Date Property with forced time --- tests/EndpointPagesTest.php | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/EndpointPagesTest.php b/tests/EndpointPagesTest.php index 2c5d869..726f3be 100644 --- a/tests/EndpointPagesTest.php +++ b/tests/EndpointPagesTest.php @@ -106,9 +106,11 @@ public function it_assembles_properties_for_a_new_page() $checkboxKey = 'CheckboxProperty'; $checkboxValue = true; $dateRangeKey = 'DateRangeProperty'; + $dateTimeRangeKey = 'DateTimeRangeProperty'; $dateRangeStartValue = Carbon::now()->toDateTime(); $dateRangeEndValue = Carbon::tomorrow()->toDateTime(); $dateKey = 'DateProperty'; + $dateTimeKey = 'DateTimeProperty'; $dateValue = Carbon::yesterday()->toDateTime(); $emailKey = 'EmailProperty'; $emailValue = 'notion-is-awesome@example.org'; @@ -135,7 +137,9 @@ public function it_assembles_properties_for_a_new_page() $page->setTitle('Name', $pageTitle); $page->setCheckbox($checkboxKey, $checkboxValue); $page->setDate($dateRangeKey, $dateRangeStartValue, $dateRangeEndValue); + $page->setDateTime($dateTimeRangeKey, $dateRangeStartValue, $dateRangeEndValue); $page->setDate($dateKey, $dateValue); + $page->setDateTime($dateTimeKey, $dateValue); $page->setEmail($emailKey, $emailValue); $page->setMultiSelect($multiSelectKey, $multiSelectValues); $page->setNumber($numberKey, $numberValue); @@ -186,6 +190,28 @@ public function it_assembles_properties_for_a_new_page() $this->assertArrayHasKey('end', $dateRangeContent['date']); $this->assertEquals($dateRangeEndValue->format('Y-m-d'), $dateRangeContent['date']['end']); + + // date range (with time) + $this->assertTrue( + $this->assertContainsInstanceOf(Date::class, $properties) + ); + $dateTimeRangeProp = $page->getProperty($dateTimeRangeKey); + $this->assertInstanceOf(RichDate::class, $dateTimeRangeProp->getContent()); + $dateTimeRangeContent = $dateTimeRangeProp->getContent(); + $this->assertTrue($dateTimeRangeProp->isRange()); + $this->assertEquals($dateRangeStartValue, $dateTimeRangeProp->getStart()); + $this->assertEquals($dateRangeEndValue, $dateTimeRangeProp->getEnd()); + $this->assertJson($dateTimeRangeProp->asText()); + $this->assertStringContainsString($dateRangeStartValue->format('Y-m-d H:i:s'), $dateTimeRangeProp->asText()); + $this->assertStringContainsString($dateRangeEndValue->format('Y-m-d H:i:s'), $dateTimeRangeProp->asText()); + $dateTimeRangeContent = $dateTimeRangeProp->getRawContent(); + $this->assertArrayHasKey('date', $dateTimeRangeContent); + $this->assertCount(2, $dateTimeRangeContent['date']); + $this->assertArrayHasKey('start', $dateTimeRangeContent['date']); + $this->assertEquals($dateRangeStartValue->format('c'), $dateTimeRangeContent['date']['start']); + $this->assertArrayHasKey('end', $dateTimeRangeContent['date']); + $this->assertEquals($dateRangeEndValue->format('c'), $dateTimeRangeContent['date']['end']); + // date $dateProp = $page->getProperty($dateKey); $this->assertInstanceOf(RichDate::class, $dateProp->getContent()); @@ -197,6 +223,17 @@ public function it_assembles_properties_for_a_new_page() $this->assertArrayHasKey('start', $dateContent['date']); $this->assertEquals($dateValue->format('Y-m-d'), $dateContent['date']['start']); + // date (with time) + $dateTimeProp = $page->getProperty($dateTimeKey); + $this->assertInstanceOf(RichDate::class, $dateTimeProp->getContent()); + $this->assertFalse($dateTimeProp->isRange()); + $this->assertEquals($dateValue, $dateTimeProp->getStart()); + $dateTimeContent = $dateTimeProp->getRawContent(); + $this->assertArrayHasKey('date', $dateTimeContent); + $this->assertCount(1, $dateTimeContent['date']); + $this->assertArrayHasKey('start', $dateTimeContent['date']); + $this->assertEquals($dateValue->format('c'), $dateTimeContent['date']['start']); + // email $this->assertTrue($this->assertContainsInstanceOf(Email::class, $properties)); $mailProp = $page->getProperty($emailKey); From 85a8ff8962ba88db1a9dc340a8c3966ce273d684 Mon Sep 17 00:00:00 2001 From: Di Date: Sat, 9 Jul 2022 16:45:31 +0200 Subject: [PATCH 4/6] Apply fixes from StyleCI (#71) --- tests/EndpointPagesTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/EndpointPagesTest.php b/tests/EndpointPagesTest.php index 726f3be..376caa3 100644 --- a/tests/EndpointPagesTest.php +++ b/tests/EndpointPagesTest.php @@ -190,7 +190,6 @@ public function it_assembles_properties_for_a_new_page() $this->assertArrayHasKey('end', $dateRangeContent['date']); $this->assertEquals($dateRangeEndValue->format('Y-m-d'), $dateRangeContent['date']['end']); - // date range (with time) $this->assertTrue( $this->assertContainsInstanceOf(Date::class, $properties) From c541080e465edc06057df5a402d44a5a3eecbab2 Mon Sep 17 00:00:00 2001 From: johguentner Date: Mon, 11 Jul 2022 10:18:41 +0200 Subject: [PATCH 5/6] polish/fix: read (fetch) hasTime in date property - refactor 'isset' to Arr::exists - evaluate if time is included, based on 'T' in datetime-string (when reading a date property from Notion) - allow return of null within ->getEnd() getter (allow same in RichDate::class) - add ->hasTime() getter, which calls ->hasTime() from RichDate::class (content) - refactor ->getHasTime() from RichDate::class to ->hasTime() --- src/Entities/Properties/Date.php | 24 ++++++++++++++++++++---- src/Entities/PropertyItems/RichDate.php | 4 ++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Entities/Properties/Date.php b/src/Entities/Properties/Date.php index 7cfc634..8465ded 100644 --- a/src/Entities/Properties/Date.php +++ b/src/Entities/Properties/Date.php @@ -6,6 +6,7 @@ use FiveamCode\LaravelNotionApi\Entities\Contracts\Modifiable; use FiveamCode\LaravelNotionApi\Entities\PropertyItems\RichDate; use FiveamCode\LaravelNotionApi\Exceptions\HandlingException; +use Illuminate\Support\Arr; /** * Class Date. @@ -90,12 +91,13 @@ protected function fillDate(): void { $richDate = new RichDate(); - if (isset($this->rawContent['start'])) { + if (Arr::exists($this->rawContent, 'start')) { $startAsIsoString = $this->rawContent['start']; $richDate->setStart(new DateTime($startAsIsoString)); + $richDate->setHasTime($this->isIsoTimeString($startAsIsoString)); } - if (isset($this->rawContent['end'])) { + if (Arr::exists($this->rawContent, 'end')) { $endAsIsoString = $this->rawContent['end']; $richDate->setEnd(new DateTime($endAsIsoString)); } @@ -103,6 +105,12 @@ protected function fillDate(): void $this->content = $richDate; } + // function for checking if ISO datetime string includes time or not + private function isIsoTimeString(string $isoTimeDateString): bool + { + return strpos($isoTimeDateString, 'T') !== false; + } + /** * @return RichDate */ @@ -128,10 +136,18 @@ public function getStart(): DateTime } /** - * @return DateTime + * @return ?DateTime */ - public function getEnd(): DateTime + public function getEnd(): ?DateTime { return $this->getContent()->getEnd(); } + + /** + * @return bool + */ + public function hasTime(): bool + { + return $this->getContent()->hasTime(); + } } diff --git a/src/Entities/PropertyItems/RichDate.php b/src/Entities/PropertyItems/RichDate.php index 8464938..90371d0 100644 --- a/src/Entities/PropertyItems/RichDate.php +++ b/src/Entities/PropertyItems/RichDate.php @@ -61,7 +61,7 @@ public function getStart(): ?DateTime } /** - * @return DateTime + * @return ?DateTime */ public function getEnd(): ?DateTime { @@ -71,7 +71,7 @@ public function getEnd(): ?DateTime /** * @return bool */ - public function getHasTime(): bool + public function hasTime(): bool { return $this->hasTime; } From 0a07217d4b048fd024a7bc80a387c4e88baa7a25 Mon Sep 17 00:00:00 2001 From: johguentner Date: Mon, 11 Jul 2022 10:21:11 +0200 Subject: [PATCH 6/6] modify tests: evaluate 'hasTime' in date props - add date with and without time in page response stub - assert true and false, if time is included - add these two additional properties within assert count of page results --- tests/EndpointPagesTest.php | 16 +++++++++++++--- .../endpoints/pages/response_specific_200.json | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/tests/EndpointPagesTest.php b/tests/EndpointPagesTest.php index 376caa3..cd33a19 100644 --- a/tests/EndpointPagesTest.php +++ b/tests/EndpointPagesTest.php @@ -69,9 +69,13 @@ public function it_returns_page_entity_with_filled_properties() // check properties $this->assertSame('Notion Is Awesome', $pageResult->getTitle()); $this->assertSame('page', $pageResult->getObjectType()); - $this->assertCount(7, $pageResult->getRawProperties()); - $this->assertCount(7, $pageResult->getProperties()); - $this->assertCount(7, $pageResult->getPropertyKeys()); + $this->assertCount(9, $pageResult->getRawProperties()); + $this->assertCount(9, $pageResult->getProperties()); + $this->assertCount(9, $pageResult->getPropertyKeys()); + + // check date and datetime properties + $this->assertTrue($pageResult->getProperty('DateWithTime')->hasTime()); + $this->assertFalse($pageResult->getProperty('DateWithoutTime')->hasTime()); $this->assertInstanceOf(Carbon::class, $pageResult->getCreatedTime()); $this->assertInstanceOf(Carbon::class, $pageResult->getLastEditedTime()); @@ -179,6 +183,7 @@ public function it_assembles_properties_for_a_new_page() $this->assertTrue($dateRangeProp->isRange()); $this->assertEquals($dateRangeStartValue, $dateRangeProp->getStart()); $this->assertEquals($dateRangeEndValue, $dateRangeProp->getEnd()); + $this->assertFalse($dateRangeProp->hasTime()); $this->assertJson($dateRangeProp->asText()); $this->assertStringContainsString($dateRangeStartValue->format('Y-m-d H:i:s'), $dateRangeProp->asText()); $this->assertStringContainsString($dateRangeEndValue->format('Y-m-d H:i:s'), $dateRangeProp->asText()); @@ -200,6 +205,7 @@ public function it_assembles_properties_for_a_new_page() $this->assertTrue($dateTimeRangeProp->isRange()); $this->assertEquals($dateRangeStartValue, $dateTimeRangeProp->getStart()); $this->assertEquals($dateRangeEndValue, $dateTimeRangeProp->getEnd()); + $this->assertTrue($dateTimeRangeProp->hasTime()); $this->assertJson($dateTimeRangeProp->asText()); $this->assertStringContainsString($dateRangeStartValue->format('Y-m-d H:i:s'), $dateTimeRangeProp->asText()); $this->assertStringContainsString($dateRangeEndValue->format('Y-m-d H:i:s'), $dateTimeRangeProp->asText()); @@ -216,6 +222,8 @@ public function it_assembles_properties_for_a_new_page() $this->assertInstanceOf(RichDate::class, $dateProp->getContent()); $this->assertFalse($dateProp->isRange()); $this->assertEquals($dateValue, $dateProp->getStart()); + $this->assertNull($dateProp->getEnd()); + $this->assertFalse($dateProp->hasTime()); $dateContent = $dateProp->getRawContent(); $this->assertArrayHasKey('date', $dateContent); $this->assertCount(1, $dateContent['date']); @@ -227,6 +235,8 @@ public function it_assembles_properties_for_a_new_page() $this->assertInstanceOf(RichDate::class, $dateTimeProp->getContent()); $this->assertFalse($dateTimeProp->isRange()); $this->assertEquals($dateValue, $dateTimeProp->getStart()); + $this->assertNull($dateTimeProp->getEnd()); + $this->assertTrue($dateTimeProp->hasTime()); $dateTimeContent = $dateTimeProp->getRawContent(); $this->assertArrayHasKey('date', $dateTimeContent); $this->assertCount(1, $dateTimeContent['date']); diff --git a/tests/stubs/endpoints/pages/response_specific_200.json b/tests/stubs/endpoints/pages/response_specific_200.json index 0dac766..268e117 100644 --- a/tests/stubs/endpoints/pages/response_specific_200.json +++ b/tests/stubs/endpoints/pages/response_specific_200.json @@ -40,6 +40,24 @@ } ] }, + "DateWithTime":{ + "id": ">d{D", + "type": "date", + "date": { + "start": "2021-05-14T00:00:00.000+00:00", + "end": "2021-06-14T00:00:00.000+00:00", + "time_zone": null + } + }, + "DateWithoutTime":{ + "id": ">c{d", + "type": "date", + "date": { + "start": "2021-05-14", + "end": "2021-06-14", + "time_zone": null + } + }, "SelectColumn": { "id": "nKff", "type": "select",