Skip to content

Commit ca6504e

Browse files
authored
Merge pull request #81 from tinect/feat/writeBatch
add writeBatch
2 parents 7d93e74 + 271056d commit ca6504e

File tree

6 files changed

+204
-87
lines changed

6 files changed

+204
-87
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
},
3636
"extra": {
3737
"branch-alias": {
38-
"dev-master": "1.0-dev"
38+
"dev-master": "3.x-dev"
3939
}
4040
}
4141
}

src/BunnyCDNAdapter.php

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace PlatformCommunity\Flysystem\BunnyCDN;
44

55
use Exception;
6+
use GuzzleHttp\Exception\RequestException;
7+
use GuzzleHttp\Pool;
68
use League\Flysystem\CalculateChecksumFromStream;
79
use League\Flysystem\ChecksumProvider;
810
use League\Flysystem\Config;
@@ -35,27 +37,8 @@ class BunnyCDNAdapter implements FilesystemAdapter, PublicUrlGenerator, Checksum
3537
{
3638
use CalculateChecksumFromStream;
3739

38-
/**
39-
* Pull Zone URL
40-
*
41-
* @var string
42-
*/
43-
private string $pullzone_url;
44-
45-
/**
46-
* @var BunnyCDNClient
47-
*/
48-
private BunnyCDNClient $client;
49-
50-
/**
51-
* @param BunnyCDNClient $client
52-
* @param string $pullzone_url
53-
*/
54-
public function __construct(BunnyCDNClient $client, string $pullzone_url = '')
40+
public function __construct(private BunnyCDNClient $client, private string $pullzone_url = '')
5541
{
56-
$this->client = $client;
57-
$this->pullzone_url = $pullzone_url;
58-
5942
if (\func_num_args() > 2 && (string) \func_get_arg(2) !== '') {
6043
throw new \RuntimeException('PrefixPath is no longer supported directly. Use PathPrefixedAdapter instead: https://flysystem.thephpleague.com/docs/adapter/path-prefixing/');
6144
}
@@ -70,12 +53,9 @@ public function __construct(BunnyCDNClient $client, string $pullzone_url = '')
7053
public function copy($source, $destination, Config $config): void
7154
{
7255
try {
73-
/** @var array<string> $files */
74-
$files = iterator_to_array($this->getFiles($source));
75-
7656
$sourceLength = \strlen($source);
7757

78-
foreach ($files as $file) {
58+
foreach ($this->getFiles($source) as $file) {
7959
$this->copyFile($file, $destination.\substr($file, $sourceLength), $config);
8060
}
8161
} catch (UnableToReadFile|UnableToWriteFile $exception) {
@@ -225,6 +205,34 @@ public function writeStream($path, $contents, Config $config): void
225205
$this->write($path, stream_get_contents($contents), $config);
226206
}
227207

208+
/**
209+
* @param WriteBatchFile[] $writeBatches
210+
* @param Config $config
211+
* @return void
212+
*/
213+
public function writeBatch(array $writeBatches, Config $config): void
214+
{
215+
$concurrency = (int) $config->get('concurrency', 50);
216+
217+
foreach (\array_chunk($writeBatches, $concurrency) as $batch) {
218+
$requests = function () use ($batch) {
219+
/** @var WriteBatchFile $file */
220+
foreach ($batch as $file) {
221+
yield $this->client->getUploadRequest($file->targetPath, \file_get_contents($file->localPath));
222+
}
223+
};
224+
225+
$pool = new Pool($this->client->guzzleClient, $requests(), [
226+
'concurrency' => $concurrency,
227+
'rejected' => function (RequestException|RuntimeException $reason, int $index) {
228+
throw UnableToWriteFile::atLocation($index, $reason->getMessage());
229+
},
230+
]);
231+
232+
$pool->promise()->wait();
233+
}
234+
}
235+
228236
/**
229237
* @param $path
230238
* @return resource

src/BunnyCDNClient.php

Lines changed: 45 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,21 @@
44

55
use GuzzleHttp\Client as Guzzle;
66
use GuzzleHttp\Exception\GuzzleException;
7+
use GuzzleHttp\Psr7\Request;
78
use PlatformCommunity\Flysystem\BunnyCDN\Exceptions\BunnyCDNException;
89
use PlatformCommunity\Flysystem\BunnyCDN\Exceptions\NotFoundException;
10+
use Psr\Http\Client\ClientExceptionInterface;
911

1012
class BunnyCDNClient
1113
{
12-
public string $storage_zone_name;
13-
14-
private string $api_key;
15-
16-
private string $region;
17-
18-
public Guzzle $client;
19-
20-
public function __construct(string $storage_zone_name, string $api_key, string $region = BunnyCDNRegion::FALKENSTEIN)
21-
{
22-
$this->storage_zone_name = $storage_zone_name;
23-
$this->api_key = $api_key;
24-
$this->region = $region;
25-
26-
$this->client = new Guzzle();
14+
public Guzzle $guzzleClient;
15+
16+
public function __construct(
17+
public string $storage_zone_name,
18+
private string $api_key,
19+
private string $region = BunnyCDNRegion::FALKENSTEIN
20+
) {
21+
$this->guzzleClient = new Guzzle();
2722
}
2823

2924
private static function get_base_url($region): string
@@ -41,23 +36,25 @@ private static function get_base_url($region): string
4136
};
4237
}
4338

44-
/**
45-
* @throws GuzzleException
46-
*/
47-
private function request(string $path, string $method = 'GET', array $options = []): mixed
39+
public function createRequest(string $path, string $method = 'GET', array $headers = [], $body = null): Request
4840
{
49-
$response = $this->client->request(
41+
return new Request(
5042
$method,
5143
self::get_base_url($this->region).Util::normalizePath('/'.$this->storage_zone_name.'/').$path,
52-
array_merge_recursive([
53-
'headers' => [
54-
'Accept' => '*/*',
55-
'AccessKey' => $this->api_key, // Honestly... Why do I have to specify this twice... @BunnyCDN
56-
],
57-
], $options)
44+
array_merge([
45+
'Accept' => '*/*',
46+
'AccessKey' => $this->api_key,
47+
], $headers),
48+
$body
5849
);
50+
}
5951

60-
$contents = $response->getBody()->getContents();
52+
/**
53+
* @throws ClientExceptionInterface
54+
*/
55+
private function request(Request $request, array $options = []): mixed
56+
{
57+
$contents = $this->guzzleClient->send($request, $options)->getBody()->getContents();
6158

6259
return json_decode($contents, true) ?? $contents;
6360
}
@@ -71,7 +68,7 @@ private function request(string $path, string $method = 'GET', array $options =
7168
public function list(string $path): array
7269
{
7370
try {
74-
$listing = $this->request(Util::normalizePath($path).'/');
71+
$listing = $this->request($this->createRequest(Util::normalizePath($path).'/'));
7572

7673
// Throw an exception if we don't get back an array
7774
if (! is_array($listing)) {
@@ -101,7 +98,7 @@ public function list(string $path): array
10198
public function download(string $path): string
10299
{
103100
try {
104-
$content = $this->request($path.'?download');
101+
$content = $this->request($this->createRequest($path.'?download'));
105102

106103
if (\is_array($content)) {
107104
return \json_encode($content);
@@ -128,17 +125,7 @@ public function download(string $path): string
128125
public function stream(string $path)
129126
{
130127
try {
131-
return $this->client->request(
132-
'GET',
133-
self::get_base_url($this->region).Util::normalizePath('/'.$this->storage_zone_name.'/').$path,
134-
array_merge_recursive([
135-
'stream' => true,
136-
'headers' => [
137-
'Accept' => '*/*',
138-
'AccessKey' => $this->api_key, // Honestly... Why do I have to specify this twice... @BunnyCDN
139-
],
140-
])
141-
)->getBody()->detach();
128+
return $this->guzzleClient->send($this->createRequest($path), ['stream' => true])->getBody()->detach();
142129
// @codeCoverageIgnoreStart
143130
} catch (GuzzleException $e) {
144131
throw match ($e->getCode()) {
@@ -149,6 +136,18 @@ public function stream(string $path)
149136
// @codeCoverageIgnoreEnd
150137
}
151138

139+
public function getUploadRequest(string $path, $contents): Request
140+
{
141+
return $this->createRequest(
142+
$path,
143+
'PUT',
144+
[
145+
'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
146+
],
147+
$contents
148+
);
149+
}
150+
152151
/**
153152
* @param string $path
154153
* @param $contents
@@ -159,17 +158,10 @@ public function stream(string $path)
159158
public function upload(string $path, $contents): mixed
160159
{
161160
try {
162-
return $this->request($path, 'PUT', [
163-
'headers' => [
164-
'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
165-
],
166-
'body' => $contents,
167-
]);
161+
return $this->request($this->getUploadRequest($path, $contents));
168162
// @codeCoverageIgnoreStart
169163
} catch (GuzzleException $e) {
170-
throw match ($e->getCode()) {
171-
default => new BunnyCDNException($e->getMessage())
172-
};
164+
throw new BunnyCDNException($e->getMessage());
173165
}
174166
// @codeCoverageIgnoreEnd
175167
}
@@ -183,11 +175,9 @@ public function upload(string $path, $contents): mixed
183175
public function make_directory(string $path): mixed
184176
{
185177
try {
186-
return $this->request(Util::normalizePath($path).'/', 'PUT', [
187-
'headers' => [
188-
'Content-Length' => 0,
189-
],
190-
]);
178+
return $this->request($this->createRequest(Util::normalizePath($path).'/', 'PUT', [
179+
'Content-Length' => 0,
180+
]));
191181
// @codeCoverageIgnoreStart
192182
} catch (GuzzleException $e) {
193183
throw match ($e->getCode()) {
@@ -208,7 +198,7 @@ public function make_directory(string $path): mixed
208198
public function delete(string $path): mixed
209199
{
210200
try {
211-
return $this->request($path, 'DELETE');
201+
return $this->request($this->createRequest($path, 'DELETE'));
212202
// @codeCoverageIgnoreStart
213203
} catch (GuzzleException $e) {
214204
throw match ($e->getCode()) {

src/WriteBatchFile.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace PlatformCommunity\Flysystem\BunnyCDN;
4+
5+
class WriteBatchFile
6+
{
7+
public function __construct(
8+
public string $localPath,
9+
public string $targetPath,
10+
) {
11+
}
12+
}

0 commit comments

Comments
 (0)