2022-02-20 20:22:07 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Friendica\Addon\s3_storage\src;
|
|
|
|
|
|
|
|
defined('AKEEBAENGINE') or define('AKEEBAENGINE', 1);
|
|
|
|
|
2024-11-27 23:18:20 +00:00
|
|
|
use Akeeba\S3\Configuration;
|
|
|
|
use Akeeba\S3\Connector;
|
|
|
|
use Akeeba\S3\Exception\CannotDeleteFile;
|
|
|
|
use Akeeba\S3\Input;
|
2022-02-20 20:22:07 +00:00
|
|
|
use Friendica\Core\Storage\Capability\ICanWriteToStorage;
|
|
|
|
use Friendica\Core\Storage\Exception\StorageException;
|
|
|
|
use Friendica\Util\Strings;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A WebDav Backend Storage class
|
|
|
|
*/
|
|
|
|
class S3Client implements ICanWriteToStorage
|
|
|
|
{
|
|
|
|
const NAME = 'S3';
|
|
|
|
|
|
|
|
/** @var Connector */
|
|
|
|
protected $connector;
|
|
|
|
|
|
|
|
/** @var string The name of the bucket used for the backend */
|
|
|
|
protected $bucket;
|
|
|
|
|
|
|
|
public function __construct(Configuration $config, string $bucket)
|
|
|
|
{
|
|
|
|
$this->connector = new Connector($config);
|
|
|
|
$this->bucket = $bucket;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Split data ref and return file path
|
|
|
|
*
|
|
|
|
* @param string $reference Data reference
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
private function pathForRef(string $reference): string
|
|
|
|
{
|
|
|
|
$fold1 = substr($reference, 0, 2);
|
|
|
|
$fold2 = substr($reference, 2, 2);
|
|
|
|
$file = substr($reference, 4);
|
|
|
|
|
|
|
|
return implode('/', [$fold1, $fold2, $file]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** {@inheritDoc} */
|
|
|
|
public function __toString(): string
|
|
|
|
{
|
|
|
|
return self::getName();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** {@inheritDoc} */
|
|
|
|
public static function getName(): string
|
|
|
|
{
|
|
|
|
return self::NAME;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** {@inheritDoc} */
|
|
|
|
public function get(string $reference): string
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return $this->connector->getObject($this->bucket, $this->pathForRef($reference), false);
|
|
|
|
} catch (\RuntimeException $exception) {
|
|
|
|
throw new StorageException(sprintf('Cannot get reference %s', $reference), $exception->getCode(), $exception);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** {@inheritDoc} */
|
|
|
|
public function put(string $data, string $reference = ""): string
|
|
|
|
{
|
|
|
|
if ($reference === '') {
|
|
|
|
try {
|
|
|
|
$reference = Strings::getRandomHex();
|
|
|
|
} catch (\Exception $exception) {
|
|
|
|
throw new StorageException('S3 storage failed to generate a random hex', $exception->getCode(), $exception);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$input = Input::createFromData($data);
|
|
|
|
$this->connector->putObject($input, $this->bucket, $this->pathForRef($reference));
|
|
|
|
return $reference;
|
|
|
|
} catch (\Exception $exception) {
|
|
|
|
throw new StorageException(sprintf('Cannot put data for reference %s', $reference), $exception->getCode(), $exception);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** {@inheritDoc} */
|
|
|
|
public function delete(string $reference)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
$this->connector->deleteObject($this->bucket, $this->pathForRef($reference));
|
|
|
|
} catch (CannotDeleteFile $exception) {
|
|
|
|
throw new StorageException(sprintf('Cannot delete reference %s', $reference), $exception->getCode(), $exception);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|