Skip to content

Commit

Permalink
Merge pull request #4 from aiglesiasn/master
Browse files Browse the repository at this point in the history
Add LazyProps capability to Inertia class
  • Loading branch information
cherifGsoul authored Jul 5, 2024
2 parents c9e8deb + eca4ed3 commit 292af3a
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 3 deletions.
30 changes: 30 additions & 0 deletions src/Model/LazyProp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Cherif\InertiaPsr15\Model;

/**
* NOTE: this is similar to Laravel Inertia\LazyProp
*/
final class LazyProp
{
/**
* @var callable $callback
*/
protected $callback;

public function __construct(
callable $callable
) {
$this->callback = $callable;
}

/**
* @return mixed
*/
public function __invoke()
{
return call_user_func($this->callback);
}
}
12 changes: 11 additions & 1 deletion src/Service/Inertia.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Cherif\InertiaPsr15\Service;

use Cherif\InertiaPsr15\Model\LazyProp;
use Cherif\InertiaPsr15\Model\Page;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
Expand Down Expand Up @@ -42,10 +43,14 @@ public function render(string $component, array $props = [], string $url = null)
$props = ($only && $this->request->getHeaderLine('X-Inertia-Partial-Component') === $component)
? array_intersect_key($props, array_flip((array) $only))
: $props;
} else {
$props = array_filter($props, function ($prop) {
return ! $prop instanceof LazyProp;
});
}

array_walk_recursive($props, function (&$prop) {
if ($prop instanceof \Closure) {
if ($prop instanceof \Closure || $prop instanceof LazyProp ) {
$prop = $prop();
}
});
Expand Down Expand Up @@ -85,4 +90,9 @@ private function createResponse(string $data, string $contentType)
->withBody($stream)
->withHeader('Content-Type', $contentType);
}

public static function lazy(callable $callable): LazyProp
{
return new LazyProp($callable);
}
}
104 changes: 102 additions & 2 deletions test/Service/InertiaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ public function testRenderReturnResponseWithRequestedUrl()
$returnedResponse = $inertia->render(
'component',
[
'key1' => fn() => 'value1',
'key2' => fn() => 'value2'
'key1' => 'value1',
'key2' => 'value2'
]
,'/test/url'
);
Expand All @@ -192,4 +192,104 @@ public function testRenderReturnResponseWithRequestedUrl()
$this->assertSame($validJson, $jsonResponse);
}

public function testRenderReturnResponseWithoutLazyProps()
{
$request = $this->prophesize(ServerRequestInterface::class);
$request->hasHeader('X-Inertia')->willReturn(true);
$request->hasHeader('X-Inertia-Partial-Data')->willReturn(false);
$invalidJson = '{"component":"component","props":{"key1":"value1","key2":"value2"},"url":"callback()","version":null}';
$validJson = '{"component":"component","props":{"key2":"value2"},"url":"callback()","version":null}';
$jsonResponse = null;

$uri = $this->prophesize(UriInterface::class);
$request->getUri()->willReturn(Argument::that([$uri, 'reveal']));

$response = $this->prophesize(ResponseInterface::class);
$responseFactory = $this->prophesize(ResponseFactoryInterface::class);
$responseFactory->createResponse()->willReturn($response);

$stream = $this->prophesize(StreamInterface::class);
$streamFactory = $this->prophesize(StreamFactoryInterface::class);
$streamFactory->createStream(Argument::type('string'))->will(function ($args) use (&$jsonResponse, $stream){
$jsonResponse = $args[0];
return $stream;
});

$rootViewProvider = $this->prophesize(RootViewProviderInterface::class);

$response->withBody($stream->reveal())->willReturn($response);
$response->withHeader('X-Inertia', true)->willReturn($response);
$response->withHeader('Content-Type', 'application/json')->willReturn($response);

$inertia = new Inertia(
$request->reveal(),
$responseFactory->reveal(),
$streamFactory->reveal(),
$rootViewProvider->reveal()
);

$returnedResponse = $inertia->render(
'component',
[
'key1' => Inertia::lazy(fn() => 'value1'),
'key2' => fn() => 'value2'
]
);

$this->assertInstanceOf(ResponseInterface::class, $returnedResponse);
$this->assertNotSame($invalidJson, $jsonResponse);
$this->assertSame($validJson, $jsonResponse);
}

public function testRenderReturnResponseWithLazyProps()
{
$request = $this->prophesize(ServerRequestInterface::class);
$request->hasHeader('X-Inertia')->willReturn(true);
$request->hasHeader('X-Inertia-Partial-Data')->willReturn(true);
$request->getHeaderLine('X-Inertia-Partial-Component')->willReturn('component');
$request->getHeaderLine('X-Inertia-Partial-Data')->willReturn('key1');
$invalidJson = '{"component":"component","props":{"key2":"value2"},"url":"callback()","version":null}';
$validJson = '{"component":"component","props":{"key1":"value1"},"url":"callback()","version":null}';
$jsonResponse = null;

$uri = $this->prophesize(UriInterface::class);
$request->getUri()->willReturn(Argument::that([$uri, 'reveal']));

$response = $this->prophesize(ResponseInterface::class);
$responseFactory = $this->prophesize(ResponseFactoryInterface::class);
$responseFactory->createResponse()->willReturn($response);

$stream = $this->prophesize(StreamInterface::class);
$streamFactory = $this->prophesize(StreamFactoryInterface::class);
$streamFactory->createStream(Argument::type('string'))->will(function ($args) use (&$jsonResponse, $stream){
$jsonResponse = $args[0];
return $stream;
});

$rootViewProvider = $this->prophesize(RootViewProviderInterface::class);

$response->withBody($stream->reveal())->willReturn($response);
$response->withHeader('X-Inertia', true)->willReturn($response);
$response->withHeader('Content-Type', 'application/json')->willReturn($response);

$inertia = new Inertia(
$request->reveal(),
$responseFactory->reveal(),
$streamFactory->reveal(),
$rootViewProvider->reveal()
);

$returnedResponse = $inertia->render(
'component',
[
'key1' => Inertia::lazy(fn() => 'value1'),
'key2' => fn() => 'value2'
]
);

$this->assertInstanceOf(ResponseInterface::class, $returnedResponse);
$this->assertNotSame($invalidJson, $jsonResponse);
$this->assertSame($validJson, $jsonResponse);
}

}

0 comments on commit 292af3a

Please sign in to comment.