self::sanitize_status( $raw['status'] ), 'updated_at_gmt' => isset( $raw['updated_at_gmt'] ) ? (string) $raw['updated_at_gmt'] : '', 'source' => isset( $raw['source'] ) ? self::sanitize_source( $raw['source'] ) : 'unknown', 'message' => isset( $raw['message'] ) ? self::sanitize_message( $raw['message'] ) : '', ); } /** * @param string $status Status. * @param string $source Source key (local|marketplace|simulated). * @param string $message Optional notice. * @return void */ public static function write( $status, $source = 'local', $message = '' ) { update_option( Constants::OPTION_ENTITLEMENT_STATE, array( 'status' => self::sanitize_status( $status ), 'updated_at_gmt' => gmdate( 'Y-m-d H:i:s' ), 'source' => self::sanitize_source( $source ), 'message' => self::sanitize_message( $message ), ), false ); } /** * @param mixed $raw Source key. * @return string */ public static function sanitize_source( $raw ) { $source = preg_replace( '/[^a-z0-9_\-]/', '', strtolower( (string) $raw ) ); return '' !== $source ? $source : 'unknown'; } /** * @param mixed $raw Message. * @return string */ public static function sanitize_message( $raw ) { return trim( wp_strip_all_tags( (string) $raw ) ); } /** * Ensure a state row exists (first Pro boot). * * @return void */ public static function ensure_default_active() { if ( ! EntitlementBootstrap::allows_dev_bootstrap() ) { return; } $raw = get_option( Constants::OPTION_ENTITLEMENT_STATE, null ); if ( ! is_array( $raw ) || empty( $raw['status'] ) ) { self::write( self::STATUS_ACTIVE, 'companion', '' ); } } /** * Map stored status to CapabilitySet. * * @param string $status Status. * @return CapabilitySet */ public static function to_capability_set( $status ) { switch ( self::sanitize_status( $status ) ) { case self::STATUS_EXPIRED: return CapabilitySet::expired(); case self::STATUS_UNAVAILABLE: return CapabilitySet::unavailable(); case self::STATUS_CORRUPTED: return CapabilitySet::corrupted(); case self::STATUS_ACTIVE: default: return CapabilitySet::pro(); } } /** * Merchant-facing tier label. * * @param string $tier CapabilitySet tier or entitlement status. * @return string */ public static function label( $tier ) { switch ( (string) $tier ) { case 'direct': return __( 'Direct Edition', 'marginbeacon' ); case 'pro': case self::STATUS_ACTIVE: return __( 'Pro (active)', 'marginbeacon' ); case self::STATUS_EXPIRED: case 'expired': return __( 'Pro expired', 'marginbeacon' ); case self::STATUS_UNAVAILABLE: case 'unavailable': return __( 'Pro unavailable', 'marginbeacon' ); case self::STATUS_CORRUPTED: case 'corrupted': return __( 'Pro entitlement corrupted', 'marginbeacon' ); case 'free': default: return __( 'Free', 'marginbeacon' ); } } /** * @return array{status:string,updated_at_gmt:string,source:string,message:string} */ private static function default_state() { return array( 'status' => self::STATUS_UNAVAILABLE, 'updated_at_gmt' => '', 'source' => '', 'message' => '', ); } /** * Prevent instantiation. */ private function __construct() {} }