✨feature: Initial functional push
This commit is contained in:
245
includes/class-rest-controller.php
Normal file
245
includes/class-rest-controller.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
|
||||
namespace SiteSync;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* REST controller for Site Sync plugin.
|
||||
*
|
||||
* Handles REST API endpoints for synchronization, media, and authentication.
|
||||
*/
|
||||
class REST_Controller {
|
||||
private const ROUTE_NAMESPACE = 'site-sync/v1';
|
||||
|
||||
/**
|
||||
* Settings instance.
|
||||
*
|
||||
* @var Settings
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* Sync_Engine instance.
|
||||
*
|
||||
* @var Sync_Engine
|
||||
*/
|
||||
private $engine;
|
||||
|
||||
/**
|
||||
* REST_Controller constructor.
|
||||
*
|
||||
* @param Settings $settings Settings instance.
|
||||
* @param Sync_Engine $engine Sync_Engine instance.
|
||||
*/
|
||||
public function __construct( Settings $settings, Sync_Engine $engine ) {
|
||||
$this->settings = $settings;
|
||||
$this->engine = $engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers REST API hooks for the Site Sync plugin.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function hooks(): void {
|
||||
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all REST API routes for the Site Sync plugin.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_routes(): void {
|
||||
register_rest_route(
|
||||
self::ROUTE_NAMESPACE,
|
||||
'/handshake',
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
'callback' => array( $this, 'handshake' ),
|
||||
'permission_callback' => '__return_true',
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
self::ROUTE_NAMESPACE,
|
||||
'/inbox',
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
'callback' => array( $this, 'receive_inbox' ),
|
||||
'permission_callback' => array( $this, 'check_auth' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
self::ROUTE_NAMESPACE,
|
||||
'/outbox',
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
'callback' => array( $this, 'send_outbox' ),
|
||||
'permission_callback' => array( $this, 'check_auth' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
self::ROUTE_NAMESPACE,
|
||||
'/media',
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
'callback' => array( $this, 'handle_media' ),
|
||||
'permission_callback' => array( $this, 'check_auth' ),
|
||||
'args' => array(
|
||||
'external_id' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
),
|
||||
'mime_type' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
),
|
||||
'filename' => array(
|
||||
'required' => false,
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
self::ROUTE_NAMESPACE,
|
||||
'/media',
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
'callback' => array( $this, 'send_media' ),
|
||||
'permission_callback' => array( $this, 'check_auth' ),
|
||||
'args' => array(
|
||||
'external_id' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the handshake endpoint for the Site Sync plugin.
|
||||
*
|
||||
* Returns basic site and plugin information for synchronization.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function handshake() {
|
||||
$settings = $this->settings->ensure_defaults();
|
||||
|
||||
return new WP_REST_Response(
|
||||
array(
|
||||
'site_uuid' => $settings['site_uuid'],
|
||||
'schema' => 'v1',
|
||||
'site_url' => home_url(),
|
||||
'version' => SITE_SYNC_VERSION,
|
||||
'capabilities' => array(
|
||||
'content' => true,
|
||||
'taxonomies' => true,
|
||||
'media' => true,
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the inbox endpoint for receiving synchronization payloads.
|
||||
*
|
||||
* @param WP_REST_Request $request The REST request object containing the payload.
|
||||
* @return WP_REST_Response The response after processing the inbox payload.
|
||||
*/
|
||||
public function receive_inbox( WP_REST_Request $request ) {
|
||||
$payload = $request->get_json_params() ? $request->get_json_params() : array();
|
||||
$result = $this->engine->handle_inbox( $payload );
|
||||
|
||||
return new WP_REST_Response( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the outbox endpoint for sending synchronization payloads.
|
||||
*
|
||||
* @return WP_REST_Response The response containing the outbox payload.
|
||||
*/
|
||||
public function send_outbox() {
|
||||
$result = $this->engine->provide_outbox( true );
|
||||
$this->engine->commit_outbox( $result['cursor'], $result['meta']['counts'] ?? array() );
|
||||
|
||||
if ( isset( $result['meta'] ) ) {
|
||||
unset( $result['meta'] );
|
||||
}
|
||||
|
||||
return new WP_REST_Response( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the media endpoint for receiving and storing media files.
|
||||
*
|
||||
* @param WP_REST_Request $request The REST request object containing media data.
|
||||
* @return WP_REST_Response|WP_Error The response after processing the media upload or WP_Error on failure.
|
||||
*/
|
||||
public function handle_media( WP_REST_Request $request ) {
|
||||
$result = $this->engine->receive_media_stream( $request );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return new WP_REST_Response(
|
||||
array(
|
||||
'status' => 'ok',
|
||||
'stored' => $result,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the media endpoint for sending media files.
|
||||
*
|
||||
* @param WP_REST_Request $request The REST request object containing the external_id parameter.
|
||||
* @return WP_REST_Response|WP_Error The response containing the media file or WP_Error on failure.
|
||||
*/
|
||||
public function send_media( WP_REST_Request $request ) {
|
||||
$externalId = $request->get_param( 'external_id' );
|
||||
$media = $this->engine->get_media_file( $externalId );
|
||||
|
||||
if ( is_wp_error( $media ) ) {
|
||||
return $media;
|
||||
}
|
||||
|
||||
$response = new WP_REST_Response( $media['contents'] );
|
||||
$response->set_status( 200 );
|
||||
$response->header( 'Content-Type', $media['mime'] );
|
||||
$response->header( 'Content-Disposition', 'attachment; filename="' . $media['filename'] . '"' );
|
||||
$response->header( 'X-Site-Sync-Checksum', $media['checksum'] );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks authentication for REST API requests.
|
||||
*
|
||||
* @param WP_REST_Request $request The REST request object.
|
||||
* @return true|WP_Error True if authentication passes, WP_Error otherwise.
|
||||
*/
|
||||
public function check_auth( WP_REST_Request $request ) {
|
||||
$result = Auth::verify( $request, $this->settings );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user