Changeset 3783145
- Timestamp:
- 11/04/2026 06:00:15 AM (4 days ago)
- Location:
- tour-booking-manager
- Files:
-
- 12 edited
- 1 copied
-
tags/2.3.11 (copied) (copied from tour-booking-manager/trunk )
-
tags/2.3.11/admin/TTBM_Get_Enquiry.php (modified) (1 diff)
-
tags/2.3.11/admin/TTBM_Payment_Settings.php (modified) (8 diffs)
-
tags/2.3.11/assets/frontend/ttbm_details.css (modified) (4 diffs)
-
tags/2.3.11/readme.txt (modified) (2 diffs)
-
tags/2.3.11/templates/ticket/tour_default_selection.php (modified) (1 diff)
-
tags/2.3.11/tour-booking-manager.php (modified) (2 diffs)
-
trunk/admin/TTBM_Get_Enquiry.php (modified) (1 diff)
-
trunk/admin/TTBM_Payment_Settings.php (modified) (8 diffs)
-
trunk/assets/frontend/ttbm_details.css (modified) (4 diffs)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/templates/ticket/tour_default_selection.php (modified) (1 diff)
-
trunk/tour-booking-manager.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
tour-booking-manager/tags/2.3.11/admin/TTBM_Get_Enquiry.php
r3781509 r3783145 501 501 } 502 502 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 */ 503 511 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) { 504 531 // The ttbm_enquery_popup action is fired without arguments from the tour templates. 505 532 $tour_id = absint($tour_id) ?: get_the_ID(); -
tour-booking-manager/tags/2.3.11/admin/TTBM_Payment_Settings.php
r3781509 r3783145 67 67 return TTBM_Global_Function::get_settings('ttbm_payment_settings', $key, $default); 68 68 } 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 } 69 75 public function __construct() { 70 76 add_filter('ttbm_settings_sec_reg', array($this, 'register_section'), 95, 1); … … 240 246 $pm_type_label = self::get_booking_mode_label(); 241 247 $pm_gateway_names = self::get_active_gateway_names(); 248 $can_manage = $this->can_manage_payments(); 242 249 ?> 243 250 <div class="ttbm-sb-card ttbm-sb-payment-card <?php echo $pm_active ? 'is-ready' : 'is-missing'; ?>"> … … 256 263 <strong><?php echo esc_html($pm_gateway_names ? implode(', ', $pm_gateway_names) : __('None', 'tour-booking-manager')); ?></strong> 257 264 </div> 258 <?php if ($ pm_gateway_names) : ?>265 <?php if ($can_manage && $pm_gateway_names) : ?> 259 266 <p class="ttbm-sb-payment-link"> 260 267 <a href="#" data-ttbm-payment-modal-open><?php esc_html_e('Payment Settings', 'tour-booking-manager'); ?></a> 261 268 </p> 262 269 <?php endif; ?> 263 <?php if ( !$pm_active) : ?>270 <?php if ($can_manage && !$pm_active) : ?> 264 271 <p class="ttbm-sb-payment-warning"> 265 272 <a href="#" data-ttbm-payment-modal-open><?php esc_html_e('Configure payment method', 'tour-booking-manager'); ?></a> … … 320 327 /** 321 328 * 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. 324 333 */ 325 334 public function maybe_render_edit_payment_notice($post) { … … 327 336 return; 328 337 } 338 $can_manage = $this->can_manage_payments(); 329 339 $needs_notice = !self::has_functional_payment_method(); 330 340 if ($needs_notice) { … … 340 350 </div> 341 351 </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; ?> 345 357 </div> 346 358 <?php 359 } 360 if (!$can_manage) { 361 return; 347 362 } 348 363 ?> … … 541 556 */ 542 557 public function render_tab_content() { 558 if (!$this->can_manage_payments()) { 559 return; 560 } 543 561 $custom_is_default = self::get_booking_mode() === 'custom'; 544 562 ?> … … 1017 1035 } 1018 1036 public function render_wc_payment_methods() { 1037 if (!$this->can_manage_payments()) { 1038 return; 1039 } 1019 1040 $gateways = $this->get_gateways(); 1020 1041 if (empty($gateways)) { -
tour-booking-manager/tags/2.3.11/assets/frontend/ttbm_details.css
r3781509 r3783145 2024 2024 errors, sending state, success panel; bottom sheet on phones. 2025 2025 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. 2026 2029 ===================================================================== */ 2027 2030 div.ttbm_popup.ttbm-enq { background: rgba(15, 23, 42, .55); padding: 24px; box-sizing: border-box; } … … 2037 2040 @keyframes ttbmEnqSpin { to { transform: rotate(360deg); } } 2038 2041 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; } 2042 div.ttbm_popup.ttbm-enq .ttbm-enq__header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 24px 24px 0 28px; } 2043 div.ttbm_popup.ttbm-enq .ttbm-enq__heading { display: flex; flex-direction: column; gap: 4px; } 2044 div.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); } 2045 div.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. */ 2049 div.ttbm_popup.ttbm-enq button { text-transform: none; letter-spacing: normal; line-height: 1.2; opacity: 1; } 2043 2050 div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close { 2044 2051 position: static; flex-shrink: 0; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 10px; 2045 2052 background: #f1f5f9; color: #334155; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: background .15s ease; 2046 2053 } 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 { 2054 div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close:hover, 2055 div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close:focus { background: #e2e8f0; color: #0f172a; opacity: 1; } 2056 div.ttbm_popup.ttbm-enq .ttbm-enq__close:focus-visible, 2057 div.ttbm_popup.ttbm-enq .ttbm-enq__submit:focus-visible, 2058 div.ttbm_popup.ttbm-enq .ttbm-enq__secondary:focus-visible { outline: 2px solid var(--color_theme); outline-offset: 2px; } 2059 2060 div.ttbm_popup.ttbm-enq .ttbm-enq__body { flex: 1 1 auto; min-height: 0; padding: 0; overflow-y: auto; } 2061 div.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. */ 2063 div.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; } 2064 div.ttbm_popup.ttbm-enq .ttbm-enq__tour-text { flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; min-width: 0; } 2065 div.ttbm_popup.ttbm-enq .ttbm-enq__tour-text strong { font-size: 15px; font-weight: 600; line-height: 1.3; color: #0f172a; } 2066 div.ttbm_popup.ttbm-enq .ttbm-enq__tour-text span { font-size: 13px; color: #475569; } 2067 2068 div.ttbm_popup.ttbm-enq .ttbm-enq__panel[hidden] { display: none; } 2069 div.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; } 2070 div.ttbm_popup.ttbm-enq .ttbm-enq__alert[hidden] { display: none; } 2071 div.ttbm_popup.ttbm-enq .ttbm-enq__form { display: flex; flex-direction: column; gap: 16px; padding: 20px 28px 28px; margin: 0; } 2072 div.ttbm_popup.ttbm-enq .ttbm-enq__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; } 2073 div.ttbm_popup.ttbm-enq .ttbm-enq__field { display: flex; flex-direction: column; gap: 6px; min-width: 0; } 2074 div.ttbm_popup.ttbm-enq .ttbm-enq__field label { margin: 0; font-size: 14px; font-weight: 600; text-transform: none; color: #0f172a; } 2075 div.ttbm_popup.ttbm-enq .ttbm-enq__label-row { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; } 2076 div.ttbm_popup.ttbm-enq .ttbm-enq__count { font-size: 13px; color: #475569; } 2077 div.ttbm_popup.ttbm-enq .ttbm-enq__field input, 2078 div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea { 2070 2079 width: 100%; box-sizing: border-box; min-height: 44px; margin: 0; padding: 10px 12px; border: 1px solid #cbd5e1; border-radius: 8px; 2071 2080 background: #fff; color: #0f172a; font: inherit; font-size: 15px; line-height: 1.5; box-shadow: none; 2072 2081 transition: border-color .15s ease, box-shadow .15s ease; 2073 2082 } 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 {2083 div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea { resize: vertical; min-height: 120px; } 2084 div.ttbm_popup.ttbm-enq .ttbm-enq__field input::placeholder, 2085 div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea::placeholder { color: #64748b; opacity: 1; } 2086 div.ttbm_popup.ttbm-enq .ttbm-enq__field input:focus, 2087 div.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); } 2088 div.ttbm_popup.ttbm-enq .ttbm-enq__field .is-invalid { border-color: #b42318; } 2089 div.ttbm_popup.ttbm-enq .ttbm-enq__field .is-invalid:focus { border-color: #b42318; box-shadow: 0 0 0 3px rgba(180, 35, 24, .15); } 2090 div.ttbm_popup.ttbm-enq .ttbm-enq__error { font-size: 13px; color: #b42318; } 2091 div.ttbm_popup.ttbm-enq .ttbm-enq__error:empty { display: none; } 2092 2093 div.ttbm_popup.ttbm-enq .ttbm-enq__submit { 2085 2094 display: inline-flex; align-items: center; justify-content: center; gap: 10px; width: 100%; min-height: 48px; margin: 0; padding: 0 20px; 2086 2095 border: 0; border-radius: 10px; background: var(--color_theme); color: #fff; font: inherit; font-size: 16px; font-weight: 600; cursor: pointer; 2087 2096 transition: filter .15s ease, opacity .15s ease; 2088 2097 } 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 { 2098 div.ttbm_popup.ttbm-enq .ttbm-enq__submit:hover, 2099 div.ttbm_popup.ttbm-enq .ttbm-enq__submit:focus { background: var(--color_theme); filter: brightness(.94); color: #fff; opacity: 1; } 2100 div.ttbm_popup.ttbm-enq .ttbm-enq__submit[disabled] { opacity: .8; cursor: progress; } 2101 div.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; } 2102 div.ttbm_popup.ttbm-enq .ttbm-enq__submit.is-sending .ttbm-enq__spinner { display: inline-block; } 2103 div.ttbm_popup.ttbm-enq .ttbm-enq__submit.is-sending .ttbm-enq__send-icon { display: none; } 2104 div.ttbm_popup.ttbm-enq .ttbm-enq__foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; font-size: 13px; color: #475569; } 2105 div.ttbm_popup.ttbm-enq .ttbm-enq__foot a { color: var(--color_theme); font-weight: 600; text-decoration: none; } 2106 div.ttbm_popup.ttbm-enq .ttbm-enq__foot a:hover { text-decoration: underline; } 2107 2108 div.ttbm_popup.ttbm-enq .ttbm-enq__success { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 12px; padding: 36px 28px 32px; } 2109 div.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; } 2110 div.ttbm_popup.ttbm-enq .ttbm-enq__success h3 { margin: 4px 0 0; font-size: 22px; font-weight: 700; color: #0f172a; } 2111 div.ttbm_popup.ttbm-enq .ttbm-enq__success p { margin: 0; font-size: 15px; line-height: 1.6; color: #334155; max-width: 38ch; } 2112 div.ttbm_popup.ttbm-enq .ttbm-enq__success-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 12px; } 2113 div.ttbm_popup.ttbm-enq .ttbm-enq__success-actions .ttbm-enq__submit { width: auto; min-height: 44px; font-size: 15px; } 2114 div.ttbm_popup.ttbm-enq .ttbm-enq__secondary { 2105 2115 min-height: 44px; margin: 0; padding: 0 18px; border-radius: 10px; border: 1px solid #cbd5e1; background: #fff; color: #0f172a; 2106 2116 font: inherit; font-size: 15px; font-weight: 500; cursor: pointer; 2107 2117 } 2108 .ttbm-enq .ttbm-enq__secondary:hover { background: #f8fafc; } 2118 div.ttbm_popup.ttbm-enq .ttbm-enq__secondary:hover, 2119 div.ttbm_popup.ttbm-enq .ttbm-enq__secondary:focus { background: #f8fafc; color: #0f172a; opacity: 1; } 2109 2120 2110 2121 /* Phones: bottom sheet, one column. */ … … 2113 2124 div.ttbm_popup.ttbm-enq .popupMainArea { max-width: none; max-height: 94vh; border-radius: 20px 20px 0 0; } 2114 2125 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; } 2125 2136 } 2126 2137 @keyframes ttbmEnqSheet { from { transform: translateY(100%); } to { transform: none; } } … … 2128 2139 div.ttbm_popup.ttbm-enq.in, 2129 2140 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; } 2131 2142 } 2132 2143 -
tour-booking-manager/tags/2.3.11/readme.txt
r3781509 r3783145 6 6 Tested up to: 7.0 7 7 Requires PHP: 7.0 8 Stable tag: 2.3.1 08 Stable tag: 2.3.11 9 9 License: GPL v2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 232 232 233 233 == 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 234 239 = 2.3.10 – 3 November 2026 = 235 240 * Security: Improved security hardening. -
tour-booking-manager/tags/2.3.11/templates/ticket/tour_default_selection.php
r3781509 r3783145 75 75 <?php } ?> 76 76 <?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)) { 80 82 TTBM_Layout::availability_button($tour_id, $time_slots_enabled); 81 83 } -
tour-booking-manager/tags/2.3.11/tour-booking-manager.php
r3781509 r3783145 4 4 * Plugin URI: http://mage-people.com 5 5 * Description: A Complete Tour and Travel Solution for WordPress by MagePeople. 6 * Version: 2.3.1 06 * Version: 2.3.11 7 7 * Author: MagePeople Team 8 8 * Author URI: http://www.mage-people.com/ … … 242 242 } 243 243 if (!defined('TTBM_PLUGIN_VERSION')) { 244 define('TTBM_PLUGIN_VERSION', '2.3.1 0');244 define('TTBM_PLUGIN_VERSION', '2.3.11'); 245 245 } 246 246 require_once TTBM_PLUGIN_DIR . '/inc/TTBM_Dependencies.php'; -
tour-booking-manager/trunk/admin/TTBM_Get_Enquiry.php
r3781509 r3783145 501 501 } 502 502 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 */ 503 511 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) { 504 531 // The ttbm_enquery_popup action is fired without arguments from the tour templates. 505 532 $tour_id = absint($tour_id) ?: get_the_ID(); -
tour-booking-manager/trunk/admin/TTBM_Payment_Settings.php
r3781509 r3783145 67 67 return TTBM_Global_Function::get_settings('ttbm_payment_settings', $key, $default); 68 68 } 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 } 69 75 public function __construct() { 70 76 add_filter('ttbm_settings_sec_reg', array($this, 'register_section'), 95, 1); … … 240 246 $pm_type_label = self::get_booking_mode_label(); 241 247 $pm_gateway_names = self::get_active_gateway_names(); 248 $can_manage = $this->can_manage_payments(); 242 249 ?> 243 250 <div class="ttbm-sb-card ttbm-sb-payment-card <?php echo $pm_active ? 'is-ready' : 'is-missing'; ?>"> … … 256 263 <strong><?php echo esc_html($pm_gateway_names ? implode(', ', $pm_gateway_names) : __('None', 'tour-booking-manager')); ?></strong> 257 264 </div> 258 <?php if ($ pm_gateway_names) : ?>265 <?php if ($can_manage && $pm_gateway_names) : ?> 259 266 <p class="ttbm-sb-payment-link"> 260 267 <a href="#" data-ttbm-payment-modal-open><?php esc_html_e('Payment Settings', 'tour-booking-manager'); ?></a> 261 268 </p> 262 269 <?php endif; ?> 263 <?php if ( !$pm_active) : ?>270 <?php if ($can_manage && !$pm_active) : ?> 264 271 <p class="ttbm-sb-payment-warning"> 265 272 <a href="#" data-ttbm-payment-modal-open><?php esc_html_e('Configure payment method', 'tour-booking-manager'); ?></a> … … 320 327 /** 321 328 * 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. 324 333 */ 325 334 public function maybe_render_edit_payment_notice($post) { … … 327 336 return; 328 337 } 338 $can_manage = $this->can_manage_payments(); 329 339 $needs_notice = !self::has_functional_payment_method(); 330 340 if ($needs_notice) { … … 340 350 </div> 341 351 </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; ?> 345 357 </div> 346 358 <?php 359 } 360 if (!$can_manage) { 361 return; 347 362 } 348 363 ?> … … 541 556 */ 542 557 public function render_tab_content() { 558 if (!$this->can_manage_payments()) { 559 return; 560 } 543 561 $custom_is_default = self::get_booking_mode() === 'custom'; 544 562 ?> … … 1017 1035 } 1018 1036 public function render_wc_payment_methods() { 1037 if (!$this->can_manage_payments()) { 1038 return; 1039 } 1019 1040 $gateways = $this->get_gateways(); 1020 1041 if (empty($gateways)) { -
tour-booking-manager/trunk/assets/frontend/ttbm_details.css
r3781509 r3783145 2024 2024 errors, sending state, success panel; bottom sheet on phones. 2025 2025 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. 2026 2029 ===================================================================== */ 2027 2030 div.ttbm_popup.ttbm-enq { background: rgba(15, 23, 42, .55); padding: 24px; box-sizing: border-box; } … … 2037 2040 @keyframes ttbmEnqSpin { to { transform: rotate(360deg); } } 2038 2041 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; } 2042 div.ttbm_popup.ttbm-enq .ttbm-enq__header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 24px 24px 0 28px; } 2043 div.ttbm_popup.ttbm-enq .ttbm-enq__heading { display: flex; flex-direction: column; gap: 4px; } 2044 div.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); } 2045 div.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. */ 2049 div.ttbm_popup.ttbm-enq button { text-transform: none; letter-spacing: normal; line-height: 1.2; opacity: 1; } 2043 2050 div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close { 2044 2051 position: static; flex-shrink: 0; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 10px; 2045 2052 background: #f1f5f9; color: #334155; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: background .15s ease; 2046 2053 } 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 { 2054 div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close:hover, 2055 div.ttbm_popup.ttbm-enq .popupClose.ttbm-enq__close:focus { background: #e2e8f0; color: #0f172a; opacity: 1; } 2056 div.ttbm_popup.ttbm-enq .ttbm-enq__close:focus-visible, 2057 div.ttbm_popup.ttbm-enq .ttbm-enq__submit:focus-visible, 2058 div.ttbm_popup.ttbm-enq .ttbm-enq__secondary:focus-visible { outline: 2px solid var(--color_theme); outline-offset: 2px; } 2059 2060 div.ttbm_popup.ttbm-enq .ttbm-enq__body { flex: 1 1 auto; min-height: 0; padding: 0; overflow-y: auto; } 2061 div.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. */ 2063 div.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; } 2064 div.ttbm_popup.ttbm-enq .ttbm-enq__tour-text { flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; min-width: 0; } 2065 div.ttbm_popup.ttbm-enq .ttbm-enq__tour-text strong { font-size: 15px; font-weight: 600; line-height: 1.3; color: #0f172a; } 2066 div.ttbm_popup.ttbm-enq .ttbm-enq__tour-text span { font-size: 13px; color: #475569; } 2067 2068 div.ttbm_popup.ttbm-enq .ttbm-enq__panel[hidden] { display: none; } 2069 div.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; } 2070 div.ttbm_popup.ttbm-enq .ttbm-enq__alert[hidden] { display: none; } 2071 div.ttbm_popup.ttbm-enq .ttbm-enq__form { display: flex; flex-direction: column; gap: 16px; padding: 20px 28px 28px; margin: 0; } 2072 div.ttbm_popup.ttbm-enq .ttbm-enq__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; } 2073 div.ttbm_popup.ttbm-enq .ttbm-enq__field { display: flex; flex-direction: column; gap: 6px; min-width: 0; } 2074 div.ttbm_popup.ttbm-enq .ttbm-enq__field label { margin: 0; font-size: 14px; font-weight: 600; text-transform: none; color: #0f172a; } 2075 div.ttbm_popup.ttbm-enq .ttbm-enq__label-row { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; } 2076 div.ttbm_popup.ttbm-enq .ttbm-enq__count { font-size: 13px; color: #475569; } 2077 div.ttbm_popup.ttbm-enq .ttbm-enq__field input, 2078 div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea { 2070 2079 width: 100%; box-sizing: border-box; min-height: 44px; margin: 0; padding: 10px 12px; border: 1px solid #cbd5e1; border-radius: 8px; 2071 2080 background: #fff; color: #0f172a; font: inherit; font-size: 15px; line-height: 1.5; box-shadow: none; 2072 2081 transition: border-color .15s ease, box-shadow .15s ease; 2073 2082 } 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 {2083 div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea { resize: vertical; min-height: 120px; } 2084 div.ttbm_popup.ttbm-enq .ttbm-enq__field input::placeholder, 2085 div.ttbm_popup.ttbm-enq .ttbm-enq__field textarea::placeholder { color: #64748b; opacity: 1; } 2086 div.ttbm_popup.ttbm-enq .ttbm-enq__field input:focus, 2087 div.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); } 2088 div.ttbm_popup.ttbm-enq .ttbm-enq__field .is-invalid { border-color: #b42318; } 2089 div.ttbm_popup.ttbm-enq .ttbm-enq__field .is-invalid:focus { border-color: #b42318; box-shadow: 0 0 0 3px rgba(180, 35, 24, .15); } 2090 div.ttbm_popup.ttbm-enq .ttbm-enq__error { font-size: 13px; color: #b42318; } 2091 div.ttbm_popup.ttbm-enq .ttbm-enq__error:empty { display: none; } 2092 2093 div.ttbm_popup.ttbm-enq .ttbm-enq__submit { 2085 2094 display: inline-flex; align-items: center; justify-content: center; gap: 10px; width: 100%; min-height: 48px; margin: 0; padding: 0 20px; 2086 2095 border: 0; border-radius: 10px; background: var(--color_theme); color: #fff; font: inherit; font-size: 16px; font-weight: 600; cursor: pointer; 2087 2096 transition: filter .15s ease, opacity .15s ease; 2088 2097 } 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 { 2098 div.ttbm_popup.ttbm-enq .ttbm-enq__submit:hover, 2099 div.ttbm_popup.ttbm-enq .ttbm-enq__submit:focus { background: var(--color_theme); filter: brightness(.94); color: #fff; opacity: 1; } 2100 div.ttbm_popup.ttbm-enq .ttbm-enq__submit[disabled] { opacity: .8; cursor: progress; } 2101 div.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; } 2102 div.ttbm_popup.ttbm-enq .ttbm-enq__submit.is-sending .ttbm-enq__spinner { display: inline-block; } 2103 div.ttbm_popup.ttbm-enq .ttbm-enq__submit.is-sending .ttbm-enq__send-icon { display: none; } 2104 div.ttbm_popup.ttbm-enq .ttbm-enq__foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; font-size: 13px; color: #475569; } 2105 div.ttbm_popup.ttbm-enq .ttbm-enq__foot a { color: var(--color_theme); font-weight: 600; text-decoration: none; } 2106 div.ttbm_popup.ttbm-enq .ttbm-enq__foot a:hover { text-decoration: underline; } 2107 2108 div.ttbm_popup.ttbm-enq .ttbm-enq__success { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 12px; padding: 36px 28px 32px; } 2109 div.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; } 2110 div.ttbm_popup.ttbm-enq .ttbm-enq__success h3 { margin: 4px 0 0; font-size: 22px; font-weight: 700; color: #0f172a; } 2111 div.ttbm_popup.ttbm-enq .ttbm-enq__success p { margin: 0; font-size: 15px; line-height: 1.6; color: #334155; max-width: 38ch; } 2112 div.ttbm_popup.ttbm-enq .ttbm-enq__success-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 12px; } 2113 div.ttbm_popup.ttbm-enq .ttbm-enq__success-actions .ttbm-enq__submit { width: auto; min-height: 44px; font-size: 15px; } 2114 div.ttbm_popup.ttbm-enq .ttbm-enq__secondary { 2105 2115 min-height: 44px; margin: 0; padding: 0 18px; border-radius: 10px; border: 1px solid #cbd5e1; background: #fff; color: #0f172a; 2106 2116 font: inherit; font-size: 15px; font-weight: 500; cursor: pointer; 2107 2117 } 2108 .ttbm-enq .ttbm-enq__secondary:hover { background: #f8fafc; } 2118 div.ttbm_popup.ttbm-enq .ttbm-enq__secondary:hover, 2119 div.ttbm_popup.ttbm-enq .ttbm-enq__secondary:focus { background: #f8fafc; color: #0f172a; opacity: 1; } 2109 2120 2110 2121 /* Phones: bottom sheet, one column. */ … … 2113 2124 div.ttbm_popup.ttbm-enq .popupMainArea { max-width: none; max-height: 94vh; border-radius: 20px 20px 0 0; } 2114 2125 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; } 2125 2136 } 2126 2137 @keyframes ttbmEnqSheet { from { transform: translateY(100%); } to { transform: none; } } … … 2128 2139 div.ttbm_popup.ttbm-enq.in, 2129 2140 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; } 2131 2142 } 2132 2143 -
tour-booking-manager/trunk/readme.txt
r3781509 r3783145 6 6 Tested up to: 7.0 7 7 Requires PHP: 7.0 8 Stable tag: 2.3.1 08 Stable tag: 2.3.11 9 9 License: GPL v2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 232 232 233 233 == 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 234 239 = 2.3.10 – 3 November 2026 = 235 240 * Security: Improved security hardening. -
tour-booking-manager/trunk/templates/ticket/tour_default_selection.php
r3781509 r3783145 75 75 <?php } ?> 76 76 <?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)) { 80 82 TTBM_Layout::availability_button($tour_id, $time_slots_enabled); 81 83 } -
tour-booking-manager/trunk/tour-booking-manager.php
r3781509 r3783145 4 4 * Plugin URI: http://mage-people.com 5 5 * Description: A Complete Tour and Travel Solution for WordPress by MagePeople. 6 * Version: 2.3.1 06 * Version: 2.3.11 7 7 * Author: MagePeople Team 8 8 * Author URI: http://www.mage-people.com/ … … 242 242 } 243 243 if (!defined('TTBM_PLUGIN_VERSION')) { 244 define('TTBM_PLUGIN_VERSION', '2.3.1 0');244 define('TTBM_PLUGIN_VERSION', '2.3.11'); 245 245 } 246 246 require_once TTBM_PLUGIN_DIR . '/inc/TTBM_Dependencies.php';
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)