checkpoint = $ids['checkpoint']; $this->ledger = $ids['ledger']; $this->measured = $ids['measured']; } /** * Resolve all three from the shared AJAX debug context. * * Read together, in one place, so the three sources cannot be paired with * the wrong scope at a call site. */ public static function fromGlobalContext(): self { $context = $GLOBALS['abj404_ajax_context'] ?? null; $checkpoint = ''; $measured = ''; if (is_array($context) && class_exists('ABJ_404_Solution_AjaxDiagnosticRequestPolicy')) { try { // These explicit-context methods existed before this value // object was introduced. During an in-flight plugin update, // PHP may retain the previous release's already-loaded policy // class while loading this current file from disk. $checkpoint = ABJ_404_Solution_AjaxDiagnosticRequestPolicy::instrumentedRequestId($context); $measured = ABJ_404_Solution_AjaxDiagnosticRequestPolicy::diagnosticRequestId($context); } catch (Throwable $error) { abj404_logPhpFallback( 'ajax-request-id-scopes', get_class($error) . ' code ' . $error->getCode() . ': ' . $error->getMessage() ); } } return new self(array( 'checkpoint' => $checkpoint, 'ledger' => ABJ_404_Solution_AjaxRequestLedger::requestIdFromGlobalContext(), 'measured' => $measured, )); } /** The instrumented table endpoint's micro-boundary scope, or ''. */ public function checkpoint(): string { return $this->checkpoint; } /** The immutable request ledger's ID, or ''. */ public function ledger(): string { return $this->ledger; } /** The scope a durable size record is written under, or ''. */ public function measured(): string { return $this->measured; } /** * Whether this response carries the instrumented endpoint's micro-boundary * checkpoints. Named because the bare `=== ''` comparison appears at six * branch points and reads as a null check rather than as the gate it is. */ public function hasCheckpoints(): bool { return $this->checkpoint !== ''; } }