Changeset 3751965
- Timestamp:
- 10/17/2026 01:38:55 PM (3 weeks ago)
- Location:
- quotanto
- Files:
-
- 31 added
- 6 edited
-
tags/1.0.1 (added)
-
tags/1.0.1/assets (added)
-
tags/1.0.1/assets/quotanto.css (added)
-
tags/1.0.1/assets/quote-cart.js (added)
-
tags/1.0.1/blocks (added)
-
tags/1.0.1/blocks/request-button (added)
-
tags/1.0.1/blocks/request-button/block.json (added)
-
tags/1.0.1/includes (added)
-
tags/1.0.1/includes/class-quotanto-abilities.php (added)
-
tags/1.0.1/includes/class-quotanto-account.php (added)
-
tags/1.0.1/includes/class-quotanto-captcha.php (added)
-
tags/1.0.1/includes/class-quotanto-catalog.php (added)
-
tags/1.0.1/includes/class-quotanto-emails.php (added)
-
tags/1.0.1/includes/class-quotanto-lifecycle.php (added)
-
tags/1.0.1/includes/class-quotanto-plugin.php (added)
-
tags/1.0.1/includes/class-quotanto-quote.php (added)
-
tags/1.0.1/includes/class-quotanto-request-form.php (added)
-
tags/1.0.1/includes/class-quotanto-settings-page.php (added)
-
tags/1.0.1/includes/class-quotanto-settings.php (added)
-
tags/1.0.1/includes/class-quotanto-statuses.php (added)
-
tags/1.0.1/includes/emails (added)
-
tags/1.0.1/includes/emails/class-quotanto-email-new-request.php (added)
-
tags/1.0.1/includes/emails/class-quotanto-email-quote.php (added)
-
tags/1.0.1/includes/emails/class-quotanto-email-request-received.php (added)
-
tags/1.0.1/includes/emails/class-quotanto-email.php (added)
-
tags/1.0.1/languages (added)
-
tags/1.0.1/languages/quotanto.pot (added)
-
tags/1.0.1/quotanto.php (added)
-
tags/1.0.1/readme.txt (added)
-
tags/1.0.1/uninstall.php (added)
-
tags/1.0.1/wpml-config.xml (added)
-
trunk/assets/quotanto.css (modified) (1 diff)
-
trunk/blocks/request-button/block.json (modified) (1 diff)
-
trunk/includes/class-quotanto-request-form.php (modified) (5 diffs)
-
trunk/languages/quotanto.pot (modified) (4 diffs)
-
trunk/quotanto.php (modified) (2 diffs)
-
trunk/readme.txt (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
quotanto/trunk/assets/quotanto.css
r3746953 r3751965 104 104 } 105 105 106 /* The quote box printed for a quote cart goes once the last quote-only line is removed, as it would after a reload. */ 107 body:not(.quotanto-quote-cart) .quotanto--quote-cart { 108 display: none; 109 } 110 106 111 /* With hidden prices it shows no prices and no totals either, instead of zeros. */ 107 112 .quotanto-quote-cart-no-prices .wc-block-cart__sidebar, -
quotanto/trunk/blocks/request-button/block.json
r3746953 r3751965 3 3 "apiVersion": 3, 4 4 "name": "quotanto/request-button", 5 "version": "1.0. 0",5 "version": "1.0.1", 6 6 "title": "Request a quote", 7 7 "category": "woocommerce", -
quotanto/trunk/includes/class-quotanto-request-form.php
r3746953 r3751965 392 392 echo '</div>'; 393 393 } elseif ( Quotanto_Catalog::cart_needs_quote() ) { 394 echo '<div class="quotanto " id="quotanto-cart"><p class="quotanto__notice quotanto__notice--error" role="alert">' . esc_html__( 'Remove the products that cannot be quoted to send this cart as a request.', 'quotanto' ) . '</p></div>';394 echo '<div class="quotanto quotanto--quote-cart" id="quotanto-cart"><p class="quotanto__notice quotanto__notice--error" role="alert">' . esc_html__( 'Remove the products that cannot be quoted to send this cart as a request.', 'quotanto' ) . '</p></div>'; 395 395 } 396 396 return; … … 440 440 $prefill = self::prefill(); 441 441 // A cart that can only be quoted shows its form open: it is the only way forward. 442 $open = ( '' !== $state && 'sent' !== $state ) || ( null === $product && Quotanto_Catalog::cart_needs_quote() ); 442 $quote_cart = null === $product && Quotanto_Catalog::cart_needs_quote(); 443 $open = ( '' !== $state && 'sent' !== $state ) || $quote_cart; 443 444 444 445 $hidden = array( 'action' => self::ACTION ) + $hidden + array( … … 449 450 450 451 ?> 451 <div class="quotanto " id="<?php echo esc_attr( $id ); ?>">452 <div class="quotanto<?php echo esc_attr( $quote_cart ? ' quotanto--quote-cart' : '' ); ?>" id="<?php echo esc_attr( $id ); ?>"> 452 453 <?php self::print_notice( $state ); ?> 453 <?php if ( null === $product && Quotanto_Catalog::cart_needs_quote()) : ?>454 <?php if ( $quote_cart ) : ?> 454 455 <p class="quotanto__note"><?php esc_html_e( 'These products are sold by quote. Send the cart as a request and we will reply with prices.', 'quotanto' ); ?></p> 455 456 <?php endif; ?> … … 527 528 528 529 /** 530 * The visitor's IP for the hourly rate limit. 531 * 532 * Uses the address WooCommerce stores on orders, which reads the forwarded headers a proxy such as 533 * Cloudflare sends; behind a proxy the server's own address is the proxy's, shared by every visitor. 534 * 535 * @return string IP address, or 'unknown'. 536 */ 537 private static function rate_limit_ip(): string { 538 $ip = class_exists( 'WC_Geolocation' ) ? WC_Geolocation::get_ip_address() : ''; 539 540 /** 541 * Filters the IP address the request form's hourly rate limit counts by. 542 * 543 * @param string $ip IP address of the visitor, as WooCommerce detects it. 544 */ 545 $ip = sanitize_text_field( (string) apply_filters( 'quotanto_rate_limit_ip', $ip ) ); 546 547 return '' === $ip ? 'unknown' : $ip; 548 } 549 550 /** 529 551 * Redirects back to the page the form was on, with the state. 530 552 * … … 683 705 } 684 706 685 $ip_key = 'quotanto_rl_' . md5( isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : 'unknown');707 $ip_key = 'quotanto_rl_' . md5( self::rate_limit_ip() ); 686 708 $count = (int) get_transient( $ip_key ); 687 709 if ( $count >= self::RATE_LIMIT ) { -
quotanto/trunk/languages/quotanto.pot
r3746953 r3751965 3 3 msgid "" 4 4 msgstr "" 5 "Project-Id-Version: Quotanto 1.0. 0\n"5 "Project-Id-Version: Quotanto 1.0.1\n" 6 6 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/quotanto\n" 7 7 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" … … 10 10 "Content-Type: text/plain; charset=UTF-8\n" 11 11 "Content-Transfer-Encoding: 8bit\n" 12 "POT-Creation-Date: 2026-10-1 1T20:31:49+02:00\n"12 "POT-Creation-Date: 2026-10-17T15:17:36+02:00\n" 13 13 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 14 14 "X-Generator: WP-CLI 2.12.0\n" … … 77 77 78 78 #: includes/class-quotanto-captcha.php:183 79 #: includes/class-quotanto-request-form.php:52 179 #: includes/class-quotanto-request-form.php:522 80 80 msgid "Please complete the captcha and try again." 81 81 msgstr "" … … 195 195 msgstr "" 196 196 197 #: includes/class-quotanto-request-form.php:45 4197 #: includes/class-quotanto-request-form.php:455 198 198 msgid "These products are sold by quote. Send the cart as a request and we will reply with prices." 199 199 msgstr "" 200 200 201 #: includes/class-quotanto-request-form.php:4 69201 #: includes/class-quotanto-request-form.php:470 202 202 msgid "Quantity" 203 203 msgstr "" 204 204 205 #: includes/class-quotanto-request-form.php:47 4205 #: includes/class-quotanto-request-form.php:475 206 206 msgid "Your name" 207 207 msgstr "" 208 208 209 #: includes/class-quotanto-request-form.php:47 8209 #: includes/class-quotanto-request-form.php:479 210 210 msgid "Email address" 211 211 msgstr "" 212 212 213 #: includes/class-quotanto-request-form.php:48 3213 #: includes/class-quotanto-request-form.php:484 214 214 #: includes/class-quotanto-settings-page.php:160 215 215 msgid "Phone" 216 216 msgstr "" 217 217 218 #: includes/class-quotanto-request-form.php:48 3218 #: includes/class-quotanto-request-form.php:484 219 219 msgid "Phone (optional)" 220 220 msgstr "" 221 221 222 #: includes/class-quotanto-request-form.php:48 4222 #: includes/class-quotanto-request-form.php:485 223 223 msgid "Digits, spaces and + ( ) - . only" 224 224 msgstr "" 225 225 226 #: includes/class-quotanto-request-form.php:4 89226 #: includes/class-quotanto-request-form.php:490 227 227 msgid "Anything we should know?" 228 228 msgstr "" 229 229 230 #: includes/class-quotanto-request-form.php:4 89230 #: includes/class-quotanto-request-form.php:490 231 231 msgid "Anything we should know? (optional)" 232 232 msgstr "" 233 233 234 #: includes/class-quotanto-request-form.php:50 7234 #: includes/class-quotanto-request-form.php:508 235 235 msgid "Send request" 236 236 msgstr "" 237 237 238 #: includes/class-quotanto-request-form.php:52 2238 #: includes/class-quotanto-request-form.php:523 239 239 msgid "Too many requests from this connection. Please try again in an hour." 240 240 msgstr "" 241 241 242 #: includes/class-quotanto-request-form.php:52 3242 #: includes/class-quotanto-request-form.php:524 243 243 msgid "Please check the form and try again. If the page has been open for a long time, reload it first." 244 244 msgstr "" 245 245 246 #: includes/class-quotanto-request-form.php:52 4246 #: includes/class-quotanto-request-form.php:525 247 247 msgid "We could not save your request. Please try again in a moment." 248 248 msgstr "" 249 249 250 #: includes/class-quotanto-request-form.php:7 22250 #: includes/class-quotanto-request-form.php:744 251 251 msgid "Quote requested from the cart." 252 252 msgstr "" 253 253 254 #: includes/class-quotanto-request-form.php:7 22254 #: includes/class-quotanto-request-form.php:744 255 255 msgid "Quote requested from the product page." 256 256 msgstr "" -
quotanto/trunk/quotanto.php
r3746953 r3751965 4 4 * Plugin URI: https://quotanto.com 5 5 * Description: Let customers request a quote, price it in WooCommerce, and let them pay at your normal checkout. Works with block cart and checkout. 6 * Version: 1.0. 06 * Version: 1.0.1 7 7 * Requires at least: 6.9 8 8 * Requires PHP: 8.1 … … 21 21 defined( 'ABSPATH' ) || exit; 22 22 23 define( 'QUOTANTO_VERSION', '1.0. 0' );23 define( 'QUOTANTO_VERSION', '1.0.1' ); 24 24 define( 'QUOTANTO_FILE', __FILE__ ); 25 25 define( 'QUOTANTO_DIR', plugin_dir_path( __FILE__ ) ); -
quotanto/trunk/readme.txt
r3746953 r3751965 6 6 Requires PHP: 8.1 7 7 Requires Plugins: woocommerce 8 Stable tag: 1.0. 08 Stable tag: 1.0.1 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 29 29 * Quotes expire on their own. 30 30 31 = Everything is free=31 = Features = 32 32 33 33 * Simple and variable products. … … 105 105 Built-in spam protection, with no third-party service. 106 106 107 = Does it work behind Cloudflare? = 108 109 Yes. The hourly request limit counts each visitor, not the proxy. 110 107 111 = Can I add a captcha? = 108 112 … … 133 137 == Changelog == 134 138 139 = 1.0.1 = 140 * Fix: Request limit counts each visitor, also behind a proxy. 141 * Fix: Cart quote form hides when the last quote-only product is removed. 142 * Dev: New filter `quotanto_rate_limit_ip`. 143 135 144 = 1.0.0 = 136 145 * First release.
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)