__( 'Contact form', 'alpeg-forms' ), 'submitLabel' => __( 'Send', 'alpeg-forms' ), 'successMessage' => __( 'Thank you! Your message has been received. We will get back to you as soon as possible.', 'alpeg-forms' ), 'confirmationSubject' => __( 'We have received your message', 'alpeg-forms' ), 'confirmationMessage' => __( "Hello,\n\nthank you for your message. We have received it and will get back to you as soon as possible.\n\nHere is a copy of your details:\n{fields}", 'alpeg-forms' ), 'firstStepTitle' => __( 'Your details', 'alpeg-forms' ), ); } /** * Block render callback. * * @param array $attributes Attributes. * @param string $content Content (empty). * @param \WP_Block $block Block instance. * @return string */ public static function render( $attributes, $content = '', $block = null ) { $fields = Fields::normalize( isset( $attributes['fields'] ) ? $attributes['fields'] : array() ); $inputs = array_filter( $fields, array( Fields::class, 'is_input' ) ); if ( ! $inputs ) { return ''; } wp_enqueue_style( 'alpeg-forms-frontend' ); $d = self::defaults(); $form_id = isset( $attributes['formId'] ) && '' !== $attributes['formId'] ? substr( sanitize_key( $attributes['formId'] ), 0, 64 ) : 'af_' . substr( md5( wp_json_encode( $fields ) ), 0, 10 ); $title = self::attr( $attributes, 'formTitle', $d['formTitle'] ); $post_id = ( $block instanceof \WP_Block && isset( $block->context['postId'] ) ) ? (int) $block->context['postId'] : (int) get_queried_object_id(); $steps = Fields::steps( $fields, self::attr( $attributes, 'firstStepTitle', $d['firstStepTitle'] ) ); $multi = count( $steps ) > 1; $files = (bool) wp_list_filter( $fields, array( 'type' => 'file' ) ); $token = Token::encode( array( 'v' => 2, 'fid' => $form_id, 'title' => $title, 'fields' => $fields, 'notify' => sanitize_text_field( self::attr( $attributes, 'notifyEmail', '' ) ), 'subject' => sanitize_text_field( self::attr( $attributes, 'notifySubject', '' ) ), 'attach' => $files && ! empty( $attributes['attachFiles'] ), 'confirm' => array( 'on' => ! empty( $attributes['sendConfirmation'] ), 'subject' => sanitize_text_field( self::attr( $attributes, 'confirmationSubject', $d['confirmationSubject'] ) ), 'message' => sanitize_textarea_field( self::attr( $attributes, 'confirmationMessage', $d['confirmationMessage'] ) ), ), 'success' => sanitize_textarea_field( self::attr( $attributes, 'successMessage', $d['successMessage'] ) ), 'pid' => $post_id, 'blog' => get_current_blog_id(), 'ts' => time(), ) ); ++self::$instance; $uid = $form_id . '-' . self::$instance; // Result of a submission without JavaScript (redirect back). $state = self::no_js_state( $form_id ); $style = ''; $accent = sanitize_hex_color( self::attr( $attributes, 'accentColor', '' ) ); if ( $accent ) { $style = '--af-accent:' . $accent . ';'; } $wrapper = get_block_wrapper_attributes( array( 'class' => 'alpeg-form' . ( $multi ? ' alpeg-form--steps' : '' ), 'style' => $style, ) ); $config = array( 'i18n' => array_merge( Fields::messages(), array( /* translators: 1: current step, 2: number of steps, 3: step title */ 'step' => __( 'Step %1$d of %2$d: %3$s', 'alpeg-forms' ), 'error' => __( 'Something went wrong while sending. Please try again.', 'alpeg-forms' ), 'network' => __( 'No connection to the server. Please check your internet connection and try again.', 'alpeg-forms' ), 'too_large' => __( 'The uploaded files are too large in total. Please send smaller files.', 'alpeg-forms' ), 'units' => array( 'B', 'KB', 'MB', 'GB' ), ) ), 'steps' => count( $steps ), ); ob_start(); ?>
>
> $step ) : ?>
1 ) { /* translators: %d: max number of files */ $info .= ' · ' . sprintf( __( 'up to %d files', 'alpeg-forms' ), $f['max_files'] ); } $help = trim( $help . ( $help ? ' – ' : '' ) . $info ); } if ( $help ) { $describe[] = $help_id; } if ( $error ) { $describe[] = $err_id; } $describe = $describe ? ' aria-describedby="' . esc_attr( implode( ' ', $describe ) ) . '"' : ''; $classes = 'alpeg-form__field alpeg-form__field--' . $f['type'] . ( 'half' === $f['width'] ? ' alpeg-form__field--half' : '' ) . ( $error ? ' has-error' : '' ); $star = $f['required'] ? ' ' : ''; $data = ' data-af-field="' . esc_attr( $f['id'] ) . '" data-af-type="' . esc_attr( $f['type'] ) . '" data-af-label="' . esc_attr( wp_strip_all_tags( $f['label'] ) ) . '"' . ( $f['required'] ? ' data-af-required' : '' ); if ( $f['condition'] ) { $data .= " data-af-cond='" . esc_attr( wp_json_encode( $f['condition'] ) ) . "'"; } echo '
'; // phpcs:ignore WordPress.Security.EscapeOutput switch ( $f['type'] ) { case 'textarea': echo ''; // phpcs:ignore WordPress.Security.EscapeOutput echo ''; // phpcs:ignore WordPress.Security.EscapeOutput break; case 'select': echo ''; // phpcs:ignore WordPress.Security.EscapeOutput echo ''; break; case 'radio': case 'checkbox': $input_type = 'radio' === $f['type'] ? 'radio' : 'checkbox'; $input_name = 'checkbox' === $f['type'] ? $name . '[]' : $name; $checked = (array) $value; // Radios form a radiogroup, which supports aria-required/aria-invalid. A checkbox group is a plain // group: it gets no ARIA state, but announces "required" through hidden legend text. if ( 'radio' === $f['type'] ) { $group = ' role="radiogroup"' . ( $f['required'] ? ' aria-required="true"' : '' ) . $invalid; $sr = ''; } else { $group = ''; $sr = $f['required'] ? ' ' . esc_html__( '(required)', 'alpeg-forms' ) . '' : ''; } echo '' . esc_html( $f['label'] ) . $star . $sr . ''; // phpcs:ignore WordPress.Security.EscapeOutput foreach ( $f['options'] as $i => $opt ) { $oid = $id . '-' . $i; $req_attr = ( 'radio' === $f['type'] && $f['required'] && ! $f['condition'] && 0 === $i ) ? ' required' : ''; echo ''; // phpcs:ignore WordPress.Security.EscapeOutput } echo ''; break; case 'consent': $policy = get_privacy_policy_url(); $text = str_replace( '{datenschutz}', esc_url( $policy ? $policy : home_url( '/' ) ), $f['label'] ); $text = str_replace( '{privacy}', esc_url( $policy ? $policy : home_url( '/' ) ), $text ); $text = preg_replace( '/]*\btarget=)/i', ' ' . wp_kses( $text, Fields::consent_kses() ) . $star . ''; // phpcs:ignore WordPress.Security.EscapeOutput break; case 'file': $exts = Files::allowed_extensions( $f ); $multiple = $f['max_files'] > 1; $accept = implode( ',', array_map( static function ( $e ) { return '.' . $e; }, $exts ) ); echo ''; // phpcs:ignore WordPress.Security.EscapeOutput echo ''; // phpcs:ignore WordPress.Security.EscapeOutput break; default: $auto = array( 'email' => 'email', 'tel' => 'tel', 'url' => 'url', ); $ac = isset( $auto[ $f['type'] ] ) ? ' autocomplete="' . $auto[ $f['type'] ] . '"' : ''; if ( 'text' === $f['type'] && preg_match( '/\bname\b|vorname|nachname/i', $f['id'] . ' ' . $f['label'] ) ) { $ac = ' autocomplete="name"'; } $extra = 'number' === $f['type'] ? ' inputmode="decimal" step="any"' : ''; echo ''; // phpcs:ignore WordPress.Security.EscapeOutput echo ''; // phpcs:ignore WordPress.Security.EscapeOutput } if ( $help ) { echo '

