options[$option][$so] = $filter; } } elseif ( is_null( $suboption ) ) { $this->options[$option] = $filter; } else { $this->options[$option][$suboption] = $filter; } add_filter( 'sanitize_option_' . $option, array( $this, 'sanitize' ), 10, 2 ); return true; } /** * Checks sanitization filter exists, and if so, passes the value through it. * * @since 1.0.0 */ public function do_filter( $filter, $new_value, $old_value ) { $available_filters = $this->get_available_filters(); if ( ! in_array( $filter, array_keys( $available_filters ) ) ) { return $new_value; } return call_user_func( $available_filters[$filter], $new_value, $old_value ); } /** * Return array of known sanitization filter types. * * @since 1.0.0 */ public function get_available_filters() { $default_filters = array( 'one_zero' => array( $this, 'one_zero' ), 'no_html' => array( $this, 'no_html' ), 'absint' => array( $this, 'absint' ), 'safe_html' => array( $this, 'safe_html' ), 'safe_text' => array( $this, 'safe_text' ), 'hex_color' => array( $this, 'hex_color' ), 'hex_color_no_hash' => array( $this, 'hex_color_no_hash' ), 'maybe_hash_hex_color' => array( $this, 'maybe_hash_hex_color' ), 'requires_unfiltered_html' => array( $this, 'requires_unfiltered_html' ), 'url' => array( $this, 'url' ), 'email_address' => array( $this, 'email_address' ), ); /** * Filter the available sanitization filter types. * * @since 1.1.0 * * @param array $default_filters Array with keys of sanitization types, and values of the filter function name as a callback */ return apply_filters( 'bizznis_available_sanitizer_filters', $default_filters ); } /** * Sanitize a value, via the sanitization filter type associated with an option. * * @since 1.0.0 */ public function sanitize( $new_value, $option ) { if ( !isset( $this->options[$option] ) ) { # We are not filtering this option at all return $new_value; } elseif ( is_string( $this->options[$option] ) ) { # Single option value return $this->do_filter( $this->options[$option], $new_value, get_option( $option ) ); } elseif ( is_array( $this->options[$option] ) ) { # Array of suboption values to loop through $old_value = get_option( $option ); foreach ( $this->options[$option] as $suboption => $filter ) { $old_value[$suboption] = isset( $old_value[$suboption] ) ? $old_value[$suboption] : ''; $new_value[$suboption] = isset( $new_value[$suboption] ) ? $new_value[$suboption] : ''; $new_value[$suboption] = $this->do_filter( $filter, $new_value[$suboption], $old_value[$suboption] ); } return $new_value; } else { # Should never hit this, but: return $new_value; } } //* Now, our filter methods /** * Returns a 1 or 0, for all truthy / falsy values. Uses double casting. First, we cast to bool, * then to integer. * * @since 1.0.0 */ public static function one_zero( $new_value ) { return (int) (bool) $new_value; } /** * Returns a positive integer value. * * @since 1.0.0 */ public static function absint( $new_value ) { return absint( $new_value ); } /** * Removes HTML tags from string. * * @since 1.0.0 */ public static function no_html( $new_value ) { return strip_tags( $new_value ); } /** * Safe URLs * * @since 1.0.0 */ public static function url( $new_value ) { return esc_url_raw( $new_value ); } /** * Makes Email Addresses safe, via sanitize_email() * * @since 1.1.0 * * @param string $new_value String, an email address, possibly unsafe * @return string String a safe email address */ public static function email_address( $new_value ) { return sanitize_email( $new_value ); } /** * Removes unsafe HTML tags, via wp_kses_post(). * * @since 1.0.0 */ public static function safe_html( $new_value ) { return wp_kses_post( $new_value ); } /** * Sanitize a string to allow only tags in the allowedtags array. * * @since 1.1.0 */ public static function safe_text( $new_value ) { global $allowedtags; return wp_kses( $new_value , $allowedtags ); } /** * Sanitizes a hex color. * * This is a copy of the core function for use when the customizer is not being shown. * * @since 1.1.0. */ public static function hex_color( $new_value ) { if ( '' === $new_value ) { return ''; } # 3 or 6 hex digits, or the empty string. if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $new_value ) ) { return $new_value; } return null; } /** * Sanitizes a hex color without a hash. Use sanitize_hex_color() when possible. * * This is a copy of the core function for use when the customizer is not being shown. * * @since 1.1.0. */ public static function hex_color_no_hash( $new_value ) { $new_value = ltrim( $new_value, '#' ); if ( '' === $new_value ) { return ''; } return sanitize_hex_color( '#' . $new_value ) ? $new_value : null; } /** * Ensures that any hex color is properly hashed. * * This is a copy of the core function for use when the customizer is not being shown. * * @since 1.1.0. */ public static function maybe_hash_hex_color( $new_value ) { if ( $unhashed = sanitize_hex_color_no_hash( $new_value ) ) { return '#' . $unhashed; } return $new_value; } /** * Keeps the option from being updated if the user lacks unfiltered_html capability. * * @since 1.0.0 */ public static function requires_unfiltered_html( $new_value, $old_value ) { if ( current_user_can( 'unfiltered_html' ) ) { return $new_value; } else { return $old_value; } } } /** * Keeps the option from being updated if the user lacks unfiltered_html capability. * * If the option is an "array" option type with "suboptions", you have to use the third param to specify the * suboption or suboptions you want the filter to apply to. DO NOT call this without the third parameter on an option * that is an array option, because in that case it will apply that filter to the array(), not each member. * * @since 1.0.0 */ function bizznis_add_option_filter( $filter, $option, $suboption = null ) { return Bizznis_Settings_Sanitizer::$instance->add_filter( $filter, $option, $suboption ); } /** * Adds string sanitization on the fly. * * @since 1.1.1 */ function bizznis_add_string_filter( $filter, $new_value, $old_value = null ) { return Bizznis_Settings_Sanitizer::$instance->do_filter( $filter, $new_value, $old_value ); } /** * Instantiate the Sanitizer. * * @since 1.0.0 */ add_action( 'init', 'bizznis_settings_sanitizer_init' ); function bizznis_settings_sanitizer_init() { new Bizznis_Settings_Sanitizer; }