Skip to content
This repository was archived by the owner on Jan 13, 2026. It is now read-only.

Commit ed841f7

Browse files
authored
✨ add download function for attachments #5 (#6)
1 parent 6a9151f commit ed841f7

File tree

10 files changed

+120
-19
lines changed

10 files changed

+120
-19
lines changed

rector.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector;
66
use Rector\CodingStyle\Rector\Encapsed\WrapEncapsedVariableInCurlyBracesRector;
77
use Rector\Config\RectorConfig;
8+
use Rector\EarlyReturn\Rector\If_\ChangeAndIfToEarlyReturnRector;
89
use Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector;
910
use Rector\Set\ValueObject\LevelSetList;
1011
use Rector\Set\ValueObject\SetList;
@@ -30,5 +31,6 @@
3031
EncapsedStringsToSprintfRector::class,
3132
WrapEncapsedVariableInCurlyBracesRector::class,
3233
FinalizeClassesWithoutChildrenRector::class,
34+
ChangeAndIfToEarlyReturnRector::class,
3335
]);
3436
};

src/Contracts/Transporter.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,11 @@ interface Transporter
2020
* @throws \JsonException
2121
*/
2222
public function request(Payload $payload): ?array;
23+
24+
/**
25+
* @throws \Jira\Exceptions\ErrorException
26+
* @throws \Jira\Exceptions\TransporterException
27+
* @throws \JsonException
28+
*/
29+
public function requestContent(Payload $payload): string;
2330
}

src/Resources/Attachments.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,18 @@ public function remove(string $id): void
5050

5151
$this->transporter->request(payload: $payload);
5252
}
53+
54+
/**
55+
* download an attachment.
56+
*
57+
* @throws \Jira\Exceptions\ErrorException
58+
* @throws \Jira\Exceptions\TransporterException
59+
* @throws \JsonException
60+
*/
61+
public function download(string $url): string
62+
{
63+
$payload = Payload::create(uri: $url);
64+
65+
return $this->transporter->requestContent(payload: $payload);
66+
}
5367
}

src/Transporters/HttpTransporter.php

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function request(Payload $payload): ?array
3838
throw new TransporterException(clientException: $clientException);
3939
}
4040

41-
$contents = $response->getBody()->getContents();
41+
$contents = (string) $response->getBody();
4242

4343
if (trim($contents) === '') {
4444
return null;
@@ -51,6 +51,42 @@ public function request(Payload $payload): ?array
5151
throw new UnserializableResponse(jsonException: $jsonException);
5252
}
5353

54+
$this->hasErrors($response);
55+
56+
return $response;
57+
}
58+
59+
public function requestContent(Payload $payload): string
60+
{
61+
$request = $payload->toRequest($this->baseUri, $this->headers);
62+
63+
try {
64+
$response = $this->client->sendRequest($request);
65+
} catch (ClientExceptionInterface $clientException) {
66+
throw new TransporterException($clientException);
67+
}
68+
69+
$contents = (string) $response->getBody();
70+
71+
try {
72+
/** @var non-empty-array<array-key, mixed> $response */
73+
$response = json_decode(json: $contents, associative: true, flags: JSON_THROW_ON_ERROR);
74+
75+
$this->hasErrors($response);
76+
} catch (JsonException) {
77+
// ..
78+
}
79+
80+
return $contents;
81+
}
82+
83+
/**
84+
* @param non-empty-array<array-key, mixed> $response
85+
*
86+
* @throws \Jira\Exceptions\ErrorException
87+
*/
88+
private function hasErrors(array $response): void
89+
{
5490
if (isset($response['errorMessage']) && $response['errorMessage'] !== '') {
5591
// @phpstan-ignore-next-line
5692
throw new ErrorException(message: $response['errorMessage']);
@@ -63,7 +99,5 @@ public function request(Payload $payload): ?array
6399
if (isset($response['errors']) && $response['errors'] !== []) {
64100
throw new ErrorException(message: reset($response['errors']));
65101
}
66-
67-
return $response;
68102
}
69103
}

src/ValueObjects/Transporter/Payload.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public function toRequest(BaseUri $baseUri, Headers $headers): Psr7Request
6464

6565
return new Psr7Request(
6666
method: $this->method->value,
67-
uri: $baseUri.$this->uri.$query,
67+
uri: filter_var(value: $this->uri, filter: FILTER_VALIDATE_URL) !== false ? $this->uri.$query : $baseUri.$this->uri.$query,
6868
headers: $headers->toArray(),
6969
body: $body,
7070
);

tests/Datasets/Functions.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
dataset('functions', [
4+
'request',
5+
'requestContent',
6+
]);

tests/Fixtures/Attachments.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,8 @@ function retrieveAttachment(): array
2424
'thumbnail' => 'https://www.example.com/jira/secure/thumbnail/10000',
2525
];
2626
}
27+
28+
function downloadAttachment(): string
29+
{
30+
return '{"a":"b"}\n';
31+
}

tests/Pest.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,23 @@
88
use Jira\ValueObjects\Transporter\Headers;
99
use Jira\ValueObjects\Transporter\Payload;
1010

