PluginProbe
Happyforms – Form Builder for WordPress: Drag & Drop Contact Forms, Surveys, Payments & Multipurpose Forms / trunk
Happyforms – Form Builder for WordPress: Drag & Drop Contact Forms, Surveys, Payments & Multipurpose Forms vtrunk
1.26.15 trunk 1.0 1.10.0 1.11.0 1.11.1 1.12.0 1.12.1 1.12.10 1.12.11 1.12.12 1.12.2 1.12.3 1.12.4 1.12.5 1.12.6 1.12.7 1.12.8 1.12.9 1.13.0 1.13.1 1.13.10 1.13.11 1.13.12 1.13.2 All 194 releases
happyforms / core / classes / class-form-admin.php

class-form-admin.php in Happyforms – Form Builder for WordPress: Drag & Drop Contact Forms, Surveys, Payments & Multipurpose Forms trunk, at core/classes/class-form-admin.php

776 lines 19.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class HappyForms_Form_Admin {
4
5 /**
6 * The singleton instance.
7 *
8 * @since 1.0
9 *
10 * @var HappyForms_Form_Admin
11 */
12 private static $instance;
13
14 private $added_to_links = array();
15
16 /**
17 * The singleton constructor.
18 *
19 * @since 1.0
20 *
21 * @return HappyForms_Form_Admin
22 */
23 public static function instance() {
24 if ( is_null( self::$instance ) ) {
25 self::$instance = new self();
26 }
27
28 self::$instance->hook();
29
30 return self::$instance;
31 }
32
33 /**
34 * Register hooks.
35 *
36 * @since 1.0
37 *
38 * @return void
39 */
40 public function hook() {
41 $post_type = happyforms_get_form_controller()->post_type;
42
43 add_action( 'admin_head', array( $this, 'admin_head' ) );
44 add_filter( 'admin_url', array( $this, 'admin_url' ), 10, 2 );
45 add_filter( "views_edit-{$post_type}", array( $this, 'table_view_links' ) );
46 add_filter( 'get_edit_post_link', array( $this, 'get_edit_post_link' ), 10, 3 );
47 add_filter( 'post_updated_messages', array( $this, 'post_updated_messages' ) );
48 add_filter( "bulk_actions-edit-{$post_type}", array( $this, 'bulk_actions' ) );
49 add_filter( 'bulk_post_updated_messages', array( $this, 'bulk_post_updated_messages' ), 10, 2 );
50 add_action( 'load-edit.php', array( $this, 'define_screen_settings' ) );
51 add_filter( 'pre_months_dropdown_query', array( $this, 'pre_months_dropdown_query' ), 10, 2 );
52 add_filter( "manage_{$post_type}_posts_columns", array( $this, 'column_headers' ), PHP_INT_MAX );
53 add_filter( "manage_edit-{$post_type}_sortable_columns", array( $this, 'sortable_columns' ) );
54 add_action( "manage_{$post_type}_posts_custom_column", array( $this, 'column_content' ), 10, 2 );
55 add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ) );
56 add_filter( 'post_row_actions', array( $this, 'row_actions' ), 10, 2 );
57 add_action( 'load-edit.php', array( $this, 'duplicate_form_redirect' ) );
58 add_filter( 'admin_footer_text', 'happyforms_admin_footer' );
59 add_action( 'load-edit.php', array( $this, 'change_bulk_draft_post_status' ) );
60 add_action( 'transition_post_status', array( $this, 'change_draft_post_status' ), 10, 3 );
61 add_action( 'load-edit.php', array( $this, 'get_added_to_links' ) );
62
63 }
64
65 /**
66 * Action: output custom styles for the All Forms screen.
67 *
68 * @since 1.0
69 *
70 * @hooked action admin_head
71 *
72 * @return void
73 */
74 public function admin_head() {
75 global $pagenow;
76 $post_type = happyforms_get_form_controller()->post_type;
77
78 if ( 'edit.php' === $pagenow && $post_type === get_post_type() ) : ?>
79 <style>
80 .alignleft.actions { height: 32px; }
81 fieldset.view-mode { display: block; }
82 </style>
83 <?php endif;
84 }
85
86 /**
87 * Filter: filter the Add New link url
88 *
89 * @since 1.5
90 *
91 * @hooked filter admin_url
92 *
93 * @param string $url The current url
94 * @param string $path The current path
95 *
96 * @return array
97 */
98 public function admin_url( $url, $path ) {
99 $post_type = happyforms_get_form_controller()->post_type;
100 $new_form_url = 'post-new.php?post_type=' . $post_type;
101
102 if ( $new_form_url === $path ) {
103 $url = happyforms_get_form_edit_link( 0 );
104 }
105
106 return $url;
107 }
108
109 /**
110 * Filter: filter the row actions links
111 * below entries in the All Forms admin table.
112 *
113 * @since 1.0
114 *
115 * @hooked filter views_edit-happyform
116 *
117 * @param array $views The original array of action links.
118 *
119 * @return array
120 */
121 public function table_view_links( $views ) {
122 unset( $views['publish'] );
123
124 return $views;
125 }
126
127 /**
128 * Filter: return a form post object edit url.
129 *
130 * @since 1.0
131 *
132 * @hooked filter get_edit_post_link
133 *
134 * @param string $link The original url.
135 * @param int|string $post_id The ID of the form post object.
136 * @param string $context The context this function is being called in.
137 *
138 * @return string
139 */
140 public function get_edit_post_link( $link, $post_id, $context ) {
141 return happyforms_get_form_edit_link( $post_id, '', $context );
142 }
143
144 /**
145 * Filter: tweak the text of the form post actions admin notices.
146 *
147 * @since 1.0
148 *
149 * @hooked filter post_updated_messages
150 *
151 * @param array $messages The messages configuration.
152 *
153 * @return array
154 */
155 public function post_updated_messages( $messages ) {
156 $post_type = happyforms_get_form_controller()->post_type;
157 $permalink = get_permalink();
158 $preview_url = get_preview_post_link();
159 $view_form_link_html = sprintf(
160 ' <a href="%1$s">%2$s</a>',
161 esc_url( $permalink ),
162 __( 'View form' )
163 );
164 $preview_post_link_html = sprintf(
165 ' <a target="_blank" href="%1$s">%2$s</a>',
166 esc_url( $preview_url ),
167 __( 'Preview form' )
168 );
169
170 $messages[$post_type] = array(
171 '',
172 __( 'Form updated.' ) . $view_form_link_html,
173 __( 'Custom field updated.' ),
174 __( 'Custom field deleted.' ),
175 __( 'Form updated.' ),
176 isset($_GET['revision']) ? sprintf( __( 'Form restored to revision from %s.' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
177 __( 'Form published.' ) . $view_form_link_html,
178 __( 'Form saved.' ),
179 __( 'Form submitted.' ),
180 __( 'Form scheduled.' ),
181 __( 'Form draft updated.' ) . $preview_post_link_html,
182 );
183
184 return $messages;
185 }
186
187 /**
188 * Filter: tweak the text of the form post
189 * bulk actions admin notices.
190 *
191 * @since 1.0
192 *
193 * @hooked filter bulk_post_updated_messages
194 *
195 * @param array $messages The messages configuration.
196 * @param int $count The amount of posts for each bulk action.
197 *
198 * @return array
199 */
200 public function bulk_post_updated_messages( $messages, $count ) {
201 $post_type = happyforms_get_form_controller()->post_type;
202
203 $messages[$post_type] = array(
204 'updated' => _n( '%s form updated.', '%s forms updated.', $count['updated'] ),
205 'locked' => _n( '%s form not updated, somebody is editing it.', '%s forms not updated, somebody is editing them.', $count['locked'] ),
206 'deleted' => _n( '%s form permanently deleted.', '%s forms permanently deleted.', $count['deleted'] ),
207 'trashed' => _n( '%s form moved to the Trash.', '%s forms moved to the Trash.', $count['trashed'] ),
208 'untrashed' => _n( '%s form restored from the Trash.', '%s forms restored from the Trash.', $count['untrashed'] ),
209 );
210
211 return $messages;
212 }
213
214 public function bulk_actions( $actions ) {
215 unset( $actions['edit'] );
216
217 return $actions;
218 }
219
220 /**
221 * Action: ensure the current screen object is initialized.
222 *
223 * @since 1.0
224 *
225 * @hooked action load-edit.php
226 *
227 * @return void
228 */
229 public function define_screen_settings() {
230 $screen = get_current_screen();
231 }
232
233 /**
234 *
235 * Filters the months list in the "All dates"
236 * filter dropdown.
237 *
238 */
239 public function pre_months_dropdown_query( $months, $post_type ) {
240 if ( $post_type !== happyforms_get_form_controller()->post_type ) {
241 return $months;
242 }
243
244 global $wpdb, $wp_locale;
245
246 $extra_checks = "AND post_status != 'auto-draft'";
247
248 if ( ! isset( $_GET['post_status'] ) ) {
249 $extra_checks .= " AND post_status != 'trash' AND post_status != 'archive'";
250 } elseif ( $_GET['post_status'] !== 'all' ) {
251 $extra_checks = $wpdb->prepare( ' AND post_status = %s', $_GET['post_status'] );
252 }
253
254 $query = $wpdb->prepare("
255 SELECT DISTINCT YEAR( post_modified ) AS year, MONTH( post_modified ) AS month
256 FROM $wpdb->posts
257 WHERE post_type = %s
258 $extra_checks
259 ORDER BY post_modified DESC",
260 $post_type
261 );
262
263 $months = $wpdb->get_results( $query );
264
265 return $months;
266 }
267
268 /**
269 * Filter: filter the column headers for the
270 * All Forms admin screen table.
271 *
272 * @since 1.0
273 *
274 * @hooked filter manage_happyform_posts_columns
275 *
276 * @param array $columns The original table headers.
277 *
278 * @return array The filtered table headers.
279 */
280 public function column_headers( $columns ) {
281 $date_column = $columns['date'];
282 $columns = array(
283 'cb' => $columns['cb'],
284 'title' => $columns['title'],
285 'author' => __( 'Author', 'happyforms' ),
286 'added_to' => __( 'Added to', 'happyforms' ),
287 'shortcode' => __( 'Shortcode', 'happyforms' ),
288 'modified' => __( 'Date', 'happyforms' )
289 );
290 /**
291 * Filter the column headers of forms admin table.
292 *
293 * @since 1.4.5
294 *
295 * @param array $columns Current column headers.
296 *
297 * @return array
298 */
299 $columns = apply_filters( 'happyforms_manage_form_column_headers', $columns );
300
301 return $columns;
302 }
303
304 /**
305 *
306 * Make modified date columnn sortable
307 *
308 */
309 public function sortable_columns( $columns ) {
310 $columns['modified'] = array( 'modified', true );
311
312 return $columns;
313 }
314
315 /**
316 * Filter: output the columns content for the
317 * All Forms admin screen table.
318 *
319 * @since 1.0
320 *
321 * @hooked filter manage_happyform_posts_custom_column
322 *
323 * @param array $column The current column header.
324 * @param int|string $id The current form post object ID.
325 *
326 * @return void
327 */
328 public function column_content( $column, $id ) {
329 switch ( $column ) {
330 case 'shortcode':
331 $shortcode = happyforms_get_shortcode( $id );
332 ?>
333 <input type="text" size="15" readonly value="<?php echo esc_html( $shortcode ); ?>" />
334 <div class="happyforms-clipboard">
335 <button type="button" class="button happyforms-clipboard__button" data-value="<?php echo esc_html( $shortcode ); ?>"><?php _e( 'Copy to clipboard', 'happyforms' ); ?></button><span aria-hidden="true" class="hidden"><?php _e( 'Copied!', 'happyforms' ); ?></span>
336 </div>
337 <?php
338 break;
339 case 'modified':
340 $t_time = sprintf(
341 __( '%1$s at %2$s' ),
342 get_the_modified_time( __( 'Y/m/d' ), $id ),
343 get_the_modified_time( __( 'g:i a' ), $id )
344 );
345
346 printf( '%1$s<br>%2$s', __( 'Last modified', 'happyforms' ), $t_time );
347 break;
348 case 'added_to':
349 $html_links = '';
350
351 foreach ( $this->added_to_links as $link ) {
352 if ( $id != $link['id'] ) {
353 continue;
354 }
355
356 if ( '' !== $html_links ) {
357 $html_links .= ', ';
358 }
359
360 $html_links .= sprintf( '<a href="%s">%s</a>', $link['edit_url'], $link['label'] );
361
362 if ( 'post' === $link['type'] && 'draft' === $link['status'] ) {
363 $html_links .= ' — Draft';
364 }
365 }
366
367 if ( empty( $html_links ) ) {
368 $html_links = '';
369 }
370
371 echo $html_links;
372 break;
373 }
374 }
375
376 /**
377 *
378 * Use modified date for date filtering
379 *
380 */
381 public function pre_get_posts( $query ) {
382 if ( ! is_admin()
383 || ! $query->is_main_query()
384 || $query->get( 'post_type' ) !== happyforms_get_form_controller()->post_type ) {
385
386 return;
387 }
388
389 $orderby = $query->get( 'orderby' );
390
391 if ( empty( $orderby ) ) {
392 $query->set( 'orderby', 'modified' );
393 $query->set( 'order', 'desc' );
394 }
395
396 $m = $query->get( 'm' );
397
398 if ( empty( $m ) ) {
399 return;
400 }
401
402 $query->set( 'm', '' );
403
404 $year = substr( $m, 0, 4 );
405 $month = substr( $m, 4, 2 );
406
407 $query->set( 'date_query', array(
408 array(
409 'column' => 'post_modified',
410 'year' => $year,
411 'month' => $month,
412 ),
413 ) );
414 }
415
416 /**
417 * Filter: filter the row actions contents for the
418 * All Form admin screen table.
419 *
420 * @since 1.0
421 *
422 * @hooked filter post_row_actions
423 *
424 * @param array $actions The original array of action contents.
425 * @param WP_Post $post The current post object.
426 *
427 * @return array The filtered array of action contents.
428 */
429 public function row_actions( $actions, $post ) {
430 $post_type = happyforms_get_form_controller()->post_type;
431
432 if ( $post->post_type === $post_type ) {
433 if ( ! isset( $actions['inline hide-if-no-js'] ) ) {
434 return $actions;
435 }
436
437 $actions = array();
438 $link_template = '<a href="%s">%s</a>';
439 $duplicate_url = add_query_arg(
440 array(
441 'happyforms_duplicate_nonce' => wp_create_nonce( 'duplicate' ),
442 'post_type' => $post_type,
443 'form_id' => $post->ID,
444 ),
445 admin_url( 'edit.php' )
446 );
447
448 $links = array(
449 'edit' => array(
450 __( 'Edit', 'happyforms' ),
451 get_edit_post_link( $post->ID, 'build' )
452 ),
453 'duplicate' => array(
454 __( 'Duplicate', 'happyforms' ),
455 $duplicate_url,
456 ),
457 'trash' => array(
458 __( 'Trash', 'happyforms' ),
459 get_delete_post_link( $post->ID, '' )
460 ),
461 );
462
463 foreach( $links as $key => $values ) {
464 $actions[$key] = sprintf( $link_template, $values[1], $values[0] );
465 }
466 }
467
468 return $actions;
469 }
470
471 /**
472 * Action: handle the redirect following a form
473 * duplicate action.
474 *
475 * @since 1.0
476 *
477 * @hooked action load-edit.php
478 *
479 * @return void
480 */
481 public function duplicate_form_redirect() {
482 if ( ! isset( $_GET['happyforms_duplicate_nonce'] )
483 || ! wp_verify_nonce( $_GET['happyforms_duplicate_nonce'], 'duplicate' )
484 || ! isset( $_GET['form_id'] ) ) {
485 return;
486 }
487
488 $form = get_post( $_GET['form_id'] );
489
490 if ( is_a( $form, 'WP_Post' ) ) {
491 $controller = happyforms_get_form_controller();
492 $new_form_id = $controller->duplicate( $form );
493
494 if ( ! is_wp_error( $new_form_id ) ) {
495 $redirect = add_query_arg(
496 array( 'post_type' => $controller->post_type ),
497 admin_url( 'edit.php' )
498 );
499
500 $notice = sprintf(
501 '%s <a href="%s">%s</a>',
502 __( '1 form duplicated.', 'happyforms' ),
503 get_delete_post_link( $new_form_id, '', true ),
504 __( 'Undo', 'happyforms' )
505 );
506
507 $admin_notices = happyforms_get_admin_notices();
508 $admin_notices->register(
509 'happyforms_form_duplicated',
510 $notice,
511 array(
512 'type' => 'success',
513 'dismissible' => true,
514 'screen' => array( 'edit-happyform' ),
515 'one-time' => true,
516 )
517 );
518
519 wp_safe_redirect( $redirect );
520 exit();
521 }
522 }
523 }
524
525 /**
526 * Action: change bulk post from draft to publish.
527 *
528 * @since 1.0
529 *
530 * @hooked action load-edit.php
531 *
532 * @return void
533 */
534 public function change_bulk_draft_post_status() {
535 $post_type = happyforms_get_form_controller()->post_type;
536
537 $args = array(
538 'post_type' => $post_type,
539 'post_status' => 'draft',
540 'posts_per_page' => -1,
541 'fields' => 'ids'
542 );
543
544 $draft_forms = get_posts( $args );
545
546 foreach( $draft_forms as $form_id ) {
547 $query = array(
548 'ID' => $form_id,
549 'post_status' => 'publish',
550 );
551 wp_update_post( $query, true );
552 }
553 }
554
555 /**
556 * Action: change post from draft to publish.
557 *
558 * @since 1.24.1
559 *
560 * @hooked action transition_post_status
561 *
562 * @return void
563 */
564 public function change_draft_post_status( $new, $old, $post ) {
565 $post_type = happyforms_get_form_controller()->post_type;
566
567 if ( $post_type !== $post->post_type ) {
568 return;
569 }
570
571 if ( $new === $old ) {
572 return;
573 }
574
575 if ( 'draft' !== $new ) {
576 return;
577 }
578
579 wp_update_post( array( 'ID' => $post->ID, 'post_status' => 'publish' ) );
580 }
581
582 public function get_added_to_links() {
583 remove_filter( 'get_edit_post_link', array( $this, 'get_edit_post_link' ), 10 );
584
585 global $wpdb;
586
587 $regex_block = '/wp:thethemefoundry\/happyforms {"id":"([0-9]*)"} \/-->/';
588 $regex_shortcode = '/\[form id="([0-9]*)"\s?\]/';
589 $search_string_block = '%wp:thethemefoundry/happyforms%';
590 $search_string_shortcode = '%[form id="%';
591
592 $query = $wpdb->prepare("
593 SELECT ID, post_title, post_content, post_status FROM $wpdb->posts WHERE 1=1
594 AND ( ( post_content LIKE %s ) OR ( post_content LIKE %s ) )
595 AND post_type IN ( 'post', 'page', 'wp_block' )
596 AND post_status IN ( 'publish', 'future', 'draft', 'pending', 'private' )
597 ORDER BY post_date DESC",
598 $search_string_block,
599 $search_string_shortcode
600 );
601
602 $posts = $wpdb->get_results( $query );
603
604 if ( ! empty( $posts ) ) {
605 foreach( $posts as $post ) {
606 $label = '' == $post->post_title ? 'Untitled' : $post->post_title;
607
608 $link_data = array(
609 'content' => $post->post_content,
610 'label' => $label,
611 'edit_url' => get_edit_post_link( $post->ID ),
612 'type' => 'post',
613 'post_id' => $post->ID,
614 'status' => $post->post_status,
615 );
616
617 $this->create_added_to_link( $link_data, $regex_block );
618 $this->create_added_to_link( $link_data, $regex_shortcode );
619 }
620 }
621
622 // check if added to widget areas
623 global $wp_registered_sidebars;
624 $widget_areas = wp_get_sidebars_widgets();
625 $url_admin_widget_areas = get_admin_url( null, 'widgets.php' );
626
627 foreach( $widget_areas as $widget_area_id => $widget_area ) {
628 if ( 'wp_inactive_widgets' === $widget_area_id ) {
629 continue;
630 }
631
632 if ( ! isset( $wp_registered_sidebars[ $widget_area_id ] ) ) {
633 continue;
634 }
635
636 $widget_happyforms = get_option( 'widget_happyforms_widget', array() );
637 $widget_block = get_option( 'widget_block', array() );
638
639 foreach ( $widget_area as $widget_id ) {
640 $widget_area_name = $wp_registered_sidebars[ $widget_area_id ]['name'];
641 $widget_name = substr( $widget_id, 0, -2 );
642 $widget_index = substr( $widget_id, -1 );
643
644 if ( 'block' === $widget_name ) {
645 if ( ! isset( $widget_block[ $widget_index ] ) ) {
646 continue;
647 }
648
649 $link_data = array(
650 'content' => $widget_block[ $widget_index ]['content'],
651 'label' => $widget_area_name,
652 'edit_url' => $url_admin_widget_areas,
653 'type' => 'widget',
654 );
655
656 $this->create_added_to_link( $link_data, $regex_block );
657 $this->create_added_to_link( $link_data, $regex_shortcode );
658
659 } else if ( 'happyforms_widget' === $widget_name ) {
660 if ( ! isset( $widget_happyforms[ $widget_index ] ) ) {
661 continue;
662 }
663
664 $hf_widget_data = $widget_happyforms[ $widget_index ];
665 $form_id = $hf_widget_data['form_id'];
666 $link_added = $this->added_to_link_exists( $form_id, $widget_area_name, 'widget' );
667
668 if ( ! $link_added ) {
669 $added_to_link = array(
670 'id' => $form_id,
671 'label' => $widget_area_name,
672 'edit_url' => $url_admin_widget_areas,
673 'type' => 'widget',
674 );
675
676 $this->added_to_links[] = $added_to_link;
677 }
678 }
679 }
680 }
681
682 // check if added to templates
683 if ( current_theme_supports( 'block-templates' ) ) {
684 $templates = get_block_templates( array(), 'wp_template' );
685 $template_parts = get_block_templates( array(), 'wp_template_part' );
686
687 $theme_templates = array_merge( $templates, $template_parts );
688
689 foreach ( $theme_templates as $template ) {
690 $edit_url = add_query_arg(
691 array(
692 'postType' => $template->type,
693 'postId' => $template->id,
694 ),
695 admin_url( 'site-editor.php' )
696 );
697
698 $link_data = array(
699 'content' => $template->content,
700 'label' => $template->title,
701 'edit_url' => $edit_url,
702 'type' => $template->type,
703 );
704
705 $this->create_added_to_link( $link_data, $regex_block );
706 $this->create_added_to_link( $link_data, $regex_shortcode );
707 }
708 }
709
710 add_filter( 'get_edit_post_link', array( $this, 'get_edit_post_link' ), 10, 3 );
711 }
712
713 public function create_added_to_link( $link_data, $regex ) {
714 $has_matches = preg_match_all( $regex, $link_data['content'], $matches );
715
716 if ( empty( $has_matches ) ) {
717 return;
718 }
719
720 foreach ( $matches[1] as $form_id ) {
721 $label = $link_data['label'];
722 $type = $link_data['type'];
723 $link_added = false;
724
725 if ( 'post' === $type ) {
726 $link_added = $this->added_to_link_exists( $form_id, $label, $type, $link_data['post_id'] );
727 } else {
728 $link_added = $this->added_to_link_exists( $form_id, $label, $type );
729 }
730
731 if ( $link_added ) {
732 continue;
733 }
734
735 $added_to_link = array(
736 'id' => $form_id,
737 'label' => $label,
738 'edit_url' => $link_data['edit_url'],
739 'type' => $type,
740 );
741
742 if ( 'post' === $type ) {
743 $added_to_link['post_id'] = $link_data['post_id'];
744 $added_to_link['status'] = $link_data['status'];
745 }
746
747 $this->added_to_links[] = $added_to_link;
748 }
749 }
750
751 public function added_to_link_exists( $form_id, $label, $type, $post_id = 0 ) {
752 $exists = false;
753
754 foreach ( $this->added_to_links as $link ) {
755 if ( 'post' === $type ) {
756 $exists = ( $type === $link['type'] && $form_id === $link['id'] &&
757 $label === $link['label'] && $post_id === $link['post_id'] );
758 } else {
759 $exists = ( $type === $link['type'] && $form_id === $link['id'] && $label === $link['label'] );
760 }
761
762 if ( $exists ) {
763 break;
764 }
765 }
766
767 return $exists;
768 }
769
770 }
771
772 /**
773 * Initialize the HappyForms_Form_Admin class immediately.
774 */
775 HappyForms_Form_Admin::instance();
776