Plugin Directory

Changeset 3783145


Ignore:
Timestamp:
11/04/2026 06:00:15 AM (4 days ago)
Author:
magepeopleteam
Message:

Publish 2.3.11

Location:
tour-booking-manager
Files:
12 edited
1 copied

Legend:

Unmodified
Added
Removed
  • tour-booking-manager/tags/2.3.11/admin/TTBM_Get_Enquiry.php

    r3781509 r3783145  
    501501        }
    502502
     503        /** Popup markup waiting for wp_footer. */
     504        private $footer_popup = '';
     505
     506        /**
     507         * ttbm_enquery_popup action. The popup is built here (where the current tour is known) but printed
     508         * in wp_footer, outside #ttbm_content: tour-page rules such as "#ttbm_content h2" (ID selectors)
     509         * otherwise override the popup's own type and colours.
     510         */
    503511        public function get_enquiry_pop_up($tour_id = 0) {
     512            if ($this->footer_popup !== '') {
     513                return; // one popup per page
     514            }
     515            ob_start();
     516            $this->render_enquiry_pop_up($tour_id);
     517            $html = ob_get_clean();
     518            if (did_action('wp_footer') || doing_action('wp_footer')) {
     519                echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped in render_enquiry_pop_up().
     520                return;
     521            }
     522            $this->footer_popup = $html;
     523            add_action('wp_footer', [$this, 'print_footer_popup'], 5);
     524        }
     525
     526        public function print_footer_popup() {
     527            echo $this->footer_popup; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped in render_enquiry_pop_up().
     528        }
     529
     530        private function render_enquiry_pop_up($tour_id = 0) {
    504531            // The ttbm_enquery_popup action is fired without arguments from the tour templates.
    505532            $tour_id = absint($tour_id) ?: get_the_ID();
  • tour-booking-manager/tags/2.3.11/admin/TTBM_Payment_Settings.php

    r3781509 r3783145  
    6767                                return TTBM_Global_Function::get_settings('ttbm_payment_settings', $key, $default);
    6868                        }
     69                        // The payment manager echoes stored gateway credentials (WooCommerce
     70                        // gateway forms, TTBM PayPal/Stripe secrets), so every render path
     71                        // needs the same capability as ttbm_settings_page and its AJAX handlers.
     72                        private function can_manage_payments(): bool {
     73                                return current_user_can('manage_options');
     74                        }
    6975                        public function __construct() {
    7076                                add_filter('ttbm_settings_sec_reg', array($this, 'register_section'), 95, 1);
    … …  
    240246                                $pm_type_label = self::get_booking_mode_label();
    241247                                $pm_gateway_names = self::get_active_gateway_names();
     248                                $can_manage = $this->can_manage_payments();
    242249                                ?>
    243250                                <div class="ttbm-sb-card ttbm-sb-payment-card <?php echo $pm_active ? 'is-ready' : 'is-missing'; ?>">
    … …  
    256263                                                        <strong><?php echo esc_html($pm_gateway_names ? implode(', ', $pm_gateway_names) : __('None', 'tour-booking-manager')); ?></strong>
    257264                                                </div>
    258                                                 <?php if ($pm_gateway_names) : ?>
     265                                                <?php if ($can_manage && $pm_gateway_names) : ?>
    259266                                                        <p class="ttbm-sb-payment-link">
    260267                                                                <a href="#" data-ttbm-payment-modal-open><?php esc_html_e('Payment Settings', 'tour-booking-manager'); ?></a>
    261268                                                        </p>
    262269                                                <?php endif; ?>
    263                                                 <?php if (!$pm_active) : ?>
     270                                                <?php if ($can_manage && !$pm_active) : ?>
    264271                                                        <p class="ttbm-sb-payment-warning">
    265272                                                                <a href="#" data-ttbm-payment-modal-open><?php esc_html_e('Configure payment method', 'tour-booking-manager'); ?></a>
    … …  
    320327                        /**
    321328                         * Yellow banner (when needed) + payment modal on tour/hotel edit screens.
    322                          * Banner markup is moved to the top of #post-body via JS; the modal is
    323                          * always available so the sidebar Payment card can open it too.
     329                         * Banner markup is moved to the top of #post-body via JS; for users who
     330                         * can manage payments the modal is always available so the sidebar
     331                         * Payment card can open it too. Other editors (e.g. Contributors) only
     332                         * see the informational banner.
    324333                         */
    325334                        public function maybe_render_edit_payment_notice($post) {
    … …  
    327336                                        return;
    328337                                }
     338                                $can_manage = $this->can_manage_payments();
    329339                                $needs_notice = !self::has_functional_payment_method();
    330340                                if ($needs_notice) {
    … …  
    340350                                                        </div>
    341351                                                </div>
    342                                                 <a href="#" class="ttbm-edit-payment-notice-link" data-ttbm-payment-modal-open>
    343                                                         <?php esc_html_e('Configure payment', 'tour-booking-manager'); ?>
    344                                                 </a>
     352                                                <?php if ($can_manage) : ?>
     353                                                        <a href="#" class="ttbm-edit-payment-notice-link" data-ttbm-payment-modal-open>
     354                                                                <?php esc_html_e('Configure payment', 'tour-booking-manager'); ?>
     355                                                        </a>
     356                                                <?php endif; ?>
    345357                                        </div>
    346358                                        <?php
     359                                }
     360                                if (!$can_manage) {
     361                                        return;
    347362                                }
    348363                                ?>
    … …  
    541556                         */
    542557                        public function render_tab_content() {
     558                                if (!$this->can_manage_payments()) {
     559                                        return;
     560                                }
    543561                                $custom_is_default = self::get_booking_mode() === 'custom';
    544562                                ?>
    … …  
    10171035                        }
    10181036                        public function render_wc_payment_methods() {
     1037                                if (!$this->can_manage_payments()) {
     1038                                        return;
     1039                                }
    10191040                                $gateways = $this->get_gateways();
    10201041                                if (empty($gateways)) {
  • tour-booking-manager/tags/2.3.11/assets/frontend/ttbm_details.css

    r3781509 r3783145  
    20242024   errors, sending state, success panel; bottom sheet on phones.
    20252025   Accent = the tour's Theme Color (--color_theme).
     2026   The popup is printed in wp_footer, outside #ttbm_content, so tour-page
     2027   rules (#ttbm_content h2 ...) cannot reach it; only the shared
     2028   .ttbm_style element rules can, and they are reset below.
    20262029   ===================================================================== */
    20272030div.ttbm_popup.ttbm-enq { background: rgba(15, 23, 42, .55); padding: 24px; box-sizing: border-box; }
    … …  
    20372040@keyframes ttbmEnqSpin { to { transform: rotate(360deg); } }
    20382041
    2039 .ttbm-enq .ttbm-enq__header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 24px 24px 0 28px; }
    2040 .ttbm-enq .ttbm-enq__heading { display: flex; flex-direction: column; gap: 4px; }
    2041 .ttbm-enq .ttbm-enq__eyebrow { margin: 0; font-size: 13px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--color_theme); }
    2042 .ttbm-enq .ttbm-enq__title { margin: 0; padding: 0; font-size: 24px; line-height: 1.25; font-weight: 700; color: #0f172a; text-align: left; }
     2042div.ttbm_popup.ttbm-enq .ttbm-enq__header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 24px 24px 0 28px; }
     2043div.ttbm_popup.ttbm-enq .ttbm-enq__heading { display: flex; flex-direction: column; gap: 4px; }
     2044div.ttbm_popup.ttbm-enq .ttbm-enq__eyebrow { margin: 0; font-size: 13px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--color_theme); }
     2045div.ttbm_popup.ttbm-enq h2.ttbm-enq__title { margin: 0; padding: 0; font-family: inherit; font-size: 24px; line-height: 1.25; font-weight: 700; letter-spacing: normal; text-transform: none; color: #0f172a; text-align: left; }
     2046/* The shared .ttbm_style button / :hover / :focus / [disabled] rules (ttbm_plugin_global.css) restyle
     2047   every button: capitalize, line-height 1, normal weight, theme background at 80% opacity on hover and
     2048   focus, grey when disabled. Every button below resets what it needs. */
     2049div.ttbm_popup.ttbm-enq button { text-transform: none; letter-spacing: normal; line-height: 1.2; opacity: 1; }
    20432050div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close {
    20442051        position: static; flex-shrink: 0; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 10px;
    20452052        background: #f1f5f9; color: #334155; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: background .15s ease;
    20462053}
    2047 div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close:hover { background: #e2e8f0; color: #0f172a; }
    2048 .ttbm-enq .ttbm-enq__close:focus-visible,
    2049 .ttbm-enq .ttbm-enq__submit:focus-visible,
    2050 .ttbm-enq .ttbm-enq__secondary:focus-visible { outline: 2px solid var(--color_theme); outline-offset: 2px; }
    2051 
    2052 .ttbm-enq .ttbm-enq__body { padding: 0; overflow-y: auto; }
    2053 .ttbm-enq .ttbm-enq__tour { margin: 20px 28px 0; padding: 12px; border-radius: 12px; background: #f8fafc; border: 1px solid #e2e8f0; display: flex; align-items: center; gap: 14px; }
    2054 .ttbm-enq .ttbm-enq__tour-img { width: 76px; height: 56px; border-radius: 8px; object-fit: cover; flex-shrink: 0; }
    2055 .ttbm-enq .ttbm-enq__tour-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
    2056 .ttbm-enq .ttbm-enq__tour-text strong { font-size: 15px; font-weight: 600; line-height: 1.3; color: #0f172a; }
    2057 .ttbm-enq .ttbm-enq__tour-text span { font-size: 13px; color: #475569; }
    2058 
    2059 .ttbm-enq .ttbm-enq__panel[hidden] { display: none; }
    2060 .ttbm-enq .ttbm-enq__alert { margin: 16px 28px 0; padding: 10px 12px; border-radius: 8px; background: #fef3f2; border: 1px solid #fecdca; color: #b42318; font-size: 14px; }
    2061 .ttbm-enq .ttbm-enq__alert[hidden] { display: none; }
    2062 .ttbm-enq .ttbm-enq__form { display: flex; flex-direction: column; gap: 16px; padding: 20px 28px 28px; margin: 0; }
    2063 .ttbm-enq .ttbm-enq__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
    2064 .ttbm-enq .ttbm-enq__field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
    2065 .ttbm-enq .ttbm-enq__field label { margin: 0; font-size: 14px; font-weight: 600; color: #0f172a; }
    2066 .ttbm-enq .ttbm-enq__label-row { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
    2067 .ttbm-enq .ttbm-enq__count { font-size: 13px; color: #475569; }
    2068 .ttbm-enq .ttbm-enq__field input,
    2069 .ttbm-enq .ttbm-enq__field textarea {
     2054div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close:hover,
     2055div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close:focus { background: #e2e8f0; color: #0f172a; opacity: 1; }
     2056div.ttbm_popup.ttbm-enq .ttbm-enq__close:focus-visible,
     2057div.ttbm_popup.ttbm-enq .ttbm-enq__submit:focus-visible,
     2058div.ttbm_popup.ttbm-enq .ttbm-enq__secondary:focus-visible { outline: 2px solid var(--color_theme); outline-offset: 2px; }
     2059
     2060div.ttbm_popup.ttbm-enq .ttbm-enq__body { flex: 1 1 auto; min-height: 0; padding: 0; overflow-y: auto; }
     2061div.ttbm_popup.ttbm-enq .ttbm-enq__tour { margin: 20px 28px 0; padding: 12px; border-radius: 12px; background: #f8fafc; border: 1px solid #e2e8f0; display: flex; align-items: center; gap: 14px; }
     2062/* Beats the shared ".ttbm_style img:not(.ttbm_wp_editor img) { width: 100% }", which blew the thumbnail up to card width. */
     2063div.ttbm_popup.ttbm-enq img.ttbm-enq__tour-img { display: block; width: 76px; height: 56px; max-width: none; margin: 0; border-radius: 8px; object-fit: cover; flex: 0 0 auto; }
     2064div.ttbm_popup.ttbm-enq .ttbm-enq__tour-text { flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
     2065div.ttbm_popup.ttbm-enq .ttbm-enq__tour-text strong { font-size: 15px; font-weight: 600; line-height: 1.3; color: #0f172a; }
     2066div.ttbm_popup.ttbm-enq .ttbm-enq__tour-text span { font-size: 13px; color: #475569; }
     2067
     2068div.ttbm_popup.ttbm-enq .ttbm-enq__panel[hidden] { display: none; }
     2069div.ttbm_popup.ttbm-enq .ttbm-enq__alert { margin: 16px 28px 0; padding: 10px 12px; border-radius: 8px; background: #fef3f2; border: 1px solid #fecdca; color: #b42318; font-size: 14px; }
     2070div.ttbm_popup.ttbm-enq .ttbm-enq__alert[hidden] { display: none; }
     2071div.ttbm_popup.ttbm-enq .ttbm-enq__form { display: flex; flex-direction: column; gap: 16px; padding: 20px 28px 28px; margin: 0; }
     2072div.ttbm_popup.ttbm-enq .ttbm-enq__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
     2073div.ttbm_popup.ttbm-enq .ttbm-enq__field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
     2074div.ttbm_popup.ttbm-enq .ttbm-enq__field label { margin: 0; font-size: 14px; font-weight: 600; text-transform: none; color: #0f172a; }
     2075div.ttbm_popup.ttbm-enq .ttbm-enq__label-row { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
     2076div.ttbm_popup.ttbm-enq .ttbm-enq__count { font-size: 13px; color: #475569; }
     2077div.ttbm_popup.ttbm-enq .ttbm-enq__field input,
     2078div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea {
    20702079        width: 100%; box-sizing: border-box; min-height: 44px; margin: 0; padding: 10px 12px; border: 1px solid #cbd5e1; border-radius: 8px;
    20712080        background: #fff; color: #0f172a; font: inherit; font-size: 15px; line-height: 1.5; box-shadow: none;
    20722081        transition: border-color .15s ease, box-shadow .15s ease;
    20732082}
    2074 .ttbm-enq .ttbm-enq__field textarea { resize: vertical; min-height: 120px; }
    2075 .ttbm-enq .ttbm-enq__field input::placeholder,
    2076 .ttbm-enq .ttbm-enq__field textarea::placeholder { color: #64748b; opacity: 1; }
    2077 .ttbm-enq .ttbm-enq__field input:focus,
    2078 .ttbm-enq .ttbm-enq__field textarea:focus { outline: 0; border-color: var(--color_theme); box-shadow: 0 0 0 3px rgba(var(--color_theme_rgb), .18); }
    2079 .ttbm-enq .ttbm-enq__field .is-invalid { border-color: #b42318; }
    2080 .ttbm-enq .ttbm-enq__field .is-invalid:focus { border-color: #b42318; box-shadow: 0 0 0 3px rgba(180, 35, 24, .15); }
    2081 .ttbm-enq .ttbm-enq__error { font-size: 13px; color: #b42318; }
    2082 .ttbm-enq .ttbm-enq__error:empty { display: none; }
    2083 
    2084 .ttbm-enq .ttbm-enq__submit {
     2083div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea { resize: vertical; min-height: 120px; }
     2084div.ttbm_popup.ttbm-enq .ttbm-enq__field input::placeholder,
     2085div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea::placeholder { color: #64748b; opacity: 1; }
     2086div.ttbm_popup.ttbm-enq .ttbm-enq__field input:focus,
     2087div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea:focus { outline: 0; border-color: var(--color_theme); box-shadow: 0 0 0 3px rgba(var(--color_theme_rgb), .18); }
     2088div.ttbm_popup.ttbm-enq .ttbm-enq__field .is-invalid { border-color: #b42318; }
     2089div.ttbm_popup.ttbm-enq .ttbm-enq__field .is-invalid:focus { border-color: #b42318; box-shadow: 0 0 0 3px rgba(180, 35, 24, .15); }
     2090div.ttbm_popup.ttbm-enq .ttbm-enq__error { font-size: 13px; color: #b42318; }
     2091div.ttbm_popup.ttbm-enq .ttbm-enq__error:empty { display: none; }
     2092
     2093div.ttbm_popup.ttbm-enq .ttbm-enq__submit {
    20852094        display: inline-flex; align-items: center; justify-content: center; gap: 10px; width: 100%; min-height: 48px; margin: 0; padding: 0 20px;
    20862095        border: 0; border-radius: 10px; background: var(--color_theme); color: #fff; font: inherit; font-size: 16px; font-weight: 600; cursor: pointer;
    20872096        transition: filter .15s ease, opacity .15s ease;
    20882097}
    2089 .ttbm-enq .ttbm-enq__submit:hover { filter: brightness(.94); color: #fff; }
    2090 .ttbm-enq .ttbm-enq__submit[disabled] { opacity: .8; cursor: progress; }
    2091 .ttbm-enq .ttbm-enq__spinner { display: none; width: 16px; height: 16px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, .45); border-top-color: #fff; animation: ttbmEnqSpin .8s linear infinite; }
    2092 .ttbm-enq .ttbm-enq__submit.is-sending .ttbm-enq__spinner { display: inline-block; }
    2093 .ttbm-enq .ttbm-enq__submit.is-sending .ttbm-enq__send-icon { display: none; }
    2094 .ttbm-enq .ttbm-enq__foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; font-size: 13px; color: #475569; }
    2095 .ttbm-enq .ttbm-enq__foot a { color: var(--color_theme); font-weight: 600; text-decoration: none; }
    2096 .ttbm-enq .ttbm-enq__foot a:hover { text-decoration: underline; }
    2097 
    2098 .ttbm-enq .ttbm-enq__success { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 12px; padding: 36px 28px 32px; }
    2099 .ttbm-enq .ttbm-enq__success-icon { width: 64px; height: 64px; border-radius: 50%; background: rgba(var(--color_theme_rgb), .12); color: var(--color_theme); display: inline-flex; align-items: center; justify-content: center; }
    2100 .ttbm-enq .ttbm-enq__success h3 { margin: 4px 0 0; font-size: 22px; font-weight: 700; color: #0f172a; }
    2101 .ttbm-enq .ttbm-enq__success p { margin: 0; font-size: 15px; line-height: 1.6; color: #334155; max-width: 38ch; }
    2102 .ttbm-enq .ttbm-enq__success-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 12px; }
    2103 .ttbm-enq .ttbm-enq__success-actions .ttbm-enq__submit { width: auto; min-height: 44px; font-size: 15px; }
    2104 .ttbm-enq .ttbm-enq__secondary {
     2098div.ttbm_popup.ttbm-enq .ttbm-enq__submit:hover,
     2099div.ttbm_popup.ttbm-enq .ttbm-enq__submit:focus { background: var(--color_theme); filter: brightness(.94); color: #fff; opacity: 1; }
     2100div.ttbm_popup.ttbm-enq .ttbm-enq__submit[disabled] { opacity: .8; cursor: progress; }
     2101div.ttbm_popup.ttbm-enq .ttbm-enq__spinner { display: none; width: 16px; height: 16px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, .45); border-top-color: #fff; animation: ttbmEnqSpin .8s linear infinite; }
     2102div.ttbm_popup.ttbm-enq .ttbm-enq__submit.is-sending .ttbm-enq__spinner { display: inline-block; }
     2103div.ttbm_popup.ttbm-enq .ttbm-enq__submit.is-sending .ttbm-enq__send-icon { display: none; }
     2104div.ttbm_popup.ttbm-enq .ttbm-enq__foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; font-size: 13px; color: #475569; }
     2105div.ttbm_popup.ttbm-enq .ttbm-enq__foot a { color: var(--color_theme); font-weight: 600; text-decoration: none; }
     2106div.ttbm_popup.ttbm-enq .ttbm-enq__foot a:hover { text-decoration: underline; }
     2107
     2108div.ttbm_popup.ttbm-enq .ttbm-enq__success { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 12px; padding: 36px 28px 32px; }
     2109div.ttbm_popup.ttbm-enq .ttbm-enq__success-icon { width: 64px; height: 64px; border-radius: 50%; background: rgba(var(--color_theme_rgb), .12); color: var(--color_theme); display: inline-flex; align-items: center; justify-content: center; }
     2110div.ttbm_popup.ttbm-enq .ttbm-enq__success h3 { margin: 4px 0 0; font-size: 22px; font-weight: 700; color: #0f172a; }
     2111div.ttbm_popup.ttbm-enq .ttbm-enq__success p { margin: 0; font-size: 15px; line-height: 1.6; color: #334155; max-width: 38ch; }
     2112div.ttbm_popup.ttbm-enq .ttbm-enq__success-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 12px; }
     2113div.ttbm_popup.ttbm-enq .ttbm-enq__success-actions .ttbm-enq__submit { width: auto; min-height: 44px; font-size: 15px; }
     2114div.ttbm_popup.ttbm-enq .ttbm-enq__secondary {
    21052115        min-height: 44px; margin: 0; padding: 0 18px; border-radius: 10px; border: 1px solid #cbd5e1; background: #fff; color: #0f172a;
    21062116        font: inherit; font-size: 15px; font-weight: 500; cursor: pointer;
    21072117}
    2108 .ttbm-enq .ttbm-enq__secondary:hover { background: #f8fafc; }
     2118div.ttbm_popup.ttbm-enq .ttbm-enq__secondary:hover,
     2119div.ttbm_popup.ttbm-enq .ttbm-enq__secondary:focus { background: #f8fafc; color: #0f172a; opacity: 1; }
    21092120
    21102121/* Phones: bottom sheet, one column. */
    … …  
    21132124        div.ttbm_popup.ttbm-enq .popupMainArea { max-width: none; max-height: 94vh; border-radius: 20px 20px 0 0; }
    21142125        div.ttbm_popup.ttbm-enq.in .popupMainArea { animation-name: ttbmEnqSheet; }
    2115         .ttbm-enq .ttbm-enq__header { padding: 18px 16px 0 20px; }
    2116         .ttbm-enq .ttbm-enq__title { font-size: 22px; }
    2117         .ttbm-enq .ttbm-enq__tour { margin: 14px 20px 0; padding: 10px; }
    2118         .ttbm-enq .ttbm-enq__tour-img { width: 60px; height: 46px; }
    2119         .ttbm-enq .ttbm-enq__alert { margin: 14px 20px 0; }
    2120         .ttbm-enq .ttbm-enq__form { padding: 16px 20px 20px; gap: 14px; }
    2121         .ttbm-enq .ttbm-enq__row { grid-template-columns: minmax(0, 1fr); gap: 14px; }
    2122         .ttbm-enq .ttbm-enq__field input,
    2123         .ttbm-enq .ttbm-enq__field textarea { font-size: 16px; } /* stops iOS zooming into the field */
    2124         .ttbm-enq .ttbm-enq__foot { flex-direction: column; align-items: center; text-align: center; }
     2126        div.ttbm_popup.ttbm-enq .ttbm-enq__header { padding: 18px 16px 0 20px; }
     2127        div.ttbm_popup.ttbm-enq h2.ttbm-enq__title { font-size: 22px; }
     2128        div.ttbm_popup.ttbm-enq .ttbm-enq__tour { margin: 14px 20px 0; padding: 10px; }
     2129        div.ttbm_popup.ttbm-enq img.ttbm-enq__tour-img { width: 60px; height: 46px; }
     2130        div.ttbm_popup.ttbm-enq .ttbm-enq__alert { margin: 14px 20px 0; }
     2131        div.ttbm_popup.ttbm-enq .ttbm-enq__form { padding: 16px 20px 20px; gap: 14px; }
     2132        div.ttbm_popup.ttbm-enq .ttbm-enq__row { grid-template-columns: minmax(0, 1fr); gap: 14px; }
     2133        div.ttbm_popup.ttbm-enq .ttbm-enq__field input,
     2134        div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea { font-size: 16px; } /* stops iOS zooming into the field */
     2135        div.ttbm_popup.ttbm-enq .ttbm-enq__foot { flex-direction: column; align-items: center; text-align: center; }
    21252136}
    21262137@keyframes ttbmEnqSheet { from { transform: translateY(100%); } to { transform: none; } }
    … …  
    21282139        div.ttbm_popup.ttbm-enq.in,
    21292140        div.ttbm_popup.ttbm-enq.in .popupMainArea { animation: none; }
    2130         .ttbm-enq .ttbm-enq__spinner { animation-duration: 2s; }
     2141        div.ttbm_popup.ttbm-enq .ttbm-enq__spinner { animation-duration: 2s; }
    21312142}
    21322143
  • tour-booking-manager/tags/2.3.11/readme.txt

    r3781509 r3783145  
    66Tested up to: 7.0
    77Requires PHP: 7.0
    8 Stable tag: 2.3.10
     8Stable tag: 2.3.11
    99License: GPL v2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    232232
    233233== Changelog ==
     234= 2.3.11 – 4 November 2026 =
     235* Security: Payment gateway settings, including saved WooCommerce gateway credentials and PayPal/Stripe keys, are no longer included in the tour and hotel edit screens for users who cannot manage the store's settings (CVE-2026-121794).
     236* Fix: Get Enquiry popup styling no longer inherits theme heading, image and label rules.
     237* Tweak: The Check availability button is hidden by default; the ttbm_show_availability_button filter restores it.
     238
    234239= 2.3.10 – 3 November 2026 =
    235240* Security: Improved security hardening.
  • tour-booking-manager/tags/2.3.11/templates/ticket/tour_default_selection.php

    r3781509 r3783145  
    7575                                                                <?php } ?>
    7676                                                                <?php
    77                                                                 // Tickets load as soon as a date (or slot) is picked, so the Check button is only
    78                                                                 // kept for Pro, which still reloads time slots per date and waits for it.
    79                                                                 if (class_exists('TTBM_Layout_Pro')) {
     77                                                                // Tickets load as soon as a date (or, with Pro's time slots, a slot) is picked, so
     78                                                                // the "Check availability" button adds nothing and is hidden. Pro's scripts check
     79                                                                // that the button exists before showing it. A site can bring it back with
     80                                                                // add_filter( 'ttbm_show_availability_button', '__return_true' ).
     81                                                                if (apply_filters('ttbm_show_availability_button', false, $tour_id)) {
    8082                                                                        TTBM_Layout::availability_button($tour_id, $time_slots_enabled);
    8183                                                                }
  • tour-booking-manager/tags/2.3.11/tour-booking-manager.php

    r3781509 r3783145  
    44 * Plugin URI: http://mage-people.com
    55 * Description: A Complete Tour and Travel Solution for WordPress by MagePeople.
    6  * Version: 2.3.10
     6 * Version: 2.3.11
    77 * Author: MagePeople Team
    88 * Author URI: http://www.mage-people.com/
    … …  
    242242                                }
    243243                                if (!defined('TTBM_PLUGIN_VERSION')) {
    244                                         define('TTBM_PLUGIN_VERSION', '2.3.10');
     244                                        define('TTBM_PLUGIN_VERSION', '2.3.11');
    245245                                }
    246246                                require_once TTBM_PLUGIN_DIR . '/inc/TTBM_Dependencies.php';
  • tour-booking-manager/trunk/admin/TTBM_Get_Enquiry.php

    r3781509 r3783145  
    501501        }
    502502
     503        /** Popup markup waiting for wp_footer. */
     504        private $footer_popup = '';
     505
     506        /**
     507         * ttbm_enquery_popup action. The popup is built here (where the current tour is known) but printed
     508         * in wp_footer, outside #ttbm_content: tour-page rules such as "#ttbm_content h2" (ID selectors)
     509         * otherwise override the popup's own type and colours.
     510         */
    503511        public function get_enquiry_pop_up($tour_id = 0) {
     512            if ($this->footer_popup !== '') {
     513                return; // one popup per page
     514            }
     515            ob_start();
     516            $this->render_enquiry_pop_up($tour_id);
     517            $html = ob_get_clean();
     518            if (did_action('wp_footer') || doing_action('wp_footer')) {
     519                echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped in render_enquiry_pop_up().
     520                return;
     521            }
     522            $this->footer_popup = $html;
     523            add_action('wp_footer', [$this, 'print_footer_popup'], 5);
     524        }
     525
     526        public function print_footer_popup() {
     527            echo $this->footer_popup; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped in render_enquiry_pop_up().
     528        }
     529
     530        private function render_enquiry_pop_up($tour_id = 0) {
    504531            // The ttbm_enquery_popup action is fired without arguments from the tour templates.
    505532            $tour_id = absint($tour_id) ?: get_the_ID();
  • tour-booking-manager/trunk/admin/TTBM_Payment_Settings.php

    r3781509 r3783145  
    6767                                return TTBM_Global_Function::get_settings('ttbm_payment_settings', $key, $default);
    6868                        }
     69                        // The payment manager echoes stored gateway credentials (WooCommerce
     70                        // gateway forms, TTBM PayPal/Stripe secrets), so every render path
     71                        // needs the same capability as ttbm_settings_page and its AJAX handlers.
     72                        private function can_manage_payments(): bool {
     73                                return current_user_can('manage_options');
     74                        }
    6975                        public function __construct() {
    7076                                add_filter('ttbm_settings_sec_reg', array($this, 'register_section'), 95, 1);
    … …  
    240246                                $pm_type_label = self::get_booking_mode_label();
    241247                                $pm_gateway_names = self::get_active_gateway_names();
     248                                $can_manage = $this->can_manage_payments();
    242249                                ?>
    243250                                <div class="ttbm-sb-card ttbm-sb-payment-card <?php echo $pm_active ? 'is-ready' : 'is-missing'; ?>">
    … …  
    256263                                                        <strong><?php echo esc_html($pm_gateway_names ? implode(', ', $pm_gateway_names) : __('None', 'tour-booking-manager')); ?></strong>
    257264                                                </div>
    258                                                 <?php if ($pm_gateway_names) : ?>
     265                                                <?php if ($can_manage && $pm_gateway_names) : ?>
    259266                                                        <p class="ttbm-sb-payment-link">
    260267                                                                <a href="#" data-ttbm-payment-modal-open><?php esc_html_e('Payment Settings', 'tour-booking-manager'); ?></a>
    261268                                                        </p>
    262269                                                <?php endif; ?>
    263                                                 <?php if (!$pm_active) : ?>
     270                                                <?php if ($can_manage && !$pm_active) : ?>
    264271                                                        <p class="ttbm-sb-payment-warning">
    265272                                                                <a href="#" data-ttbm-payment-modal-open><?php esc_html_e('Configure payment method', 'tour-booking-manager'); ?></a>
    … …  
    320327                        /**
    321328                         * Yellow banner (when needed) + payment modal on tour/hotel edit screens.
    322                          * Banner markup is moved to the top of #post-body via JS; the modal is
    323                          * always available so the sidebar Payment card can open it too.
     329                         * Banner markup is moved to the top of #post-body via JS; for users who
     330                         * can manage payments the modal is always available so the sidebar
     331                         * Payment card can open it too. Other editors (e.g. Contributors) only
     332                         * see the informational banner.
    324333                         */
    325334                        public function maybe_render_edit_payment_notice($post) {
    … …  
    327336                                        return;
    328337                                }
     338                                $can_manage = $this->can_manage_payments();
    329339                                $needs_notice = !self::has_functional_payment_method();
    330340                                if ($needs_notice) {
    … …  
    340350                                                        </div>
    341351                                                </div>
    342                                                 <a href="#" class="ttbm-edit-payment-notice-link" data-ttbm-payment-modal-open>
    343                                                         <?php esc_html_e('Configure payment', 'tour-booking-manager'); ?>
    344                                                 </a>
     352                                                <?php if ($can_manage) : ?>
     353                                                        <a href="#" class="ttbm-edit-payment-notice-link" data-ttbm-payment-modal-open>
     354                                                                <?php esc_html_e('Configure payment', 'tour-booking-manager'); ?>
     355                                                        </a>
     356                                                <?php endif; ?>
    345357                                        </div>
    346358                                        <?php
     359                                }
     360                                if (!$can_manage) {
     361                                        return;
    347362                                }
    348363                                ?>
    … …  
    541556                         */
    542557                        public function render_tab_content() {
     558                                if (!$this->can_manage_payments()) {
     559                                        return;
     560                                }
    543561                                $custom_is_default = self::get_booking_mode() === 'custom';
    544562                                ?>
    … …  
    10171035                        }
    10181036                        public function render_wc_payment_methods() {
     1037                                if (!$this->can_manage_payments()) {
     1038                                        return;
     1039                                }
    10191040                                $gateways = $this->get_gateways();
    10201041                                if (empty($gateways)) {
  • tour-booking-manager/trunk/assets/frontend/ttbm_details.css

    r3781509 r3783145  
    20242024   errors, sending state, success panel; bottom sheet on phones.
    20252025   Accent = the tour's Theme Color (--color_theme).
     2026   The popup is printed in wp_footer, outside #ttbm_content, so tour-page
     2027   rules (#ttbm_content h2 ...) cannot reach it; only the shared
     2028   .ttbm_style element rules can, and they are reset below.
    20262029   ===================================================================== */
    20272030div.ttbm_popup.ttbm-enq { background: rgba(15, 23, 42, .55); padding: 24px; box-sizing: border-box; }
    … …  
    20372040@keyframes ttbmEnqSpin { to { transform: rotate(360deg); } }
    20382041
    2039 .ttbm-enq .ttbm-enq__header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 24px 24px 0 28px; }
    2040 .ttbm-enq .ttbm-enq__heading { display: flex; flex-direction: column; gap: 4px; }
    2041 .ttbm-enq .ttbm-enq__eyebrow { margin: 0; font-size: 13px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--color_theme); }
    2042 .ttbm-enq .ttbm-enq__title { margin: 0; padding: 0; font-size: 24px; line-height: 1.25; font-weight: 700; color: #0f172a; text-align: left; }
     2042div.ttbm_popup.ttbm-enq .ttbm-enq__header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 24px 24px 0 28px; }
     2043div.ttbm_popup.ttbm-enq .ttbm-enq__heading { display: flex; flex-direction: column; gap: 4px; }
     2044div.ttbm_popup.ttbm-enq .ttbm-enq__eyebrow { margin: 0; font-size: 13px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--color_theme); }
     2045div.ttbm_popup.ttbm-enq h2.ttbm-enq__title { margin: 0; padding: 0; font-family: inherit; font-size: 24px; line-height: 1.25; font-weight: 700; letter-spacing: normal; text-transform: none; color: #0f172a; text-align: left; }
     2046/* The shared .ttbm_style button / :hover / :focus / [disabled] rules (ttbm_plugin_global.css) restyle
     2047   every button: capitalize, line-height 1, normal weight, theme background at 80% opacity on hover and
     2048   focus, grey when disabled. Every button below resets what it needs. */
     2049div.ttbm_popup.ttbm-enq button { text-transform: none; letter-spacing: normal; line-height: 1.2; opacity: 1; }
    20432050div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close {
    20442051        position: static; flex-shrink: 0; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 10px;
    20452052        background: #f1f5f9; color: #334155; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: background .15s ease;
    20462053}
    2047 div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close:hover { background: #e2e8f0; color: #0f172a; }
    2048 .ttbm-enq .ttbm-enq__close:focus-visible,
    2049 .ttbm-enq .ttbm-enq__submit:focus-visible,
    2050 .ttbm-enq .ttbm-enq__secondary:focus-visible { outline: 2px solid var(--color_theme); outline-offset: 2px; }
    2051 
    2052 .ttbm-enq .ttbm-enq__body { padding: 0; overflow-y: auto; }
    2053 .ttbm-enq .ttbm-enq__tour { margin: 20px 28px 0; padding: 12px; border-radius: 12px; background: #f8fafc; border: 1px solid #e2e8f0; display: flex; align-items: center; gap: 14px; }
    2054 .ttbm-enq .ttbm-enq__tour-img { width: 76px; height: 56px; border-radius: 8px; object-fit: cover; flex-shrink: 0; }
    2055 .ttbm-enq .ttbm-enq__tour-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
    2056 .ttbm-enq .ttbm-enq__tour-text strong { font-size: 15px; font-weight: 600; line-height: 1.3; color: #0f172a; }
    2057 .ttbm-enq .ttbm-enq__tour-text span { font-size: 13px; color: #475569; }
    2058 
    2059 .ttbm-enq .ttbm-enq__panel[hidden] { display: none; }
    2060 .ttbm-enq .ttbm-enq__alert { margin: 16px 28px 0; padding: 10px 12px; border-radius: 8px; background: #fef3f2; border: 1px solid #fecdca; color: #b42318; font-size: 14px; }
    2061 .ttbm-enq .ttbm-enq__alert[hidden] { display: none; }
    2062 .ttbm-enq .ttbm-enq__form { display: flex; flex-direction: column; gap: 16px; padding: 20px 28px 28px; margin: 0; }
    2063 .ttbm-enq .ttbm-enq__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
    2064 .ttbm-enq .ttbm-enq__field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
    2065 .ttbm-enq .ttbm-enq__field label { margin: 0; font-size: 14px; font-weight: 600; color: #0f172a; }
    2066 .ttbm-enq .ttbm-enq__label-row { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
    2067 .ttbm-enq .ttbm-enq__count { font-size: 13px; color: #475569; }
    2068 .ttbm-enq .ttbm-enq__field input,
    2069 .ttbm-enq .ttbm-enq__field textarea {
     2054div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close:hover,
     2055div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close:focus { background: #e2e8f0; color: #0f172a; opacity: 1; }
     2056div.ttbm_popup.ttbm-enq .ttbm-enq__close:focus-visible,
     2057div.ttbm_popup.ttbm-enq .ttbm-enq__submit:focus-visible,
     2058div.ttbm_popup.ttbm-enq .ttbm-enq__secondary:focus-visible { outline: 2px solid var(--color_theme); outline-offset: 2px; }
     2059
     2060div.ttbm_popup.ttbm-enq .ttbm-enq__body { flex: 1 1 auto; min-height: 0; padding: 0; overflow-y: auto; }
     2061div.ttbm_popup.ttbm-enq .ttbm-enq__tour { margin: 20px 28px 0; padding: 12px; border-radius: 12px; background: #f8fafc; border: 1px solid #e2e8f0; display: flex; align-items: center; gap: 14px; }
     2062/* Beats the shared ".ttbm_style img:not(.ttbm_wp_editor img) { width: 100% }", which blew the thumbnail up to card width. */
     2063div.ttbm_popup.ttbm-enq img.ttbm-enq__tour-img { display: block; width: 76px; height: 56px; max-width: none; margin: 0; border-radius: 8px; object-fit: cover; flex: 0 0 auto; }
     2064div.ttbm_popup.ttbm-enq .ttbm-enq__tour-text { flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
     2065div.ttbm_popup.ttbm-enq .ttbm-enq__tour-text strong { font-size: 15px; font-weight: 600; line-height: 1.3; color: #0f172a; }
     2066div.ttbm_popup.ttbm-enq .ttbm-enq__tour-text span { font-size: 13px; color: #475569; }
     2067
     2068div.ttbm_popup.ttbm-enq .ttbm-enq__panel[hidden] { display: none; }
     2069div.ttbm_popup.ttbm-enq .ttbm-enq__alert { margin: 16px 28px 0; padding: 10px 12px; border-radius: 8px; background: #fef3f2; border: 1px solid #fecdca; color: #b42318; font-size: 14px; }
     2070div.ttbm_popup.ttbm-enq .ttbm-enq__alert[hidden] { display: none; }
     2071div.ttbm_popup.ttbm-enq .ttbm-enq__form { display: flex; flex-direction: column; gap: 16px; padding: 20px 28px 28px; margin: 0; }
     2072div.ttbm_popup.ttbm-enq .ttbm-enq__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
     2073div.ttbm_popup.ttbm-enq .ttbm-enq__field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
     2074div.ttbm_popup.ttbm-enq .ttbm-enq__field label { margin: 0; font-size: 14px; font-weight: 600; text-transform: none; color: #0f172a; }
     2075div.ttbm_popup.ttbm-enq .ttbm-enq__label-row { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
     2076div.ttbm_popup.ttbm-enq .ttbm-enq__count { font-size: 13px; color: #475569; }
     2077div.ttbm_popup.ttbm-enq .ttbm-enq__field input,
     2078div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea {
    20702079        width: 100%; box-sizing: border-box; min-height: 44px; margin: 0; padding: 10px 12px; border: 1px solid #cbd5e1; border-radius: 8px;
    20712080        background: #fff; color: #0f172a; font: inherit; font-size: 15px; line-height: 1.5; box-shadow: none;
    20722081        transition: border-color .15s ease, box-shadow .15s ease;
    20732082}
    2074 .ttbm-enq .ttbm-enq__field textarea { resize: vertical; min-height: 120px; }
    2075 .ttbm-enq .ttbm-enq__field input::placeholder,
    2076 .ttbm-enq .ttbm-enq__field textarea::placeholder { color: #64748b; opacity: 1; }
    2077 .ttbm-enq .ttbm-enq__field input:focus,
    2078 .ttbm-enq .ttbm-enq__field textarea:focus { outline: 0; border-color: var(--color_theme); box-shadow: 0 0 0 3px rgba(var(--color_theme_rgb), .18); }
    2079 .ttbm-enq .ttbm-enq__field .is-invalid { border-color: #b42318; }
    2080 .ttbm-enq .ttbm-enq__field .is-invalid:focus { border-color: #b42318; box-shadow: 0 0 0 3px rgba(180, 35, 24, .15); }
    2081 .ttbm-enq .ttbm-enq__error { font-size: 13px; color: #b42318; }
    2082 .ttbm-enq .ttbm-enq__error:empty { display: none; }
    2083 
    2084 .ttbm-enq .ttbm-enq__submit {
     2083div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea { resize: vertical; min-height: 120px; }
     2084div.ttbm_popup.ttbm-enq .ttbm-enq__field input::placeholder,
     2085div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea::placeholder { color: #64748b; opacity: 1; }
     2086div.ttbm_popup.ttbm-enq .ttbm-enq__field input:focus,
     2087div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea:focus { outline: 0; border-color: var(--color_theme); box-shadow: 0 0 0 3px rgba(var(--color_theme_rgb), .18); }
     2088div.ttbm_popup.ttbm-enq .ttbm-enq__field .is-invalid { border-color: #b42318; }
     2089div.ttbm_popup.ttbm-enq .ttbm-enq__field .is-invalid:focus { border-color: #b42318; box-shadow: 0 0 0 3px rgba(180, 35, 24, .15); }
     2090div.ttbm_popup.ttbm-enq .ttbm-enq__error { font-size: 13px; color: #b42318; }
     2091div.ttbm_popup.ttbm-enq .ttbm-enq__error:empty { display: none; }
     2092
     2093div.ttbm_popup.ttbm-enq .ttbm-enq__submit {
    20852094        display: inline-flex; align-items: center; justify-content: center; gap: 10px; width: 100%; min-height: 48px; margin: 0; padding: 0 20px;
    20862095        border: 0; border-radius: 10px; background: var(--color_theme); color: #fff; font: inherit; font-size: 16px; font-weight: 600; cursor: pointer;
    20872096        transition: filter .15s ease, opacity .15s ease;
    20882097}
    2089 .ttbm-enq .ttbm-enq__submit:hover { filter: brightness(.94); color: #fff; }
    2090 .ttbm-enq .ttbm-enq__submit[disabled] { opacity: .8; cursor: progress; }
    2091 .ttbm-enq .ttbm-enq__spinner { display: none; width: 16px; height: 16px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, .45); border-top-color: #fff; animation: ttbmEnqSpin .8s linear infinite; }
    2092 .ttbm-enq .ttbm-enq__submit.is-sending .ttbm-enq__spinner { display: inline-block; }
    2093 .ttbm-enq .ttbm-enq__submit.is-sending .ttbm-enq__send-icon { display: none; }
    2094 .ttbm-enq .ttbm-enq__foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; font-size: 13px; color: #475569; }
    2095 .ttbm-enq .ttbm-enq__foot a { color: var(--color_theme); font-weight: 600; text-decoration: none; }
    2096 .ttbm-enq .ttbm-enq__foot a:hover { text-decoration: underline; }
    2097 
    2098 .ttbm-enq .ttbm-enq__success { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 12px; padding: 36px 28px 32px; }
    2099 .ttbm-enq .ttbm-enq__success-icon { width: 64px; height: 64px; border-radius: 50%; background: rgba(var(--color_theme_rgb), .12); color: var(--color_theme); display: inline-flex; align-items: center; justify-content: center; }
    2100 .ttbm-enq .ttbm-enq__success h3 { margin: 4px 0 0; font-size: 22px; font-weight: 700; color: #0f172a; }
    2101 .ttbm-enq .ttbm-enq__success p { margin: 0; font-size: 15px; line-height: 1.6; color: #334155; max-width: 38ch; }
    2102 .ttbm-enq .ttbm-enq__success-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 12px; }
    2103 .ttbm-enq .ttbm-enq__success-actions .ttbm-enq__submit { width: auto; min-height: 44px; font-size: 15px; }
    2104 .ttbm-enq .ttbm-enq__secondary {
     2098div.ttbm_popup.ttbm-enq .ttbm-enq__submit:hover,
     2099div.ttbm_popup.ttbm-enq .ttbm-enq__submit:focus { background: var(--color_theme); filter: brightness(.94); color: #fff; opacity: 1; }
     2100div.ttbm_popup.ttbm-enq .ttbm-enq__submit[disabled] { opacity: .8; cursor: progress; }
     2101div.ttbm_popup.ttbm-enq .ttbm-enq__spinner { display: none; width: 16px; height: 16px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, .45); border-top-color: #fff; animation: ttbmEnqSpin .8s linear infinite; }
     2102div.ttbm_popup.ttbm-enq .ttbm-enq__submit.is-sending .ttbm-enq__spinner { display: inline-block; }
     2103div.ttbm_popup.ttbm-enq .ttbm-enq__submit.is-sending .ttbm-enq__send-icon { display: none; }
     2104div.ttbm_popup.ttbm-enq .ttbm-enq__foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; font-size: 13px; color: #475569; }
     2105div.ttbm_popup.ttbm-enq .ttbm-enq__foot a { color: var(--color_theme); font-weight: 600; text-decoration: none; }
     2106div.ttbm_popup.ttbm-enq .ttbm-enq__foot a:hover { text-decoration: underline; }
     2107
     2108div.ttbm_popup.ttbm-enq .ttbm-enq__success { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 12px; padding: 36px 28px 32px; }
     2109div.ttbm_popup.ttbm-enq .ttbm-enq__success-icon { width: 64px; height: 64px; border-radius: 50%; background: rgba(var(--color_theme_rgb), .12); color: var(--color_theme); display: inline-flex; align-items: center; justify-content: center; }
     2110div.ttbm_popup.ttbm-enq .ttbm-enq__success h3 { margin: 4px 0 0; font-size: 22px; font-weight: 700; color: #0f172a; }
     2111div.ttbm_popup.ttbm-enq .ttbm-enq__success p { margin: 0; font-size: 15px; line-height: 1.6; color: #334155; max-width: 38ch; }
     2112div.ttbm_popup.ttbm-enq .ttbm-enq__success-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 12px; }
     2113div.ttbm_popup.ttbm-enq .ttbm-enq__success-actions .ttbm-enq__submit { width: auto; min-height: 44px; font-size: 15px; }
     2114div.ttbm_popup.ttbm-enq .ttbm-enq__secondary {
    21052115        min-height: 44px; margin: 0; padding: 0 18px; border-radius: 10px; border: 1px solid #cbd5e1; background: #fff; color: #0f172a;
    21062116        font: inherit; font-size: 15px; font-weight: 500; cursor: pointer;
    21072117}
    2108 .ttbm-enq .ttbm-enq__secondary:hover { background: #f8fafc; }
     2118div.ttbm_popup.ttbm-enq .ttbm-enq__secondary:hover,
     2119div.ttbm_popup.ttbm-enq .ttbm-enq__secondary:focus { background: #f8fafc; color: #0f172a; opacity: 1; }
    21092120
    21102121/* Phones: bottom sheet, one column. */
    … …  
    21132124        div.ttbm_popup.ttbm-enq .popupMainArea { max-width: none; max-height: 94vh; border-radius: 20px 20px 0 0; }
    21142125        div.ttbm_popup.ttbm-enq.in .popupMainArea { animation-name: ttbmEnqSheet; }
    2115         .ttbm-enq .ttbm-enq__header { padding: 18px 16px 0 20px; }
    2116         .ttbm-enq .ttbm-enq__title { font-size: 22px; }
    2117         .ttbm-enq .ttbm-enq__tour { margin: 14px 20px 0; padding: 10px; }
    2118         .ttbm-enq .ttbm-enq__tour-img { width: 60px; height: 46px; }
    2119         .ttbm-enq .ttbm-enq__alert { margin: 14px 20px 0; }
    2120         .ttbm-enq .ttbm-enq__form { padding: 16px 20px 20px; gap: 14px; }
    2121         .ttbm-enq .ttbm-enq__row { grid-template-columns: minmax(0, 1fr); gap: 14px; }
    2122         .ttbm-enq .ttbm-enq__field input,
    2123         .ttbm-enq .ttbm-enq__field textarea { font-size: 16px; } /* stops iOS zooming into the field */
    2124         .ttbm-enq .ttbm-enq__foot { flex-direction: column; align-items: center; text-align: center; }
     2126        div.ttbm_popup.ttbm-enq .ttbm-enq__header { padding: 18px 16px 0 20px; }
     2127        div.ttbm_popup.ttbm-enq h2.ttbm-enq__title { font-size: 22px; }
     2128        div.ttbm_popup.ttbm-enq .ttbm-enq__tour { margin: 14px 20px 0; padding: 10px; }
     2129        div.ttbm_popup.ttbm-enq img.ttbm-enq__tour-img { width: 60px; height: 46px; }
     2130        div.ttbm_popup.ttbm-enq .ttbm-enq__alert { margin: 14px 20px 0; }
     2131        div.ttbm_popup.ttbm-enq .ttbm-enq__form { padding: 16px 20px 20px; gap: 14px; }
     2132        div.ttbm_popup.ttbm-enq .ttbm-enq__row { grid-template-columns: minmax(0, 1fr); gap: 14px; }
     2133        div.ttbm_popup.ttbm-enq .ttbm-enq__field input,
     2134        div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea { font-size: 16px; } /* stops iOS zooming into the field */
     2135        div.ttbm_popup.ttbm-enq .ttbm-enq__foot { flex-direction: column; align-items: center; text-align: center; }
    21252136}
    21262137@keyframes ttbmEnqSheet { from { transform: translateY(100%); } to { transform: none; } }
    … …  
    21282139        div.ttbm_popup.ttbm-enq.in,
    21292140        div.ttbm_popup.ttbm-enq.in .popupMainArea { animation: none; }
    2130         .ttbm-enq .ttbm-enq__spinner { animation-duration: 2s; }
     2141        div.ttbm_popup.ttbm-enq .ttbm-enq__spinner { animation-duration: 2s; }
    21312142}
    21322143
  • tour-booking-manager/trunk/readme.txt

    r3781509 r3783145  
    66Tested up to: 7.0
    77Requires PHP: 7.0
    8 Stable tag: 2.3.10
     8Stable tag: 2.3.11
    99License: GPL v2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    232232
    233233== Changelog ==
     234= 2.3.11 – 4 November 2026 =
     235* Security: Payment gateway settings, including saved WooCommerce gateway credentials and PayPal/Stripe keys, are no longer included in the tour and hotel edit screens for users who cannot manage the store's settings (CVE-2026-121794).
     236* Fix: Get Enquiry popup styling no longer inherits theme heading, image and label rules.
     237* Tweak: The Check availability button is hidden by default; the ttbm_show_availability_button filter restores it.
     238
    234239= 2.3.10 – 3 November 2026 =
    235240* Security: Improved security hardening.
  • tour-booking-manager/trunk/templates/ticket/tour_default_selection.php

    r3781509 r3783145  
    7575                                                                <?php } ?>
    7676                                                                <?php
    77                                                                 // Tickets load as soon as a date (or slot) is picked, so the Check button is only
    78                                                                 // kept for Pro, which still reloads time slots per date and waits for it.
    79                                                                 if (class_exists('TTBM_Layout_Pro')) {
     77                                                                // Tickets load as soon as a date (or, with Pro's time slots, a slot) is picked, so
     78                                                                // the "Check availability" button adds nothing and is hidden. Pro's scripts check
     79                                                                // that the button exists before showing it. A site can bring it back with
     80                                                                // add_filter( 'ttbm_show_availability_button', '__return_true' ).
     81                                                                if (apply_filters('ttbm_show_availability_button', false, $tour_id)) {
    8082                                                                        TTBM_Layout::availability_button($tour_id, $time_slots_enabled);
    8183                                                                }
  • tour-booking-manager/trunk/tour-booking-manager.php

    r3781509 r3783145  
    44 * Plugin URI: http://mage-people.com
    55 * Description: A Complete Tour and Travel Solution for WordPress by MagePeople.
    6  * Version: 2.3.10
     6 * Version: 2.3.11
    77 * Author: MagePeople Team
    88 * Author URI: http://www.mage-people.com/
    … …  
    242242                                }
    243243                                if (!defined('TTBM_PLUGIN_VERSION')) {
    244                                         define('TTBM_PLUGIN_VERSION', '2.3.10');
     244                                        define('TTBM_PLUGIN_VERSION', '2.3.11');
    245245                                }
    246246                                require_once TTBM_PLUGIN_DIR . '/inc/TTBM_Dependencies.php';
Note: See TracChangeset for help on using the changeset viewer.