Development issueshttps://lab.civicrm.org/groups/dev/-/issues2020-11-09T13:37:51Zhttps://lab.civicrm.org/dev/financial/-/issues/155Incorrect deductible shown in contribution summary report2020-11-09T13:37:51ZMonish DebIncorrect deductible shown in contribution summary reportSteps to replicate:
1. Ensure that there are multiple contributions with non-zero non-deductible amount.
2. Go to Contribution Summary Report
3. Select Non-Deductible amount column + Grouping on Receive Date - Month
Result: Total non-d...Steps to replicate:
1. Ensure that there are multiple contributions with non-zero non-deductible amount.
2. Go to Contribution Summary Report
3. Select Non-Deductible amount column + Grouping on Receive Date - Month
Result: Total non-deductible amount is incorrect against each month
On closer look, group function (- SUM) is not applied on non-deductible amount, thus the report column show random amount.
Here's a screencast that explains the issue, where I added two contributions this month w/o non-deductible amount respectively, but the Contribution summary report shows incorrect value:
![yhv](/uploads/e851d5c3b56e46c1de049d12d1f977ff/yhv.gif)
ping @JoeMurray @eileen @mattwire @EdselopezMonish DebMonish Debhttps://lab.civicrm.org/dev/core/-/issues/2157Array to string conversion in DB_DataObject when doing on behalf of and no st...2023-05-26T16:13:04ZDaveDArray to string conversion in DB_DataObject when doing on behalf of and no state/provinceIf you submit a contribution on behalf of an org and leave the state/province blank, you get `Notice: Array to string conversion in DB_DataObject->_build_condition() (line 2903 of .../web/sites/all/modules/civicrm/packages/DB/DataObject....If you submit a contribution on behalf of an org and leave the state/province blank, you get `Notice: Array to string conversion in DB_DataObject->_build_condition() (line 2903 of .../web/sites/all/modules/civicrm/packages/DB/DataObject.php)`
(At the moment to see this you need to make the field not required on the profile, but it happens either way it's just there's currently a separate issue when the field is required and the country has no state/provinces.)
What happens is that at that code line `$this->name` and `$this->abbreviation` contain a big long list of numbers and letters, including, oddly, the strings "_A", "_B", "_C", etc, but ONLY up to "_P".https://lab.civicrm.org/dev/translation/-/issues/57Mixed up translation for a few case role-related strings in nl_BE2020-10-23T15:08:34ZDaveDMixed up translation for a few case role-related strings in nl_BEThere are a couple lines in the nl_BE po file that are a bit mixed up. This came up before and it got fixed for nl_NL but didn't get updated for nl_BE. I think this needs to be updated in transifex.
https://lab.civicrm.org/dev/translati...There are a couple lines in the nl_BE po file that are a bit mixed up. This came up before and it got fixed for nl_NL but didn't get updated for nl_BE. I think this needs to be updated in transifex.
https://lab.civicrm.org/dev/translation/-/blob/41c36bc0532e3dd5e96e3481d6212f0c36e84686/po/nl_BE/case.po#L787-797
The nl_NL ones are correct so the corresponding lines above just need to match these:
https://lab.civicrm.org/dev/translation/-/blob/41c36bc0532e3dd5e96e3481d6212f0c36e84686/po/nl_NL/case.po#L771-781https://lab.civicrm.org/dev/user-interface/-/issues/33Theming meta issue2022-02-27T23:34:43ZeileenTheming meta issueI've created this issue so we can have somewhere to put the link to the theming presentation that took place this week (once it's available).
I would encourage people to link to other issues or repositories discussed as part of do-ocrac...I've created this issue so we can have somewhere to put the link to the theming presentation that took place this week (once it's available).
I would encourage people to link to other issues or repositories discussed as part of do-ocracy week from here too.https://lab.civicrm.org/dev/core/-/issues/2122Account for time zone on event registration pages2023-11-05T14:13:53ZwmortadaAccount for time zone on event registration pagesOverview
----------------------------------------
There doesn't appear to be a way to account for the time zone on an event registration page.
This is less of an issue for a local event, but is quite a problem for a global online event....Overview
----------------------------------------
There doesn't appear to be a way to account for the time zone on an event registration page.
This is less of an issue for a local event, but is quite a problem for a global online event.
At a minimum I would expect there to be an option to set the time zone for the event and for the time zone to display on the event registration page. (Ideally you'd want the page to show the time in the user's time zone.)
Current behaviour
----------------------------------------
There is no option to set the time zone for an event. (I presume that the system time zone is used but I'm not sure.)
![image](/uploads/6727ccb71e4b3129120a3275240c56cf/image.png)
The time zone isn't displayed on the event registration page.
![image](/uploads/a16d1c595ab9020e2d9e9c2d668e114c/image.png)
Proposed behaviour
----------------------------------------
There is an option to set the time zone when creating an event. This should default to the user's time zone.
The time zone is displayed on the event registration page.
Comments
----------------------------------------
I became aware of this when trying to register for this event: https://civicrm.org/civicrm/event/info?reset=1&id=1553
Probably relates to https://lab.civicrm.org/dev/core/-/issues/441
Agileware Ref: CIVICRM-404 (feature not found)https://lab.civicrm.org/dev/user-interface/-/issues/32Instructions for making a donation differ from button name2020-10-14T23:22:26ZsudomanInstructions for making a donation differ from button nameThis is a minor issue, but when checking out with a contribution form, the instructions say:
"Please verify the information below carefully. Click Go Back if you need to make changes. To complete your contribution, click the Continue bu...This is a minor issue, but when checking out with a contribution form, the instructions say:
"Please verify the information below carefully. Click Go Back if you need to make changes. To complete your contribution, click the Continue button below."
However there is no "Continue" button, it is called "Make Contribution".
Thanks! : )https://lab.civicrm.org/dev/drupal/-/issues/144D8 kcfinder needs to be in two locations, currently in one2021-07-15T05:43:44Zbails@circle-interactive.co.ukD8 kcfinder needs to be in two locations, currently in oneWe've had to
Symlink from vendor/civicrm/civicrm-packages/kcfinder web/libraries/civicrm/core/packages/
ln -s vendor/civicrm/civicrm-packages/kcfinder web/libraries/civicrm/core/packages/
Then ensure the sites civicrm.settings.php con...We've had to
Symlink from vendor/civicrm/civicrm-packages/kcfinder web/libraries/civicrm/core/packages/
ln -s vendor/civicrm/civicrm-packages/kcfinder web/libraries/civicrm/core/packages/
Then ensure the sites civicrm.settings.php contains the following lines:
$civicrm_paths['civicrm.bower']['path'] = '/home/user/public_html/web/libraries/civicrm/core/bower_components';
$civicrm_paths['civicrm.bower']['url'] = CIVICRM_UF_BASEURL . '/libraries/civicrm/core/bower_components/';
$civicrm_paths['civicrm.packages']['path'] = '/home/user/public_html/vendor/civicrm/civicrm-packages/';
$civicrm_paths['civicrm.packages']['url'] = CIVICRM_UF_BASEURL . '/libraries/civicrm/core/packages/';
And also:
Add settings_location.php inside web/libraries/civicrm/core/ and /libraries/civicrm/
<?php
define('CIVICRM_CONFDIR', dirname(dirname(dirname(__FILE__))) . '/../sites');
And finally:
# Allow access to CKEditor for CiviCRM.
RewriteCond %{REQUEST_URI} !/libraries/civicrm/core/packages/kcfinder/[a-z_/]+\.php$https://lab.civicrm.org/dev/core/-/issues/2114Trigger-based logging doesn't log if just changing a letter to upper/lower case2023-06-29T12:55:38ZDaveDTrigger-based logging doesn't log if just changing a letter to upper/lower case1. Turn on logging. (Admin - System Settings - Misc - Logging).
1. Change the first name of a contact just changing e.g. the first letter from upper to lower case.
1. Either look in the database in log_civicrm_contact or go to CiviReport...1. Turn on logging. (Admin - System Settings - Misc - Logging).
1. Change the first name of a contact just changing e.g. the first letter from upper to lower case.
1. Either look in the database in log_civicrm_contact or go to CiviReports - Contact Reports - Contact Logging.
1. Change has not been logged.
It's because the standard collation for civi is the case-insensitive xxx_unicode_ci or possibly xxx_general_ci. You might have also changed it manually to use the same as your CMS but is likely still case-insensitive. And in mysql 8 the default utf8mb4_0900_ai_ci is also accent-insensitive (i.e. `é` is treated the same as `e`), if you manually changed your civi tables to use that.
The logging triggers should probably use `xxx_bin`. Related but separate: https://github.com/civicrm/civicrm-core/pull/18721https://lab.civicrm.org/dev/financial/-/issues/153Orange Paypal Pro button not redirecting properly after reCaptcha on Paypal2020-12-09T00:33:53ZStoobOrange Paypal Pro button not redirecting properly after reCaptcha on Paypal#151 related issue @eileen @seamuslee
The javascript errors are fixed but we have been able to reproduce other errors related to the reCaptcha system at Paypal.com. I am not sure if these can be fixed on CiviCRM's side or not but we sh...#151 related issue @eileen @seamuslee
The javascript errors are fixed but we have been able to reproduce other errors related to the reCaptcha system at Paypal.com. I am not sure if these can be fixed on CiviCRM's side or not but we should be aware of the following experience from user testing.
My guess is the from the Civi side we should confirm we are sending Paypal the proper auto-return URL to ensure that Paypal can find its way back to us after hitting us with the reCaptcha on their end.
In *Chrome and Safari* the Javascript errors are fixed -- when you click the Paypal button, there's no validation error requiring the user to input CC fields.
**But** when I go to Paypal, I'm asked to complete a ReCaptcha at this URL: https://www.paypal.com//cgi-bin/webscr?cmd=_express-checkout&token=EC-2JE64037K02097038. Once I complete the challenge, the page does not reload to the log-in screen. Instead it just sits with the challenge results accepted. If I then reload the page, it redirects me to the Paypal log-in page as it should at this URL: https://www.paypal.com//cgi-bin/webscr?cmd=_express-checkout&token=EC-2JE64037K02097038
In *Firefox*, the Javascript errors are fixed -- when I click the Paypal button, there's no validation error requiring the user to input CC fields. When you go to Paypal, I'm asked to complete a ReCaptcha. Once I complete the challenge, the Paypal experience is different page loads the sad dinosaur error screen "hmm we're having trouble finding that site"https://lab.civicrm.org/dev/core/-/issues/2107scheduled reminders incorrectly exclude emails with on_hold = opt-out2023-05-20T05:50:59Zlcdwebscheduled reminders incorrectly exclude emails with on_hold = opt-outTo reproduce:
1. create a contact with an email and flag it on_hold = opt out
2. create a scheduled reminder that can be easily triggered. e.g. on creation of a scheduled activity
3. create the conditions for the scheduled reminder (e.g....To reproduce:
1. create a contact with an email and flag it on_hold = opt out
2. create a scheduled reminder that can be easily triggered. e.g. on creation of a scheduled activity
3. create the conditions for the scheduled reminder (e.g. create a scheduled activity of the selected type)
4. run the scheduled reminder job
Result: the contact will not receive the scheduled reminder because it skips email addresses with on_hold of either type (either bound or opt out).
Expected result: contact receives email.
This is worth some discussion as I know scheduled reminders sometimes fall into a grey area between bulk email and transactional email. Personally I believe they are more transactional than bulk, and believe we have historically viewed them that way.
The offending code is in: CRM_Contact_BAO_Contact::getPrimaryEmail(). That method has a parameter $polite = (bool) which is only used once in the codebase when called by CRM_Core_BAO_ActionSchedule::sendReminderEmail(). When that is true we condition on civicrm_email.on_hold = 0. I believe it should be civicrm_email.on_hold != 1 (doesn't equal bounce). As it's the only place that parameter/condition is used, we just need to decide if scheduled reminders are indeed transactional and should not exclude opt outs.
It's worth noting that the condition in that function also excludes civicrm_contact.do_not_email but does NOT exclude civicrm_contact.is_opt_out. We're not currently treating it like a bulk email at the contact level -- just at the email level.lcdweblcdwebhttps://lab.civicrm.org/dev/core/-/issues/2083If using the email processor to file inbound emails on cases via subject, it ...2022-09-27T16:29:36ZDaveDIf using the email processor to file inbound emails on cases via subject, it can file it on the wrong case on even moderately large sitesCame up as a side-thought while testing https://github.com/civicrm/civicrm-core/pull/18624.
On Manage Case, in the case roles section, you can send an outbound email to people by clicking the mail icon. In this context, civi will add a ...Came up as a side-thought while testing https://github.com/civicrm/civicrm-core/pull/18624.
On Manage Case, in the case roles section, you can send an outbound email to people by clicking the mail icon. In this context, civi will add a hash to the subject. If you've set up the inbound email processor, you can autofile responses onto cases since it will try to match the hash.
The problem is the algorithm used for the hash stops being unique at some point, and so matches a different case. It turns out you're almost guaranteed hash collisions on a site with 20000 cases. The exact first collision depends on CIVICRM_SITE_KEY which is different for every site. In fact for the site_key on a dev site where I was testing the PR you get the first collision around 11000 cases.
The easy solution is stop using substrings of hashes and just use case id as has been requested several times over the years and there's an extension that does this (self-promo): https://lab.civicrm.org/extensions/caseidinsubject
(Further promo: It also lets you remove the hash completely.)
Civi would still need to accept the 7-character version for inbound emails since there will be a (possibly lengthy) period of time where external recipients will still reply to older emails with the 7-character hash in the subject. But eventually that could be moved to an extension for anyone who wants to support it for longer.
For some background on why it's a hash, I've mentioned in several places that I vaguely recall this being a misunderstanding during initial development. Well-meant, as a privacy thought, but not necessary.
If there's desire to still have a hash, an obvious alternate solution is use a bigger substring or the whole string. In theory this could also be done by an extension.https://lab.civicrm.org/dev/core/-/issues/2081Proposal: Extension upgrades should reconcile managed entities2023-01-19T22:49:26ZJonGoldProposal: Extension upgrades should reconcile managed entitiesWhen you install a new extension, `CRM_Extension_Manager::install()` contains this line:
```php
CRM_Core_Invoke::rebuildMenuAndCaches(TRUE);
```
However, no equivalent code runs on extension upgrade.
I propose that on extension up...When you install a new extension, `CRM_Extension_Manager::install()` contains this line:
```php
CRM_Core_Invoke::rebuildMenuAndCaches(TRUE);
```
However, no equivalent code runs on extension upgrade.
I propose that on extension upgrade, we run this code.
Recently, I've had two different extensions fail to work on deployment because the upgrade process doesn't reconcile managed entities. I imagine I'm not alone.https://lab.civicrm.org/dev/user-interface/-/issues/31Clicking the browser's back button on Profile search results page removes sel...2020-10-01T13:24:02Zdarren.woodsClicking the browser's back button on Profile search results page removes selected Option from Select listCiviCRM 5.29.0 Wordpress 5.5.1
Steps to recreate:-
1) Open a Profile Page in "Search" mode (The Profile should contain a Select type field).
2) Select an Option from the list and click Search button.
3) Click browser's back button when ...CiviCRM 5.29.0 Wordpress 5.5.1
Steps to recreate:-
1) Open a Profile Page in "Search" mode (The Profile should contain a Select type field).
2) Select an Option from the list and click Search button.
3) Click browser's back button when results shown.
Expected result: All the Select list Options should be in the drop down list.
Actual result: The selected Option is not shown in the list.
Workaround: Rather than clicking the browsers' back button, users can click the "Edit search criteria" from the Profile search results page. This will show all the drop down list options as expected.
Appreciate this is a low priority bug, with a logical workaround, but would be nice to fix if it's not too much effort.https://lab.civicrm.org/dev/core/-/issues/2074Case activity assignees receive an email copy every time activity is edited2023-05-16T12:45:13ZDaveDCase activity assignees receive an email copy every time activity is editedNot sure yet when this changed. It used to only send newly added assignees an email. Investigating...Not sure yet when this changed. It used to only send newly added assignees an email. Investigating...https://lab.civicrm.org/dev/drupal/-/issues/142D8/D9 - Define composer upgrade test protocol2020-10-22T04:39:49ZtottenD8/D9 - Define composer upgrade test protocolWith composer-based distribution, there's an extra dimension/risk that you don't see in D7/WP/BD distribution -- Civi and Drupal build on some of the same packages (eg `symfony/*`), and they pull in various plugins, and the different tem...With composer-based distribution, there's an extra dimension/risk that you don't see in D7/WP/BD distribution -- Civi and Drupal build on some of the same packages (eg `symfony/*`), and they pull in various plugins, and the different templates have different conventions. It is entirely plausible for problems to sneak into the dependency-graph that are then awkward for system-implementers to resolve.
During the test/review/RC processes, we currently run [upgrade tests to check the DB-update procedure](https://github.com/civicrm/civicrm-upgrade-test/) against a range of older DB versions. This would be a sort of parallel for checking the composer-code-update procedure.
Ideally, as part of the release-cycle, one might run an upgrade-matrix. Example:
| Drupal Template | Drupal Version | CiviCRM Old Version | CiviCRM New Version |
| -- | -- | -- | -- |
| `drupal-composer/drupal-project` | `8.7.0` | `5.27.0` | `5.31.0` |
| `drupal/legacy-project` | `8.8.0` | `5.29.0` | `5.31.0` |
| `drupal/recommended-project` | `8.9.0` | `5.28.0` | `5.31.0` |
| `drupal/recommended-project` | `9.0.0` | `5.29.0` | `5.31.0` |
Of course, there are a huge number of permutations, and we're not gonna test all of them, but it would be appropriate to ensure that several distinct (in each column) do get tested.https://lab.civicrm.org/dev/core/-/issues/2072Why does composer.json contain `"include-path": ["vendor/tecnickcom"]`2023-05-10T12:51:31ZDaveDWhy does composer.json contain `"include-path": ["vendor/tecnickcom"]`As per https://lab.civicrm.org/extensions/cdntaxreceipts/-/issues/110#note_47514 it seems to cause issues with extensions that try to use TCPDF in drupal 8 since composer creates a vendor/composer/include_paths.php file that then makes t...As per https://lab.civicrm.org/extensions/cdntaxreceipts/-/issues/110#note_47514 it seems to cause issues with extensions that try to use TCPDF in drupal 8 since composer creates a vendor/composer/include_paths.php file that then makes the path relative to /vendor/civicrm/civicrm-core, instead of relative to just /vendor.
Maybe the line was from an early iteration of autoloading and using composer?https://lab.civicrm.org/dev/translation/-/issues/53Frequency units frequently fail to be translated properly2023-11-23T07:20:57ZStéphane Lussierstephane@symbiotic.coopFrequency units frequently fail to be translated properlyOn numerous occasions, the internal value of frequency units (eg: year, month) are sent for display to a template without being translated first.
One such issue may be found in [CRM/Contribute/Form/Contribution/Main.php](https://lab.ci...On numerous occasions, the internal value of frequency units (eg: year, month) are sent for display to a template without being translated first.
One such issue may be found in [CRM/Contribute/Form/Contribution/Main.php](https://lab.civicrm.org/dev/core/-/blob/master/CRM/Contribute/Form/Contribution/Main.php#L550). In this case, a simple fix would usually suffice:
```patch
--- a/civicrm/CRM/Contribute/Form/Contribution/Main.php
+++ b/civicrm/CRM/Contribute/Form/Contribution/Main.php
@@ -548,7 +548,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
if (!empty($form->_values['is_recur_interval']) || $className == 'CRM_Contribute_Form_Contribution') {
$unit .= "(s)";
}
- $form->assign('frequency_unit', $unit);
+ $form->assign('frequency_unit', ts($unit));
}
else {
$form->assign('one_frequency_unit', FALSE);
```
However, this patch in incomplete. There are multiple cases where a similar fix would need to be applied.
It's also not uncommon to find singular/plural tests in existing templates. The following example comes from [templates/CRM/Contribute/Form/Contribution/ThankYou.tpl](https://lab.civicrm.org/dev/core/-/blob/master/templates/CRM/Contribute/Form/Contribution/ThankYou.tpl#L123):
```smarty
{if $frequency_interval > 1}
<strong>{ts 1=$frequency_interval 2=$frequency_unit}This membership will be renewed automatically every %1 %2(s).{/ts}</strong>
{else}
<strong>{ts 1=$frequency_unit}This membership will be renewed automatically every %1.{/ts}</strong>
{/if}
```
This solution looks a bit strange to me... It assumes that adding an `(s)` to an internal keyword will make it plural. That may work in most situations, but it would prevent the already translated keyword to be altered upon the phrase translation.
Shouldn't the keyword be fully translated _and_ pluralized (if necessary) _before_ being sent to the translation string?
Could the `ts` function take care of translating and pluralizing substrings?
I don't mean to make a huge issue out of a small one, but I wonder: Is there a pattern that we can agree on for these sorts of situations?https://lab.civicrm.org/dev/financial/-/issues/150civicrm/payment/form url got empty currency argument in backoffice live CC form2021-07-07T08:47:08ZMonish Debcivicrm/payment/form url got empty currency argument in backoffice live CC formThis affects iATS Payments ACH/EFT payment processor which renders the payment block based on currency chosen. Here are the steps to replicate:
1. Install and enable [iATS paymentextension](https://github.com/iATSPayments/com.iatspayme...This affects iATS Payments ACH/EFT payment processor which renders the payment block based on currency chosen. Here are the steps to replicate:
1. Install and enable [iATS paymentextension](https://github.com/iATSPayments/com.iatspayments.civicrm)
2. Add and configure an iATS Payments ACH/EFT payment type payment processor.
3. Enable USD and CAD currencies
4. Go to 'Submit Credit Card Contribution' backoffice form
5. Choose payment processor created at step 2
Issue:
1. Payment block renders payment block with check template
2. Switching currency doesn't update the payment block.
For more detail discussion on MM - https://chat.civicrm.org/civicrm/pl/ixxrxhxs43r4mfyjpnf6tnwnnc
ping @KarinG @eileen @JoeMurray @seamuslee5.31.0Monish DebMonish Debhttps://lab.civicrm.org/dev/core/-/issues/2048Rename crmStripAlternatives function and its friend CRM_Utils_String::stripAl...2023-05-05T14:13:30ZDaveDRename crmStripAlternatives function and its friend CRM_Utils_String::stripAlternativesIt's not used much at least in core, and it's not clear from the name what it does, and there's potential for it to be mistaken as a security function.
I'd suggest something like getFirstEmailMultipart or stripAlternativeEmailMultiparts.It's not used much at least in core, and it's not clear from the name what it does, and there's potential for it to be mistaken as a security function.
I'd suggest something like getFirstEmailMultipart or stripAlternativeEmailMultiparts.https://lab.civicrm.org/dev/core/-/issues/2021Contribution receipt has donor's name printed twice, once with non-printable ...2023-11-23T07:22:03ZBobSContribution receipt has donor's name printed twice, once with non-printable charactersOverview
----------------------------------------
Contribution receipts, notably those created with the Stripe extension, display the donor's information as follows:
```
Jane�Mary�Smith <$first . \x01 . $middle . \x01 . $last>
...Overview
----------------------------------------
Contribution receipts, notably those created with the Stripe extension, display the donor's information as follows:
```
Jane�Mary�Smith <$first . \x01 . $middle . \x01 . $last>
Jane Mary Smith <$first . \x20 . $middle . \x20 . $last>
123 Main St
...
```
The two \x01 characters (ASCII SOH, CRM_Core_DAO::VALUE_SEPARATOR) are displayed as boxes in some email clients, although they aren't displayable in this bug report.
The message template "Contributions - Receipt (on-line)" includes:
```
{if $billingName}
<tr>
<th {$headerStyle}>
{ts}Billing Name and Address{/ts}
</th>
</tr>
<tr>
<td colspan="2" {$valueStyle}>
{$billingName}<br />
{$address|nl2br}<br />
{$email}
</td>
</tr>
{elseif $email}
```
For Stripe contributions, $billingName contains the first/middle/last names separated by SOH characters, as found in civicrm_address.name. The {if $billingName} block therefore gets printed, including both $billingName and the $address variable which contains the second instance of the donor's name, followed by their address.
The SOH characters in the first line of $address (the donor's name) are replaced with spaces in CRM_Core_BAO_Address::addDisplay().
Contributions via Paypal standard, in contrast, do not display the $billingName block as addresses created that way store NULL in civicrm_address.name.
Reproduction steps
----------------------------------------
1. Create a contribution with CiviCRM Stripe extension v. 6.4.2.
1. Observe the Billing Name and Address section of the emailed receipt.
Current behaviour
----------------------------------------
The donor's name is printed twice. Once with SOH separators, and again with spaces. If the middle name is blank, the second instance contains two spaces between first and last name.
Expected behaviour
----------------------------------------
The name should be printed once, with a single space between non-blank name components.
Additional comments
----------------------------------------
1. Perhaps the fix is to simply remove "$billingName\<br \/\>" from the template(s). Ideally, the double spaces in the case of a null middle name should be corrected also.
2. Event and Membership templates seem to have the same structure as the template shown above.
3. The Thank You page displays the donor's name as expected -- only once, with a single \x20 character between first and last name.
Environment information
----------------------------------------
<!-- Some of the items below may not be relevant for every bug - if in doubt please include more information than you think is neccessary. -->
* __CiviCRM:__ 5.28.2
* __CiviCRM Stripe extension__ v. 6.4.2
* __mjwshared extension__ v. 0.8.1
* __PHP:__ 7.3
* __CMS:__ Drupal 7.72