PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.32.1
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.32.1
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / controllers / FrmDashboardController.php

FrmDashboardController.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.32.1, at classes/controllers/FrmDashboardController.php

566 lines 16.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 class FrmDashboardController {
7
8 /**
9 * Handle name used for registering controller scripts and style.
10 */
11 const PAGE_SLUG = 'formidable-dashboard';
12
13 /**
14 * Option name used to store the dashboard options into db options table.
15 */
16 const OPTION_META_NAME = 'frm-dashboard-options';
17
18 /**
19 * Register all of the hooks related to the welcome screen functionality
20 *
21 * @return void
22 */
23 public static function load_admin_hooks() {
24 add_action( 'admin_menu', self::class . '::menu', 9 );
25 }
26
27 /**
28 * Register Dashboard page tp Formidable admin menu.
29 *
30 * @return void
31 */
32 public static function menu() {
33 add_submenu_page( 'formidable', 'Formidable | ' . __( 'Dashboard', 'formidable' ), esc_html__( 'Dashboard', 'formidable' ) . wp_kses_post( FrmInboxController::get_notice_count() ), 'frm_view_forms', 'formidable-dashboard', 'FrmDashboardController::route' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
34 }
35
36 /**
37 * Triggered from FrmAppController::load_page() with admin_init
38 *
39 * @since 6.8
40 *
41 * @return void
42 */
43 public static function load_page() {
44 self::remove_admin_notices_on_dashboard();
45 self::load_assets();
46
47 $unread_count = FrmEntriesHelper::get_visible_unread_inbox_count();
48
49 add_filter( 'manage_' . sanitize_title( FrmAppHelper::get_menu_name() ) . ( $unread_count ? '-' . $unread_count : '' ) . '_page_formidable-dashboard_columns', 'FrmDashboardController::entries_columns' ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
50 add_filter( 'frm_show_footer_links', '__return_false' );
51 add_filter( 'screen_options_show_screen', '__return_false' );
52 }
53
54 /**
55 * Register and enqueue dashboard assets.
56 *
57 * @since 6.8
58 *
59 * @return void
60 */
61 public static function load_assets() {
62 self::register_assets();
63 self::enqueue_assets();
64 }
65
66 /**
67 * Gets dashboard helper instance.
68 *
69 * @since 6.17
70 *
71 * @return FrmDashboardHelper
72 */
73 public static function get_dashboard_helper() {
74 $total_payments = self::view_args_payments();
75 $counters_value = array(
76 'forms' => FrmForm::get_forms_count(),
77 'entries' => FrmEntry::get_entries_count(),
78 );
79
80 return new FrmDashboardHelper(
81 array(
82 'counters' => array(
83 'counters' => self::view_args_counters( FrmForm::get_latest_form(), $counters_value ),
84 ),
85 'license' => array(),
86 'get_free_templates' => array(),
87 'inbox' => self::view_args_inbox(),
88 'entries' => array(
89 'widget-heading' => __( 'Latest Entries', 'formidable' ),
90 'cta' => array(
91 'label' => __( 'View All Entries', 'formidable' ),
92 'link' => admin_url( 'admin.php?page=formidable-entries' ),
93 ),
94 'show-placeholder' => 0 >= (int) $counters_value['entries'],
95 'count' => $counters_value['entries'],
96 'placeholder' => self::view_args_entries_placeholder( $counters_value['forms'] ),
97 ),
98 'payments' => array(
99 'show-placeholder' => ! $total_payments,
100 'placeholder' => array(
101 'copy' => __( 'You don\'t have a payment form setup yet.', 'formidable' ),
102 'cta' => array(
103 'link' => admin_url( 'admin.php?page=formidable-form-templates' ),
104 'label' => esc_html__( 'Create a Payment Form', 'formidable' ),
105 ),
106 ),
107 'counters' => array(
108 array(
109 'heading' => __( 'Total Earnings', 'formidable' ),
110 'type' => 'currency',
111 'items' => $total_payments,
112 ),
113 ),
114 ),
115 'video' => array( 'id' => self::get_youtube_embed_video( $counters_value['entries'] ) ),
116 )
117 );
118 }
119
120 /**
121 * Init dashboard page.
122 *
123 * @return void
124 */
125 public static function route() {
126 $dashboard_view = self::get_dashboard_helper();
127 $should_display_videos = is_callable( 'FrmProDashboardHelper::should_display_videos' ) ? FrmProDashboardHelper::should_display_videos() : true;
128
129 require FrmAppHelper::plugin_path() . '/classes/views/dashboard/dashboard.php';
130 }
131
132 /**
133 * Init top counters widgets view args used to construct FrmDashboardHelper.
134 *
135 * @param false|object $latest_available_form If a form is available, we utilize its ID to direct the 'Create New Entry' link of the entries counter CTA when no entries exist.
136 * @param array $counters_value The counter values for "Total Forms" & "Total Entries".
137 *
138 * @return array
139 */
140 private static function view_args_counters( $latest_available_form, $counters_value ) {
141 $add_entry_cta_link = false !== $latest_available_form && isset( $latest_available_form->id ) ? admin_url( 'admin.php?page=formidable-entries&frm_action=new&form=' . $latest_available_form->id ) : ''; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
142
143 $lite_counters = array(
144 self::view_args_build_counter( __( 'Total Forms', 'formidable' ), array(), $counters_value['forms'] ),
145 self::view_args_build_counter(
146 __( 'Total Entries', 'formidable' ),
147 self::view_args_build_cta(
148 __( 'Add Entry', 'formidable' ),
149 $add_entry_cta_link,
150 self::display_counter_cta( 'entries', $counters_value['entries'], $latest_available_form )
151 ),
152 $counters_value['entries']
153 ),
154 );
155
156 $pro_counters_placeholder = array(
157 self::view_args_build_counter(
158 __( 'All Views', 'formidable' ),
159 self::view_args_build_cta(
160 __( 'Learn More', 'formidable' ),
161 admin_url( 'admin.php?page=formidable-views' )
162 )
163 ),
164 self::view_args_build_counter(
165 __( 'Installed Apps', 'formidable' ),
166 self::view_args_build_cta(
167 __( 'Learn More', 'formidable' ),
168 admin_url( 'admin.php?page=formidable-applications' )
169 )
170 ),
171 );
172
173 if ( class_exists( 'FrmProDashboardController' ) ) {
174 $pro_counters = FrmProDashboardController::get_counters();
175 return array_merge( $lite_counters, $pro_counters );
176 }
177
178 return array_merge( $lite_counters, $pro_counters_placeholder );
179 }
180
181 /**
182 * Build view args for counter widget.
183 *
184 * @param string $heading
185 * @param array $cta
186 * @param int $value
187 * @param string $type
188 *
189 * @return array
190 */
191 public static function view_args_build_counter( $heading, $cta = array(), $value = 0, $type = 'default' ) {
192 $counter_args = array(
193 'heading' => $heading,
194 'counter' => $value,
195 'type' => 'default',
196 );
197
198 if ( $cta ) {
199 $counter_args['cta'] = $cta;
200 }
201
202 return $counter_args;
203 }
204
205 /**
206 * Build view args for cta.
207 *
208 * @param string $title
209 * @param string $link
210 * @param bool $display
211 *
212 * @return array
213 */
214 public static function view_args_build_cta( $title, $link = '#', $display = true ) {
215 return array(
216 'title' => $title,
217 'link' => $link,
218 'display' => $display,
219 );
220 }
221
222 /**
223 * Init total earnings widget view args to FrmDashboardHelper.
224 *
225 * @return array
226 */
227 private static function view_args_payments() {
228 $prepared_data = array();
229 $model_payments = new FrmTransLitePayment();
230 $payments = $model_payments->get_payments_stats();
231
232 foreach ( $payments['total'] as $currency => $total_payments ) {
233 if ( 0 < (int) $total_payments ) {
234 $prepared_data[] = array(
235 'counter_label' => FrmCurrencyHelper::get_currency( $currency ),
236 'counter' => (int) $total_payments,
237 );
238 }
239 }
240
241 return $prepared_data;
242 }
243
244 /**
245 * Init view args for entries placeholder.
246 *
247 * @param array $forms_count The total forms count. If there are no any forms yet, we'll have CTA pointing to creating a form.
248 *
249 * @return array
250 */
251 private static function view_args_entries_placeholder( $forms_count ) {
252 if ( ! $forms_count ) {
253 $copy = sprintf(
254 /* translators: %1$s: HTML start of a tag, %2$s: HTML close a tag */
255 __( 'See the %1$sform documentation%2$s for instructions on publishing your form', 'formidable' ),
256 '<a target="_blank" href="' . esc_url( FrmAppHelper::admin_upgrade_link( '', 'knowledgebase/publish-a-form/' ) ) . '">',
257 '</a>'
258 );
259 return array(
260 'background' => 'entries-placeholder',
261 'heading' => __( 'You Have No Entries Yet', 'formidable' ),
262 'copy' => $copy,
263 'button' => array(
264 'label' => esc_html__( 'Add New Form', 'formidable' ),
265 'link' => admin_url( 'admin.php?page=' . FrmFormTemplatesController::PAGE_SLUG ),
266 ),
267 );
268 }
269
270 $copy = sprintf(
271 /* translators: %1$s: HTML start of a tag, %2$s: HTML close a tag */
272 __( 'See the %1$sform documentation%2$s for instructions on publishing a form. Once vou have at least one entry you\'ll see it here.', 'formidable' ),
273 '<a target="_blank" href="' . esc_url( FrmAppHelper::admin_upgrade_link( '', 'knowledgebase/publish-a-form/' ) ) . '">',
274 '</a>'
275 );
276 return array(
277 'background' => 'entries-placeholder',
278 'heading' => __( 'You Have No Entries Yet', 'formidable' ),
279 'copy' => $copy,
280 'button' => null,
281 );
282 }
283
284 /**
285 * A function to handle the counters cta from the top: Total Forms, Total Entries, All Views, Installed Apps.
286 *
287 * @param string $counter_type
288 * @param int $counter_value
289 * @param false|object $latest_available_form The form object of the latest form available. If there are at least one
290 * form available we show "Add Entry" cta for entries counter.
291 *
292 * @return array
293 */
294 public static function display_counter_cta( $counter_type, $counter_value, $latest_available_form = false ) {
295 return $counter_value <= 0 && ! ( 'entries' === $counter_type && false === $latest_available_form );
296 }
297
298 /**
299 * Hide 3rd party notifications from dashboard
300 *
301 * @return void
302 */
303 public static function remove_admin_notices_on_dashboard() {
304 if ( false === self::is_dashboard_page() ) {
305 return;
306 }
307
308 global $wp_filter;
309
310 if ( isset( $wp_filter['admin_notices'] ) ) {
311 unset( $wp_filter['admin_notices'] );
312 }
313 }
314
315 /**
316 * Handle dashboard AJAX requests. Used in FrmHooksController
317 * Action name: dashboard_ajax_action.
318 *
319 * @return void
320 */
321 public static function ajax_requests() {
322 $dashboard_action = FrmAppHelper::get_post_param( 'dashboard_action', '', 'sanitize_text_field' );
323
324 switch ( $dashboard_action ) {
325
326 case 'welcome-banner-has-closed':
327 self::add_welcome_closed_banner_user_id();
328 wp_send_json_success();
329 break;
330
331 case 'save-subscribed-email':
332 $email = FrmAppHelper::get_post_param( 'email', '', 'sanitize_email' );
333 self::save_subscribed_email( $email );
334 wp_send_json_success();
335 break;
336 }
337 }
338
339 /**
340 * Handle the entries list. Called via add_filter.
341 * Hook name: manage_formidable_page_formidable-dashboard_columns.
342 *
343 * @param array $columns An associative array of column headings.
344 *
345 * @return array
346 */
347 public static function entries_columns( $columns = array() ) {
348 $columns['0_form_id'] = esc_html__( 'Form', 'formidable' );
349 $columns['0_name'] = esc_html__( 'Name', 'formidable' );
350 $columns['0_user_id'] = esc_html__( 'Author', 'formidable' );
351 $columns['0_created_at'] = esc_html__( 'Created on', 'formidable' );
352 return $columns;
353 }
354
355 /**
356 * Check if user has closed the welcome banner. The status of banner is saved in db options.
357 *
358 * @return bool
359 */
360 public static function welcome_banner_has_closed() {
361 $banner_closed_by_users = self::get_closed_welcome_banner_user_ids();
362 return $banner_closed_by_users && in_array( get_current_user_id(), $banner_closed_by_users, true );
363 }
364
365 /**
366 * Check if is dashboard page.
367 *
368 * @return bool
369 */
370 public static function is_dashboard_page() {
371 return FrmAppHelper::is_admin_page( 'formidable-dashboard' );
372 }
373
374 /**
375 * Detect if the logged user's email is subscribed. Used for inbox email subscribe.
376 *
377 * @param string $email The logged user's email.
378 *
379 * @return bool
380 */
381 public static function email_is_subscribed( $email ) {
382 return in_array( $email, self::get_subscribed_emails(), true );
383 }
384
385 /**
386 * Register controller assets.
387 *
388 * @return void
389 */
390 public static function register_assets() {
391 wp_register_script( self::PAGE_SLUG, FrmAppHelper::plugin_url() . '/js/formidable_dashboard.js', array( 'formidable_admin' ), FrmAppHelper::plugin_version(), true );
392 wp_register_style( self::PAGE_SLUG, FrmAppHelper::plugin_url() . '/css/admin/dashboard.css', array(), FrmAppHelper::plugin_version() );
393 }
394
395 /**
396 * Enqueue controller assets.
397 *
398 * @return void
399 */
400 public static function enqueue_assets() {
401 if ( ! self::is_dashboard_page() ) {
402 return;
403 }
404
405 wp_enqueue_style( 'formidable-animations' );
406 wp_enqueue_style( self::PAGE_SLUG );
407 wp_enqueue_script( self::PAGE_SLUG );
408 }
409
410 /**
411 * Init the view args for Inbox widget.
412 *
413 * @return array
414 */
415 private static function view_args_inbox() {
416 return self::inbox_prepare_messages( FrmInboxController::get_inbox_messages() );
417 }
418
419 /**
420 * Prepare inbox messages data.
421 *
422 * @param array $data
423 *
424 * @return array
425 */
426 private static function inbox_prepare_messages( $data ) {
427 foreach ( $data as $key => $messages ) {
428 if ( ! in_array( $key, array( 'unread', 'dismissed' ), true ) ) {
429 continue;
430 }
431
432 foreach ( $messages as $key_msg => $message ) {
433 $data[ $key ][ $key_msg ]['cta'] = self::inbox_clean_messages_cta( $message['cta'] );
434 }
435 }
436
437 return $data;
438 }
439
440 /**
441 * Clean messages CTA.
442 *
443 * @param string $cta
444 *
445 * @return string
446 */
447 private static function inbox_clean_messages_cta( $cta ) {
448 // Remove dismiss button
449 $pattern = '/<a[^>]*class="[^"]*frm_inbox_dismiss[^"]*"[^>]*>.*?<\/a>/is';
450 return preg_replace( $pattern, ' ', $cta );
451 }
452
453 /**
454 * Get the embed YouTube video from YouTube feed api. If there are 0 entries we show the welcome video otherwise latest video from FF YouTube channel is displayed.
455 *
456 * @param int|string $entries_count The total entries available.
457 *
458 * @return string|null The YouTube video ID.
459 */
460 private static function get_youtube_embed_video( $entries_count ) {
461 $youtube_api = new FrmYoutubeFeedApi();
462 $welcome_video = $youtube_api->get_video();
463 $featured_video = $youtube_api->get_video( 'featured' );
464
465 if ( 0 === (int) $entries_count && false === $welcome_video && false === $featured_video ) {
466 return null;
467 }
468
469 if ( 0 === (int) $entries_count && false !== $welcome_video ) {
470 return $welcome_video['video-id'] ?? null;
471 }
472
473 // We might receive the most recent video feed as the featured selection.
474 if ( isset( $featured_video[0] ) ) {
475 return $featured_video[0]['video-id'];
476 }
477
478 return $featured_video['video-id'] ?? null;
479 }
480
481 /**
482 * Save subscribed user's email to dashboard options.
483 * Used for Inbox widget - email subscribe.
484 *
485 * @param string $email The user email address.
486 *
487 * @return void
488 */
489 private static function save_subscribed_email( $email ) {
490 $subscribed_emails = self::get_subscribed_emails();
491
492 if ( in_array( $email, $subscribed_emails, true ) ) {
493 return;
494 }
495
496 $subscribed_emails[] = $email;
497 self::update_dashboard_options( $subscribed_emails, 'inbox-subscribed-emails' );
498 }
499
500 /**
501 * Get list of users' ids that have closed the welcome banner.
502 *
503 * @return array
504 */
505 private static function get_closed_welcome_banner_user_ids() {
506 return self::get_dashboard_options( 'closed-welcome-banner-user-ids' );
507 }
508
509 /**
510 * Get list of subscribed emails. The list will contain all emails subscribed via Inbox widget.
511 *
512 * @return array
513 */
514 private static function get_subscribed_emails() {
515 return self::get_dashboard_options( 'inbox-subscribed-emails' );
516 }
517
518 /**
519 * Get the dashboard options from db.
520 *
521 * @param string|null $option_name The dashboard option name. If null it will return all dashboard options.
522 *
523 * @return array
524 */
525 private static function get_dashboard_options( $option_name = null ) {
526 $options = get_option( self::OPTION_META_NAME, array() );
527
528 if ( null !== $option_name && ! isset( $options[ $option_name ] ) ) {
529 return array();
530 }
531
532 return null !== $option_name ? $options[ $option_name ] : $options;
533 }
534
535 /**
536 * Update the dashboard options to db.
537 *
538 * @param array $data
539 * @param string $option_name
540 *
541 * @return void
542 */
543 private static function update_dashboard_options( $data, $option_name ) {
544 $options = self::get_dashboard_options();
545 $options[ $option_name ] = $data;
546 update_option( self::OPTION_META_NAME, $options, false );
547 }
548
549 /**
550 * Save user id to closed banner list.
551 *
552 * @return void
553 */
554 private static function add_welcome_closed_banner_user_id() {
555 $users_list = self::get_closed_welcome_banner_user_ids();
556 $user_id = get_current_user_id();
557
558 if ( in_array( $user_id, $users_list, true ) ) {
559 return;
560 }
561
562 $users_list[] = $user_id;
563 self::update_dashboard_options( $users_list, 'closed-welcome-banner-user-ids' );
564 }
565 }
566