' . esc_html__( 'Dayslot requires WooCommerce to be installed and active.', 'dayslot' ) . '

'; } ); return; } require_once DAYSLOT_DIR . 'includes/helpers.php'; // Module => feature that can be switched off in Settings → Features (null = always on). $modules = array( 'schedule' => null, 'occupancy' => null, 'availability' => null, 'pickup' => null, 'shipping' => 'shipping', 'checkout' => null, 'blocks' => null, 'placement' => 'placement', 'compat-funnelkit' => null, 'order-display' => null, 'cart-note' => null, 'app-fields' => null, 'page-cache' => null, 'ical-format' => null, 'add-to-calendar' => null, 'emails' => null, 'admin-calendar' => 'calendar', 'ical' => 'ical', 'appearance' => null, 'texts' => null, 'multilingual' => null, 'features' => null, 'settings' => null, ); foreach ( $modules as $module => $feature ) { if ( null === $feature || dayslot_feature_on( $feature ) ) { require_once DAYSLOT_DIR . 'includes/' . $module . '.php'; } } // Setup wizard and the quick start checklist: admin only. if ( is_admin() ) { require_once DAYSLOT_DIR . 'includes/wizard.php'; require_once DAYSLOT_DIR . 'includes/help.php'; require_once DAYSLOT_DIR . 'includes/upsell.php'; } /** * Add-ons (the Pro plugin) load their modules here. */ do_action( 'dayslot_loaded' ); }, 20 ); /** * Languages shipped with both plugins (languages/), by their own name. English is the source. */ function dayslot_languages() { return array( 'en_US' => 'English', 'pl_PL' => 'Polski', 'de_DE' => 'Deutsch', 'fr_FR' => 'Français', 'es_ES' => 'Español', 'it_IT' => 'Italiano', 'pt_BR' => 'Português', 'nl_NL' => 'Nederlands', 'cs_CZ' => 'Čeština', 'uk' => 'Українська', 'ru_RU' => 'Русский', ); } /** * Language of the plugin texts: the shop's choice (Settings → Texts) or, by default, the WordPress * language. A regional variant without its own file uses the closest one (de_AT → de_DE, pt_PT → pt_BR). */ function dayslot_plugin_locale( $locale, $domain = '' ) { if ( 'dayslot' !== $domain && 'dayslot' !== $domain ) { return $locale; } $settings = get_option( 'dayslot_settings', array() ); $chosen = is_array( $settings ) && isset( $settings['language'] ) ? $settings['language'] : ''; // With Polylang / WPML the chosen language is the one of the main-language pages; other pages keep theirs. $other = $chosen && function_exists( 'dayslot_multilingual' ) && dayslot_multilingual() && strtok( $locale, '_' ) !== strtok( dayslot_main_locale(), '_' ); if ( $chosen && isset( dayslot_languages()[ $chosen ] ) && ! $other ) { return $chosen; } return dayslot_closest_locale( $locale, $domain ); } /** * The shipped language for a WordPress language, or the language itself when there is no close one. */ function dayslot_closest_locale( $locale, $domain = 'dayslot' ) { if ( isset( dayslot_languages()[ $locale ] ) || is_readable( WP_LANG_DIR . '/plugins/' . $domain . '-' . $locale . '.mo' ) ) { return $locale; } $lang = strtok( $locale, '_' ); foreach ( array_keys( dayslot_languages() ) as $known ) { if ( strtok( $known, '_' ) === $lang ) { return $known; } } return $locale; } add_filter( 'plugin_locale', 'dayslot_plugin_locale', 10, 2 ); /** * Load a plugin's texts in dayslot_plugin_locale(). WordPress 6.7+ loads translations "just in time" * in the WordPress language only, so the chosen or closest language is loaded here directly. */ function dayslot_load_textdomain( $domain, $plugin_file ) { $locale = dayslot_plugin_locale( determine_locale(), $domain ); if ( 'en_US' === $locale ) { // English is the original text: load no translation at all. add_filter( 'override_load_textdomain', function ( $override, $loading ) use ( $domain ) { return $loading === $domain ? true : $override; }, 10, 2 ); unload_textdomain( $domain ); return; } $file = WP_LANG_DIR . '/plugins/' . $domain . '-' . $locale . '.mo'; if ( ! is_readable( $file ) ) { $file = plugin_dir_path( $plugin_file ) . 'languages/' . $domain . '-' . $locale . '.mo'; } unload_textdomain( $domain ); // Filed under the current WordPress language: passing another one would switch the language of the whole site. load_textdomain( $domain, $file, determine_locale() ); } /** * Translations shipped with the plugin (languages/). Translations from * WordPress.org (wp-content/languages/plugins) take priority when they exist. */ add_action( 'init', function () { dayslot_load_textdomain( 'dayslot', DAYSLOT_FILE ); }, 1 ); register_activation_hook( DAYSLOT_FILE, function () { // A fresh site (never had our settings): the setup wizard is offered. if ( false === get_option( 'dayslot_settings', false ) ) { add_option( 'dayslot_wizard', 'start', '', false ); } // Right after activation the shop owner lands in the setup wizard (or the settings), not on a license page. set_transient( 'dayslot_activation_redirect', 1, 60 ); // Make sure the settings are autoloaded (read on every page with the cart) and add our shipping method. add_option( 'dayslot_settings', array(), '', true ); add_option( 'dayslot_texts', array(), '', true ); if ( false === get_option( 'edc_settings', false ) ) { // Not when moving from the old plugin: its shipping method is moved (pro/includes/migrate.php). update_option( 'dayslot_add_shipping_method', 1, false ); } } ); /** * Options read on every page must exist (and be autoloaded), otherwise WordPress * asks the database for them on each request. */ add_action( 'admin_init', function () { if ( get_option( 'dayslot_db_version' ) !== DAYSLOT_VERSION ) { foreach ( array( 'dayslot_settings', 'dayslot_texts' ) as $name ) { if ( false === get_option( $name, false ) ) { add_option( $name, array(), '', true ); } } dayslot_upgrade_settings(); update_option( 'dayslot_db_version', DAYSLOT_VERSION, true ); } } ); add_filter( 'plugin_action_links_' . plugin_basename( DAYSLOT_FILE ), function ( $links ) { array_unshift( $links, '' . esc_html__( 'Calendar', 'dayslot' ) . '', '' . esc_html__( 'Settings', 'dayslot' ) . '' ); return $links; } ); /** * Freemius reads three options of its own on every page (logger switch, clone check, cache). When they don't * exist or aren't autoloaded, each read is a database query — even on shop pages. Keep them existing and * autoloaded (they are small), so they come with WordPress's one autoload query. */ function dayslot_fs_fast_options() { $names = array( 'fs_storage_logger' => 0, 'fs_clone_management' => array(), ); if ( function_exists( 'dayslot_fs' ) && is_object( dayslot_fs() ) ) { $names[ 'fs_cache_' . dayslot_fs()->get_id() ] = array(); } return $names; } function dayslot_fs_autoload( $name ) { global $wpdb; if ( function_exists( 'wp_set_option_autoload' ) ) { wp_set_option_autoload( $name, true ); return; } $wpdb->update( $wpdb->options, array( 'autoload' => 'yes' ), array( 'option_name' => $name ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery wp_cache_delete( 'alloptions', 'options' ); } add_action( 'admin_init', function () { if ( get_option( 'dayslot_fs_fast' ) === DAYSLOT_VERSION ) { return; } foreach ( dayslot_fs_fast_options() as $name => $empty ) { if ( false === get_option( $name, false ) ) { add_option( $name, $empty, '', true ); } else { dayslot_fs_autoload( $name ); } } update_option( 'dayslot_fs_fast', DAYSLOT_VERSION, true ); } ); // Freemius saves its cache with autoload off: switch it back on (only when Freemius writes, which is rare). foreach ( array( 'added_option', 'updated_option' ) as $dayslot_hook ) { add_action( $dayslot_hook, function ( $name ) { if ( isset( dayslot_fs_fast_options()[ $name ] ) && ! doing_action( 'dayslot_fs_autoload' ) ) { dayslot_fs_autoload( $name ); } } ); } unset( $dayslot_hook ); /** * Saved settings from older versions in today's form. The ready-made look "bajeczne" is now "candy". */ function dayslot_upgrade_settings() { $s = get_option( 'dayslot_settings', array() ); if ( is_array( $s ) && isset( $s['style']['preset'] ) && 'bajeczne' === $s['style']['preset'] ) { $s['style']['preset'] = 'candy'; update_option( 'dayslot_settings', $s ); } } // After activation: straight to the setup wizard (the settings once it was done). Not for bulk activation. add_action( 'admin_init', function () { if ( ! get_transient( 'dayslot_activation_redirect' ) || wp_doing_ajax() || is_network_admin() ) { return; } delete_transient( 'dayslot_activation_redirect' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- only reads which screen WordPress shows. if ( isset( $_GET['activate-multi'] ) || ! current_user_can( 'manage_woocommerce' ) ) { return; } $page = 'done' === get_option( 'dayslot_wizard' ) ? 'dayslot-settings' : 'dayslot-wizard'; wp_safe_redirect( admin_url( 'admin.php?page=' . $page ) ); exit; } );