Skip to content

Commit ce67626

Browse files
committed
Improve HTML layout for pdf
1 parent b35f792 commit ce67626

File tree

4 files changed

+168
-37
lines changed

4 files changed

+168
-37
lines changed

projects/packages/forms/src/contact-form/class-contact-form.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2880,7 +2880,7 @@ function ( $json_str ) {
28802880
* @param string $label The field label.
28812881
* @return string The formatted label.
28822882
*/
2883-
private static function maybe_add_colon_to_label( $label ) {
2883+
public static function maybe_add_colon_to_label( $label ) {
28842884
$formatted_label = $label ? $label : '';
28852885
// Special case for the Terms consent field block which a period after the label.
28862886
$formatted_label = str_ends_with( $formatted_label, '?' ) ? $formatted_label : rtrim( $formatted_label, ':.' ) . ':';
@@ -2948,7 +2948,7 @@ function ( $choice ) {
29482948
* @param string|null $raw_label The raw label input.
29492949
* @return string The formatted and kses'd label string, or an empty string if raw_label is empty.
29502950
*/
2951-
private static function escape_and_sanitize_field_label( $raw_label ) {
2951+
public static function escape_and_sanitize_field_label( $raw_label ) {
29522952
if ( empty( $raw_label ) ) {
29532953
return ''; // kses the empty string
29542954
}

projects/packages/forms/src/contact-form/class-feedback-field.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ public function get_render_value( $context = 'default' ) {
146146
return $this->get_render_web_value();
147147
case 'email':
148148
return $this->get_render_email_value();
149+
case 'pdf':
150+
return $this->get_render_pdf_value();
149151
case 'ajax':
150152
return $this->get_render_web_value(); // For now, we use the same value for ajax and web.
151153
case 'csv':
@@ -222,6 +224,32 @@ private function get_render_email_value() {
222224
return $this->get_render_default_value();
223225
}
224226

227+
/**
228+
* Get the value of the field for rendering the pdf.
229+
*
230+
* @return string
231+
*/
232+
private function get_render_pdf_value() {
233+
if ( $this->is_of_type( 'image-select' ) ) {
234+
$choices = array();
235+
236+
foreach ( $this->value['choices'] as $choice ) {
237+
// On the email, we want to show the actual selected value, not the perceived value, as the options can be shuffled.
238+
$value = $choice['selected'];
239+
240+
if ( ! empty( $choice['label'] ) ) {
241+
$value .= ' - ' . $choice['label'];
242+
243+
}
244+
$choices[] = $value;
245+
}
246+
247+
return implode( ', ', $choices );
248+
}
249+
250+
return $this->get_render_default_value();
251+
}
252+
225253
/**
226254
* Get the default value of the field for rendering.
227255
*

projects/packages/forms/src/contact-form/class-feedback.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ public function get_all_legacy_values() {
571571
/**
572572
* Return the compiled fields for the given context.
573573
*
574-
* @param string $context The context in which the fields are compiled.
574+
* @param string $context The context in which the fields are compiled. Can be 'submit', 'api', 'web', 'email', 'pdf', 'ajax', 'csv', or 'default'.
575575
* @param string $array_shape The shape of the array to return. Can be 'all', 'value', 'label', or 'key-value'.
576576
*
577577
* @return array An array of compiled fields with labels and values.

projects/packages/forms/src/contact-form/class-response-pdf.php

Lines changed: 137 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,11 @@ public function stream_pdf( $feedback_id ) {
6363
// Allow remote images (http/s), but they're only allowed from same-site urls
6464
$options->set( 'isRemoteEnabled', true );
6565
$options->set( 'isHtml5ParserEnabled', true );
66+
$options->set( 'defaultFont', 'Sans-Serif' );
6667

6768
$dompdf = new Dompdf( $options );
6869

69-
$dompdf->setPaper( 'A4', 'landscape' );
70+
$dompdf->setPaper( 'A4', 'portrait' );
7071
$dompdf->setHttpContext(
7172
stream_context_create(
7273
array(
@@ -98,30 +99,149 @@ public function stream_pdf( $feedback_id ) {
9899
}
99100

100101
/**
101-
* Return Form HTML
102+
* Returns a compiled form with labels and values formatted for the pdf file
103+
* in a form of an array of lines.
102104
*
103-
* @param int $feedback_id the feedback id.
105+
* @param int $feedback_id - the feedback ID.
106+
* @param Contact_Form $form - the form.
107+
*
108+
* @return array $lines
104109
*/
105-
private function get_form_html( $feedback_id ) {
110+
public static function get_compiled_form_fields( $feedback_id, $form ) {
111+
$compiled_form = array();
112+
$response = Feedback::get( $feedback_id );
106113

107-
$footer = '';
108-
$tracking_pixel = '';
109-
$actions = '';
110-
$style = '';
111-
$template = '';
112-
$title = '';
114+
if ( $response instanceof Feedback ) {
115+
// If the response is an instance of Feedback, we can use its method to get compiled fields.
116+
$compiled_form = $response->get_compiled_fields( 'pdf', 'label|value' );
117+
}
113118

114119
/**
115-
* Filter the title used in the response pdf.
120+
* This filter allows a site owner to customize the response pdf file, by adding their own HTML around it for example.
116121
*
117122
* @module contact-form
118123
*
119124
* @since $$next-version$$
120125
*
121-
* @param string the title of the pdf
126+
* @param array $compiled_form the form response to be filtered
127+
* @param int $feedback_id the ID of the feedback form
128+
* @param Contact_Form $form a copy of this object
122129
*/
123-
$title = (string) apply_filters( 'jetpack_forms_response_pdf_title', '' );
124-
$body = Contact_Form::get_compiled_form_for_email( $feedback_id, null );
130+
$updated_compiled_form = apply_filters( 'jetpack_forms_response_pdf', $compiled_form, $feedback_id, $form );
131+
if ( $updated_compiled_form !== $compiled_form ) {
132+
$compiled_form = $updated_compiled_form;
133+
} else {
134+
// add styling to the array
135+
foreach ( $compiled_form as $key => $value ) {
136+
$safe_display_label = Contact_Form::escape_and_sanitize_field_label( $value['label'] );
137+
$safe_display_value = Contact_Form::escape_and_sanitize_field_value( $value['value'] );
138+
139+
if ( ! empty( $safe_display_label ) ) {
140+
$compiled_form[ $key ] = sprintf(
141+
'<p><strong>%1$s</strong><br /><span>%2$s</span></p>',
142+
Contact_Form::maybe_add_colon_to_label( $safe_display_label ),
143+
$safe_display_value
144+
);
145+
} else {
146+
$compiled_form[ $key ] = sprintf(
147+
'<p><span>%s</span></p>',
148+
$safe_display_value
149+
);
150+
}
151+
}
152+
}
153+
154+
return $compiled_form;
155+
}
156+
157+
/**
158+
* Return Form HTML
159+
*
160+
* @param int $feedback_id the feedback id.
161+
* @return string the HTML of the form or empty when not found.
162+
*/
163+
private function get_form_html( $feedback_id ) {
164+
165+
$response = Feedback::get( $feedback_id );
166+
167+
if ( ! $response ) {
168+
return '';
169+
}
170+
171+
$header = '<header>';
172+
$header .= '';
173+
if ( $response->get_author() ) {
174+
$header .= '<h3>' . $response->get_author() . '</h3>';
175+
}
176+
if ( $response->get_author_email() ) {
177+
$header .= '<p>';
178+
$header .= '<a href="mailto:' . $response->get_author_email() . '">' . $response->get_author_email() . '</a>';
179+
$header .= '</p>';
180+
}
181+
if ( $response->get_time() ) {
182+
$header .= sprintf(
183+
/* translators: Placeholder is the date of the form. */
184+
esc_html__( 'Date: %1$s', 'jetpack-forms' ),
185+
$response->get_time()
186+
);
187+
$header .= '<br/>';
188+
}
189+
if ( $response->get_entry_title() ) {
190+
$header .= sprintf(
191+
/* translators: Placeholder is the name of the form. */
192+
esc_html__( 'Source: %1$s', 'jetpack-forms' ),
193+
$response->get_entry_title()
194+
);
195+
$header .= '<br/>';
196+
}
197+
if ( $response->get_entry_permalink() ) {
198+
$header .= sprintf(
199+
/* translators: Placeholder is the URL of the form. */
200+
esc_html__( 'Source URL: %1$s', 'jetpack-forms' ),
201+
'<a href="' . $response->get_entry_permalink() . '">' . $response->get_entry_permalink() . '</a>'
202+
);
203+
$header .= '<br/>';
204+
}
205+
206+
// Todo add flag when emoji support is added in Dompdf.
207+
if ( $response->get_ip_address() ) {
208+
$header .= sprintf(
209+
/* translators: Placeholder is the IP address of the person who submitted a form. */
210+
esc_html__( 'IP Address: %1$s', 'jetpack-forms' ),
211+
( $response->get_country_flag() ? $response->get_country_flag() . ' ' : '' ) . $response->get_ip_address()
212+
);
213+
$header .= '<br/>';
214+
}
215+
216+
if ( $response->get_browser() ) {
217+
$header .= sprintf(
218+
/* translators: Placeholder is the Browser address of the person who submitted a form. */
219+
esc_html__( 'Browser: %1$s', 'jetpack-forms' ),
220+
$response->get_browser()
221+
);
222+
$header .= '<br/>';
223+
}
224+
225+
$header .= '</header>';
226+
227+
$message = implode( '', self::get_compiled_form_fields( $feedback_id, null ) );
228+
229+
$styles = '<style>
230+
a {
231+
color: #000;
232+
text-decoration: none;
233+
}
234+
</style>';
235+
236+
// Dompdf does not support emojis: https://github.com/dompdf/dompdf/issues/1698,
237+
// and hence we're using `wp_staticize_emoji()` to convert them to images.
238+
// See potential workaround: https://www.beaubus.com/blog/add_emoji_support_to_dompdf.html
239+
$html = '<html><head><meta charset="UTF-8">'
240+
. $styles
241+
. '</head><body><article>'
242+
. wp_staticize_emoji( $header )
243+
. wp_staticize_emoji( $message )
244+
. '</article></body></html>';
125245

126246
/**
127247
* Filter the filename of the template HTML surrounding the response email. The PHP file will return the template in a variable called $template.
@@ -130,27 +250,10 @@ private function get_form_html( $feedback_id ) {
130250
*
131251
* @since $$next-version$$
132252
*
133-
* @param string the filename of the HTML template used for response pdf
253+
* @param string the HTML body of the pdf
134254
*/
135-
require apply_filters( 'jetpack_forms_response_pdf_template', __DIR__ . '/templates/email-response.php' );
136-
$html_message = sprintf(
137-
// The tabs are just here so that the raw code is correctly formatted for developers
138-
// They're removed so that they don't affect the final message sent to users
139-
str_replace(
140-
"\t",
141-
'',
142-
$template
143-
),
144-
( $title !== '' ? '<h1>' . $title . '</h1>' : '' ),
145-
$body,
146-
'',
147-
'',
148-
$footer,
149-
$style,
150-
$tracking_pixel,
151-
$actions
152-
);
255+
$html = apply_filters( 'jetpack_forms_response_pdf_template', $html );
153256

154-
return $html_message;
257+
return $html;
155258
}
156259
}

0 commit comments

Comments
 (0)