init_components(); // Action links on plugins page. add_filter( 'plugin_action_links_' . ABHINAVDEV_ENV_BADGE_BASENAME, array( $this, 'add_plugin_action_links' ) ); } /** * Initialize plugin sub-components. */ private function init_components() { $this->settings = new Abhinavdev_Env_Badge_Settings(); $this->admin_bar = new Abhinavdev_Env_Badge_Admin_Bar(); } /** * Add 'Settings' action link on Plugins listing screen. * * @param array $links Existing plugin links. * @return array */ public function add_plugin_action_links( $links ) { $settings_link = sprintf( '%s', esc_url( admin_url( 'options-general.php?page=abhinavdev-environment-badge' ) ), esc_html__( 'Settings', 'abhinavdev-environment-badge' ) ); array_unshift( $links, $settings_link ); return $links; } /** * Retrieve default options for the plugin. * * @return array */ public static function get_default_options() { return array( 'mode' => 'auto', // 'auto' or 'manual'. 'manual_env' => 'production', 'production_domain' => '', // Primary production domain (e.g. mysite.com). 'custom_label' => '', 'show_on_frontend' => 1, // Show for logged-in admins on frontend. 'show_on_backend' => 1, // Show in wp-admin. 'show_details_popup' => 1, // Show dropdown with system details (PHP, WP, IP). 'badge_position' => 'right', // 'left' or 'right'. // Color schemes for each environment. 'colors' => array( 'production' => array( 'bg' => '#dc2626', // Red. 'text' => '#ffffff', 'text_label' => 'LIVE PRODUCTION', ), 'staging' => array( 'bg' => '#ea580c', // Orange. 'text' => '#ffffff', 'text_label' => 'STAGING SERVER', ), 'development' => array( 'bg' => '#2563eb', // Blue. 'text' => '#ffffff', 'text_label' => 'DEVELOPMENT', ), 'local' => array( 'bg' => '#16a34a', // Green. 'text' => '#ffffff', 'text_label' => 'LOCAL DEV', ), 'custom' => array( 'bg' => '#7c3aed', // Purple. 'text' => '#ffffff', 'text_label' => 'CUSTOM ENV', ), ), ); } /** * Retrieve saved plugin options merged with defaults. * * @return array */ public static function get_options() { $defaults = self::get_default_options(); $saved = get_option( self::OPTION_NAME, array() ); if ( ! is_array( $saved ) ) { return $defaults; } $options = wp_parse_args( $saved, $defaults ); // Ensure colors sub-array is properly merged. if ( isset( $saved['colors'] ) && is_array( $saved['colors'] ) ) { foreach ( $defaults['colors'] as $key => $color_defaults ) { if ( isset( $saved['colors'][ $key ] ) && is_array( $saved['colors'][ $key ] ) ) { $options['colors'][ $key ] = wp_parse_args( $saved['colors'][ $key ], $color_defaults ); } else { $options['colors'][ $key ] = $color_defaults; } } } return $options; } /** * Detect current environment type. * Evaluates explicit constants, known hosting preview domains, * user-defined production domain, and WP core environment settings. * * @return string 'production'|'staging'|'development'|'local' */ public static function detect_environment() { $options = self::get_options(); $host = wp_parse_url( home_url(), PHP_URL_HOST ); $host = ! empty( $host ) ? strtolower( trim( $host ) ) : ''; // 1. Explicit constant set by user or host in wp-config.php. if ( defined( 'WP_ENVIRONMENT_TYPE' ) && in_array( WP_ENVIRONMENT_TYPE, array( 'production', 'staging', 'development', 'local' ), true ) ) { return WP_ENVIRONMENT_TYPE; } if ( defined( 'WP_ENV' ) && in_array( strtolower( WP_ENV ), array( 'production', 'staging', 'development', 'local' ), true ) ) { return strtolower( WP_ENV ); } // 2. Local environment detection. if ( ! empty( $host ) ) { if ( 'localhost' === $host || '127.0.0.1' === $host || '::1' === $host ) { return 'local'; } if ( preg_match( '/\.(local|test|localhost|ddev\.site|lndo\.site|site\.test)$/i', $host ) ) { return 'local'; } } // 3. Known Hosting Provider Preview / Staging Domains. // These domains are temporary sandbox/preview URLs provided by major hosts. if ( ! empty( $host ) ) { $hosting_staging_patterns = array( 'hostingersite\.com', // Hostinger preview/staging 'sg-host\.com', // SiteGround preview 'wpenginepowered\.com', // WP Engine preview 'wpengine\.com', // WP Engine staging 'kinsta\.cloud', // Kinsta staging 'cloudwaysapps\.com', // Cloudways staging 'flywheelsites\.com', // Flywheel staging 'pantheonsite\.io', // Pantheon staging/dev 'mybluehost\.me', // Bluehost temporary preview 'dreamhosters\.com', // DreamHost preview 'pressdns\.com', // Pagely staging ); if ( preg_match( '/\.(' . implode( '|', $hosting_staging_patterns ) . ')$/i', $host ) ) { return 'staging'; } // Subdomain and keyword heuristics for staging/dev. if ( preg_match( '/(^|\.)(staging|stg|stage|dev|development|test|testing|uat|demo|sandbox)\./i', $host ) ) { return 'staging'; } } // 4. Production Domain matching (if configured by user). // If the user set a Production Domain, any host matching it is production; // any other host (cloned staging, preview, etc.) automatically becomes staging! if ( ! empty( $options['production_domain'] ) && ! empty( $host ) ) { $prod_domain = strtolower( trim( $options['production_domain'] ) ); $parsed_prod = wp_parse_url( $prod_domain, PHP_URL_HOST ); if ( ! empty( $parsed_prod ) ) { $prod_domain = $parsed_prod; } $prod_domain = preg_replace( '/^www\./', '', $prod_domain ); $clean_host = preg_replace( '/^www\./', '', $host ); if ( $clean_host === $prod_domain ) { return 'production'; } return 'staging'; } // 5. WordPress Core function if explicitly set to non-default. if ( function_exists( 'wp_get_environment_type' ) ) { $wp_env = wp_get_environment_type(); if ( in_array( $wp_env, array( 'staging', 'development', 'local' ), true ) ) { return $wp_env; } } // 6. Default fallback to production for safety. return 'production'; } /** * Get badge details for current render (label, bg color, text color, env type). * * @return array */ public static function get_badge_data() { $options = self::get_options(); // Determine which environment type is active. if ( 'manual' === $options['mode'] ) { $env = $options['manual_env']; } else { $env = self::detect_environment(); } $config = isset( $options['colors'][ $env ] ) ? $options['colors'][ $env ] : $options['colors']['production']; // Check for custom label override. $label = ! empty( $options['custom_label'] ) ? $options['custom_label'] : $config['text_label']; return array( 'environment' => $env, 'label' => $label, 'bg_color' => $config['bg'], 'text_color' => $config['text'], ); } }