<?php
/**
 * Security modules that must load even when the per-request module cap is reached.
 *
 * @package WP_PowerSuite\Core
 * @since 1.0.0
 */

namespace WP_PowerSuite\Core;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class SecurityCriticalModules {

	/**
	 * Module IDs that bypass {@see ModuleManager}'s per-request load cap.
	 *
	 * @var list<string>
	 */
	private const LOAD_CAP_EXEMPT = [
		'advanced-security-headers',
		'change-login-url',
		'disable-application-passwords',
		'disable-author-archives',
		'obfuscate-author-slugs',
		'disable-file-editing',
		'disable-password-reset',
		'disable-rest-api',
		'disable-trackbacks-pingbacks',
		'disable-xmlrpc',
		'force-ssl-admin',
		'ip-whitelist-blacklist',
		'limit-login-attempts',
		'temporary-login',
		'login-as-user',
		'login-id-type',
		'custom-login-error-messages',
		'password-protection',
		'two-factor-authentication',
		'google-sign-in',
		'facebook-sign-in',
		'github-sign-in',
	];

	/**
	 * Free security modules that keep running when the license is invalid.
	 *
	 * Premium modules (is_pro) are excluded so they require a valid license to load.
	 *
	 * @var list<string>
	 */
	private const LICENSE_EXEMPT = [
		'disable-application-passwords',
		'disable-author-archives',
		'obfuscate-author-slugs',
		'disable-file-editing',
		'disable-password-reset',
		'disable-rest-api',
		'disable-trackbacks-pingbacks',
		'disable-xmlrpc',
		'force-ssl-admin',
		'temporary-login',
		'login-id-type',
		'custom-login-error-messages',
	];

	public static function isLoadCapExempt( string $module_id ): bool {
		return self::isListedModule( $module_id, self::LOAD_CAP_EXEMPT, 'wp_powersuite_load_cap_exempt_modules' );
	}

	/**
	 * Whether a security module must keep running when the license is invalid.
	 */
	public static function isLicenseExempt( string $module_id ): bool {
		return self::isListedModule( $module_id, self::LICENSE_EXEMPT, 'wp_powersuite_license_exempt_modules' );
	}

	/**
	 * @param list<string> $defaults
	 */
	private static function isListedModule( string $module_id, array $defaults, string $filter ): bool {
		$module_id = sanitize_key( $module_id );
		$list      = apply_filters( $filter, $defaults );

		if ( ! is_array( $list ) ) {
			$list = $defaults;
		}

		return in_array( $module_id, array_map( 'sanitize_key', $list ), true );
	}
}
