PluginProbe
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce / 3.3.0
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce v3.3.0
3.3.0 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.1 trunk 1.0.4 1.1.0 1.1.0.1 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 All 162 releases
← All changes | classes/class-cartflows-admin.php +287 -320 1.1.15 → 3.3.0 View file →
@@ -4,8 +4,12 @@
4 4 *
5 5 * @package CartFlows
6 6 */
7 7
8 +// Exit if accessed directly.
9 +if ( ! defined( 'ABSPATH' ) ) {
10 + exit;
11 +}
8 12 /**
9 13 * Class Cartflows_Admin.
10 14 */
11 15 class Cartflows_Admin {
@@ -10,267 +14,272 @@
10 14 */
11 15 class Cartflows_Admin {
12 16
13 17 /**
14 - * Calls on initialization
18 + * Instance
15 19 *
20 + * @access private
21 + * @var object Class object.
16 22 * @since 1.0.0
17 23 */
18 - public static function init() {
24 + private static $instance;
19 25
20 - self::initialise_plugin();
21 - self::init_hooks();
26 + /**
27 + * Initiator
28 + *
29 + * @since 1.0.0
30 + * @return object initialized object of class.
31 + */
32 + public static function get_instance() {
33 + if ( ! isset( self::$instance ) ) {
34 + self::$instance = new self();
35 + }
36 + return self::$instance;
22 37 }
23 38
24 39 /**
40 + * Constructor
41 + */
42 + public function __construct() {
43 +
44 + $this->init_hooks();
45 + }
46 +
47 + /**
25 48 * Init Hooks.
26 49 *
27 50 * @since 1.0.0
28 51 * @return void
29 52 */
30 - static public function init_hooks() {
53 + public function init_hooks() {
31 54
32 55 if ( ! is_admin() ) {
33 56 return;
34 57 }
35 58
36 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-admin-fields.php';
59 + /* Add lite version class to body */
60 + add_action( 'admin_body_class', array( $this, 'add_admin_body_class' ) );
37 61
38 - // Add CARTFLOWS menu option to admin.
39 - add_action( 'network_admin_menu', __CLASS__ . '::menu' );
40 - add_action( 'admin_menu', __CLASS__ . '::menu' );
41 - add_action( 'admin_menu', __CLASS__ . '::submenu', 999 );
62 + add_filter( 'plugin_action_links_' . CARTFLOWS_BASE, array( $this, 'add_action_links' ) );
42 63
43 - add_action( 'cartflows_render_admin_content', __CLASS__ . '::render_content' );
64 + add_action( 'admin_init', array( $this, 'flush_rules_after_save_permalinks' ) );
44 65
45 - add_action( 'init', __CLASS__ . '::settings_admin_scripts' );
66 + add_filter( 'post_row_actions', array( $this, 'remove_flow_actions' ), 99, 2 );
46 67
47 - /* Global Addmin Script */
48 - add_action( 'admin_enqueue_scripts', __CLASS__ . '::global_admin_scripts', 20 );
68 + add_action( 'wp_dashboard_setup', array( $this, 'dashboard_widget' ) );
49 69
50 - add_action( 'admin_footer', __CLASS__ . '::global_admin_data', 9555 );
70 + add_action( 'init', array( $this, 'run_scheduled_docs_job' ) );
71 + add_action( 'cartflows_update_knowledge_base_data', array( $this, 'cartflows_update_knowledge_base_data' ) );
72 + add_action( 'admin_post_cartflows_rollback', array( $this, 'post_cartflows_rollback' ) );
51 73
52 - /* Add lite version class to body */
53 - add_action( 'admin_body_class', __CLASS__ . '::add_admin_body_class' );
74 + $this->do_not_cache_admin_pages_actions();
75 +
76 + // Provide pointer configuration via filter.
77 + add_filter( 'cartflows_pointer_config', array( $this, 'get_pointer_config' ) );
54 78 }
55 79
56 -
57 80 /**
58 - * Initialize after Cartflows pro get loaded.
59 - */
60 - static public function settings_admin_scripts() {
61 - // Enqueue admin scripts.
62 - if ( isset( $_REQUEST['page'] ) && CARTFLOWS_SETTINGS == $_REQUEST['page'] ) {
63 - add_action( 'admin_enqueue_scripts', __CLASS__ . '::styles_scripts' );
64 -
65 - self::save_settings();
66 - }
67 - }
68 - /**
69 - * Initialises the Plugin Name.
81 + * Do not cache admin pages actions.
70 82 *
71 - * @since 1.0.0
83 + * @since 1.6.13
72 84 * @return void
73 85 */
74 - static public function initialise_plugin() {
86 + public function do_not_cache_admin_pages_actions() {
75 87
76 - $name = 'Cartflows';
77 - $short_name = 'Cflows';
78 -
79 - define( 'CARTFLOWS_PLUGIN_NAME', $name );
80 - define( 'CARTFLOWS_PLUGIN_SHORT_NAME', $short_name );
88 + add_action( 'admin_init', array( $this, 'add_admin_cache_restrict_const' ) );
89 + add_action( 'admin_head', array( $this, 'add_admin_cache_restrict_meta' ) );
81 90 }
82 91
83 92 /**
84 - * Renders the admin settings menu.
93 + * Run scheduled job for CartFLows knowledge base data.
85 94 *
86 - * @since 1.0.0
95 + * @since 2.0.0
87 96 * @return void
88 97 */
89 - static public function menu() {
98 + public function run_scheduled_docs_job() {
90 99
91 - if ( ! current_user_can( 'manage_options' ) ) {
100 + if ( wp_installing() ) {
92 101 return;
93 102 }
94 103
95 - add_menu_page(
96 - 'CartFlows',
97 - 'CartFlows',
98 - 'manage_options',
99 - CARTFLOWS_SLUG,
100 - __CLASS__ . '::render',
101 - 'data:image/svg+xml;base64,' . base64_encode( file_get_contents( CARTFLOWS_DIR . 'assets/images/cartflows-icon.svg' ) ),
102 - 39.7
103 - );
104 + // Only the legacy admin renders the Knowledge Base screen that consumes this data.
105 + if ( ! defined( 'CARTFLOWS_LEGACY_ADMIN' ) || ! CARTFLOWS_LEGACY_ADMIN ) {
106 + return;
107 + }
104 108
109 + if ( false === as_next_scheduled_action( 'cartflows_update_knowledge_base_data' ) ) {
110 + as_schedule_recurring_action( time(), WEEK_IN_SECONDS, 'cartflows_update_knowledge_base_data' );
111 + }
105 112 }
106 113
107 114 /**
108 - * Add submenu to admin menu.
115 + * Cartflows's REST knowledge base data.
109 116 *
110 - * @since 1.0.0
117 + * @since 2.0.0
118 + * @return mixed
111 119 */
112 - static function submenu() {
120 + public static function cartflows_update_knowledge_base_data() {
121 + $docs_json = json_decode( wp_remote_retrieve_body( wp_remote_get( 'https://cartflows.com//wp-json/powerful-docs/v1/get-docs' ) ) );
113 122
114 - $parent_slug = CARTFLOWS_SLUG;
115 - $page_title = __( 'Settings', 'cartflows' );
116 - $menu_title = __( 'Settings', 'cartflows' );
117 - $capability = 'manage_options';
118 - $menu_slug = 'cartflows_settings';
119 - $callback = __CLASS__ . '::render';
120 -
121 - add_submenu_page(
122 - $parent_slug,
123 - $page_title,
124 - $menu_title,
125 - $capability,
126 - $menu_slug,
127 - $callback
128 - );
123 + // Never autoload — this payload runs to hundreds of KB and only the Knowledge Base screen reads it.
124 + update_option( 'cartflows_docs_data', $docs_json, false );
129 125 }
130 126
131 127 /**
132 - * Renders the admin settings.
133 - *
134 - * @since 1.0.0
135 - * @return void
128 + * Init dashboard widgets.
136 129 */
137 - static public function render() {
138 - $action = ( isset( $_GET['action'] ) ) ? sanitize_text_field( $_GET['action'] ) : '';
139 - $action = ( ! empty( $action ) && '' != $action ) ? $action : 'general';
140 - $action = str_replace( '_', '-', $action );
130 + public function dashboard_widget() {
141 131
142 - // Enable header icon filter below.
143 - $header_wrapper_class = apply_filters( 'cartflows_header_wrapper_class', array( $action ) );
144 -
145 - include_once CARTFLOWS_DIR . 'includes/admin/cartflows-admin.php';
132 + if ( current_user_can( 'manage_options' ) && '1' === get_option( 'wcf_setup_skipped', false ) && '1' !== get_option( 'wcf_setup_complete', false ) ) {
133 + wp_add_dashboard_widget(
134 + 'cartFlows_setup_dashboard_widget',
135 + __( 'CartFlows Setup', 'cartflows' ),
136 + array( $this, 'status_widget' )
137 + );
138 + }
146 139 }
147 140
148 141 /**
149 - * Renders the admin settings content.
150 - *
151 - * @since 1.0.0
152 - * @return void
142 + * Show status widget.
153 143 */
154 - static public function render_content() {
144 + public function status_widget() {
155 145
156 - $action = ( isset( $_GET['action'] ) ) ? sanitize_text_field( $_GET['action'] ) : '';
157 - $action = ( ! empty( $action ) && '' != $action ) ? $action : 'general';
158 - $action = str_replace( '_', '-', $action );
159 - $action = 'general';
146 + $admin_url = admin_url( 'index.php' ) . '?page=cartflows-onboarding&';
160 147
161 - $header_wrapper_class = apply_filters( 'cartflows_header_wrapper_class', array( $action ) );
148 + $steps = array(
149 + 'welcome' => $admin_url . 'step=welcome',
150 + 'page-builder' => $admin_url . 'step=page-builder',
151 + 'plugin-install' => $admin_url . 'step=plugin-install',
152 + 'global-checkout' => $admin_url . 'step=global-checkout',
153 + 'optin' => $admin_url . 'step=optin',
154 + 'ready' => $admin_url . 'step=ready',
155 + );
162 156
163 - include_once CARTFLOWS_DIR . 'includes/admin/cartflows-general.php';
157 + $exit_step = get_option( 'wcf_exit_setup_step', 'welcome' );
158 +
159 + $incompleted_steps = array_search( $exit_step, array_keys( $steps ), true );
160 + $remianing_steps = array_slice( $steps, 0, $incompleted_steps );
161 +
162 + $completed_tasks_count = count( $remianing_steps ) + 1;
163 + $tasks_count = count( $steps );
164 + $button_link = ! empty( $exit_step ) ? $steps[ $exit_step ] : '';
165 +
166 + $progress_percentage = ( $completed_tasks_count / $tasks_count ) * 100;
167 + $circle_r = 6.5;
168 + $circle_dashoffset = ( ( 100 - $progress_percentage ) / 100 ) * ( pi() * ( $circle_r * 2 ) );
169 +
170 + wp_enqueue_style( 'cartflows-dashboard-widget', CARTFLOWS_URL . 'admin/assets/css/admin-widget.css', array(), CARTFLOWS_VER );
171 +
172 + ?>
173 +
174 + <div class="cartflows-dashboard-widget-finish-setup">
175 + <span class='progress-wrapper'>
176 + <svg class="circle-progress" width="17" height="17" version="1.1" xmlns="http://www.w3.org/2000/svg">
177 + <circle r="6.5" cx="10" cy="10" fill="transparent" stroke-dasharray="40.859" stroke-dashoffset="0"></circle>
178 + <circle class="bar" r="6.5" cx="190" cy="10" fill="transparent" stroke-dasharray="40.859" stroke-dashoffset="<?php echo esc_attr( $circle_dashoffset ); ?>" transform='rotate(-90 100 100)'></circle>
179 + </svg>
180 + <span><?php echo esc_html_e( 'Step', 'cartflows' ); ?> <?php echo esc_html( $completed_tasks_count ); ?> <?php echo esc_html_e( 'of', 'cartflows' ); ?> <?php echo esc_html( $tasks_count ); ?></span>
181 + </span>
182 +
183 + <div class="description">
184 + <div class="wcf-left-column">
185 + <p>
186 + <?php echo esc_html_e( 'You\'re almost there! Once you complete CartFlows setup you can start receiving orders from flows.', 'cartflows' ); ?>
187 + </p>
188 + <a href='<?php echo esc_url( $button_link ); ?>' class='button button-primary'><?php echo esc_html_e( 'Complete Setup', 'cartflows' ); ?></a>
189 + </div>
190 + <div class="wcf-right-column">
191 + <img src="<?php echo esc_url( CARTFLOWS_URL . 'admin/assets/images/cartflows-home-widget.svg' ); ?>" />
192 + </div>
193 + </div>
194 + </div>
195 + <?php
164 196 }
165 197
166 198 /**
167 - * Save Global Setting options.
199 + * Add the clone link to action list for flows row actions
168 200 *
169 - * @since 1.0.0
201 + * @param array $actions Actions array.
202 + * @param object $post Post object.
203 + *
204 + * @return array
170 205 */
171 - static public function save_common_settings() {
206 + public function remove_flow_actions( $actions, $post ) {
172 207
173 - if ( isset( $_POST['cartflows-common-settings-nonce'] ) && wp_verify_nonce( $_POST['cartflows-common-settings-nonce'], 'cartflows-common-settings' ) ) {
208 + if ( current_user_can( 'edit_posts' ) && isset( $post ) && CARTFLOWS_FLOW_POST_TYPE === $post->post_type ) {
174 209
175 - $url = $_SERVER['REQUEST_URI'];
176 - $input_settings = array();
177 - $new_settings = array();
210 + if ( isset( $actions['duplicate'] ) ) { // Duplicate page plugin remove.
211 + unset( $actions['duplicate'] );
212 + }
178 213
179 - if ( isset( $_POST['_cartflows_common'] ) ) {
180 -
181 - $input_settings = $_POST['_cartflows_common'];
182 -
183 - // Loop through the input and sanitize each of the values.
184 - foreach ( $input_settings as $key => $val ) {
185 -
186 - if ( is_array( $val ) ) {
187 - foreach ( $val as $k => $v ) {
188 - $new_settings[ $key ][ $k ] = ( isset( $val[ $k ] ) ) ? sanitize_text_field( $v ) : '';
189 - }
190 - } else {
191 - $new_settings[ $key ] = ( isset( $input_settings[ $key ] ) ) ? sanitize_text_field( $val ) : '';
192 - }
193 - }
214 + if ( isset( $actions['edit_as_new_draft'] ) ) { // Duplicate post plugin remove.
215 + unset( $actions['edit_as_new_draft'] );
194 216 }
217 + }
195 218
196 - Cartflows_Helper::update_admin_settings_option( '_cartflows_common', $new_settings, true );
219 + return $actions;
220 + }
197 221
198 - $query = array(
199 - 'message' => 'saved',
200 - );
222 + /**
223 + * After save of permalinks.
224 + */
225 + public static function flush_rules_after_save_permalinks() {
201 226
202 - $redirect_to = add_query_arg( $query, $url );
203 -
204 - wp_redirect( $redirect_to );
205 - exit;
206 - } // End if statement.
227 + $has_saved_permalinks = get_option( 'cartflows_permalink_refresh' );
228 + if ( $has_saved_permalinks ) {
229 + // Required to flush rules when permalink changes.
230 + flush_rewrite_rules(); //phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules
231 + delete_option( 'cartflows_permalink_refresh' );
232 + }
207 233 }
208 234
209 235 /**
210 - * Save Debug Setting options.
236 + * Show action on plugin page.
211 237 *
212 - * @since 1.1.14
238 + * @param array $links links.
239 + * @return array
213 240 */
214 - static public function save_debug_settings() {
241 + public function add_action_links( $links ) {
215 242
216 - if ( isset( $_POST['cartflows-debug-settings-nonce'] ) && wp_verify_nonce( $_POST['cartflows-debug-settings-nonce'], 'cartflows-debug-settings' ) ) {
243 + $mylinks = array(
244 + '<a target="_blank" href="' . esc_url(
245 + Cartflows_Helper::get_kb_doc_link(
246 + 'https://cartflows.com/docs/',
247 + array(
248 + 'utm_source' => 'plugin-page',
249 + 'utm_campaign' => 'go-pro',
250 + )
251 + )
252 + ) . '">' . __( 'Docs', 'cartflows' ) . '</a>',
253 + );
217 254
218 - $url = $_SERVER['REQUEST_URI'];
219 - $input_settings = array();
220 - $new_settings = array();
255 + if ( current_user_can( 'cartflows_manage_settings' ) ) {
221 256
222 - if ( isset( $_POST['_cartflows_debug_data'] ) ) {
257 + $is_legacy_admin = defined( 'CARTFLOWS_LEGACY_ADMIN' ) && CARTFLOWS_LEGACY_ADMIN;
223 258
224 - $input_settings = $_POST['_cartflows_debug_data'];
259 + $settings_args = array( 'page' => CARTFLOWS_SLUG );
225 260
226 - // Loop through the input and sanitize each of the values.
227 - foreach ( $input_settings as $key => $val ) {
261 + if ( $is_legacy_admin ) {
262 + $settings_args['settings'] = true;
263 + } else {
264 + $settings_args['path'] = 'settings';
265 + }
228 266
229 - if ( is_array( $val ) ) {
230 - foreach ( $val as $k => $v ) {
231 - $new_settings[ $key ][ $k ] = ( isset( $val[ $k ] ) ) ? sanitize_text_field( $v ) : '';
232 - }
233 - } else {
234 - $new_settings[ $key ] = ( isset( $input_settings[ $key ] ) ) ? sanitize_text_field( $val ) : '';
235 - }
236 - }
237 - }
267 + $default_url = add_query_arg( $settings_args, admin_url( 'admin.php' ) );
238 268
239 - Cartflows_Helper::update_admin_settings_option( '_cartflows_debug_data', $new_settings, true );
269 + array_unshift( $mylinks, '<a href="' . esc_url( $default_url ) . '">' . __( 'Settings', 'cartflows' ) . '</a>' );
270 + }
240 271
241 - $query = array(
242 - 'message' => 'saved',
272 + if ( ! _is_cartflows_pro() ) {
273 + array_push(
274 + $mylinks,
275 + '<a style="color: #39b54a; font-weight: 700;" target="_blank" href="' . esc_url(
276 + Cartflows_Helper::get_upgrade_to_pro_link( 'pricing', '', array( 'utm_source' => 'plugin-page' ) )
277 + ) . '"> ' . __( 'Get CartFlows Pro', 'cartflows' ) . ' </a>'
243 278 );
244 -
245 - $redirect_to = add_query_arg( $query, $url );
246 -
247 - wp_redirect( $redirect_to );
248 - exit;
249 -
250 279 }
251 - }
252 280
253 - /**
254 - * Check is cartflows admin.
255 - *
256 - * @since 1.0.0
257 - * @return boolean
258 - */
259 - static public function is_global_admin() {
260 -
261 - $current_screen = get_current_screen();
262 -
263 - if (
264 - is_object( $current_screen ) &&
265 - isset( $current_screen->post_type ) &&
266 - ( CARTFLOWS_FLOW_POST_TYPE === $current_screen->post_type ||
267 - CARTFLOWS_STEP_POST_TYPE === $current_screen->post_type
268 - )
269 - ) {
270 - return true;
271 - }
272 - return false;
281 + return array_merge( $links, $mylinks );
273 282 }
274 283
275 284 /**
276 285 * Check is flow admin.
@@ -277,9 +286,9 @@
277 286 *
278 287 * @since 1.0.0
279 288 * @return boolean
280 289 */
281 - static public function is_flow_edit_admin() {
290 + public static function is_flow_edit_admin() {
282 291
283 292 $current_screen = get_current_screen();
284 293
285 294 if (
@@ -294,197 +303,155 @@
294 303 return false;
295 304 }
296 305
297 306 /**
298 - * Global Admin Scripts.
307 + * Admin body classes.
299 308 *
300 - * @since 1.0.0
309 + * Body classes to be added to <body> tag in admin page
310 + *
311 + * @param String $classes body classes returned from the filter.
312 + * @return String body classes to be added to <body> tag in admin page
301 313 */
302 - static public function global_admin_scripts() {
314 + public function add_admin_body_class( $classes ) {
303 315
304 - $localize = array(
305 - 'ajaxurl' => admin_url( 'admin-ajax.php' ),
306 - 'ajax_nonce' => wp_create_nonce( 'cartflows-nonce' ),
307 - );
316 + $classes .= ' cartflows-' . CARTFLOWS_VER;
308 317
309 - wp_localize_script( 'jquery', 'cartflows_admin', apply_filters( 'cartflows_admin_js_localize', $localize ) );
318 + if ( isset( $_GET['action'] ) && 'wcf-license' === sanitize_text_field( wp_unslash( $_GET['action'] ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
319 + $classes .= ' wcf-debug-page ';
320 + }
310 321
311 - if ( self::is_global_admin() ) {
312 -
313 - // Styles.
314 - wp_enqueue_style( 'cartflows-global-admin', CARTFLOWS_URL . 'admin/assets/css/global-admin.css', array(), CARTFLOWS_VER );
315 - wp_style_add_data( 'cartflows-global-admin', 'rtl', 'replace' );
316 -
317 - wp_enqueue_script(
318 - 'wcf-global-admin',
319 - CARTFLOWS_URL . 'admin/assets/js/global-admin.js',
320 - array( 'jquery' ),
321 - CARTFLOWS_VER,
322 - true
323 - );
324 -
325 - do_action( 'cartflows_global_admin_scripts' );
326 - }
322 + return $classes;
327 323 }
328 324
329 325 /**
330 - * Global Admin Data.
326 + * Check allowed screen for notices.
331 327 *
332 328 * @since 1.0.0
329 + * @return bool
333 330 */
334 - static public function global_admin_data() {
331 + public function allowed_screen_for_notices() {
335 332
336 - $current_screen = get_current_screen();
333 + $screen = get_current_screen();
334 + $screen_id = $screen ? $screen->id : '';
335 + $allowed_screens = array(
336 + 'toplevel_page_cartflows',
337 + 'edit-cartflows_flow',
338 + );
337 339
338 - if ( ! $current_screen ) {
339 - return;
340 + if ( in_array( $screen_id, $allowed_screens, true ) ) {
341 + return true;
340 342 }
341 343
342 - if ( 'edit-' . CARTFLOWS_FLOW_POST_TYPE != $current_screen->id ) {
343 - return;
344 - }
345 -
346 - $default_page_builder = Cartflows_Helper::get_common_setting( 'default_page_builder' );
347 - ?>
348 -
349 - <div id="wcf-remote-flow-importer" class="wcf-templates-popup-overlay">
350 - <div class="wcf-templates-popup-content">
351 - <div class="spinner"></div>
352 - <div class="wcf-templates-wrap wcf-templates-wrap-flows">
353 -
354 - <div id="wcf-remote-flow-actions" class="wcf-template-header">
355 - <div class="wcf-template-logo-wrap">
356 - <span class="wcf-cartflows-logo-img">
357 - <span class="cartflows-logo-icon"></span>
358 - </span>
359 - <span class="wcf-cartflows-title"><?php _e( 'Flows Library', 'cartflows' ); ?></span>
360 - </div>
361 - <div class="wcf-tab-wrapper">
362 - <?php if ( 'other' !== $default_page_builder ) { ?>
363 - <div id="wcf-get-started-steps">
364 - <ul class="filter-links ">
365 - <li>
366 - <a href="#" class="current" data-slug="ready-templates" data-title="<?php _e( 'Ready Templates', 'cartflows' ); ?>"><?php _e( 'Ready Templates', 'cartflows' ); ?></a>
367 - </li>
368 - <li>
369 - <a href="#" data-slug="canvas" data-title="<?php _e( 'Create Your Own', 'cartflows' ); ?>"><?php _e( 'Create Your Own', 'cartflows' ); ?></a>
370 - </li>
371 - </ul>
372 - </div>
373 - <?php } ?>
374 - </div>
375 - <div class="wcf-popup-close-wrap">
376 - <span class="close-icon"><span class="wcf-cartflow-icons dashicons dashicons-no"></span></span>
377 - </div>
378 - </div>
379 - <!-- <div class="wcf-search-form">
380 - <label class="screen-reader-text" for="wp-filter-search-input"><?php _e( 'Search Sites', 'cartflows' ); ?> </label>
381 - <input placeholder="<?php _e( 'Search Flow...', 'cartflows' ); ?>" type="text" aria-describedby="live-search-desc" class="wcf-flow-search-input">
382 - </div> -->
383 -
384 - <div id="wcf-remote-content">
385 - <?php if ( 'other' !== $default_page_builder ) { ?>
386 - <div id="wcf-ready-templates">
387 - <div id="wcf-remote-filters">
388 - <div id="wcf-page-builders"></div>
389 - <div id="wcf-categories"></div>
390 - </div>
391 - <div class="wcf-page-builder-notice"></div>
392 - <div id="wcf-remote-flow-list" class="wcf-remote-list wcf-template-list-wrap"><span class="spinner is-active"></span></div>
393 - <div id="wcf-upcoming-page-builders" style="display: none;" class="wcf-remote-list wcf-template-list-wrap"></div>
394 - </div>
395 - <?php } ?>
396 - <div id="wcf-start-from-scratch" style="<?php echo ( 'other' !== $default_page_builder ) ? 'display: none;' : ''; ?>">
397 - <div class="inner">
398 - <a href="#" class="button button-hero button-primary cartflows-flow-import-blank"><?php _e( 'Design Your Flow', 'cartflows' ); ?></a>
399 - <p class="wcf-learn-how"><a href="https://cartflows.com/docs/cartflows-step-types/" target="_blank"><?php _e( 'Learn How', 'cartflows' ); ?> <i class="dashicons dashicons-external"></i></a></p>
400 - </div>
401 - </div>
402 - </div>
403 - </div>
404 - </div>
405 - </div>
406 -
407 - <?php
344 + return false;
408 345 }
409 346
410 347 /**
411 - * Enqueues the needed CSS/JS for the builder's admin settings page.
348 + * Function to add the meta and headers for not to cache the CartFlows wp-admin page.
412 349 *
413 - * @since 1.0.0
350 + * @return void
414 351 */
415 - static public function styles_scripts() {
352 + public function add_admin_cache_restrict_meta() {
416 353
417 - // Styles.
418 - wp_enqueue_style( 'cartflows-admin-settings', CARTFLOWS_URL . 'admin/assets/css/admin-menu-settings.css', array(), CARTFLOWS_VER );
419 - wp_style_add_data( 'cartflows-admin-settings', 'rtl', 'replace' );
354 + if ( ! $this->allowed_screen_for_notices() ) {
355 + return;
356 + }
420 357
421 - // Script.
422 - wp_enqueue_script( 'cartflows-admin-settings', CARTFLOWS_URL . 'admin/assets/js/admin-menu-settings.js', array( 'jquery', 'wp-util', 'updates' ), CARTFLOWS_VER );
423 -
424 - $localize = array(
425 - 'ajax_nonce' => wp_create_nonce( 'cartflows-widget-nonce' ),
426 - );
427 -
428 - wp_localize_script( 'cartflows-admin-settings', 'cartflows', apply_filters( 'cartflows_js_localize', $localize ) );
429 -
430 - do_action( 'cartflows_admin_settings_after_enqueue_scripts' );
358 + echo '<!-- Added by CartFlows -->';
359 + echo '<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Expires" content="0" />';
360 + echo '<!-- Added by CartFlows -->';
431 361 }
432 362
433 363 /**
434 - * Save All admin settings here
364 + * Function to add the Do Not Cache Constants on the CartFlows admin pages.
365 + *
366 + * @return void
435 367 */
436 - static public function save_settings() {
437 -
438 - // Only admins can save settings.
439 - if ( ! current_user_can( 'manage_options' ) ) {
440 - return;
368 + public function add_admin_cache_restrict_const() {
369 + // Ignoring nonce verification as using SuperGlobal variables on WordPress hooks.
370 + if ( isset( $_GET['page'] ) && ( 'cartflows' === sanitize_text_field( $_GET['page'] ) || false !== strpos( sanitize_text_field( $_GET['page'] ), 'cartflows_' ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
371 + wcf()->utils->get_cache_headers();
441 372 }
442 -
443 - self::save_common_settings();
444 - self::save_debug_settings();
445 -
446 - // Let extensions hook into saving.
447 - do_action( 'cartflows_admin_settings_save' );
448 373 }
449 374
450 375 /**
451 - * Get and return page URL
376 + * CartFlows version rollback.
452 377 *
453 - * @param string $menu_slug Menu name.
454 - * @since 1.0.0
455 - * @return string page url
378 + * Rollback to previous CartFlows version.
379 + *
380 + * Fired by `admin_post_cartflows_rollback` action.
381 + *
382 + * @since 2.1.6
383 + * @access public
384 + * @return void
456 385 */
457 - static public function get_page_url( $menu_slug ) {
386 + public function post_cartflows_rollback() {
458 387
459 - $parent_page = self::$default_menu_position;
388 + if ( ! current_user_can( 'install_plugins' ) ) {
389 + wp_die(
390 + esc_html__( 'You do not have permission to access this page.', 'cartflows' ),
391 + esc_html__( 'Rollback to Previous Version', 'cartflows' ),
392 + array(
393 + 'response' => 200,
394 + )
395 + );
396 + }
460 397
461 - if ( strpos( $parent_page, '?' ) !== false ) {
462 - $query_var = '&page=' . self::$plugin_slug;
463 - } else {
464 - $query_var = '?page=' . self::$plugin_slug;
398 + check_admin_referer( 'cartflows_rollback' );
399 +
400 + $rollback_versions = \Cartflows_Helper::get_rollback_versions();
401 + $update_version = isset( $_GET['version'] ) ? sanitize_text_field( $_GET['version'] ) : '';
402 +
403 + if ( empty( $update_version ) || ! in_array( $update_version, $rollback_versions, true ) ) {
404 + wp_die( esc_html__( 'Error occurred, The version selected is invalid. Try selecting different version.', 'cartflows' ) );
465 405 }
466 406
467 - $parent_page_url = admin_url( $parent_page . $query_var );
407 + $plugin_slug = basename( CARTFLOWS_FILE, '.php' );
468 408
469 - $url = $parent_page_url . '&action=' . $menu_slug;
409 + $rollback = new Cartflows_Rollback(
410 + array(
411 + 'version' => $update_version,
412 + 'plugin_name' => CARTFLOWS_BASE,
413 + 'plugin_slug' => $plugin_slug,
414 + 'package_url' => sprintf( 'https://downloads.wordpress.org/plugin/%s.%s.zip', $plugin_slug, $update_version ),
415 + )
416 + );
470 417
471 - return esc_url( $url );
418 + $rollback->run();
419 +
420 + wp_die(
421 + '',
422 + esc_html__( 'Rollback to Previous Version', 'cartflows' ),
423 + array(
424 + 'response' => 200,
425 + )
426 + );
472 427 }
473 428
474 429 /**
475 - * Admin body classes.
430 + * Provide CartFlows Pointer configuration via filter.
476 431 *
477 - * Body classes to be added to <body> tag in admin page
478 - *
479 - * @param String $classes body classes returned from the filter.
480 - * @return String body classes to be added to <body> tag in admin page
432 + * @param array<string, mixed> $config Existing configuration.
433 + * @return array<string, mixed> Pointer configuration.
481 434 */
482 - static public function add_admin_body_class( $classes ) {
483 -
484 - $classes .= ' cartflows-' . CARTFLOWS_VER;
485 -
486 - return $classes;
435 + public function get_pointer_config( $config ) {
436 + return array(
437 + 'option_name' => 'cartflows_pointer_data',
438 + 'title' => __( 'CartFlows is waiting for you!', 'cartflows' ),
439 + 'content' => sprintf(
440 + /* translators: %1$s opening <strong> tag, %2$s closing </strong> tag */
441 + __( '%1$sLaunch your first funnel in minutes.%2$s Follow a guided setup to start capturing leads or sales immediately.', 'cartflows' ),
442 + '<strong>',
443 + '</strong>'
444 + ),
445 + 'button_text' => __( 'Create My First Funnel', 'cartflows' ),
446 + 'button_url' => admin_url( 'admin.php?page=cartflows' ),
447 + 'dismiss_text' => __( 'Dismiss', 'cartflows' ),
448 + 'target_selector' => '#toplevel_page_cartflows',
449 + 'fallback_target' => '#menu-plugins',
450 + 'allowed_pages' => array( 'index.php', 'plugins.php' ),
451 + 'post_type' => CARTFLOWS_FLOW_POST_TYPE,
452 + 'max_posts' => 0,
453 + );
487 454 }
488 455 }
489 456
490 -Cartflows_Admin::init();
457 +Cartflows_Admin::get_instance();