11-
function mockClient(Method $method, string $uri, array $response = null): Client
11+
function mockClient(Method $method, string $uri, mixed $response = null, $function = 'request'): Client
1212
{
1313
$transporter = Mockery::mock(Transporter::class);
1414

1515
$transporter
16-
->shouldReceive('request')
16+
->shouldReceive($function)
1717
->once()
18-
->withArgs(function (Payload $payload) use ($uri, $method) {
18+
->withArgs(function (Payload $payload) use ($function, $uri, $method) {
1919
$baseUri = BaseUri::from('jira.domain.com');
2020
$headers = Headers::withAuthorization(BasicAuthentication::from('foo', 'bar'));
2121

2222
$request = $payload->toRequest($baseUri, $headers);
2323

24+
if ($function === 'requestContent') {
25+
return $request->getMethod() === $method->value && $request->getUri()->__toString() === $uri;
26+
}
27+
2428
return $request->getMethod() === $method->value
2529
&& $request->getUri()->getScheme() === 'https'
2630
&& $request->getUri()->getHost() === 'jira.domain.com'

tests/Resources/Attachments.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,16 @@
2424

2525
expect($result)->toBeNull();
2626
});
27+
28+
it('can download an attachment content', function () {
29+
$client = mockClient(
30+
method: Method::GET,
31+
uri: 'https://www.example.com/jira/attachments/10000',
32+
response: downloadAttachment(),
33+
function: 'requestContent'
34+
);
35+
36+
$result = $client->attachments()->download(url: 'https://www.example.com/jira/attachments/10000');
37+
38+
expect($result)->toBe(downloadAttachment());
39+
});

tests/Transporters/HttpTransporter.php

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,35 @@
3838
$this->http->request(payload: Payload::create(uri: 'api/2/issues'));
3939
});
4040

41-
it('can send valid request and receive invalid response (errorMessage)', function () {
41+
it('can send valid request and receive invalid response (errorMessage)', function (string $function) {
4242
$this->client->shouldReceive('sendRequest')
4343
->once()
4444
->andReturn(new Response(status: 400, body: json_encode(errorMessage())));
4545

46-
$this->http->request(payload: Payload::create(uri: 'api/2/issues'));
47-
})->throws(ErrorException::class, errorMessage()['errorMessage'], 0);
46+
$this->http->{$function}(payload: Payload::create(uri: 'api/2/issues'));
47+
})
48+
->with('functions')
49+
->throws(ErrorException::class, errorMessage()['errorMessage'], 0);
4850

49-
it('can send valid request and receive invalid response (errorMessages)', function () {
51+
it('can send valid request and receive invalid response (errorMessages)', function (string $function) {
5052
$this->client->shouldReceive('sendRequest')
5153
->once()
5254
->andReturn(new Response(status: 400, body: json_encode(errorMessages())));
5355

54-
$this->http->request(payload: Payload::create(uri: 'api/2/issues'));
55-
})->throws(ErrorException::class, errorMessages()['errorMessages'][0], 0);
56+
$this->http->{$function}(payload: Payload::create(uri: 'api/2/issues'));
57+
})
58+
->with('functions')
59+
->throws(ErrorException::class, errorMessages()['errorMessages'][0], 0);
5660

57-
it('can send valid request and receive invalid response (errors)', function () {
61+
it('can send valid request and receive invalid response (errors)', function (string $function) {
5862
$this->client->shouldReceive('sendRequest')
5963
->once()
6064
->andReturn(new Response(status: 400, body: json_encode(errors())));
6165

62-
$this->http->request(payload: Payload::create(uri: 'api/2/issues'));
63-
})->throws(ErrorException::class, errors()['errors']['customfield_18208'], 0);
66+
$this->http->{$function}(payload: Payload::create(uri: 'api/2/issues'));
67+
})
68+
->with('functions')
69+
->throws(ErrorException::class, errors()['errors']['customfield_18208'], 0);
6470

6571
it('can send valid request and receive invalid response (syntax)', function () {
6672
$this->client->shouldReceive('sendRequest')
@@ -70,7 +76,7 @@
7076
$this->http->request(payload: Payload::create(uri: 'api/2/issues'));
7177
})->throws(UnserializableResponse::class, 'Syntax error', 0);
7278

73-
it('will fail because of a client errors', function () {
79+
it('will fail because of a client errors', function (string $function) {
7480
$payload = Payload::create(
7581
uri: 'api/2/issues',
7682
);
@@ -87,5 +93,15 @@
8793
)
8894
);
8995

90-
$this->http->request(payload: $payload);
91-
})->throws(TransporterException::class, 'Could not resolve host.', 0);
96+
$this->http->{$function}(payload: $payload);
97+
})
98+
->with('functions')
99+
->throws(TransporterException::class, 'Could not resolve host.', 0);
100+
101+
it('can send valid requestContent and receive valid response', function () {
102+
$this->client->shouldReceive('sendRequest')
103+
->once()
104+
->andReturn(new Response(body: ''));
105+
106+
$this->http->requestContent(payload: Payload::create(uri: 'https://www.example.com/jira/attachments/10000', query: ['a' => 'b']));
107+
});

0 commit comments

Comments
 (0)