Skip to content

Replacing 0.00 with Free for free levels when set in advanced settings#45

Draft
dwanjuki wants to merge 1 commit into
strangerstudios:devfrom
dwanjuki:replacing-zero-with-free
Draft

Replacing 0.00 with Free for free levels when set in advanced settings#45
dwanjuki wants to merge 1 commit into
strangerstudios:devfrom
dwanjuki:replacing-zero-with-free

Conversation

@dwanjuki

@dwanjuki dwanjuki commented Mar 27, 2025

Copy link
Copy Markdown

Using preg_replace to replace "0.00" with free when not preceded by a currency symbol and not part of cost eg. 50.00

All Submissions:

Changes proposed in this Pull Request:

Resolves: #41

How to test the changes in this Pull Request:

  1. Create a free level.
  2. Set the custom cost text to "The price is !!initial_payment!!" and save the level.
  3. Under PMPro's Advanced Settings set the option "Replace 0.00 with 'free'" to Yes, save your settings.
  4. Navigate to pages with level cost, observe that 0.00 is replaced with 'free'

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you successfully run tests with your changes locally?

Changelog entry

Fixes an issue where replacing 0.00 with "Free" wasn't working in some cases.

@andrewlimaza andrewlimaza self-requested a review April 2, 2025 09:25
@dparker1005

Copy link
Copy Markdown
Member

Thanks for taking this on, @dwanjuki. While reviewing this for merge we surfaced a couple of issues that I think mean we need to step back and rethink the approach. I'm moving this to draft while we figure out the right path.

What this PR currently does: swaps two of the four str_replace lines in pclct_format_cost() for preg_replace('/^0.00/', …) and preg_replace('/^0,00/', …).

The concerns:

  1. Regression for right-symbol currencies. The original 0.00+symbol and 0,00+symbol lines handled the mid-string suffix-symbol case (e.g. SEK, DKK, where pmpro_formatPrice() outputs 0,00 kr with the symbol on the right). Replacing them with a ^-anchored regex means the default cost text on right-symbol-currency sites stops getting 0,00 kr → "Free" replacement.

  2. The ^ anchor only matches at the very start of the string. That works for the recursive pclct_apply_variables call where the input is exactly "0.00", but it doesn't help any other context.

  3. Unescaped dot in the regex. /^0.00/ matches 0X00, 0a00, etc., not just literal 0.00. Should be /^0\.00/.

  4. Decimals are hardcoded. Both the original code and this PR assume two-decimal currencies. JPY and other zero-decimal currencies format zero as "0" (no decimals), and BHD/KWD format it as "0.000". None of those are matched today; this PR doesn't fix that either.

The deeper issue we ran into:

While reviewing, we realized pclct_format_cost() is doing double duty — it's used both for full cost-text strings (where settings like "remove 'now'" and "use slashes" make sense) and for individual variable values inside pclct_apply_variables() (where those settings are no-ops, and use_free silently fails because the bare value has no currency symbol attached). #41 is really a symptom of that dual-use: when !!initial_payment!! is substituted, pclct_format_cost() is called on a bare 0 with no symbol, so the $0.00 → "Free" str_replace can't match. Patching the use_free regex to handle bare zeros would technically fix the reported case but at the cost of false positives on any non-money zero in cost text (cycle counts, trial limits, "0% APR", etc.).

Suggested path forward:

I think the right fix happens at a different layer — either:

  • Wrap money-valued tokens (!!initial_payment!!, !!billing_amount!!, !!trial_amount!!) in pmpro_formatPrice() inside pclct_apply_variables() so they substitute as already-symbolized strings ("$0.00", "0,00€", "¥0"), which then flows through the existing symbol-attached use_free matching. This does change !!initial_payment!!'s rendered output to include the currency symbol — that's a backwards-compat consideration we'd want to call out in the changelog.
  • Or split pclct_format_cost() into a full-cost-text formatter and a money-value formatter so each operates on inputs it was designed for.

Either way, while we're in there, we should also make the use_free matching locale-correct (compute the zero string from pmpro_get_currency() so JPY/BHD/etc. work) and broaden the lookbehind so wrapped contexts like <strong>0,00€</strong> are caught.

Happy to chat through the approach before you spend more time on this — let me know what you think.

@dparker1005 dparker1005 marked this pull request as draft May 1, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Replacing 0.00 with "Free" doesn't work in some cases.

3 participants