' . esc_html( $help ) . '

'; } echo '

' . esc_html( $error ) . '

'; echo '
'; } /** * State after a redirect (submission without JavaScript). * * @param string $form_id Form ID. * @return array */ private static function no_js_state( $form_id ) { $state = array( 'status' => '', 'errors' => array(), 'field_errors' => array(), 'values' => array(), ); // phpcs:disable WordPress.Security.NonceVerification.Recommended -- display only, no action. if ( empty( $_GET['alpeg_form'] ) || sanitize_key( wp_unslash( $_GET['alpeg_form'] ) ) !== $form_id ) { return $state; } if ( isset( $_GET['alpeg_form_status'] ) && 'ok' === $_GET['alpeg_form_status'] ) { $state['status'] = 'success'; return $state; } if ( ! empty( $_GET['alpeg_form_key'] ) ) { $key = 'alpeg_forms_state_' . sanitize_key( wp_unslash( $_GET['alpeg_form_key'] ) ); $data = get_transient( $key ); if ( is_array( $data ) ) { delete_transient( $key ); $state = array_merge( $state, $data ); } } // phpcs:enable return $state; } /** * Read an attribute with fallback. * * @param array $a Attributes. * @param string $key Key. * @param string $default Fallback when empty. * @return string */ private static function attr( $a, $key, $default ) { return isset( $a[ $key ] ) && '' !== trim( (string) $a[ $key ] ) ? (string) $a[ $key ] : $default; } }