CiviCRM Core issueshttps://lab.civicrm.org/dev/core/-/issues2023-08-03T12:45:52Zhttps://lab.civicrm.org/dev/core/-/issues/4448SearchKit HAVING clause does not support relative dates.2023-08-03T12:45:52ZTony Maynard-SmithSearchKit HAVING clause does not support relative dates.## Overview
SearchKit WHERE clauses on a Date field provide a facility for comparing with a relative date, e.g. "\< Before Now 12 Months". The HAVING clause does not, but I am suggesting that it should.
## Example use-case
1. SearchK...## Overview
SearchKit WHERE clauses on a Date field provide a facility for comparing with a relative date, e.g. "\< Before Now 12 Months". The HAVING clause does not, but I am suggesting that it should.
## Example use-case
1. SearchKit search to select Contacts who have not participated in an Event for the last 12 months. Also applies to Activities, Memberships, etc.
## Current behaviour
Can construct a HAVING clause to compare e.g. a MAX Date field with a literal date, but not with a relative date as for a WHERE clause.
## Proposed behaviour
Relative dates should be provided for HAVING as well as WHERE clauses. This is much more user friendly for a packaged search than having to edit the search definition in SearchKit each time.
## Comments
_Anything else you would like the reviewer to note._https://lab.civicrm.org/dev/core/-/issues/4420crmDate support for Date Preferences2023-07-10T06:21:42ZlarsssandergreencrmDate support for Date Preferences[crmDate](https://github.com/civicrm/civicrm-core/blob/master/CRM/Core/Smarty/plugins/modifier.crmDate.php) only supports Date Formats, not the confusingly separate Date Preferences, which include creditCard format. It would be nice to b...[crmDate](https://github.com/civicrm/civicrm-core/blob/master/CRM/Core/Smarty/plugins/modifier.crmDate.php) only supports Date Formats, not the confusingly separate Date Preferences, which include creditCard format. It would be nice to be able to use `crmDate:'creditCard'` on Contribution Page Review and Thank You pages, etc.
Or maybe we should use tokens for credit_card_expiration_date instead, @DaveD thinks they support the Preferences.https://lab.civicrm.org/dev/core/-/issues/4412Add something like API 3 Attachments to API 42023-07-06T06:35:00ZlarsssandergreenAdd something like API 3 Attachments to API 4We can't get the full URL for a file from API 4 File and there is no API 4 Attachments, so API 3 must be used — which seems like a significant gap.
Thought this was worth noting as it has come up [twice](https://civicrm.stackexchange.co...We can't get the full URL for a file from API 4 File and there is no API 4 Attachments, so API 3 must be used — which seems like a significant gap.
Thought this was worth noting as it has come up [twice](https://civicrm.stackexchange.com/questions/45209/get-uploaded-file-full-url-via-api-v4/45210) on [SE](https://civicrm.stackexchange.com/questions/45179/civi-crm-apiv4-image-retrieval) recently.https://lab.civicrm.org/dev/core/-/issues/4406SearchKit: make 'inplace edit' conditional2023-07-09T03:06:31Zaydunsaidan.saunders@squiffle.ukSearchKit: make 'inplace edit' conditionalSuggestion: apply conditional rules (like those on the `Style` option) to `In-place edit`
Use case:
On a listing of Participant Status Types, we want to enable in-place edit if the type is not `Reserved`Suggestion: apply conditional rules (like those on the `Style` option) to `In-place edit`
Use case:
On a listing of Participant Status Types, we want to enable in-place edit if the type is not `Reserved`colemanwcolemanwhttps://lab.civicrm.org/dev/core/-/issues/4404Possibility to reuse the list of languages available for "Preferred language"2023-07-06T06:36:35ZquimgilPossibility to reuse the list of languages available for "Preferred language"Overview
----------------------------------------
Out of the box, CiviCRM comes with a full list of languages used for the field "Preferred language". Right now, there is no way to reuse this list in custom fields. Admins must create the...Overview
----------------------------------------
Out of the box, CiviCRM comes with a full list of languages used for the field "Preferred language". Right now, there is no way to reuse this list in custom fields. Admins must create their own list of languages manually or use different unsupported approaches to reuse the one CiviCRM already has.
Example use-case
----------------------------------------
An international organization working with volunteers wants to know in which languages they have basic, advanced, and native/professional fluency, in separate questions.
Current behaviour
----------------------------------------
The list of languages available in CiviCRM's database cannot be reused for custom fields.
Proposed behaviour
----------------------------------------
Make the "Preferred language" list of languages available to custom fields, just like you can create any list that is then available to other custom fields.
Comments
----------------------------------------
See examples of ad hoc solutions admins are recurring to on https://civicrm.stackexchange.com/questions/6604/how-to-reuse-preferred-language-selecthttps://lab.civicrm.org/dev/core/-/issues/4389Can't import using contact id2023-08-03T12:40:09Zaydunsaidan.saunders@squiffle.ukCan't import using contact idOverview
----------------------------------------
`Contact id` cannot be selected as a field to match on when importing.
(I'm fairly certain this used to work, but don't know when it stopped.)
Reproduction steps
-----------------------...Overview
----------------------------------------
`Contact id` cannot be selected as a field to match on when importing.
(I'm fairly certain this used to work, but don't know when it stopped.)
Reproduction steps
----------------------------------------
1. Click on **Contacts -> Import Contacts**.
1. Upload a CSV with a 'contact id' column
1. Note that there is no option to select 'Contact ID' in the field mapping options.
Current behaviour
----------------------------------------
Can't match to existing contact using contact id.
Expected behaviour
----------------------------------------
Can match to existing contact using contact id.
Environment information
----------------------------------------
* __CiviCRM:__ master_ <!-- If this problem relates to an upgrade, then specify both old and new versions -->
Comments
----------------------------------------https://lab.civicrm.org/dev/core/-/issues/4361Add Pay now link to Invoice template2023-06-28T06:58:22ZlarsssandergreenAdd Pay now link to Invoice templateIt would be nice to have the link to pay online included in the Invoice template. Currently, a user would have to guess this is possible, find the correct link on SE and add it to the template (then maintain it as the template is updated...It would be nice to have the link to pay online included in the Invoice template. Currently, a user would have to guess this is possible, find the correct link on SE and add it to the template (then maintain it as the template is updated).
I think if default_invoice_page is set, we could simply include a Pay Now link in the Payment Advice section (which is only shown if the Contribution is pending and pay later). If an org doesn't want to include a link for online payment, they can simply leave default_invoice_page empty (Edit: They cannot currently do this for newer installs, will have to make it possible). I think it would be very rare for an org to want to have a default_invoice_page for payments from the User Dashboard, but not to include a link for online payments in invoices (and in that case, they can edit the template).
Will do this and add docs if supported.https://lab.civicrm.org/dev/core/-/issues/4346Find Groups improvements2023-06-09T07:50:00ZyashodhaFind Groups improvementsThe idea is to give more insight into the parents and children of the said group. It's hard to understand the complexity of the group in the current UI esp in the scenarios where the smart groups are heavily used.
I am proposing this c...The idea is to give more insight into the parents and children of the said group. It's hard to understand the complexity of the group in the current UI esp in the scenarios where the smart groups are heavily used.
I am proposing this change which should help significantly by adding these 2 columns to the listing :
- Parent - Add parent column which shows parents count which is a url when clicked lists all parents groups
- Children - Add children column which shows children count which is a url when clicked lists all child groupsyashodhayashodhahttps://lab.civicrm.org/dev/core/-/issues/4339Add hook for member userdashboard for altering results2023-06-09T07:48:14ZyashodhaAdd hook for member userdashboard for altering resultsAdd hook for member userdashboard for altering resultsAdd hook for member userdashboard for altering resultsyashodhayashodhahttps://lab.civicrm.org/dev/core/-/issues/4332Error in membership status after a) changing membership type followed by b) p...2023-11-23T07:23:38ZJoeMurrayError in membership status after a) changing membership type followed by b) payment failure## Overview
Using a pay later payment when renewing a membership can lead to problems with the membership status, membership end date and membership type being changed at the time of the renewal being initiated ; these fields are update...## Overview
Using a pay later payment when renewing a membership can lead to problems with the membership status, membership end date and membership type being changed at the time of the renewal being initiated ; these fields are updated without a payment being recorded. It is possible that a payment will never be received, or its processing may fail. It is not easy to revert the data to its former state, or what it would have become through time from date of update to when the correction is attempted. For example, a renewal with a delayed payment might change the status from Grace to Current, the End Date from May 14, 2023 to May 14, 2024, and the Membership Type from General to Student.
These are very old problems dating to at least 2013 I believe.
The problem only occurs when both membership types have the same parent organization, and only for paid memberships. It occurs whether the membership period is Rolling or Fixed, and whether a membership type is being changed or not.
## Proposal
Refactor the current implementation so that a second, temporary membership is created that can store the new information without overwriting the old information until a payment is received for it. The new temporary membership would have a status of Pending. The Pending contribution would be related to the temporary rather than existing membership. When the payment is received (status=complete), the Pending membership's information is used to update the permanent membership, and the temporary membership record is deleted.
## Relevant code
In the Contribution Confirmation page postProcess call [legacyProcessMembership](https://github.com/civicrm/civicrm-core/blob/master/CRM/Contribute/Form/Contribution/Confirm.php#L1623), various fields are updated before the doPayment call is processed [here](https://github.com/civicrm/civicrm-core/blob/master/CRM/Contribute/Form/Contribution/Confirm.php#LL1702C42-L1702C51). As a result, the existing membership record is updated with selected membership type/end date/status after user submits a payment but before the code makes payment request, e.g. to a payment processor. This works if the payment went successfully.
In the case of a payment failure such as for IPN payment processors like Paypal Standard (occasionally when there is a delay on getting IPN callback or if the IPN response is not handled properly like https://lab.civicrm.org/dev/core/-/issues/1931) or for a manual Pay Later payment that isn't received, it leaves the selected membership in current/active state with a changed end date and possibly a different membership type. There is no fallback code written to revert the membership state or set it to Pending, and it isn't easy to reconstruct the data.
## New Behaviour
1. When initiating the Payment for Membership Renewal, create a new membership record and link the contribution in pending status to it. Add a new field, renewing_membership_id, to civicrm_membership to hold a reference from this 'temporary' pending membership to the existing membership that is being renewed. The existing membership record remains unchanged.
2. When the contribution status of the related contribution changes to Complete, update the original membership with the information from the temporary membership and delete the temporary membership.
Recommendation: delay the creation of activities for Membership Renewal (id=8), Change Membership Status (id=35) and Change Membership Type (id=36) until the contribution is completed.
Recommendation: create a new Activity Type, Membership Renewal Pending, to be created when the renewal request is received. In its body, provide: "ID of Membership being renewed: xx, Number of Periods: yy, Membership Type: [Label of Membership Type".
## Implementation:
1. Modify [here](https://github.com/civicrm/civicrm-core/blob/master/CRM/Contribute/Form/Contribution/Confirm.php#L2900), CRM_Member_BAO_Membership::getContactMembership and [here](https://github.com/civicrm/civicrm-core/blob/master/CRM/Contribute/Form/Contribution/Confirm.php#L2939).
2. Add / update new / existing unit tests on these new scenarios.EdselopezEdselopezhttps://lab.civicrm.org/dev/core/-/issues/4316Allow administrators to restrict which contacts will receive an email notific...2023-05-31T23:54:42Zayush_compucoAllow administrators to restrict which contacts will receive an email notification when an activity is assigned to a contactHow it works currently:
----------------------------------------
Administrators can only choose either to enable or disable sending email notifications (including a copy of the activity) when an activity is assigned to a contact OR limit...How it works currently:
----------------------------------------
Administrators can only choose either to enable or disable sending email notifications (including a copy of the activity) when an activity is assigned to a contact OR limit it to specific types of activity.
![image](/uploads/15806181b9f0204f847f4e8a8a70b817/image.png)
https://dmaster.demo.civicrm.org/civicrm/admin/setting/preferences/display?reset=1
**Improvement**
----------------------------------------
We would like to allow administrators to specify which groups of users would receive an email so that certain users can be assigned an activity, but they would not receive CiviCRM's default activity assignee email.
**Note**
----------------------------------------
Note, there is already some similar (but subtly different!) functionality on CiviCase for case activities:
![image](/uploads/7683b54741cb91ec61227f47c7eb87cc/image.png)
The above restricts **who can be selected** to be assigned an activity, whereas we are specifying **who would be sent** a notification for an activity.
**Proposed solution**
----------------------------------------
We propose adding a new functionality that allows administrators to specify which CiviCRM groups would receive an email notifications. This can be achieved by introducing a new dropdown field.
We would create 2 new settings for this under the setting for "Do not notify assignees for" <Activity types> on the Display Preferences page: https://dmaster.demo.civicrm.org/civicrm/admin/setting/preferences/display?reset=1 which states:
1. Restrict email recipients to groups
- <Select Group> (list all CiviCRM groups or smart groups)
- Multiselect
- Help: Limit which contacts will receive a CiviCRM activity notification email when an activity is assigned to them. You can select any group or smart group. Leave blank for no restriction. Note that you may still assign an activity to a contact who is not in the group, but they will not receive an email.
If the field is blank there will be no restriction. If a group is selected, emails will be restricted to only go to that group.
2. Restrict email recipients to Website Users
- Checkbox
- Help: Limit which contacts will receive a CiviCRM activity notification email to only be those who have a CMS user when an activity is assigned to them. Note that you may still assign an activity to a contact who does not have a CMS user, but they will not receive an email.
Emails will be suppressed in each case.
**Next steps**
----------------------------------------
We are prepared to submit a pull request (PR) for this feature. If the concept is approved, we will promptly submit the core PR.
Thank you.https://lab.civicrm.org/dev/core/-/issues/4308CryptoKeys - Converting CryptoException into status messages2023-06-05T14:10:29ZVangelisPCryptoKeys - Converting CryptoException into status messages### Overview
From time to time, we clone/replicate our live sites into our development servers to do some reviews/coding enhancements etc. Since the live sites are having a different key from the development site(s), whenever we try to ...### Overview
From time to time, we clone/replicate our live sites into our development servers to do some reviews/coding enhancements etc. Since the live sites are having a different key from the development site(s), whenever we try to access the path `/civicrm/admin/setting/smtp?reset=1` (and assuming that we had set the configuration to SMTP with a username & password in live), we end up with an exception error: "Failed to find key by ID or tag", leaving us unable to access the page so that we can modify or re-enter the SMTP password.
### Reproduction steps
* Configure `CIVICRM_CRED_KEYS`
* Go to `/civicrm/admin/setting/smtp?reset=1`
* Set up the mailer as SMTP and store a password
* Clone the site's database and filebase (except the `civicrm.settings.php`) into another site OR change the `CIVICRM_CRED_KEYS`
* Try to access the page `/civicrm/admin/setting/smtp?reset=1`. You will get an exception error and the page won't load.
### Expected behaviour
* Manage to get to the page `/civicrm/admin/setting/smtp?reset=1` but throw a status message that there's something wrong with the stored password.
### Proposed solution
* On `/Civi/Crypto/CryptoRegistry.php` convert the `CryptoException`s into Status messages
* On `/Civi/Crypto/CryptoToken.php` check if the variable `$key` is null or set and if not, return the `$plaintext`
This way, even if the system cannot decode/decrypt properly the key, we will still be able to return to the password page but also throw the notices to the visitor.
I'm assuming that this exact behaviour/effect fires up wherever we use the crypto functionality.
I am also aware that in order to fix this, one needs to also configure the *same* `CIVICRM_CRED_KEY` as seen in the live site.
If this makes any sense, I can provide a patch/PR.
### Environment information
* CiviCRM: 5.57
* PHP: 7.4.33
* CMS: Drupal 9.4.15https://lab.civicrm.org/dev/core/-/issues/4301FormBuilder: Allow placeholder text to be configured2023-05-24T06:34:31Zaydunsaidan.saunders@squiffle.ukFormBuilder: Allow placeholder text to be configuredIt would be nice to be able to specify placeholder text on form fields such as filters.It would be nice to be able to specify placeholder text on form fields such as filters.https://lab.civicrm.org/dev/core/-/issues/4298CiviMail - throw 400 (Bad Request) rather than 500 (Server Error) if public u...2023-07-27T17:17:06ZufundoCiviMail - throw 400 (Bad Request) rather than 500 (Server Error) if public url endpoints hit with bad parametersOverview
----------------------------------------
Urls for CiviMail public endpoints like `civicrm/mailing/open` have a few required parameters, identifying the user / url etc. How should we handle if params aren't valid?
Current behavi...Overview
----------------------------------------
Urls for CiviMail public endpoints like `civicrm/mailing/open` have a few required parameters, identifying the user / url etc. How should we handle if params aren't valid?
Current behaviour
----------------------------------------
Current standard behaviour Civi-wide for missing/invalid params is a `CRM_Core_Exception`, which in turn results in a 500 server error.
Proposed behaviour
----------------------------------------
I think a 400 Bad Request error is more appropriate, for the "public" CiviMail links in particular.
Comments
----------------------------------------
It also helps with detecting and blocking spammy click behaviour, which I've seen with random permutations of parameters and things like this.5.65.0https://lab.civicrm.org/dev/core/-/issues/4296FormBuilder filters suggestion: text filter as select2023-06-08T18:02:44Zaydunsaidan.saunders@squiffle.ukFormBuilder filters suggestion: text filter as selectOverview
----------------------------------------
For FormBuilder filters, it would be useful to have the option to turn `Text` into `Select`.
Example use-case
----------------------------------------
For a search return results like:
...Overview
----------------------------------------
For FormBuilder filters, it would be useful to have the option to turn `Text` into `Select`.
Example use-case
----------------------------------------
For a search return results like:
```
Org, Contact
------------
Org1, ContactA
Org1, ContactB
Org1, ContactC
Org2, ContactD
Org2, ContactE
```
you can add a filter on Org Display Name which is displayed as a text box.
It would be nice to be able to present this as a `Select` dropdown of 'Org1', 'Org2' etc (or even multi-select). The configuration for the filter provides a `Type` box with several options, so add a `Select` one to that (in addition to the existing `Text`).
The current text filter is a substring match which means that if one display name is a substring of another, you can't filter to just the shorter name. So eg 'Org1', 'Org1 - committee A', 'Org1 - committee B' you can't just show 'Org1'. Turning this into a `Select` should either exact match on the text string or convert to filtering by `id`.https://lab.civicrm.org/dev/core/-/issues/4290SearchKit: Return results faster by optimizing access check2023-05-15T08:14:11ZlarsssandergreenSearchKit: Return results faster by optimizing access checkThrough some testing, it looks like quite a bit of the execution time for SearchKit results on Compose Search, at least for relatively simple queries, is being spent checking the current user's access to edit or delete the specific entit...Through some testing, it looks like quite a bit of the execution time for SearchKit results on Compose Search, at least for relatively simple queries, is being spent checking the current user's access to edit or delete the specific entity for the View / Edit / Delete menu in the last column. It's not too bad with just 50 rows, but if you increase the page size to 100 or more, there's a pretty perceptible difference between checking the access and skipping that access check. I had a few thoughts about how we could improve this:
1. Since we aren't actually showing the links until the user clicks on the hamburger menu, we could just add the links as usual, but then check access in JS and only unhide those that the user has access to. This way we aren't doing 100 checkAccess API calls per page of 50 entities (one for update, one for delete). This would make the Compose Search page faster as well as any Displays that contain the same menu, but wouldn't help if there are links or buttons in a Display.
2. I think quite a few of the users accessing Compose Search probably have superadmin, so we could check that at the start of the process and then skip the access checks for each row.
3. Maybe it would make sense to make it possible to pass an array of ids to the checkAccess API. I don't know the details of how this works, but imagine that would speed up the process. At least for Contacts, there already is `allowList()`, so maybe this could be implemented just for Contacts without too much trouble.https://lab.civicrm.org/dev/core/-/issues/4255AdminUI breadcrumb links are confusing and unhelpful2023-05-02T07:14:25ZlarsssandergreenAdminUI breadcrumb links are confusing and unhelpfulOverview
----------------------------------------
The breadcrumb links for AdminUI pages are incorrect and confusing for users.
Current behaviour
----------------------------------------
For example for profile fields, the breadcrumb li...Overview
----------------------------------------
The breadcrumb links for AdminUI pages are incorrect and confusing for users.
Current behaviour
----------------------------------------
For example for profile fields, the breadcrumb links are:
`Home › CiviCRM › Admin › FormBuilder › Edit Form › Profile Fields`
If a user clicks the breadcrumb link for Profile Fields, they get all profile fields for all profiles, not just the profile fields for their profile. They also cannot go back to the main profiles page or the settings for the profile they are editing the fields for.
This is the same for custom fields and other AdminUI pages.
Expected behaviour
----------------------------------------
The breadcrumb links should be:
`Home › CiviCRM › Admin › Profiles › PROFILENAME › Profile Fields`
Clicking the breadcrumb links should lead to the expected pages.
Environment information
----------------------------------------
dmasterhttps://lab.civicrm.org/dev/core/-/issues/4243Support APCu with apcu_* functions2023-04-18T17:34:00ZherbdoolSupport APCu with apcu_* functionsAPC and APCu is supported according to https://docs.civicrm.org/sysadmin/en/latest/setup/cache/#config-ref but it currently only supports `apc_*` functions which are ~~backwards-compatible with~~ _not compatible_ with APC. ~~But some set...APC and APCu is supported according to https://docs.civicrm.org/sysadmin/en/latest/setup/cache/#config-ref but it currently only supports `apc_*` functions which are ~~backwards-compatible with~~ _not compatible_ with APC. ~~But some setups may only have the newer `apcu_*` functions so the class should try both functions.~~ APCu only has `apcu_*` functions, but still uses `apc.` for the configuration.
UPDATE: discovered there are some differences between the two in how they handle things, which isn't surprising. So depending on how much they differ, may require different classes.https://lab.civicrm.org/dev/core/-/issues/4127is_drupal: move functionality that calls this deprecated variable to System c...2023-03-03T12:22:06Zherbdoolis_drupal: move functionality that calls this deprecated variable to System classes`CRM_Utils_System::is_drupal` (and `is_wordpress`, `is_joomla`) is deprecated so need to move these to the System classes. Some of these are minor so I figure it's easier to capture a few different PRs with this issue.
1. `CRM_Custom_Fo...`CRM_Utils_System::is_drupal` (and `is_wordpress`, `is_joomla`) is deprecated so need to move these to the System classes. Some of these are minor so I figure it's easier to capture a few different PRs with this issue.
1. `CRM_Custom_Form_Group::postProcess()`
2. `CRM_Utils_System::ipAddress()`
3. `CRM_Core_Error::debug_log_message()`
4. `CRM_Core_BAO_UFMatch::synchronizeUFMatch()`
5. `CRM_UF_Page_Group::profile()`
6. `CRM_Mailing_Info::workflowEnabled()`
7. `CRM_Utils_System_Base::getCiviSourceStorage()`
8. `CRM_Dedupe_Merger::relTables()`
`$config->userFramework` has not been deprecated and might still be useful for templates and such. Should any call to `$config->userSystem->is_drupal` be replaced with the more verbose: `$config->userFramework EQ 'Drupal' || $config->userFramework EQ 'Backdrop' || $config->userFramework EQ 'Drupal8'`.https://lab.civicrm.org/dev/core/-/issues/4125Use a maintenance template and theme for Drupal 8/9+ in CRM_Utils_System_Drup...2023-02-20T06:21:58ZherbdoolUse a maintenance template and theme for Drupal 8/9+ in CRM_Utils_System_Drupal8::theme() (follow up to dev/core#4076)In https://lab.civicrm.org/dev/core/-/issues/4076 we're splitting up the `theme()` method and putting it into each System class. The Drupal8 method doesn't behave like Drupal 7's, which uses the maintenance template and theme (without th...In https://lab.civicrm.org/dev/core/-/issues/4076 we're splitting up the `theme()` method and putting it into each System class. The Drupal8 method doesn't behave like Drupal 7's, which uses the maintenance template and theme (without the admin menu, etc). It would be nice if it did.
A first attempt looked like the following but it's missing the Civi core JS and CSS:
```
public function theme(&$content, $print = FALSE, $maintenance = FALSE) {
$ret = FALSE;
if (!$print) {
if ($maintenance) {
if ($region = CRM_Core_Region::instance('html-header', FALSE)) {
CRM_Utils_System::addHTMLHead($region->render(''));
}
$renderer = \Drupal::service('bare_html_page_renderer');
$build['content'] = [
'#markup' => \Drupal\Core\Render\Markup::create($content),
];
$civicrmPageState = \Drupal::service('civicrm.page_state');
$title = $civicrmPageState->getTitle();
$response = $renderer->renderBarePage($build, $title, 'maintenance_page');
print $response->getContent();
exit();
}
$ret = TRUE;
}
$out = $content;
if ($ret) {
return $out;
}
else {
print $out;
return NULL;
}
}
```