Skip to content

Commit 01541ae

Browse files
committed
fix: recursive call to bindList if value is itself a list
for #486
1 parent fe62f74 commit 01541ae

File tree

5 files changed

+87
-0
lines changed

5 files changed

+87
-0
lines changed

src/ListBinder.php

+4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ public function bindListData(
7373
// If the $listValue's first value is iterable, then treat this as a nested list.
7474
if($this->isNested($listValue)) {
7575
$elementBinder->bind(null, $listKey, $t);
76+
$this->bindListData(
77+
$listValue,
78+
$t,
79+
);
7680
foreach($this->bindableCache->convertToKvp($listValue) as $key => $value) {
7781
$elementBinder->bind($key, $value, $t);
7882
}

test/phpunit/DocumentBinderTest.php

+34
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use Gt\DomTemplate\Test\TestHelper\HTMLPageContent;
2626
use Gt\DomTemplate\Test\TestHelper\ExampleClass;
2727
use Gt\DomTemplate\Test\TestHelper\Model\Address;
28+
use Gt\DomTemplate\Test\TestHelper\Model\ArrayIterator\Product\ProductList;
2829
use Gt\DomTemplate\Test\TestHelper\Model\Country;
2930
use Gt\DomTemplate\Test\TestHelper\Model\Customer;
3031
use PHPUnit\Framework\TestCase;
@@ -1366,6 +1367,39 @@ public function getIterator():Traversable {
13661367
self::assertCount(1, $ol->children);
13671368
}
13681369

1370+
public function testBindList_arrayIterator():void {
1371+
$document = new HTMLDocument(HTMLPageContent::HTML_SHOP_PRODUCTS);
1372+
$sut = new DocumentBinder($document);
1373+
$sut->setDependencies(...$this->documentBinderDependencies($document));
1374+
1375+
$categoryNameList = ["Category 1", "Category 2"];
1376+
$productNameList = [
1377+
["Product 1 in cat 1", "Product 2 in cat 1"],
1378+
["Product 3 in cat 2", "Product 4 in cat 2", "Product 5 in cat 2"],
1379+
];
1380+
1381+
$obj = new ProductList(
1382+
$categoryNameList,
1383+
$productNameList,
1384+
);
1385+
$sut->bindList($obj);
1386+
1387+
$categoryList = $document->querySelector("ul.categoryList");
1388+
self::assertCount(count($categoryNameList), $categoryList->children);
1389+
1390+
$productCount = 0;
1391+
foreach($categoryList->children as $categoryIndex => $categoryLi) {
1392+
self::assertSame("Category " . ($categoryIndex + 1), $categoryLi->querySelector("h2")->innerText);
1393+
1394+
self::assertCount(count($productNameList[$categoryIndex]), $categoryLi->querySelector("ul")->children);
1395+
1396+
foreach($categoryLi->querySelectorAll("ul li") as $productIndex => $productLi) {
1397+
self::assertSame("Product " . ($productCount + 1) . " in cat " . ($categoryIndex + 1), $productLi->textContent);
1398+
$productCount++;
1399+
}
1400+
}
1401+
}
1402+
13691403
private function documentBinderDependencies(HTMLDocument $document, mixed...$otherObjectList):array {
13701404
$htmlAttributeBinder = new HTMLAttributeBinder();
13711405
$htmlAttributeCollection = new HTMLAttributeCollection();

test/phpunit/TestHelper/HTMLPageContent.php

+16
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,22 @@ class HTMLPageContent {
10341034
</customer-list>
10351035
HTML;
10361036

1037+
const HTML_SHOP_PRODUCTS = <<<HTML
1038+
<!doctype html>
1039+
<h1>Categorised shop items</h1>
1040+
1041+
<ul class="categoryList">
1042+
<li data-list>
1043+
<h2 data-bind:text>Category name</h2>
1044+
1045+
<ul class="productList">
1046+
<li data-list data-bind:text="name">Product name</li>
1047+
</ul>
1048+
</li>
1049+
</ul>
1050+
HTML;
1051+
1052+
10371053
const HTML_REMOVE_UNBOUND = <<<HTML
10381054
<!doctype html>
10391055
<h1>Log in to the system</h1>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
namespace Gt\DomTemplate\Test\TestHelper\Model\ArrayIterator\Product;
3+
4+
class Product {
5+
public function __construct(
6+
public readonly string $name
7+
) {}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
namespace Gt\DomTemplate\Test\TestHelper\Model\ArrayIterator\Product;
3+
4+
use ArrayIterator;
5+
6+
class ProductList extends ArrayIterator {
7+
/**
8+
* @param array<string> $categoryNameList
9+
* @param array<array<string>> $productNameList
10+
*/
11+
public function __construct(array $categoryNameList, array $productNameList) {
12+
/** @var array<string, array<Product>> $categorisedProducts */
13+
$categorisedProducts = [];
14+
15+
foreach($categoryNameList as $i => $categoryName) {
16+
$categorisedProducts[$categoryName] = [];
17+
18+
foreach($productNameList[$i] as $productName) {
19+
array_push($categorisedProducts[$categoryName], new Product($productName));
20+
}
21+
}
22+
23+
parent::__construct($categorisedProducts);
24+
}
25+
}

0 commit comments

Comments
 (0)