Changeset 3419619
- Timestamp:
- 12/15/2025 12:17:32 AM (4 months ago)
- Location:
- bandwidth-saver/trunk
- Files:
-
- 7 edited
-
admin/css/imgpro-cdn-admin.css (modified) (2 diffs)
-
admin/js/imgpro-cdn-admin.js (modified) (1 diff)
-
imgpro-cdn.php (modified) (2 diffs)
-
includes/class-imgpro-cdn-admin-ajax.php (modified) (3 diffs)
-
includes/class-imgpro-cdn-admin.php (modified) (5 diffs)
-
includes/class-imgpro-cdn-api.php (modified) (3 diffs)
-
readme.txt (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
bandwidth-saver/trunk/admin/css/imgpro-cdn-admin.css
r3411500 r3419619 271 271 } 272 272 273 .imgpro-btn-primary:hover { 273 .imgpro-btn-primary:hover, 274 .imgpro-btn-primary:focus, 275 a.imgpro-btn-primary:hover, 276 a.imgpro-btn-primary:focus, 277 a.imgpro-btn-primary:visited { 274 278 background: var(--imgpro-primary-700); 275 279 border-color: var(--imgpro-primary-700); 276 280 box-shadow: 0 2px 8px rgba(0, 51, 255, 0.25); 281 color: white; 277 282 } 278 283 … … 1021 1026 gap: var(--imgpro-space-6); 1022 1027 padding: var(--imgpro-space-5) var(--imgpro-space-6); 1028 margin-bottom: var(--imgpro-space-4); 1023 1029 background: var(--imgpro-bg); 1024 1030 border: 1px solid var(--imgpro-border); -
bandwidth-saver/trunk/admin/js/imgpro-cdn-admin.js
r3411500 r3419619 363 363 // Revert toggle 364 364 $toggle.prop('checked', !isEnabled); 365 showNotice('error', response.data.message || imgproCdnAdmin.i18n.settingsError); 365 // Account exists with email - show recovery modal 366 if (response.data.show_recovery) { 367 showRecoveryVerificationModal(response.data.email_hint); 368 } else { 369 showNotice('error', response.data.message || imgproCdnAdmin.i18n.settingsError); 370 } 366 371 } 367 372 }, -
bandwidth-saver/trunk/imgpro-cdn.php
r3411500 r3419619 4 4 * Plugin URI: https://github.com/img-pro/bandwidth-saver 5 5 * Description: Instant image CDN. 100 GB/month free, no DNS changes, no external accounts. 6 * Version: 0.2. 36 * Version: 0.2.4 7 7 * Author: ImgPro 8 8 * Author URI: https://img.pro … … 47 47 // Define plugin constants 48 48 if (!defined('IMGPRO_CDN_VERSION')) { 49 define('IMGPRO_CDN_VERSION', '0.2. 3');49 define('IMGPRO_CDN_VERSION', '0.2.4'); 50 50 } 51 51 if (!defined('IMGPRO_CDN_PLUGIN_DIR')) { -
bandwidth-saver/trunk/includes/class-imgpro-cdn-admin-ajax.php
r3410342 r3419619 134 134 135 135 /** 136 * Auto-register a cloud account when toggling on for the first time 137 * 138 * This enables frictionless activation without requiring email upfront. 139 * Email is collected later when user upgrades via Stripe. 140 * 141 * @since 0.2.3 142 * @return true|WP_Error True on success, WP_Error on failure 143 */ 144 private function auto_register_cloud_account() { 145 $site_url = get_site_url(); 146 147 // Register without email (frictionless free activation) 148 $result = $this->api->create_site(null, $site_url, false); 149 150 if (is_wp_error($result)) { 151 $error_code = $result->get_error_code(); 152 153 // Handle existing account with email - needs recovery 154 if ('conflict' === $error_code) { 155 // Clear any stale API key from singleton before calling public endpoint 156 $this->api->set_api_key(null); 157 158 // Automatically request recovery code 159 $recovery_result = $this->api->request_recovery($site_url); 160 161 if (!is_wp_error($recovery_result)) { 162 // Check if this is a no-email account (no recovery needed) 163 if (!empty($recovery_result['no_recovery_needed'])) { 164 // This shouldn't happen since we just tried to register 165 // But handle it gracefully - try again 166 return new WP_Error('registration_failed', __('Registration failed. Please try again.', 'bandwidth-saver')); 167 } 168 169 // Recovery email sent 170 return new WP_Error('account_exists', __('We found an existing account for this site. Please check your email for a verification code.', 'bandwidth-saver'), [ 171 'show_recovery' => true, 172 'email_hint' => $recovery_result['email_hint'] ?? null, 173 ]); 174 } 175 176 return new WP_Error('recovery_failed', __('An account exists but recovery failed. Please try again.', 'bandwidth-saver')); 177 } 178 179 // Other API errors 180 return $result; 181 } 182 183 // Success - save site data to settings 184 $this->save_site_data_to_settings($result); 185 186 return true; 187 } 188 189 /** 190 * Save site data from API response to plugin settings 191 * 192 * @since 0.2.3 193 * @param array $site Site data from API 194 * @return void 195 */ 196 private function save_site_data_to_settings($site) { 197 $data = [ 198 'setup_mode' => ImgPro_CDN_Settings::MODE_CLOUD, 199 'cloud_api_key' => $site['api_key'] ?? '', 200 'cloud_tier' => $site['tier']['id'] ?? ImgPro_CDN_Settings::TIER_FREE, 201 'onboarding_completed' => true, 202 ]; 203 204 // Only set email if provided 205 if (!empty($site['email'])) { 206 $data['cloud_email'] = $site['email']; 207 } 208 209 // Extract source domains if available 210 if (!empty($site['domains'])) { 211 $domains = []; 212 foreach ($site['domains'] as $domain_info) { 213 if (!empty($domain_info['domain'])) { 214 $domains[] = $domain_info['domain']; 215 } 216 } 217 if (!empty($domains)) { 218 $data['source_urls'] = $domains; 219 } 220 } 221 222 $this->settings->update($data); 223 } 224 225 /** 136 226 * AJAX handler for toggling CDN enabled state 137 227 * … … 158 248 $current_settings = $this->settings->get_all(); 159 249 250 $auto_registered = false; 251 160 252 // Check if the mode is properly configured before allowing enable 161 253 if ($enabled && !ImgPro_CDN_Settings::is_mode_valid($mode, $current_settings)) { 162 wp_send_json_error(['message' => __('Please complete setup first before enabling.', 'bandwidth-saver')]); 163 return; 254 // For cloud mode: auto-register if not yet set up 255 if (ImgPro_CDN_Settings::MODE_CLOUD === $mode) { 256 $registration_result = $this->auto_register_cloud_account(); 257 if (is_wp_error($registration_result)) { 258 $error_data = $registration_result->get_error_data(); 259 260 // Check if this needs recovery flow (account with email) 261 if (!empty($error_data['show_recovery'])) { 262 wp_send_json_error([ 263 'message' => $registration_result->get_error_message(), 264 'code' => $registration_result->get_error_code(), 265 'show_recovery' => true, 266 'email_hint' => $error_data['email_hint'] ?? null, 267 ]); 268 return; 269 } 270 271 wp_send_json_error([ 272 'message' => $registration_result->get_error_message(), 273 'code' => $registration_result->get_error_code(), 274 ]); 275 return; 276 } 277 // Registration succeeded - refresh settings and flag for page reload 278 $this->settings->clear_cache(); 279 $current_settings = $this->settings->get_all(); 280 $auto_registered = true; 281 } else { 282 // Cloudflare mode still requires manual setup 283 wp_send_json_error(['message' => __('Please complete setup first before enabling.', 'bandwidth-saver')]); 284 return; 285 } 164 286 } 165 287 … … 194 316 : __('Image CDN disabled. Images now load from your server.', 'bandwidth-saver'); 195 317 196 wp_send_json_success(['message' => $message]); 318 $response = ['message' => $message]; 319 320 // If we just auto-registered, reload page to show full dashboard 321 if ($auto_registered) { 322 $response['redirect'] = admin_url('options-general.php?page=imgpro-cdn-settings&tab=cloud&activated=1'); 323 } 324 325 wp_send_json_success($response); 197 326 } else { 198 327 wp_send_json_error(['message' => __('Could not save settings. Please try again.', 'bandwidth-saver')]); -
bandwidth-saver/trunk/includes/class-imgpro-cdn-admin.php
r3411500 r3419619 574 574 575 575 if (filter_input(INPUT_GET, 'activated', FILTER_VALIDATE_BOOLEAN)) { 576 $tier = $this->settings->get('cloud_tier', ImgPro_CDN_Settings::TIER_FREE); 577 $is_free = ImgPro_CDN_Settings::TIER_FREE === $tier; 576 578 ?> 577 579 <div class="imgpro-notice imgpro-notice-success"> 578 580 <svg width="20" height="20" viewBox="0 0 20 20" fill="none"><circle cx="10" cy="10" r="8" stroke="currentColor" stroke-width="2"/><path d="M6 10l3 3 5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> 579 <p><strong><?php esc_html_e('Subscription activated. Your images now load from the global edge network.', 'bandwidth-saver'); ?></strong></p> 581 <p><strong> 582 <?php if ($is_free): ?> 583 <?php esc_html_e('Account activated. Your images now load from the global edge network.', 'bandwidth-saver'); ?> 584 <?php else: ?> 585 <?php esc_html_e('Subscription activated. Your images now load from the global edge network.', 'bandwidth-saver'); ?> 586 <?php endif; ?> 587 </strong></p> 580 588 </div> 581 589 <?php … … 620 628 $settings = $this->settings->get_all(); 621 629 622 // Check if should show onboarding 623 if ($this->onboarding->should_show_onboarding()) { 624 $this->render_onboarding_page(); 625 return; 626 } 630 // Onboarding wizard disabled - frictionless activation via toggle 631 // Users now toggle ON directly, which auto-registers if needed 632 // Keeping onboarding code for potential future use (e.g., guided tours) 627 633 628 634 // Handle mode switching (nonce verified immediately after isset check) … … 1116 1122 */ 1117 1123 private function render_cloud_tab($settings) { 1118 $is_configured = !empty($settings['cloud_api_key']);1119 1124 $tier = $settings['cloud_tier'] ?? ImgPro_CDN_Settings::TIER_NONE; 1120 $has_subscription = in_array($tier, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE], true); 1121 $pricing = $this->get_pricing(); 1125 $has_subscription = in_array($tier, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE, ImgPro_CDN_Settings::TIER_PAST_DUE], true); 1122 1126 ?> 1123 1127 <div class="imgpro-tab-panel" role="tabpanel"> 1124 1128 <?php if (!$has_subscription): ?> 1125 <?php $this->render_cloud_signup($pricing); ?> 1129 <?php // New install - show toggle card (will auto-register on first enable) ?> 1130 <?php $this->render_toggle_card($settings, ImgPro_CDN_Settings::MODE_CLOUD); ?> 1131 <p class="imgpro-safety-note"> 1132 <?php esc_html_e('Your original images stay on your server. Turning the CDN off or deactivating the plugin will not break your site — image URLs simply return to normal.', 'bandwidth-saver'); ?> 1133 </p> 1126 1134 <?php else: ?> 1127 1135 <?php $this->render_cloud_settings($settings); ?> … … 1339 1347 </div> 1340 1348 <div class="imgpro-account-card__footer"> 1341 <span><?php echo esc_html($email); ?></span>1342 <span class="imgpro-separator">·</span>1343 1349 <span><?php esc_html_e('Free Plan — 100 GB/month included', 'bandwidth-saver'); ?></span> 1350 <?php if (!empty($email)): ?> 1351 <span class="imgpro-separator">·</span> 1352 <span><?php echo esc_html($email); ?></span> 1353 <?php endif; ?> 1344 1354 </div> 1345 1355 </div> … … 1377 1387 </div> 1378 1388 <div class="imgpro-account-card__footer"> 1379 <span><?php echo esc_html($email); ?></span> 1389 <?php if (!empty($email)): ?> 1390 <span><?php echo esc_html($email); ?></span> 1391 <?php endif; ?> 1380 1392 <?php if (!$is_business): ?> 1381 <span class="imgpro-separator">·</span> 1393 <?php if (!empty($email)): ?> 1394 <span class="imgpro-separator">·</span> 1395 <?php endif; ?> 1382 1396 <button type="button" class="imgpro-btn-link" id="imgpro-manage-subscription"> 1383 1397 <?php esc_html_e('Manage Subscription', 'bandwidth-saver'); ?> -
bandwidth-saver/trunk/includes/class-imgpro-cdn-api.php
r3410342 r3419619 277 277 * Create new site account 278 278 * 279 * @param string $email User email. 280 * @param string $site_url WordPress site URL. 281 * @param bool $marketing_opt_in Marketing consent. 279 * Email is optional for free accounts. If the site_url already exists: 280 * - If existing site has NO email: returns existing site (reconnection) 281 * - If existing site HAS email: returns conflict (requires recovery) 282 * 283 * @param string|null $email User email (optional for free tier). 284 * @param string $site_url WordPress site URL. 285 * @param bool $marketing_opt_in Marketing consent. 282 286 * @return array|WP_Error Site data array or error. 283 287 */ 284 288 public function create_site($email, $site_url, $marketing_opt_in = false) { 285 if (empty($ email) || empty($site_url)) {286 return new WP_Error('missing_fields', __(' Email and site URL arerequired', 'bandwidth-saver'));289 if (empty($site_url)) { 290 return new WP_Error('missing_fields', __('Site URL is required', 'bandwidth-saver')); 287 291 } 288 292 … … 290 294 $this->set_api_key(null); 291 295 292 $response = $this->request('POST', '/api/sites', [ 293 'email' => $email, 296 $data = [ 294 297 'site_url' => $site_url, 295 298 'marketing_opt_in' => $marketing_opt_in, 296 ]); 299 ]; 300 301 // Only include email if provided 302 if (!empty($email)) { 303 $data['email'] = $email; 304 } 305 306 $response = $this->request('POST', '/api/sites', $data); 297 307 298 308 if (is_wp_error($response)) { … … 301 311 302 312 $site = $response['site'] ?? $response; 313 314 // Check if this was a reconnection (existing account without email) 315 $reconnected = !empty($response['reconnected']); 316 if ($reconnected) { 317 $site['_reconnected'] = true; 318 } 319 303 320 $this->cache_site($site); 304 321 -
bandwidth-saver/trunk/readme.txt
r3411500 r3419619 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 0.2. 37 Stable tag: 0.2.4 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 19 19 Bandwidth Saver fixes this by serving your images from servers close to your visitors — automatically. A visitor in Tokyo loads images from Asia. A visitor in London loads from Europe. Everyone gets faster pages. 20 20 21 **The best part?** You don't need to understand how it works. Just activate the plugin , enter your email, and toggle it on. Your images start loading faster immediately.21 **The best part?** You don't need to understand how it works. Just activate the plugin and flip the switch. Your images start loading faster immediately. 22 22 23 23 = What You Get = … … 35 35 Behind the scenes, Bandwidth Saver uses a global CDN (Content Delivery Network) with 300+ edge locations. But you don't need to know what that means or how to set it up. 36 36 37 1. You activate the plugin and enter your email 38 2. The plugin automatically rewrites image URLs on your pages 39 3. Visitors load images from the nearest edge server 40 4. Your original images stay exactly where they are 41 42 That's it. No DNS changes. No external accounts to manage. No settings to configure. 37 1. Install the plugin from your WordPress dashboard 38 2. Flip the switch to activate 39 3. Images instantly load from 300+ global servers 40 41 That's it. No DNS changes. No external accounts. No settings to configure. Your original images stay exactly where they are. 43 42 44 43 = Why People Choose This Over Other Speed Plugins = … … 83 82 1. Install and activate the plugin 84 83 2. Go to **Settings → Bandwidth Saver** 85 3. Enter your email 86 4. Toggle the CDN on 87 88 Done. Your images are now loading faster. 84 3. Toggle the CDN on 85 86 Done. Your images are now loading faster. No email required for the free tier. 89 87 90 88 == Frequently Asked Questions == … … 96 94 = I'm not technical. Can I still use this? = 97 95 98 Yes. That's exactly who this is for. You don't need to understand CDNs, DNS, or servers. Just activate , enter your email,and toggle it on.96 Yes. That's exactly who this is for. You don't need to understand CDNs, DNS, or servers. Just activate and toggle it on. 99 97 100 98 = How do I know it's working? = … … 104 102 = Is there really a free plan? = 105 103 106 Yes. 100 GB of bandwidth per month, free forever. No credit card required. No trial period. Most s mall to medium sites never need to upgrade.104 Yes. 100 GB of bandwidth per month, free forever. No credit card required. No trial period. Most sites never need to upgrade. 107 105 108 106 = What if I go over my bandwidth limit? = … … 151 149 152 150 * Your site URL is used to configure CDN routing 153 * Your email address is used for account creation151 * Email is optional — only collected if you upgrade or request account recovery 154 152 * Custom domain settings are sent if configured 155 153 … … 173 171 174 172 * Purpose: Account management, usage tracking 175 * Data sent: Site URL, email , custom domain (if configured)173 * Data sent: Site URL, email (if provided), custom domain (if configured) 176 174 177 175 Self-hosted users connect only to their own Cloudflare account. 178 176 179 177 == Changelog == 178 179 = 0.2.4 = 180 * New: Frictionless activation — no email required for free tier 181 * Improved: Toggle on directly from dashboard, account created automatically 182 * Improved: Cleaner first-run experience with fewer steps 183 * Fixed: Account card displays correctly when email is not set 180 184 181 185 = 0.2.3 = … … 237 241 == Upgrade Notice == 238 242 243 = 0.2.4 = 244 Frictionless activation: Just flip the switch, no email required. Simpler than ever. 245 239 246 = 0.2.3 = 240 247 Clearer messaging and improved onboarding experience. Recommended for all users.
Note: See TracChangeset
for help on using the changeset viewer.