Spaces:
Sleeping
Sleeping
| defined( 'ABSPATH' ) || exit; | |
| /** | |
| * Logical bridge to Fluent (and other) surface tables. | |
| * Closed enumeration — extending requires touching this class. | |
| * Per SA-Core invariants I1 + I8: no DB-level FK to surface tables. | |
| */ | |
| class SA_Orch_Bridge_Fluent { | |
| /** | |
| * Resolve a (surface, ref) to the underlying surface row, or null. | |
| * The 'derived' surface intentionally returns null — it has no row. | |
| */ | |
| public static function resolve( $surface, $ref ) { | |
| global $wpdb; | |
| if ( $surface === 'derived' ) { | |
| return null; | |
| } | |
| if ( $surface === 'fluent-support' && preg_match( '/^ticket#(\d+)$/', $ref, $m ) ) { | |
| return $wpdb->get_row( $wpdb->prepare( | |
| "SELECT * FROM {$wpdb->prefix}fs_tickets WHERE id = %d", | |
| (int) $m[1] | |
| ) ); | |
| } | |
| if ( $surface === 'fluent-boards' && preg_match( '/^task#(\d+)$/', $ref, $m ) ) { | |
| return $wpdb->get_row( $wpdb->prepare( | |
| "SELECT * FROM {$wpdb->prefix}fbs_tasks WHERE id = %d", | |
| (int) $m[1] | |
| ) ); | |
| } | |
| if ( $surface === 'fluentcrm' && preg_match( '/^subscriber#(\d+)$/', $ref, $m ) ) { | |
| return $wpdb->get_row( $wpdb->prepare( | |
| "SELECT * FROM {$wpdb->prefix}fc_subscribers WHERE id = %d", | |
| (int) $m[1] | |
| ) ); | |
| } | |
| return null; | |
| } | |
| /** | |
| * True if the surface/ref pair points to a real row OR is the | |
| * 'derived' surface (legitimately rowless). False otherwise. | |
| */ | |
| public static function validate( $surface, $ref ) { | |
| if ( $surface === 'derived' ) { | |
| return $ref !== '' && preg_match( '/^derived#[A-Za-z0-9_\-]+$/', $ref ); | |
| } | |
| return self::resolve( $surface, $ref ) !== null; | |
| } | |
| /** Recognized surface vocabulary (closed set). */ | |
| public static function known_surfaces() { | |
| return [ 'fluent-support', 'fluent-boards', 'fluentcrm', 'derived' ]; | |
| } | |
| /** | |
| * Surface adapter factory. | |
| * | |
| * Returns the adapter for a given surface, or null if no adapter is | |
| * registered yet. Adapters are the safe path to surface data — | |
| * external schema knowledge is bounded to the adapter file. Direct | |
| * $wpdb access to surface tables in callers is the legacy path; new | |
| * code should route through the adapter. | |
| * | |
| * v0.7.0 shipped one adapter (fluent-boards). Board #18 added | |
| * fluent-support to the contract. fluentcrm and derived still resolve | |
| * via the legacy paths in resolve() / validate() above; that carryover | |
| * stays until those surfaces are ported (deferred Board #18 scope). | |
| */ | |
| public static function adapter_for( string $surface ): ?SA_Orch_Surface_Adapter { | |
| switch ( $surface ) { | |
| case 'fluent-boards': | |
| return new SA_Orch_Adapter_FluentBoards(); | |
| case 'fluent-support': | |
| return new SA_Orch_Adapter_FluentSupport(); | |
| // Deferred (later Board): | |
| // case 'fluentcrm': return new SA_Orch_Adapter_FluentCRM(); | |
| // case 'derived': return new SA_Orch_Adapter_Derived(); | |
| } | |
| return null; | |
| } | |
| } | |