PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 1.3.0
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v1.3.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
516 lines 18.1 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 ?>
149 <div class="srfm-tooltip">
150 <?php call_user_func( $element_cb ); ?>
151 <div class="tooltip-wrap <?php echo esc_attr( $position ); ?>">
152 <div class="tooltip-content">
153 <div class="tooltip-text">
154 <?php call_user_func( $tooltip_cb ); ?>
155 </div>
156 <a target="_blank" href="https://sureforms.com/pricing"><?php esc_html_e( 'Upgrade', 'sureforms' ); ?></a>
157 </div>
158 <i></i>
159 </div>
160 </div>
161 <?php
162 }
163
164 /**
165 * Renders the upsell placeholder.
166 *
167 * @param string $for The placeholder type.
168 * @since 1.3.0
169 * @return void
170 */
171 protected function render_upsell_placeholder( $for ) {
172 if ( defined( 'SRFM_PRO_VER' ) ) {
173 return;
174 }
175
176 switch ( $for ) {
177 case 'edit-button':
178 $position = 'top';
179 $element_cb = static function() {
180 ?>
181 <button class="button button-link srfm-edit-entry" type="button">
182 <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
183 <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"/>
184 </svg>
185 <?php esc_html_e( 'Edit', 'sureforms' ); ?>
186 </button>
187 <?php
188 };
189 $tooltip_cb = static function() {
190 ?>
191 <h3><?php esc_html_e( 'Unlock Edit Form Entires', 'sureforms' ); ?></h3>
192 <p><?php esc_html_e( 'With the SureForms Starter plan, you can easily edit your entries to suit your needs.', 'sureforms' ); ?></p>
193 <?php
194 };
195 break;
196
197 case 'resend-notification':
198 $position = 'left';
199 $element_cb = static function() {
200 ?>
201 <button type="button" class="button srfm-resend-notification-trigger-btn"><?php esc_html_e( 'Resend Notification', 'sureforms' ); ?></button>
202 <?php
203 };
204 $tooltip_cb = static function() {
205 ?>
206 <h3><?php esc_html_e( 'Unlock Resend Email Notification', 'sureforms' ); ?></h3>
207 <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>
208 <?php
209 };
210 break;
211
212 case 'notes':
213 $position = 'left';
214 $element_cb = static function() {
215 ?>
216 <div id="submitdiv" class="postbox entry-notes">
217 <div class="postbox-header">
218 <h2><?php esc_html_e( 'Entry Notes', 'sureforms' ); ?></h2>
219 <button type="button" id="srfm-add-entry-note" class="srfm-add-entry-note-button">
220 <?php esc_html_e( 'Add Note', 'sureforms' ); ?>
221 <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>
222 </button>
223 </div>
224 <div class="inside">
225 <div class="srfm-entry-note-wrapper">
226 <div class="entry-notes-container"></div>
227 <div class="add-notes-field">
228 <textarea disabled id="srfm-entry-note" rows="5"></textarea>
229 <button id="srfm-add-note" type="button" class="button"><?php esc_html_e( 'Submit Note', 'sureforms' ); ?></button>
230 </div>
231 </div>
232 </div>
233 </div>
234 <?php
235 };
236 $tooltip_cb = static function() {
237 ?>
238 <h3><?php esc_html_e( 'Unlock Add Note', 'sureforms' ); ?></h3>
239 <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>
240 <?php
241 };
242 break;
243
244 default:
245 // Do nothing.
246 return;
247 }
248
249 $this->add_tooltip( $position, $element_cb, $tooltip_cb );
250 }
251
252 /**
253 * Render the submission information for a specific entry.
254 *
255 * @param string $form_name The form title/name.
256 * @param string $entry_status The entry status (read/unread).
257 * @param string $submitted_on The submission date.
258 * @since 0.0.13
259 * @return void
260 */
261 private function render_submission_info( $form_name, $entry_status, $submitted_on ) {
262 $mark_as_unread_url = add_query_arg( 'action', 'unread' );
263 $user_id = Helper::get_integer_value( $this->entry['user_id'] );
264 $user_info = 0 !== $user_id ? get_userdata( $user_id ) : null;
265 $user_name = $user_info ? $user_info->display_name : '';
266 $user_profile_url = $user_info ? get_author_posts_url( $user_id ) : '';
267 ?>
268 <div id="sureform_form_name_meta" class="postbox ">
269 <div class="postbox-header">
270 <!-- Removed "hndle ui-sortable-handle" class from h2 to remove the draggable stylings. -->
271 <h2><?php esc_html_e( 'Submission Info', 'sureforms' ); ?></h2>
272 </div>
273 <div class="inside">
274 <table style="border-collapse: separate; border-spacing: 5px 5px;">
275 <tbody>
276 <!-- TODO: Add Type and User info. -->
277 <tr>
278 <td><b><?php esc_html_e( 'Entry:', 'sureforms' ); ?></b></td>
279 <td>#<?php echo esc_attr( $this->entry_id ); ?></td>
280 </tr>
281 <tr>
282 <td><b><?php esc_html_e( 'Form Name:', 'sureforms' ); ?></b></td>
283 <td><a target="_blank" rel="noopener" href="<?php the_permalink( $this->entry['form_id'] ); ?>"><?php echo esc_attr( $form_name ); ?></a></td>
284 </tr>
285 <?php if ( ! empty( $this->entry['submission_info']['user_ip'] ) ) { ?>
286 <tr>
287 <td><b><?php esc_html_e( 'User IP:', 'sureforms' ); ?></b></td>
288 <td><a target="_blank" rel="noopener" href="https://ipinfo.io/"><?php echo esc_attr( $this->entry['submission_info']['user_ip'] ); ?></a></td>
289 </tr>
290 <?php } ?>
291 <tr>
292 <td><b><?php esc_html_e( 'Browser:', 'sureforms' ); ?></b></td>
293 <td><?php echo esc_attr( $this->entry['submission_info']['browser_name'] ); ?></td>
294 </tr>
295 <tr>
296 <td><b><?php esc_html_e( 'Device:', 'sureforms' ); ?></b></td>
297 <td><?php echo esc_attr( $this->entry['submission_info']['device_name'] ); ?></td>
298 </tr>
299 <?php if ( 0 !== $user_id ) { ?>
300 <tr>
301 <td><b><?php esc_html_e( 'User:', 'sureforms' ); ?></b></td>
302 <td><a target="_blank" rel="noopener" href="<?php echo esc_url( $user_profile_url ); ?>"><?php echo esc_attr( $user_name ); ?></a></td>
303 </tr>
304 <?php } ?>
305 <tr>
306 <td><b><?php esc_html_e( 'Status:', 'sureforms' ); ?></b></td>
307 <td>
308 <span style="text-transform: capitalize;">
309 <?php echo esc_attr( $entry_status ); ?>
310 </span>
311 <?php if ( 'read' === $entry_status ) { ?>
312 <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>
313 <?php } ?>
314 </td>
315 </tr>
316 <tr>
317 <td><b><?php esc_html_e( 'Submitted On:', 'sureforms' ); ?></b></td>
318 <td><?php echo esc_attr( $submitted_on ); ?></td>
319 </tr>
320 </tbody>
321 </table>
322 </div>
323 </div>
324 <?php
325 }
326
327 /**
328 * Render the form data for a specific entry.
329 *
330 * @param array<mixed> $meta_data The form meta data.
331 * @param array<string> $excluded_fields Fields to exlude from display.
332 * @since 0.0.13
333 * @return void
334 */
335 private function render_form_data( $meta_data, $excluded_fields ) {
336 ?>
337 <div id="sureform_entry_meta" class="postbox srfm-form-data">
338 <div class="postbox-header">
339 <!-- Removed "hndle ui-sortable-handle" class from h2 to remove the draggable stylings. -->
340 <h2><?php esc_html_e( 'Form Data', 'sureforms' ); ?></h2>
341 <?php
342 /**
343 * Action hook right after entry form opening tag.
344 *
345 * @since 1.3.0
346 */
347 do_action( 'srfm_after_entry_postbox_title', $this->entry, $this );
348 $this->render_upsell_placeholder( 'edit-button' );
349 ?>
350 </div>
351 <div class="inside">
352 <table class="widefat striped">
353 <tbody>
354 <tr>
355 <th><b><?php esc_html_e( 'Fields', 'sureforms' ); ?></b></th>
356 <th><b><?php esc_html_e( 'Values', 'sureforms' ); ?></b></th>
357 </tr>
358 <?php
359 foreach ( $meta_data as $field_name => $value ) {
360 if ( in_array( $field_name, $excluded_fields, true ) ) {
361 continue;
362 }
363 if ( false === str_contains( $field_name, '-lbl-' ) ) {
364 continue;
365 }
366 $label = explode( '-lbl-', $field_name )[1];
367 // Getting the encrypted label. we are removing the block slug here.
368 $label = explode( '-', $label )[0];
369 ?>
370 <tr>
371 <td><b><?php echo $label ? wp_kses_post( html_entity_decode( Helper::decrypt( $label ) ) ) : ''; ?></b></td>
372 <?php
373 if ( false !== strpos( $field_name, 'srfm-upload' ) ) {
374 ?>
375 <style>
376 .file-cards-container {
377 display: flex;
378 flex-wrap: wrap;
379 gap: 10px;
380 }
381 .file-card {
382 border: 1px solid #ddd;
383 border-radius: 4px;
384 padding: 10px;
385 width: 100px; /* Reduced width */
386 text-align: center;
387 background: #f9f9f9;
388 font-size: 12px; /* Reduced font size for smaller cards */
389 }
390 .file-card-image img {
391 max-width: 80px; /* Reduced max width */
392 max-height: 80px; /* Reduced max height */
393 object-fit: cover;
394 }
395 .file-card-icon {
396 font-size: 24px; /* Reduced icon size */
397 margin-bottom: 5px;
398 }
399 .file-card-details {
400 margin-bottom: 5px;
401 font-weight: bold;
402 }
403 .file-card-url a {
404 color: #007bff;
405 text-decoration: none;
406 font-size: 12px; /* Reduced font size */
407 }
408 .file-card-url a:hover {
409 text-decoration: underline;
410 }
411 </style>
412 <td>
413 <div class="file-cards-container">
414 <?php
415 $upload_values = $value;
416 if ( ! empty( $upload_values ) && is_array( $upload_values ) ) {
417 foreach ( $upload_values as $file_url ) {
418 $file_url = urldecode( Helper::get_string_value( $file_url ) );
419
420 if ( ! empty( $file_url ) ) {
421 if ( ! file_exists( Helper::convert_fileurl_to_filepath( $file_url ) ) ) {
422 continue;
423 }
424
425 $file_type = pathinfo( $file_url, PATHINFO_EXTENSION );
426 $is_image = in_array( $file_type, [ 'gif', 'png', 'bmp', 'jpg', 'jpeg', 'svg' ], true );
427 ?>
428 <div class="file-card" data-fileurl-hash="<?php echo esc_attr( md5( $file_url ) ); ?>">
429 <?php if ( $is_image ) { ?>
430 <div class="file-card-image">
431 <a target="_blank" href="<?php echo esc_attr( $file_url ); ?>">
432 <img src="<?php echo esc_attr( $file_url ); ?>" alt="<?php esc_attr_e( 'Image', 'sureforms' ); ?>" />
433 </a>
434 </div>
435 <?php } else { ?>
436 <div class="file-card-icon">
437 <?php // Display a file icon for non-image files. ?>
438 <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>
439 </div>
440 <div class="file-card-details">
441 <span><?php echo esc_html( strtoupper( $file_type ) ); ?></span>
442 </div>
443 <?php } ?>
444 <div class="file-card-url">
445 <a target="_blank" href="<?php echo esc_attr( $file_url ); ?>"><?php echo esc_html__( 'Open', 'sureforms' ); ?></a>
446 </div>
447 </div>
448 <?php
449 }
450 }
451 }
452 ?>
453 </div>
454 </td>
455 <?php } elseif ( false !== strpos( $field_name, 'srfm-url' ) ) { ?>
456 <td><a target="_blank" href="<?php echo esc_url( $value ); ?>"><?php echo esc_url( $value ); ?></a></td>
457 <?php } else { ?>
458 <td><?php echo false !== strpos( $value, PHP_EOL ) ? wp_kses_post( wpautop( $value ) ) : wp_kses_post( $value ); ?></td>
459 <?php } ?>
460 </tr>
461 <?php } ?>
462 </tbody>
463 </table>
464 </div>
465 </div>
466 <?php
467 }
468 /**
469 * Render the entry logs for a specific entry.
470 *
471 * @param array<mixed> $entry_logs Entry logs stored in the database.
472 * @since 0.0.13
473 * @return void
474 */
475 private function render_entry_logs( $entry_logs ) {
476 ob_start();
477 ?>
478 <div id="sureform_entry_meta" class="postbox srfm-entry-logs">
479 <div class="postbox-header">
480 <!-- Removed "hndle ui-sortable-handle" class from h2 to remove the draggable stylings. -->
481 <h2><?php esc_html_e( 'Entry Logs', 'sureforms' ); ?></h2>
482 </div>
483 <div class="inside">
484 <table class="striped entry-logs-table">
485 <tbody>
486 <?php if ( ! empty( $entry_logs ) ) { ?>
487 <?php foreach ( $entry_logs as $log ) { ?>
488 <tr>
489 <td class="entry-log-container">
490 <div class="entry-log">
491 <h4 class="entry-log-title">
492 <?php echo esc_html( $log['title'] ); ?>
493 <?php echo esc_html( gmdate( '\a\t Y-m-d H:i:s', $log['timestamp'] ) ); ?>
494 </h4>
495 <div class="entry-log-messages">
496 <?php foreach ( $log['messages'] as $message ) { ?>
497 <p><?php echo wp_kses_post( $message ); ?></p>
498 <?php } ?>
499 </div>
500 </div>
501 </td>
502 </tr>
503 <?php } ?>
504 <?php } else { ?>
505 <p class="no-logs-found"><?php esc_html_e( 'No logs found for this entry.', 'sureforms' ); ?></p>
506 <?php } ?>
507 </tbody>
508 </table>
509 </div>
510 </div>
511 <?php
512 $content = ob_get_clean();
513 echo apply_filters( 'srfm_entry_logs_markup', $content, $entry_logs ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
514 }
515 }
516