| @@ -85,8 +85,35 @@ | ||
| 85 | 85 | $this->enable_country_filter = $attributes['enableCountryFilter'] ?? false; |
| 86 | 86 | $this->country_filter_type = $attributes['countryFilterType'] ?? 'include'; |
| 87 | 87 | $this->include_countries = $attributes['includeCountries'] ?? []; |
| 88 | 88 | $this->exclude_countries = $attributes['excludeCountries'] ?? []; |
| 89 | + | |
| 90 | + // When auto country is enabled, resolve a best-effort country here at render | |
| 91 | + // time to seed the baked `default-country` attribute (a sensible flag before | |
| 92 | + // any JS runs). The authoritative per-visitor detection happens client-side: | |
| 93 | + // phone.js applies an immediate network-free Intl guess and then refines it | |
| 94 | + // from the same-origin geo-country REST endpoint — so it stays correct even on | |
| 95 | + // full-page-cached sites, where this baked value would otherwise be the first | |
| 96 | + // visitor's country. | |
| 97 | + // | |
| 98 | + // Why not get_locale()? | |
| 99 | + // WordPress get_locale() returns the *site's* configured language (e.g. 'en_US'), | |
| 100 | + // not the visitor's physical location. A site set to English would show 'US' for | |
| 101 | + // every visitor worldwide — defeating the purpose of auto-country detection. | |
| 102 | + // | |
| 103 | + // Why resolve server-side at all (vs. a browser geo-IP fetch)? | |
| 104 | + // A client-side fetch('https://ipapi.co/json') caused CORS failures, 429 rate | |
| 105 | + // limits on high-traffic sites, and exposed visitor IPs to a third party from the | |
| 106 | + // browser. The server path (CDN header first, then a capped, cached ipapi.co | |
| 107 | + // lookup in Helper::get_geo_country()) avoids all three. | |
| 108 | + if ( $this->auto_country ) { | |
| 109 | + // Pass the configured default as the fallback so a detection failure | |
| 110 | + // degrades to the user's chosen country instead of a hardcoded 'us'. | |
| 111 | + $fallback = ! empty( $this->default_country ) && is_string( $this->default_country ) | |
| 112 | + ? strtolower( $this->default_country ) | |
| 113 | + : 'us'; | |
| 114 | + $this->default_country = Helper::get_geo_country( $fallback ); | |
| 115 | + } | |
| 89 | 116 | $this->set_unique_slug(); |
| 90 | 117 | $this->set_field_name( $this->unique_slug ); |
| 91 | 118 | $this->set_markup_properties( $this->input_label, true ); |
| 92 | 119 | $this->set_aria_described_by(); |
| @@ -111,10 +138,12 @@ | ||
| 111 | 138 | id="<?php echo esc_attr( $this->unique_slug ); ?>" |
| 112 | 139 | <?php echo ! empty( $this->aria_described_by ) ? "aria-describedby='" . esc_attr( trim( $this->aria_described_by ) ) . "'" : ''; ?> |
| 113 | 140 | data-required="<?php echo esc_attr( $this->data_require_attr ); ?>" |
| 114 | 141 | aria-required="<?php echo esc_attr( $this->data_require_attr ); ?>" |
| 115 | - auto-country="<?php echo esc_attr( $this->auto_country ? 'true' : 'false' ); ?>" | |
| 116 | 142 | default-country="<?php echo esc_attr( $this->default_country ); ?>" |
| 143 | + <?php if ( $this->auto_country ) { ?> | |
| 144 | + data-auto-country="true" | |
| 145 | + <?php } ?> | |
| 117 | 146 | <?php if ( $this->enable_country_filter ) { ?> |
| 118 | 147 | data-enable-country-filter="true" |
| 119 | 148 | data-country-filter-type="<?php echo esc_attr( $this->country_filter_type ); ?>" |
| 120 | 149 | <?php if ( 'include' === $this->country_filter_type && ! empty( $this->include_countries ) ) { ?> |
| @@ -133,5 +162,6 @@ | ||
| 133 | 162 | </div> |
| 134 | 163 | <?php |
| 135 | 164 | return ob_get_clean(); |
| 136 | 165 | } |
| 166 | + | |
| 137 | 167 | } |