PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.29
Booktics – Appointment Booking Calendar for Service Businesses v1.0.29
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 +150 -26 1.0.23 → 1.0.29 View file →
@@ -1,6 +1,11 @@
1 1 <?php
2 -if ( ! defined( 'ABSPATH' ) && PHP_SAPI !== 'cli' ) { 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,8 +641,24 @@
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 664 'type' => 'integration',
@@ -786,8 +793,26 @@
786 793 }
787 794 }
788 795 }
789 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 +
790 815 if ( ! function_exists( 'booktics_get_multisite_table_name' ) ) {
791 816 /**
792 817 * Get multisite-safe table name
793 818 *
@@ -1025,6 +1050,105 @@
1025 1050
1026 1051 $value = sanitize_text_field( (string) $value );
1027 1052
1028 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 +}
1097 +
1098 +if ( ! function_exists( 'booktics_get_store_currency' ) ) {
1099 + /**
1100 + * The currency the merchant configured for the store, lowercased.
1101 + *
1102 + * Public checkout must always price in this currency. A currency sent by the
1103 + * buyer cannot be trusted: the total is computed server side in the store
1104 + * currency, so relabeling it as another currency changes what is charged.
1105 + *
1106 + * @return string Lowercase ISO 4217 currency code.
1107 + */
1108 + function booktics_get_store_currency(): string {
1109 + $currency = strtolower( trim( (string) booktics_get_option( 'currency', 'USD' ) ) );
1110 +
1111 + // An empty or malformed setting would make every Stripe charge fail.
1112 + return preg_match( '/^[a-z]{3}$/', $currency ) ? $currency : 'usd';
1113 + }
1114 +}
1115 +
1116 +if ( ! function_exists( 'booktics_amount_to_minor_units' ) ) {
1117 + /**
1118 + * Convert a decimal amount to the smallest unit of a currency.
1119 + *
1120 + * Stripe takes amounts in minor units, and not every currency has two
1121 + * decimals: 100 JPY is sent as 100, 100 USD as 10000 and 100 KWD as 100000.
1122 + * ISK and UGX are zero-decimal but Stripe still expects them as whole
1123 + * amounts times 100, so 5 UGX is sent as 500.
1124 + *
1125 + * @see https://docs.stripe.com/currencies#minor-units
1126 + *
1127 + * @param float|int|string $amount Amount in major units, e.g. 19.99.
1128 + * @param string $currency ISO 4217 currency code.
1129 + *
1130 + * @return int Amount in minor units.
1131 + */
1132 + function booktics_amount_to_minor_units( $amount, string $currency ): int {
1133 + $zero_decimal = array( 'bif', 'clp', 'djf', 'gnf', 'jpy', 'kmf', 'krw', 'mga', 'pyg', 'rwf', 'vnd', 'vuv', 'xaf', 'xof', 'xpf' );
1134 + $whole_x100 = array( 'isk', 'ugx' );
1135 + $three_decimal = array( 'bhd', 'jod', 'kwd', 'omr', 'tnd' );
1136 + $currency = strtolower( $currency );
1137 + $amount = (float) $amount;
1138 +
1139 + if ( in_array( $currency, $zero_decimal, true ) ) {
1140 + return (int) round( $amount );
1141 + }
1142 +
1143 + if ( in_array( $currency, $whole_x100, true ) ) {
1144 + return (int) round( $amount ) * 100;
1145 + }
1146 +
1147 + if ( in_array( $currency, $three_decimal, true ) ) {
1148 + // Stripe requires the last digit of three-decimal amounts to be 0.
1149 + return (int) ( round( $amount * 100 ) * 10 );
1150 + }
1151 +
1152 + return (int) round( $amount * 100 );
1029 1153 }
1030 1154 }