RcmEmailAutomation / sa-orchestration /includes /class-sa-demand-registry.php
NujacsaintS's picture
reseed
f51c224
Raw
History Blame Contribute Delete
3.1 kB
<?php
defined( 'ABSPATH' ) || exit;
/**
* Demand Registration Hook.
*
* A surface object (ticket, task, subscriber) is NOT automatically a
* Demand. It exists operationally on its surface (Fluent Support, Fluent
* Boards, FluentCRM) but is invisible to Asterion's trace/audit/closure
* logic until explicitly registered.
*
* This class provides that registration. It writes an arbitration row
* (the canonical first entry of a Demand lifecycle) through the surface
* adapter — never via direct $wpdb access to surface tables.
*
* v1 surface: a single static method, callable from PHP. Future:
* an admin UI button or REST endpoint can wrap this.
*
* Demand Registration Boundary (per doctrine):
* - Unregistered surface objects remain operational but do NOT
* participate in trace, audit, or closure logic.
* - They are referred to as "untracked demand candidates" until
* registered.
*/
class SA_Orch_Demand_Registry {
/**
* Register a surface object as an Asterion Demand.
*
* @param string $surface Surface id (must have a registered adapter).
* @param string $ref Surface-specific ref (must validate via adapter).
* @param string $rationale Human-readable rationale for arbitration.
* @param string $projection_type Default 'scope-direct-no-plan'; see SA_Orch_Arbitration::write.
* @param string $truth_class Default 'canonical'.
*
* @return array|WP_Error Arbitration row data on success; WP_Error on failure.
*/
public static function register(
string $surface,
string $ref,
string $rationale,
string $projection_type = 'scope-direct-no-plan',
string $truth_class = 'canonical'
) {
$adapter = SA_Orch_Bridge_Fluent::adapter_for( $surface );
if ( ! $adapter ) {
return new WP_Error(
'no_adapter',
"No surface adapter registered for '{$surface}'."
);
}
if ( ! $adapter->validate( $ref ) ) {
return new WP_Error(
'invalid_ref',
"Ref '{$ref}' does not resolve under the '{$surface}' adapter."
);
}
return SA_Orch_Arbitration::write( [
'demand_surface' => $surface,
'demand_ref' => $ref,
'rationale' => $rationale,
'projection_type' => $projection_type,
'truth_class' => $truth_class,
] );
}
/**
* Convenience: is this surface object already registered as a Demand?
* Returns true if at least one arbitration exists for the (surface, ref) pair.
*/
public static function is_registered( string $surface, string $ref ): bool {
global $wpdb;
$arb_table = $wpdb->prefix . SA_ORCH_DB_PREFIX . 'arbitration';
$count = (int) $wpdb->get_var( $wpdb->prepare(
"SELECT COUNT(*) FROM {$arb_table} WHERE demand_surface = %s AND demand_ref = %s",
$surface, $ref
) );
return $count > 0;
}
}