Skip to content

Commit cf38fcc

Browse files
committed
Add BatchResult
1 parent 67baf37 commit cf38fcc

File tree

4 files changed

+293
-51
lines changed

4 files changed

+293
-51
lines changed

spec/BatchResultSpec.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace spec\Http\Client;
4+
5+
use Http\Client\Exception;
6+
use Psr\Http\Message\RequestInterface;
7+
use Psr\Http\Message\ResponseInterface;
8+
use PhpSpec\ObjectBehavior;
9+
10+
class BatchResultSpec extends ObjectBehavior
11+
{
12+
function it_is_initializable()
13+
{
14+
$this->shouldHaveType('Http\Client\BatchResult');
15+
}
16+
17+
function it_is_immutable(RequestInterface $request, ResponseInterface $response, Exception $exception)
18+
{
19+
$new = $this->addResponse($request, $response);
20+
$new2 = $new->addException($request, $exception);
21+
22+
$this->getResponses()->shouldReturn([]);
23+
$this->getExceptions()->shouldReturn([]);
24+
$new->shouldHaveType('Http\Client\BatchResult');
25+
$new->getResponses()->shouldReturn([$response]);
26+
$new->getExceptions()->shouldReturn([]);
27+
$new2->shouldHaveType('Http\Client\BatchResult');
28+
$new2->getResponses()->shouldReturn([$response]);
29+
$new2->getExceptions()->shouldReturn([$exception]);
30+
}
31+
32+
function it_has_a_response_for_a_request(RequestInterface $request, ResponseInterface $response)
33+
{
34+
$new = $this->addResponse($request, $response);
35+
36+
$this->getResponseFor($request)->shouldReturn(null);
37+
$this->hasResponses()->shouldReturn(false);
38+
$this->hasResponseFor($request)->shouldReturn(false);
39+
$this->getResponses()->shouldReturn([]);
40+
$this->isSuccessful($request)->shouldReturn(false);
41+
$this->isFailed($request)->shouldReturn(false);
42+
$new->getResponseFor($request)->shouldReturn($response);
43+
$new->hasResponses()->shouldReturn(true);
44+
$new->hasResponseFor($request)->shouldReturn(true);
45+
$new->getResponses()->shouldReturn([$response]);
46+
$new->isSuccessful($request)->shouldReturn(true);
47+
$new->isFailed($request)->shouldReturn(false);
48+
}
49+
50+
function it_has_an_exception_for_a_request(RequestInterface $request, Exception $exception)
51+
{
52+
$new = $this->addException($request, $exception);
53+
54+
$this->getExceptionFor($request)->shouldReturn(null);
55+
$this->hasExceptions()->shouldReturn(false);
56+
$this->hasExceptionFor($request)->shouldReturn(false);
57+
$this->getExceptions()->shouldReturn([]);
58+
$this->isSuccessful($request)->shouldReturn(false);
59+
$this->isFailed($request)->shouldReturn(false);
60+
$new->getExceptionFor($request)->shouldReturn($exception);
61+
$new->hasExceptions()->shouldReturn(true);
62+
$new->hasExceptionFor($request)->shouldReturn(true);
63+
$new->getExceptions()->shouldReturn([$exception]);
64+
$new->isSuccessful($request)->shouldReturn(false);
65+
$new->isFailed($request)->shouldReturn(true);
66+
}
67+
}

spec/Exception/BatchExceptionSpec.php

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,31 @@
22

33
namespace spec\Http\Client\Exception;
44

5-
use Http\Client\Exception\TransferException;
6-
use Psr\Http\Message\ResponseInterface;
5+
use Http\Client\BatchResult;
76
use PhpSpec\ObjectBehavior;
87

