PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / trunk
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell vtrunk
3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 2.8.17 2.8.18 All 259 releases
wpfunnels / admin / class-wpfnl-admin.php

class-wpfnl-admin.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell trunk, at admin/class-wpfnl-admin.php

2,024 lines 67.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Admin class
5 *
6 * @package
7 */
8
9 namespace WPFunnels\Admin;
10
11 use WPFunnels\Admin\BatchProcessing\BatchProcessingController;
12 use WPFunnels\Admin\Migrations\MigrationManager;
13 use WPFunnels\Wpfnl;
14 use WPFunnels\Wpfnl_functions;
15 use MRM\Common\MrmCommon;
16
17
18 /**
19 * The admin-specific functionality of the plugin.
20 *
21 * @link https://rextheme.com
22 * @since 1.0.0
23 *
24 * @package WPFunnels
25 * @subpackage WPFunnels/Admin
26 */
27
28 /**
29 * The admin-specific functionality of the plugin.
30 *
31 * Defines the plugin name, version, and two examples hooks for how to
32 * enqueue the admin-specific stylesheet and JavaScript.
33 *
34 * @package Wpfnl
35 * @subpackage Wpfnl/admin
36 * @author RexTheme <support@rextheme.com>
37 */
38 class Wpfnl_Admin
39 {
40 /**
41 * Wpfunnels feed option key.
42 */
43 const WPFNL_FEED_OPTION_KEY = 'wpfnl_remote_info_feed_data';
44
45 /**
46 * The ID of this plugin.
47 *
48 * @since 1.0.0
49 * @access private
50 * @var string $plugin_name The ID of this plugin.
51 */
52 private $plugin_name;
53
54 /**
55 * The version of this plugin.
56 *
57 * @since 1.0.0
58 * @access private
59 * @var string $version The current version of this plugin.
60 */
61 private $version;
62
63
64 private $dependency_plugins;
65
66
67 /**
68 * Page hooks
69 *
70 * @var array
71 */
72 private $page_hooks = [
73 'toplevel_page_wpf_templates',
74 'toplevel_page_wpfunnels',
75 'wpfunnels_page_wpf_templates',
76 'wpfunnels_page_trash_funnels',
77 'wpfunnels_page_wpf_feature_comparison',
78 'wpfunnels_page_wp_funnel_settings',
79 'wpfunnels_page_wpfnl_settings',
80 'wpfunnels_page_wp_global_store',
81 'wpfunnels_page_edit_funnel',
82 'wpfunnels_page_create_funnel',
83 'wpfunnels_page_wpfnl_settings',
84 'wpfunnels_page_wpfnl_automations',
85 'wpfunnels_page_wpfnl_addons',
86 'wpfunnels_page_store_checkout',
87 'wpfunnels_page_wpfunnels_integrations',
88 'wpfunnels_page_wpf-license',
89 'wpfunnels_page_email-builder',
90 'wpfunnels_page_wp_funnels',
91 'wpfunnels_page_wpf_templates'
92 ];
93
94 /**
95 * Initialize the class and set its properties.
96 *
97 * @param string $plugin_name The name of this plugin.
98 * @param string $version The version of this plugin.
99 *
100 * @since 1.0.0
101 */
102 public function __construct($plugin_name, $version)
103 {
104 $this->plugin_name = $plugin_name;
105 $this->version = $version;
106
107 add_action('admin_enqueue_scripts', [$this, 'enqueue_styles']);
108 add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts']);
109 add_filter('plugin_action_links_' . WPFNL_BASE, [$this, 'add_funnel_action_links']);
110 add_filter('locale', array($this, 'change_local_for_funnel_canvas'));
111 if (is_admin()) {
112 add_filter('admin_body_class', [$this, 'add_wpfunnels_admin_body_class']);
113 add_filter('wp_dropdown_pages', array($this, 'show_funnel_steps_on_reading'));
114 add_filter('gettext', [$this, 'wpfnl_customizing_checkout_text'], 10, 3);
115 add_action('admin_init', [$this, 'wpfnl_add_type_meta']);
116 add_action('admin_init', array($this, 'init_actions'));
117 add_action('deactivated_plugin', [$this, 'wpfnl_deactivated_plugin']);
118 add_action('activated_plugin', [$this, 'wpfnl_activated_plugin']);
119
120 // Register Dashboard Widgets.
121 add_action('wp_dashboard_setup', [$this, 'wpfnl_register_dashboard_widgets']);
122
123 if (isset($_GET['page']) && 'edit_funnel' === $_GET['page']) {
124 wp_cache_flush();
125 }
126 }
127
128 add_action('admin_head', function () {
129 remove_submenu_page(WPFNL_MAIN_PAGE_SLUG, 'email-builder');
130 });
131
132
133 // Remove all admin notices from WPFunnels Dashboard
134 if ($this->is_current_page('wpfunnels')) {
135 remove_all_actions('admin_notices');
136 }
137
138
139 /**
140 * @todo This piece of code will be removed after releasing 3.2.0. We need to introduced this because we have changed the funnel template creation strategy.
141 *
142 */
143 add_action('admin_init', function () {
144 $current_version = get_option('wpfunnels_version');
145 $is_already_synced = get_option('_is_wpfunnels_new_templates_synced', 'no');
146 if (version_compare($current_version, '3.1.2', '>') && 'yes' != $is_already_synced) {
147 delete_option(WPFNL_TEMPLATES_OPTION_KEY . '_wc');
148 delete_option(WPFNL_TEMPLATES_OPTION_KEY . '_lms');
149 delete_transient('wpfunnels_remote_template_data_wc_' . WPFNL_VERSION);
150 delete_transient('wpfunnels_remote_template_data_lms_' . WPFNL_VERSION);
151 delete_transient('wpfunnels_remote_template_data_lead_' . WPFNL_VERSION);
152 delete_transient('wpfunnels_remote_template_data_store_checkout_' . WPFNL_VERSION);
153 update_option('_is_wpfunnels_new_templates_synced', 'yes');
154 }
155 });
156
157 add_action('admin_init', array($this, 'attach_admin_capabilities'));
158
159 add_action('wpfunnels_tracker_optin', array($this, 'wpfunnels_tracker_optin'), 10);
160 add_action('mint_before_sending_sms', array($this, 'create_mrm_contact'), 10);
161 }
162
163
164 public function init_actions()
165 {
166 $batch_processor = new BatchProcessingController();
167 new MigrationManager($batch_processor);
168
169
170 // Run stat status sync migration directly (independent of Action Scheduler).
171 $stat_sync = new \WPFunnels\Admin\Migrations\StatStatusSyncMigration();
172 $stat_sync->run();
173 }
174
175 /**
176 * Register dashboard widgets.
177 *
178 * Adds a new WPFunnels widgets to WordPress dashboard.
179 *
180 * Fired by `wp_dashboard_setup` action.
181 *
182 * @since 2.6.2
183 */
184 public function wpfnl_register_dashboard_widgets()
185 {
186 wp_add_dashboard_widget('wpfnl-dashboard-overview', esc_html__('WPFunnels Overview', 'wpfnl'), [$this, 'wpfnl_dashboard_overview_widget']);
187 global $wp_meta_boxes;
188
189 $dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
190 $ours = [
191 'wpfnl-dashboard-overview' => $dashboard['wpfnl-dashboard-overview'],
192 ];
193
194 $wp_meta_boxes['dashboard']['normal']['core'] = array_merge($ours, $dashboard);
195 }
196
197
198 /**
199 * WPFunnels dashboard widget.
200 *
201 * Displays the wpfunnels dashboard widget.
202 *
203 * @since 2.6.2
204 */
205 public function wpfnl_dashboard_overview_widget()
206 {
207 $upgrade_to_pro = __('Upgrade to Pro', 'wpfnl');
208 $install_activate = __('Install & Activate', 'wpfnl');
209 $is_mail_mint_active = WPFnl_functions::is_mail_mint_free_active();
210
211 $response = $this->get_wpfnl_feed_data();
212
213 $icons = [
214 'Total Orders' => '<svg width="16" height="17" fill="none" viewBox="0 0 16 17" xmlns="http://www.w3.org/2000/svg"><path fill="#B7A6E9" d="M12.061 8.04a4.015 4.015 0 01-3.478-6.03h-5.74l-.029-.236A2.01 2.01 0 00.82 0H.67a.67.67 0 000 1.34h.15a.67.67 0 01.665.592l.922 7.84a3.35 3.35 0 003.328 2.96h6.997a.67.67 0 000-1.341H5.734a2.01 2.01 0 01-1.89-1.34h7.987a3.35 3.35 0 003.298-2.756l.16-.884a4.01 4.01 0 01-3.228 1.63z"/><path fill="#B7A6E9" d="M10.542 5.994a1.254 1.254 0 00.901.402h.023a1.255 1.255 0 00.894-.37l2.863-2.863a.672.672 0 10-.95-.952l-2.806 2.81-.827-.887a.67.67 0 00-.98.915l.882.945zM4.69 16.082a1.34 1.34 0 100-2.68 1.34 1.34 0 000 2.68zm6.701 0a1.34 1.34 0 100-2.68 1.34 1.34 0 000 2.68z"/></svg>',
215 'Total Revenue' => '<svg width="15" height="15" fill="none" viewBox="0 0 15 15" xmlns="http://www.w3.org/2000/svg"><path fill="#B7A6E9" d="M9.75 15h-4.5C1.5 15 0 13.5 0 9.75v-4.5C0 1.5 1.5 0 5.25 0h4.5C13.5 0 15 1.5 15 5.25v4.5C15 13.5 13.5 15 9.75 15z"/><path fill="#B7A6E9" d="M5.004 9.247c0 .968.742 1.748 1.665 1.748H8.55c.803 0 1.455-.683 1.455-1.523 0-.915-.397-1.237-.99-1.447l-3.022-1.05c-.593-.21-.99-.533-.99-1.448 0-.84.652-1.522 1.455-1.522H8.34c.923 0 1.665.78 1.665 1.747"/><path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" d="M5.004 9.247c0 .968.742 1.748 1.665 1.748H8.55c.803 0 1.455-.683 1.455-1.523 0-.915-.397-1.237-.99-1.447l-3.022-1.05c-.593-.21-.99-.533-.99-1.448 0-.84.652-1.522 1.455-1.522H8.34c.923 0 1.665.78 1.665 1.747"/><path fill="#B7A6E9" d="M7.5 3v9-9z"/><path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" d="M7.5 3v9"/></svg>',
216 'Order Bump Revenue' => '<svg width="15" height="15" fill="none" viewBox="0 0 15 15" xmlns="http://www.w3.org/2000/svg"><path stroke="#B7A6E9" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.5" d="M5.376 1L3.05 3.333M9.475 1l2.327 2.333"/><path fill="#fff" stroke="#B7A6E9" stroke-width="1.5" d="M1 4.76c0-1.19.636-1.286 1.427-1.286h10c.791 0 1.428.097 1.428 1.286 0 1.382-.637 1.285-1.427 1.285H2.427C1.637 6.045 1 6.142 1 4.76z"/><path fill="#B7A6E9" d="M3.273 13.064L1.79 5.944h10.975l-.89 6.526c0 .712-1.582 1.286-2.373 1.484H5.35c-.237.237-1.483-.495-2.076-.89z"/><path stroke="#B7A6E9" stroke-linecap="round" stroke-width="1.5" d="M1.964 6.142l.906 5.553c.206 1.247.7 2.16 2.54 2.16h3.875c1.999 0 2.294-.874 2.526-2.082l1.08-5.63"/><path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" d="M8.91 9.504L7.425 8.021 5.943 9.504M7.426 8.02v3.56"/></svg>',
217 'Upsell/Downsell Revenue' => '<svg width="15" height="15" fill="none" viewBox="0 0 15 15" xmlns="http://www.w3.org/2000/svg"><path fill="#B7A6E9" d="M5.25 15h4.5C13.5 15 15 13.5 15 9.75v-4.5C15 1.5 13.5 0 9.75 0h-4.5C1.5 0 0 1.5 0 5.25v4.5C0 13.5 1.5 15 5.25 15z"/><path fill="#B7A6E9" d="M6.379 5.25h3.37v3.371"/><path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6.379 5.25h3.37v3.371M9.75 5.25l-4.5 4.5"/></svg>',
218 'Total Leads' => '<svg width="13" height="13" fill="none" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg"><path fill="#B7A6E9" d="M8.45 0h-3.9C1.3 0 0 1.3 0 4.55v3.9c0 2.457.741 3.803 2.509 4.303.143-1.69 1.879-3.023 3.991-3.023 2.113 0 3.848 1.333 3.991 3.023C12.259 12.253 13 10.907 13 8.45v-3.9C13 1.3 11.7 0 8.45 0zM6.5 7.91a2.33 2.33 0 010-4.66 2.33 2.33 0 010 4.66z"/></svg>',
219 ];
220
221
222 $pro_icon_svg = '<div class="pro-icon"><svg width="14" height="14" fill="none" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><circle cx="7" cy="7" r="7" fill="#66CB64"/><path fill="#fff" fill-rule="evenodd" d="M7.623 4.465a.69.69 0 00-1.15 0l-1.36 2.08-1.04-.59c-.52-.294-1.146.168-1.005.743l.706 2.88c.032.13.15.222.285.222h5.977a.292.292 0 00.285-.221l.706-2.88c.141-.576-.485-1.038-1.005-.743l-1.04.588-1.36-2.08zm-.493.312a.098.098 0 00-.165 0l-1.51 2.311a.296.296 0 01-.393.094l-1.28-.725a.097.097 0 00-.144.106l.652 2.659h5.515l.652-2.66a.096.096 0 00-.143-.105l-1.281.725a.296.296 0 01-.393-.094l-1.51-2.31z" clip-rule="evenodd"/><path fill="#fff" d="M4.312 10.377a.291.291 0 00-.293.29.29.29 0 00.293.288h5.472c.161 0 .293-.13.293-.289a.291.291 0 00-.293-.289H4.312z"/><circle cx="10.739" cy="4.987" r=".514" fill="#fff"/><circle cx="3.139" cy="4.987" r=".514" fill="#fff"/><circle cx="7.042" cy="3.139" r=".514" fill="#fff"/><path fill="#fff" d="M9.918 9.404h-5.65L3.241 6.22l1.952.616 1.849-2.465L8.993 6.94l1.746-.822-.821 3.287z"/></svg></div>';
223
224 ?>
225 <div class="wpfnl-dashboard-widget">
226 <div class="wpfnl-overview__header">
227 <div class="wpfnl-overview__logo">
228 <div class="wpfnl-logo-wrapper">
229 <svg width="38" height="28" viewBox="0 0 38 28" fill="none" xmlns="http://www.w3.org/2000/svg">
230 <path d="M7.01532 18H31.9847L34 11H5L7.01532 18Z" fill="#EE8134"></path>
231 <path
232 d="M11.9621 27.2975C12.0923 27.7154 12.4792 28 12.9169 28H26.0831C26.5208 28 26.9077 27.7154 27.0379 27.2975L29 21H10L11.9621 27.2975Z"
233 fill="#6E42D3"></path>
234 <path
235 d="M37.8161 0.65986C37.61 0.247888 37.2609 0 36.8867 0H1.11326C0.739128 0 0.390003 0.247888 0.183972 0.65986C-0.0220592 1.07193 -0.0573873 1.59277 0.0898627 2.04655L1.69781 7H36.3022L37.9102 2.04655C38.0574 1.59287 38.022 1.07193 37.8161 0.65986Z"
236 fill="#6E42D3"></path>
237 </svg>
238 </div>
239 </div>
240
241 <div class="wpfnl-overview__upgrade">
242 <span><?php echo !Wpfnl_functions::is_pro_license_activated() ? __('Upgrade to Pro to get premium features such as one-click upsells, A/B testing and more!', 'wpfnl') : __('Start creating high converting landing pages, sales funnels, and checkout flows in minutes!', 'wpfnl'); ?></span>
243 </div>
244
245 <?php if (!Wpfnl_functions::is_pro_license_activated()) { ?>
246 <div class="wpfnl-overview__create">
247 <a href="https://getwpfunnels.com/pricing/" target="_blank" class="button"><span aria-hidden="true"></span>
248 <?php echo esc_html($upgrade_to_pro); ?></a>
249 </div>
250 <?php
251 }?>
252
253 </div>
254
255 <!-- overview report -->
256 <div class="wpfnl-overview__report">
257 <?php foreach ($response as $report):
258 $icon_html = $icons[$report['title']] ?? '';
259 ?>
260 <div class="report-item">
261 <div class="icon"><?php echo $icon_html; ?></div>
262 <div class="text-wrapper">
263 <p class="title"><?php echo esc_html($report['title']); ?></p>
264 <p class="amount"><?php echo $report['amount']; ?></p>
265 </div>
266
267 <?php if ($report['show_pro'] && !Wpfnl_functions::is_pro_license_activated()): ?>
268 <?php echo $pro_icon_svg; ?>
269 <?php
270 endif; ?>
271
272 </div>
273 <?php
274 endforeach; ?>
275 </div>
276
277 <?php if (!Wpfnl_functions::is_mint_mrm_active()): ?>
278 <!-- install mail mint -->
279 <div
280 class="wpfnl-overview__mailmint <?php echo Wpfnl_functions::is_mint_mrm_active() ? 'is-active' : 'is-disabled'; ?>">
281 <div class="icon-wrapper">
282 <div class="icon">
283 <svg width="34" height="34" fill="none" viewBox="0 0 34 34" xmlns="http://www.w3.org/2000/svg">
284 <circle cx="17" cy="17" r="16.5" fill="#fff" stroke="#573BFF" />
285 <path fill="#573BFF"
286 d="M24.084 14.876l-.634 8.778.905-1.267.996-10.225-9.23 6.153-2.082-2.172-5.972-5.067 7.601 8.868c.272.271.634.362.996.09l7.42-5.158z" />
287 <path fill="#02C4FB"
288 d="M21.822 11.62c-3.891.814-7.24.904-8.416.814l.995 1.086c4.525-.272 6.697-.905 7.24-1.267.362-.272.271-.543.18-.634z" />
289 <path fill="#573BFF"
290 d="M20.374 13.61c-2.444.724-4.525.905-5.249.905l.724.633c2.805-.362 4.163-.905 4.434-1.176.272-.181.181-.362.09-.362z" />
291 <path fill="#573BFF"
292 d="M25.947 11.345c-.212-.033-.418.064-.596.184l-9.05 6.153-4.162-4.525-.749-.793-.79-.835c1.72.18 8.778-.09 12.67-.996 1.81-.452 1.447-1.267 1.266-1.176-8.415 1.176-15.745.452-15.745.452-.403-.034-.617.066-.815.362-.18.272-.09.634.09.905l.453.453 2.082 2.08 5.158 5.43c.271.272.633.272.995.09l8.054-5.52c-.453 4.073-.996 8.145-1.267 9.14-1.81.363-12.397.453-13.845.091-.453-.724-.996-4.253-1.358-7.963-.09-.543-.633-.905-1.176-.634 0 0-.362.177-.362.724.905 8.597 1.81 9.05 2.081 9.23.543.272 4.163.453 7.873.453s7.33-.181 7.873-.634c.18-.18.814-.723 1.9-11.401v-.091c.074-.736-.152-1.113-.58-1.18z" />
293 <path fill="url(#paint0_linear_129_34)" d="M8.474 11.538h2.135l1.687 1.79H9.984l-1.51-1.79z" />
294 <defs>
295 <linearGradient id="paint0_linear_129_34" x1="9.613" x2="10.654" y1="11.538" y2="13.37"
296 gradientUnits="userSpaceOnUse">
297 <stop stop-color="#0C0632" />
298 <stop offset="1" stop-color="#573BFF" />
299 </linearGradient>
300 </defs>
301 </svg>
302 </div>
303 <div class="text-wrapper">
304 <p class="description">
305 <?php echo $is_mail_mint_active ? __('Use email marketing automation for your funnels easily with <b>Mail Mint</b>!', 'wpfnl') : __('Use email marketing automation for your funnels easily with <b>Mail Mint</b>!', 'wpfnl'); ?>
306 </p>
307 </div>
308 </div>
309 <div class="wpfnl-overview__install-mailmint">
310 <?php if (Wpfnl_functions::is_mail_mint_free_active()): ?>
311 <a href="https://getwpfunnels.com/pricing/#mail-mint" target="_blank" class="button">
312 <?php echo $upgrade_to_pro; ?>
313 </a>
314 <?php
315 else: ?>
316 <button id="pro-modal-dropdown-btn" class="button">
317 <span class="loader" style="display:none;"></span>
318 <span class="btn-text"><?php echo $install_activate; ?></span>
319 </button>
320 <?php
321 endif; ?>
322 </div>
323
324 </div>
325 <?php
326 endif; ?>
327
328 <div class="wpfnl-overview__footer wpfnl-divider_top">
329 <ul>
330 <?php foreach ($this->get_wpfunnels_dashboard_overview_widget_footer_actions() as $action_id => $action): ?>
331 <li class="wpfnl-overview__<?php echo esc_attr($action_id); ?>"><a
332 href="<?php echo esc_attr($action['link']); ?>"
333 target="_blank"><?php echo esc_html($action['title']); ?> <span
334 class="screen-reader-text"><?php echo esc_html__('(opens in a new window)', 'wpfnl'); ?></span></a>
335 </li>
336 <?php
337 endforeach; ?>
338 </ul>
339 </div>
340
341 <script>
342 (function ($) {
343
344 const apiService = (path = "", method = "GET", data, content_type = "text/plain") => {
345 return new Promise((resolve, reject) => {
346 jQuery.ajax({
347 url: wpApiSettings.root + path,
348 type: method,
349 data: data,
350 beforeSend: function (xhr) {
351 xhr.setRequestHeader("X-WP-Nonce", wpApiSettings.nonce);
352 },
353 dataType: "json",
354 contentType: content_type,
355 success: resolve,
356 error: reject
357 });
358 });
359 };
360
361 $(document).ready(function () {
362 jQuery("#pro-modal-dropdown-btn").click((e) => {
363 e.preventDefault();
364 var btn = $('#pro-modal-dropdown-btn');
365 var loader = btn.find('.loader');
366 var btnText = btn.find('.btn-text');
367 loader.show();
368 btn.prop('disabled', true);
369 btnText.text('Processing...');
370 apiService("wpfunnels/v1/activate-plugin", 'POST', JSON.stringify({
371 basename: 'mail-mint/mail-mint.php',
372 slug: 'mail-mint',
373 }), 'application/json').then((res) => {
374 var upgradeBtn = $(
375 '<a href="https://getwpfunnels.com/pricing/#mail-mint" target="_blank" class="button" style="margin-left:0;">' +
376 'Upgrade to Pro' +
377 '</a>'
378 );
379 btn.closest('.wpfnl-overview__install-mailmint').html(upgradeBtn);
380 $('.text-wrapper .title').text('Get Mail Mint Pro');
381 $('.text-wrapper .description').html('Use email marketing automation for your funnels easily with <b>Mail Mint</b>!');
382 }).catch((e) => {
383 btn.replaceWith(btnPrevState);
384 addClickEvent();
385 })
386 });
387 });
388 })(jQuery);
389 </script>
390
391 <style>
392 .wpfnl-dashboard-widget {
393 margin-top: -11px;
394 }
395
396 .wpfnl-dashboard-widget .wpfnl-overview__mailmint {
397 display: flex;
398 align-items: center;
399 justify-content: space-between;
400 padding: 16px 20px;
401 border: 1px solid #EEEAF8;
402 margin-bottom: 15px;
403 }
404
405 .wpfnl-dashboard-widget .wpfnl-overview__mailmint.is-active .wpfnl-overview__install-mailmint button {
406 pointer-events: none;
407 cursor: not-allowed;
408 }
409
410 .wpfnl-dashboard-widget .wpfnl-overview__mailmint .icon-wrapper {
411 display: flex;
412 gap: 12px;
413 align-items: center;
414 }
415
416 .wpfnl-dashboard-widget .wpfnl-overview__mailmint .wpfnl-overview__install-mailmint .button {
417 border-radius: 7px;
418 background: #573BFF;
419 color: #FFF;
420 text-align: center;
421 font-family: Inter;
422 font-size: 12px;
423 font-style: normal;
424 font-weight: 500;
425 line-height: 2.6;
426 border: none;
427 }
428
429 .wpfnl-dashboard-widget .wpfnl-overview__mailmint .wpfnl-overview__install-mailmint .button:focus {
430 box-shadow: unset;
431 }
432
433 .wpfnl-dashboard-widget .wpfnl-overview__mailmint .wpfnl-overview__install-mailmint .loader {
434 border: 2px solid #f3f3f3;
435 border-top: 2px solid #573BFF;
436 border-radius: 50%;
437 width: 12px;
438 height: 12px;
439 animation: spin 0.8s linear infinite;
440 display: inline-block;
441 vertical-align: middle;
442 margin-right: 4px;
443 }
444
445 @keyframes spin {
446 0% {
447 transform: rotate(0deg);
448 }
449
450 100% {
451 transform: rotate(360deg);
452 }
453 }
454
455 .wpfnl-dashboard-widget .wpfnl-overview__mailmint .wpfnl-overview__install-mailmint .button:disabled {
456 cursor: not-allowed;
457 opacity: 0.7;
458 background: #573BFF !important;
459 color: #FFF !important;
460 }
461
462
463 .wpfnl-dashboard-widget .wpfnl-overview__mailmint .icon-wrapper .text-wrapper .title {
464 color: #2E3148;
465 font-size: 16px;
466 font-weight: 600;
467 line-height: 1;
468 letter-spacing: -0.32px;
469 margin: 0 0 8px;
470 }
471
472 .wpfnl-dashboard-widget .wpfnl-overview__mailmint .icon-wrapper .text-wrapper .description {
473 margin: 0;
474 line-height: 1;
475 }
476
477 .wpfnl-dashboard-widget .wpfnl-overview__report {
478 display: grid;
479 grid-template-columns: repeat(2, 1fr);
480 border: 1px solid #EEEAF8;
481 margin: 15px 0;
482 }
483
484 .wpfnl-dashboard-widget .wpfnl-overview__report .report-item {
485 display: flex;
486 gap: 15px;
487 padding: 20px;
488 position: relative;
489
490 }
491
492 .wpfnl-dashboard-widget .wpfnl-overview__report .report-item:nth-child(odd)::before {
493 content: "";
494 position: absolute;
495 right: 15%;
496 height: 36px;
497 width: 1px;
498 background: linear-gradient(180deg, rgba(238, 234, 248, 0.00) -2.78%, #EEEAF8 47.1%, rgba(238, 234, 248, 0.00) 104.17%);
499 }
500
501 .wpfnl-dashboard-widget .wpfnl-overview__report .report-item .text-wrapper p {
502 margin: 0;
503 line-height: 1;
504 }
505
506 .wpfnl-dashboard-widget .wpfnl-overview__report .report-item .text-wrapper p.title {
507 color: #2E3148;
508 font-size: 12px;
509 font-weight: 400;
510 margin-bottom: 8px;
511 }
512
513 .wpfnl-dashboard-widget .wpfnl-overview__report .report-item .text-wrapper p.amount {
514 color: #2E3148;
515 font-size: 15px;
516 font-weight: 600;
517 line-height: normal;
518 }
519
520 .wpfnl-dashboard-widget .wpfnl-overview__header {
521 display: flex;
522 align-items: center;
523 justify-content: space-between;
524 border-bottom: 1px solid #eee;
525 gap: 15px;
526 padding: 15px 15px;
527 margin: 0 -12px;
528
529 }
530
531 .wpfnl-dashboard-widget .wpfnl-overview__header .wpfnl-overview__upgrade {
532 padding: 0px 15px;
533 }
534
535 .wpfnl-dashboard-widget .wpfnl-overview__versions {
536 font-size: 0.9em;
537 line-height: 1.5;
538 }
539
540 .wpfnl-dashboard-widget .wpfnl-overview__version {
541 display: block;
542 }
543
544 .wpfnl-dashboard-widget .wpfnl-overview__create a {
545 border-radius: 7px;
546 background: #6E42D3;
547 border: 1px solid #6E42D3;
548 font-style: normal;
549 line-height: 2.28;
550 color: #FFF;
551 text-align: center;
552 font-family: Inter;
553 font-size: 14px;
554 font-weight: 500;
555 }
556
557 .wpfnl-dashboard-widget .wpfnl-overview__create a:hover {
558 background: #6E42D3;
559 color: #FFF;
560 box-shadow: unset;
561 border-color: transparent;
562 }
563
564 .wpfnl-dashboard-widget .wpfnl-overview__create a:focus {
565 background: #6E42D3;
566 color: #FFF;
567 outline: none;
568 box-shadow: unset;
569 border-color: transparent;
570 }
571
572 .wpfnl-dashboard-widget .wpfnl-overview__create .dashicons {
573 font-size: 15px;
574 line-height: 1;
575 position: relative;
576 top: 8px;
577 }
578
579 .wpfnl-dashboard-widget .wpfnl-overview__recently-edited .wpfnl-heading {
580 font-weight: 600 !important;
581 border-bottom: 1px solid #eee;
582 margin: 0 -12px !important;
583 padding: 6px 12px !important;
584 margin-bottom: 13px !important;
585 }
586
587 .wpfnl-dashboard-widget .wpfnl-overview__post {
588 margin-top: 10px;
589 font-weight: 500;
590 }
591
592 .wpfnl-dashboard-widget .wpfnl-overview__post-link {
593 display: inline-block;
594 }
595
596 .wpfnl-dashboard-widget .wpfnl-overview__post-description {
597 margin: 0 0 1.5em;
598 }
599
600 .wpfnl-dashboard-widget .wpfnl-overview__footer {
601 border-top: 1px solid #eee;
602 margin: 0 -12px;
603 padding: 6px 12px;
604 padding-top: 12px;
605 padding-bottom: 0;
606 }
607
608 .wpfnl-dashboard-widget .wpfnl-overview__footer ul {
609 display: -webkit-box;
610 display: -ms-flexbox;
611 display: flex;
612 list-style: none;
613 margin: 0;
614 padding: 0;
615 }
616
617 .wpfnl-dashboard-widget .wpfnl-overview__footer ul li {
618 padding: 0 10px;
619 margin: 0;
620 position: relative;
621 }
622
623 .wpfnl-dashboard-widget .wpfnl-overview__footer .wpfnl-overview__blog a,
624 .wpfnl-dashboard-widget .wpfnl-overview__footer .wpfnl-overview__changelog a,
625 .wpfnl-dashboard-widget .wpfnl-overview__footer .wpfnl-overview__help a {
626 color: #667085;
627 font-size: 12px;
628 font-weight: 400;
629 position: relative;
630 }
631
632 .wpfnl-dashboard-widget .wpfnl-overview__footer .wpfnl-overview__blog a:hover,
633 .wpfnl-dashboard-widget .wpfnl-overview__footer .wpfnl-overview__changelog a:hover,
634 .wpfnl-dashboard-widget .wpfnl-overview__footer .wpfnl-overview__help a:hover {
635 color: #6846CE;
636 }
637
638 .wpfnl-dashboard-widget .wpfnl-overview__footer ul li:not(:last-child)::before {
639 content: "";
640 position: absolute;
641 right: 0;
642 top: 3px;
643 height: 16px;
644 width: 1px;
645 background: linear-gradient(180deg, rgba(238, 234, 248, 0.00) -2.78%, #EEEAF8 47.1%, rgba(238, 234, 248, 0.00) 104.17%);
646 }
647
648 .wpfnl-dashboard-widget .wpfnl-overview__footer ul li:first-child {
649 padding-left: 0;
650 border: none;
651 }
652
653 .wpfnl-dashboard-widget .wpfnl-overview__footer ul li.wpfnl-overview__go-pro a {
654 color: #DF8740;
655 font-size: 12px;
656 font-weight: 400;
657 line-height: normal;
658 }
659 </style>
660 </div>
661 <?php
662 }
663
664 /**
665 * Get wpfunnels feed data.
666 *
667 * Retrieve the feed info data from remote wpfunnels server.
668 *
669 * @access public
670 *
671 * @param bool $force_update Optional. Whether to force the data update or
672 * not. Default is false.
673 *
674 * @return array Feed data.
675 * @since 2.7.16
676 */
677 public function get_wpfnl_feed_data($force_update = false)
678 {
679 return $this->get_wpfnl_info_data($force_update);
680 }
681
682 /**
683 * Get wpfunnles info data.
684 *
685 * This function retrieves post from wpfunnels remote API.
686 *
687 * @access private
688 *
689 * @param bool $force_update Optional. Whether to force the data retrieval or
690 * not. Default is false.
691 *
692 * @return array|false Info data, or false.
693 * @since 2.7.16
694 */
695 private function get_wpfnl_info_data($force_update)
696 {
697 global $wpdb;
698 $response = [
699 [
700 'title' => 'Total Orders',
701 'amount' => $wpdb->get_var($wpdb->prepare("SELECT COUNT(id) FROM {$wpdb->prefix}wpfnl_stats WHERE status = %s", 'completed')),
702 'show_pro' => false
703 ],
704 [
705 'title' => 'Total Revenue',
706 'amount' => Wpfnl_functions::is_wc_active() ? wc_price((int)$wpdb->get_var($wpdb->prepare("SELECT SUM(total_sales) FROM {$wpdb->prefix}wpfnl_stats WHERE status = %s", 'completed'))) : number_format(0, 2),
707 'show_pro' => false
708 ],
709 [
710 'title' => 'Order Bump Revenue',
711 'amount' => Wpfnl_functions::is_wc_active() ? wc_price((int)$wpdb->get_var($wpdb->prepare("SELECT SUM(orderbump_sales) FROM {$wpdb->prefix}wpfnl_stats WHERE status = %s", 'completed'))) : number_format(0, 2),
712 'show_pro' => false
713 ],
714 [
715 'title' => 'Upsell/Downsell Revenue',
716 'amount' => (Wpfnl_functions::is_pro_license_activated() && Wpfnl_functions::is_wc_active()) ? wc_price((int)$wpdb->get_var($wpdb->prepare("SELECT SUM(upsell_sales + downsell_sales) FROM {$wpdb->prefix}wpfnl_stats WHERE status = %s", 'completed'))) : number_format(0, 2),
717 'show_pro' => true
718 ],
719 [
720 'title' => 'Total Leads',
721 'amount' => $wpdb->get_var("SELECT COUNT(id) FROM {$wpdb->prefix}wpfnl_optin_entries"),
722 'show_pro' => false
723 ],
724 ];
725
726 return $response;
727 }
728
729 /**
730 * Get all post from url
731 *
732 * @param $url
733 * @param $args
734 *
735 * @return array
736 */
737 private function remote_get($url, $args = [])
738 {
739 $response = wp_remote_get($url, $args);
740
741 if (is_wp_error($response) || !is_array($response) || !isset($response['body'])) {
742 return [
743 'success' => false,
744 'message' => $response->get_error_message(),
745 'data' => $response,
746 ];
747 }
748
749 // Decode the results.
750 $results = json_decode($response['body'], true);
751
752 if (!is_array($results)) {
753 return new \WP_Error('unexpected_data_format', 'Data was not returned in the expected format.');
754 }
755
756 return [
757 'success' => true,
758 'message' => 'Data successfully retrieved',
759 'data' => json_decode(wp_remote_retrieve_body($response), true),
760 ];
761 }
762
763
764 /**
765 * Get wpfunnels dashboard overview widget footer actions.
766 *
767 * Retrieves the footer action links displayed in wpfunnels dashboard widget.
768 *
769 * @since 1.9.0
770 * @access private
771 */
772 private function get_wpfunnels_dashboard_overview_widget_footer_actions()
773 {
774 $actions = [
775 'go-pro' => [
776 'title' => esc_html__('Upgrade to Pro', 'wpfnl'),
777 'link' => 'https://getwpfunnels.com/pricing/',
778 ],
779 'blog' => [
780 'title' => esc_html__('Blogs', 'wpfnl'),
781 'link' => 'https://getwpfunnels.com/blog/',
782 ],
783 'changelog' => [
784 'title' => esc_html__('Changelogs', 'wpfnl'),
785 'link' => 'https://getwpfunnels.com/changelog/',
786 ],
787 'help' => [
788 'title' => esc_html__('Get Help', 'wpfnl'),
789 'link' => 'https://getwpfunnels.com/docs/getting-started-with-wpfunnels/',
790 ],
791
792 ];
793
794 if (Wpfnl_functions::is_pro_license_activated()) {
795 unset($actions['go-pro']);
796 }
797
798 return $actions;
799 }
800
801
802
803 /**
804 * Funnel action links
805 *
806 * @since 1.0.0
807 */
808 public function add_funnel_action_links($actions)
809 {
810 $documentation = array(
811 '<a href="https://getwpfunnels.com/docs/wpfunnels-wordpress-funnel-builder/" target="_blank" >Documentation</a>',
812 );
813 $is_pro_installed = Wpfnl_functions::is_plugin_installed('wpfunnels-pro/wpfnl-pro.php');
814 if (!defined('WPFNL_PRO_VERSION') && !$is_pro_installed) {
815 $documentation[] = '<a href="https://getwpfunnels.com/pricing/" target="_blank" style="color:#6E42D3;font-weight:bold" >Upgrade to Pro</a>';
816 }
817 $actions = array_merge($actions, $documentation);
818 return $actions;
819 }
820
821 /**
822 * Register the stylesheets for the admin area.
823 *
824 * @since 1.0.0
825 */
826 public function enqueue_styles($hook)
827 {
828
829 /**
830 * This function is provided for demonstration purposes only.
831 *
832 * An instance of this class should be passed to the run() function
833 * defined in Wpfnl_Loader as all of the hooks are defined
834 * in that particular class.
835 *
836 * The Wpfnl_Loader will then create the relationship
837 * between the defined hooks and the functions defined in this
838 * class.
839 */
840 if ('wpfunnels_page_email-builder' === $hook) {
841 wp_enqueue_style($this->plugin_name . '-email-builder', plugin_dir_url(__FILE__) . 'assets/dist/email-builder/email-builder.css', [], $this->version, 'all');
842 }
843
844 if ('wpfunnels_page_' . WPFNL_AI_FUNNEL_PAGE_SLUG === $hook) {
845 wp_enqueue_style('wpfnl-admin-app', plugin_dir_url(__FILE__) . 'assets/css/admin-app.css', [], $this->version, 'all');
846 wp_enqueue_style($this->plugin_name, plugin_dir_url(__FILE__) . 'assets/css/wpfnl-admin.css', [], $this->version, 'all');
847 }
848
849 if ($this->is_current_page('wpfunnels')) {
850 wp_enqueue_style('wpfnl-admin-app', plugin_dir_url(__FILE__) . 'assets/css/admin-app.css', [], $this->version, 'all');
851 }
852
853
854 if (in_array($hook, $this->page_hooks)) {
855 wp_enqueue_style('wp-color-picker');
856 wp_enqueue_style($this->plugin_name . '-jquery-ui', plugin_dir_url(__FILE__) . 'assets/css/jquery-ui.min.css', [], $this->version, 'all');
857
858 wp_enqueue_style($this->plugin_name, plugin_dir_url(__FILE__) . 'assets/css/wpfnl-admin.css', [], $this->version, 'all');
859
860 do_action('wpfunnels_after_styles_loaded');
861 }
862 }
863
864 /**
865 * Register the JavaScript for the admin area.
866 *
867 * @since 1.0.0
868 */
869 public function enqueue_scripts($hook)
870 {
871 /**
872 * This function is provided for demonstration purposes only.
873 *
874 * An instance of this class should be passed to the run() function
875 * defined in Wpfnl_Loader as all of the hooks are defined
876 * in that particular class.
877 *
878 * The Wpfnl_Loader will then create the relationship
879 * between the defined hooks and the functions defined in this
880 * class.
881 */
882
883
884 $screen = get_current_screen();
885
886
887 if ('dashboard' === $screen->id || 'plugins' === $screen->id) {
888 wp_enqueue_script($this->plugin_name . '-global', plugin_dir_url(__FILE__) . 'assets/js/wpfnl-global.js', ['jquery', 'jquery-ui-sortable'], $this->version, true);
889 }
890
891 if ('wpfunnels_page_email-builder' === $hook) {
892 $is_wc_installed = 'no';
893 $is_wpfunnels_installed = 'no';
894 if (is_plugin_active('woocommerce/woocommerce.php')) {
895 $is_wc_installed = 'yes';
896 }
897 if (is_plugin_active('wpfunnels/wpfunnels.php')) {
898 $is_wpfunnels_installed = 'yes';
899 }
900 $dependency = require_once WPFNL_PATH . '/admin/assets/dist/email-builder/main.min.asset.php';
901 wp_enqueue_script(
902 $this->plugin_name . '-email-builder',
903 plugin_dir_url(__FILE__) . 'assets/dist/email-builder/main.min.js',
904 $dependency['dependencies'],
905 $this->version,
906 true
907 );
908 wp_localize_script(
909 $this->plugin_name . '-email-builder',
910 'WPFEmailBuilderVars',
911 array(
912 'editor_data_source' => $this->get_editor_source(),
913 'post_types' => MrmCommon::get_all_post_types(),
914 'is_wc_installed' => $is_wc_installed,
915 'is_mint_active' => Wpfnl_functions::is_mint_mrm_active(),
916 )
917 );
918 }
919
920 // Store Checkout without WooCommerce: power the "Plugin Required" modal
921 // rendered by admin/modules/store-checkout/views/woocommerce-required.php.
922 if ('wpfunnels_page_' . WPFNL_STORE_CHECKOUT_SLUG === $hook && !Wpfnl_functions::is_wc_active()) {
923 $wc_plugin = 'woocommerce/woocommerce.php';
924 $wc_status = Wpfnl_functions::is_plugin_installed($wc_plugin) ? 'inactive' : 'not-installed';
925 $wc_label = 'not-installed' === $wc_status
926 ? __('Install WooCommerce', 'wpfnl')
927 : __('Activate WooCommerce', 'wpfnl');
928
929 wp_enqueue_script(
930 $this->plugin_name . '-store-checkout-woo',
931 plugin_dir_url(__FILE__) . 'assets/js/wpfnl-store-checkout-woo.js',
932 ['jquery', 'updates'],
933 $this->version,
934 true
935 );
936 wp_localize_script($this->plugin_name . '-store-checkout-woo', 'wpfnlStoreCheckoutWoo', array(
937 'ajaxUrl' => admin_url('admin-ajax.php'),
938 'nonce' => wp_create_nonce('wpfnl_activate_plugin_nonce'),
939 'plugin' => $wc_plugin,
940 'slug' => 'woocommerce',
941 'status' => $wc_status,
942 'buttonLabel' => $wc_label,
943 'i18n' => array(
944 'installing' => __('Installing', 'wpfnl'),
945 'activating' => __('Activating', 'wpfnl'),
946 'redirecting' => __('Redirecting', 'wpfnl'),
947 'error' => __('Something went wrong. Please install and activate WooCommerce manually.', 'wpfnl'),
948 ),
949 ));
950 }
951
952 if ('wpfunnels_page_' . WPFNL_AI_FUNNEL_PAGE_SLUG === $hook) {
953 wp_enqueue_script('wpfnl-ai-funnel-app', plugin_dir_url(__FILE__) . 'assets/dist/js/ai-funnel-app.min.js', [], $this->version, true);
954 Wpfnl_functions::enqueue_bundle_style( 'ai-funnel-app', 'wpfnl-ai-funnel-app-bundle' );
955 $_ai_pro_active = Wpfnl_functions::is_wpfnl_pro_activated();
956 $_ai_enabled = \WPFunnels\AI\Settings\AISettings::isEnabled();
957 wp_localize_script('wpfnl-ai-funnel-app', 'WPFNAIFunnel', array(
958 'adminUrl' => esc_url_raw(admin_url('admin.php')),
959 'pageUrl' => esc_url_raw(add_query_arg(array(
960 'page' => WPFNL_AI_FUNNEL_PAGE_SLUG,
961 ), admin_url('admin.php'))),
962 'funnelsUrl' => esc_url_raw(add_query_arg(array(
963 'page' => WPFNL_FUNNEL_PAGE_SLUG,
964 ), admin_url('admin.php'))),
965 // The combined "AI Settings" tab was split into "MCP for AI Agents"
966 // and "AI Assistant" — deep-link to the AI Assistant tab, its direct
967 // feature successor.
968 'settingsUrl' => esc_url_raw( add_query_arg( array( 'page' => WPFNL_GLOBAL_SETTINGS_SLUG ), admin_url( 'admin.php' ) ) . '#ai-assistant-settings' ),
969 'restApiUrl' => esc_url_raw( get_rest_url() ),
970 'restNonce' => wp_create_nonce( 'wp_rest' ),
971 // The copilot client reads rest_url/nonce; without these it falls
972 // back to an empty nonce and every REST call 401s.
973 'rest_url' => esc_url_raw( get_rest_url() ),
974 'nonce' => wp_create_nonce( 'wp_rest' ),
975 'rest_nonce' => wp_create_nonce( 'wp_rest' ),
976 'settingsPage' => esc_url_raw( add_query_arg( array( 'page' => WPFNL_GLOBAL_SETTINGS_SLUG ), admin_url( 'admin.php' ) ) . '#ai-assistant-settings' ),
977 'isProActive' => $_ai_pro_active ? 'yes' : 'no',
978 'isAiEnabled' => $_ai_enabled ? 'yes' : 'no',
979 ));
980 }
981
982 if ( 'wpfunnels_page_' . WPFNL_GLOBAL_SETTINGS_SLUG === $hook ) {
983 $_current_user = wp_get_current_user();
984 $_settings_common_data = array(
985 'username' => $_current_user ? $_current_user->user_login : '',
986 'rest_url' => esc_url_raw( get_rest_url() ),
987 'nonce' => wp_create_nonce( 'wp_rest' ),
988 'admin_url' => esc_url_raw( admin_url() ),
989 );
990
991 wp_enqueue_script( 'wpfnl-mcp-agent-settings', plugin_dir_url( __FILE__ ) . 'assets/dist/js/mcp-agent-settings.min.js', [], $this->version, true );
992 Wpfnl_functions::enqueue_bundle_style( 'mcp-agent-settings', 'wpfnl-mcp-agent-settings-bundle' );
993 wp_localize_script(
994 'wpfnl-mcp-agent-settings',
995 'WPFnlMcpSettings',
996 array_merge(
997 $_settings_common_data,
998 array(
999 'site_url' => esc_url_raw( home_url() ),
1000 )
1001 )
1002 );
1003
1004 wp_enqueue_script( 'wpfnl-ai-assistant-settings', plugin_dir_url( __FILE__ ) . 'assets/dist/js/ai-assistant-settings.min.js', [], $this->version, true );
1005 Wpfnl_functions::enqueue_bundle_style( 'ai-assistant-settings', 'wpfnl-ai-assistant-settings-bundle' );
1006 wp_localize_script( 'wpfnl-ai-assistant-settings', 'WPFnlAiAssistantSettings', $_settings_common_data );
1007 }
1008
1009 if (in_array($hook, $this->page_hooks)) {
1010
1011 // Admin header actions — the Knowledge Base, AI Assistant, Settings
1012 // and Upgrade group rendered into #wpfnl-header-actions from every
1013 // WPFunnels admin screen. Reuses the same WPFNAIFunnel global name
1014 // the full-page ai-funnel-app bundle localizes (see above) so
1015 // admin/src/copilot/services/ai.js works unmodified; safe because
1016 // $this->page_hooks and the AI-funnel page hook never match on the
1017 // same request.
1018 $_settings_page_url = add_query_arg( array( 'page' => WPFNL_GLOBAL_SETTINGS_SLUG ), admin_url( 'admin.php' ) );
1019
1020 wp_enqueue_script('wpfnl-global-ai-drawer', plugin_dir_url(__FILE__) . 'assets/dist/js/global-ai-drawer.min.js', [], $this->version, true);
1021 Wpfnl_functions::enqueue_bundle_style( 'global-ai-drawer', 'wpfnl-global-ai-drawer-bundle' );
1022 wp_localize_script('wpfnl-global-ai-drawer', 'WPFNAIFunnel', array(
1023 'adminUrl' => esc_url_raw( admin_url( 'admin.php' ) ),
1024 'settingsUrl' => esc_url_raw( $_settings_page_url . '#ai-assistant-settings' ),
1025 'settingsPageUrl' => esc_url_raw( $_settings_page_url ),
1026 'isSettingsPage' => isset( $_GET['page'] ) && WPFNL_GLOBAL_SETTINGS_SLUG === sanitize_text_field( wp_unslash( $_GET['page'] ) ),
1027 'isPro' => (bool) apply_filters( 'wpfunnels/is_pro_license_activated', false ),
1028 'upgradeUrl' => 'https://getwpfunnels.com/pricing/',
1029 'restApiUrl' => esc_url_raw( get_rest_url() ),
1030 'restNonce' => wp_create_nonce( 'wp_rest' ),
1031 'rest_url' => esc_url_raw( get_rest_url() ),
1032 'nonce' => wp_create_nonce( 'wp_rest' ),
1033 'rest_nonce' => wp_create_nonce( 'wp_rest' ),
1034 ));
1035
1036 $is_wc_installed = 'no';
1037 $is_wpfunnels_installed = 'no';
1038 if (is_plugin_active('woocommerce/woocommerce.php')) {
1039 $is_wc_installed = 'yes';
1040 }
1041 if (is_plugin_active('wpfunnels/wpfunnels.php')) {
1042 $is_wpfunnels_installed = 'yes';
1043 }
1044
1045 wp_enqueue_script($this->plugin_name . '-select2', plugin_dir_url(__FILE__) . 'assets/js/select2.min.js', ['jquery'], $this->version, true);
1046 $products = array();
1047 if (isset($_GET['step_id'])) {
1048 $step_id = sanitize_text_field($_GET['step_id']);
1049 if ($step_id) {
1050 if (Wpfnl_functions::check_if_this_is_step_type_by_id($step_id, 'checkout')) {
1051 $products = get_post_meta($step_id, '_wpfnl_checkout_products', true);
1052 if (empty($products)) {
1053 $products = [];
1054 }
1055 }
1056 }
1057 }
1058
1059 $funnel_id = '';
1060 $funnel_title = '';
1061 $step_id = '';
1062 if (isset($_GET['id'])) {
1063 $funnel_id = $_GET['id'];
1064 $funnel_title = html_entity_decode(get_the_title($funnel_id));
1065 if (isset($_GET['step_id'])) {
1066 $step_id = filter_input(INPUT_GET, 'step_id', FILTER_VALIDATE_INT);
1067 }
1068
1069 // For store checkout funnels, resolve the checkout step ID when not in URL.
1070 if ( empty( $step_id ) && 'store_checkout' === get_post_meta( $funnel_id, '_wpfnl_funnel_type', true ) ) {
1071 $step_id = \WPFunnels\WooCommerce\Wpfnl_Store_Checkout_Conditions::get_checkout_step_id_for_funnel( $funnel_id );
1072 }
1073 }
1074
1075 /**
1076 * Get funnel preview link
1077 */
1078 $steps = get_post_meta($funnel_id, '_steps_order', true);
1079 $funnel_preview_link = '#';
1080 $response['success'] = false;
1081 if ($steps) {
1082 if (isset($steps[0]) && $steps[0]['id']) {
1083 $funnel_preview_link = get_post_permalink($steps[0]['id']);
1084 }
1085 }
1086
1087
1088 wp_enqueue_script('jquery-ui-datepicker');
1089 wp_enqueue_editor();
1090 wp_enqueue_script('wp-color-picker');
1091 wp_enqueue_media();
1092
1093 wp_enqueue_script($this->plugin_name . '-jed', plugin_dir_url(__FILE__) . 'assets/js/jed.js', ['jquery'], $this->version, true);
1094 wp_enqueue_script($this->plugin_name, plugin_dir_url(__FILE__) . 'assets/js/wpfnl-admin.js', ['jquery', 'jquery-ui-sortable'], $this->version, true);
1095
1096 wp_enqueue_script($this->plugin_name . '-runtime', plugin_dir_url(__FILE__) . 'assets/dist/runtime/index.min.js', ['jquery', 'wp-i18n', 'wp-util', 'updates', 'wp-color-picker', $this->plugin_name . '-jed'], $this->version, true);
1097 wp_enqueue_script($this->plugin_name . '-funnel-window', plugin_dir_url(__FILE__) . 'assets/dist/js/funnel-components.min.js', ['jquery', 'wp-i18n', 'wp-util', 'updates', 'wp-color-picker', $this->plugin_name . '-jed', $this->plugin_name . '-runtime'], $this->version, true);
1098 Wpfnl_functions::enqueue_bundle_style( 'funnel-components', $this->plugin_name . '-funnel-window-bundle' );
1099 wp_enqueue_script($this->plugin_name . '-backbone-marionette', plugin_dir_url(__FILE__) . 'assets/lib/backbone/backbone.marionette.min.js', ['backbone'], $this->version, true);
1100 wp_enqueue_script($this->plugin_name . '-backbone-radio', plugin_dir_url(__FILE__) . 'assets/lib/backbone/backbone.radio.min.js', ['backbone'], $this->version, true);
1101
1102 $general_settings = Wpfnl_functions::get_general_settings();
1103 $builder = $general_settings['builder'];
1104 $funnel_builder_mode = Wpfnl_functions::get_default_funnel_builder_mode();
1105 $canvas_view_mode = Wpfnl_functions::get_canvas_view_mode();
1106
1107 /**
1108 * This code snippet will check if pro addons is activated or not. if not activated
1109 * Total number of funnels will be maximum 3, otherwise customer can add as more funnels
1110 * As they want
1111 */
1112 $is_pro_active = apply_filters('wpfunnels/is_pro_license_activated', false);
1113 $count_funnels = Wpfnl_functions::count_non_store_checkout_funnels( array( 'publish', 'draft', 'trash' ) );
1114 $count_active_funnels = Wpfnl_functions::count_non_store_checkout_funnels();
1115 $total_allowed_funnels = 3;
1116 if ($is_pro_active) {
1117 $total_allowed_funnels = -1;
1118 }
1119 $count_store_checkouts = Wpfnl_functions::count_store_checkout_funnels();
1120 $total_allowed_store_checkouts = $is_pro_active ? -1 : 3;
1121
1122 $wc_currency_symbol = '$';
1123 if (function_exists('get_woocommerce_currency_symbol')) {
1124 $wc_currency_symbol = html_entity_decode(get_woocommerce_currency_symbol());
1125 }
1126 $ld_currency_symbol = '$';
1127 if (function_exists('learndash_get_currency_symbol')) {
1128 $ld_currency_symbol = html_entity_decode(learndash_get_currency_symbol());
1129 }
1130
1131 $product_url = esc_url_raw(
1132 add_query_arg(
1133 array(
1134 'post_type' => 'product',
1135 'wpfunnels' => 'yes',
1136 ),
1137 admin_url('post-new.php')
1138 )
1139 );
1140
1141 wp_localize_script($this->plugin_name, 'WPFunnelVars', array(
1142 'ajaxurl' => admin_url('admin-ajax.php'),
1143 'rest_api_url' => get_rest_url(),
1144 'security' => wp_create_nonce('wpfnl-admin'),
1145 'import_nonce' => wp_create_nonce('wpfnl_import_funnels_nonce'),
1146 'admin_url' => admin_url(),
1147 'edit_funnel_url' => admin_url('admin.php?page=edit_funnel'),
1148 'i18n' => array('wpfnl' => $this->get_jed_locale_data('wpfnl')),
1149 'current_user_id' => get_current_user_id(),
1150 'is_wc_installed' => $is_wc_installed,
1151 'is_wpfunnels_installed' => $is_wpfunnels_installed,
1152 'products' => $products,
1153 'funnel_id' => $funnel_id,
1154 'step_id' => $step_id,
1155 'funnel_title' => $funnel_title,
1156 'funnel_preview_link' => $funnel_preview_link,
1157 'site_url' => site_url(),
1158 'image_path' => WPFNL_URL . 'admin/assets/images',
1159 'placeholder_image_path' => WPFNL_URL . 'admin/assets/images/ob_placeholder.png',
1160 'nonce' => wp_create_nonce('wp_rest'),
1161 'isNewFunnel' => \Wpfnl_Activator::is_new_install() ? true : false,
1162 'isProActivated' => $is_pro_active,
1163 'totalFunnels' => $count_funnels,
1164 'count_active_funnels' => $count_active_funnels,
1165 'totalStoreCheckouts' => $count_store_checkouts,
1166 'totalAllowedStoreCheckouts' => $total_allowed_store_checkouts,
1167 'product_url' => $product_url,
1168 'totalAllowedFunnels' => $total_allowed_funnels,
1169 'builder' => $builder,
1170 'funnel_builder_mode' => $funnel_builder_mode,
1171 'canvas_view_mode' => $canvas_view_mode,
1172 'dependencyPlugins' => Wpfnl_functions::get_dependency_plugins_status(),
1173 'isAnyPluginMissing' => Wpfnl_functions::is_any_plugin_missing(),
1174 'isGlobalFunnelActivated' => Wpfnl_functions::is_global_funnel_activated(),
1175 'isGlobalFunnel' => Wpfnl_functions::is_global_funnel($funnel_id),
1176 'GBFVersion' => defined('WPFNL_PRO_GBF_VERSION') ? WPFNL_PRO_GBF_VERSION : ( defined('WPFNL_PRO_GB_VERSION') ? WPFNL_PRO_GB_VERSION : '' ),
1177 'isSkipOffer' => $this->is_skip_offer(),
1178 'paymentMethod' => $this->get_payment_method(),
1179 'shippingMethod' => $this->get_shipping_method(),
1180 'isGbf' => $this->maybe_gbf($funnel_id),
1181 'isLms' => $this->maybe_lms($funnel_id),
1182 'lmsProvider' => $this->get_lms_provider(),
1183 'isLmsActivated' => Wpfnl_functions::is_lms_addon_active(),
1184 'isAnyLmsPluginActive' => Wpfnl_functions::is_any_lms_plugin_active(),
1185 'isLmsSettings' => Wpfnl_functions::is_enable_lms_settings(),
1186 'isLmsDisbaled' => $this->maybe_lms_settings_disbaled(),
1187 'lmsVersion' => (defined('WPFNL_PRO_LMS_VERSION') || defined('WPFUNNELS_PRO_LMS_VERSION')) && defined('LEARNDASH_VERSION') ? version_compare(LEARNDASH_VERSION, '4.2.1.1', '>=') : false,
1188 'individual_funnel_type' => get_post_meta($funnel_id, '_wpfnl_funnel_type', true),
1189 'isStoreCheckout' => get_post_meta($funnel_id, '_wpfnl_funnel_type', true) === 'store_checkout',
1190 'isSaleFunnel' => get_post_meta($funnel_id, '_wpfnl_funnel_type', true) === 'wc' || get_post_meta($funnel_id, '_wpfnl_funnel_type', true) === 'store_checkout',
1191 'gbf_set_condition_steps' => $this->get_gbf_steps($funnel_id),
1192 'reconfigurable_condition_data' => $this->get_reconfigurable_condition_data($funnel_id),
1193 'mint_steps' => $this->mint_step_settings($funnel_id),
1194 'mint_tags' => Wpfnl_functions::get_mint_contact_groups('tags'),
1195 'mint_lists' => Wpfnl_functions::get_mint_contact_groups('lists'),
1196 'mint_sequences' => Wpfnl_functions::get_sequences(),
1197 'obList' => Wpfnl_functions::get_all_ob($funnel_id),
1198 'upsellSteps' => Wpfnl_functions::get_selected_steps('upsell', $funnel_id),
1199 'downsellSteps' => Wpfnl_functions::get_selected_steps('downsell', $funnel_id),
1200 'landingAndCustomSteps' => Wpfnl_functions::get_selected_steps('landing', $funnel_id),
1201 'customSteps' => Wpfnl_functions::get_selected_steps('custom', $funnel_id),
1202 'onlySettingsSteps' => Wpfnl_functions::get_only_settings_steps(),
1203 'isWCML' => defined('WCML_VERSION'),
1204 'cfeDefault' => Wpfnl_functions::get_cfe_default_fields(),
1205 'adminEmail' => get_bloginfo('admin_email'),
1206 'siteName' => get_option('blogname'),
1207 'mailMintEmail' => Wpfnl_functions::get_mailmint_email(),
1208 'email_settings' => Wpfnl_functions::get_mailmint_email_settings(),
1209 'mint_twillo_settings' => Wpfnl_functions::get_mailmint_twillo_settings(),
1210 'emailBuilderUrl' => admin_url() . 'admin.php?page=email-builder',
1211 'currentUrl' => (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]",
1212 'wc_currency' => $wc_currency_symbol,
1213 'ld_currency' => $ld_currency_symbol,
1214 'getText' => Wpfnl_functions::get_text(),
1215 'user_role_manager_data' => Wpfnl_functions::get_user_role_settings(),
1216 'availableGateways' => Wpfnl_functions::get_enabled_payment_gateways(),
1217 'guidedTour' => Wpfnl_functions::get_guided_tour(),
1218 'isWPFIntegrationActive' => apply_filters( 'wpfunnels/is_integration_license_active', false ),
1219 ));
1220 wp_localize_script(
1221 $this->plugin_name,
1222 'template_library_object',
1223 array(
1224 'ajaxurl' => esc_url_raw(admin_url('admin-ajax.php')),
1225 'rest_api_url' => esc_url_raw(get_rest_url()),
1226 'dashboard_url' => ( $funnel_id && get_post_meta( $funnel_id, '_wpfnl_funnel_type', true ) === 'store_checkout' )
1227 ? esc_url_raw(admin_url('admin.php?page=store_checkout'))
1228 : esc_url_raw(admin_url('admin.php?page=' . WPFNL_FUNNEL_PAGE_SLUG)),
1229 'settings_url' => esc_url_raw(admin_url('admin.php?page=settings')),
1230 'home_url' => esc_url_raw(home_url()),
1231 'funnel_id' => $funnel_id,
1232 'isTemplatePage' => 'wpfunnels_page_wpf_templates' === $hook,
1233 'is_pro' => Wpfnl_functions::is_pro_license_activated(),
1234 'is_ab_tesing_available' => defined('WPFNL_PRO_VERSION') ? version_compare(WPFNL_PRO_VERSION, "1.7.3", ">=") : false,
1235 'is_webhook_licensed' => Wpfnl_functions::is_webhook_license_activated(),
1236 'pro_url' => add_query_arg('wpfnl-dashboard', '1', GETWPFUNNEL_PRICING_URL),
1237 'nonce' => wp_create_nonce('wp_rest'),
1238 'image_path' => WPFNL_URL . 'admin/assets/images',
1239 'template_type' => Wpfnl_functions::get_template_types(),
1240 'countries' => Wpfnl_functions::get_countries(),
1241 'supported_steps' => Wpfnl_functions::get_supported_step_type(),
1242 'is_mint_active' => Wpfnl_functions::is_mint_mrm_active(),
1243 'settingsSteps' => Wpfnl_functions::get_settings_steps(),
1244 'isRemote' => Wpfnl_functions::maybe_remote_funnel(),
1245 'isStoreCheckout' => 'wpfunnels_page_store_checkout' === $hook,
1246 )
1247 );
1248
1249 wp_localize_script(
1250 $this->plugin_name,
1251 'CheckoutStep',
1252 array(
1253 'ajaxurl' => esc_url_raw(admin_url('admin-ajax.php')),
1254 'rest_api_url' => esc_url_raw(get_rest_url()),
1255 'wc_currency' => $wc_currency_symbol,
1256 'nonce' => wp_create_nonce('wp_rest'),
1257 'security' => wp_create_nonce('wpfnl-admin'),
1258 'image_path' => WPFNL_URL . 'admin/assets/images',
1259 'tooltipIcon' => WPFNL_URL . 'admin/partials/icons/question-tooltip-icon.php',
1260 'imageUploadIcon' => WPFNL_URL . 'admin/partials/icons/image-upload-icon.php',
1261 'step_id' => $step_id,
1262 'back' => add_query_arg(
1263 array(
1264 'page' => WPFNL_EDIT_FUNNEL_SLUG,
1265 'id' => filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT),
1266 'step_id' => $step_id,
1267 ),
1268 admin_url('admin.php')
1269 ),
1270 'priceConfig' => Wpfnl_functions::get_wc_price_config(),
1271 )
1272 );
1273
1274 wp_localize_script(
1275 $this->plugin_name,
1276 'wpfnl_addons_vars',
1277 array(
1278 'addons' => Wpfnl_functions::get_supported_addons(),
1279 'gbf_conditions' => Wpfnl_functions::get_supported_gbf_offer_condition(),
1280 'categories' => Wpfnl_functions::get_categories_gbf_offer_condition(),
1281 'role' => Wpfnl_functions::get_all_user_roles(),
1282 'tags' => Wpfnl_functions::get_all_tags(),
1283 'shippingClasses' => Wpfnl_functions::get_shipping_classes(),
1284 )
1285 );
1286
1287 // Enqueue the admin dashboard script only on WPFunnels Main Page
1288
1289 if ($this->is_current_page('wpfunnels')) {
1290 wp_enqueue_script('wpfnl-admin-app', plugin_dir_url(__FILE__) . 'assets/dist/js/wpfnl-admin-app.min.js', array(), $this->version, true);
1291 Wpfnl_functions::enqueue_bundle_style( 'wpfnl-admin-app', 'wpfnl-admin-app-bundle' );
1292 wp_localize_script('wpfnl-admin-app', 'WPFAdminObj', array(
1293 'rest_api_url' => get_rest_url(),
1294 'security' => wp_create_nonce('wpfnl-admin'),
1295 'nonce' => wp_create_nonce('wp_rest'),
1296 'priceConfig' => Wpfnl_functions::get_wc_price_config(),
1297 'isProActivated' => apply_filters('wpfunnels/is_wpfnl_pro_active', false),
1298 'isWPFIntegrationActive' => apply_filters( 'wpfunnels/is_integration_license_active', false ),
1299 'getText' => Wpfnl_functions::get_text(),
1300 'startOfWeek' => (int) get_option('start_of_week', 0),
1301 'admin_url' => admin_url(),
1302 ));
1303 }
1304
1305
1306 /**
1307 * Localize scripts for funnel window
1308 *
1309 * @var $localize
1310 */
1311
1312 $notices = $this->get_builder_notice();
1313
1314 $localize = apply_filters('wpfunnels/funnel_window_admin_localize', array());
1315 wp_localize_script($this->plugin_name . '-funnel-window', 'wpfunnels_funnel_localize', array($localize));
1316
1317
1318 do_action('wpfunnels_after_scripts_loaded');
1319 }
1320 }
1321
1322
1323 public function get_lms_provider()
1324 {
1325 $lms_settings = get_option('_wpfunnels_lms_settings', array());
1326 $provider_id = isset($lms_settings['lms_provider']) ? $lms_settings['lms_provider'] : 'learndash';
1327 return $provider_id;
1328 }
1329
1330
1331 /**
1332 * Get the reconfigurable condition data for a funnel
1333 */
1334 public function get_reconfigurable_condition_data($funnel_id)
1335 {
1336 if (!$funnel_id) {
1337 return [];
1338 }
1339 $data = get_post_meta($funnel_id, '_wpfnl_reconfigurable_condition_data', true);
1340 if (!is_array($data) || empty($data)) {
1341 return [];
1342 }
1343 return $data;
1344 }
1345
1346
1347 /**
1348 * Get all setps where GBF conditions is already set
1349 *
1350 * @param Integer $funnel_id
1351 *
1352 * @since 2.6.1
1353 */
1354 private function get_gbf_steps($funnel_id)
1355 {
1356 $gbf_steps = [];
1357 if ($funnel_id) {
1358 $funnel_type = get_post_meta($funnel_id, '_wpfnl_funnel_type', true);
1359 $is_gbf = get_post_meta($funnel_id, 'is_global_funnel', true);
1360
1361 if ('yes' === $is_gbf) {
1362 $steps = Wpfnl_functions::get_steps($funnel_id);
1363 if (is_array($steps)) {
1364 foreach ($steps as $step) {
1365 if (isset($step['id'], $step['step_type'])) {
1366 if ('checkout' === $step['step_type']) {
1367 $conditions = get_post_meta($funnel_id, 'global_funnel_start_condition', true);
1368 if (is_array($conditions)) {
1369 array_push($gbf_steps, $step['id']);
1370 }
1371 }
1372 elseif ('upsell' === $step['step_type'] || 'downsell' === $step['step_type']) {
1373 $conditions = get_post_meta($step['id'], 'global_funnel_' . $step['step_type'] . '_rules', true);
1374 if (is_array($conditions)) {
1375 array_push($gbf_steps, $step['id']);
1376 }
1377 }
1378 }
1379 }
1380 }
1381 } elseif ('store_checkout' === $funnel_type) {
1382 $steps = Wpfnl_functions::get_steps($funnel_id);
1383 if (is_array($steps)) {
1384 foreach ($steps as $step) {
1385 if (isset($step['id'], $step['step_type']) && 'checkout' === $step['step_type']) {
1386 $raw = get_post_meta($step['id'], '_wpfnl_store_checkout_condition', true);
1387 $condition = is_string($raw) ? json_decode($raw, true) : $raw;
1388 if (is_array($condition) && isset($condition['condition_type']) && 'rules' === $condition['condition_type']) {
1389 array_push($gbf_steps, $step['id']);
1390 }
1391 }
1392 }
1393 }
1394 }
1395 }
1396
1397 return $gbf_steps;
1398 }
1399
1400
1401 /**
1402 * Returns Jed-formatted localization data.
1403 *
1404 * @param string $domain Translation domain.
1405 *
1406 * @return array
1407 */
1408 public function get_jed_locale_data($domain, $language_dir = null)
1409 {
1410 $plugin_translations = $this->get_translations_for_plugin_domain($domain, $language_dir);
1411 $translations = get_translations_for_domain($domain);
1412
1413 $locale = array(
1414 'domain' => $domain,
1415 'locale_data' => array(
1416 $domain => array(
1417 '' => array(
1418 'domain' => $domain,
1419 'lang' => is_admin() ? get_user_locale() : get_locale(),
1420 ),
1421 ),
1422 ),
1423 );
1424
1425 if (!empty($translations->headers['Plural-Forms'])) {
1426 $locale['locale_data'][$domain]['']['plural_forms'] = $translations->headers['Plural-Forms'];
1427 }
1428 else if (!empty($plugin_translations['header'])) {
1429 $locale['locale_data'][$domain]['']['plural_forms'] = $plugin_translations['header']['Plural-Forms'];
1430 }
1431
1432 $entries = array_merge($plugin_translations['translations'], $translations->entries);
1433
1434 foreach ($entries as $msgid => $entry) {
1435 $locale['locale_data'][$domain][$msgid] = $entry->translations;
1436 }
1437
1438 return $locale;
1439 }
1440
1441
1442 /**
1443 * Get translactions for WePos plugin
1444 *
1445 * @param string $domain
1446 * @param string $language_dir
1447 *
1448 * @return array
1449 */
1450 public function get_translations_for_plugin_domain($domain, $language_dir = null)
1451 {
1452 if ($language_dir == null) {
1453 $language_dir = WPFNL_PATH . '/languages/';
1454 }
1455 $languages = get_available_languages($language_dir);
1456 $get_site_lang = is_admin() ? get_user_locale() : get_locale();
1457 $mo_file_name = $domain . '-' . $get_site_lang;
1458 $translations = [];
1459
1460 if (in_array($mo_file_name, $languages) && file_exists($language_dir . $mo_file_name . '.mo')) {
1461 $mo = new \MO();
1462 if ($mo->import_from_file($language_dir . $mo_file_name . '.mo')) {
1463 $translations = $mo->entries;
1464 }
1465 }
1466
1467 return [
1468 'header' => isset($mo) ? $mo->headers : '',
1469 'translations' => $translations,
1470 ];
1471 }
1472
1473
1474 /**
1475 * Check GBF version for skip offer
1476 */
1477 public function is_skip_offer()
1478 {
1479 // GBF is now built into WPFunnels Pro — always available when GBF is activated.
1480 if ( Wpfnl_functions::is_global_funnel_activated() ) {
1481 return true;
1482 }
1483 // Legacy: standalone addon still active.
1484 if ( defined('WPFNL_PRO_GB_VERSION') ) {
1485 return version_compare( WPFNL_PRO_GB_VERSION, '1.0.9', '>=' );
1486 }
1487 return false;
1488 }
1489
1490 public function mint_step_settings($funnel_id)
1491 {
1492 $steps = get_post_meta($funnel_id, '_steps', true);
1493 $mint_steps = [];
1494 if (is_array($steps)) {
1495 foreach ($steps as $step) {
1496 $mint_settings['stepID'] = $step['id'];
1497 $value = get_post_meta($step['id'], '_wpfnl_automation_steps', true);
1498 $mint_settings['value'] = is_array($value) ? $value : [];
1499 array_push($mint_steps, $mint_settings);
1500 }
1501 }
1502 return $mint_steps;
1503 }
1504
1505
1506 /**
1507 * Define w2cloud routes
1508 *
1509 * @return array
1510 */
1511 public function get_wpfnl_routes()
1512 {
1513 $routes = array(
1514 array(
1515 'path' => '/',
1516 'name' => 'home',
1517 'component' => 'Home'
1518 )
1519 );
1520 return apply_filters('wpfnl_routes', $routes);
1521 }
1522
1523 /**
1524 * Get all active Payment Method
1525 *
1526 * @return array
1527 */
1528 public function get_payment_method()
1529 {
1530 if (Wpfnl_functions::is_wc_active()) {
1531 $gateways = WC()->payment_gateways->get_available_payment_gateways();
1532 $enabled_gateways = [];
1533
1534 if ($gateways) {
1535 foreach ($gateways as $key => $gateway) {
1536 if ($gateway->enabled == 'yes') {
1537 $enabled_gateways[$key] = $gateway->method_title;
1538 }
1539 }
1540 }
1541 return $enabled_gateways;
1542 }
1543 return [];
1544 }
1545
1546 /**
1547 * Get all shipping methods
1548 *
1549 * @return array
1550 */
1551 public function get_shipping_method()
1552 {
1553 if (Wpfnl_functions::is_wc_active()) {
1554 $available_shipping = WC()->shipping()->get_shipping_methods();
1555 $enabled_shipping = [];
1556 if ($available_shipping) {
1557 foreach ($available_shipping as $key => $shipping) {
1558 $enabled_shipping[$key] = $shipping->method_title;
1559 }
1560 }
1561 return $enabled_shipping;
1562 }
1563 return [];
1564 }
1565
1566
1567 /**
1568 * Show funnel steps on reading
1569 *
1570 * @param $output
1571 *
1572 * @return mixed
1573 */
1574 public function show_funnel_steps_on_reading($output)
1575 {
1576 global $pagenow;
1577 if (('options-reading.php' === $pagenow || 'customize.php' === $pagenow) && preg_match('#page_on_front#', $output)) {
1578 $output = $this->show_steps_options($output);
1579 }
1580 return $output;
1581 }
1582
1583
1584 /**
1585 * Show steps pages on reading
1586 *
1587 * @param $output
1588 *
1589 * @return string
1590 */
1591 private function show_steps_options($output)
1592 {
1593 $options = '';
1594
1595 $steps = get_posts(
1596 array(
1597 'post_type' => WPFNL_STEPS_POST_TYPE,
1598 'posts_per_page' => -1,
1599 'numberposts' => 100,
1600 'orderby' => 'title',
1601 'order' => 'ASC',
1602 'post_status' => 'publish',
1603 'meta_query' => array(
1604 'relation' => 'OR',
1605 array(
1606 'key' => '_step_type',
1607 'value' => 'landing',
1608 ),
1609 array(
1610 'key' => '_step_type',
1611 'value' => 'checkout',
1612 )
1613 ),
1614 )
1615 );
1616
1617 if ($steps && is_array($steps)) {
1618 $front_page_id = get_option('page_on_front');
1619 foreach ($steps as $step) {
1620 $selected = selected($front_page_id, $step->ID, false);
1621 $post_type_obj = get_post_type_object($step->post_type);
1622 $options .= "<option value=\"{$step->ID}\"{$selected}>{$step->post_title} (WPFunnels {$post_type_obj->labels->singular_name})</option>";
1623 }
1624 $options .= '</select>';
1625 $output = str_replace('</select>', $options, $output);
1626 }
1627 return $output;
1628 }
1629
1630
1631 /**
1632 * Get notice for builder
1633 *
1634 * @return array
1635 */
1636 public function get_builder_notice()
1637 {
1638 $builder = Wpfnl_functions::get_builder_type();
1639 $notices = array();
1640 if ('divi-builder' === $builder) {
1641 $notices['notices'][] = array();
1642 }
1643 return $notices;
1644 }
1645
1646
1647 /**
1648 * Change text in order details page
1649 */
1650 public function wpfnl_customizing_checkout_text($translated_text, $untranslated_text, $domain)
1651 {
1652
1653 if (is_admin()) {
1654 if ($translated_text == 'Coupon(s):') {
1655 $translated_text = __('Discount:', 'wpfnl');
1656 }
1657 }
1658
1659 return $translated_text;
1660 }
1661
1662
1663 /**
1664 * Change local for if this is funnel canvas window
1665 *
1666 * @param $local
1667 *
1668 * @return string
1669 *
1670 * @since 2.3.8
1671 */
1672 public function change_local_for_funnel_canvas($local)
1673 {
1674 if (Wpfnl_functions::is_funnel_canvas_window()) {
1675 return 'en_US';
1676 }
1677 return $local;
1678 }
1679
1680
1681 /**
1682 * Add type meta
1683 *
1684 * @since 2.4.4
1685 */
1686 public function wpfnl_add_type_meta()
1687 {
1688 Wpfnl_functions::add_type_meta();
1689 }
1690
1691
1692 /**
1693 * Maybe Global funnel
1694 *
1695 * @param String
1696 *
1697 * @return Bool
1698 * @since 2.4.11
1699 */
1700 public function maybe_gbf($funnel_id)
1701 {
1702
1703 if ( Wpfnl_functions::is_global_funnel_activated() ) {
1704 if ($funnel_id) {
1705 $is_gbf = get_post_meta($funnel_id, 'is_global_funnel', true);
1706 if ('yes' == $is_gbf) {
1707 return true;
1708 }
1709 }
1710 }
1711
1712 return false;
1713 }
1714
1715 /**
1716 * Check funnel type is lms or not by funnel_id
1717 *
1718 * @return Bool
1719 */
1720 public function maybe_lms($funnel_id)
1721 {
1722
1723 $type = get_post_meta($funnel_id, '_wpfnl_funnel_type', true);
1724 if ('lms' === $type) {
1725 return true;
1726 }
1727 return false;
1728 }
1729
1730 /**
1731 * May be lms settings is disbaled
1732 */
1733 public function maybe_lms_settings_disbaled()
1734 {
1735 return Wpfnl_functions::is_wc_active() && Wpfnl_functions::is_lms_addon_active();
1736 }
1737
1738
1739 /**
1740 * Trigger when any plugin is deactivated
1741 *
1742 * @param $filename
1743 *
1744 * @since 2.5.1
1745 */
1746 public function wpfnl_deactivated_plugin($filename)
1747 {
1748 if ('woocommerce/woocommerce.php' === $filename) {
1749 Wpfnl_functions::wpfnl_delete_transient();
1750 }
1751 elseif ('sfwd-lms/sfwd_lms.php' === $filename) {
1752 Wpfnl_functions::wpfnl_delete_transient();
1753 }
1754 elseif ('wpfunnels-pro-lms/wpfunnels-pro-lms.php' === $filename) {
1755 Wpfnl_functions::wpfnl_delete_transient();
1756 }
1757 elseif ('qubely/qubely.php' === $filename) {
1758 Wpfnl_functions::wpfnl_delete_transient();
1759 delete_option(WPFNL_TEMPLATES_OPTION_KEY . '_wc');
1760 delete_option(WPFNL_TEMPLATES_OPTION_KEY . '_lms');
1761 delete_transient('wpfunnels_remote_template_data_wc_' . WPFNL_VERSION);
1762 delete_transient('wpfunnels_remote_template_data_lms_' . WPFNL_VERSION);
1763 delete_transient('wpfunnels_remote_template_data_lead_' . WPFNL_VERSION);
1764 delete_transient('wpfunnels_remote_template_data_store_checkout_' . WPFNL_VERSION);
1765 }
1766 }
1767
1768
1769 /**
1770 * Trigger when any plugin is activated
1771 *
1772 * @param $filename
1773 *
1774 * @since 2.5.1
1775 */
1776 public function wpfnl_activated_plugin($filename)
1777 {
1778 if ('woocommerce/woocommerce.php' === $filename) {
1779 Wpfnl_functions::wpfnl_delete_transient();
1780 }
1781 elseif ('sfwd-lms/sfwd_lms.php' === $filename) {
1782 if (Wpfnl_functions::is_lms_addon_active()) {
1783 Wpfnl_functions::wpfnl_delete_transient();
1784 }
1785 }
1786 elseif ('wpfunnels-pro-lms/wpfunnels-pro-lms.php' === $filename) {
1787 Wpfnl_functions::wpfnl_delete_transient();
1788 }
1789 elseif ('qubely/qubely.php' === $filename) {
1790 Wpfnl_functions::wpfnl_delete_transient();
1791 delete_option(WPFNL_TEMPLATES_OPTION_KEY . '_wc');
1792 delete_option(WPFNL_TEMPLATES_OPTION_KEY . '_lms');
1793 delete_transient('wpfunnels_remote_template_data_wc_' . WPFNL_VERSION);
1794 delete_transient('wpfunnels_remote_template_data_lms_' . WPFNL_VERSION);
1795 delete_transient('wpfunnels_remote_template_data_lead_' . WPFNL_VERSION);
1796 delete_transient('wpfunnels_remote_template_data_store_checkout_' . WPFNL_VERSION);
1797 }
1798 }
1799
1800
1801
1802 /**
1803 * Get editor source data
1804 *
1805 * @return array
1806 * @since 1.0.0
1807 */
1808 private function get_editor_source()
1809 {
1810 // get product categories for email builder.
1811 $wc_categories = $this->get_formatted_wc_categories();
1812 $wp_categories = $this->get_formatted_wp_post_categories();
1813
1814 return apply_filters(
1815 'plugin_hook_name',
1816 array(
1817 'product_categories' => $wc_categories,
1818 'post_categories' => $wp_categories,
1819 'placeholder_image' => ''
1820 )
1821 );
1822 }
1823
1824
1825
1826 /**
1827 * Get the WooCommerce product categories
1828 *
1829 * @return array
1830 * @since 1.0.0
1831 */
1832 private function get_formatted_wc_categories()
1833 {
1834 $taxonomy = 'product_cat';
1835 $orderby = 'name';
1836 $show_count = 0;
1837 $pad_counts = 0;
1838 $hierarchical = 1;
1839 $title = '';
1840 $empty = 0;
1841
1842 $args = array(
1843 'taxonomy' => $taxonomy,
1844 'orderby' => $orderby,
1845 'show_count' => $show_count,
1846 'pad_counts' => $pad_counts,
1847 'hierarchical' => $hierarchical,
1848 'title_li' => $title,
1849 'hide_empty' => $empty,
1850 );
1851 $product_categories = get_categories($args);
1852 $wc_categories = array();
1853 foreach ($product_categories as $product_cat) {
1854 $wc_categories[] = array(
1855 'value' => $product_cat->term_id,
1856 'label' => $product_cat->name,
1857 );
1858 }
1859
1860 return $wc_categories;
1861 }
1862
1863
1864 /**
1865 * Get the WordPress post categories
1866 *
1867 * @return array
1868 * @since 1.0.0
1869 */
1870 private function get_formatted_wp_post_categories()
1871 {
1872 $taxonomy = 'category';
1873 $orderby = 'name';
1874 $show_count = 0;
1875 $pad_counts = 0;
1876 $hierarchical = 1;
1877 $title = '';
1878 $empty = 0;
1879
1880 $args = array(
1881 'taxonomy' => $taxonomy,
1882 'orderby' => $orderby,
1883 'show_count' => $show_count,
1884 'pad_counts' => $pad_counts,
1885 'hierarchical' => $hierarchical,
1886 'title_li' => $title,
1887 'hide_empty' => $empty,
1888 );
1889 $post_categories = get_categories($args);
1890 $categories = array();
1891 foreach ($post_categories as $post_cat) {
1892 $categories[] = array(
1893 'value' => $post_cat->term_id,
1894 'label' => $post_cat->name,
1895 );
1896 }
1897 return $categories;
1898 }
1899
1900
1901 /**
1902 * Add custom capabilities to administrator role
1903 *
1904 * @since 3.1.3
1905 */
1906 public function attach_admin_capabilities()
1907 {
1908 global $wp_roles;
1909 $capabilities = array(
1910 'wpf_manage_funnels',
1911 );
1912 foreach ($capabilities as $cap) {
1913 $wp_roles->add_cap('administrator', $cap);
1914 }
1915 }
1916
1917 /**
1918 * Checks if the current page slug matches the provided slug.
1919 *
1920 * @param $slug
1921 * @return bool
1922 * @since 3.5.0
1923 */
1924 public function is_current_page($slug)
1925 {
1926 if (empty($slug)) {
1927 return false;
1928 }
1929 $current_page_slug = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : '';
1930 if ($slug === $current_page_slug) {
1931 return true;
1932 }
1933 return false;
1934 }
1935
1936 /**
1937 * Add body class for WPFunnels admin pages.
1938 *
1939 * @param string $classes Current body classes.
1940 * @return string Modified body classes.
1941 * @since 3.9.5
1942 */
1943 public function add_wpfunnels_admin_body_class($classes)
1944 {
1945 // Check if we're on a WPFunnels admin page.
1946 $screen = get_current_screen();
1947
1948 if ($screen && (in_array($screen->id, $this->page_hooks) || 'wpfunnels_page_' . WPFNL_AI_FUNNEL_PAGE_SLUG === $screen->id)) {
1949 $classes .= ' wpfunnels-body';
1950 }
1951
1952 return $classes;
1953 }
1954
1955
1956 /**
1957 * Create contact on mailmint when user allows to track data
1958 *
1959 * @param array $data
1960 *
1961 * @since 3.3.1
1962 */
1963 public function wpfunnels_tracker_optin($data)
1964 {
1965 if (isset($data['admin_email'], $data['first_name'], $data['last_name'])) {
1966 $json_body_data = json_encode([
1967 'email' => $data['admin_email'],
1968 'first_name' => $data['first_name'],
1969 'last_name' => $data['last_name'],
1970 ]);
1971
1972 $webHookUrl = [
1973 'https://staging-useraccount.kinsta.cloud/?mailmint=1&route=webhook&topic=contact&hash=b258136d-6759-4e91-bbab-0b7397af6dc7'
1974 ];
1975
1976 try {
1977 if (!empty($webHookUrl)) {
1978 foreach ($webHookUrl as $url) {
1979 wp_remote_request($url, [
1980 'method' => 'POST',
1981 'headers' => [
1982 'Content-Type' => 'application/json',
1983 ],
1984 'body' => $json_body_data
1985 ]);
1986 }
1987 }
1988 }
1989 catch (\Exception $e) {
1990 }
1991 }
1992 }
1993
1994 /**
1995 * Creates a new MRM contact.
1996 *
1997 * @param array $data The data for the contact.
1998 * @return void
1999 */
2000 public function create_mrm_contact($data)
2001 {
2002 if (!isset($data['data']['user_email'])) {
2003 return;
2004 }
2005 // Get double opt-in settings.
2006 $default = \MRM\Common\MrmCommon::double_optin_default_configuration();
2007 $settings = get_option('_mrm_optin_settings', $default);
2008 $enable = isset($settings['enable']) ? $settings['enable'] : false;
2009
2010 $user_data = array(
2011 'email' => $data['data']['user_email'],
2012 'first_name' => isset($data['data']['first_name']) ? $data['data']['first_name'] : '',
2013 'last_name' => isset($data['data']['last_name']) ? $data['data']['last_name'] : '',
2014 'meta_fields' => array(
2015 'phone_number' => isset($data['data']['phone_number']) ? $data['data']['phone_number'] : '',
2016 ),
2017 'status' => $enable ? 'pending' : 'subscribed',
2018 'source' => 'WPFunnels',
2019 );
2020
2021 $mail_mint_object = new \WPFunnels\Integrations\MailMint($user_data);
2022 $mail_mint_object->create_or_update_contact();
2023 }
2024 }