PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 2.3.2
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v2.3.2
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 2.3.2, at sellkit.php

720 lines 15.6 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: 2.3.2
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/redirect',
164 'funnel/homepage',
165 'funnel/analytics/data-updater',
166 'global-checkout/class',
167 'funnel/class',
168 'funnel/contacts/base-contacts',
169 'funnel/steps',
170 ] );
171
172 if ( class_exists( 'SitePress' ) ) {
173 $this->load_files([
174 'compatibility/wpml/module',
175 'compatibility/module',
176 ] );
177 }
178
179 $this->db = new Database();
180
181 add_action( 'plugins_loaded', [ $this, 'check_if_has_sellkit_pro' ], 11 );
182 add_action( 'plugins_loaded', [ $this, 'plugins_loaded' ] );
183 add_action( 'init', [ $this, 'init' ] );
184 add_action( 'admin_init', [ $this, 'admin_init' ] );
185 add_action( 'admin_menu', [ $this, 'register_admin_menu' ] );
186 add_action( 'admin_menu', [ $this, 'register_admin_settings_menu' ], 12 );
187
188 // Editor script.
189 add_action( 'elementor/editor/before_enqueue_scripts', [ $this, 'enqueue_editor_script' ] );
190
191 add_action( 'requests-curl.before_request', [ $this, 'actions_before_curl_requests' ], 9999 );
192
193 // Register activation hook.
194 register_activation_hook( __FILE__, array( $this, 'activation' ) );
195
196 if ( ! $this->is_sellkit_screen() ) {
197 return;
198 }
199
200 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_scripts' ] );
201 add_action( 'admin_head', [ $this, 'remove_notice_for_sellkit_pages' ] );
202 add_filter( 'admin_body_class', [ $this, 'sellkit_admin_body_class' ] );
203 }
204
205 /**
206 * Actions before all curl requests.
207 *
208 * @since 1.5.4
209 * @return void
210 */
211 public function actions_before_curl_requests() {
212 session_write_close();
213 }
214
215 /**
216 * Has sellKit pro.
217 *
218 * @since 1.1.0
219 */
220 public function check_if_has_sellkit_pro() {
221 if ( class_exists( 'Sellkit_Pro' ) ) {
222 $this->has_pro = true;
223 }
224 }
225
226 /**
227 * Defines constants used by the plugin.
228 *
229 * @since 1.1.0
230 */
231 protected function define_constants() {
232 $plugin_data = get_file_data( __FILE__, array( 'Plugin Name', 'Version' ), 'sellkit' );
233
234 self::$plugin_basename = plugin_basename( __FILE__ );
235 self::$plugin_name = array_shift( $plugin_data );
236 self::$version = array_shift( $plugin_data );
237 self::$plugin_dir = trailingslashit( plugin_dir_path( __FILE__ ) );
238 self::$plugin_url = trailingslashit( plugin_dir_url( __FILE__ ) );
239 self::$plugin_assets_url = trailingslashit( self::$plugin_url . 'assets' );
240 }
241
242 /**
243 * Plugins loaded.
244 *
245 * @since 1.1.0
246 */
247 public function plugins_loaded() {
248 if ( 'elementor' === $this->page_builder() ) {
249 $this->load_files( [
250 'elementor/class',
251 ] );
252 }
253
254 $this->load_files( [
255 'admin/class-promote-sellkit-pro',
256 ] );
257
258 if ( class_exists( 'WooCommerce' ) && 'gutenberg' === $this->page_builder() ) {
259 $this->load_files( [
260 'block-editor/helper',
261 'block-editor/class',
262 ] );
263 }
264 }
265
266 /**
267 * Do some stuff on plugin activation.
268 *
269 * @since NEXT
270 * @return void
271 */
272 public function activation() {
273 $this->load_files( [
274 'core/libraries/wp-async-request',
275 'core/libraries/wp-background-process',
276 'core/install',
277 ] );
278
279 Install::check_database_tables();
280
281 if ( empty( sellkit_get_option( 'current_db_version' ) ) ) {
282 sellkit_update_option( 'current_db_version', '1.2.7' ); // @since 1.5.0
283 }
284
285 if ( ! wp_next_scheduled( 'sellkit_update_rfm_score' ) ) {
286 wp_schedule_event( time(), 'twicedaily', 'sellkit_update_rfm_score' );
287 }
288
289 $this->sellkit_installed_time();
290 }
291
292 /**
293 * Saves sellkit installation time.
294 *
295 * @since 1.5.9
296 */
297 private function sellkit_installed_time() {
298 update_option( 'sellkit-installed-time', time() );
299 }
300
301 /**
302 * Adding sellkit class to body.
303 *
304 * @param string $classes Sellkit the sellkit class.
305 * @return string
306 */
307 public function sellkit_admin_body_class( $classes ) {
308 return "{$classes} sellkit";
309 }
310
311 /**
312 * Initialize admin.
313 *
314 * @since 1.1.0
315 */
316 public function admin_init() {
317 $this->load_files( [
318 'admin/class-notices',
319 'admin/class',
320 ] );
321
322 $this->load_files( [
323 'admin/utilities',
324 'admin/class-components',
325 'admin/components/class-list-table',
326 'admin/components/class-filters',
327 'admin/components/class-analytics',
328 'admin/class-posts',
329 'admin/settings/class-settings',
330 'admin/class-custom-tables',
331 'admin/funnel/class',
332 'admin/class-global-checkout',
333 'core/install',
334 ] );
335 }
336
337 /**
338 * Initialize.
339 *
340 * @since 1.1.0
341 */
342 public function init() {
343 $this->load_files( [
344 'admin/class-steps',
345 'utilities/functions',
346 'contact-segmentation/class',
347 'dynamic-keywords/class',
348 'core/libraries/wp-async-request',
349 'core/libraries/wp-background-process',
350 'settings/class',
351 'contact-segmentation/rfm/class',
352 'admin/settings/integration/class',
353 ] );
354
355 // Register post types.
356 $post_types = [
357 // 'sellkit-analytics',
358 'sellkit-funnels',
359 ];
360
361 foreach ( $post_types as $post_type ) {
362 register_post_type( $post_type, [
363 'public' => false,
364 ] );
365 }
366
367 load_plugin_textdomain( 'sellkit', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
368 }
369
370 /**
371 * Enqueue editor scripts.
372 *
373 * @since 1.1.0
374 * @return void
375 */
376 public function enqueue_editor_script() {
377 wp_enqueue_script(
378 'sellkit-editor',
379 sellkit()->plugin_url() . 'assets/dist/js/editor.min.js',
380 [ 'jquery' ],
381 self::$version,
382 true
383 );
384 }
385
386 /**
387 * Enqueue admin scripts.
388 *
389 * @since 1.1.0
390 */
391 public function enqueue_admin_scripts() {
392 $page = ! empty( $_GET['page'] ) ? $_GET['page'] : ''; // phpcs:ignore
393
394 if ( ! in_array( $page, $this->sellkit_menus, true ) ) {
395 return false;
396 }
397
398 wp_enqueue_editor();
399
400 wp_enqueue_script(
401 'sellkit',
402 sellkit()->plugin_url() . 'assets/dist/admin/sellkit.js',
403 [ 'lodash', 'wp-element', 'wp-i18n', 'wp-util' ],
404 sellkit()->version(),
405 true
406 );
407
408 wp_localize_script(
409 'sellkit',
410 'sellkit',
411 $this->get_localize_data()
412 );
413
414 wp_enqueue_style(
415 'sellkit',
416 sellkit()->plugin_url() . 'assets/dist/admin/sellkit.css',
417 [],
418 sellkit()->version()
419 );
420
421 wp_set_script_translations( 'sellkit', 'sellkit', sellkit()->plugin_dir() . 'languages' );
422 }
423
424 /**
425 * Register admin menu.
426 *
427 * @since 1.1.0
428 * @SuppressWarnings(PHPMD.NPathComplexity)
429 */
430 public function register_admin_menu() {
431 $menu_name = esc_html__( 'Sellkit', 'sellkit' );
432 $initial_page = 'sellkit-dashboard';
433 $submenu = [
434 'sellkit-dashboard' => esc_html__( 'Dashboard', 'sellkit' ),
435 'sellkit-funnel' => esc_html__( 'Funnels', 'sellkit' ),
436 'sellkit-checkout' => esc_html__( 'Global Checkout', 'sellkit' ),
437 ];
438
439 $submenu = apply_filters( 'sellkit_sub_menu', $submenu );
440
441 $svg_file = wp_remote_get( self::plugin_url() . 'assets/img/icons/sellkit-dashboard.svg' );
442
443 add_menu_page(
444 $menu_name,
445 $menu_name,
446 'manage_options',
447 $initial_page,
448 [ $this, 'register_admin_menu_callback' ],
449 'data:image/svg+xml;base64,' . base64_encode( wp_remote_retrieve_body( $svg_file ) ),
450 '58.1'
451 );
452
453 foreach ( $submenu as $slug => $title ) {
454 add_submenu_page(
455 $initial_page,
456 "{$menu_name} {$title}",
457 $title,
458 'edit_theme_options',
459 $slug,
460 [ $this, 'register_admin_menu_callback' ]
461 );
462 }
463 }
464
465 /**
466 * Adds settings menu.
467 *
468 * @since 1.1.0
469 */
470 public function register_admin_settings_menu() {
471 add_submenu_page(
472 'sellkit-dashboard',
473 esc_html__( 'Sellkit', 'sellkit' ) . ' ' . esc_html__( 'Settings', 'sellkit' ),
474 esc_html__( 'Settings', 'sellkit' ),
475 'edit_theme_options',
476 'sellkit-settings',
477 [ $this, 'register_admin_menu_callback' ]
478 );
479 }
480
481 /**
482 * Register admin menu callback.
483 *
484 * @since 1.1.0
485 */
486 public function register_admin_menu_callback() {
487 ?>
488 <div id="wrap" class="wrap">
489 <!-- It's required for notices, otherwise WP adds the notices wherever it finds the first heading element. -->
490 <h1></h1>
491 <div id="sellkit-root"></div>
492 </div>
493 <?php
494 }
495
496 /**
497 * Check if in SellKit pages.
498 *
499 * @since 1.1.0
500 *
501 * @return boolean SellKit screen.
502 */
503 private function is_sellkit_screen() {
504 $page = sellkit_htmlspecialchars( INPUT_GET, 'page' );
505
506 return (
507 is_admin() &&
508 isset( $page ) &&
509 strpos( $page, 'sellkit' ) !== false
510 );
511 }
512
513 /**
514 * Get localize data.
515 *
516 * @since 1.1.0
517 *
518 * @return array
519 */
520 public function get_localize_data() {
521 return [
522 'nonce' => wp_create_nonce( 'sellkit' ),
523 'assetsUrl' => self::$plugin_assets_url,
524 'dynamicKeywords' => Sellkit_Dynamic_Keywords::$keywords['contact_segmentation'],
525 'defaultFunnelSteps' => Sellkit_Admin_Steps::get_default_funnel_steps(),
526 'woocommerceSettings' => $this->get_woocommerce_settings_data(),
527 'contactSegmentation' => [
528 'conditionsOperators' => Operators::$condition_operator_names,
529 'operators' => Operators::$names,
530 'conditionsData' => Conditions::$data,
531 'browserLanguages' => Conditions\Browser_Language::browser_languages_array(),
532 ],
533 'adminUrl' => admin_url(),
534 'url' => site_url(),
535 'timezones' => timezone_identifiers_list(),
536 'defaultSettings' => [
537 'defaultTimezone' => get_option( 'timezone_string' ),
538 ],
539 'elementorActivation' => class_exists( 'Elementor\Plugin' ) ? true : false,
540 'funnelsTemplateSource' => Funnel::SELLKIT_FUNNELS_TEMPLATE_SOURCE,
541 'removedContentBoxes' => Sellkit_Admin_Settings::get_removed_content_box(),
542 'sellkitProIsActive' => $this->has_pro,
543 'wcIsActivated' => $this->has_valid_dependencies(),
544 'activeTheme' => wp_get_theme()->get( 'Name' ),
545 'pageBuilder' => $this->page_builder(),
546 ];
547 }
548
549 /**
550 * Get page builder.
551 *
552 * @since 2.3.0
553 * @return string
554 */
555 public function page_builder() {
556 $default = 'gutenberg';
557
558 if ( class_exists( 'Elementor\Plugin' ) ) {
559 $default = 'elementor';
560 }
561
562 $page_builder = sellkit_get_option( 'page_builder', '' );
563
564 if ( empty( $page_builder ) ) {
565 sellkit_update_option( 'page_builder', $default );
566
567 return $default;
568 }
569
570 return $page_builder;
571 }
572
573 /**
574 * Get woocommerce settings data.
575 *
576 * @since 1.1.0
577 *
578 * @return array|boolean
579 */
580 public function get_woocommerce_settings_data() {
581 if ( ! class_exists( 'WooCommerce' ) ) {
582 return false;
583 }
584
585 return [
586 'currencyFormatNumDecimals' => wc_get_price_decimals(),
587 'currencySymbol' => html_entity_decode( get_woocommerce_currency_symbol() ),
588 'currencyFormatDecimalSep' => wc_get_price_decimal_separator(),
589 'currencyFormatThousandSep' => wc_get_price_thousand_separator(),
590 'currencyPosition' => get_option( 'woocommerce_currency_pos' ),
591 'productDefaultThumbnail' => wc_placeholder_img_src(),
592 ];
593 }
594
595 /**
596 * Remove notices.
597 *
598 * @since 1.1.0
599 */
600 public function remove_notice_for_sellkit_pages() {
601 remove_all_actions( 'admin_notices' );
602 }
603
604 /**
605 * Sellkit dependencies.
606 *
607 * @since 1.1.0
608 */
609 public function has_valid_dependencies() {
610 if ( ! class_exists( 'woocommerce' ) ) {
611 return false;
612 }
613
614 return true;
615 }
616
617 /**
618 * Loads specified PHP files from the plugin includes directory.
619 *
620 * @since 1.1.0
621 *
622 * @param array $file_names The names of the files to be loaded in the includes directory.
623 */
624 public function load_files( $file_names = array() ) {
625
626 foreach ( $file_names as $file_name ) {
627 $path = self::plugin_dir() . 'includes/' . $file_name . '.php';
628
629 if ( file_exists( $path ) ) {
630 require_once $path;
631 }
632 }
633 }
634
635 /**
636 * Returns the version number of the plugin.
637 *
638 * @since 1.1.0
639 *
640 * @return string
641 */
642 public function version() {
643 return self::$version;
644 }
645
646 /**
647 * Returns the plugin basename.
648 *
649 * @since 1.1.0
650 *
651 * @return string
652 */
653 public function plugin_basename() {
654 return self::$plugin_basename;
655 }
656
657 /**
658 * Returns the plugin name.
659 *
660 * @since 1.1.0
661 *
662 * @return string
663 */
664 public function plugin_name() {
665 return self::$plugin_name;
666 }
667
668 /**
669 * Returns the plugin directory.
670 *
671 * @since 1.1.0
672 *
673 * @return string
674 */
675 public function plugin_dir() {
676 return self::$plugin_dir;
677 }
678
679 /**
680 * Returns the plugin URL.
681 *
682 * @since 1.1.0
683 *
684 * @return string
685 */
686 public function plugin_url() {
687 return self::$plugin_url;
688 }
689
690 /**
691 * Returns the plugin assets URL.
692 *
693 * @since 1.1.0
694 *
695 * @return string
696 */
697 public function plugin_assets_url() {
698 return self::$plugin_assets_url;
699 }
700 }
701 }
702
703 if ( ! function_exists( 'sellkit' ) ) {
704 /**
705 * Initialize the Sellkit.
706 *
707 * @since 1.1.0
708 */
709 function sellkit() {
710 return Sellkit::get_instance();
711 }
712 }
713
714 /**
715 * Initialize the Sellkit application.
716 *
717 * @since 1.1.0
718 */
719 sellkit();
720