*/ public static function get_compat_plugins(): array { $plugins = [ // Other plugins that change the login URL. 'wps-hide-login/wps-hide-login.php' => [ 'name' => 'WPS Hide Login', 'severity' => self::SEVERITY_CONFLICT, ], 'better-wp-security/better-wp-security.php' => [ 'name' => 'Solid Security / iThemes Security', 'severity' => self::SEVERITY_CONFLICT, ], 'all-in-one-wp-security-and-firewall/wp-security.php' => [ 'name' => 'All In One WP Security', 'severity' => self::SEVERITY_CONFLICT, ], 'rename-wp-login/rename-wp-login.php' => [ 'name' => 'Rename wp-login.php', 'severity' => self::SEVERITY_CONFLICT, ], 'loginpress/loginpress.php' => [ 'name' => 'LoginPress', 'severity' => self::SEVERITY_CONFLICT, ], // Not on WordPress.org, so this basename is unverified (no copy of the plugin was available to read its header). 'perfmatters/perfmatters.php' => [ 'name' => 'Perfmatters', 'severity' => self::SEVERITY_CONFLICT, ], 'hide-my-wp/index.php' => [ 'name' => 'Hide My WP Ghost', 'severity' => self::SEVERITY_CONFLICT, ], // Plugins that affect login, password reset or 2FA flows. 'woocommerce/woocommerce.php' => [ 'name' => 'WooCommerce', 'severity' => self::SEVERITY_VERIFY, ], 'wordfence/wordfence.php' => [ 'name' => 'Wordfence', 'severity' => self::SEVERITY_VERIFY, ], 'two-factor/two-factor.php' => [ 'name' => 'Two-Factor', 'severity' => self::SEVERITY_VERIFY, ], 'wp-2fa/wp-2fa.php' => [ 'name' => 'WP 2FA', 'severity' => self::SEVERITY_VERIFY, ], 'ultimate-member/ultimate-member.php' => [ 'name' => 'Ultimate Member', 'severity' => self::SEVERITY_VERIFY, ], 'paid-memberships-pro/paid-memberships-pro.php' => [ 'name' => 'Paid Memberships Pro', 'severity' => self::SEVERITY_VERIFY, ], 'theme-my-login/theme-my-login.php' => [ 'name' => 'Theme My Login', 'severity' => self::SEVERITY_VERIFY, ], ]; /** * Filters the plugins checked for login-flow compatibility. * * @param array $plugins Plugin basename => name and * severity ('conflict' or 'verify'). */ $plugins = apply_filters( 'ao_login_url_compat_plugins', $plugins ); return is_array( $plugins ) ? $plugins : []; } /** * Page-caching plugins whose cache the login URL should be excluded from. * WP Rocket is not on WordPress.org, so it is detected by its version * constant instead of a guessed path. * * @return array Plugin basename (or 'const:NAME') => display name. */ public static function get_cache_plugins(): array { $plugins = [ 'const:WP_ROCKET_VERSION' => 'WP Rocket', 'w3-total-cache/w3-total-cache.php' => 'W3 Total Cache', 'wp-super-cache/wp-cache.php' => 'WP Super Cache', 'litespeed-cache/litespeed-cache.php' => 'LiteSpeed Cache', 'wp-fastest-cache/wpFastestCache.php' => 'WP Fastest Cache', 'cache-enabler/cache-enabler.php' => 'Cache Enabler', ]; /** * Filters the page-caching plugins that trigger the cache-exclusion note. * * @param array $plugins Plugin basename (or 'const:NAME') => display name. */ $plugins = apply_filters( 'ao_login_url_cache_plugins', $plugins ); return is_array( $plugins ) ? $plugins : []; } /** * Active plugins that also change the login URL (the "conflict" list only). * One list for the settings box and Site Health, so they cannot drift. Call * only when building the settings screen or Site Health rows. * * @return string[] Display names. */ public static function detect_conflicts(): array { if ( ! function_exists( 'is_plugin_active' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $names = []; foreach ( self::get_compat_plugins() as $basename => $plugin ) { if ( isset( $plugin['name'], $plugin['severity'] ) && self::SEVERITY_CONFLICT === $plugin['severity'] && is_plugin_active( $basename ) ) { $names[] = (string) $plugin['name']; } } return $names; } /** * Detect active plugins. Call only on the module's settings screen. * * @return array{conflict:string[],verify:string[],cache:string[]} Display names. */ public static function detect(): array { if ( ! function_exists( 'is_plugin_active' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $found = [ self::SEVERITY_CONFLICT => [], self::SEVERITY_VERIFY => [], 'cache' => [], ]; foreach ( self::get_compat_plugins() as $basename => $plugin ) { if ( isset( $plugin['name'], $plugin['severity'] ) && isset( $found[ $plugin['severity'] ] ) && is_plugin_active( $basename ) ) { $found[ $plugin['severity'] ][] = (string) $plugin['name']; } } foreach ( self::get_cache_plugins() as $basename => $name ) { $active = 0 === strpos( $basename, 'const:' ) ? defined( substr( $basename, 6 ) ) : is_plugin_active( $basename ); if ( $active ) { $found['cache'][] = (string) $name; } } return $found; } }