activities_helper.php
3 months ago
agent_helper.php
3 months ago
analytics_helper.php
4 months ago
auth_helper.php
3 months ago
blocks_helper.php
3 months ago
booking_helper.php
3 months ago
bricks_helper.php
3 months ago
bundles_helper.php
3 months ago
calendar_helper.php
3 months ago
carts_helper.php
3 months ago
connector_helper.php
3 months ago
csv_helper.php
3 months ago
customer_helper.php
3 months ago
customer_import_helper.php
3 months ago
database_helper.php
3 months ago
debug_helper.php
3 months ago
defaults_helper.php
3 months ago
elementor_helper.php
3 months ago
email_helper.php
3 months ago
encrypt_helper.php
3 months ago
events_helper.php
3 months ago
form_helper.php
3 months ago
icalendar_helper.php
3 months ago
image_helper.php
3 months ago
invoices_helper.php
3 months ago
license_helper.php
3 months ago
location_helper.php
3 months ago
marketing_systems_helper.php
3 months ago
meeting_systems_helper.php
3 months ago
menu_helper.php
3 months ago
meta_helper.php
3 months ago
migrations_helper.php
3 months ago
money_helper.php
3 months ago
notifications_helper.php
3 months ago
nps_survey_helper.php
3 months ago
order_intent_helper.php
3 months ago
orders_helper.php
3 months ago
otp_helper.php
3 months ago
pages_helper.php
3 months ago
params_helper.php
3 months ago
payments_helper.php
3 months ago
price_breakdown_helper.php
3 months ago
process_jobs_helper.php
3 months ago
processes_helper.php
3 months ago
replacer_helper.php
3 months ago
resource_helper.php
3 months ago
roles_helper.php
3 months ago
router_helper.php
3 months ago
service_helper.php
3 months ago
sessions_helper.php
3 months ago
settings_helper.php
3 months ago
short_links_systems_helper.php
3 months ago
shortcodes_helper.php
3 months ago
sms_helper.php
3 months ago
steps_helper.php
3 months ago
stripe_connect_helper.php
3 months ago
styles_helper.php
3 months ago
support_topics_helper.php
3 months ago
time_helper.php
3 months ago
timeline_helper.php
3 months ago
transaction_helper.php
3 months ago
transaction_intent_helper.php
3 months ago
util_helper.php
3 months ago
version_specific_updates_helper.php
3 months ago
whatsapp_helper.php
3 months ago
work_periods_helper.php
3 months ago
wp_datetime.php
3 months ago
wp_user_helper.php
3 months ago
settings_helper.php
813 lines
| 1 | <?php |
| 2 | |
| 3 | class OsSettingsHelper { |
| 4 | |
| 5 | public static $loaded_values; |
| 6 | |
| 7 | |
| 8 | private static $encrypted_settings = [ |
| 9 | 'license', |
| 10 | 'google_calendar_client_secret', |
| 11 | 'facebook_app_secret', |
| 12 | 'google_client_secret', |
| 13 | 'braintree_secret_key', |
| 14 | 'braintree_merchant_id', |
| 15 | 'paypal_client_secret', |
| 16 | ]; |
| 17 | |
| 18 | private static $settings_to_autoload = [ |
| 19 | 'enable_google_login', |
| 20 | 'time_system', |
| 21 | 'date_format', |
| 22 | 'currency_symbol_before', |
| 23 | 'currency_symbol_after', |
| 24 | 'phone_format', |
| 25 | 'steps_show_timezone_selector', |
| 26 | 'show_booking_end_time', |
| 27 | 'stripe_publishable_key', |
| 28 | 'enable_facebook_login', |
| 29 | 'earliest_possible_booking', |
| 30 | 'enable_payments_local', |
| 31 | 'color_scheme_for_booking_form', |
| 32 | 'latest_possible_booking', |
| 33 | 'facebook_app_id', |
| 34 | 'google_client_id', |
| 35 | 'paypal_client_id', |
| 36 | 'paypal_currency_iso_code', |
| 37 | 'paypal_use_braintree_api', |
| 38 | 'stripe_secret_key', |
| 39 | 'steps_hide_agent_info', |
| 40 | 'booking_hash', |
| 41 | 'payments_environment', |
| 42 | 'list_of_phone_countries', |
| 43 | 'included_phone_countries', |
| 44 | 'wp_users_as_customers', |
| 45 | 'thousand_separator', |
| 46 | 'decimal_separator', |
| 47 | 'number_of_decimals', |
| 48 | 'default_phone_country', |
| 49 | ]; |
| 50 | |
| 51 | private static $defaults = [ |
| 52 | 'date_format' => LATEPOINT_DEFAULT_DATE_FORMAT, |
| 53 | 'time_system' => LATEPOINT_DEFAULT_TIME_SYSTEM, |
| 54 | 'currency_symbol_before' => '$', |
| 55 | ]; |
| 56 | |
| 57 | public static function get_business_logo_url() { |
| 58 | $default_logo_url = LATEPOINT_IMAGES_URL . 'logo.png'; |
| 59 | |
| 60 | return OsImageHelper::get_image_url_by_id( OsSettingsHelper::get_settings_value( 'business_logo' ), 'thumbnail', $default_logo_url ); |
| 61 | } |
| 62 | |
| 63 | public static function get_business_logo_image( $height = '50px' ) { |
| 64 | $url = self::get_business_logo_url(); |
| 65 | |
| 66 | return '<img src="' . $url . '" style="height: ' . $height . '; width: auto"/>'; |
| 67 | } |
| 68 | |
| 69 | public static function get_encrypted_settings() { |
| 70 | $encrypted_settings = apply_filters( 'latepoint_encrypted_settings', self::$encrypted_settings ); |
| 71 | |
| 72 | return $encrypted_settings; |
| 73 | } |
| 74 | |
| 75 | |
| 76 | public static function get_active_addons(): array { |
| 77 | return json_decode( OsSettingsHelper::get_settings_value( 'active_addons', '' ) ) ?? []; |
| 78 | } |
| 79 | |
| 80 | public static function get_earliest_possible_booking_restriction( $service_id = 0 ) { |
| 81 | if ( ! empty( $service_id ) ) { |
| 82 | $service = new OsServiceModel( $service_id ); |
| 83 | if ( ! $service->is_new_record() && ! empty( $service->earliest_possible_booking ) && OsTimeHelper::is_valid_date( $service->earliest_possible_booking ) ) { |
| 84 | return $service->earliest_possible_booking; |
| 85 | } |
| 86 | } |
| 87 | $restriction_from_general_settings = OsSettingsHelper::get_settings_value( 'earliest_possible_booking', '' ); |
| 88 | if ( OsTimeHelper::is_valid_date( $restriction_from_general_settings ) ) { |
| 89 | return $restriction_from_general_settings; |
| 90 | } else { |
| 91 | return ''; |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | public static function get_latest_possible_booking_restriction( $service_id = 0 ) { |
| 96 | if ( ! empty( $service_id ) ) { |
| 97 | $service = new OsServiceModel( $service_id ); |
| 98 | if ( ! $service->is_new_record() && ! empty( $service->latest_possible_booking ) && OsTimeHelper::is_valid_date( $service->latest_possible_booking ) ) { |
| 99 | return $service->latest_possible_booking; |
| 100 | } |
| 101 | } |
| 102 | $restriction_from_general_settings = OsSettingsHelper::get_settings_value( 'latest_possible_booking', '' ); |
| 103 | if ( OsTimeHelper::is_valid_date( $restriction_from_general_settings ) ) { |
| 104 | return $restriction_from_general_settings; |
| 105 | } else { |
| 106 | return ''; |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | /** |
| 111 | * @param array $tables |
| 112 | * |
| 113 | * @return string |
| 114 | */ |
| 115 | public static function export_data( array $tables = [] ): string { |
| 116 | |
| 117 | if ( empty( $tables ) ) { |
| 118 | $tables = OsDatabaseHelper::get_all_latepoint_tables(); |
| 119 | } |
| 120 | |
| 121 | global $wpdb; |
| 122 | |
| 123 | $output = []; |
| 124 | |
| 125 | foreach ( $tables as $table ) { |
| 126 | // Check if table exists |
| 127 | $table_exists = $wpdb->get_var( "SHOW TABLES LIKE '{$table}'" ); |
| 128 | |
| 129 | if ( ! $table_exists ) { |
| 130 | continue; // Skip this table if it doesn't exist |
| 131 | } |
| 132 | // Get all rows from the table |
| 133 | $rows = $wpdb->get_results( "SELECT * FROM {$table}", ARRAY_A ); |
| 134 | |
| 135 | if ( $rows ) { |
| 136 | // Get table create statement |
| 137 | $create_table = $wpdb->get_row( "SHOW CREATE TABLE {$table}", ARRAY_N ); |
| 138 | $var_table = str_replace( $wpdb->prefix, '{{TABLE_PREFIX}}', $table ); |
| 139 | $create_table = str_replace( $table, $var_table, $create_table ); |
| 140 | |
| 141 | $output[ $var_table ] = [ |
| 142 | 'create' => $create_table[1], |
| 143 | 'prefix' => $wpdb->prefix, |
| 144 | 'data' => $rows, |
| 145 | ]; |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | // Generate filename |
| 150 | $filename = 'latepoint_backup_' . date( 'Y-m-d_H-i-s' ) . '.json'; |
| 151 | |
| 152 | $json = wp_json_encode( $output, JSON_PRETTY_PRINT ); |
| 153 | |
| 154 | // Send headers for file download |
| 155 | header( 'Content-Type: application/json' ); |
| 156 | header( 'Content-Disposition: attachment; filename="' . $filename . '"' ); |
| 157 | header( 'Content-Length: ' . strlen( $json ) ); |
| 158 | header( 'Pragma: no-cache' ); |
| 159 | |
| 160 | return $json; |
| 161 | } |
| 162 | |
| 163 | /** |
| 164 | * @param string $data |
| 165 | * |
| 166 | * @return bool |
| 167 | * @throws Exception |
| 168 | */ |
| 169 | public static function import_data( string $data ): bool { |
| 170 | global $wpdb; |
| 171 | |
| 172 | if ( empty( $data ) ) { |
| 173 | throw new Exception( __( 'Error reading uploaded file', 'latepoint' ) ); |
| 174 | } |
| 175 | |
| 176 | // update table name from original to new prefix |
| 177 | $data = str_replace( '{{TABLE_PREFIX}}', $wpdb->prefix, $data ); |
| 178 | |
| 179 | $data = json_decode( $data, true ); |
| 180 | if ( json_last_error() !== JSON_ERROR_NONE ) { |
| 181 | throw new Exception( __( 'Invalid JSON file format', 'latepoint' ) ); |
| 182 | } |
| 183 | |
| 184 | // Get whitelist of allowed LatePoint tables. |
| 185 | $allowed_tables = OsDatabaseHelper::get_all_latepoint_tables(); |
| 186 | |
| 187 | // Validate all tables before processing to ensure security. |
| 188 | foreach ( $data as $table => $table_data ) { |
| 189 | // Security check: Ensure table is in whitelist. |
| 190 | if ( ! in_array( $table, $allowed_tables, true ) ) { |
| 191 | throw new Exception( sprintf( __( 'Security: Table "%s" is not allowed for import', 'latepoint' ), esc_html( $table ) ) ); |
| 192 | } |
| 193 | |
| 194 | // Security check: Validate required fields exist. |
| 195 | if ( ! isset( $table_data['create'] ) || ! isset( $table_data['data'] ) ) { |
| 196 | throw new Exception( sprintf( __( 'Invalid data structure for table "%s"', 'latepoint' ), esc_html( $table ) ) ); |
| 197 | } |
| 198 | |
| 199 | // Security check: Validate CREATE statement only creates the expected table. |
| 200 | $create_statement = $table_data['create']; |
| 201 | if ( ! preg_match( '/^\s*CREATE\s+TABLE\s+/i', $create_statement ) ) { |
| 202 | throw new Exception( sprintf( __( 'Security: Invalid CREATE statement for table "%s"', 'latepoint' ), esc_html( $table ) ) ); |
| 203 | } |
| 204 | |
| 205 | // Extract table name from CREATE statement and validate it matches. |
| 206 | if ( ! preg_match( '/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?[`\'"]?(' . preg_quote( $table, '/' ) . ')[`\'"]?\s+/i', $create_statement ) ) { |
| 207 | throw new Exception( sprintf( __( 'Security: CREATE statement table name mismatch for "%s"', 'latepoint' ), esc_html( $table ) ) ); |
| 208 | } |
| 209 | |
| 210 | // Security check: Ensure no dangerous SQL keywords in CREATE statement (whole-word match to avoid false positives on column names like "selection_image_id"). |
| 211 | $dangerous_keywords = array( 'SELECT', 'UNION', 'EXEC', 'EXECUTE', 'CALL', 'LOAD_FILE', 'INTO\s+OUTFILE', 'INTO\s+DUMPFILE' ); |
| 212 | foreach ( $dangerous_keywords as $keyword ) { |
| 213 | if ( preg_match( '/\b' . $keyword . '\b/i', $create_statement ) ) { |
| 214 | $display_keyword = str_replace( '\s+', ' ', $keyword ); |
| 215 | throw new Exception( sprintf( __( 'Security: Dangerous SQL keyword "%s" detected in CREATE statement', 'latepoint' ), esc_html( $display_keyword ) ) ); |
| 216 | } |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | // Process each table after validation. |
| 221 | foreach ( $data as $table => $table_data ) { |
| 222 | // Drop table if exists |
| 223 | $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $table ) ); |
| 224 | |
| 225 | // Create table |
| 226 | $result = $wpdb->query( $table_data['create'] ); |
| 227 | if ( $result === false ) { |
| 228 | throw new Exception( sprintf( __( 'Error creating table "%s": %s', 'latepoint' ), esc_html( $table ), $wpdb->last_error ) ); |
| 229 | } |
| 230 | |
| 231 | // Insert data |
| 232 | if ( is_array( $table_data['data'] ) ) { |
| 233 | foreach ( $table_data['data'] as $row ) { |
| 234 | if ( is_array( $row ) ) { |
| 235 | // Security fix: Prevent mass assignment of wordpress_user_id during import. |
| 236 | if ( $table === $wpdb->prefix . 'latepoint_customers' ) { |
| 237 | unset( $row['wordpress_user_id'] ); |
| 238 | } |
| 239 | |
| 240 | $insert_result = $wpdb->insert( $table, $row ); |
| 241 | if ( $insert_result === false ) { |
| 242 | // Log error but continue with other rows. |
| 243 | error_log( sprintf( 'LatePoint Import: Error inserting data into %s: %s', $table, $wpdb->last_error ) ); |
| 244 | } |
| 245 | } |
| 246 | } |
| 247 | } |
| 248 | |
| 249 | // Find auto-increment columns and their max values |
| 250 | $columns = $wpdb->get_results( $wpdb->prepare( "SHOW COLUMNS FROM %i WHERE Extra = 'auto_increment'", $table ) ); |
| 251 | if ( is_array( $columns ) ) { |
| 252 | foreach ( $columns as $column ) { |
| 253 | if ( isset( $column->Field ) ) { |
| 254 | // Sanitize column name to prevent SQL injection. |
| 255 | $column_name = preg_replace( '/[^a-zA-Z0-9_]/', '', $column->Field ); |
| 256 | |
| 257 | // Get the maximum value for this column. |
| 258 | $max_id = $wpdb->get_var( $wpdb->prepare( 'SELECT MAX(%i) FROM %i', $column_name, $table ) ); |
| 259 | |
| 260 | // Set the auto_increment value to max + 1. |
| 261 | if ( $max_id ) { |
| 262 | $next_id = intval( $max_id ) + 1; |
| 263 | $wpdb->query( $wpdb->prepare( 'ALTER TABLE %i AUTO_INCREMENT = %d', $table, $next_id ) ); |
| 264 | } |
| 265 | } |
| 266 | } |
| 267 | } |
| 268 | } |
| 269 | |
| 270 | return true; |
| 271 | } |
| 272 | |
| 273 | public static function run_autoload() { |
| 274 | /** |
| 275 | * Default settings to be used in SettingsHelper when no value exists in DB |
| 276 | * |
| 277 | * @param {array} $default_settings Array of key => value pairs of setting names and their default values |
| 278 | * @returns {array} The filtered array of default settings |
| 279 | * |
| 280 | * @since 4.7.2 |
| 281 | * @hook latepoint_settings_defaults |
| 282 | * |
| 283 | */ |
| 284 | self::$defaults = apply_filters( 'latepoint_settings_defaults', self::$defaults ); |
| 285 | foreach ( self::$defaults as $name => $default ) { |
| 286 | self::$loaded_values[ $name ] = $default; |
| 287 | } |
| 288 | |
| 289 | $settings_model = new OsSettingsModel(); |
| 290 | |
| 291 | /** |
| 292 | * Settings to autoload in SettingsHelper on every page load, this is done to reduce the number of queries to DB |
| 293 | * |
| 294 | * @param {array} $settings Array of setting names to autoload |
| 295 | * @returns {array} The filtered array of setting names |
| 296 | * |
| 297 | * @since 4.7.2 |
| 298 | * @hook latepoint_settings_to_autoload |
| 299 | * |
| 300 | */ |
| 301 | self::$settings_to_autoload = apply_filters( 'latepoint_settings_to_autoload', self::$settings_to_autoload ); |
| 302 | $settings_arr = $settings_model->select( 'name, value' )->where( array( 'name' => self::$settings_to_autoload ) )->get_results(); |
| 303 | |
| 304 | |
| 305 | if ( $settings_arr && is_array( $settings_arr ) ) { |
| 306 | foreach ( $settings_arr as $setting ) { |
| 307 | if ( in_array( $setting->name, self::get_encrypted_settings() ) ) { |
| 308 | self::$loaded_values[ $setting->name ] = OsEncryptHelper::decrypt_value( $setting->value ); |
| 309 | } else { |
| 310 | self::$loaded_values[ $setting->name ] = $setting->value; |
| 311 | } |
| 312 | } |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | |
| 317 | // ENVIRONMENT SETTINGS |
| 318 | |
| 319 | // BASE ENVIRONMENT |
| 320 | public static function is_env_live() { |
| 321 | return ( LATEPOINT_ENV == LATEPOINT_ENV_LIVE ); |
| 322 | } |
| 323 | |
| 324 | public static function is_env_dev() { |
| 325 | return ( LATEPOINT_ENV == LATEPOINT_ENV_DEV ); |
| 326 | } |
| 327 | |
| 328 | public static function is_env_demo() { |
| 329 | return ( LATEPOINT_ENV == LATEPOINT_ENV_DEMO ); |
| 330 | } |
| 331 | |
| 332 | // SMS, EMAILS |
| 333 | |
| 334 | public static function is_sms_allowed() { |
| 335 | return LATEPOINT_ALLOW_SMS; |
| 336 | } |
| 337 | |
| 338 | public static function is_whatsapp_allowed() { |
| 339 | return LATEPOINT_ALLOW_WHATSAPP; |
| 340 | } |
| 341 | |
| 342 | public static function is_email_allowed() { |
| 343 | return LATEPOINT_ALLOW_EMAILS; |
| 344 | } |
| 345 | |
| 346 | // PAYMENTS ENVIRONMENT |
| 347 | public static function is_env_payments_live() { |
| 348 | return ( self::get_payments_environment() == LATEPOINT_PAYMENTS_ENV_LIVE ); |
| 349 | } |
| 350 | |
| 351 | public static function is_env_payments_dev() { |
| 352 | return ( self::get_payments_environment() == LATEPOINT_PAYMENTS_ENV_DEV ); |
| 353 | } |
| 354 | |
| 355 | public static function is_env_payments_demo() { |
| 356 | return ( self::get_payments_environment() == LATEPOINT_PAYMENTS_ENV_DEMO ); |
| 357 | } |
| 358 | |
| 359 | public static function get_payments_environment() { |
| 360 | return self::get_settings_value( 'payments_environment', LATEPOINT_PAYMENTS_ENV_LIVE ); |
| 361 | } |
| 362 | |
| 363 | |
| 364 | public static function append_payment_env_key( string $string, string $force_env = '' ): string { |
| 365 | if ( $force_env ) { |
| 366 | if ( $force_env == LATEPOINT_PAYMENTS_ENV_DEV ) { |
| 367 | $string .= LATEPOINT_PAYMENTS_DEV_SUFFIX; |
| 368 | } |
| 369 | } else { |
| 370 | if ( self::is_env_payments_dev() ) { |
| 371 | $string .= LATEPOINT_PAYMENTS_DEV_SUFFIX; |
| 372 | } |
| 373 | } |
| 374 | |
| 375 | return $string; |
| 376 | } |
| 377 | |
| 378 | public static function set_menu_layout_style( $layout ) { |
| 379 | $layout = in_array( $layout, [ 'compact', 'full' ] ) ? $layout : 'full'; |
| 380 | update_user_meta( get_current_user_id(), 'latepoint_admin_menu_style', $layout ); |
| 381 | } |
| 382 | |
| 383 | public static function get_menu_layout_style(): string { |
| 384 | $menu_style = get_user_meta( get_current_user_id(), 'latepoint_admin_menu_style', true ); |
| 385 | |
| 386 | // Set default if not set |
| 387 | if ( empty( $menu_style ) ) { |
| 388 | $menu_style = 'full'; // default value |
| 389 | } |
| 390 | return $menu_style; |
| 391 | } |
| 392 | |
| 393 | public static function get_time_system() { |
| 394 | return self::get_settings_value( 'time_system', LATEPOINT_DEFAULT_TIME_SYSTEM ); |
| 395 | } |
| 396 | |
| 397 | public static function get_date_format() { |
| 398 | return self::get_settings_value( 'date_format', LATEPOINT_DEFAULT_DATE_FORMAT ); |
| 399 | } |
| 400 | |
| 401 | public static function get_date_format_for_js() { |
| 402 | $format = strtolower( self::get_date_format() ); |
| 403 | |
| 404 | return str_replace( [ 'd', 'm', 'y' ], [ 'dd', 'mm', 'yyyy' ], $format ); |
| 405 | } |
| 406 | |
| 407 | public static function get_readable_datetime_format( $no_year = false, $no_seconds = true ) { |
| 408 | return self::get_readable_date_format( $no_year ) . ', ' . self::get_readable_time_format( $no_seconds ); |
| 409 | } |
| 410 | |
| 411 | public static function get_order_types_list_for_any_agent_logic(): array { |
| 412 | $order_types = [ |
| 413 | LATEPOINT_ANY_AGENT_ORDER_RANDOM => __( 'Randomly picked agent', 'latepoint' ), |
| 414 | LATEPOINT_ANY_AGENT_ORDER_PRICE_HIGH => __( 'Most expensive agent', 'latepoint' ), |
| 415 | LATEPOINT_ANY_AGENT_ORDER_PRICE_LOW => __( 'Least expensive agent', 'latepoint' ), |
| 416 | LATEPOINT_ANY_AGENT_ORDER_BUSY_HIGH => __( 'Agent with the most bookings on that day', 'latepoint' ), |
| 417 | LATEPOINT_ANY_AGENT_ORDER_BUSY_LOW => __( 'Agent with the least bookings on that day', 'latepoint' ), |
| 418 | ]; |
| 419 | |
| 420 | /** |
| 421 | * Get the list of order types for agent selection logic when "ANY" agent is pre-selected in the booking form |
| 422 | * |
| 423 | * @param {array} $order_types Array of order types |
| 424 | * |
| 425 | * @returns {array} Filtered array of order types |
| 426 | * @since 4.7.6 |
| 427 | * @hook latepoint_get_order_types_list_for_any_agent_logic |
| 428 | * |
| 429 | */ |
| 430 | return apply_filters( 'latepoint_get_order_types_list_for_any_agent_logic', $order_types ); |
| 431 | } |
| 432 | |
| 433 | public static function get_readable_time_format( $no_seconds = true ) { |
| 434 | $seconds = $no_seconds ? '' : ':s'; |
| 435 | $format = ( self::get_time_system() == '12' ) ? "g:i$seconds a" : "G:i$seconds"; |
| 436 | |
| 437 | return $format; |
| 438 | } |
| 439 | |
| 440 | public static function get_readable_date_format( $no_year = false, $short_month = false ) { |
| 441 | if ( OsSettingsHelper::is_on( 'disable_verbose_date_output' ) ) { |
| 442 | return self::get_date_format(); |
| 443 | } |
| 444 | $format = ( $no_year ) ? 'F j' : 'M j, Y'; |
| 445 | switch ( self::get_date_format() ) { |
| 446 | case 'm/d/Y': |
| 447 | case 'm.d.Y': |
| 448 | $format = ( $no_year ) ? 'F j' : 'M j, Y'; |
| 449 | break; |
| 450 | case 'd.m.Y': |
| 451 | case 'd/m/Y': |
| 452 | $format = ( $no_year ) ? 'j F' : 'j M, Y'; |
| 453 | break; |
| 454 | case 'Y-m-d': |
| 455 | $format = ( $no_year ) ? 'F j' : 'Y, M j'; |
| 456 | break; |
| 457 | } |
| 458 | if ( $short_month ) { |
| 459 | // if short month is requested - use month shorthand; |
| 460 | $format = str_replace( 'F', 'M', $format ); |
| 461 | } |
| 462 | |
| 463 | return $format; |
| 464 | } |
| 465 | |
| 466 | |
| 467 | public static function get_booking_template_for_calendar() { |
| 468 | return OsSettingsHelper::get_settings_value( 'booking_template_for_calendar', '{{service_name}}' ); |
| 469 | } |
| 470 | |
| 471 | |
| 472 | public static function get_selected_columns_for_bookings_table() { |
| 473 | return OsSettingsHelper::get_settings_value( 'bookings_table_columns', [] ); |
| 474 | } |
| 475 | |
| 476 | public static function get_available_columns_for_bookings_table() { |
| 477 | $available_columns = []; |
| 478 | |
| 479 | $available_columns['customer'] = [ |
| 480 | 'email' => __( 'Email', 'latepoint' ), |
| 481 | 'phone' => __( 'Phone', 'latepoint' ), |
| 482 | ]; |
| 483 | |
| 484 | $available_columns['booking'] = [ |
| 485 | 'booking_code' => __( 'Code', 'latepoint' ), |
| 486 | 'duration' => __( 'Duration', 'latepoint' ), |
| 487 | 'source_id' => __( 'Source ID', 'latepoint' ), |
| 488 | 'payment_method' => __( 'Payment Method', 'latepoint' ), |
| 489 | 'payment_portion' => __( 'Payment Portion', 'latepoint' ), |
| 490 | 'formatted_price' => __( 'Price', 'latepoint' ), |
| 491 | ]; |
| 492 | |
| 493 | $available_columns = apply_filters( 'latepoint_bookings_table_columns', $available_columns ); |
| 494 | |
| 495 | return $available_columns; |
| 496 | } |
| 497 | |
| 498 | public static function force_bite( $request ) { |
| 499 | } |
| 500 | |
| 501 | public static function read_encoded( $str ) { |
| 502 | return base64_decode( $str ); |
| 503 | } |
| 504 | |
| 505 | public static function get_db_version() { |
| 506 | return get_option( 'latepoint_db_version' ); |
| 507 | } |
| 508 | |
| 509 | public static function force_release( $request ) { |
| 510 | } |
| 511 | |
| 512 | public static function is_enabled_show_dial_code_with_flag() { |
| 513 | return ( self::get_settings_value( 'show_dial_code_with_flag', LATEPOINT_VALUE_ON ) == LATEPOINT_VALUE_ON ); |
| 514 | } |
| 515 | |
| 516 | public static function is_using_google_login() { |
| 517 | return self::is_on( 'enable_google_login' ); |
| 518 | } |
| 519 | |
| 520 | public static function is_using_facebook_login() { |
| 521 | return self::is_on( 'enable_facebook_login' ); |
| 522 | } |
| 523 | |
| 524 | public static function is_using_social_login() { |
| 525 | return ( self::is_using_google_login() || self::is_using_facebook_login() ); |
| 526 | } |
| 527 | |
| 528 | public static function get_steps_support_text() { |
| 529 | $default = '<h5>Questions?</h5><p>Call (858) 939-3746 for help</p>'; |
| 530 | |
| 531 | return self::get_settings_value( 'steps_support_text', $default ); |
| 532 | } |
| 533 | |
| 534 | public static function get_default_fields_for_customer() { |
| 535 | $default_fields = [ |
| 536 | 'first_name' => [ |
| 537 | 'label' => __( 'First Name', 'latepoint' ), |
| 538 | 'required' => true, |
| 539 | 'width' => 'os-col-6', |
| 540 | 'active' => true, |
| 541 | ], |
| 542 | 'last_name' => [ |
| 543 | 'label' => __( 'Last Name', 'latepoint' ), |
| 544 | 'required' => true, |
| 545 | 'width' => 'os-col-6', |
| 546 | 'active' => true, |
| 547 | ], |
| 548 | 'email' => [ |
| 549 | 'label' => __( 'Email Address', 'latepoint' ), |
| 550 | 'required' => true, |
| 551 | 'width' => 'os-col-6', |
| 552 | 'active' => true, |
| 553 | ], |
| 554 | 'phone' => [ |
| 555 | 'label' => __( 'Phone Number', 'latepoint' ), |
| 556 | 'required' => false, |
| 557 | 'width' => 'os-col-6', |
| 558 | 'active' => true, |
| 559 | ], |
| 560 | 'notes' => [ |
| 561 | 'label' => __( 'Comments', 'latepoint' ), |
| 562 | 'required' => false, |
| 563 | 'width' => 'os-col-12', |
| 564 | 'active' => true, |
| 565 | ], |
| 566 | ]; |
| 567 | |
| 568 | $fields_from_db = OsSettingsHelper::get_settings_value( 'default_fields_for_customer', '' ); |
| 569 | $fields_from_db_arr = json_decode( $fields_from_db, true ); |
| 570 | if ( $fields_from_db_arr ) { |
| 571 | foreach ( $fields_from_db_arr as $name => $field_from_db ) { |
| 572 | if ( isset( $default_fields[ $name ] ) ) { |
| 573 | $default_fields[ $name ] = $field_from_db; |
| 574 | } |
| 575 | } |
| 576 | } |
| 577 | $default_fields = apply_filters( 'latepoint_default_fields_for_customer', $default_fields ); |
| 578 | |
| 579 | return $default_fields; |
| 580 | } |
| 581 | |
| 582 | public static function remove_setting_by_name( $name ) { |
| 583 | $settings_model = new OsSettingsModel(); |
| 584 | $settings_model = $settings_model->delete_where( array( 'name' => $name ) ); |
| 585 | self::reset_loaded_value( $name ); |
| 586 | } |
| 587 | |
| 588 | public static function save_setting_by_name( $name, $value ) { |
| 589 | $settings_model = new OsSettingsModel(); |
| 590 | $settings_model = $settings_model->where( array( 'name' => $name ) )->set_limit( 1 )->get_results_as_models(); |
| 591 | if ( $settings_model ) { |
| 592 | $settings_model->value = self::prepare_value( $name, $value ); |
| 593 | } else { |
| 594 | $settings_model = new OsSettingsModel(); |
| 595 | $settings_model->name = $name; |
| 596 | $settings_model->value = self::prepare_value( $name, $value ); |
| 597 | } |
| 598 | self::reset_loaded_value( $name ); |
| 599 | |
| 600 | return $settings_model->save(); |
| 601 | } |
| 602 | |
| 603 | public static function reset_loaded_value( $name ) { |
| 604 | unset( self::$loaded_values[ $name ] ); |
| 605 | } |
| 606 | |
| 607 | public static function prepare_value( $name, $value ) { |
| 608 | if ( in_array( $name, self::get_encrypted_settings() ) ) { |
| 609 | $value = OsEncryptHelper::encrypt_value( $value ); |
| 610 | } |
| 611 | if ( is_array( $value ) ) { |
| 612 | $value = maybe_serialize( $value ); |
| 613 | } |
| 614 | |
| 615 | return $value; |
| 616 | } |
| 617 | |
| 618 | public static function get_settings_value( $name, $default = false ) { |
| 619 | if ( isset( self::$loaded_values[ $name ] ) ) { |
| 620 | return self::$loaded_values[ $name ]; |
| 621 | } |
| 622 | $settings_model = new OsSettingsModel(); |
| 623 | $settings_model = $settings_model->where( array( 'name' => $name ) )->set_limit( 1 )->get_results_as_models(); |
| 624 | if ( $settings_model ) { |
| 625 | if ( in_array( $name, self::get_encrypted_settings() ) ) { |
| 626 | $value = OsEncryptHelper::decrypt_value( $settings_model->value ); |
| 627 | } else { |
| 628 | $value = maybe_unserialize( $settings_model->value ); |
| 629 | } |
| 630 | } else { |
| 631 | $value = $default; |
| 632 | } |
| 633 | self::$loaded_values[ $name ] = $value; |
| 634 | |
| 635 | return self::$loaded_values[ $name ]; |
| 636 | } |
| 637 | |
| 638 | |
| 639 | public static function get_any_agent_order() { |
| 640 | return self::get_settings_value( 'any_agent_order', LATEPOINT_ANY_AGENT_ORDER_RANDOM ); |
| 641 | } |
| 642 | |
| 643 | public static function get_day_calendar_min_height() { |
| 644 | $height = preg_replace( '/\D/', '', self::get_settings_value( 'day_calendar_min_height', 700 ) ); |
| 645 | if ( ! $height ) { |
| 646 | $height = 700; |
| 647 | } |
| 648 | |
| 649 | return $height; |
| 650 | } |
| 651 | |
| 652 | public static function get_default_timeblock_interval() { |
| 653 | $timeblock_interval = self::get_settings_value( 'timeblock_interval', LATEPOINT_DEFAULT_TIMEBLOCK_INTERVAL ); |
| 654 | if ( empty( $timeblock_interval ) ) { |
| 655 | $timeblock_interval = LATEPOINT_DEFAULT_TIMEBLOCK_INTERVAL; |
| 656 | } |
| 657 | |
| 658 | return intval( $timeblock_interval ); |
| 659 | } |
| 660 | |
| 661 | public static function get_customer_dashboard_url( $include_site_url = true ) { |
| 662 | $path = self::get_settings_value( 'page_url_customer_dashboard', '/customer-dashboard' ); |
| 663 | |
| 664 | return ( $include_site_url ) ? site_url( $path ) : $path; |
| 665 | } |
| 666 | |
| 667 | public static function get_customer_login_url( $include_site_url = true ) { |
| 668 | $path = self::get_settings_value( 'page_url_customer_login', '/customer-login' ); |
| 669 | |
| 670 | return ( $include_site_url ) ? site_url( $path ) : $path; |
| 671 | } |
| 672 | |
| 673 | |
| 674 | // BOOKING STEPS |
| 675 | |
| 676 | public static function steps_show_service_categories() { |
| 677 | return ( self::get_settings_value( 'steps_show_service_categories', 'on' ) == 'on' ); |
| 678 | } |
| 679 | |
| 680 | public static function steps_show_location_categories() { |
| 681 | return ( self::get_settings_value( 'steps_show_location_categories', 'on' ) == 'on' ); |
| 682 | } |
| 683 | |
| 684 | public static function steps_show_agent_bio() { |
| 685 | return ( self::get_settings_value( 'steps_show_agent_bio' ) == 'on' ); |
| 686 | } |
| 687 | |
| 688 | public static function get_booking_form_color_scheme() { |
| 689 | return self::get_settings_value( 'color_scheme_for_booking_form', 'blue' ); |
| 690 | } |
| 691 | |
| 692 | public static function get_booking_form_border_radius() { |
| 693 | return self::get_settings_value( 'border_radius', 'flat' ); |
| 694 | } |
| 695 | |
| 696 | public static function get_default_phone_country() { |
| 697 | return OsSettingsHelper::get_settings_value( 'default_phone_country', 'us' ); |
| 698 | } |
| 699 | |
| 700 | public static function get_included_phone_countries(): array { |
| 701 | if ( OsSettingsHelper::get_settings_value( 'list_of_phone_countries', LATEPOINT_ALL ) == LATEPOINT_ALL ) { |
| 702 | return []; |
| 703 | } else { |
| 704 | return array_map( 'trim', explode( ',', OsSettingsHelper::get_settings_value( 'included_phone_countries', '' ) ) ); |
| 705 | } |
| 706 | } |
| 707 | |
| 708 | |
| 709 | public static function is_on( string $setting, $default = false ): bool { |
| 710 | return ( self::get_settings_value( $setting, $default ) == LATEPOINT_VALUE_ON ); |
| 711 | } |
| 712 | |
| 713 | public static function is_off( string $setting, $default = false ): bool { |
| 714 | return ( self::get_settings_value( $setting, $default ) != LATEPOINT_VALUE_ON ); |
| 715 | } |
| 716 | |
| 717 | public static function generate_default_form_fields( array $default_fields ) { |
| 718 | ?> |
| 719 | <div class="os-default-fields" data-route="<?php echo esc_attr( OsRouterHelper::build_route_name( 'form_fields', 'update_default_fields' ) ); ?>"> |
| 720 | <form> |
| 721 | <?php foreach ( $default_fields as $name => $default_field ) { |
| 722 | $atts = []; |
| 723 | ?> |
| 724 | <div class="os-default-field <?php echo $default_field['active'] ? '' : 'is-disabled'; ?>"> |
| 725 | <?php |
| 726 | $active = $default_field['active'] ? 'on' : 'off'; |
| 727 | $field_name = 'default_fields[' . $name . '][active]'; |
| 728 | echo '<div class="os-toggler ' . esc_attr( $active ) . '" data-for="' . esc_attr( OsFormHelper::name_to_id( $field_name ) ) . '"><div class="toggler-rail"><div class="toggler-pill"></div></div></div>'; |
| 729 | echo OsFormHelper::hidden_field( $field_name, $default_field['active'] ); |
| 730 | ?> |
| 731 | <div class="os-field-name"><?php echo esc_html( $default_field['label'] ); ?></div> |
| 732 | <div class="os-field-setting"> |
| 733 | <?php echo OsFormHelper::checkbox_field( 'default_fields[' . $name . '][required]', __( 'Required?', 'latepoint' ), 'on', $default_field['required'], $atts ); ?> |
| 734 | </div> |
| 735 | <div class="os-field-setting"> |
| 736 | <?php echo OsFormHelper::select_field( |
| 737 | 'default_fields[' . $name . '][width]', |
| 738 | false, |
| 739 | array( |
| 740 | 'os-col-12' => __( 'Full Width', 'latepoint' ), |
| 741 | 'os-col-6' => __( 'Half Width', 'latepoint' ), |
| 742 | ), |
| 743 | $default_field['width'] |
| 744 | ); ?> |
| 745 | </div> |
| 746 | </div> |
| 747 | <?php } ?> |
| 748 | </form> |
| 749 | </div> |
| 750 | <?php |
| 751 | } |
| 752 | |
| 753 | |
| 754 | /** |
| 755 | * Get value set for start of week in WordPress, can be from 1-7 (representing Monday-Sunday) |
| 756 | * @return mixed |
| 757 | */ |
| 758 | public static function get_start_of_week(): int { |
| 759 | $wp_value = intval( get_option( 'start_of_week', 0 ) ); |
| 760 | |
| 761 | return $wp_value ? $wp_value : 7; // in WordPress they start count on sunday and it's 0, we are using PHP Date library that starts week on Monday and it's 1-7 |
| 762 | } |
| 763 | |
| 764 | public static function get_number_of_records_per_page(): int { |
| 765 | return intval( OsSettingsHelper::get_settings_value( 'number_of_records_per_page', 20 ) ); |
| 766 | } |
| 767 | |
| 768 | public static function can_download_records_as_csv(): bool { |
| 769 | return OsAuthHelper::is_admin_logged_in() || self::is_on( 'allow_non_admins_download_csv' ); |
| 770 | } |
| 771 | |
| 772 | public static function get_link_attributes_for_premium_features(): string { |
| 773 | return ' data-os-action="' . OsRouterHelper::build_route_name( 'settings', 'premium_modal' ) . '" data-os-lightbox-classes="width-600" data-os-output-target="lightbox" '; |
| 774 | } |
| 775 | |
| 776 | public static function generate_instant_booking_page_url( array $url_settings ): string { |
| 777 | $url_settings['latepoint'] = 'instant'; |
| 778 | return OsUtilHelper::get_site_url() . '/?' . http_build_query( $url_settings ); |
| 779 | } |
| 780 | |
| 781 | public static function instant_page_background_patterns(): array { |
| 782 | return [ |
| 783 | 'pattern_1' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%);', |
| 784 | 'pattern_2' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(to top, #a18cd1 0%, #fbc2eb 100%);', |
| 785 | 'pattern_3' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(to top, #fbc2eb 0%, #a6c1ee 100%);', |
| 786 | 'pattern_4' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(120deg, #f6d365 0%, #fda085 100%);', |
| 787 | 'pattern_5' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(180deg, #2af598 0%, #009efd 100%);', |
| 788 | 'pattern_6' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(to right, #6a11cb 0%, #2575fc 100%);', |
| 789 | 'pattern_7' => 'background-color: transparent; background-size: auto; background-color: #DCD9D4; background-image: linear-gradient(to bottom, rgba(255,255,255,0.50) 0%, rgba(0,0,0,0.50) 100%), radial-gradient(at 50% 0%, rgba(255,255,255,0.10) 0%, rgba(0,0,0,0.50) 50%); background-blend-mode: soft-light,screen;', |
| 790 | 'pattern_8' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(to top, #f77062 0%, #fe5196 100%);', |
| 791 | 'pattern_9' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(to top, #00c6fb 0%, #005bea 100%);', |
| 792 | 'pattern_10' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(to top, #09203f 0%, #537895 100%);', |
| 793 | 'pattern_11' => 'background-color: transparent; background-size: auto; background-image: radial-gradient(73% 147%, #EADFDF 59%, #ECE2DF 100%), radial-gradient(91% 146%, rgba(255,255,255,0.50) 47%, rgba(0,0,0,0.50) 100%); background-blend-mode: screen;', |
| 794 | 'pattern_12' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(to top, lightgrey 0%, lightgrey 1%, #e0e0e0 26%, #efefef 48%, #d9d9d9 75%, #bcbcbc 100%);', |
| 795 | 'pattern_13' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(to top, #fddb92 0%, #d1fdff 100%);', |
| 796 | 'pattern_14' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(to top, #dfe9f3 0%, white 100%);', |
| 797 | 'pattern_15' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(-225deg, #5271C4 0%, #B19FFF 48%, #ECA1FE 100%);', |
| 798 | 'pattern_16' => 'background-color: transparent; background-size: auto; background: linear-gradient(to bottom, rgba(255,255,255,0.15) 0%, rgba(0,0,0,0.15) 100%), radial-gradient(at top center, rgba(255,255,255,0.40) 0%, rgba(0,0,0,0.40) 120%) #989898;background-blend-mode: multiply,multiply;', |
| 799 | 'pattern_17' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(to top, #f43b47 0%, #453a94 100%);', |
| 800 | 'pattern_18' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(to right, #222 0%, #111 100%);', |
| 801 | 'pattern_19' => 'background-color: transparent; background-size: auto; background-image: linear-gradient(-20deg, #d558c8 0%, #24d292 100%);', |
| 802 | ]; |
| 803 | } |
| 804 | |
| 805 | public static function get_default_wp_role_for_new_customers(): string { |
| 806 | if ( ! wp_roles()->is_role( LATEPOINT_WP_CUSTOMER_ROLE ) ) { |
| 807 | OsRolesHelper::register_customer_role(); |
| 808 | } |
| 809 | return OsSettingsHelper::get_settings_value( 'default_wp_role_for_customer', LATEPOINT_WP_CUSTOMER_ROLE ); |
| 810 | } |
| 811 | } |
| 812 | |
| 813 | ?> |