Skip to content

Commit

Permalink
Merge pull request #10 from PhpGt/9-optional-bind-keys
Browse files Browse the repository at this point in the history
Optional bind keys
  • Loading branch information
g105b authored Jan 6, 2018
2 parents 664a88a + a5fa432 commit 62272e3
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 8 deletions.
19 changes: 11 additions & 8 deletions src/Bindable.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,8 @@ protected function setData(BaseElement $element, iterable $data):void {
continue;
}

$key = $this->getKeyFromAttribute($element, $attr);
if(!isset($data[$key])) {
throw new BoundDataNotSetException($key);
}
$dataValue = $data[$key];
$dataKeyMatch = $this->getKeyFromAttribute($element, $attr);
$dataValue = $dataKeyMatch->getValue($data) ?? "";

switch($matches[1]) {
case "html":
Expand All @@ -104,20 +101,26 @@ protected function setData(BaseElement $element, iterable $data):void {
}
}

protected function getKeyFromAttribute(BaseElement $element, Attr $attr):string {
protected function getKeyFromAttribute(BaseElement $element, Attr $attr):DataKeyMatch {
$required = true;
$key = $attr->value;

if($key[0] === "?") {
$required = false;
$key = substr($key, 1);
}

if($key[0] === "@") {
$key = substr($key, 1);
$attributeValue = $element->getAttribute($key);
if(is_null($attributeValue)) {
throw new BoundAttributeDoesNotExistException($attr->name);
}

return $attributeValue;
$key = $attributeValue;
}

return $key;
return new DataKeyMatch($key, $required);
}

protected function wrapData(iterable $data):iterable {
Expand Down
24 changes: 24 additions & 0 deletions src/DataKeyMatch.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
namespace Gt\DomTemplate;

class DataKeyMatch {
public function __construct(string $key, bool $required) {
$this->key = $key;
$this->required = $required;
}

public function checkDataExists(iterable $data) {
if(!$this->required) {
return;
}

if(!isset($data[$this->key])) {
throw new BoundDataNotSetException($this->key);
}
}

public function getValue(iterable $data):?string {
$this->checkDataExists($data);
return $data[$this->key] ?? null;
}
}
38 changes: 38 additions & 0 deletions test/unit/BindableTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Gt\DomTemplate\Test;

use Gt\DomTemplate\BoundDataNotSetException;
use Gt\DomTemplate\HTMLDocument;
use Gt\DomTemplate\Test\Helper\Helper;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -185,4 +186,41 @@ public function testBindWithInlineNamedTemplateWhenAnotherTemplateExists() {
self::assertContains("Implement features", $todoListElement->innerHTML);
self::assertNotContains("Use the other template instead!", $todoListElement->innerHTML);
}

public function testBindWithNonOptionalKey() {
$document = new HTMLDocument(Helper::HTML_TODO_LIST);
$todoData = [
["title" => "Write tests", "complete" => true],
["title" => "Implement features", "complete" => false],
["title" => "Pass tests", "complete" => false],
];
$document->extractTemplates();
$todoListElement = $document->getElementById("todo-list");

self::expectException(BoundDataNotSetException::class);
$todoListElement->bind($todoData);
}

public function testBindWithOptionalKey() {
$document = new HTMLDocument(Helper::HTML_TODO_LIST_OPTIONAL_ID);
$todoData = [
["title" => "Write tests", "complete" => true],
["title" => "Implement features", "complete" => false],
["title" => "Pass tests", "complete" => false],
];
$document->extractTemplates();
$todoListElement = $document->getElementById("todo-list");

$todoListElement->bind($todoData);
$items = $todoListElement->querySelectorAll("li");
self::assertCount(3, $items);

self::assertEquals(
"Implement features",
$items[1]->querySelector("input[name=title]")->value
);
self::assertNull(
$items[1]->querySelector("input[name=id]")->value
);
}
}
30 changes: 30 additions & 0 deletions test/unit/Helper/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,5 +188,35 @@ class Helper {
</li>
</ul>
</main>
HTML;

const HTML_TODO_LIST_OPTIONAL_ID = <<<HTML
<!doctype html>
<meta charset="utf-8" />
<title>Todo list</title>
<main>
<ul id="todo-list">
<li data-template>
<input name="id" data-bind:value="?id" />
<input name="title" data-bind:value="@name" />
<button name="do" value="complete">Complete</button>
</li>
</ul>
</main>
HTML;

const HTML_TODO_LIST_OPTIONAL_ID_REFERENCED = <<<HTML
<!doctype html>
<meta charset="utf-8" />
<title>Todo list</title>
<main>
<ul id="todo-list">
<li data-template>
<input name="id" data-bind:value="?@name" />
<input name="title" data-bind:value="@name" />
<button name="do" value="complete">Complete</button>
</li>
</ul>
</main>
HTML;
}

0 comments on commit 62272e3

Please sign in to comment.