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

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