b4400a68e5
Baseline before backporting wp-data-optimizer v3.0.1-v3.4.6. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
169 lines
4.4 KiB
PHP
169 lines
4.4 KiB
PHP
<?php
|
|
/**
|
|
* REST API endpoints for the HivePress family integration.
|
|
*
|
|
* Three read-only endpoints (manage_options capability required):
|
|
*
|
|
* GET /wpdo/v1/hivepress/status → detection + adapter binding state
|
|
* GET /wpdo/v1/hivepress/score → 8-D suitability report
|
|
* GET /wpdo/v1/hivepress/health → doctor probes for each adapter
|
|
*
|
|
* No mutating endpoints in v3.0.0 — `migrate` / `rollback` are CLI-only
|
|
* because they alter site-wide FSM state (Karpathy: high-blast-radius
|
|
* actions need explicit operator intent, not a button click).
|
|
*
|
|
* Bound on `rest_api_init` from wp-data-optimizer.php after the existing
|
|
* `TMDO_REST_API` registration.
|
|
*
|
|
* @package WP_Data_Optimizer
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
if ( ! class_exists( 'TMDO_HivePress_REST' ) ) {
|
|
|
|
/**
|
|
* REST controller for the HivePress integration.
|
|
*/
|
|
final class TMDO_HivePress_REST {
|
|
|
|
/** REST namespace. */
|
|
public const NAMESPACE = 'wpdo/v1';
|
|
|
|
/**
|
|
* Register the three GET routes.
|
|
*/
|
|
public function register_routes(): void {
|
|
register_rest_route(
|
|
self::NAMESPACE,
|
|
'/hivepress/status',
|
|
array(
|
|
'methods' => WP_REST_Server::READABLE,
|
|
'callback' => array( $this, 'get_status' ),
|
|
'permission_callback' => array( $this, 'check_permission' ),
|
|
)
|
|
);
|
|
register_rest_route(
|
|
self::NAMESPACE,
|
|
'/hivepress/score',
|
|
array(
|
|
'methods' => WP_REST_Server::READABLE,
|
|
'callback' => array( $this, 'get_score' ),
|
|
'permission_callback' => array( $this, 'check_permission' ),
|
|
)
|
|
);
|
|
register_rest_route(
|
|
self::NAMESPACE,
|
|
'/hivepress/health',
|
|
array(
|
|
'methods' => WP_REST_Server::READABLE,
|
|
'callback' => array( $this, 'get_health' ),
|
|
'permission_callback' => array( $this, 'check_permission' ),
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Capability check — operator-only (manage_options).
|
|
*
|
|
* @return bool|\WP_Error
|
|
*/
|
|
public function check_permission() {
|
|
if ( ! function_exists( 'current_user_can' ) || ! current_user_can( 'manage_options' ) ) {
|
|
return new WP_Error(
|
|
'wpdo_hp_forbidden',
|
|
__( 'You do not have permission to read HivePress integration data.', 'tmdo-hivepress' ),
|
|
array( 'status' => 403 )
|
|
);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* GET /hivepress/status — detection + binding state.
|
|
*/
|
|
public function get_status() {
|
|
$detected = class_exists( 'TMDO_HivePress_Detector' )
|
|
? TMDO_HivePress_Detector::detect()
|
|
: array();
|
|
$catalog = class_exists( 'TMDO_HivePress_Detector' )
|
|
? TMDO_HivePress_Detector::catalog()
|
|
: array();
|
|
$bound = class_exists( 'TMDO_HivePress_Bootstrap' )
|
|
? array_keys( TMDO_HivePress_Bootstrap::adapters() )
|
|
: array();
|
|
$conflict = class_exists( 'TMDO_HivePress_Conflict_Guard' )
|
|
? TMDO_HivePress_Conflict_Guard::detect_conflicts()
|
|
: array();
|
|
|
|
$addons = array();
|
|
foreach ( $catalog as $slug => $name ) {
|
|
$addons[] = array(
|
|
'slug' => $slug,
|
|
'name' => $name,
|
|
'detected' => isset( $detected[ $slug ] ),
|
|
'version' => $detected[ $slug ] ?? null,
|
|
'bound' => in_array( $slug, $bound, true ),
|
|
);
|
|
}
|
|
|
|
return new WP_REST_Response(
|
|
array(
|
|
'addons' => $addons,
|
|
'conflicts' => $conflict,
|
|
'totals' => array(
|
|
'detected' => count( $detected ),
|
|
'bound' => count( $bound ),
|
|
'catalog' => count( $catalog ),
|
|
),
|
|
),
|
|
200
|
|
);
|
|
}
|
|
|
|
/**
|
|
* GET /hivepress/score — 8-D suitability report.
|
|
*/
|
|
public function get_score() {
|
|
if ( ! class_exists( 'TMDO_HivePress_Suitability_Scorer' ) ) {
|
|
return new WP_REST_Response( array( 'error' => 'scorer_unavailable' ), 503 );
|
|
}
|
|
return new WP_REST_Response( TMDO_HivePress_Suitability_Scorer::report(), 200 );
|
|
}
|
|
|
|
/**
|
|
* GET /hivepress/health — doctor probes for each adapter.
|
|
*/
|
|
public function get_health() {
|
|
$adapters = class_exists( 'TMDO_HivePress_Bootstrap' )
|
|
? TMDO_HivePress_Bootstrap::adapters()
|
|
: array();
|
|
|
|
$probes = array();
|
|
$ok = true;
|
|
foreach ( $adapters as $slug => $adapter ) {
|
|
if ( ! $adapter instanceof TMDO_HivePress_Adapter ) {
|
|
continue;
|
|
}
|
|
$probe = $adapter->doctor_check();
|
|
$probes[ $slug ] = $probe;
|
|
if ( empty( $probe['ok'] ) ) {
|
|
$ok = false;
|
|
}
|
|
}
|
|
|
|
return new WP_REST_Response(
|
|
array(
|
|
'ok' => $ok,
|
|
'probes' => $probes,
|
|
),
|
|
200
|
|
);
|
|
}
|
|
}
|
|
|
|
} // end if ( ! class_exists )
|