PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.28
Booktics – Appointment Booking Calendar for Service Businesses v1.0.28
1.0.29 1.0.28 1.0.27 1.0.26 1.0.25 1.0.24 1.0.23 1.0.22 1.0.21 1.0.20 1.0.19 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.2 1.0.3 All 31 releases
← All changes | utils/global-helper.php +203 -29 1.0.19 → 1.0.28 View file →
@@ -1,6 +1,11 @@
1 1 <?php
2 -if ( ! defined( 'ABSPATH' ) ) exit;
2 +if ( ! defined( 'ABSPATH' ) ) {
3 + // Composer autoloads this file, so CLI tooling loads it without WordPress.
4 + if ( PHP_SAPI !== 'cli' ) {
5 + exit;
6 + }
7 +}
3 8 /**
4 9 * Get timezone list.
5 10 *
6 11 * @return array
@@ -273,44 +278,30 @@
273 278
274 279 if ( ! function_exists( 'booktics_is_woocommerce_active' ) ) {
275 280
276 281 /**
277 - * Check woocommerce is active or not
282 + * Check whether WooCommerce payments are usable.
278 283 *
284 + * True only when WooCommerce itself is running, the module is enabled and
285 + * the payment setting is on. Any one of the three being false means the
286 + * gateway must not be offered.
287 + *
279 288 * @return bool
280 289 */
281 290 function booktics_is_woocommerce_active() {
291 + if ( ! class_exists( 'WooCommerce' ) ) {
292 + return false;
293 + }
282 294
283 - if ( function_exists( 'WC' ) && booktics_get_option( 'wc_integration' ) ) {
284 - return true;
295 + if ( ! booktics_extension()->is_enabled( 'woocommerce' ) ) {
296 + return false;
285 297 }
286 298
287 - return false;
299 + return (bool) booktics_get_option( 'enable_woocommerce_payment' );
288 300 }
289 301 }
290 302
291 -if ( ! function_exists( 'booktics_add_woocommerce_product_cat' ) ) {
292 - /**
293 - * Add woocommerce product category
294 - *
295 - * @return void
296 - */
297 - function booktics_add_woocommerce_product_cat() {
298 - $category_name = __( 'Booktics Meeting', 'booktics' );
299 303
300 - // Prepare category arguments
301 - $category_args = array(
302 - 'taxonomy' => 'product_cat',
303 - 'cat_name' => $category_name,
304 - 'category_description' => __( 'Booktics meeting', 'booktics' ),
305 - 'slug' => 'booktics-meeting',
306 - );
307 -
308 - // Insert the category
309 - wp_insert_term( $category_args['cat_name'], $category_args['taxonomy'], $category_args );
310 - }
311 -}
312 -
313 304 if ( ! function_exists( 'booktics_is_valid_timezone' ) ) {
314 305 /**
315 306 * Check a timezone is valid or not
316 307 *
@@ -650,12 +641,28 @@
650 641 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-stripe',
651 642 'settings_link' => '',
652 643 'doc_link' => 'https://docs.arraytics.com/docs/booktics/payment-type/how-to-configure-the-stripe-in-booktics/',
653 644 ),
645 + 'woocommerce' => array(
646 + 'name' => 'woocommerce',
647 + 'slug' => 'woocommerce',
648 + 'type' => 'module',
649 + 'upgrade' => true,
650 + 'upgrade_link' => 'https://themewinter.com/purchase-history',
651 + 'status' => 'off',
652 + 'is_pro' => false,
653 + 'title' => __( 'WooCommerce', 'booktics' ),
654 + 'description' => __( 'Take booking payments through WooCommerce checkout.', 'booktics' ),
655 + 'icon' => \Booktics\Extensions\Extension_Icon::get( 'woocommerce-addon' ),
656 + 'notice' => '',
657 + 'demo_link' => '',
658 + 'settings_link' => '',
659 + 'doc_link' => 'https://arraytics.com/docs/docs/booktics/integration/woocommerce-payment-in-booktics-setup-guide/',
660 + ),
654 661 'fluentcrm' => array(
655 662 'name' => 'fluentcrm',
656 663 'slug' => 'fluentcrm',
657 - 'type' => 'module',
664 + 'type' => 'integration',
658 665 'upgrade' => true,
659 666 'upgrade_link' => 'https://themewinter.com/purchase-history',
660 667 'status' => 'off',
661 668 'is_pro' => false,
@@ -664,10 +671,75 @@
664 671 'icon' => \Booktics\Extensions\Extension_Icon::get( 'booktics-fluentcrm-addon' ),
665 672 'notice' => '',
666 673 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-fluentcrm',
667 674 'settings_link' => '',
668 - 'doc_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-google-calendar',
675 + 'doc_link' => 'https://docs.arraytics.com/docs/booktics/integration/how-to-integrate-fluentcrm-with-booktics/',
669 676 ),
677 + 'pabbly' => array(
678 + 'name' => 'pabbly',
679 + 'slug' => 'pabbly',
680 + 'type' => 'integration',
681 + 'upgrade' => true,
682 + 'upgrade_link' => 'https://themewinter.com/purchase-history',
683 + 'status' => 'off',
684 + 'is_pro' => false,
685 + 'title' => __( 'Pabbly', 'booktics' ),
686 + 'description' => __( 'Send booking data to Pabbly Connect via webhook.', 'booktics' ),
687 + 'icon' => \Booktics\Extensions\Extension_Icon::get( 'booktics-pabbly-addon' ),
688 + 'notice' => '',
689 + 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-pabbly',
690 + 'settings_link' => '',
691 + 'doc_link' => 'https://docs.arraytics.com/docs/booktics/integration/how-to-integrate-booktics-with-pabbly/',
692 + ),
693 + 'zapier' => array(
694 + 'name' => 'zapier',
695 + 'slug' => 'zapier',
696 + 'type' => 'integration',
697 + 'upgrade' => true,
698 + 'upgrade_link' => 'https://themewinter.com/purchase-history',
699 + 'status' => 'off',
700 + 'is_pro' => false,
701 + 'title' => __( 'Zapier', 'booktics' ),
702 + 'description' => __( 'Send booking data to Zapier via webhook.', 'booktics' ),
703 + 'icon' => \Booktics\Extensions\Extension_Icon::get( 'booktics-zapier-addon' ),
704 + 'notice' => '',
705 + 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-zapier',
706 + 'settings_link' => '',
707 + 'doc_link' => 'https://docs.arraytics.com/docs/booktics/integration/how-to-integrate-booktics-with-zapier/',
708 + ),
709 + 'zoho' => array(
710 + 'name' => 'zoho',
711 + 'slug' => 'zoho',
712 + 'type' => 'integration',
713 + 'upgrade' => true,
714 + 'upgrade_link' => 'https://themewinter.com/purchase-history',
715 + 'status' => 'off',
716 + 'is_pro' => false,
717 + 'title' => __( 'Zoho', 'booktics' ),
718 + 'description' => __( 'Send booking data to Zoho via webhook.', 'booktics' ),
719 + 'icon' => \Booktics\Extensions\Extension_Icon::get( 'booktics-zoho-addon' ),
720 + 'notice' => '',
721 + 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-zoho',
722 + 'settings_link' => '',
723 + 'doc_link' => 'https://docs.arraytics.com/docs/booktics/integration/how-to-integrate-booktics-with-zoho-crm/',
724 + ),
725 + 'mailpoet' => array(
726 + 'name' => 'mailpoet',
727 + 'slug' => 'mailpoet',
728 + 'type' => 'integration',
729 + 'upgrade' => true,
730 + 'upgrade_link' => 'https://themewinter.com/purchase-history',
731 + 'status' => 'off',
732 + 'is_pro' => false,
733 + 'plugin_slug' => 'mailpoet',
734 + 'title' => __( 'MailPoet', 'booktics' ),
735 + 'description' => __( 'Add booking customers to your MailPoet lists.', 'booktics' ),
736 + 'icon' => \Booktics\Extensions\Extension_Icon::get( 'booktics-mailpoet-addon' ),
737 + 'notice' => '',
738 + 'demo_link' => 'https://support.themewinter.com/docs/plugins/plugin-docs/integration/booktics-mailpoet',
739 + 'settings_link' => '',
740 + 'doc_link' => 'https://docs.arraytics.com/docs/booktics/integration/how-to-integrate-booktics-with-mailpoet/',
741 + ),
670 742 'google-calendar' => array(
671 743 'name' => 'google-calendar',
672 744 'slug' => 'google-calendar',
673 745 'type' => 'module',
@@ -721,8 +793,26 @@
721 793 }
722 794 }
723 795 }
724 796
797 +if ( ! function_exists( 'booktics_log' ) ) {
798 + /**
799 + * Write a debug line, but only when the site has debug logging switched on.
800 + *
801 + * @param string $message Message to log.
802 + *
803 + * @return void
804 + */
805 + function booktics_log( $message ) {
806 + if ( ! defined( 'WP_DEBUG_LOG' ) || ! WP_DEBUG_LOG ) {
807 + return;
808 + }
809 +
810 + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Guarded above; this is the plugin's only debug sink.
811 + error_log( 'Booktics: ' . $message );
812 + }
813 +}
814 +
725 815 if ( ! function_exists( 'booktics_get_multisite_table_name' ) ) {
726 816 /**
727 817 * Get multisite-safe table name
728 818 *
@@ -918,5 +1008,89 @@
918 1008 $local_datetime = get_date_from_gmt( $gmt_datetime_string );
919 1009
920 1010 return gmdate( 'H:i:s', strtotime( $local_datetime ) );
921 1011 }
922 -}
1012 +}
1013 +
1014 +if ( ! function_exists( 'booktics_safe_maybe_unserialize' ) ) {
1015 + /**
1016 + * Safely unserialize a value without ever instantiating PHP objects.
1017 + *
1018 + * @param mixed $value Possibly serialized value.
1019 + *
1020 + * @return mixed Unserialized value, or the original value when not serialized.
1021 + */
1022 + function booktics_safe_maybe_unserialize( $value ) {
1023 + if ( is_string( $value ) && is_serialized( $value ) ) {
1024 + // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize -- allowed_classes => false prevents PHP Object Injection.
1025 + return @unserialize( trim( $value ), array( 'allowed_classes' => false ) );
1026 + }
1027 +
1028 + return $value;
1029 + }
1030 +}
1031 +
1032 +if ( ! function_exists( 'booktics_sanitize_id_string' ) ) {
1033 + /**
1034 + * Sanitize a free-form identifier received from a request.
1035 + *
1036 + * Returns a plain-text string id (e.g. 'default' or a client-generated id such
1037 + * as a uuid/nanoid). A legitimate identifier is never a PHP-serialized string,
1038 + * so any value that looks serialized is dropped to '' — this neutralizes PHP
1039 + * Object Injection payloads at the storage boundary while leaving every real id
1040 + * untouched. Non-scalar input (arrays/objects) is rejected to ''.
1041 + *
1042 + * @param mixed $value Raw value from the request.
1043 + *
1044 + * @return string Sanitized identifier, or '' when missing, non-scalar, or serialized.
1045 + */
1046 + function booktics_sanitize_id_string( $value ) {
1047 + if ( ! is_scalar( $value ) ) {
1048 + return '';
1049 + }
1050 +
1051 + $value = sanitize_text_field( (string) $value );
1052 +
1053 + return is_serialized( $value ) ? '' : $value;
1054 + }
1055 +}
1056 +
1057 +if ( ! function_exists( 'booktics_aisentic_identity' ) ) {
1058 + /**
1059 + * Build the site identity offered to Aisentic when the user opts in.
1060 + *
1061 + * The consent UI and the send path both read this helper, so the email shown
1062 + * on the consent checkbox is always the email that actually leaves the site.
1063 + *
1064 + * @return array{name: string, email: string, site_url: string}
1065 + */
1066 + function booktics_aisentic_identity(): array {
1067 + $name = booktics_get_option( 'business_name', get_bloginfo( 'name' ) );
1068 + $email = booktics_get_option( 'business_email', get_option( 'admin_email' ) );
1069 +
1070 + return array(
1071 + 'name' => sanitize_text_field( (string) $name ),
1072 + 'email' => sanitize_email( (string) $email ),
1073 + 'site_url' => esc_url_raw( site_url() ),
1074 + );
1075 + }
1076 +}
1077 +
1078 +if ( ! function_exists( 'booktics_aisentic_is_registered' ) ) {
1079 + /**
1080 + * Whether Aisentic already holds an API key.
1081 + *
1082 + * Reading Aisentic's own storage instead of our consent option means anyone
1083 + * who connected from Aisentic's screens is never nagged by our banner.
1084 + *
1085 + * @return bool True when an Aisentic API key is present.
1086 + */
1087 + function booktics_aisentic_is_registered(): bool {
1088 + if ( function_exists( 'aisentic_get_option' ) ) {
1089 + return ! empty( aisentic_get_option( 'llmProviders.aisentic.apiKey', '' ) );
1090 + }
1091 +
1092 + $settings = get_option( 'aisentic_settings', array() );
1093 +
1094 + return ! empty( $settings['llmProviders']['aisentic']['apiKey'] );
1095 + }
1096 +}