Skip to content

Commit

Permalink
#213: use ListItemContext for ListView::renderItem related operations.
Browse files Browse the repository at this point in the history
  • Loading branch information
glpzzz committed Sep 10, 2024
1 parent e9eec42 commit 7d1824f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 33 deletions.
16 changes: 16 additions & 0 deletions src/ListItemContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Yiisoft\Yii\DataView;

final class ListItemContext
{

public function __construct(
public readonly array|object $data,
public readonly int|string $key,
public readonly int $index,
public readonly ListView $widget,
)
{
}
}
46 changes: 21 additions & 25 deletions src/ListView.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,13 @@ public function itemViewTag(?string $tag): self
* signature:
*
* ```php
* function ($data, $key, $index, $widget)
* function (ListItemContext $context)
* ```
* Also, each attribute value can be a function too, with the same signature as in:
*
* ```php
* [
* 'class' => static fn($data, $key, $index, $widget) => "custom-class-{$data['id']}",
* 'class' => static fn(ListItemContext $context) => "custom-class-{$context->data['id']}",
* ]
* ```
* @return ListView
Expand Down Expand Up @@ -223,13 +223,11 @@ public function viewParams(array $viewParams): self
/**
* Renders a single data model.
*
* @param array|object $data The data to be rendered.
* @param mixed $key The key value associated with the data.
* @param int $index The zero-based index of the data array.
* @param ListItemContext $context
*
* @throws ViewNotFoundException If the item view file doesn't exist.
*/
protected function renderItem(array|object $data, mixed $key, int $index): string
protected function renderItem(ListItemContext $context): string
{
$content = '';

Expand All @@ -242,9 +240,9 @@ protected function renderItem(array|object $data, mixed $key, int $index): strin
$this->itemView,
array_merge(
[
'data' => $data,
'index' => $index,
'key' => $key,
'data' => $context->data,
'index' => $context->index,
'key' => $context->key,
'widget' => $this,
],
$this->viewParams
Expand All @@ -253,16 +251,16 @@ protected function renderItem(array|object $data, mixed $key, int $index): strin
}

if ($this->itemView instanceof Closure) {
$content = (string)call_user_func($this->itemView, $data, $key, $index, $this);
$content = (string)call_user_func($this->itemView, $context);
}

$itemViewAttributes = is_callable($this->itemViewAttributes)
? (array)call_user_func($this->itemViewAttributes, $data, $key, $index, $this)
? (array)call_user_func($this->itemViewAttributes, $context)
: $this->itemViewAttributes;

foreach ($itemViewAttributes as $i => $attribute) {
if (is_callable($attribute)) {
$itemViewAttributes[$i] = $attribute($data, $key, $index, $this);
$itemViewAttributes[$i] = $attribute($context);
}
}

Expand All @@ -289,13 +287,15 @@ protected function renderItems(array $items, \Yiisoft\Validator\Result $filterVa
foreach (array_values($items) as $index => $value) {
$key = $keys[$index];

if ('' !== ($before = $this->renderBeforeItem($value, $key, $index))) {
$itemContext = new ListItemContext($value, $key, $index, $this);

if ('' !== ($before = $this->renderBeforeItem($itemContext))) {
$rows[] = $before;
}

$rows[] = $this->renderItem($value, $key, $index);
$rows[] = $this->renderItem($itemContext);

if ('' !== ($after = $this->renderAfterItem($value, $key, $index))) {
if ('' !== ($after = $this->renderAfterItem($itemContext))) {
$rows[] = $after;
}
}
Expand All @@ -314,20 +314,18 @@ protected function renderItems(array $items, \Yiisoft\Validator\Result $filterVa
*
* If {@see afterItem} is not a closure, `null` will be returned.
*
* @param array|object $data The data to be rendered.
* @param mixed $key The key value associated with the data.
* @param int $index The zero-based index of the data.
* @param ListItemContext $context context of the item to be rendered.
*
* @return string call result when {@see afterItem} is not a closure.
*
* {@see afterItem}
*/
private function renderAfterItem(array|object $data, mixed $key, int $index): string
private function renderAfterItem(ListItemContext $context): string
{
$result = '';

if (!empty($this->afterItem)) {
$result = (string)call_user_func($this->afterItem, $data, $key, $index, $this);
$result = (string)call_user_func($this->afterItem, $context->data, $context->key, $context->index, $context->widget);
}

return $result;
Expand All @@ -338,20 +336,18 @@ private function renderAfterItem(array|object $data, mixed $key, int $index): st
*
* If {@see beforeItem} is not a closure, `null` will be returned.
*
* @param array|object $data The data to be rendered.
* @param mixed $key The key value associated with the data.
* @param int $index The zero-based index of the data.
* @param ListItemContext $context context of the item to be rendered.
*
* @return string call result or `null` when {@see beforeItem} is not a closure.
*
* {@see beforeItem}
*/
private function renderBeforeItem(array|object $data, mixed $key, int $index): string
private function renderBeforeItem(ListItemContext $context): string
{
$result = '';

if (!empty($this->beforeItem)) {
$result = (string)call_user_func($this->beforeItem, $data, $key, $index, $this);
$result = (string)call_user_func($this->beforeItem, $context->data, $context->key, $context->index, $context->widget);
}

return $result;
Expand Down
17 changes: 9 additions & 8 deletions tests/ListView/BaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Yiisoft\Definitions\Exception\InvalidConfigException;
use Yiisoft\Definitions\Exception\NotInstantiableException;
use Yiisoft\Factory\NotFoundException;
use Yiisoft\Yii\DataView\ListItemContext;
use Yiisoft\Yii\DataView\ListView;
use Yiisoft\Yii\DataView\Tests\Support\Assert;
use Yiisoft\Yii\DataView\Tests\Support\TestTrait;
Expand Down Expand Up @@ -122,7 +123,7 @@ public function testItemViewAsCallable(): void
HTML,
ListView::widget()
->itemView(
fn (array $data) => '<div>' . $data['id'] . '</div><div>' . $data['name'] . '</div>' . PHP_EOL
fn (ListItemContext $context) => '<div>' . $context->data['id'] . '</div><div>' . $context->data['name'] . '</div>' . PHP_EOL
)
->dataReader($this->createOffsetPaginator($this->data, 10))
->render(),
Expand Down Expand Up @@ -426,10 +427,10 @@ public function testClosureForItemViewAttributes(): void
HTML,
ListView::widget()
->itemView(dirname(__DIR__) . '/Support/view/_listview.php')
->itemViewAttributes(static fn (array $data, $key, $index, $widget) => [
'data-item-id' => $data['id'],
'data-item-key' => $key,
'data-item-index' => $index,
->itemViewAttributes(static fn (ListItemContext $context) => [
'data-item-id' => $context->data['id'],
'data-item-key' => $context->key,
'data-item-index' => $context->index,
])
->dataReader($this->createOffsetPaginator($this->data, 10))
->separator(PHP_EOL)
Expand All @@ -456,7 +457,7 @@ public function testItemViewAttributesWithClosure(): void
ListView::widget()
->itemView(dirname(__DIR__) . '/Support/view/_listview.php')
->itemViewAttributes([
'class' => static fn(array $data, $key, $index) => "id-{$data['id']}-key-{$key}-index-{$index}",
'class' => static fn(ListItemContext $context) => "id-{$context->data['id']}-key-{$context->key}-index-{$context->index}",
])
->dataReader($this->createOffsetPaginator($this->data, 10))
->separator(PHP_EOL)
Expand All @@ -482,8 +483,8 @@ public function testClosureForItemViewAttributesWithClosure(): void
HTML,
ListView::widget()
->itemView(dirname(__DIR__) . '/Support/view/_listview.php')
->itemViewAttributes(static fn (array $data, $key, $index) => [
'class' => static fn(array $data, $key, $index) => "id-{$data['id']}-key-{$key}-index-{$index}",
->itemViewAttributes(static fn (ListItemContext $context) => [
'class' => static fn(ListItemContext $context) => "id-{$context->data['id']}-key-{$context->key}-index-{$context->index}",
])
->dataReader($this->createOffsetPaginator($this->data, 10))
->separator(PHP_EOL)
Expand Down

0 comments on commit 7d1824f

Please sign in to comment.