| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | |
| 3 | 3 | Plugin Name: s2Member Framework |
| 4 | 4 | Plugin URI: https://s2member.com/ |
| 5 | 5 | Tags: membership, content restriction, paid subscriptions, members only, paid access |
| 6 | -Version: 260829 | |
| 7 | -Stable tag: 260829 | |
| 8 | -Tested up to: 7.2-alpha-63379 | |
| 6 | +Version: 260927 | |
| 7 | +Stable tag: 260927 | |
| 8 | +Tested up to: 7.2-alpha-63947 | |
| 9 | 9 | Requires at least: 4.2 |
| 10 | 10 | Requires PHP: 5.6.2 |
| 11 | 11 | Tested up to PHP: 8.5.9 |
| 12 | 12 | License: GNU General Public License v2 or later. |
| @@ -175,14 +175,188 @@ | ||
| 175 | 175 | Please see: <http://s2member.com/r/translations/> |
| 176 | 176 | |
| 177 | 177 | == Upgrade Notice == |
| 178 | 178 | |
| 179 | -= v260829 = | |
| 179 | += v260927 = | |
| 180 | 180 | |
| 181 | 181 | (SECURITY RELEASE) UPGRADE IMMEDIATELY. v260215 included a CRITICAL VULNERABILITY fix, and you shouldn't wait any longer to update if you're behind. |
| 182 | 182 | |
| 183 | 183 | == Changelog == |
| 184 | 184 | |
| 185 | += v260927 = | |
| 186 | + | |
| 187 | +- (Pro) **Fix:** Improved Stripe 3D Secure recovery when browser and webhook processing overlap, or when the browser loses the final checkout response after successful authentication. s2Member now reconciles those recovery paths using the saved checkout state so successful signups can finish correctly without repeating fulfillment. Thanks to Felix for reporting it. See [thread #13627](https://f.wpsharks.com/t/13627). | |
| 188 | + | |
| 189 | +- (Framework) **Fix:** Improved Gateway Checkout state handling so concurrent recovery paths can safely patch independent checkout data and explicitly reload newly committed state without stale request-local cache values. | |
| 190 | + | |
| 191 | +- (Pro) **Fix:** Improved Stripe subscription recovery for new customers when payment authentication continues after the initial Pro-Form request. s2Member now keeps the pending WordPress account linked to the checkout, allowing browser or webhook recovery to complete the correct signup without losing its account association. | |
| 192 | + | |
| 193 | +- (Pro) **Fix:** In a rare Stripe pending-payment recovery case, membership processing could already be complete while the original checkout request still saw an older cached copy of the member's data and continued showing a processing state. s2Member now refreshes that data before deciding whether fulfillment has completed. | |
| 194 | + | |
| 195 | +- (Pro) **Fix:** Stripe one-time (Buy Now) Pro-Form purchases requiring 3D Secure could lose the password entered during the initial checkout when the form resumed after authentication. s2Member now keeps the same pending WordPress account through authentication and completes it with the password the customer originally chose. | |
| 196 | + | |
| 197 | +- (Pro) **Fix:** Closed a remaining failed-3D-Secure cleanup case where Stripe.js could return an authentication error without the PaymentIntent details used by s2Member's cleanup flow. s2Member now recovers the PaymentIntent ID from the existing Stripe client secret when needed so the incomplete subscription can still be cleaned up correctly. | |
| 198 | + | |
| 199 | +- (Pro) **Fix:** Failed card authentication during Stripe free-trial subscription checkout could leave the pending subscription active in a trialing state at Stripe. s2Member now cancels the incomplete subscription generation so unsuccessful authentication attempts do not leave orphaned trial subscriptions behind. | |
| 200 | + | |
| 201 | +- (Pro) **Fix:** Immediately retrying a Stripe free-trial subscription with another card after failed authentication could overlap with cleanup of the previous attempt or fail to continue correctly. s2Member now safely finishes that cleanup, confirms the retried authentication when needed, and starts a fresh subscription attempt without browser and webhook recovery interfering with each other. | |
| 202 | + | |
| 203 | +- (Pro) **Compatibility:** Improved Stripe SDK loading so s2Member does not accidentally trigger another plugin's dormant Stripe autoloader. This prevents an older Stripe library registered by another plugin from loading before s2Member Pro's bundled Stripe SDK. | |
| 204 | + | |
| 205 | +- (Pro) **Fix:** Prevented a PHP warning during Stripe Buy Now checkouts for existing members when determining whether a previous recurring subscription should be cancelled. | |
| 206 | + | |
| 207 | +- (Framework) **Compatibility:** Expanded no-cache support for caching solutions that use their own page-exclusion APIs or signals in addition to the commonly supported WordPress no-cache conventions. Added explicit compatibility for LiteSpeed Cache, FlyingPress, Super Page Cache for Cloudflare, WP Fastest Cache, and Cloudflare APO, helping prevent dynamic/private s2Member pages from being cached. | |
| 208 | + | |
| 209 | +- (Pro) **Fix:** When `[s2Member-List]` used `rlc_satisfy="ANY"` with multiple Levels, Roles, or Custom Capabilities, additional filtering on the member list could cause unrelated members to appear. Membership filters are now grouped correctly, so only members matching the requested criteria are returned. Thanks to Philip for reporting this. | |
| 210 | + | |
| 211 | +- (Framework) **Fix:** PayPal IPN domain checks could fail on some server setups when the incoming request did not provide a usable domain, for example with some reverse-proxy setups where something like Nginx, Cloudflare, a load balancer, etc. sits in front of WordPress and affects the request host. s2Member now falls back to the site's configured domain when needed. | |
| 212 | + | |
| 213 | +- (Framework) **Fix:** Some unexpected PayPal proxy values could cause notifications to fail and be ignored. These values are now normalized before the notification is processed. | |
| 214 | + | |
| 215 | +- (Framework) **Fix:** PayPal proxy notifications could fail on sites where their domain differs from the site's configured domain. s2Member now uses the appropriate site domain more consistently in these cases. | |
| 216 | + | |
| 217 | +- (Framework) **Fix:** Corrected the timeout value passed to the Mailchimp API client, preventing an invalid HTTP stream configuration that could interfere with list subscription requests. | |
| 218 | + | |
| 219 | +- (Framework) **Fix:** Avoided calling WordPress's deprecated `force_ssl_login()` helper on current WordPress versions when determining login and RPC URL schemes, preventing deprecation notices while preserving the same SSL behavior and compatibility with older WordPress versions. | |
| 220 | + | |
| 221 | +- (Framework) **Fix:** Prevented PHP notices from the `[s2Member-Security-Badge /]` shortcode when the optional `v` attribute is omitted. The shortcode now applies its default badge version before validating the value. | |
| 222 | + | |
| 223 | +- (Framework) **Fix:** Prevented PHP notices from the `[s2Stream /]` shortcode when the optional `player` attribute is omitted. Existing player defaults and behavior are unchanged. | |
| 224 | + | |
| 225 | +- (Framework & Pro) **UI:** Shortcode whitelist security notices are now more compact and easier to review, grouping detected user fields and template paths instead of repeating each shortcode occurrence, and listing the affected pages once with direct links. Thanks to Sherry for her feedback on these. _WP Admin > s2Member > General Options > Shortcode User Fields Whitelist_ and _Pro Shortcode Templates Whitelist_ | |
| 226 | + | |
| 227 | +- (Framework) **UI:** Corrected several PayPal Button Generator shortcode attribute descriptions to match current PayPal Checkout behavior, particularly the `output` and `image` attributes. | |
| 228 | + | |
| 229 | += v260917 = | |
| 230 | + | |
| 231 | +- (Framework) **Performance:** Further improved searching on the _WP Admin > Users_ screen, building on the performance improvements introduced in v260909. Searches across user profiles and s2Member membership data now require substantially less database work, with the biggest benefit on sites with large member databases. This can make member administration noticeably faster while preserving the same searchable fields, sorting, and pagination. | |
| 232 | + | |
| 233 | +- (Pro) **Performance:** Significantly improved `[s2Member-List]` and `[s2Member-List-Search]` performance for member directories and searches, especially on sites with larger user databases. Member searches now require substantially less database work, with much more efficient profile-field searching, filtering, sorting, and pagination. This can make large member directories noticeably faster and more responsive while preserving the shortcodes' existing Custom Field, wildcard, filtering, pagination, and sorting features. See: [s2Member-List Shortcode Documentation](https://s2member.com/kb-article/s2member-list-shortcode-documentation/). | |
| 234 | + | |
| 235 | +- (Framework) **Performance:** Improved Alternative View Protection performance on sites with larger amounts of protected content. Searches, archives, menus, widgets, and other areas where restricted content needs to be filtered now do less repeated work during each page request, helping busy pages load more efficiently while preserving the same access-control behavior. _WP Admin > s2Member > Alternative View Protection_ | |
| 236 | + | |
| 237 | +- (Pro) **Performance:** Reduced overhead when End-of-Term reminder emails are disabled. The heavier reminder processing, health, and email code is now loaded only when it is actually needed. | |
| 238 | + | |
| 239 | +- (Framework & Pro) **Security & UI:** Added a prominent admin warning for outdated s2Member Pro installations that predate the current Pro updater. The Framework now warns administrators when an old Pro version may be missing recent security fixes, shows how old the installed release is, and provides a prominent link to download the latest Pro version. The warning does not disable the installed Pro add-on or its features. | |
| 240 | + | |
| 241 | +- (Pro) **Security:** Enforced the _Shortcode User Fields Whitelist_ for `[s2Member-List]`'s `show_fields` attribute. Fields not on the whitelist are now omitted from Member Lists, with an administrator notice identifying blocked fields that may need to be allowed. _WP Admin > s2Member > General Options > Shortcode User Fields Whitelist_ | |
| 242 | + | |
| 243 | +- (Pro) **Security:** Enforced the _Pro Shortcode Templates Whitelist_. Custom templates specified with the `template` attribute are now blocked unless specifically allowed. The shortcode uses its standard template instead, and an administrator notice identifies blocked template files that may need to be allowed. _WP Admin > s2Member > General Options > Pro Shortcode Templates Whitelist_ | |
| 244 | + | |
| 245 | +- (Pro) **Improvement:** Hardened validation of PayPal Pro-Form `success` URLs used after subscription cancellation. Redirects are now limited to normal HTTP(S) destinations after replacement codes are processed, preventing executable or other non-web URL schemes from being used. Also hardened malformed programmatic `success` values to avoid PHP warnings. | |
| 246 | + | |
| 247 | +- (Framework) **Fix & UI:** Corrected Asset Health reporting when static CSS or JavaScript cannot be used because the site's current hooks or configuration require dynamic delivery. This intentional compatibility behavior is now treated as healthy instead of being reported as an unexpected fallback, and it no longer creates misleading "Latest Issues" entries. Asset Health now identifies why dynamic delivery is required, explains when the Full WordPress Dynamic Loader is necessary, and points to the "JavaScript Text Delivery" setting when it can help more pages continue using static JavaScript. | |
| 248 | + | |
| 249 | +- (Framework) **Improvement:** EOT demotion traditionally replaced all of a member's WordPress roles, but some sites need to preserve unrelated roles. The new _Demote From_ setting can now remove only the member's s2Member Level role instead. New installations use this level-only behavior by default; existing installations keep the legacy replace-all behavior unless changed. Thanks to Craig for suggesting this. See: [thread #13494](https://f.wpsharks.com/t/13494). | |
| 250 | + | |
| 251 | +- (Framework) **Improvement:** EOT demotion normally sends members to _Subscriber / s2Member Level 0_, and using another role previously required custom code. The new _Demote To Role_ setting lets site owners choose another s2Member Level or an available custom role directly from the EOT settings. Existing customizations using the `ws_plugin__s2member_force_demotion_role` filter continue to work. | |
| 252 | + | |
| 253 | +- (Pro) **Improvement:** PayPal Checkout cancellation buttons using `output="button"` can now also use a `success=""` attribute to redirect the member after a successful subscription cancellation. If no Success URL is provided, the existing cancellation confirmation remains unchanged. Thanks to Felix for suggesting this. See: [thread #13462](https://f.wpsharks.com/t/13462/7) | |
| 254 | + | |
| 255 | +- (Framework) **Improvement:** Added date formatting support to the `[s2Get /]` shortcode when retrieving the current user's registration timestamps. `S2MEMBER_CURRENT_USER_REGISTRATION_TIME` and `S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME` can now use the existing `date_format` attribute (e.g., `m/d/Y`, `default`, or `timestamp`), making these timestamps easier to display as readable dates without custom PHP. Also corrected the related scripting documentation to distinguish registration day counts from Unix timestamps. Thanks to Gerard for suggesting this. See [thread #13221](https://f.wpsharks.com/t/13221). | |
| 256 | + | |
| 257 | +- (Framework) **Improvement:** Expanded the AWS S3 region selector with several compatible regions that were missing: Canada Central (`ca-central-1`), Ohio (`us-east-2`), Mumbai (`ap-south-1`), Paris (`eu-west-3`), and Stockholm (`eu-north-1`). Sites using buckets in those regions can now select them directly. Thanks to David for the reminder. See: [thread #4706](https://f.wpsharks.com/t/4706). | |
| 258 | + | |
| 259 | +- (Framework & Pro) **Improvement:** Added some needed filters that were missing, giving developers more ways to customize s2Member emails and Tracking Codes. | |
| 260 | + | |
| 261 | +- (Pro) **Fix:** Resolved PHP 8.x warnings in `[s2Member-List]` caused by optional member-query arguments, including `meta_query`, not always being present. | |
| 262 | + | |
| 263 | +- (Framework) **Fix:** Prevented a fatal error in the s2Member-Only dynamic CSS/JS loader when BuddyPress is detected but its `bp_is_create_blog()` helper is unavailable. This also prevents affected sites from unnecessarily falling back to the Full WordPress Dynamic asset loader. | |
| 264 | + | |
| 265 | += v260913 = | |
| 266 | + | |
| 267 | +- (Framework) **Fix:** Made frontend CSS/JavaScript monitoring less impatient on sites where expected assets take a little longer to become active. Although the monitor already waited until the page had fully loaded before checking, some setups make their CSS/JavaScript become active a little later, which could cause a false alarm. This has now been fixed. Thanks to Gerard for reporting this. See: [thread #13609](https://f.wpsharks.com/t/13609) | |
| 268 | + | |
| 269 | +- (Framework) **Enhancement:** Expanded the frontend CSS/JavaScript monitoring introduced in the previous release into a new "CSS/JS Asset Health" system. The earlier monitoring layer is now smarter, more patient, more informative, more self-healing, quieter when the administrator does not need to intervene, and still designed to stay lightweight during normal frontend traffic. | |
| 270 | + - **New overall health status:** "CSS/JS Asset Health" monitors frontend assets, including the Pro add-on's assets when installed, keeps track of recent delivery results, and summarizes the current situation as "Healthy", "Recent issue", "Working, review suggested", or "Needs attention" instead of reacting to every individual hiccup in isolation. | |
| 271 | + - **More patient, configurable checks:** The original monitor checked whether expected assets had become active 1 second after the page finished loading. The default wait is now 3 seconds, and the new "Wait Before Checking Frontend Assets" setting lets site owners adjust that delay for setups where optimization, caching, networking, or other conditions make assets become active a little later. | |
| 272 | + - **Smarter issue handling:** A single delayed or uncertain result no longer needs to become an immediate administrator problem. Asset Health considers both how recent and how persistent problems are, and can return to "Healthy" as normal loads continue. | |
| 273 | + - **More resilient automatic recovery:** If an enabled static asset file unexpectedly disappears, s2Member will try to rebuild it automatically the moment the problem is encountered instead of waiting for the administrator to refresh it manually. Assets that need rebuilding can also be recovered during normal admin activity, avoiding an extra rebuild during a frontend page-load when possible, and relevant settings changes can trigger affected assets to be rebuilt immediately, too. | |
| 274 | + - **Clearer diagnostics:** The new Asset Health panel shows each CSS/JavaScript asset and its current delivery state, including "Healthy", "Late", "Fallback", "Failed", "Not generated yet", and "Pending rebuild", with plain-language details when more information is useful. A persistent "Last issue" reminder and compact "Latest Issues" log preserve useful troubleshooting details, including affected frontend URLs, occurrence times, and repeated occurrences, with controls to clear them when they are no longer useful. | |
| 275 | + - **Fallback visibility:** Asset Health understands s2Member's existing automatic fallback behavior, distinguishes successful delivery from successful fallback, and shows when the preferred delivery method could not be used but a compatible fallback kept the asset working. It can also show when the fallback itself is unavailable, even while the preferred delivery method is still working, so the administrator knows that the safety net needs attention before it's needed. | |
| 276 | + - **More useful administrator notices:** Short-lived issues are given time to recover without unnecessary warnings. When a problem persists long enough to deserve attention, or is serious enough to require attention sooner, s2Member can show a compact administrator notice explaining the affected asset and link directly to the "CSS/JS Asset Health" section for review. | |
| 277 | + - **Manual recovery and rechecking:** The "Refresh Static Assets" button rebuilds the enabled static files, while the "Recheck Asset Health" button performs a fresh check of the current delivery setup. Refreshing static assets also rechecks their health automatically afterward. | |
| 278 | + - **Performance-conscious health tracking:** Frontend page-loads save small, independent Asset Health records without waiting for the shared health history to be updated. Those events are merged into the rolling history separately and in chronological order, preserving delayed reports and recent-issue details without making normal frontend page-loads wait on Asset Health bookkeeping. | |
| 279 | + | |
| 280 | +- (Framework) **UI:** Refined the CSS/JavaScript delivery controls and status presentation. Renamed the beta section to "CSS/JS Delivery & Optimization (Beta)", improved the shared health-status colors used across s2Member status sections, clarified help text and status explanations, and corrected the disabled "Refresh Static Assets" button so it remains visibly disabled when unavailable because static assets are not enabled or a configuration change needs to be saved first. | |
| 281 | + | |
| 282 | +- (Framework) **Fix:** Corrected a compatibility issue that could cause a PHP fatal error when another plugin printed WordPress scripts unusually early, before s2Member had finished initializing. s2Member now handles that early script output safely. Thanks to Sim Architect for reporting it. | |
| 283 | + | |
| 284 | +- (Pro) **Improvement:** EOT Reminder failure notices are now more actionable. Reminder Status can identify the oldest failing recipient and, when available, the related WordPress user. Persistent admin warnings can now be dismissed for the current incident, while retry and failure details remain available in the _EOT Reminder Status_ section. A materially new or escalated critical reminder problem will alert administrators again. Thanks to Matt for reporting this. | |
| 285 | + | |
| 286 | +- (Framework & Pro) **Fix:** Restored compatibility with WordPress 4.2–4.3 by replacing uses of `wp_parse_url()`, which wasn't introduced until WordPress 4.4. | |
| 287 | + | |
| 288 | += v260909 = | |
| 289 | + | |
| 290 | +- (Framework & Pro) **Major Improvement:** Until now, s2Member normally generated CSS/JS assets dynamically because some of their contents can change depending on the visitor or other conditions. Dynamic generation requires PHP and WordPress to load before each file can be built. s2Member can now build in advance the parts that don't change and whose contents are shared across all visitors, and save them as static files, allowing the web server to return them directly without loading WordPress for each request. In our tests, static requests were consistently more than 100× faster than dynamic delivery, helping pages load faster while reducing server work. See _WP Admin > s2Member > General Options > Performance & Caching > Static CSS/JS Optimization (beta)_. | |
| 291 | + - **Flexible opt-in controls:** Enable static CSS, static JavaScript, or both. The existing _CSS/JS Lazy Loading_ option still controls which pages load s2Member's files. | |
| 292 | + - **Better caching for logged-in users:** Most of s2Member's JavaScript is the same for everyone, so it can now be shared and cached instead of being rebuilt separately for each visitor. Personal/member-specific values stay with the WordPress page and are never stored in reusable static files. This lets logged-in and logged-out visitors reuse the same shared JavaScript more effectively across page views. | |
| 293 | + - **Pro and gateway support:** Pro core and enabled-gateway CSS and JavaScript can use the same static delivery, combining, and minification options. | |
| 294 | + - **Flexible static asset delivery:** Static Framework and Pro assets can be kept separate for more granular caching, refreshing, and monitoring, or combined into one CSS file and one JavaScript file to minimize the number of requests. | |
| 295 | + - **Optional automatic minification:** Generated CSS and JavaScript can also be minified automatically. Smaller files take less time and bandwidth to download, helping pages load faster, especially on slower connections. | |
| 296 | + - **Multilingual-site optimization:** Sites that change language between pages or visitors can reuse the same static JavaScript file across languages. s2Member loads translated messages and other page-varying values with each WordPress page instead, while personal/member details always remain page-specific and are never stored in reusable static files. Single-language sites can keep more site-wide values in the static JavaScript file for maximum efficiency. | |
| 297 | + - **Reliable automatic fallback:** Static delivery is an optimization, not a requirement for the site to keep working. If a static file cannot be used, rebuilt, or delivered correctly, s2Member automatically falls back to a compatible dynamic delivery method instead of serving a stale or broken asset. | |
| 298 | + - **Targeted refreshes and recovery:** When relevant settings change, s2Member refreshes only the affected static files. During normal WordPress admin use, s2Member also checks that active generated files are still available and working. If a problem is confirmed, it can fall back safely, show an administrator warning, and provide a Refresh Static Assets control to recreate the files. | |
| 299 | + - **Troubleshooting and event logging:** When s2Member logging is enabled, a dedicated `css-js.log` records important CSS/JavaScript delivery events such as generation and refreshes, configuration changes, loader or delivery problems, automatic fallbacks and recoveries, browser-reported runtime issues, and stale-file cleanup, without logging routine page loads. | |
| 300 | + - **Safer plugin updates:** s2Member keeps its generated static JavaScript synchronized with the installed Framework and Pro versions. If an older generated file no longer matches the current plugin files, s2Member rebuilds it or falls back safely instead of risking broken JavaScript after an update. | |
| 301 | + - **Cache-safe cleanup:** Recently replaced static files are kept temporarily so visitors can still load pages cached with an older file URL. Older unused generations are cleaned up automatically, preventing the generated-assets directory from growing indefinitely. | |
| 302 | + | |
| 303 | +- (Framework & Pro) **Improvement:** Added a choice of loaders for dynamically generated CSS and JavaScript. The Lightweight s2Member Loader remains the default and avoids loading more of WordPress than necessary for better performance. A WordPress Loader option is also available, loading WordPress normally for these asset requests on sites where the server or security software blocks direct s2member-o.php requests. Configure it from _WP Admin > s2Member > General Options > Performance & Caching > Dynamic CSS/JS Loader_. See [Mod Security (Odd 403, 503, 500 Errors)](https://s2member.com/kb-article/mod-security-odd-403-503-500-errors/) | |
| 304 | + | |
| 305 | +- (Framework & Pro) **Fix:** Due to an earlier change in WordPress, s2Member's dynamic CSS and JavaScript loader could end up loading more of WordPress than necessary, making those files slower to load. Its original lightweight loading behavior has now been restored. See: [s2Member-Only Mode](https://s2member.com/kb-article/s2member-only-mode/) | |
| 306 | + | |
| 307 | +- (Framework) **Improvement:** Added a shared checkout recovery system that lets supported gateways preserve an in-progress checkout across requests, prevent overlapping processing, and recognize a checkout that already completed even if the browser lost the final response. Recovery information can be retained securely for up to 7 days by default, providing a common foundation for safer retry and recovery behavior across payment gateways. | |
| 308 | + | |
| 309 | +- (Pro) **Improvement:** PayPal Checkout Pro-Forms now keep a durable checkout identity across reloads, back/forward navigation, and interrupted browser requests. This gives s2Member a reliable way to reconnect the customer with the same PayPal checkout already in progress, while remaining compatible with older in-progress recovery state during the transition. | |
| 310 | + | |
| 311 | +- (Pro) **Security:** Hardened password handling across Pro-Forms as part of the new checkout recovery protections. Submitted passwords are not carried into reusable PayPal Checkout recovery state or repopulated if the form has to be shown again after submission. If an interrupted checkout is later recovered without the original browser session, WordPress's secure set-password flow is used instead. | |
| 312 | + | |
| 313 | +- (Pro) **Security:** Hardened Specific Post/Page checkout recovery by minimizing the form data saved for interrupted-checkout recovery. Sensitive payment fields are explicitly excluded from saved recovery state, adding an extra safeguard against unexpected checkout data being retained. | |
| 314 | + | |
| 315 | +- (Pro) **Fix:** Significantly extended Stripe Pro-Form duplicate-billing protection for interrupted or retried checkouts. If a reload, interrupted request, lost response, or 3D Secure retry leaves an existing Stripe payment or subscription in progress, s2Member now preserves enough checkout state to find and resume that same payment or subscription instead of accidentally starting another one. This extends the duplicate-charge protection added in v260829 to several additional failure and recovery paths. See [thread 13589](https://f.wpsharks.com/t/13589). | |
| 316 | + | |
| 317 | +- (Pro) **Fix:** Improved handling when a successful Stripe Pro-Form checkout completes on the server but the final confirmation never reaches the customer. Because the form can still appear unfinished, the customer may submit it again even though Stripe already completed the payment. Successful checkout results are now retained server-side so s2Member can recognize the completed checkout and resume from the saved result instead of treating the retry as a new payment attempt. | |
| 318 | + | |
| 319 | +- (Pro) **Fix:** Strengthened duplicate-subscription protection in PayPal Checkout Pro-Forms. Subscriptions are now created server-side and recorded before browser approval continues, so reloads, lost PayPal responses, interrupted callbacks, and retries can recover and reuse the subscription already created at PayPal instead of creating another one. | |
| 320 | + | |
| 321 | +- (Pro) **Fix:** Corrected PayPal Checkout subscription activation handling so membership access is not granted while PayPal still considers the subscription pending approval. s2Member now waits for PayPal to confirm activation, and can recover that confirmation through PayPal's webhook if the browser response is lost or delayed. | |
| 322 | + | |
| 323 | +- (Pro) **Fix:** Added comprehensive recovery for interrupted or delayed PayPal Checkout one-time payments. s2Member now keeps track of both the PayPal order and its payment capture, safely handles lost or ambiguous responses, keeps access pending until PayPal confirms the payment completed, and can later recover a completed payment through either the browser or PayPal's webhook without attempting a second capture. The recovery state is also kept deliberately minimal without retaining sensitive checkout data. | |
| 324 | + | |
| 325 | +- (Framework) **Performance:** Reduced overhead in high-frequency query and capability checks by bypassing hook and filter setup when nothing is registered and avoiding unnecessary construction of hook context variables, while preserving registered callbacks and WordPress `all` hook compatibility. Screens and operations that perform many capability checks, such as the WordPress Users list, can benefit especially from these savings. | |
| 326 | + | |
| 327 | +- (Framework) **Performance:** Reduced database overhead during page loads by eliminating repeated access-restriction database queries within the same request, reusing the initial lookup result. | |
| 328 | + | |
| 329 | +- (Pro) **Improvement:** The Pro updater now handles version mismatches more clearly when the latest Pro release is ahead of the installed Framework. It recommends updating the Framework first, or links to the [Release Archive](https://s2member.com/release-archive/) for a matching Pro version when staying on the current Framework. | |
| 330 | + | |
| 331 | +- (Pro) **Performance:** Moved checks for available Pro updates to a background task. The latest available Pro version is now saved locally and reused for up to a day when deciding whether to show the Pro Updater. This way, slow Pro availability checks or connection problems can't delay frontend or admin page loads. After Framework updates, a fresh background check keeps compatibility information current. | |
| 332 | + | |
| 333 | +- (Pro) **Performance:** Moved the Pro server environment details collection to a background task, so it can't delay normal admin page loads. | |
| 334 | + | |
| 335 | +- (Pro) **Performance:** Eliminated repeated cron and transient housekeeping during normal page loads when End-of-Term reminders are disabled, moving the necessary cleanup to settings changes and stale background callbacks. | |
| 336 | + | |
| 337 | +- (Framework) **Improvement:** End-of-Term Administrative Notes in the user's profile now use the level custom names when the "Force WordPress to use your Labels" setting is enabled. Also, if a user is already in the configured demotion role, the note now says so instead of recording a "role change" to the same role. | |
| 338 | + | |
| 339 | +- (Framework) **Fix:** Solved a remaining PayPal cancellation EOT issue when stored IPN Signup Vars are completely missing. An older subscription check could prevent the newer PayPal lookup from running, causing the EOT to fall back to an incorrect one-day period. s2Member now uses PayPal's next billing date when available. Thanks to Felix for reporting this. See [thread 13462](https://f.wpsharks.com/t/13462). | |
| 340 | + | |
| 341 | +- (Framework) **Fix:** Improved Automatic End-of-Term health warnings on low-traffic sites. A delayed WP-Cron event, which can happen when there have been few or no site visitors to trigger it, is now shown as an Attention item without triggering the admin warning by itself, while missing cron or an actual overdue EOT backlog still triggers the stronger warning. EOT warning links also now open the relevant settings panel and jump directly to the affected setting. | |
| 342 | + | |
| 343 | +- (Framework) **Fix:** Prevented PHP warnings during some Stripe cancellation/End-of-Term processing when currency information is missing. s2Member now recovers the stored payment currency when possible, and continues processing cleanly without PHP warnings. | |
| 344 | + | |
| 345 | +- (Framework) **Fix:** In some edge cases, legacy encryption/decryption could trigger a PHP 8.5 deprecation warning for certain byte values. The byte handling is now explicitly normalized while preserving compatibility with existing encrypted data. | |
| 346 | + | |
| 347 | +- (Framework) **Fix:** Redacting sensitive data in large multiline gateway/API logs could cause the regular-expression redaction step to fail and trigger PHP 8.1+ deprecation warnings. Redaction now handles large log entries more reliably. | |
| 348 | + | |
| 349 | +- (Framework) **Fix:** The bundled Mailchimp API client could trigger a PHP 8.1+ deprecation warning by passing a deprecated `null` value during query-string construction. It now uses the correct empty-string value instead, preserving the same API request behavior. | |
| 350 | + | |
| 351 | +- (Pro) **Fix:** ClickBank request processing could trigger PHP 8.1+ deprecation warnings by passing a deprecated `null` value during query-string construction. Those calls now use the correct empty-string value instead, preserving the same request behavior. | |
| 352 | + | |
| 353 | +- (Framework) **Fix:** PayPal notifications and returns could trigger PHP warnings when the optional `s2member_paypal_proxy` and `s2member_paypal_proxy_use` fields were absent. Those optional fields are now set to empty values when missing before processing, while preserving existing gateway integration behavior. | |
| 354 | + | |
| 355 | +- (Pro) **Fix:** Prevented a PHP warning when processing malformed Stripe webhook payloads by validating the decoded event before accessing its ID. | |
| 356 | + | |
| 357 | +- (Framework) **Fix:** Corrected an off-by-one issue in Brute Force Login Protection that allowed one additional login attempt after the configured failed-login limit had been reached. | |
| 358 | + | |
| 185 | 359 | = v260829 = |
| 186 | 360 | |
| 187 | 361 | - (Framework) **Major Improvement:** Rebuilt the Automatic End-of-Term processing engine so membership expirations are handled more reliably and promptly when due, even on busy sites or after delays, while making the system safer to administer and easier to review and troubleshoot. |
| 188 | 362 | - **Faster, adaptive processing:** Instead of stopping after 6 users, the new engine uses the safe processing time available in each run and adapts to current speed, allowing it to handle hundreds of users in one pass. |
| @@ -444,9 +618,9 @@ | ||
| 444 | 618 | - (Framework) **PayPal Enhancement**: Modernized s2Member’s PayPal integration by adding support for PayPal Checkout with their latest REST APIs, Smart Buttons, and webhook event handling. This release introduces PayPal’s current Checkout platform as an optional, reliable alternative to the legacy PayPal Standard buttons. Existing s2Member PayPal button shortcodes continue to work as-is (no edits required). See: _WP Admin > s2Member > PayPal Options > PayPal Checkout (Beta)_. Thanks to the beta testers, especially Sim Architect. |
| 445 | 619 | |
| 446 | 620 | = v260101 = |
| 447 | 621 | |
| 448 | -- (Framework) **Security**: Improved sanitization and normalization of attribute values for the s2Eot, s2Strem and s2Member-Security-Badge shortcodes. | |
| 622 | +- (Framework) **Security**: Improved sanitization and normalization of attribute values for the s2Eot, s2Stream and s2Member-Security-Badge shortcodes. | |
| 449 | 623 | |
| 450 | 624 | - (Framework) **Security**: Improved sanitization of replacement values for confirmation and notification emails. |
| 451 | 625 | |
| 452 | 626 | = v251005 = |
| @@ -542,9 +716,9 @@ | ||
| 542 | 716 | - (Framework) **Enhancement**: s2Get shortcode can now be used to show s2's current user constants. E.g. `[s2Get constant="S2MEMBER_CURRENT_USER_DISPLAY_NAME" /]` _WP Admin > s2Member > API / Scripting > s2Member PHP/API Constants_ |
| 543 | 717 | |
| 544 | 718 | = v240325 = |
| 545 | 719 | |
| 546 | -- (Framework) **Fix**: Some sites were getting a warning from v240315's restriction improvement when the WP REST request doesn't include a type or ID. Fixed in this release.See [thread 11347](https://f.wpsharks.com/t/11347) | |
| 720 | +- (Framework) **Fix**: Some sites were getting a warning from v240315's restriction improvement when the WP REST request doesn't include a type or ID. Fixed in this release. See [thread 11347](https://f.wpsharks.com/t/11347) | |
| 547 | 721 | |
| 548 | 722 | - (Pro) **Enhancement**: Checkout success redirection URLs are now validated as safe with WordPress' _wp_validate_redirect_. To use a domain different than the site's, it can be allowed with wp's filter [allowed_redirect_hosts](https://developer.wordpress.org/reference/hooks/allowed_redirect_hosts/). |
| 549 | 723 | |
| 550 | 724 | - (Framework) **Enhancement**: Additional validation to prevent an invalid s2Member Level role during registration. |