98
class BatchExceptionSpec extends ObjectBehavior
109
{
11-
function let(TransferException $e, ResponseInterface $response)
10+
private $result;
11+
12+
function let()
1213
{
13-
$this->beConstructedWith([$e], [$response]);
14+
$this->beConstructedWith($this->result = new BatchResult());
1415
}
1516

1617
function it_is_initializable()
1718
{
1819
$this->shouldHaveType('Http\Client\Exception\BatchException');
1920
}
2021

21-
function it_is_a_transfer_exception()
22-
{
23-
$this->shouldHaveType('Http\Client\Exception\TransferException');
24-
}
25-
26-
function it_has_exceptions(TransferException $e, TransferException $e2)
22+
function it_is_an_exception()
2723
{
28-
$this->getExceptions()->shouldReturn([$e]);
29-
$this->hasException($e)->shouldReturn(true);
30-
$this->hasException($e2)->shouldReturn(false);
31-
$this->hasExceptions()->shouldReturn(true);
24+
$this->shouldImplement('Http\Client\Exception');
25+
$this->shouldHaveType('Exception');
3226
}
3327

34-
function it_has_responses(ResponseInterface $response, ResponseInterface $response2)
28+
function it_has_a_result()
3529
{
36-
$this->getResponses()->shouldReturn([$response]);
37-
$this->hasResponse($response)->shouldReturn(true);
38-
$this->hasResponse($response2)->shouldReturn(false);
39-
$this->hasResponses()->shouldReturn(true);
30+
$this->getResult()->shouldReturn($this->result);
4031
}
4132
}

src/BatchResult.php

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
<?php
2+
3+
namespace Http\Client;
4+
5+
use Psr\Http\Message\RequestInterface;
6+
use Psr\Http\Message\ResponseInterface;
7+
8+
/**
9+
* Successful responses and exceptions returned from parallel request execution
10+
*
11+
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
12+
*/
13+
final class BatchResult
14+
{
15+
/**
16+
* @var \SplObjectStorage
17+
*/
18+
private $responses;
19+
20+
/**
21+
* @var \SplObjectStorage
22+
*/
23+
private $exceptions;
24+
25+
public function __construct()
26+
{
27+
$this->responses = new \SplObjectStorage();
28+
$this->exceptions = new \SplObjectStorage();
29+
}
30+
31+
/**
32+
* Checks if a request is successful
33+
*
34+
* @param RequestInterface $request
35+
*
36+
* @return boolean
37+
*/
38+
public function isSuccessful(RequestInterface $request)
39+
{
40+
return $this->responses->contains($request);
41+
}
42+
43+
/**
44+
* Checks if a request is failed
45+
*
46+
* @param RequestInterface $request
47+
*
48+
* @return boolean
49+
*/
50+
public function isFailed(RequestInterface $request)
51+
{
52+
return $this->exceptions->contains($request);
53+
}
54+
55+
/**
56+
* Returns all successful responses
57+
*
58+
* @return ResponseInterface[]
59+
*/
60+
public function getResponses()
61+
{
62+
$responses = [];
63+
64+
foreach ($this->responses as $request) {
65+
$responses[] = $this->responses[$request];
66+
}
67+
68+
return $responses;
69+
}
70+
71+
/**
72+
* Returns a response of a request or null if not found
73+
*
74+
* @param RequestInterface $request
75+
*
76+
* @return ResponseInterface|null
77+
*/
78+
public function getResponseFor(RequestInterface $request)
79+
{
80+
if ($this->responses->contains($request)) {
81+
return $this->responses[$request];
82+
}
83+
}
84+
85+
/**
86+
* Checks if there are any successful responses at all
87+
*
88+
* @return boolean
89+
*/
90+
public function hasResponses()
91+
{
92+
return $this->responses->count() > 0;
93+
}
94+
95+
/**
96+
* Checks if there is a response of a request
97+
*
98+
* @param RequestInterface $request
99+
*
100+
* @return ResponseInterface
101+
*/
102+
public function hasResponseFor(RequestInterface $request)
103+
{
104+
return $this->responses->contains($request);
105+
}
106+
107+
/**
108+
* Adds a response in an immutable way
109+
*
110+
* @param RequestInterface $request
111+
* @param ResponseInterface $response
112+
*
113+
* @return BatchResult
114+
*/
115+
public function addResponse(RequestInterface $request, ResponseInterface $response)
116+
{
117+
$new = clone $this;
118+
$new->responses->attach($request, $response);
119+
120+
return $new;
121+
}
122+
123+
/**
124+
* Returns all exceptions
125+
*
126+
* @return Exception[]
127+
*/
128+
public function getExceptions()
129+
{
130+
$exceptions = [];
131+
132+
foreach ($this->exceptions as $request) {
133+
$exceptions[] = $this->exceptions[$request];
134+
}
135+
136+
return $exceptions;
137+
}
138+
139+
/**
140+
* Returns an exception for a request or null if not found
141+
*
142+
* @param RequestInterface $request
143+
*
144+
* @return Exception|null
145+
*/
146+
public function getExceptionFor(RequestInterface $request)
147+
{
148+
if ($this->exceptions->contains($request)) {
149+
return $this->exceptions[$request];
150+
}
151+
}
152+
153+
/**
154+
* Checks if there are any exceptions at all
155+
*
156+
* @return boolean
157+
*/
158+
public function hasExceptions()
159+
{
160+
return $this->exceptions->count() > 0;
161+
}
162+
163+
/**
164+
* Checks if there is an exception for a request
165+
*
166+
* @param RequestInterface $request
167+
*
168+
* @return Exception
169+
*/
170+
public function hasExceptionFor(RequestInterface $request)
171+
{
172+
return $this->exceptions->contains($request);
173+
}
174+
175+
/**
176+
* Adds an exception in an immutable way
177+
*
178+
* @param RequestInterface $request
179+
* @param Exception $exception
180+
*
181+
* @return BatchResult
182+
*/
183+
public function addException(RequestInterface $request, Exception $exception)
184+
{
185+
$new = clone $this;
186+
$new->exceptions->attach($request, $exception);
187+
188+
return $new;
189+
}
190+
191+
public function __clone()
192+
{
193+
$this->responses = clone $this->responses;
194+
$this->exceptions = clone $this->exceptions;
195+
}
196+
}

