Skip to content

Commit 693ec3f

Browse files
committed
finish refactor
1 parent 4be2dff commit 693ec3f

5 files changed

Lines changed: 120 additions & 49 deletions

File tree

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"php": "^5.6.4 || ^7.0",
1414
"aws/aws-sdk-php": "^3.31",
1515
"illuminate/support": ">=5.0.0",
16-
"guzzlehttp/guzzle": "^6.2"
16+
"guzzlehttp/guzzle": "^6.2",
17+
"mockery/mockery": "0.9.*"
1718
},
1819
"require-dev": {
1920
"phpunit/phpunit": "^6.1"

src/S3Presigned.php

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@
99
class S3Presigned
1010
{
1111
protected $client;
12+
protected $region;
1213
protected $options;
13-
protected $requiredOptions = ['region'];
14+
protected $requiredOptions = [];
1415
protected $baseUri;
1516
protected $prefix;
1617

17-
public function __construct(S3Client $client, $bucket, $prefix = '', array $options = [])
18+
public function __construct(S3Client $client, $region, $bucket, $prefix = '', array $options = [])
1819
{
1920
$this->client = $client;
2021
$this->bucket = $bucket;
22+
$this->region = $region;
2123
$this->options = $options;
2224
$this->checkOptions();
2325
$this->setBaseUri();
@@ -64,25 +66,30 @@ public function getUploadForm($key, $minutes = 10, array $policies = [], array $
6466
];
6567
}
6668

67-
public function listObjects()
69+
public function listObjects($directory = '', $recursive = false)
6870
{
6971
// http://docs.aws.amazon.com/AmazonS3/latest/dev/ListingObjectKeysUsingPHP.html
7072
// http://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#listobjects
71-
// https://github.com/thephpleague/flysystem-aws-s3-v3/blob/master/src/AwsS3Adapter.php
72-
$resultPaginator = $this->client->getPaginator('ListObjects', [
73+
$options = [
7374
'Bucket' => $this->getBucket(),
7475
'Prefix' => $this->getPrefix()
75-
]);
76+
];
77+
if ($recursive === false) {
78+
$options['Delimiter'] = '/';
79+
}
80+
$listing = $this->retrievePaginatedListing($options);
81+
$normalized = array_map([$this, 'normalizeObject'], $listing);
82+
83+
return $normalized;
84+
}
85+
86+
protected function retrievePaginatedListing(array $options)
87+
{
88+
$resultPaginator = $this->client->getPaginator('ListObjects', $options);
7689

7790
$listing = [];
7891
foreach ($resultPaginator as $result) {
79-
$objects = $result->get('Contents');
80-
if (is_null($objects)) {
81-
continue;
82-
}
83-
foreach ($objects as $object) {
84-
$listing[] = $this->normalizeObject($object);
85-
}
92+
$listing = array_merge($result->get('Contents') ?: [], $result->get('CommonPrefixes') ?: []);
8693
}
8794

8895
return $listing;
@@ -96,17 +103,17 @@ public function deleteObject($key)
96103
]);
97104
}
98105

99-
private function normalizeObject(array $object)
106+
protected function normalizeObject(array $object)
100107
{
101-
$normalized = [];
102-
$normalized['key'] = $object['Key'] ?? '';
103-
$normalized['url'] = $this->baseUri . $normalized['key'];
104-
$normalized['size'] = $object['Size'] ?? '';
108+
if (array_key_exists('LastModified', $object)) {
109+
$object['Timestamp'] = strtotime($object['LastModified']);
110+
}
111+
$object['Url'] = $this->getBaseUri() . $object['Key'];
105112

106-
return $normalized;
113+
return $object;
107114
}
108115

109-
private function getPostObject(array $defaults, array $options, $minutes = 10)
116+
protected function getPostObject(array $defaults, array $options, $minutes = 10)
110117
{
111118
return new PostObjectV4(
112119
$this->getClient(),
@@ -117,7 +124,7 @@ private function getPostObject(array $defaults, array $options, $minutes = 10)
117124
);
118125
}
119126

120-
public function checkOptions()
127+
protected function checkOptions()
121128
{
122129
$missings = array_filter($this->requiredOptions, function ($value) {
123130
return !array_key_exists($value, $this->options);
@@ -130,8 +137,7 @@ public function checkOptions()
130137

131138
public function setBaseUri()
132139
{
133-
$baseUri = "https://{$this->bucket}.s3-{$this->options['region']}.amazonaws.com/";
134-
$this->baseUri = $baseUri;
140+
$this->baseUri = "https://{$this->bucket}.s3-{$this->region}.amazonaws.com/";
135141

136142
return $this;
137143
}

src/S3PresignedServiceProvider.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,18 @@ public function register()
3939
'version' => $configs['version']
4040
'credentials' => $credentials,
4141
'options' => [
42-
$configs['options']
42+
$configs['s3_client']['options']
4343
]
4444
]);
4545

4646
$this->app->singleton('s3.presigned', function ($app) use ($s3Client, $configs) {
47-
return new S3Presigned($s3Client, $configs['bucket'], $configs['prefix'], $configs)
47+
return new S3Presigned(
48+
$s3Client,
49+
$configs['region'],
50+
$configs['bucket'],
51+
$configs['prefix'],
52+
$configs['options']
53+
);
4854
});
4955
}
5056

