is_pro_active = $is_pro_active ?? array( __CLASS__, 'default_is_pro_active' ); $this->is_pro_installed = $is_pro_installed ?? array( __CLASS__, 'default_is_pro_installed' ); $this->allows_pro_execution = $allows_pro_execution ?? static function () { return ( new EntitlementService() )->resolve()->allows_pro_execution(); }; $this->is_direct = $is_direct ?? array( DistributionChannel::class, 'is_direct' ); } /** * Resolved state. * * @return string One of the STATE_* constants. */ public function resolve() { if ( call_user_func( $this->is_direct ) ) { return self::STATE_DIRECT; } $active = (bool) call_user_func( $this->is_pro_active ); if ( $active ) { return call_user_func( $this->allows_pro_execution ) ? self::STATE_PRO_ACTIVE : self::STATE_PRO_ACTIVE_NOT_ENTITLED; } return call_user_func( $this->is_pro_installed ) ? self::STATE_PRO_INSTALLED_INACTIVE : self::STATE_FREE_ONLY; } /** * Whether the current state warrants a primary purchase/upgrade CTA. * * @return bool */ public function shows_upgrade_cta() { return self::STATE_FREE_ONLY === $this->resolve(); } /** * Whether Pro is installed but inactive (activation prompt, not purchase). * * @return bool */ public function is_pro_installed_inactive() { return self::STATE_PRO_INSTALLED_INACTIVE === $this->resolve(); } /** * Whether Pro is active but not entitled (license setup prompt, not purchase). * * @return bool */ public function is_pro_active_not_entitled() { return self::STATE_PRO_ACTIVE_NOT_ENTITLED === $this->resolve(); } /** * Whether Pro is active and fully entitled (hide all CTA/price). * * @return bool */ public function is_pro_active_entitled() { return self::STATE_PRO_ACTIVE === $this->resolve(); } /** * Whether the single-package Direct edition is active. * * @return bool */ public function is_direct() { return self::STATE_DIRECT === $this->resolve(); } /** * Human-readable label for a state (for tests / logs). * * @param string $state State constant. * @return string */ public static function label( $state ) { switch ( $state ) { case self::STATE_DIRECT: return 'Direct Edition'; case self::STATE_PRO_INSTALLED_INACTIVE: return 'Pro installed (inactive)'; case self::STATE_PRO_ACTIVE_NOT_ENTITLED: return 'Pro active (not entitled)'; case self::STATE_PRO_ACTIVE: return 'Pro active'; case self::STATE_FREE_ONLY: default: return 'Free-only'; } } /** * Default active detector using the WordPress plugin API. * * @return bool */ private static function default_is_pro_active() { if ( ! function_exists( 'is_plugin_active' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } if ( ! function_exists( 'is_plugin_active' ) ) { return false; } return is_plugin_active( Constants::PRO_PLUGIN_BASENAME ); } /** * Default installed detector using the WordPress plugin API. * * @return bool */ private static function default_is_pro_installed() { if ( ! function_exists( 'get_plugins' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } if ( ! function_exists( 'get_plugins' ) ) { return false; } $plugins = get_plugins(); return isset( $plugins[ Constants::PRO_PLUGIN_BASENAME ] ); } }