PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 1.7.4
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v1.7.4
2.6.0 trunk 1.1.0 1.1.4 1.2.1 1.2.2 1.2.3 1.2.5 1.2.9 1.3.1 1.3.2 1.5.0 1.5.1 1.5.4 1.5.7 1.5.8 1.5.9 1.6.2 1.6.5 1.6.8 1.7.2 1.7.4 1.7.5 1.7.9 1.8.1 All 42 releases
sellkit / sellkit.php

sellkit.php in SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster 1.7.4, at sellkit.php

674 lines 14.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Sellkit
4 * Plugin URI: https://getsellkit.com/
5 * Description: Build unlimited sales funnels, one-click order bumps and upsells, custom thank you pages, and more. The free version of SellKit also offers a huge round of features to optimize your WooCommerce store: build and style single or multi-step checkout pages with advanced styling options. Add, remove & reorder form fields. Fasten the form submission process with pre-populated form data, Instant form validation, and removing cart page. All this and more is 100% free and for an unlimited number of sites.
6 * Version: 1.7.4
7 * Author: Artbees
8 * Author URI: https://artbees.net
9 * Text Domain: sellkit
10 * License: GPL2
11 *
12 * @package Sellkit
13 */
14
15 use Sellkit\Admin\Funnel\Funnel;
16 use Sellkit\Admin\Settings\Sellkit_Admin_Settings;
17 use Sellkit\Contact_Segmentation\Conditions;
18 use Sellkit\Contact_Segmentation\Operators;
19 use Sellkit\Core\Install;
20 use Sellkit\Database;
21 use Sellkit\Product_Meta_Key\Sellkit_Product_Meta_Key;
22
23 defined( 'ABSPATH' ) || die();
24
25 /**
26 * Check If sellkit Class exists.
27 *
28 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
29 */
30 if ( ! class_exists( 'Sellkit' ) ) {
31
32 /**
33 * SellKit class.
34 *
35 * @since 1.1.0
36 */
37 class Sellkit {
38
39 /**
40 * Class instance.
41 *
42 * @since 1.1.0
43 * @var Sellkit
44 */
45 private static $instance = null;
46
47 /**
48 * The plugin version number.
49 *
50 * @since 1.1.0
51 *
52 * @access private
53 * @var string
54 */
55 private static $version;
56
57 /**
58 * The plugin basename.
59 *
60 * @since 1.1.0
61 *
62 * @access private
63 * @var string
64 */
65 private static $plugin_basename;
66
67 /**
68 * The plugin name.
69 *
70 * @since 1.1.0
71 *
72 * @access private
73 * @var string
74 */
75 private static $plugin_name;
76
77 /**
78 * The plugin directory.
79 *
80 * @since 1.1.0
81 *
82 * @access private
83 * @var string
84 */
85 public static $plugin_dir;
86
87 /**
88 * The plugin URL.
89 *
90 * @since 1.1.0
91 *
92 * @access private
93 * @var string
94 */
95 private static $plugin_url;
96
97 /**
98 * The plugin assets URL.
99 *
100 * @since 1.1.0
101 * @access public
102 *
103 * @var string
104 */
105 public static $plugin_assets_url;
106
107 /**
108 * Database object.
109 *
110 * @since 1.1.0
111 * @access public
112 * @var Database
113 */
114 public $db;
115
116 /**
117 * Sellkit menus.
118 *
119 * @since 1.1.0
120 * @var array Sellkit menus.
121 */
122 public $sellkit_menus = [
123 'sellkit-dashboard',
124 'sellkit-funnel',
125 'sellkit-settings',
126 'sellkit-checkout',
127 ];
128
129 /**
130 * Has pro plugin or not.
131 *
132 * @since 1.1.0
133 * @var array Checks if has pro or not.
134 */
135 public $has_pro = false;
136
137 /**
138 * Get a class instance.
139 *
140 * @since 1.1.0
141 *
142 * @return Sellkit Class
143 */
144 public static function get_instance() {
145 if ( is_null( self::$instance ) ) {
146 self::$instance = new self();
147 }
148
149 return self::$instance;
150 }
151
152 /**
153 * Class constructor.
154 *
155 * @since 1.1.0
156 */
157 public function __construct() {
158 $this->define_constants();
159
160 $this->load_files( [
161 'db',
162 'functions',
163 'funnel/analytics/data-updater',
164 'global-checkout/class',
165 'funnel/class',
166 'funnel/contacts/base-contacts',
167 'funnel/steps',
168 ] );
169
170 $this->db = new Database();
171
172 add_action( 'plugins_loaded', [ $this, 'check_if_has_sellkit_pro' ], 11 );
173 add_action( 'plugins_loaded', [ $this, 'plugins_loaded' ] );
174 add_action( 'init', [ $this, 'init' ] );
175 add_action( 'admin_init', [ $this, 'admin_init' ] );
176 add_action( 'admin_menu', [ $this, 'register_admin_menu' ] );
177 add_action( 'admin_menu', [ $this, 'register_admin_settings_menu' ], 12 );
178
179 // Editor script.
180 add_action( 'elementor/editor/before_enqueue_scripts', [ $this, 'enqueue_editor_script' ] );
181
182 add_action( 'requests-curl.before_request', [ $this, 'actions_before_curl_requests' ], 9999 );
183
184 // Register activation hook.
185 register_activation_hook( __FILE__, array( $this, 'activation' ) );
186
187 if ( ! $this->is_sellkit_screen() ) {
188 return;
189 }
190
191 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_scripts' ] );
192 add_action( 'admin_head', [ $this, 'remove_notice_for_sellkit_pages' ] );
193 add_filter( 'admin_body_class', [ $this, 'sellkit_admin_body_class' ] );
194 }
195
196 /**
197 * Actions before all curl requests.
198 *
199 * @since 1.5.4
200 * @return void
201 */
202 public function actions_before_curl_requests() {
203 session_write_close();
204 }
205
206 /**
207 * Has sellKit pro.
208 *
209 * @since 1.1.0
210 */
211 public function check_if_has_sellkit_pro() {
212 if ( class_exists( 'Sellkit_Pro' ) ) {
213 $this->has_pro = true;
214 }
215 }
216
217 /**
218 * Defines constants used by the plugin.
219 *
220 * @since 1.1.0
221 */
222 protected function define_constants() {
223 $plugin_data = get_file_data( __FILE__, array( 'Plugin Name', 'Version' ), 'sellkit' );
224
225 self::$plugin_basename = plugin_basename( __FILE__ );
226 self::$plugin_name = array_shift( $plugin_data );
227 self::$version = array_shift( $plugin_data );
228 self::$plugin_dir = trailingslashit( plugin_dir_path( __FILE__ ) );
229 self::$plugin_url = trailingslashit( plugin_dir_url( __FILE__ ) );
230 self::$plugin_assets_url = trailingslashit( self::$plugin_url . 'assets' );
231 }
232
233 /**
234 * Plugins loaded.
235 *
236 * @since 1.1.0
237 */
238 public function plugins_loaded() {
239 $this->load_files( [
240 'elementor/class',
241 'admin/class-promote-sellkit-pro',
242 ] );
243 }
244
245 /**
246 * Do some stuff on plugin activation.
247 *
248 * @since NEXT
249 * @return void
250 */
251 public function activation() {
252 $this->load_files( [
253 'core/libraries/wp-async-request',
254 'core/libraries/wp-background-process',
255 'core/install',
256 ] );
257
258 Install::check_database_tables();
259
260 if ( empty( sellkit_get_option( 'current_db_version' ) ) ) {
261 sellkit_update_option( 'current_db_version', '1.2.7' ); // @since 1.5.0
262 }
263
264 if ( ! wp_next_scheduled( 'sellkit_update_rfm_score' ) ) {
265 wp_schedule_event( time(), 'twicedaily', 'sellkit_update_rfm_score' );
266 }
267
268 $this->sellkit_installed_time();
269 }
270
271 /**
272 * Saves sellkit installation time.
273 *
274 * @since 1.5.9
275 */
276 private function sellkit_installed_time() {
277 update_option( 'sellkit-installed-time', time() );
278 }
279
280 /**
281 * Adding sellkit class to body.
282 *
283 * @param string $classes Sellkit the sellkit class.
284 * @return string
285 */
286 public function sellkit_admin_body_class( $classes ) {
287 return "{$classes} sellkit";
288 }
289
290 /**
291 * Initialize admin.
292 *
293 * @since 1.1.0
294 */
295 public function admin_init() {
296 $this->load_files( [
297 'admin/class-notices',
298 'admin/class',
299 ] );
300
301 $this->load_files( [
302 'admin/utilities',
303 'admin/class-components',
304 'admin/components/class-list-table',
305 'admin/components/class-filters',
306 'admin/components/class-analytics',
307 'admin/class-posts',
308 'admin/settings/class-settings',
309 'admin/class-custom-tables',
310 'admin/funnel/class',
311 'admin/class-global-checkout',
312 'core/install',
313 ] );
314 }
315
316 /**
317 * Initialize.
318 *
319 * @since 1.1.0
320 */
321 public function init() {
322 $this->load_files( [
323 'admin/class-steps',
324 'utilities/functions',
325 'contact-segmentation/class',
326 'dynamic-keywords/class',
327 'core/libraries/wp-async-request',
328 'core/libraries/wp-background-process',
329 'settings/class',
330 'contact-segmentation/rfm/class',
331 'admin/settings/integration/class',
332 ] );
333
334 // Register post types.
335 $post_types = [
336 // 'sellkit-analytics',
337 'sellkit-funnels',
338 ];
339
340 foreach ( $post_types as $post_type ) {
341 register_post_type( $post_type, [
342 'public' => false,
343 ] );
344 }
345
346 load_plugin_textdomain( 'sellkit', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
347 }
348
349 /**
350 * Enqueue editor scripts.
351 *
352 * @since 1.1.0
353 * @return void
354 */
355 public function enqueue_editor_script() {
356 wp_enqueue_script(
357 'sellkit-editor',
358 sellkit()->plugin_url() . 'assets/dist/js/editor.min.js',
359 [ 'jquery' ],
360 self::$version,
361 true
362 );
363 }
364
365 /**
366 * Enqueue admin scripts.
367 *
368 * @since 1.1.0
369 */
370 public function enqueue_admin_scripts() {
371 $page = ! empty( $_GET['page'] ) ? $_GET['page'] : ''; // phpcs:ignore
372
373 if ( ! in_array( $page, $this->sellkit_menus, true ) ) {
374 return false;
375 }
376
377 wp_enqueue_editor();
378
379 wp_enqueue_script(
380 'sellkit',
381 sellkit()->plugin_url() . 'assets/dist/admin/sellkit.js',
382 [ 'lodash', 'wp-element', 'wp-i18n', 'wp-util' ],
383 sellkit()->version(),
384 true
385 );
386
387 wp_localize_script(
388 'sellkit',
389 'sellkit',
390 $this->get_localize_data()
391 );
392
393 wp_enqueue_style(
394 'sellkit',
395 sellkit()->plugin_url() . 'assets/dist/admin/sellkit.css',
396 [],
397 sellkit()->version()
398 );
399
400 wp_set_script_translations( 'sellkit', 'sellkit', sellkit()->plugin_dir() . 'languages' );
401 }
402
403 /**
404 * Register admin menu.
405 *
406 * @since 1.1.0
407 * @SuppressWarnings(PHPMD.NPathComplexity)
408 */
409 public function register_admin_menu() {
410 $menu_name = esc_html__( 'Sellkit', 'sellkit' );
411 $initial_page = 'sellkit-dashboard';
412 $submenu = [
413 'sellkit-dashboard' => esc_html__( 'Dashboard', 'sellkit' ),
414 'sellkit-funnel' => esc_html__( 'Funnels', 'sellkit' ),
415 'sellkit-checkout' => esc_html__( 'Global Checkout', 'sellkit' ),
416 ];
417
418 $submenu = apply_filters( 'sellkit_sub_menu', $submenu );
419
420 $svg_file = wp_remote_get( self::plugin_url() . 'assets/img/icons/sellkit-dashboard.svg' );
421
422 add_menu_page(
423 $menu_name,
424 $menu_name,
425 'manage_options',
426 $initial_page,
427 [ $this, 'register_admin_menu_callback' ],
428 'data:image/svg+xml;base64,' . base64_encode( wp_remote_retrieve_body( $svg_file ) ),
429 '58.1'
430 );
431
432 foreach ( $submenu as $slug => $title ) {
433 add_submenu_page(
434 $initial_page,
435 "{$menu_name} {$title}",
436 $title,
437 'edit_theme_options',
438 $slug,
439 [ $this, 'register_admin_menu_callback' ]
440 );
441 }
442 }
443
444 /**
445 * Adds settings menu.
446 *
447 * @since 1.1.0
448 */
449 public function register_admin_settings_menu() {
450 add_submenu_page(
451 'sellkit-dashboard',
452 esc_html__( 'Sellkit', 'sellkit' ) . ' ' . esc_html__( 'Settings', 'sellkit' ),
453 esc_html__( 'Settings', 'sellkit' ),
454 'edit_theme_options',
455 'sellkit-settings',
456 [ $this, 'register_admin_menu_callback' ]
457 );
458 }
459
460 /**
461 * Register admin menu callback.
462 *
463 * @since 1.1.0
464 */
465 public function register_admin_menu_callback() {
466 ?>
467 <div id="wrap" class="wrap">
468 <!-- It's required for notices, otherwise WP adds the notices wherever it finds the first heading element. -->
469 <h1></h1>
470 <div id="sellkit-root"></div>
471 </div>
472 <?php
473 }
474
475 /**
476 * Check if in SellKit pages.
477 *
478 * @since 1.1.0
479 *
480 * @return boolean SellKit screen.
481 */
482 private function is_sellkit_screen() {
483 $page = sellkit_htmlspecialchars( INPUT_GET, 'page' );
484
485 return (
486 is_admin() &&
487 isset( $page ) &&
488 strpos( $page, 'sellkit' ) !== false
489 );
490 }
491
492 /**
493 * Get localize data.
494 *
495 * @since 1.1.0
496 *
497 * @return array
498 */
499 public function get_localize_data() {
500 return [
501 'nonce' => wp_create_nonce( 'sellkit' ),
502 'assetsUrl' => self::$plugin_assets_url,
503 'dynamicKeywords' => Sellkit_Dynamic_Keywords::$keywords['contact_segmentation'],
504 'defaultFunnelSteps' => Sellkit_Admin_Steps::get_default_funnel_steps(),
505 'woocommerceSettings' => $this->get_woocommerce_settings_data(),
506 'contactSegmentation' => [
507 'conditionsOperators' => Operators::$condition_operator_names,
508 'operators' => Operators::$names,
509 'conditionsData' => Conditions::$data,
510 'browserLanguages' => Conditions\Browser_Language::browser_languages_array(),
511 ],
512 'adminUrl' => admin_url(),
513 'url' => site_url(),
514 'timezones' => timezone_identifiers_list(),
515 'defaultSettings' => [
516 'defaultTimezone' => get_option( 'timezone_string' ),
517 ],
518 'elementorActivation' => class_exists( 'Elementor\Plugin' ) ? true : false,
519 'funnelsTemplateSource' => Funnel::SELLKIT_FUNNELS_TEMPLATE_SOURCE,
520 'removedContentBoxes' => Sellkit_Admin_Settings::get_removed_content_box(),
521 'sellkitProIsActive' => $this->has_pro,
522 'wcIsActivated' => $this->has_valid_dependencies(),
523 'activeTheme' => wp_get_theme()->get( 'Name' ),
524 ];
525 }
526
527 /**
528 * Get woocommerce settings data.
529 *
530 * @since 1.1.0
531 *
532 * @return array|boolean
533 */
534 public function get_woocommerce_settings_data() {
535 if ( ! class_exists( 'WooCommerce' ) ) {
536 return false;
537 }
538
539 return [
540 'currencyFormatNumDecimals' => wc_get_price_decimals(),
541 'currencySymbol' => html_entity_decode( get_woocommerce_currency_symbol() ),
542 'currencyFormatDecimalSep' => wc_get_price_decimal_separator(),
543 'currencyFormatThousandSep' => wc_get_price_thousand_separator(),
544 'currencyPosition' => get_option( 'woocommerce_currency_pos' ),
545 'productDefaultThumbnail' => wc_placeholder_img_src(),
546 ];
547 }
548
549 /**
550 * Remove notices.
551 *
552 * @since 1.1.0
553 */
554 public function remove_notice_for_sellkit_pages() {
555 remove_all_actions( 'admin_notices' );
556 }
557
558 /**
559 * Sellkit dependencies.
560 *
561 * @since 1.1.0
562 */
563 public function has_valid_dependencies() {
564 if ( ! class_exists( 'woocommerce' ) ) {
565 return false;
566 }
567
568 return true;
569 }
570
571 /**
572 * Loads specified PHP files from the plugin includes directory.
573 *
574 * @since 1.1.0
575 *
576 * @param array $file_names The names of the files to be loaded in the includes directory.
577 */
578 public function load_files( $file_names = array() ) {
579
580 foreach ( $file_names as $file_name ) {
581 $path = self::plugin_dir() . 'includes/' . $file_name . '.php';
582
583 if ( file_exists( $path ) ) {
584 require_once $path;
585 }
586 }
587 }
588
589 /**
590 * Returns the version number of the plugin.
591 *
592 * @since 1.1.0
593 *
594 * @return string
595 */
596 public function version() {
597 return self::$version;
598 }
599
600 /**
601 * Returns the plugin basename.
602 *
603 * @since 1.1.0
604 *
605 * @return string
606 */
607 public function plugin_basename() {
608 return self::$plugin_basename;
609 }
610
611 /**
612 * Returns the plugin name.
613 *
614 * @since 1.1.0
615 *
616 * @return string
617 */
618 public function plugin_name() {
619 return self::$plugin_name;
620 }
621
622 /**
623 * Returns the plugin directory.
624 *
625 * @since 1.1.0
626 *
627 * @return string
628 */
629 public function plugin_dir() {
630 return self::$plugin_dir;
631 }
632
633 /**
634 * Returns the plugin URL.
635 *
636 * @since 1.1.0
637 *
638 * @return string
639 */
640 public function plugin_url() {
641 return self::$plugin_url;
642 }
643
644 /**
645 * Returns the plugin assets URL.
646 *
647 * @since 1.1.0
648 *
649 * @return string
650 */
651 public function plugin_assets_url() {
652 return self::$plugin_assets_url;
653 }
654 }
655 }
656
657 if ( ! function_exists( 'sellkit' ) ) {
658 /**
659 * Initialize the Sellkit.
660 *
661 * @since 1.1.0
662 */
663 function sellkit() {
664 return Sellkit::get_instance();
665 }
666 }
667
668 /**
669 * Initialize the Sellkit application.
670 *
671 * @since 1.1.0
672 */
673 sellkit();
674