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
149 lines
5.5 KiB
PHP
149 lines
5.5 KiB
PHP
<?php
|
|
|
|
namespace DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Serializer;
|
|
|
|
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\MapShape;
|
|
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Service;
|
|
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\Shape;
|
|
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\StructureShape;
|
|
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\ListShape;
|
|
use DeliciousBrains\WP_Offload_Media\Aws3\Aws\Api\TimestampShape;
|
|
use XMLWriter;
|
|
/**
|
|
* @internal Formats the XML body of a REST-XML services.
|
|
*/
|
|
class XmlBody
|
|
{
|
|
/** @var \Aws\Api\Service */
|
|
private $api;
|
|
/**
|
|
* @param Service $api API being used to create the XML body.
|
|
*/
|
|
public function __construct(Service $api)
|
|
{
|
|
$this->api = $api;
|
|
}
|
|
/**
|
|
* Builds the XML body based on an array of arguments.
|
|
*
|
|
* @param Shape $shape Operation being constructed
|
|
* @param array $args Associative array of arguments
|
|
*
|
|
* @return string
|
|
*/
|
|
public function build(Shape $shape, array $args)
|
|
{
|
|
$xml = new XMLWriter();
|
|
$xml->openMemory();
|
|
$xml->startDocument('1.0', 'UTF-8');
|
|
$this->format($shape, $shape['locationName'] ?: $shape['name'], $args, $xml);
|
|
$xml->endDocument();
|
|
return $xml->outputMemory();
|
|
}
|
|
private function startElement(Shape $shape, $name, XMLWriter $xml)
|
|
{
|
|
$xml->startElement($name);
|
|
if ($ns = $shape['xmlNamespace']) {
|
|
$xml->writeAttribute(isset($ns['prefix']) ? "xmlns:{$ns['prefix']}" : 'xmlns', $shape['xmlNamespace']['uri']);
|
|
}
|
|
}
|
|
private function format(Shape $shape, $name, $value, XMLWriter $xml)
|
|
{
|
|
// Any method mentioned here has a custom serialization handler.
|
|
static $methods = ['add_structure' => \true, 'add_list' => \true, 'add_blob' => \true, 'add_timestamp' => \true, 'add_boolean' => \true, 'add_map' => \true, 'add_string' => \true];
|
|
$type = 'add_' . $shape['type'];
|
|
if (isset($methods[$type])) {
|
|
$this->{$type}($shape, $name, $value, $xml);
|
|
} else {
|
|
$this->defaultShape($shape, $name, $value, $xml);
|
|
}
|
|
}
|
|
private function defaultShape(Shape $shape, $name, $value, XMLWriter $xml)
|
|
{
|
|
$this->startElement($shape, $name, $xml);
|
|
$xml->text($value);
|
|
$xml->endElement();
|
|
}
|
|
private function add_structure(StructureShape $shape, $name, array $value, \XMLWriter $xml)
|
|
{
|
|
$this->startElement($shape, $name, $xml);
|
|
foreach ($this->getStructureMembers($shape, $value) as $k => $definition) {
|
|
$this->format($definition['member'], $definition['member']['locationName'] ?: $k, $definition['value'], $xml);
|
|
}
|
|
$xml->endElement();
|
|
}
|
|
private function getStructureMembers(StructureShape $shape, array $value)
|
|
{
|
|
$members = [];
|
|
foreach ($value as $k => $v) {
|
|
if ($v !== null && $shape->hasMember($k)) {
|
|
$definition = ['member' => $shape->getMember($k), 'value' => $v];
|
|
if ($definition['member']['xmlAttribute']) {
|
|
// array_unshift_associative
|
|
$members = [$k => $definition] + $members;
|
|
} else {
|
|
$members[$k] = $definition;
|
|
}
|
|
}
|
|
}
|
|
return $members;
|
|
}
|
|
private function add_list(ListShape $shape, $name, array $value, XMLWriter $xml)
|
|
{
|
|
$items = $shape->getMember();
|
|
if ($shape['flattened']) {
|
|
$elementName = $name;
|
|
} else {
|
|
$this->startElement($shape, $name, $xml);
|
|
$elementName = $items['locationName'] ?: 'member';
|
|
}
|
|
foreach ($value as $v) {
|
|
$this->format($items, $elementName, $v, $xml);
|
|
}
|
|
if (!$shape['flattened']) {
|
|
$xml->endElement();
|
|
}
|
|
}
|
|
private function add_map(MapShape $shape, $name, array $value, XMLWriter $xml)
|
|
{
|
|
$xmlEntry = $shape['flattened'] ? $shape['locationName'] : 'entry';
|
|
$xmlKey = $shape->getKey()['locationName'] ?: 'key';
|
|
$xmlValue = $shape->getValue()['locationName'] ?: 'value';
|
|
$this->startElement($shape, $name, $xml);
|
|
foreach ($value as $key => $v) {
|
|
$this->startElement($shape, $xmlEntry, $xml);
|
|
$this->format($shape->getKey(), $xmlKey, $key, $xml);
|
|
$this->format($shape->getValue(), $xmlValue, $v, $xml);
|
|
$xml->endElement();
|
|
}
|
|
$xml->endElement();
|
|
}
|
|
private function add_blob(Shape $shape, $name, $value, XMLWriter $xml)
|
|
{
|
|
$this->startElement($shape, $name, $xml);
|
|
$xml->writeRaw(\base64_encode($value));
|
|
$xml->endElement();
|
|
}
|
|
private function add_timestamp(TimestampShape $shape, $name, $value, XMLWriter $xml)
|
|
{
|
|
$this->startElement($shape, $name, $xml);
|
|
$timestampFormat = !empty($shape['timestampFormat']) ? $shape['timestampFormat'] : 'iso8601';
|
|
$xml->writeRaw(TimestampShape::format($value, $timestampFormat));
|
|
$xml->endElement();
|
|
}
|
|
private function add_boolean(Shape $shape, $name, $value, XMLWriter $xml)
|
|
{
|
|
$this->startElement($shape, $name, $xml);
|
|
$xml->writeRaw($value ? 'true' : 'false');
|
|
$xml->endElement();
|
|
}
|
|
private function add_string(Shape $shape, $name, $value, XMLWriter $xml)
|
|
{
|
|
if ($shape['xmlAttribute']) {
|
|
$xml->writeAttribute($shape['locationName'] ?: $name, $value);
|
|
} else {
|
|
$this->defaultShape($shape, $name, $value, $xml);
|
|
}
|
|
}
|
|
}
|