$this->template( new $template['path']( '', false, $this->current_template ) );
$email_template = $this->__get( 'template' );
! method_exists( $email_template, 'get_field_template' ) ||
! method_exists( $email_template, 'set_field' )
$this->field_template = $email_template->get_field_template();
$field_values = trim( $this->process_field_values() );
return make_clickable( $field_values );
* Process the plain text email message.
* @param bool $show_empty_fields Whether to display empty fields in the email.
private function process_plain_message( bool $show_empty_fields = false ): string {
* Filter the form data before it is used to generate the email message.
* @param array $form_data Form data.
* @param array $fields List of submitted fields.
$this->form_data = apply_filters( 'wpforms_emails_notifications_form_data', $this->form_data, $this->fields );
foreach ( $this->form_data['fields'] as $field ) {
* Filter whether to ignore the field in the email.
* @param bool $ignore Whether to ignore the field in the email.
* @param array $field Field data.
* @param array $form_data Form data.
if ( apply_filters( 'wpforms_emails_notifications_field_ignored', false, $field, $this->form_data ) ) {
$field_message = $this->get_field_plain( $field, $show_empty_fields );
* Filter the field message before it is added to the email message.
* @since 1.8.9.3 The $notifications parameter was added.
* @param string $field_message Field message.
* @param array $field Field data.
* @param bool $show_empty_fields Whether to display empty fields in the email.
* @param array $form_data Form data.
* @param array $fields List of submitted fields.
* @param Notifications $notifications Notifications instance.
$message .= apply_filters( 'wpforms_emails_notifications_field_message_plain', $field_message, $field, $show_empty_fields, $this->form_data, $this->fields, $this );
// Trim the message and return.
return rtrim( $message, "\r\n" );
* Get a single field plain text markup.
* @param array $field Field data.
* @param bool $show_empty_fields Whether to display empty fields in the email.
public function get_field_plain( array $field, bool $show_empty_fields ): string { // phpcs:ignore Generic.Metrics.CyclomaticComplexity
$field_id = $field['id'] ?? '';
$field = $this->fields[ $field_id ] ?? $field;
if ( ! $show_empty_fields && ( ! isset( $field['value'] ) || (string) $field['value'] === '' ) ) {
if ( $this->is_calculated_field_hidden( $field_id ) ) {
$field_name = $field['name'] ?? '';
$field_val = empty( $field['value'] ) && ! is_numeric( $field['value'] ) ? esc_html__( '(empty)', 'wpforms-lite' ) : $field['value'];
// Add quantity for the field.
if ( wpforms_payment_has_quantity( $field, $this->form_data ) ) {
$field_val = wpforms_payment_format_quantity( $field );
// Set a default field name if empty.
if ( empty( $field_name ) && $field_name !== null ) {
$field_name = $this->get_default_field_name( $field['id'] );
$message .= '--- ' . $field_name . " ---\r\n\r\n";
$field_value = wpforms_decode_string( $field_val ) . "\r\n\r\n";
* Filter the field value before it is added to the email message.
* @param string $field_value Field value.
* @param array $field Field data.
* @param array $form_data Form data.
$field_value = apply_filters_deprecated( // phpcs:disable WPForms.Comments.ParamTagHooks.InvalidParamTagsQuantity
'wpforms_emails_notifications_plaintext_field_value',
[ $field_value, $field, $this->form_data ],
'1.8.7 of the WPForms plugin',
'wpforms_plaintext_field_value'
/** This filter is documented in /includes/emails/class-emails.php */
$field_value = apply_filters( // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
'wpforms_plaintext_field_value',
// Append the filtered field value to the message.
$message .= $field_value;
* Process the HTML email message.
* @param bool $show_empty_fields Whether to display empty fields in the email.
* @noinspection PhpUnusedLocalVariableInspection
private function process_html_message( $show_empty_fields = false ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity
* Filter the list of field types to display in the email.
* @param array $other_fields List of field types.
* @param array $form_data Form data.
$other_fields = apply_filters_deprecated( // phpcs:disable WPForms.Comments.ParamTagHooks.InvalidParamTagsQuantity
'wpforms_emails_notifications_display_other_fields',
[ [], $this->form_data ],
'1.8.5.2 of the WPForms plugin',
'wpforms_email_display_other_fields'
/** This filter is documented in /includes/emails/class-emails.php */
$other_fields = (array) apply_filters( // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
'wpforms_email_display_other_fields',
* Filter the form data before it is used to generate the email message.
* @since 1.8.9 The $fields parameter was added.
* @param array $form_data Form data.
* @param array $fields List of submitted fields.
$this->form_data = apply_filters( 'wpforms_emails_notifications_form_data', $this->form_data, $this->fields );
foreach ( $this->form_data['fields'] as $field ) {
* Filter whether to ignore the field in the email.
* @param bool $ignore Whether to ignore the field in the email.
* @param array $field Field data.
* @param array $form_data Form data.
if ( apply_filters( 'wpforms_emails_notifications_field_ignored', false, $field, $this->form_data ) ) {
$field_message = $this->get_field_html( $field, $show_empty_fields, $other_fields );
* Filter the field message before it is added to the email message.
* @since 1.8.9.3 The $notifications parameter was added.
* @param string $field_message Field message.
* @param array $field Field data.
* @param bool $show_empty_fields Whether to display empty fields in the email.
* @param array $other_fields List of field types.
* @param array $form_data Form data.
* @param array $fields List of submitted fields.
* @param Notifications $notifications Notifications instance.
$field_message = (string) apply_filters( 'wpforms_emails_notifications_field_message_html', $field_message, $field, $show_empty_fields, $other_fields, $this->form_data, $this->fields, $this );
$message .= trim( $field_message );
* Get a single field HTML markup.
* @param array $field Field data.
* @param bool $show_empty_fields Whether to display empty fields in the email.
* @param array $other_fields List of field types.
public function get_field_html( array $field, bool $show_empty_fields, array $other_fields ): string { // phpcs:ignore Generic.Metrics.CyclomaticComplexity
$field_type = ! empty( $field['type'] ) ? $field['type'] : '';
$field_id = $field['id'] ?? '';
// Check if the field is empty in $this->fields.
if ( empty( $this->fields[ $field_id ] ) ) {
// Check if the field type is in $other_fields, otherwise skip.
// Skip if the field is conditionally hidden.
empty( $other_fields ) ||
! in_array( $field_type, $other_fields, true ) ||
wpforms_conditional_logic_fields()->field_is_hidden( $this->form_data, $field_id )
// Handle specific field types.
[ $field_name, $field_val ] = $this->process_special_field_values( $field );
// Handle fields that are not empty in $this->fields.
if ( ! $show_empty_fields && ( ! isset( $this->fields[ $field_id ]['value'] ) || (string) $this->fields[ $field_id ]['value'] === '' ) ) {
if ( $this->is_calculated_field_hidden( $field_id ) ) {
$field_name = $this->fields[ $field_id ]['name'] ?? '';
$field_val = empty( $this->fields[ $field_id ]['value'] ) && ! is_numeric( $this->fields[ $field_id ]['value'] ) ? '<em>' . esc_html__( '(empty)', 'wpforms-lite' ) . '</em>' : $this->fields[ $field_id ]['value'];
// Set a default field name if empty.
if ( empty( $field_name ) && $field_name !== null ) {
$field_name = $this->get_default_field_name( $field_id );
* Filter the field name before it is added to the email message.
* @param string $field_name Field name.
* @param array $field Field data.
* @param array $form_data Form data.
* @param string $context Context of the field name.
$field_name = (string) apply_filters( // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
'wpforms_html_field_name',
$this->fields[ $field_id ] ?? $field,
/** This filter is documented in src/SmartTags/SmartTag/FieldHtmlId.php.*/
$field_val = (string) apply_filters( // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
'wpforms_html_field_value',
$this->fields[ $field_id ] ?? $field,
$field_val = str_replace( [ "\r\n", "\r", "\n" ], '<br/>', $field_val );
// Replace the payment total value if an order summary is enabled.
// Ideally, it could be done through the `wpforms_html_field_value` filter,
// but necessary data is missed there, e.g., entry data ($this->fields).
if ( $field_type === 'payment-total' && ! empty( $field['summary'] ) ) {
$field_val = $this->get_payment_total_value( $field_val );
// Append the field item to the message.
[ '{field_type}', '{field_name}', '{field_value}' ],
[ $field_type, $field_name, $field_val ],
* Get payment total value.
* @param string $value Field value.
private function get_payment_total_value( string $value ): string {
return $this->process_tag( '{order_summary}' ) . '<span class="wpforms-payment-total">' . $value . '</span>';
* Check if a calculated field is hidden.
* @param int $field_id Field ID.
private function is_calculated_field_hidden( $field_id ): bool {
return ! empty( $this->form_data['fields'][ $field_id ]['calculation_is_enabled'] ) &&
! empty( $this->form_data['fields'][ $field_id ]['calculation_code_php'] ) &&
isset( $this->fields[ $field_id ]['visible'] )
&& ! $this->fields[ $field_id ]['visible'];
* @param string $input Smart tag.
* @param string $context Context of the smart tag.
private function process_tag( $input = '', $context = 'notification' ): string {
return wpforms_process_smart_tags( $input, $this->form_data, $this->fields, (string) $this->entry_id, $context );
* Filter the smart tag value for the mailer email addresses.
* @param string|mixed $value Smart Tag value.
* @param string $tag_name Smart tag name.
* @param array $form_data Form data.
* @param array $fields List of fields.
* @param int $entry_id Entry ID.
* @param SmartTag $smart_tag_object The smart tag object or the Generic object for those cases when class
* @noinspection PhpMissingParamTypeInspection
* @noinspection PhpUnusedParameterInspection
public static function filter_smarttags_process_value( $value, $tag_name, $form_data, $fields, $entry_id, $smart_tag_object ): ?string {
$tag_name = (string) $tag_name;
$fields = (array) $fields;
// Smart tag isn't registered and can be replaced via filters.
$value = (string) $value;
$context = $smart_tag_object->context ?? '';
// In these contexts, we need to check if the smart tag is allowed.
// Check if the smart tag is allowed AND if the context is allowed.
if ( in_array( $tag_name, $allowed_tags, true ) || ! in_array( $context, $address_context, true ) ) {
return self::validate_notification_email_smart_tags( $value, $tag_name, $fields, $smart_tag_object );
* Validate notification email fields.
* @param string|mixed $value Smart Tag value.
* @param string $tag_name Smart tag name.
* @param array $fields List of fields.
* @param SmartTag $smart_tag_object The smart tag object or the Generic object for those cases when class unregistered.
private static function validate_notification_email_smart_tags( string $value, string $tag_name, array $fields, SmartTag $smart_tag_object ): string {
$field_id = self::get_smart_tag_field_id( $tag_name, $smart_tag_object );
// Empty value for all non-field smart tags.
if ( $field_id === null || $field_id === '' || ! isset( $fields[ $field_id ]['type'] ) ) {
$field_type = $fields[ $field_id ]['type'];
// If the field type is Email, return the value.
if ( $field_type === 'email' ) {
// Allow the Name field value in the Reply To setting.
if ( $field_type === 'name' && $smart_tag_object->context === 'notification-reply-to' ) {
// Otherwise, return an empty string if the value is not an email.
return wpforms_is_email( $value ) ? $value : '';
* Get smart tag field ID.
* @param string $tag_name Smart tag name.
* @param SmartTag $smart_tag_object The smart tag object or the Generic object for those cases when class unregistered.
* @return mixed|string|null
private static function get_smart_tag_field_id( string $tag_name, SmartTag $smart_tag_object ) {
if ( $tag_name === 'field_value_id' ) {
return $smart_tag_object->get_attributes()[ $tag_name ] ?? null;
if ( $tag_name !== 'field_id' ) {
$field_id_parts = explode( '|', $smart_tag_object->get_attributes()['field_id'] ?? '' );
return $field_id_parts[0] ?? null;
* Process special field types.
* This is used for fields such as Page Break, HTML, Content, etc.
* @param array $field Field data.
private function process_special_field_values( $field ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity