Skip to content

Commit b57816c

Browse files
committed
Merge pull request #25 from chimeraphp/prevent-generated-id-override
Prevent generated id override
1 parent 7a8346a commit b57816c

File tree

4 files changed

+114
-22
lines changed

4 files changed

+114
-22
lines changed

src/Handler/CreateAndFetch.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public function handle(ServerRequestInterface $request): ResponseInterface
7474
{
7575
$request = $request->withAttribute(
7676
IdentifierGenerator::class,
77-
$this->identifierGenerator->generate()
77+
$request->getAttribute(IdentifierGenerator::class, $this->identifierGenerator->generate())
7878
);
7979

8080
$input = new HttpRequest($request);

src/Handler/CreateOnly.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public function handle(ServerRequestInterface $request): ResponseInterface
7070
{
7171
$request = $request->withAttribute(
7272
IdentifierGenerator::class,
73-
$this->identifierGenerator->generate()
73+
$request->getAttribute(IdentifierGenerator::class, $this->identifierGenerator->generate())
7474
);
7575

7676
$this->action->execute(new HttpRequest($request));

tests/Handler/CreateAndFetchTest.php

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use PHPUnit\Framework\MockObject\MockObject;
1616
use PHPUnit\Framework\TestCase;
1717
use Psr\Http\Message\ResponseInterface;
18+
use Psr\Http\Message\ServerRequestInterface;
1819
use Zend\Diactoros\ResponseFactory;
1920
use Zend\Diactoros\ServerRequest;
2021

@@ -65,15 +66,6 @@ public function createDependencies(): void
6566
*/
6667
public function handleShouldExecuteTheCommandAndReturnAnEmptyResponse(): void
6768
{
68-
$handler = new CreateAndFetch(
69-
new ExecuteCommand($this->bus, $this->creator, 'command'),
70-
new ExecuteQuery($this->bus, $this->creator, 'query'),
71-
new ResponseFactory(),
72-
'info',
73-
$this->uriGenerator,
74-
$this->idGenerator
75-
);
76-
7769
$request = new ServerRequest();
7870
$command = (object) ['a' => 'b'];
7971
$query = (object) ['c' => 'd'];
@@ -96,12 +88,68 @@ public function handleShouldExecuteTheCommandAndReturnAnEmptyResponse(): void
9688
->willReturn('/testing/1');
9789

9890
/** @var ResponseInterface|UnformattedResponse $response */
99-
$response = $handler->handle($request);
91+
$response = $this->handleRequest($request);
10092

10193
self::assertInstanceOf(UnformattedResponse::class, $response);
10294
self::assertSame(StatusCodeInterface::STATUS_CREATED, $response->getStatusCode());
10395
self::assertSame('/testing/1', $response->getHeaderLine('Location'));
10496
self::assertSame([ExecuteQuery::class => 'query'], $response->getAttributes());
10597
self::assertSame('result', $response->getUnformattedContent());
10698
}
99+
100+
/**
101+
* @test
102+
*
103+
* @covers ::__construct()
104+
* @covers ::handle()
105+
* @covers ::generateResponse()
106+
*
107+
* @uses \Chimera\Routing\HttpRequest
108+
*/
109+
public function handleShouldPreserveTheRequestGeneratedIdIfAlreadyPresent(): void
110+
{
111+
$request = (new ServerRequest())->withAttribute(IdentifierGenerator::class, 2);
112+
$command = (object) ['a' => 'b'];
113+
$query = (object) ['c' => 'd'];
114+
115+
$this->creator->expects(self::exactly(2))
116+
->method('create')
117+
->willReturn($command, $query);
118+
119+
$this->bus->expects(self::exactly(2))
120+
->method('handle')
121+
->withConsecutive([$command], [$query])
122+
->willReturn(null, 'result');
123+
124+
$this->idGenerator->method('generate')
125+
->willReturn(1);
126+
127+
$this->uriGenerator->expects(self::once())
128+
->method('generateRelativePath')
129+
->with($request, 'info')
130+
->willReturn('/testing/2');
131+
132+
/** @var ResponseInterface|UnformattedResponse $response */
133+
$response = $this->handleRequest($request);
134+
135+
self::assertInstanceOf(UnformattedResponse::class, $response);
136+
self::assertSame(StatusCodeInterface::STATUS_CREATED, $response->getStatusCode());
137+
self::assertSame('/testing/2', $response->getHeaderLine('Location'));
138+
self::assertSame([ExecuteQuery::class => 'query'], $response->getAttributes());
139+
self::assertSame('result', $response->getUnformattedContent());
140+
}
141+
142+
private function handleRequest(ServerRequestInterface $request): ResponseInterface
143+
{
144+
$handler = new CreateAndFetch(
145+
new ExecuteCommand($this->bus, $this->creator, 'command'),
146+
new ExecuteQuery($this->bus, $this->creator, 'query'),
147+
new ResponseFactory(),
148+
'info',
149+
$this->uriGenerator,
150+
$this->idGenerator
151+
);
152+
153+
return $handler->handle($request);
154+
}
107155
}

tests/Handler/CreateOnlyTest.php

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
use Lcobucci\ContentNegotiation\UnformattedResponse;
1414
use PHPUnit\Framework\MockObject\MockObject;
1515
use PHPUnit\Framework\TestCase;
16+
use Psr\Http\Message\ResponseInterface;
17+
use Psr\Http\Message\ServerRequestInterface;
1618
use Zend\Diactoros\ResponseFactory;
1719
use Zend\Diactoros\ServerRequest;
1820

@@ -63,15 +65,6 @@ public function createDependencies(): void
6365
*/
6466
public function handleShouldExecuteTheCommandAndReturnAnEmptyResponse(): void
6567
{
66-
$handler = new CreateOnly(
67-
new ExecuteCommand($this->bus, $this->creator, 'command'),
68-
new ResponseFactory(),
69-
'info',
70-
$this->uriGenerator,
71-
$this->idGenerator,
72-
StatusCodeInterface::STATUS_CREATED
73-
);
74-
7568
$request = new ServerRequest();
7669
$command = (object) ['a' => 'b'];
7770

@@ -91,10 +84,61 @@ public function handleShouldExecuteTheCommandAndReturnAnEmptyResponse(): void
9184
->with($request->withAttribute(IdentifierGenerator::class, 1), 'info')
9285
->willReturn('/testing/1');
9386

94-
$response = $handler->handle($request);
87+
$response = $this->handleRequest($request);
9588

9689
self::assertNotInstanceOf(UnformattedResponse::class, $response);
9790
self::assertSame(StatusCodeInterface::STATUS_CREATED, $response->getStatusCode());
9891
self::assertSame('/testing/1', $response->getHeaderLine('Location'));
9992
}
93+
94+
/**
95+
* @test
96+
*
97+
* @covers ::__construct()
98+
* @covers ::handle()
99+
* @covers ::generateResponse()
100+
*
101+
* @uses \Chimera\Routing\HttpRequest
102+
*/
103+
public function handleShouldPreserveTheRequestGeneratedIdIfAlreadyPresent(): void
104+
{
105+
$request = (new ServerRequest())->withAttribute(IdentifierGenerator::class, 2);
106+
$command = (object) ['a' => 'b'];
107+
108+
$this->creator->expects(self::once())
109+
->method('create')
110+
->willReturn($command);
111+
112+
$this->bus->expects(self::once())
113+
->method('handle')
114+
->with($command);
115+
116+
$this->idGenerator->method('generate')
117+
->willReturn(1);
118+
119+
$this->uriGenerator->expects(self::once())
120+
->method('generateRelativePath')
121+
->with($request, 'info')
122+
->willReturn('/testing/2');
123+
124+
$response = $this->handleRequest($request);
125+
126+
self::assertNotInstanceOf(UnformattedResponse::class, $response);
127+
self::assertSame(StatusCodeInterface::STATUS_CREATED, $response->getStatusCode());
128+
self::assertSame('/testing/2', $response->getHeaderLine('Location'));
129+
}
130+
131+
private function handleRequest(ServerRequestInterface $request): ResponseInterface
132+
{
133+
$handler = new CreateOnly(
134+
new ExecuteCommand($this->bus, $this->creator, 'command'),
135+
new ResponseFactory(),
136+
'info',
137+
$this->uriGenerator,
138+
$this->idGenerator,
139+
StatusCodeInterface::STATUS_CREATED
140+
);
141+
142+
return $handler->handle($request);
143+
}
100144
}

0 commit comments

Comments
 (0)