'system-ui,-apple-system,"Segoe UI",sans-serif', 'serif' => 'Georgia,"Times New Roman",serif', 'system' => 'system-ui,sans-serif', 'mono' => 'ui-monospace,Menlo,monospace' ); $gaps = array( 'compact' => '12px', 'normal' => '18px', 'relaxed' => '26px' ); $style = array(); $class = array(); if ( isset( $d['primary'] ) && preg_match( self::HEX, (string) $d['primary'] ) ) { $style[] = '--htform-accent:' . $d['primary']; } if ( isset( $d['text'] ) && preg_match( self::HEX, (string) $d['text'] ) ) { $style[] = '--htform-ink:' . $d['text']; } if ( isset( $d['background'] ) && preg_match( self::HEX, (string) $d['background'] ) ) { $style[] = '--htform-bg:' . $d['background']; $class[] = 'htform-has-bg'; } if ( isset( $d['radius'] ) && is_numeric( $d['radius'] ) ) { $style[] = '--htform-radius:' . max( 0, min( 24, (int) $d['radius'] ) ) . 'px'; } if ( isset( $d['font'] ) && isset( $fonts[ $d['font'] ] ) ) { $style[] = '--htform-font:' . $fonts[ $d['font'] ]; } if ( isset( $d['spacing'] ) && isset( $gaps[ $d['spacing'] ] ) ) { $style[] = '--htform-gap:' . $gaps[ $d['spacing'] ]; } if ( ! empty( $d['buttonStyle'] ) ) { $class[] = 'htform-btn-' . sanitize_html_class( (string) $d['buttonStyle'] ); } return array( 'style' => implode( ';', $style ), 'class' => implode( ' ', $class ) ); } /** * Full instant markup for the first step of the form. * * @param array $payload Public payload. * @return string */ public static function markup( $payload ) { if ( empty( $payload['schema']['fields'] ) || ! is_array( $payload['schema']['fields'] ) ) { return ''; } $schema = $payload['schema']; $settings = isset( $schema['settings'] ) && is_array( $schema['settings'] ) ? $schema['settings'] : array(); $design = isset( $settings['design'] ) && is_array( $settings['design'] ) ? $settings['design'] : array(); $name = isset( $payload['name'] ) ? (string) $payload['name'] : ''; if ( isset( $payload['schedule'] ) && 'open' !== $payload['schedule'] ) { $closed = ! empty( $settings['closedMessage'] ) ? (string) $settings['closedMessage'] : __( 'This form is not accepting responses right now.', 'htforms-builder' ); return '
' . esc_html( $closed ) . '
'; } $conv = isset( $settings['layout'] ) && 'conversational' === $settings['layout']; $first = array(); $steps = 1; $context = array(); $has_question = false; foreach ( $schema['fields'] as $f ) { if ( ! is_array( $f ) || ! isset( $f['type'] ) ) { continue; } if ( 'pagebreak' === $f['type'] ) { if ( ! $conv ) { $steps++; } continue; } if ( $conv ) { if ( 'hidden' === $f['type'] ) { $first[] = $f; continue; } if ( in_array( $f['type'], array( 'html', 'divider', 'image', 'calculation' ), true ) || ! empty( $f['blocksSubmission'] ) ) { if ( ! $has_question ) { $context[] = $f; } continue; } if ( ! $has_question ) { $first = array_merge( $first, $context, array( $f ) ); $has_question = true; } $steps++; continue; } if ( 1 === $steps ) { $first[] = $f; } } if ( $conv ) { $steps = max( 1, $steps - 1 ); } $out = ''; if ( ! empty( $payload['branding'] ) && HTForm_Attribution::enabled() ) { $out .= 'Powered by HTforms
'; } return $out; } /** * Only https or small inline images. * * @param string $src Source. * @return bool */ private static function safe_image( $src ) { return 1 === preg_match( '#^(https://|data:image/(png|jpeg|webp|gif);base64,)#', $src ); } /** * Country list shared with the JS renderer. * * @return string[] */ private static function countries() { static $list = null; if ( null === $list ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- local plugin file. $list = json_decode( (string) file_get_contents( HTFORM_DIR . 'assets/countries.json' ), true ); $list = is_array( $list ) ? $list : array(); } return $list; } /** * One field, same structure and names as htform.js buildField(). * * @param array $f Field. * @return string */ private static function field( $f ) { $type = sanitize_key( (string) $f['type'] ); $fid = isset( $f['id'] ) ? (string) $f['id'] : ''; $id = 'htfs-' . preg_replace( '/[^A-Za-z0-9_-]/', '', $fid ); $lbl = isset( $f['label'] ) ? (string) $f['label'] : ''; $ph = isset( $f['placeholder'] ) ? (string) $f['placeholder'] : ''; $def = isset( $f['defaultValue'] ) && is_scalar( $f['defaultValue'] ) ? (string) $f['defaultValue'] : ''; $req = ! empty( $f['required'] ); $star = $req ? '' : ''; $desc = ! empty( $f['description'] ) ? '' . esc_html( (string) $f['description'] ) . '
' : ''; $err = ''; $opts = isset( $f['options'] ) && is_array( $f['options'] ) ? array_map( 'strval', $f['options'] ) : array(); if ( 'hidden' === $type ) { return ''; } $cls = 'htform-field htform-type-' . $type; if ( isset( $f['boundaryStyle'] ) && in_array( $f['boundaryStyle'], array( 'sky_dashed', 'orange_solid', 'grey_dashed' ), true ) ) { $cls .= ' htform-bd htform-bd-' . $f['boundaryStyle'] . ' htform-bd-' . sanitize_html_class( isset( $f['boundaryPosition'] ) ? (string) $f['boundaryPosition'] : 'below' ) . ' htform-bda-' . sanitize_html_class( isset( $f['boundaryAnimation'] ) ? (string) $f['boundaryAnimation'] : 'none' ); } $open = '' . esc_html( $f['signatureDisclaimer'] ) . '
' : '' ) . $desc . $err . ''; case 'likert': $h = $open . $label; foreach ( isset( $f['rows'] ) ? $f['rows'] : array() as $i => $row ) { $h .= ''; } return $h . $desc . $err . ''; case 'rating': case 'nps': $h = $open . $label . '' . esc_html( ( isset( $f['lowLabel'] ) ? $f['lowLabel'] : '' ) . ' — ' . ( isset( $f['highLabel'] ) ? $f['highLabel'] : '' ) ) . '
' . $desc . $err . ''; case 'image': if ( empty( $f['imageUrl'] ) || ! self::safe_image( (string) $f['imageUrl'] ) ) { return $open . ''; } $w = isset( $f['imageWidth'] ) ? max( 10, min( 100, (int) $f['imageWidth'] ) ) : 100; $align = isset( $f['imageAlign'] ) ? (string) $f['imageAlign'] : 'center'; $style = 'width:' . $w . '%;margin-left:' . ( 'left' === $align ? '0' : 'auto' ) . ';margin-right:' . ( 'right' === $align ? '0' : 'auto' ); return $open . '