> */ private static array $cache = array(); /** * Returns the built in defaults. * * @return array Default values keyed by setting. */ public static function defaults(): array { return array( // General. 'submit_label' => '', 'success_message' => '', 'remove_data' => false, 'save_progress' => false, 'progress_lifetime' => 7, // Email. 'from_name' => '', 'from_email' => '', 'admin_recipients' => '', 'queue' => 'immediate', // Security. 'honeypot' => true, 'rate_limit' => 5, 'submission_interval' => 0, 'min_submit_seconds' => 3, 'spam_threshold' => 100, 'blocked_ips' => '', 'captcha_provider' => self::inherited_captcha(), 'recaptcha_enabled' => false, 'recaptcha_site_key' => '', 'recaptcha_secret' => '', 'recaptcha_threshold' => 0.5, 'turnstile_site_key' => '', 'turnstile_secret' => '', // Uploads. 'upload_max_size' => 5120, 'upload_allowed_types' => 'pdf, doc, docx, jpg, jpeg, png', 'upload_to_media_library' => false, 'upload_cleanup' => true, 'upload_retention' => 24, // Export. 'export_delimiter' => ',', /* * Off by default. The metadata columns include the visitor's IP address, * which is personal data in most jurisdictions — so every export leaving * the site carried it unless somebody had thought to turn it off. Sites * that want it say so; the setting is one tick. */ 'export_include_meta' => false, // Integrations. Null rather than an empty list: never saved is not the // same as saved with nothing ticked, and only the first shows them all. 'integrations_enabled' => null, // Developer. 'rest_enabled' => true, 'log_level' => LogLevel::ERROR, 'log_retention' => 14, 'webhook_retention' => 30, ); } /** * Returns the challenge a site had before it could choose one. * * The single "enable reCAPTCHA" switch became a list of providers. Defaulting * the new setting from the old switch is what keeps an upgrading site's * challenge working — and, because it is a default rather than a fallback * applied at read time, it is also what the settings screen shows as selected. * A site that opens the tab and saves without touching it therefore keeps * what it had, instead of quietly turning the challenge off. * * The option is read directly rather than through {@see Settings::all()}, * which is the method calling this. */ private static function inherited_captcha(): string { $stored = get_option( self::OPTION, array() ); return is_array( $stored ) && ! empty( $stored['recaptcha_enabled'] ) ? 'recaptcha_v3' : 'none'; } /** * Returns every setting, defaults included. * * @return array Values keyed by setting. */ public static function all(): array { $site = get_current_blog_id(); if ( isset( self::$cache[ $site ] ) ) { return self::$cache[ $site ]; } $stored = get_option( self::OPTION, array() ); $stored = is_array( $stored ) ? $stored : array(); /** * Filters the resolved plugin settings. * * @since 1.0.0 * * @param array $settings Values keyed by setting. */ self::$cache[ $site ] = (array) apply_filters( 'formpilot_settings', array_merge( self::defaults(), $stored ) ); return self::$cache[ $site ]; } /** * Returns a single setting. * * @param string $key Setting name. * @param mixed $fallback Optional. Value returned when the setting is unknown. Default null. * * @return mixed The stored value. */ public static function get( string $key, mixed $fallback = null ): mixed { $settings = self::all(); if ( array_key_exists( $key, $settings ) ) { return $settings[ $key ]; } return $fallback ?? ( self::defaults()[ $key ] ?? null ); } /** * Returns a setting as a string. * * @param string $key Setting name. */ public static function text( string $key ): string { $value = self::get( $key, '' ); return is_scalar( $value ) ? (string) $value : ''; } /** * Returns a setting as a boolean. * * @param string $key Setting name. */ public static function flag( string $key ): bool { return (bool) self::get( $key, false ); } /** * Returns a setting as an integer. * * @param string $key Setting name. */ public static function number( string $key ): int { return (int) self::get( $key, 0 ); } /** * Forgets the cached settings. */ public static function flush(): void { self::$cache = array(); } }