Skip to content

Commit

Permalink
ReadOnly properties act as bind getters by default (#355)
Browse files Browse the repository at this point in the history
* feature: load readonly properties

* test: load readonly properties from constructor

* test: readonly alongside bind attributes

* tidy: keep code style happy

* test: nullable fields
  • Loading branch information
g105b authored Jul 12, 2022
1 parent 4aabdd1 commit 1075f8d
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 3 deletions.
18 changes: 15 additions & 3 deletions src/BindableCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use ReflectionMethod;
use ReflectionObject;
use ReflectionProperty;
use function PHPUnit\Framework\stringStartsWith;

class BindableCache {
/**
Expand Down Expand Up @@ -49,13 +48,26 @@ public function isBindable(object $object):bool {
}
}
foreach($refObj->getProperties() as $refProp) {
$refAttributes = $this->getBindAttributes($refProp);
$propName = $refProp->getName();
if($refProp->isPublic() && $refProp->isReadOnly() && $refProp->isInitialized($object)) {
$bindKey = $propName;
$value = $object->$propName;
if(!is_null($value)) {
$value = (string)$value;
}
$attributeCache[$bindKey]
= fn(object $object) => $value;
}
$refAttributes = $this->getBindAttributes($refProp);

foreach($refAttributes as $refAttr) {
$bindKey = $this->getBindKey($refAttr);
$value = $object->$propName;
if(!is_null($value)) {
$value = (string)$value;
}
$attributeCache[$bindKey]
= fn(object $object) => $object->$propName;
= fn(object $object) => $value;
}
}

Expand Down
80 changes: 80 additions & 0 deletions test/phpunit/BindableCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public function getName():string {

public function testConvertToKvp_getterDoesNotStartWithGet():void {
$obj = new class {
/** @noinspection PhpUnused */
#[BindGetter]
public function retrieveName():string {
return "Test Name";
Expand All @@ -74,4 +75,83 @@ public function getName():string {
$sut = new BindableCache();
self::assertSame([], $sut->convertToKvp($obj));
}

/** @noinspection PhpUnused */
public function testConvertToKvp_publicReadOnly():void {
$obj = new class {
public readonly string $id;
public readonly string $name;
public readonly int $age;

public function __construct() {
$this->id = "test-id";
$this->name = "test-name";
}
};

$sut = new BindableCache();
self::assertSame([
"id" => "test-id",
"name" => "test-name",
], $sut->convertToKvp($obj));
}

public function testConvertToKvp_publicReadOnly_constructor():void {
$obj = new class("test-name", 55) {
public readonly string $id;

public function __construct(
public readonly string $name,
public readonly int $age,
) {
$this->id = "id-$name";
}
};

$sut = new BindableCache();
self::assertSame([
"id" => "id-test-name",
"name" => "test-name",
"age" => "55",
], $sut->convertToKvp($obj));
}

public function testConvertToKvp_publicReadOnly_mixedWithBindAttr():void {
$obj = new class("test-name", 5) {
public function __construct(
public readonly string $name,
public readonly int $age,
) {}

/** @noinspection PhpUnused */
#[BindGetter]
public function getAgeStatus():string {
return $this->age >= 18
? "adult"
: "minor";
}
};

$sut = new BindableCache();
self::assertSame([
"ageStatus" => "minor",
"name" => "test-name",
"age" => "5",
], $sut->convertToKvp($obj));
}

public function testConvertToKvp_publicReadOnlyNull():void {
$obj = new class("test-name") {
public function __construct(
public readonly string $name,
public readonly ?string $email = null,
) {}
};

$sut = new BindableCache();
self::assertSame([
"name" => "test-name",
"email" => null,
], $sut->convertToKvp($obj));
}
}
18 changes: 18 additions & 0 deletions test/phpunit/DocumentBinderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,24 @@ public function testBindData_object():void {
self::assertSame($userObject->category, $document->getElementById("dd3")->textContent);
}

public function testBindData_classWithReadonlyProperties():void {
$userObject = new class("g105b", "greg.bowler@g105b.com") {
public function __construct(
public readonly string $username,
public readonly string $email,
public readonly ?string $category = null,
) {}
};

$document = new HTMLDocument(DocumentTestFactory::HTML_USER_PROFILE);
$sut = new DocumentBinder($document);
$sut->bindData($userObject);

self::assertSame($userObject->username, $document->getElementById("dd1")->textContent);
self::assertSame($userObject->email, $document->getElementById("dd2")->textContent);
self::assertSame("N/A", $document->getElementById("dd3")->textContent);
}

public function testBindData_object_withNull():void {
$userObject = new StdClass();
$userObject->username = "g105b";
Expand Down

0 comments on commit 1075f8d

Please sign in to comment.