array( 'action', 'method', 'enctype', 'novalidate', 'autocomplete', 'name', 'target' ), 'input' => array( 'type', 'name', 'value', 'checked', 'disabled', 'readonly', 'required', 'placeholder', 'min', 'max', 'step', 'minlength', 'maxlength', 'pattern', 'inputmode', 'autocomplete', 'accept', 'multiple', 'size', 'form' ), 'select' => array( 'name', 'required', 'disabled', 'multiple', 'size', 'autocomplete' ), 'option' => array( 'value', 'selected', 'disabled', 'label' ), 'optgroup' => array( 'label', 'disabled' ), 'textarea' => array( 'name', 'rows', 'cols', 'required', 'disabled', 'readonly', 'placeholder', 'minlength', 'maxlength', 'autocomplete' ), 'button' => array( 'type', 'name', 'value', 'disabled' ), 'label' => array( 'for' ), 'fieldset' => array( 'disabled', 'name' ), 'legend' => array(), 'output' => array( 'for', 'name' ), 'progress' => array( 'value', 'max' ), 'div' => array(), 'span' => array(), 'p' => array(), 'br' => array(), 'hr' => array(), 'strong' => array(), 'b' => array(), 'em' => array(), 'i' => array(), 'small' => array(), 'abbr' => array(), 'h2' => array(), 'h3' => array(), 'h4' => array(), 'ul' => array(), 'ol' => array(), 'li' => array(), 'a' => array( 'href', 'target', 'rel' ), 'img' => array( 'src', 'alt', 'width', 'height', 'loading', 'decoding' ), 'table' => array(), 'thead' => array(), 'tbody' => array(), 'tr' => array(), 'th' => array( 'scope', 'colspan', 'rowspan' ), 'td' => array( 'colspan', 'rowspan' ), 'canvas' => array( 'width', 'height' ), ); /** * The allowed tags in the shape wp_kses() expects. * * @return array> */ public static function allowed(): array { $allowed = array(); foreach ( self::TAGS as $tag => $own ) { $allowed[ $tag ] = array_fill_keys( array_merge( self::COMMON, $own ), true ); } /** * Filters the tags and attributes a rendered form may contain. * * @param array> $allowed Tags in the shape of wp_kses(). */ return (array) apply_filters( 'forensix_form_allowed_html', $allowed ); } /** * The markup with everything removed that a form may not contain. * * @param string $html Form markup. */ public static function escape( string $html ): string { // The spam trap is moved off screen with position and left; keep both while checking. add_filter( 'safe_style_css', array( self::class, 'style_properties' ) ); $clean = wp_kses( $html, self::allowed() ); remove_filter( 'safe_style_css', array( self::class, 'style_properties' ) ); return $clean; } /** * Adds the CSS properties the form markup uses to the ones wp_kses() keeps. * * @param mixed $properties Allowed properties. * @return string[] */ public static function style_properties( $properties ): array { return array_values( array_unique( array_merge( is_array( $properties ) ? $properties : array(), array( 'position', 'left' ) ) ) ); } }