'card' ); const LAYOUTS = array( 'card', 'wash' ); const STYLE = 'rooster-lib-form-panel'; const MODULE = '@rooster-one/form-panel'; const LOCATION_ARG = 'aieo_loc'; const DIR = 'includes/dmm/blocks/contact-form/variants/'; const REQUIRED_TOKEN = '{{required}}'; private static $found = array(); private static $drawn = array(); public static function register() { static $done = false; if ( $done ) { return; } $done = true; add_action( 'init', array( __CLASS__, 'register_assets' ), 5 ); add_action( 'enqueue_block_editor_assets', array( __CLASS__, 'editor_data' ) ); add_action( 'enqueue_block_assets', array( __CLASS__, 'editor_style' ) ); add_action( 'wp_footer', array( __CLASS__, 'remember_view' ), 99 ); } public static function seen_key() { return 'aieo_rv_' . substr( md5( home_url() ), 0, 8 ); } public static function remember_view() { if ( ! function_exists( 'is_product' ) || ! is_product() ) { return; } $pid = (int) get_queried_object_id(); if ( $pid <= 0 ) { return; } $js = '(function(){var k=' . wp_json_encode( self::seen_key() ) . ',id=' . $pid . ';function go(){try{if(typeof window.aieoConsentAllows==="function"&&!window.aieoConsentAllows()){return;}var n=Math.round(Date.now()/1e3),l=JSON.parse(localStorage.getItem(k)||"[]");if(!Array.isArray(l)){l=[];}l=l.filter(function(e){return e&&+e.id>0&&+e.id!==id&&(+e.t||0)>=n-2592000;});l.push({id:id,t:n});localStorage.setItem(k,JSON.stringify(l.slice(-30)));}catch(e){}}if("requestIdleCallback"in window){requestIdleCallback(go,{timeout:4000});}else{setTimeout(go,1500);}})();'; wp_print_inline_script_tag( $js, array( 'id' => 'aieo-remember-view', 'data-rooster-ui' => 'rooster-one/form' ) ); } public static function editor_data() { if ( ! class_exists( 'AIEO_Form_CPT' ) || ! current_user_can( 'edit_posts' ) ) { return; } $forms = array(); foreach ( get_posts( array( 'post_type' => AIEO_Form_CPT::POST_TYPE, 'post_status' => 'publish', 'numberposts' => 100, 'orderby' => 'title', 'order' => 'ASC', 'no_found_rows' => true ) ) as $post ) { $forms[] = array( 'key' => (string) $post->post_name, 'title' => '' !== $post->post_title ? (string) $post->post_title : (string) $post->post_name ); } $locations = array(); foreach ( class_exists( 'AIEO_Location_Contact' ) ? AIEO_Location_Contact::choices() : array() as $slug => $label ) { $locations[] = array( 'key' => (string) $slug, 'title' => (string) $label ); } foreach ( array( 'aieo-contact-form-editor-script', 'aieo-form-button-editor-script' ) as $handle ) { wp_add_inline_script( $handle, 'window.aieoFormsEditor = ' . wp_json_encode( array( 'forms' => $forms, 'locations' => $locations, 'listUrl' => admin_url( 'edit.php?post_type=' . AIEO_Form_CPT::POST_TYPE ) ) ) . ';', 'before' ); } } public static function editor_style() { if ( is_admin() && wp_style_is( self::STYLE, 'registered' ) ) { wp_enqueue_style( self::STYLE ); } } public static function register_assets() { $base = defined( 'AIEO_FILE' ) ? AIEO_FILE : __FILE__; $dir = defined( 'AIEO_DIR' ) ? AIEO_DIR : ''; $ver = static function ( $rel ) use ( $dir ) { return '' !== $dir && is_readable( $dir . $rel ) ? (string) filemtime( $dir . $rel ) : ( defined( 'AIEO_VERSION' ) ? AIEO_VERSION : '1' ); }; if ( ! wp_style_is( self::STYLE, 'registered' ) ) { wp_register_style( self::STYLE, plugins_url( self::DIR . 'panel.css', $base ), array(), $ver( self::DIR . 'panel.css' ) ); if ( '' !== $dir ) { wp_style_add_data( self::STYLE, 'path', wp_normalize_path( $dir . self::DIR . 'panel.css' ) ); } } if ( function_exists( 'wp_register_script_module' ) ) { wp_register_script_module( self::MODULE, plugins_url( self::DIR . 'panel.js', $base ), array(), $ver( self::DIR . 'panel.js' ) ); } } public static function find( $ref ) { $ref = trim( (string) $ref ); if ( '' === $ref || ! class_exists( 'AIEO_Form_CPT' ) ) { return 0; } if ( isset( self::$found[ $ref ] ) ) { return self::$found[ $ref ]; } $id = 0; if ( ctype_digit( $ref ) ) { $post = get_post( (int) $ref ); $id = $post && AIEO_Form_CPT::POST_TYPE === $post->post_type && 'publish' === $post->post_status ? (int) $post->ID : 0; } else { $ids = get_posts( array( 'post_type' => AIEO_Form_CPT::POST_TYPE, 'name' => sanitize_title( $ref ), 'post_status' => 'publish', 'numberposts' => 1, 'fields' => 'ids', 'no_found_rows' => true, 'suppress_filters' => false, ) ); $id = $ids ? (int) $ids[0] : 0; } self::$found[ $ref ] = $id; return $id; } public static function allowed_html() { $common = array( 'class' => true, 'id' => true, 'data-*' => true, 'aria-hidden' => true, 'aria-describedby' => true, 'aria-required' => true, 'aria-label' => true, 'role' => true, 'hidden' => true ); $field = $common + array( 'name' => true, 'required' => true, 'autocomplete' => true, 'placeholder' => true, 'maxlength' => true ); return array( 'div' => $common + array( 'style' => true ), 'p' => $common, 'span' => $common, 'strong' => $common, 'code' => $common, 'br' => array(), 'a' => $common + array( 'href' => true, 'rel' => true, 'target' => true ), 'h2' => $common, 'h3' => $common, 'h4' => $common, 'h5' => $common, 'h6' => $common, 'form' => $common + array( 'method' => true, 'action' => true, 'novalidate' => true ), 'fieldset' => $common, 'legend' => $common, 'label' => $common + array( 'for' => true ), 'input' => $field + array( 'type' => true, 'value' => true, 'tabindex' => true, 'inputmode' => true, 'spellcheck' => true, 'checked' => true ), 'select' => $field, 'option' => array( 'value' => true, 'selected' => true ), 'textarea' => $field + array( 'rows' => true ), 'button' => $common + array( 'type' => true ), ); } public static function reset() { self::$found = array(); self::$drawn = array(); } public static function block( array $a ) { $variant = (string) ( $a['variant'] ?? '' ); if ( ! isset( self::VARIANTS[ $variant ] ) ) { return ''; } $form_id = self::find( $a['form'] ?? '' ); if ( ! $form_id ) { return ''; } $fields = AIEO_Form_CPT::fields( $form_id ); if ( ! $fields ) { return ''; } $settings = AIEO_Form_CPT::words( $form_id ); $layout = in_array( (string) ( $a['layout'] ?? '' ), self::LAYOUTS, true ) ? (string) $a['layout'] : self::VARIANTS[ $variant ]; wp_enqueue_style( self::STYLE ); if ( function_exists( 'wp_enqueue_script_module' ) ) { wp_enqueue_script_module( self::MODULE ); } $slug = (string) get_post_field( 'post_name', $form_id ); $base = 'aieo-form-' . ( '' !== $slug ? $slug : (string) $form_id ); self::$drawn[ $base ] = ( self::$drawn[ $base ] ?? 0 ) + 1; if ( self::$drawn[ $base ] > 1 ) { $base .= '-' . self::$drawn[ $base ]; } $tone = class_exists( 'AIEO_Engine_Blocks' ) ? AIEO_Engine_Blocks::tone( (string) ( $a['tone'] ?? '' ) ) : ''; $classes = 'aieo-form aieo-form--' . $variant . ' aieo-form--' . $layout; if ( ! empty( $a['bare'] ) ) { $classes .= ' aieo-form--bare'; } if ( '' !== $tone && class_exists( 'AIEO_Engine_Blocks' ) ) { $classes .= ' ' . AIEO_Engine_Blocks::tone_classes( $tone, true ); } $wrapper = function_exists( 'get_block_wrapper_attributes' ) && class_exists( 'WP_Block_Supports' ) && null !== WP_Block_Supports::$block_to_render ? get_block_wrapper_attributes( array( 'class' => $classes, 'data-rooster-ui' => 'rooster-one/form' ) ) : 'class="' . esc_attr( $classes ) . '" data-rooster-ui="rooster-one/form"'; $result = self::posted_result( $form_id, $settings ); $html = '
'; $html .= self::head( $a ); $html .= '
'; $html .= '
'; $html .= '
'; foreach ( $fields as $f ) { $html .= self::field( $base, $f ); } $html .= ''; $html .= '
'; $html .= '
'; $html .= '

' . ( $result ? esc_html( $result['message'] ) : '' ) . '

'; $html .= self::hidden( $form_id, self::location( $a ) ); $html .= '
'; return $html; } private static function head( array $a ) { $eyebrow = trim( (string) ( $a['eyebrow'] ?? '' ) ); $badge = trim( (string) ( $a['badge'] ?? '' ) ); $title = trim( (string) ( $a['title'] ?? '' ) ); $intro = trim( (string) ( $a['intro'] ?? '' ) ); if ( '' === $eyebrow . $badge . $title . $intro ) { return ''; } $level = max( 2, min( 6, (int) ( $a['level'] ?? 2 ) ) ); $html = '
'; if ( '' !== $eyebrow ) { $html .= '

' . esc_html( $eyebrow ) . '

'; } if ( '' !== $badge ) { $icon = sanitize_key( (string) ( $a['icon'] ?? '' ) ); $mark = '' !== $icon && function_exists( 'rooster_icon' ) ? (string) rooster_icon( $icon, array( 'width' => 16, 'class' => 'aieo-form__icon' ) ) : ''; $html .= '

' . $mark . esc_html( $badge ) . '

'; } if ( '' !== $title ) { $html .= '' . esc_html( $title ) . ''; } if ( '' !== $intro ) { $parts = array_map( array( __CLASS__, 'inline' ), explode( self::REQUIRED_TOKEN, $intro ) ); $html .= '

' . implode( '*', $parts ) . '

'; } return $html . '
'; } private static function field( $base, array $f ) { $key = (string) $f['key']; $id = $base . '-' . $key; $type = (string) $f['type']; $width = 'half' === (string) ( $f['width'] ?? '' ) ? 'aieo-form__half' : 'aieo-form__full'; $req = ! empty( $f['required'] ); $mark = $req ? '' : ''; $words = ' data-aieo-field="' . esc_attr( $key ) . '"' . ( '' !== (string) $f['missing'] ? ' data-aieo-missing="' . esc_attr( (string) $f['missing'] ) . '"' : '' ) . ( '' !== (string) $f['invalid'] ? ' data-aieo-invalid="' . esc_attr( (string) $f['invalid'] ) . '"' : '' ); $help = '' !== (string) $f['help'] ? '

' . self::inline( (string) $f['help'] ) . '

' : ''; $desc = '' !== $help ? ' aria-describedby="' . esc_attr( $id . '-help' ) . '"' : ''; $need = $req ? ' required aria-required="true"' : ''; if ( 'consent' === $type || ( 'checkbox' === $type && 1 === count( $f['choices'] ) && '' === trim( (string) $f['label'] ) ) ) { if ( 'consent' === $type ) { $name = 'aieo_form[' . $key . ']'; $value = '1'; $text = (string) $f['label']; } else { $name = 'aieo_form[' . $key . '][]'; $value = (string) array_key_first( $f['choices'] ); $text = (string) reset( $f['choices'] ); } return '
' . '' . '' . $help . '
'; } if ( 'checkbox' === $type || 'radio' === $type ) { $html = '
' . '' . esc_html( (string) $f['label'] ) . $mark . '
'; $i = 0; foreach ( $f['choices'] as $ck => $cl ) { $html .= ''; $i++; } return $html . '
' . $help . '
'; } $label = ''; $attrs = ' class="aieo-form__control" id="' . esc_attr( $id ) . '" name="' . esc_attr( 'aieo_form[' . $key . ']' ) . '"' . ( '' !== (string) $f['placeholder'] ? ' placeholder="' . esc_attr( (string) $f['placeholder'] ) . '"' : '' ) . ( '' !== (string) $f['autocomplete'] ? ' autocomplete="' . esc_attr( (string) $f['autocomplete'] ) . '"' : '' ) . $need . $desc . $words; if ( 'select' === $type ) { $options = '' !== (string) $f['prompt'] ? '' : ''; foreach ( $f['choices'] as $ck => $cl ) { $options .= ''; } return '
' . $label . '' . $options . '' . $help . '
'; } if ( 'textarea' === $type ) { $rows = (int) $f['rows']; return '
' . $label . ' 0 ? ' rows="' . $rows . '"' : '' ) . ' maxlength="' . (int) AIEO_Form_CPT::max_length( $type ) . '">' . $help . '
'; } $input = in_array( $type, array( 'email', 'url', 'tel' ), true ) ? $type : 'text'; $extra = 'email' === $input ? ' inputmode="email" spellcheck="false"' : ( 'tel' === $input ? ' inputmode="tel"' : '' ); return '
' . $label . '' . $help . '
'; } public static function location( array $a ) { $slug = sanitize_key( (string) ( $a['location'] ?? '' ) ); if ( '' === $slug && isset( $_GET[ self::LOCATION_ARG ] ) && is_scalar( $_GET[ self::LOCATION_ARG ] ) ) { $slug = sanitize_key( wp_unslash( (string) $_GET[ self::LOCATION_ARG ] ) ); } return '' !== $slug && class_exists( 'AIEO_Location_Contact' ) && isset( AIEO_Location_Contact::all()[ $slug ] ) ? $slug : ''; } private static function hidden( $form_id, $location = '' ) { $html = ''; $html .= ''; $html .= ''; $html .= ''; if ( '' !== $location ) { $html .= ''; } $html .= ''; $html .= AIEO_Form_Submit::captcha_field(); return $html; } private static function posted_result( $form_id, array $settings ) { if ( empty( $_GET['aieo_form'] ) || empty( $_GET['aieo_form_for'] ) || absint( wp_unslash( $_GET['aieo_form_for'] ) ) !== (int) $form_id ) { return null; } $code = sanitize_key( wp_unslash( (string) $_GET['aieo_form'] ) ); if ( 'sent' === $code ) { return array( 'state' => 'ok', 'message' => (string) $settings['success'] ); } return array( 'state' => 'error', 'message' => AIEO_Form_Submit::error_message( $code, $settings ) ); } private static function inline( $text ) { return class_exists( 'AIEO_Engine_Blocks' ) ? AIEO_Engine_Blocks::inline( (string) $text ) : esc_html( (string) $text ); } private static function run( $text ) { return class_exists( 'AIEO_Engine_Blocks' ) ? AIEO_Engine_Blocks::run( (string) $text ) : esc_html( (string) $text ); } } }