feat: add content handler registry
This commit is contained in:
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Content package handler boundary.
|
||||||
|
*
|
||||||
|
* @package WPContentSync
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WPContentSync\Content;
|
||||||
|
|
||||||
|
use WPContentSync\Sync\SyncContext;
|
||||||
|
use WPContentSync\Sync\SyncResult;
|
||||||
|
|
||||||
|
interface ContentHandlerInterface {
|
||||||
|
public function bucket(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, array<string, mixed>> $records Package records for this handler bucket.
|
||||||
|
*/
|
||||||
|
public function importRecords( array $records, SyncContext $context ): SyncResult;
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Ordered content handler registry.
|
||||||
|
*
|
||||||
|
* @package WPContentSync
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WPContentSync\Content;
|
||||||
|
|
||||||
|
final class ContentHandlerRegistry {
|
||||||
|
private const PACKAGE_ORDER = array(
|
||||||
|
'custom_post_types',
|
||||||
|
'terms',
|
||||||
|
'posts',
|
||||||
|
'media',
|
||||||
|
);
|
||||||
|
|
||||||
|
/** @var array<string, ContentHandlerInterface> */
|
||||||
|
private array $handlers = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, ContentHandlerInterface> $handlers Content handlers.
|
||||||
|
*/
|
||||||
|
public function __construct( array $handlers ) {
|
||||||
|
foreach ( $handlers as $handler ) {
|
||||||
|
$this->register( $handler );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function register( ContentHandlerInterface $handler ): void {
|
||||||
|
$bucket = $handler->bucket();
|
||||||
|
|
||||||
|
if ( isset( $this->handlers[ $bucket ] ) ) {
|
||||||
|
throw new \InvalidArgumentException( sprintf( 'Handler bucket "%s" is already registered.', $bucket ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->handlers[ $bucket ] = $handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, ContentHandlerInterface>
|
||||||
|
*/
|
||||||
|
public function ordered(): array {
|
||||||
|
$ordered = array();
|
||||||
|
|
||||||
|
foreach ( self::PACKAGE_ORDER as $bucket ) {
|
||||||
|
if ( isset( $this->handlers[ $bucket ] ) ) {
|
||||||
|
$ordered[] = $this->handlers[ $bucket ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ordered;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Typed content import failure.
|
||||||
|
*
|
||||||
|
* @package WPContentSync
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WPContentSync\Content;
|
||||||
|
|
||||||
|
final class ContentImportException extends \RuntimeException {
|
||||||
|
private string $bucket;
|
||||||
|
|
||||||
|
/** @var array<string, mixed> */
|
||||||
|
private array $record;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $record Content record that failed.
|
||||||
|
*/
|
||||||
|
public function __construct( string $bucket, array $record, string $message, ?\Throwable $previous = null ) {
|
||||||
|
parent::__construct( $message, 0, $previous );
|
||||||
|
|
||||||
|
$this->bucket = $bucket;
|
||||||
|
$this->record = $record;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bucket(): string {
|
||||||
|
return $this->bucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function record(): array {
|
||||||
|
return $this->record;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Tests for content handler registry.
|
||||||
|
*
|
||||||
|
* @package WPContentSync
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WPContentSync\Tests\Unit\Content;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use WPContentSync\Content\ContentHandlerInterface;
|
||||||
|
use WPContentSync\Content\ContentHandlerRegistry;
|
||||||
|
use WPContentSync\Sync\SyncContext;
|
||||||
|
use WPContentSync\Sync\SyncResult;
|
||||||
|
|
||||||
|
class ContentHandlerRegistryTest extends TestCase {
|
||||||
|
public function test_it_returns_handlers_in_package_order(): void {
|
||||||
|
$posts = $this->handler( 'posts' );
|
||||||
|
$terms = $this->handler( 'terms' );
|
||||||
|
$media = $this->handler( 'media' );
|
||||||
|
|
||||||
|
$registry = new ContentHandlerRegistry( array( $media, $posts, $terms ) );
|
||||||
|
|
||||||
|
self::assertSame( array( $terms, $posts, $media ), $registry->ordered() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_it_rejects_duplicate_buckets(): void {
|
||||||
|
$this->expectException( \InvalidArgumentException::class );
|
||||||
|
$this->expectExceptionMessage( 'Handler bucket "posts" is already registered.' );
|
||||||
|
|
||||||
|
new ContentHandlerRegistry( array( $this->handler( 'posts' ), $this->handler( 'posts' ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handler( string $bucket ): ContentHandlerInterface {
|
||||||
|
return new class( $bucket ) implements ContentHandlerInterface {
|
||||||
|
private string $bucket;
|
||||||
|
|
||||||
|
public function __construct( string $bucket ) {
|
||||||
|
$this->bucket = $bucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bucket(): string {
|
||||||
|
return $this->bucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, array<string, mixed>> $records Package records.
|
||||||
|
*/
|
||||||
|
public function importRecords( array $records, SyncContext $context ): SyncResult {
|
||||||
|
return SyncResult::success( array( 'skipped' => count( $records ) ) );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user