@@ -55,7 +61,7 @@ public function register()
5561
*/
5662
protected function bootConfig()
5763
{
58-
$path = __DIR__.'/config/captcha.php';
64+
$path = __DIR__ . '/config/captcha.php';
5965
$this->mergeConfigFrom($path, 's3_presigned');
6066
if (function_exists('config_path')) {
6167
$this->publishes([$path => config_path('s3_presigned.php')]);

src/config/s3_presigned.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
'version' => env('AWS_VERSION', 'latest'),
1010
'bucket' => env('AWS_S3_BUCKET'),
1111
'prefix' => env('AWS_S3_PREFIX', ''),
12+
's3_client' => [
13+
'options' => []
14+
],
1215
'options' => [
1316
//
1417
]

tests/PresignedTest.php

Lines changed: 77 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
namespace Tests;
44

5-
use Illuminate\Container\Container;
6-
use Illuminate\Filesystem\Filesystem;
5+
use Mockery as m;
76
use PHPUnit\Framework\TestCase;
87
use Aws\Credentials\Credentials;
98
use Aws\S3\S3Client;
9+
use Aws\S3\PostObjectV4;
10+
use Aws\Api\DateTimeResult;
1011
use Unisharp\S3\Presigned\S3PresignedServiceProvider;
1112
use Unisharp\S3\Presigned\S3Presigned;
1213
use Unisharp\S3\Presigned\Exceptions\OptionsMissingException;
@@ -22,6 +23,9 @@ class PresignedTest extends TestCase
2223
'version' => 'latest',
2324
'bucket' => 'bucket',
2425
'prefix' => 'prefix/',
26+
's3_client' => [
27+
'options' => []
28+
],
2529
'options' => [
2630
'foo' => 'bar'
2731
]
@@ -32,18 +36,18 @@ protected function setUp()
3236
parent::setUp();
3337
}
3438

35-
public function testCheckOptions()
36-
{
37-
$options = [
38-
'bucket' => 'bucket',
39-
'prefix' => 'prefix/',
40-
'options' => [
41-
'foo' => 'bar'
42-
]
43-
];
44-
$this->expectException(OptionsMissingException::class);
45-
$s3Presigned = $this->getS3Presigned($options);
46-
}
39+
// public function testCheckOptions()
40+
// {
41+
// $configs = [
42+
// 'bucket' => 'bucket',
43+
// 'prefix' => 'prefix/',
44+
// 'options' => [
45+
// 'foo' => 'bar'
46+
// ]
47+
// ];
48+
// $this->expectException(OptionsMissingException::class);
49+
// $s3Presigned = $this->getS3Presigned($configs);
50+
// }
4751

4852
public function testSetPrefix()
4953
{
@@ -85,24 +89,75 @@ public function testGetUploadForm()
8589
$this->assertEquals($result['inputs']['foo'], 'bar');
8690
}
8791

88-
private function getS3Presigned($options = [])
92+
public function testListObjects()
93+
{
94+
$number = 10;
95+
$url = "https://{$this->configs['bucket']}.s3-ap-northeast-1.amazonaws.com/public/";
96+
$s3Client = m::mock(S3Client::class);
97+
$s3Client->shouldReceive('getPaginator')
98+
->once()
99+
->with('ListObjects', m::type('array'))
100+
->andReturn([$this->getMockedObjects($number)]);
101+
102+
$s3Presigned = $this->getS3Presigned([], $s3Client);
103+
$objects = $s3Presigned->listObjects();
104+
$this->assertEquals($number , count($objects));
105+
$this->assertEquals($url, $objects[0]['Url']);
106+
}
107+
108+
protected function getMockedObjects($number = 5)
109+
{
110+
$objects = m::mock(\stdObject::class);
111+
$objects->shouldReceive('get')
112+
->once()
113+
->with('Contents')
114+
->andReturn(array_fill(0, $number, [
115+
'Key' => 'public/',
116+
'LastModified' => DateTimeResult::fromEpoch(time()),
117+
'ETag' => 'etag',
118+
'Size' => 0,
119+
'StorageClass' => 'STANDARD',
120+
'Owner' => [
121+
'DisplayName' => 'seafood',
122+
'ID' => 'owner_id',
123+
]
124+
]));
125+
$objects->shouldReceive('get')
126+
->once()
127+
->with('CommonPrefixes')
128+
->andReturn([]);
129+
130+
return $objects;
131+
}
132+
133+
protected function getS3Presigned(array $configs = [], S3Client $s3Client = null)
134+
{
135+
$configs = array_merge($this->configs, $configs);
136+
$s3Client = $s3Client ? $s3Client : $this->getS3Client($configs);
137+
138+
return new S3Presigned(
139+
$s3Client,
140+
$configs['region'],
141+
$configs['bucket'],
142+
$configs['prefix'],
143+
$configs['options']
144+
);
145+
}
146+
147+
protected function getS3Client(array $configs)
89148
{
90-
$configs = $this->configs;
91149
$credentials = new Credentials(
92150
$configs['credentials']['access_key'],
93151
$configs['credentials']['secret_key']
94152
);
95-
$s3Client = new S3Client([
153+
154+
return new S3Client([
96155
'region' => $configs['region'],
97156
'version' => $configs['version'],
98157
'credentials' => $credentials,
99158
'options' => [
100-
$configs['options']
159+
$configs['s3_client']['options']
101160
]
102161
]);
103-
104-
$options = $options ?: $configs;
105-
106-
return new S3Presigned($s3Client, $options['bucket'], $options['prefix'], $options);
107162
}
108163
}

0 commit comments

Comments
 (0)