src/Exception/BatchException.php

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,49 @@
22

33
namespace Http\Client\Exception;
44

5+
use Http\Client\BatchResult;
6+
57
/**
68
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
79
*/
8-
final class BatchException extends TransferException
10+
final class BatchException extends RuntimeException
911
{
1012
/**
11-
* @var TransferException[]
13+
* @var BatchResult
1214
*/
13-
private $exceptions;
15+
private $result;
1416

1517
/**
16-
* @param TransferException[] $exceptions
18+
* @param BatchResult $result
1719
*/
18-
public function __construct(array $exceptions = [])
20+
public function __construct(BatchResult $result)
1921
{
20-
parent::__construct('An error occurred when sending multiple requests.');
21-
22-
foreach ($exceptions as $e) {
23-
if (!$e instanceof TransferException) {
24-
throw new InvalidArgumentException('Exception is not an instanceof Http\Client\Exception\TransferException');
25-
}
26-
}
27-
28-
$this->exceptions = $exceptions;
22+
$this->result = $result;
2923
}
3024

3125
/**
32-
* Returns all exceptions
26+
* Returns successful responses or null
3327
*
34-
* @return TransferException[]
28+
* @return BatchResult
3529
*/
36-
public function getExceptions()
30+
public function getResult()
3731
{
38-
return $this->exceptions;
32+
return $this->result;
3933
}
4034

4135
/**
42-
* Checks if a specific exception exists
36+
* Decides whether the result has any failures
4337
*
44-
* @param TransferException $exception
38+
* @param BatchResult $result
4539
*
46-
* @return boolean TRUE if there is the exception else FALSE.
40+
* @return BatchResult|BatchException
4741
*/
48-
public function hasException(TransferException $exception)
42+
public static function decideReturnValue(BatchResult $result)
4943
{
50-
return array_search($exception, $this->exceptions, true) !== false;
51-
}
44+
if ($result->hasExceptions()) {
45+
return new self($result);
46+
}
5247

53-
/**
54-
* Checks if any exception exists
55-
*
56-
* @return boolean
57-
*/
58-
public function hasExceptions()
59-
{
60-
return !empty($this->exceptions);
48+
return $result;
6149
}
6250
}

0 commit comments

Comments
 (0)