fix(s3): delete persons image sizes from bucket + add keyPrefix to config

This commit is contained in:
Yassine Doghri 2023-03-21 17:08:42 +00:00
parent 0a54b413b3
commit 208c2715f9
3 changed files with 71 additions and 29 deletions

View File

@ -181,15 +181,16 @@ media.s3.region="your_s3_region"
#### S3 config options #### S3 config options
| Variable name | Type | Default | | Variable name | Type | Default |
| ------------------------- | ------- | ----------- | | ----------------------- | ------- | ----------- |
| **`endpoint`** | string | `undefined` | | **`endpoint`** | string | `undefined` |
| **`key`** | string | `undefined` | | **`key`** | string | `undefined` |
| **`secret`** | string | `undefined` | | **`secret`** | string | `undefined` |
| **`region`** | string | `undefined` | | **`region`** | string | `undefined` |
| **`bucket`** | string | `castopod` | | **`bucket`** | string | `castopod` |
| **`protocol`** | number | `undefined` | | **`protocol`** | number | `undefined` |
| **`path_style_endpoint`** | boolean | `false` | | **`pathStyleEndpoint`** | boolean | `false` |
| **`keyPrefix`** | string | `undefined` |
## Community packages ## Community packages

View File

@ -31,7 +31,8 @@ class Media extends BaseConfig
'protocol' => '', 'protocol' => '',
'endpoint' => '', 'endpoint' => '',
'debug' => false, 'debug' => false,
'path_style_endpoint' => false, 'pathStyleEndpoint' => false,
'keyPrefix' => '',
]; ];
/** /**

View File

@ -24,7 +24,7 @@ class S3 implements FileManagerInterface
'endpoint' => $config->s3['endpoint'], 'endpoint' => $config->s3['endpoint'],
'credentials' => new Credentials((string) $config->s3['key'], (string) $config->s3['secret']), 'credentials' => new Credentials((string) $config->s3['key'], (string) $config->s3['secret']),
'debug' => $config->s3['debug'], 'debug' => $config->s3['debug'],
'use_path_style_endpoint' => $config->s3['path_style_endpoint'], 'use_path_style_endpoint' => $config->s3['pathStyleEndpoint'],
]); ]);
try { try {
@ -48,7 +48,7 @@ class S3 implements FileManagerInterface
try { try {
$this->s3->putObject([ $this->s3->putObject([
'Bucket' => $this->config->s3['bucket'], 'Bucket' => $this->config->s3['bucket'],
'Key' => $key, 'Key' => $this->prefixKey($key),
'SourceFile' => $file, 'SourceFile' => $file,
]); ]);
} catch (Exception) { } catch (Exception) {
@ -66,7 +66,7 @@ class S3 implements FileManagerInterface
try { try {
$this->s3->deleteObject([ $this->s3->deleteObject([
'Bucket' => $this->config->s3['bucket'], 'Bucket' => $this->config->s3['bucket'],
'Key' => $key, 'Key' => $this->prefixKey($key),
]); ]);
} catch (Exception) { } catch (Exception) {
return false; return false;
@ -79,13 +79,13 @@ class S3 implements FileManagerInterface
{ {
$url = new URI((string) $this->config->s3['endpoint']); $url = new URI((string) $this->config->s3['endpoint']);
if ($this->config->s3['path_style_endpoint'] === true) { if ($this->config->s3['pathStyleEndpoint'] === true) {
$url->setPath($this->config->s3['bucket'] . '/' . $key); $url->setPath($this->config->s3['bucket'] . '/' . $this->prefixKey($key));
return (string) $url; return (string) $url;
} }
$url->setHost($this->config->s3['bucket'] . '.' . $url->getHost()); $url->setHost($this->config->s3['bucket'] . '.' . $url->getHost());
$url->setPath($key); $url->setPath($this->prefixKey($key));
return (string) $url; return (string) $url;
} }
@ -95,22 +95,22 @@ class S3 implements FileManagerInterface
// copy old object with new key // copy old object with new key
$this->s3->copyObject([ $this->s3->copyObject([
'Bucket' => $this->config->s3['bucket'], 'Bucket' => $this->config->s3['bucket'],
'CopySource' => $this->config->s3['bucket'] . '/' . $oldKey, 'CopySource' => $this->config->s3['bucket'] . '/' . $this->prefixKey($oldKey),
'Key' => $newKey, 'Key' => $this->prefixKey($newKey),
]); ]);
} catch (Exception) { } catch (Exception) {
return false; return false;
} }
// delete old object // delete old object
return $this->delete($oldKey); return $this->delete($this->prefixKey($oldKey));
} }
public function getFileContents(string $key): string public function getFileContents(string $key): string
{ {
$result = $this->s3->getObject([ $result = $this->s3->getObject([
'Bucket' => $this->config->s3['bucket'], 'Bucket' => $this->config->s3['bucket'],
'Key' => $key, 'Key' => $this->prefixKey($key),
]); ]);
return (string) $result->get('Body'); return (string) $result->get('Body');
@ -125,7 +125,7 @@ class S3 implements FileManagerInterface
{ {
$results = $this->s3->getPaginator('ListObjectsV2', [ $results = $this->s3->getPaginator('ListObjectsV2', [
'Bucket' => $this->config->s3['bucket'], 'Bucket' => $this->config->s3['bucket'],
'Prefix' => 'podcasts/' . $podcastHandle . '/', 'Prefix' => $this->prefixKey('podcasts/' . $podcastHandle . '/'),
]); ]);
$keys = []; $keys = [];
@ -134,7 +134,9 @@ class S3 implements FileManagerInterface
return $object['Key']; return $object['Key'];
}, $result['Contents']); }, $result['Contents']);
array_push($keys, ...preg_grep("~^podcasts\/{$podcastHandle}\/.*_.*.\.(jpg|png|webp)$~", $key)); $prefixedPodcasts = $this->prefixKey('podcasts');
array_push($keys, ...preg_grep("~^{$prefixedPodcasts}\/{$podcastHandle}\/.*_.*.\.(jpg|png|webp)$~", $key));
} }
$objectsToDelete = array_map(static function ($key): array { $objectsToDelete = array_map(static function ($key): array {
@ -163,17 +165,44 @@ class S3 implements FileManagerInterface
public function deletePersonImagesSizes(): bool public function deletePersonImagesSizes(): bool
{ {
$objects = $this->s3->getIterator('ListObjectsV2', [ $results = $this->s3->getPaginator('ListObjectsV2', [
'Bucket' => $this->config->s3['bucket'], 'Bucket' => $this->config->s3['bucket'],
'prefix' => 'persons/', 'prefix' => $this->prefixKey('persons/'),
]); ]);
$objectsKeys = array_map(static function ($object) { $keys = [];
return $object['Key']; foreach ($results as $result) {
}, iterator_to_array($objects)); $key = array_map(static function ($object) {
return $object['Key'];
}, $result['Contents']);
$podcastImageKeys = preg_grep("~^persons\/.*_.*.\.(jpg|png|webp)$~", $objectsKeys); $prefixedPersons = $this->prefixKey('persons');
return (bool) $podcastImageKeys;
array_push($keys, ...preg_grep("~^{$prefixedPersons}\/.*_.*.\.(jpg|png|webp)$~", $key));
}
$objectsToDelete = array_map(static function ($key): array {
return [
'Key' => $key,
];
}, $keys);
if ($objectsToDelete === []) {
return true;
}
try {
$this->s3->deleteObjects([
'Bucket' => $this->config->s3['bucket'],
'Delete' => [
'Objects' => $objectsToDelete,
],
]);
} catch (Exception) {
return false;
}
return true;
} }
public function isHealthy(): bool public function isHealthy(): bool
@ -189,4 +218,15 @@ class S3 implements FileManagerInterface
return true; return true;
} }
private function prefixKey(string $key): string
{
if ($this->config->s3['keyPrefix'] === '') {
return $key;
}
$keyPrefix = rtrim((string) $this->config->s3['keyPrefix']);
return $keyPrefix . '/' . $key;
}
} }