-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add relation database property (#150)
- Loading branch information
1 parent
71ddb61
commit 706942c
Showing
6 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
<?php | ||
|
||
namespace Notion\Databases\Properties; | ||
|
||
use Notion\Exceptions\RelationException; | ||
|
||
/** | ||
* @psalm-type RelationJson = array{ | ||
* id: string, | ||
* name: string, | ||
* type: "relation", | ||
* relation: array{ | ||
* database_id: string, | ||
* type: string, | ||
* single_property?: array<empty, empty>, | ||
* dual_property?: array{ | ||
* synced_property_name: string, | ||
* synced_property_id: string | ||
* } | ||
* } | ||
* } | ||
* | ||
* @psalm-immutable | ||
*/ | ||
class Relation implements PropertyInterface | ||
{ | ||
private function __construct( | ||
private readonly PropertyMetadata $metadata, | ||
public readonly string $databaseId, | ||
public readonly RelationType $type, | ||
public readonly string|null $syncedPropertyName, | ||
public readonly string|null $syncedPropertyId, | ||
) { | ||
if ($type === RelationType::DualProperty && $syncedPropertyName === null) { | ||
throw RelationException::emptySyncedPropertyName(); | ||
} | ||
|
||
if ($type === RelationType::DualProperty && $syncedPropertyId === null) { | ||
throw RelationException::emptySyncedPropertyId(); | ||
} | ||
} | ||
|
||
public static function createUnidirectional(string $propertyName, string $databaseId): self | ||
{ | ||
$metadata = PropertyMetadata::create("", $propertyName, PropertyType::Relation); | ||
$type = RelationType::SingleProperty; | ||
|
||
return new self($metadata, $databaseId, $type, null, null); | ||
} | ||
|
||
public static function createBidirectional( | ||
string $propertyName, | ||
string $databaseId, | ||
string $syncedPropertyName, | ||
string $syncedPropertyId, | ||
): self { | ||
$metadata = PropertyMetadata::create("", $propertyName, PropertyType::Relation); | ||
$type = RelationType::DualProperty; | ||
|
||
return new self($metadata, $databaseId, $type, $syncedPropertyName, $syncedPropertyId); | ||
} | ||
|
||
public function changeToUnidirectional(): self | ||
{ | ||
$newType = RelationType::SingleProperty; | ||
|
||
return new self($this->metadata(), $this->databaseId, $newType, null, null); | ||
} | ||
|
||
public function changeToBidirectional(string $syncedPropertyName, string $syncedPropertyId): self | ||
{ | ||
$newType = RelationType::DualProperty; | ||
|
||
return new self( | ||
$this->metadata(), | ||
$this->databaseId, | ||
$newType, | ||
$syncedPropertyName, | ||
$syncedPropertyId | ||
); | ||
} | ||
|
||
public function metadata(): PropertyMetadata | ||
{ | ||
return $this->metadata; | ||
} | ||
|
||
public static function fromArray(array $array): self | ||
{ | ||
/** @psalm-var RelationJson $array */ | ||
$metadata = PropertyMetadata::fromArray($array); | ||
|
||
$databaseId = $array["relation"]["database_id"]; | ||
$type = RelationType::from($array["relation"]["type"]); | ||
|
||
$syncedPropertyName = null; | ||
$syncedPropertyId = null; | ||
if ($type === RelationType::DualProperty) { | ||
$syncedPropertyName = $array["relation"]["dual_property"]["synced_property_name"] ?? null; | ||
$syncedPropertyId = $array["relation"]["dual_property"]["synced_property_id"] ?? null; | ||
} | ||
|
||
return new self($metadata, $databaseId, $type, $syncedPropertyName, $syncedPropertyId); | ||
} | ||
|
||
public function toArray(): array | ||
{ | ||
$array = $this->metadata->toArray(); | ||
$relation = [ | ||
"database_id" => $this->databaseId, | ||
"type" => $this->type->value, | ||
]; | ||
|
||
if ($this->isUniderectional()) { | ||
$relation["single_property"] = new \stdClass(); | ||
} | ||
|
||
if ($this->isBiderectional()) { | ||
$relation["dual_property"] = [ | ||
"synced_property_name" => $this->syncedPropertyName, | ||
"synced_property_id" => $this->syncedPropertyId, | ||
]; | ||
} | ||
|
||
$array["relation"] = $relation; | ||
|
||
return $array; | ||
} | ||
|
||
public function isUniderectional(): bool | ||
{ | ||
return $this->type === RelationType::SingleProperty; | ||
} | ||
|
||
public function isBiderectional(): bool | ||
{ | ||
return $this->type === RelationType::DualProperty; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?php | ||
|
||
namespace Notion\Databases\Properties; | ||
|
||
enum RelationType: string | ||
{ | ||
case SingleProperty = "single_property"; | ||
case DualProperty = "dual_property"; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php | ||
|
||
namespace Notion\Exceptions; | ||
|
||
class RelationException extends NotionException | ||
{ | ||
public static function emptySyncedPropertyName(): self | ||
{ | ||
return new self("Bidirectional relations must provide 'synced property name'."); | ||
} | ||
|
||
public static function emptySyncedPropertyId(): self | ||
{ | ||
return new self("Bidirectional relations must provide 'synced property ID'."); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
<?php | ||
|
||
namespace Notion\Test\Unit\Databases\Properties; | ||
|
||
use Notion\Databases\Properties\PropertyFactory; | ||
use Notion\Databases\Properties\Relation; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
class RelationTest extends TestCase | ||
{ | ||
public function test_create_unidirectional(): void | ||
{ | ||
$databaseId = "04eecdf8-f2d9-43a0-abbc-476182192c8f"; | ||
$relation = Relation::createUnidirectional("My relation", $databaseId); | ||
|
||
$this->assertSame("My relation", $relation->metadata()->name); | ||
$this->assertSame($databaseId, $relation->databaseId); | ||
$this->assertTrue($relation->isUniderectional()); | ||
} | ||
|
||
public function test_create_bidirectional(): void | ||
{ | ||
$databaseId = "04eecdf8-f2d9-43a0-abbc-476182192c8f"; | ||
$syncedPropertyName = "Prop name"; | ||
$syncedPropertyId = "12ac"; | ||
|
||
$relation = Relation::createBidirectional( | ||
"My relation", | ||
$databaseId, | ||
$syncedPropertyName, | ||
$syncedPropertyId, | ||
); | ||
|
||
$this->assertSame("My relation", $relation->metadata()->name); | ||
$this->assertSame($databaseId, $relation->databaseId); | ||
$this->assertSame($syncedPropertyName, $relation->syncedPropertyName); | ||
$this->assertSame($syncedPropertyId, $relation->syncedPropertyId); | ||
$this->assertTrue($relation->isBiderectional()); | ||
} | ||
|
||
public function test_change_to_unidirectional(): void | ||
{ | ||
$databaseId = "04eecdf8-f2d9-43a0-abbc-476182192c8f"; | ||
$syncedPropertyName = "Prop name"; | ||
$syncedPropertyId = "12ac"; | ||
|
||
$relation = Relation::createBidirectional( | ||
"My relation", | ||
$databaseId, | ||
$syncedPropertyName, | ||
$syncedPropertyId, | ||
); | ||
|
||
$relation = $relation->changeToUnidirectional(); | ||
|
||
$this->assertTrue($relation->isUniderectional()); | ||
$this->assertNull($relation->syncedPropertyId); | ||
$this->assertNull($relation->syncedPropertyName); | ||
} | ||
|
||
public function test_change_to_bidirectional(): void | ||
{ | ||
$databaseId = "04eecdf8-f2d9-43a0-abbc-476182192c8f"; | ||
$relation = Relation::createUnidirectional("My relation", $databaseId); | ||
|
||
$syncedPropertyName = "Prop name"; | ||
$syncedPropertyId = "12ac"; | ||
|
||
|
||
$relation = $relation->changeToBidirectional($syncedPropertyName, $syncedPropertyId); | ||
|
||
$this->assertTrue($relation->isBiderectional()); | ||
$this->assertSame($syncedPropertyName, $relation->syncedPropertyName); | ||
$this->assertSame($syncedPropertyId, $relation->syncedPropertyId); | ||
} | ||
|
||
public function test_array_conversion(): void | ||
{ | ||
$array = [ | ||
"id" => "abc", | ||
"name" => "dummy", | ||
"type" => "relation", | ||
"relation" => [ | ||
"database_id" => "84660ad0-9cb9-45d0-aae0-91e2c2526e12", | ||
"type" => "single_property", | ||
"single_property" => new \stdClass(), | ||
], | ||
]; | ||
$relation = Relation::fromArray($array); | ||
$fromFactory = PropertyFactory::fromArray($array); | ||
|
||
$this->assertEquals($array, $relation->toArray()); | ||
$this->assertEquals($array, $fromFactory->toArray()); | ||
} | ||
} |