Add component prop-passing coverage

Extend View component rendering tests to cover functional and class components receiving props via variadic and individual parameters, and update View callable invocation to map template data into callable arguments.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
580-view-class-steroids
fadrian06 2 weeks ago
parent 8c277dadd6
commit dd238319da

@ -4,7 +4,9 @@ declare(strict_types=1);
namespace flight\template; namespace flight\template;
use Closure;
use Exception; use Exception;
use ReflectionFunction;
/** /**
* The View class represents output to be displayed. It provides * The View class represents output to be displayed. It provides
@ -153,7 +155,8 @@ class View
switch (true) { switch (true) {
case is_callable($component): case is_callable($component):
$view = $component(); $arguments = $this->getCallableArguments($component, $data);
$view = $component(...$arguments);
ob_end_clean(); ob_end_clean();
break; break;
@ -290,4 +293,39 @@ class View
): string { ): string {
return str_replace(['\\', '/'], $separator, $path); return str_replace(['\\', '/'], $separator, $path);
} }
/**
* @param callable $component
* @param ?array<string, mixed> $data
* @return array<int, mixed>
*/
private function getCallableArguments(callable $component, ?array $data): array
{
if (!is_array($data) || !$data) {
return [];
}
$arguments = [];
$remainingData = $data;
$reflection = new ReflectionFunction(Closure::fromCallable($component));
foreach ($reflection->getParameters() as $parameter) {
if ($parameter->isVariadic()) {
foreach ($remainingData as $value) {
$arguments[] = $value;
}
break;
}
$name = $parameter->getName();
if (array_key_exists($name, $remainingData)) {
$arguments[] = $remainingData[$name];
unset($remainingData[$name]);
}
}
return $arguments;
}
} }

@ -308,6 +308,27 @@ class ViewTest extends TestCase
my-class-component my-class-component
html, html,
], ],
[
'page-with-functional-component-with-props',
<<<'html'
functional-component-with-props: Astronaut Victoria
html,
['name' => 'Victoria', 'occupation' => 'Astronaut'],
],
[
'page-with-functional-component-with-individual-props',
<<<'html'
functional-component-with-individual-props: Astronaut Victoria
html,
['name' => 'Victoria', 'occupation' => 'Astronaut'],
],
[
'page-with-class-component-with-props',
<<<'html'
class-component-with-props: Astronaut Victoria
html,
['name' => 'Victoria', 'occupation' => 'Astronaut'],
],
[ [
'page-with-class-component-with-styles', 'page-with-class-component-with-styles',
<<<'html' <<<'html'

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
use flight\template\Component;
return new class($name, $occupation) extends Component
{
private string $name;
private string $occupation;
public function __construct(string $name, string $occupation)
{
$this->name = $name;
$this->occupation = $occupation;
}
public function html(): string
{
return "class-component-with-props: $this->occupation $this->name";
}
};

@ -0,0 +1,6 @@
<?php
declare(strict_types=1);
return fn (string $name, string $occupation): string =>
"functional-component-with-individual-props: $occupation $name";

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
return fn (...$props): string => sprintf(
'functional-component-with-props: %s %s',
$props[1] ?? '',
$props[0] ?? ''
);

@ -0,0 +1 @@
<f-my-class-component-with-props name="<?= $name ?>" occupation="<?= $occupation ?>" />

@ -0,0 +1 @@
<f-my-functional-component-with-individual-props occupation="<?= $occupation ?>" name="<?= $name ?>" />

@ -0,0 +1 @@
<f-my-functional-component-with-props name="<?= $name ?>" occupation="<?= $occupation ?>" />
Loading…
Cancel
Save