PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 1.7.0
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v1.7.0
2.12.6 2.12.5 2.12.4 2.12.3 2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 0.0.2 0.0.3 All 96 releases
sureforms / admin / views / single-entry.php
single-entry.php
541 lines 18.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * SureForms Single Entries Page.
4 *
5 * @since 0.0.13
6 * @package sureforms.
7 */
8
9 namespace SRFM\Admin\Views;
10
11 use SRFM\Inc\Database\Tables\Entries;
12 use SRFM\Inc\Helper;
13
14 /**
15 * Exit if accessed directly.
16 */
17 if ( ! defined( 'ABSPATH' ) ) {
18 exit;
19 }
20
21 /**
22 * Single entry page.
23 *
24 * @since 0.0.13
25 */
26 class Single_Entry {
27 /**
28 * Stores the entry ID.
29 *
30 * @var string|null $entry_id ID for the specific entry.
31 * @since 0.0.13
32 */
33 private $entry_id;
34
35 /**
36 * Stores the entry data for the specified entry ID.
37 *
38 * @var array<mixed>|null $entry Entry data for the specified entry ID.
39 * @since 0.0.13
40 */
41 private $entry;
42
43 /**
44 * Initialize the properties.
45 *
46 * @since 0.0.13
47 */
48 public function __construct() {
49 if ( isset( $_GET['_wpnonce'] ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'srfm_entries_action' ) ) {
50 return;
51 }
52 $this->entry_id = isset( $_GET['entry_id'] ) ? intval( sanitize_text_field( wp_unslash( $_GET['entry_id'] ) ) ) : null;
53 $this->entry = $this->entry_id ? Entries::get( $this->entry_id ) : null;
54 }
55
56 /**
57 * Render the single entry page if an entry is found.
58 *
59 * @since 0.0.13
60 * @return void
61 */
62 public function render() {
63 if ( ! $this->entry ) {
64 return;
65 }
66 $entry_status = $this->entry['status'];
67 $submitted_on = gmdate( 'Y/m/d \a\t g:i a', strtotime( $this->entry['created_at'] ) );
68 // Translators: %d is the form ID.
69 $form_name = ! empty( get_the_title( $this->entry['form_id'] ) ) ? get_the_title( $this->entry['form_id'] ) : sprintf( esc_html__( 'SureForms Form #%d', 'sureforms' ), intval( $this->entry['form_id'] ) );
70 $meta_data = $this->entry['form_data'];
71 $excluded_fields = [ 'srfm-honeypot-field', 'g-recaptcha-response', 'srfm-sender-email-field' ];
72 ?>
73 <div class="wrap">
74 <h1 class="wp-heading-inline">
75 <?php
76 /* Translators: %s is the entry id. */
77 printf( esc_html__( 'Entry #%s', 'sureforms' ), esc_html( $this->entry_id ) );
78 ?>
79 </h1>
80
81 <form method="post" action="<?php echo esc_url( admin_url( "admin.php?page=sureforms_entries&entry_id={$this->entry_id}&view=details" ) ); ?>"> <!-- check for nonce, referrer, etc. -->
82 <?php
83 /**
84 * Action hook right after entry form opening tag.
85 *
86 * @since 1.3.0
87 */
88 do_action( 'srfm_after_entry_form_opening_tag', $this->entry, $this );
89 ?>
90
91 <div id="poststuff">
92 <div id="post-body" class="metabox-holder columns-2">
93 <div id="postbox-container-1" class="postbox-container">
94 <?php
95 /**
96 * Action hook right before entry form opening tag.
97 *
98 * @since 1.3.0
99 */
100 do_action( 'srfm_before_entry_submission_info', $this->entry, $this );
101 $this->render_upsell_placeholder( 'notes' );
102
103 $this->render_submission_info( $form_name, $entry_status, $submitted_on );
104
105 /**
106 * Action hook right after entry form opening tag.
107 *
108 * @since 1.3.0
109 */
110 do_action( 'srfm_after_entry_submission_info', $this->entry, $this );
111 $this->render_upsell_placeholder( 'resend-notification' );
112 ?>
113 </div>
114 <div id="postbox-container-2" class="postbox-container">
115 <?php $this->render_form_data( $meta_data, $excluded_fields ); ?>
116 </div>
117 <div id="postbox-container-3" class="postbox-container">
118 <?php $this->render_entry_logs( $this->entry['logs'] ); ?>
119 </div>
120 </div><!-- /post-body -->
121 <br class="clear">
122 </div>
123 <!-- /poststuff -->
124
125 <?php
126 /**
127 * Action hook right before entry form closing tag.
128 *
129 * @since 1.3.0
130 */
131 do_action( 'srfm_before_entry_form_closing_tag', $this->entry, $this );
132 ?>
133 </form>
134 </div>
135 <?php
136 }
137
138 /**
139 * Add tooltip wrapper.
140 *
141 * @param string $position Tooltip position.
142 * @param callable $element_cb Element callback.
143 * @param callable $tooltip_cb Tooltip callback.
144 * @since 1.3.0
145 * @return void
146 */
147 protected function add_tooltip( $position, $element_cb, $tooltip_cb ) {
148 $upsell_url = Helper::get_sureforms_website_url( 'pricing', [ 'utm_medium' => 'srfm_entries_management' ] );
149 ?>
150 <div class="srfm-tooltip">
151 <?php call_user_func( $element_cb ); ?>
152 <div class="tooltip-wrap <?php echo esc_attr( $position ); ?>">
153 <div class="tooltip-content">
154 <div class="tooltip-text">
155 <?php call_user_func( $tooltip_cb ); ?>
156 </div>
157 <a target="_blank" href="<?php echo esc_url( $upsell_url ); ?>"><?php esc_html_e( 'Upgrade', 'sureforms' ); ?></a>
158 </div>
159 <i></i>
160 </div>
161 </div>
162 <?php
163 }
164
165 /**
166 * Renders the upsell placeholder.
167 *
168 * @param string $for The placeholder type.
169 * @since 1.3.0
170 * @return void
171 */
172 protected function render_upsell_placeholder( $for ) {
173 if ( defined( 'SRFM_PRO_VER' ) ) {
174 return;
175 }
176
177 switch ( $for ) {
178 case 'edit-button':
179 $position = 'top';
180 $element_cb = static function() {
181 ?>
182 <button class="button button-link srfm-edit-entry" type="button">
183 <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
184 <path d="M11.2411 2.99111L12.3661 1.86612C12.8543 1.37796 13.6457 1.37796 14.1339 1.86612C14.622 2.35427 14.622 3.14573 14.1339 3.63388L7.05479 10.713C6.70234 11.0654 6.26762 11.3245 5.78993 11.4668L4 12L4.53319 10.2101C4.67548 9.73239 4.93456 9.29767 5.28701 8.94522L11.2411 2.99111ZM11.2411 2.99111L13 4.74999M12 9.33333V12.5C12 13.3284 11.3284 14 10.5 14H3.5C2.67157 14 2 13.3284 2 12.5V5.49999C2 4.67157 2.67157 3.99999 3.5 3.99999H6.66667" stroke="#2271b1" stroke-linecap="round" stroke-linejoin="round"/>
185 </svg>
186 <?php esc_html_e( 'Edit', 'sureforms' ); ?>
187 </button>
188 <?php
189 };
190 $tooltip_cb = static function() {
191 ?>
192 <h3><?php esc_html_e( 'Unlock Edit Form Entires', 'sureforms' ); ?></h3>
193 <p><?php esc_html_e( 'With the SureForms Starter plan, you can easily edit your entries to suit your needs.', 'sureforms' ); ?></p>
194 <?php
195 };
196 break;
197
198 case 'resend-notification':
199 $position = 'left';
200 $element_cb = static function() {
201 ?>
202 <button type="button" class="button srfm-resend-notification-trigger-btn"><?php esc_html_e( 'Resend Notification', 'sureforms' ); ?></button>
203 <?php
204 };
205 $tooltip_cb = static function() {
206 ?>
207 <h3><?php esc_html_e( 'Unlock Resend Email Notification', 'sureforms' ); ?></h3>
208 <p><?php esc_html_e( 'With the SureForms Starter plan, you can effortlessly resend email notifications, ensuring your important updates reach their recipients with ease.', 'sureforms' ); ?></p>
209 <?php
210 };
211 break;
212
213 case 'notes':
214 $position = 'left';
215 $element_cb = static function() {
216 ?>
217 <div id="submitdiv" class="postbox entry-notes">
218 <div class="postbox-header">
219 <h2><?php esc_html_e( 'Entry Notes', 'sureforms' ); ?></h2>
220 <button type="button" id="srfm-add-entry-note" class="srfm-add-entry-note-button">
221 <?php esc_html_e( 'Add Note', 'sureforms' ); ?>
222 <svg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M8 3.33594V12.6693' stroke='black' stroke-width='1.25' stroke-linecap='round' stroke-linejoin='round'/><path d='M3.33337 8H12.6667' stroke='black' stroke-width='1.25' stroke-linecap='round' stroke-linejoin='round'/></svg>
223 </button>
224 </div>
225 <div class="inside">
226 <div class="srfm-entry-note-wrapper">
227 <div class="entry-notes-container"></div>
228 <div class="add-notes-field">
229 <textarea disabled id="srfm-entry-note" rows="5"></textarea>
230 <button id="srfm-add-note" type="button" class="button"><?php esc_html_e( 'Submit Note', 'sureforms' ); ?></button>
231 </div>
232 </div>
233 </div>
234 </div>
235 <?php
236 };
237 $tooltip_cb = static function() {
238 ?>
239 <h3><?php esc_html_e( 'Unlock Add Note', 'sureforms' ); ?></h3>
240 <p><?php esc_html_e( 'With the SureForms Starter plan, enhance your submitted form entries by adding personalized notes for better clarity and tracking.', 'sureforms' ); ?></p>
241 <?php
242 };
243 break;
244
245 default:
246 // Do nothing.
247 return;
248 }
249
250 $this->add_tooltip( $position, $element_cb, $tooltip_cb );
251 }
252
253 /**
254 * Render the submission information for a specific entry.
255 *
256 * @param string $form_name The form title/name.
257 * @param string $entry_status The entry status (read/unread).
258 * @param string $submitted_on The submission date.
259 * @since 0.0.13
260 * @return void
261 */
262 private function render_submission_info( $form_name, $entry_status, $submitted_on ) {
263 $mark_as_unread_url = add_query_arg( 'action', 'unread' );
264 $user_id = Helper::get_integer_value( $this->entry['user_id'] );
265 $user_info = 0 !== $user_id ? get_userdata( $user_id ) : null;
266 $user_name = $user_info ? $user_info->display_name : '';
267 $user_profile_url = $user_info ? get_author_posts_url( $user_id ) : '';
268 ?>
269 <div id="sureform_form_name_meta" class="postbox ">
270 <div class="postbox-header">
271 <!-- Removed "hndle ui-sortable-handle" class from h2 to remove the draggable stylings. -->
272 <h2><?php esc_html_e( 'Submission Info', 'sureforms' ); ?></h2>
273 </div>
274 <div class="inside">
275 <table style="border-collapse: separate; border-spacing: 5px 5px;">
276 <tbody>
277 <!-- TODO: Add Type and User info. -->
278 <tr>
279 <td><b><?php esc_html_e( 'Entry:', 'sureforms' ); ?></b></td>
280 <td>#<?php echo esc_attr( $this->entry_id ); ?></td>
281 </tr>
282 <tr>
283 <td><b><?php esc_html_e( 'Form Name:', 'sureforms' ); ?></b></td>
284 <td><a target="_blank" rel="noopener" href="<?php the_permalink( $this->entry['form_id'] ); ?>"><?php echo esc_attr( $form_name ); ?></a></td>
285 </tr>
286 <?php if ( ! empty( $this->entry['submission_info']['user_ip'] ) ) { ?>
287 <tr>
288 <td><b><?php esc_html_e( 'User IP:', 'sureforms' ); ?></b></td>
289 <td><a target="_blank" rel="noopener" href="https://ipinfo.io/"><?php echo esc_attr( $this->entry['submission_info']['user_ip'] ); ?></a></td>
290 </tr>
291 <?php } ?>
292 <tr>
293 <td><b><?php esc_html_e( 'Browser:', 'sureforms' ); ?></b></td>
294 <td><?php echo esc_attr( $this->entry['submission_info']['browser_name'] ); ?></td>
295 </tr>
296 <tr>
297 <td><b><?php esc_html_e( 'Device:', 'sureforms' ); ?></b></td>
298 <td><?php echo esc_attr( $this->entry['submission_info']['device_name'] ); ?></td>
299 </tr>
300 <?php if ( 0 !== $user_id ) { ?>
301 <tr>
302 <td><b><?php esc_html_e( 'User:', 'sureforms' ); ?></b></td>
303 <td><a target="_blank" rel="noopener" href="<?php echo esc_url( $user_profile_url ); ?>"><?php echo esc_attr( $user_name ); ?></a></td>
304 </tr>
305 <?php } ?>
306 <tr>
307 <td><b><?php esc_html_e( 'Status:', 'sureforms' ); ?></b></td>
308 <td>
309 <span style="text-transform: capitalize;">
310 <?php echo esc_attr( $entry_status ); ?>
311 </span>
312 <?php if ( 'read' === $entry_status ) { ?>
313 <span> | <a href="<?php echo esc_url( $mark_as_unread_url ); ?>" id="srfm-entry-mark-unread" style="font-size: 12px;"><?php esc_html_e( 'Mark as Unread', 'sureforms' ); ?></a></span>
314 <?php } ?>
315 </td>
316 </tr>
317 <tr>
318 <td><b><?php esc_html_e( 'Submitted On:', 'sureforms' ); ?></b></td>
319 <td><?php echo esc_attr( $submitted_on ); ?></td>
320 </tr>
321 </tbody>
322 </table>
323 </div>
324 </div>
325 <?php
326 }
327
328 /**
329 * Render the form data for a specific entry.
330 *
331 * @param array<mixed> $meta_data The form meta data.
332 * @param array<string> $excluded_fields Fields to exlude from display.
333 * @since 0.0.13
334 * @return void
335 */
336 private function render_form_data( $meta_data, $excluded_fields ) {
337 ?>
338 <div id="sureform_entry_meta" class="postbox srfm-form-data">
339 <div class="postbox-header">
340 <!-- Removed "hndle ui-sortable-handle" class from h2 to remove the draggable stylings. -->
341 <h2><?php esc_html_e( 'Form Data', 'sureforms' ); ?></h2>
342 <?php
343 /**
344 * Action hook right after entry form opening tag.
345 *
346 * @since 1.3.0
347 */
348 do_action( 'srfm_after_entry_postbox_title', $this->entry, $this );
349 $this->render_upsell_placeholder( 'edit-button' );
350 ?>
351 </div>
352 <div class="inside">
353 <table class="widefat striped">
354 <tbody>
355 <tr>
356 <th><b><?php esc_html_e( 'Fields', 'sureforms' ); ?></b></th>
357 <th><b><?php esc_html_e( 'Values', 'sureforms' ); ?></b></th>
358 </tr>
359 <?php
360 foreach ( $meta_data as $field_name => $value ) {
361 if ( in_array( $field_name, $excluded_fields, true ) ) {
362 continue;
363 }
364 if ( false === str_contains( $field_name, '-lbl-' ) ) {
365 continue;
366 }
367 $label = explode( '-lbl-', $field_name )[1];
368 // Getting the encrypted label. we are removing the block slug here.
369 $label = explode( '-', $label )[0];
370 ?>
371 <tr>
372 <style>
373 .file-cards-container {
374 display: flex;
375 flex-wrap: wrap;
376 gap: 10px;
377 }
378 .file-card {
379 border: 1px solid #ddd;
380 border-radius: 4px;
381 padding: 10px;
382 width: 100px; /* Reduced width */
383 text-align: center;
384 background: #f9f9f9;
385 font-size: 12px; /* Reduced font size for smaller cards */
386 }
387 .file-card-image img {
388 max-width: 80px; /* Reduced max width */
389 max-height: 80px; /* Reduced max height */
390 object-fit: cover;
391 }
392 .file-card-icon {
393 font-size: 24px; /* Reduced icon size */
394 margin-bottom: 5px;
395 }
396 .file-card-details {
397 margin-bottom: 5px;
398 font-weight: bold;
399 }
400 .file-card-url a {
401 color: #007bff;
402 text-decoration: none;
403 font-size: 12px; /* Reduced font size */
404 }
405 .file-card-url a:hover {
406 text-decoration: underline;
407 }
408 </style>
409 <td><b><?php echo $label ? wp_kses_post( html_entity_decode( Helper::decrypt( $label ) ) ) : ''; ?></b></td>
410 <?php
411 if ( false !== strpos( $field_name, 'srfm-upload' ) ) {
412 ?>
413 <td>
414 <div class="file-cards-container">
415 <?php
416 $upload_values = $value;
417 if ( ! empty( $upload_values ) && is_array( $upload_values ) ) {
418 foreach ( $upload_values as $file_url ) {
419 $file_url = urldecode( Helper::get_string_value( $file_url ) );
420
421 if ( ! empty( $file_url ) ) {
422 if ( ! file_exists( Helper::convert_fileurl_to_filepath( $file_url ) ) ) {
423 continue;
424 }
425
426 $file_type = pathinfo( $file_url, PATHINFO_EXTENSION );
427 $is_image = in_array( $file_type, [ 'gif', 'png', 'bmp', 'jpg', 'jpeg', 'svg' ], true );
428 ?>
429 <div class="file-card" data-fileurl-hash="<?php echo esc_attr( md5( $file_url ) ); ?>">
430 <?php if ( $is_image ) { ?>
431 <div class="file-card-image">
432 <a target="_blank" href="<?php echo esc_attr( $file_url ); ?>">
433 <img src="<?php echo esc_attr( $file_url ); ?>" alt="<?php esc_attr_e( 'Image', 'sureforms' ); ?>" />
434 </a>
435 </div>
436 <?php } else { ?>
437 <div class="file-card-icon">
438 <?php // Display a file icon for non-image files. ?>
439 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M4 16.333V4.667a1.333 1.333 0 011.333-1.333h13.334a1.333 1.333 0 011.333 1.333v11.666a1.333 1.333 0 01-1.333 1.333H5.333A1.333 1.333 0 014 16.333zm8-8h2v6h-2v-6zm-2 8h6v2H10v-2zm-6-6h4v6H4v-6zm0-4h16v2H4V6z"/></svg>
440 </div>
441 <div class="file-card-details">
442 <span><?php echo esc_html( strtoupper( $file_type ) ); ?></span>
443 </div>
444 <?php } ?>
445 <div class="file-card-url">
446 <a target="_blank" href="<?php echo esc_attr( $file_url ); ?>"><?php echo esc_html__( 'Open', 'sureforms' ); ?></a>
447 </div>
448 </div>
449 <?php
450 }
451 }
452 }
453 ?>
454 </div>
455 </td>
456 <?php } elseif ( false !== strpos( $field_name, 'srfm-url' ) ) { ?>
457 <td><a target="_blank" href="<?php echo esc_url( $value ); ?>"><?php echo esc_url( $value ); ?></a></td>
458 <?php } elseif ( apply_filters( 'srfm_entry_render_field_custom_value', false, $field_name ) ) { ?>
459 <?php echo wp_kses_post( apply_filters( 'srfm_entry_custom_value', '', $value ) ); ?>
460 <?php } else { ?>
461 <td><?php echo false !== strpos( $value, PHP_EOL ) ? wp_kses_post( wpautop( $value ) ) : wp_kses_post( $value ); ?></td>
462 <?php } ?>
463 </tr>
464 <?php } ?>
465 </tbody>
466 </table>
467 </div>
468 </div>
469 <?php
470 }
471 /**
472 * Render the entry logs for a specific entry.
473 *
474 * @param array<mixed> $entry_logs Entry logs stored in the database.
475 * @since 0.0.13
476 * @return void
477 */
478 private function render_entry_logs( $entry_logs ) {
479 ob_start();
480 ?>
481 <div id="sureform_entry_meta" class="postbox srfm-entry-logs">
482 <div class="postbox-header">
483 <!-- Removed "hndle ui-sortable-handle" class from h2 to remove the draggable stylings. -->
484 <h2><?php esc_html_e( 'Entry Logs', 'sureforms' ); ?></h2>
485 </div>
486 <div class="inside">
487 <table class="striped entry-logs-table">
488 <tbody>
489 <?php if ( ! empty( $entry_logs ) ) { ?>
490 <?php foreach ( $entry_logs as $log ) { ?>
491 <tr>
492 <td class="entry-log-container">
493 <div class="entry-log">
494 <h4 class="entry-log-title">
495 <?php echo esc_html( $log['title'] ); ?>
496 <?php echo esc_html( gmdate( '\a\t Y-m-d H:i:s', $log['timestamp'] ) ); ?>
497 </h4>
498 <div class="entry-log-messages">
499 <?php foreach ( $log['messages'] as $message ) { ?>
500 <p><?php echo wp_kses_post( $message ); ?></p>
501 <?php } ?>
502 </div>
503 </div>
504 </td>
505 </tr>
506 <?php } ?>
507 <?php } else { ?>
508 <p class="no-logs-found"><?php esc_html_e( 'No logs found for this entry.', 'sureforms' ); ?></p>
509 <?php } ?>
510 </tbody>
511 </table>
512 </div>
513 </div>
514 <?php
515 $content = ob_get_clean();
516
517 $allowed_tags = array_merge(
518 wp_kses_allowed_html( 'post' ),
519 [
520 'svg' => [
521 'width' => true,
522 'height' => true,
523 'fill' => true,
524 'viewbox' => true,
525 'xmlns' => true,
526 ],
527 'path' => [
528 'd' => true,
529 'opacity' => true,
530 'class' => true,
531 'stroke-width' => true,
532 'stroke-linecap' => true,
533 'stroke-linejoin' => true,
534 ],
535 ]
536 );
537
538 echo wp_kses( apply_filters( 'srfm_entry_logs_markup', $content, $entry_logs ), $allowed_tags );
539 }
540 }
541