$posted_data Unslashed root request data. * @param string $rate_limit_identifier Identifier used only for hashing. * @param int|null $timestamp Current timestamp. */ public function build_from_record( $record, array $posted_data, string $rate_limit_identifier = '', ?int $timestamp = null ): SubmissionContext { $post_id = isset( $posted_data['post_id'] ) && is_scalar( $posted_data['post_id'] ) ? (int) $posted_data['post_id'] : 0; $widget_id = isset( $posted_data['form_id'] ) && is_scalar( $posted_data['form_id'] ) ? (string) $posted_data['form_id'] : ''; return $this->build_from_submitted_data( $this->normalize_record_data( $record, $posted_data ), self::create_form_id( $post_id, $widget_id ), $rate_limit_identifier, $timestamp ); } /** * Normalize provider fields while keeping root ZSF fields available. * * @param object|null $record Hello Plus form record. * @param array $posted_data Unslashed root request data. * * @return array */ private function normalize_record_data( $record, array $posted_data ): array { $submitted_data = array(); foreach ( $this->get_internal_field_names() as $field_name ) { if ( array_key_exists( $field_name, $posted_data ) ) { $submitted_data[ $field_name ] = $posted_data[ $field_name ]; } } if ( ! is_object( $record ) || ! method_exists( $record, 'get' ) ) { return $submitted_data; } $fields = $record->get( 'fields' ); if ( ! is_array( $fields ) ) { return $submitted_data; } foreach ( $fields as $field_key => $field ) { $key = (string) $field_key; if ( is_array( $field ) ) { $value = $this->extract_field_value( $field ); if ( null !== $value ) { $submitted_data[ 'field_' . $key ] = $value; } } elseif ( is_scalar( $field ) ) { $submitted_data[ 'field_' . $key ] = $field; } } return $submitted_data; } /** * Extract the normalized scalar value from a provider field. * * @param array $field Provider field. * * @return scalar|null */ private function extract_field_value( array $field ) { foreach ( array( 'value', 'raw_value', 'title' ) as $value_key ) { if ( isset( $field[ $value_key ] ) && is_scalar( $field[ $value_key ] ) ) { return $field[ $value_key ]; } } return null; } /** * Get root protection field names. * * @return array */ private function get_internal_field_names(): array { return array( ProtectionFieldRenderer::HONEYPOT_FIELD, ProtectionFieldRenderer::TOKEN_FIELD, ProtectionFieldRenderer::STARTED_AT_FIELD, ); } /** * Sanitize a widget ID without WordPress runtime dependencies. * * @param string $widget_id Widget identifier. */ private static function sanitize_widget_id( string $widget_id ): string { if ( ! self::is_valid_widget_id( $widget_id ) ) { return 'unknown'; } return $widget_id; } }