Adds a new 'S3-Compatible Storage' provider that works with any
S3-API-compatible object storage service, including MinIO, Ceph,
Cloudflare R2, Backblaze B2, and others.
Changes:
- New provider class: classes/providers/storage/s3-compatible-provider.php
- Provider key: s3compatible
- Reads user-configured endpoint URL from settings
- Uses path-style URL access (required by most S3-compatible services)
- Supports credentials via AS3CF_S3COMPAT_ACCESS_KEY_ID /
AS3CF_S3COMPAT_SECRET_ACCESS_KEY wp-config.php constants
- Disables AWS-specific features (Block Public Access, Object Ownership)
- New provider SVG icons (s3compatible.svg, -link.svg, -round.svg)
- Registered provider in main plugin class with endpoint setting support
- Updated StorageProviderSubPage to show endpoint URL input for S3-compatible
- Built pro settings bundle with rollup (Svelte 4.2.19)
- Added package.json and updated rollup.config.mjs for pro-only builds
144 lines
4.1 KiB
PHP
144 lines
4.1 KiB
PHP
<?php
|
|
|
|
declare (strict_types=1);
|
|
namespace DeliciousBrains\WP_Offload_Media\Aws3\GuzzleHttp\Promise;
|
|
|
|
use Generator;
|
|
use Throwable;
|
|
/**
|
|
* Creates a promise that is resolved using a generator that yields values or
|
|
* promises (somewhat similar to C#'s async keyword).
|
|
*
|
|
* When called, the Coroutine::of method will start an instance of the generator
|
|
* and returns a promise that is fulfilled with its final yielded value.
|
|
*
|
|
* Control is returned back to the generator when the yielded promise settles.
|
|
* This can lead to less verbose code when doing lots of sequential async calls
|
|
* with minimal processing in between.
|
|
*
|
|
* use GuzzleHttp\Promise;
|
|
*
|
|
* function createPromise($value) {
|
|
* return new Promise\FulfilledPromise($value);
|
|
* }
|
|
*
|
|
* $promise = Promise\Coroutine::of(function () {
|
|
* $value = (yield createPromise('a'));
|
|
* try {
|
|
* $value = (yield createPromise($value . 'b'));
|
|
* } catch (\Throwable $e) {
|
|
* // The promise was rejected.
|
|
* }
|
|
* yield $value . 'c';
|
|
* });
|
|
*
|
|
* // Outputs "abc"
|
|
* $promise->then(function ($v) { echo $v; });
|
|
*
|
|
* @param callable $generatorFn Generator function to wrap into a promise.
|
|
*
|
|
* @return Promise
|
|
*
|
|
* @see https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
|
|
*/
|
|
final class Coroutine implements PromiseInterface
|
|
{
|
|
/**
|
|
* @var PromiseInterface|null
|
|
*/
|
|
private $currentPromise;
|
|
/**
|
|
* @var Generator
|
|
*/
|
|
private $generator;
|
|
/**
|
|
* @var Promise
|
|
*/
|
|
private $result;
|
|
public function __construct(callable $generatorFn)
|
|
{
|
|
$this->generator = $generatorFn();
|
|
$this->result = new Promise(function () : void {
|
|
while (isset($this->currentPromise)) {
|
|
$this->currentPromise->wait();
|
|
}
|
|
});
|
|
try {
|
|
$this->nextCoroutine($this->generator->current());
|
|
} catch (Throwable $throwable) {
|
|
$this->result->reject($throwable);
|
|
}
|
|
}
|
|
/**
|
|
* Create a new coroutine.
|
|
*/
|
|
public static function of(callable $generatorFn) : self
|
|
{
|
|
return new self($generatorFn);
|
|
}
|
|
public function then(?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface
|
|
{
|
|
return $this->result->then($onFulfilled, $onRejected);
|
|
}
|
|
public function otherwise(callable $onRejected) : PromiseInterface
|
|
{
|
|
return $this->result->otherwise($onRejected);
|
|
}
|
|
public function wait(bool $unwrap = \true)
|
|
{
|
|
return $this->result->wait($unwrap);
|
|
}
|
|
public function getState() : string
|
|
{
|
|
return $this->result->getState();
|
|
}
|
|
public function resolve($value) : void
|
|
{
|
|
$this->result->resolve($value);
|
|
}
|
|
public function reject($reason) : void
|
|
{
|
|
$this->result->reject($reason);
|
|
}
|
|
public function cancel() : void
|
|
{
|
|
$this->currentPromise->cancel();
|
|
$this->result->cancel();
|
|
}
|
|
private function nextCoroutine($yielded) : void
|
|
{
|
|
$this->currentPromise = Create::promiseFor($yielded)->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
public function _handleSuccess($value) : void
|
|
{
|
|
unset($this->currentPromise);
|
|
try {
|
|
$next = $this->generator->send($value);
|
|
if ($this->generator->valid()) {
|
|
$this->nextCoroutine($next);
|
|
} else {
|
|
$this->result->resolve($value);
|
|
}
|
|
} catch (Throwable $throwable) {
|
|
$this->result->reject($throwable);
|
|
}
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
public function _handleFailure($reason) : void
|
|
{
|
|
unset($this->currentPromise);
|
|
try {
|
|
$nextYield = $this->generator->throw(Create::exceptionFor($reason));
|
|
// The throw was caught, so keep iterating on the coroutine
|
|
$this->nextCoroutine($nextYield);
|
|
} catch (Throwable $throwable) {
|
|
$this->result->reject($throwable);
|
|
}
|
|
}
|
|
}
|