Development issueshttps://lab.civicrm.org/groups/dev/-/issues2022-10-20T07:25:22Zhttps://lab.civicrm.org/dev/core/-/issues/3896api.Contact.create happy to create invalid employer relationship2022-10-20T07:25:22Zkonadaveapi.Contact.create happy to create invalid employer relationshipOverview
----------------------------------------
api.Contact.create does not check that the relationship between `employer_id` and the contact is valid.
Reproduction steps
----------------------------------------
Reproduced on dmaster....Overview
----------------------------------------
api.Contact.create does not check that the relationship between `employer_id` and the contact is valid.
Reproduction steps
----------------------------------------
Reproduced on dmaster.demo using combo of UI and API 3 Explorer. Showing as command line here to better illustrate.
```bash
$ cv api Contact.create first_name="Mickey" last_name="Mouse" email="mickey.mouse@example.com" contact_type="Individual"
{
"is_error": 0,
"version": 3,
"count": 1,
"id": 9,
"values": {...}
}
$ cv api Contact.create first_name="Minnie" last_name="Mouse" email="minnie.mouse@example.com" contact_type="Individual"
{
"is_error": 0,
"version": 3,
"count": 1,
"id": 10,
"values": {...}
}
$ cv api RelationshipType.getsingle name_b_a="Employer of" return="id,contact_type_b"
{
"id": "5",
"contact_type_b": "Organization"
}
$ cv api Relationship.create contact_id_a="9" contact_id_b="10" relationship_type_id="5"
{
"tip": "add debug=1 to your API call to have more info about the error",
"is_error": 1,
"error_message": "Invalid Relationship"
}
$ cv api Contact.create id="9" employer_id="10"
{
"is_error": 0,
"version": 3,
"count": 1,
"id": 9,
"values": {...}
}
$ cv api Relationship.get contact_id_a="9"
{
"is_error": 0,
"version": 3,
"count": 1,
"id": 5,
"values": {
"5": {
"id": "5",
"contact_id_a": "9",
"contact_id_b": "10",
"relationship_type_id": "5",
"is_active": "1",
"is_permission_a_b": "0",
"is_permission_b_a": "0",
"created_date": "2022-10-05 19:48:23",
"modified_date": "2022-10-05 19:48:23"
}
}
}
```
Current behaviour
----------------------------------------
An invalid relationship is created. On the contact summary screen, an employer may or may not be listed, but it's unlikely to be the invalid contact (i.e. it lists a unrelated org instead).
Expected behaviour
----------------------------------------
The API call should fail for the same reason as api.Relationship.create.
Environment information
----------------------------------------
Confirmed on dmaster.demo, and a local vanilla install of D9/Civi 5.48.2.https://lab.civicrm.org/dev/core/-/issues/3889API4 dates entered without time can give unexpected results2022-10-25T11:50:59ZlarsssandergreenAPI4 dates entered without time can give unexpected resultsFor a datetime field, any date in an API call is converted to a datetime (midnight on the date in question). This can give unexpected results for gets, especially using Search Kit or Form Builder, where users probably aren't thinking abo...For a datetime field, any date in an API call is converted to a datetime (midnight on the date in question). This can give unexpected results for gets, especially using Search Kit or Form Builder, where users probably aren't thinking about dates versus datetimes. These results also aren't consistent with what you get from Advanced Search or other searches.
For example, searching for a contribution with receive_date = 2022-01-01 does not return all contributions received on that date. It only returns contributions received at exactly midnight, i.e. with receive_date = 20220101000000.
Similar issues exist for other operators, like !=, > (will include the date), <= (won't include the date), BETWEEN and NOT BETWEEN (will include the from date, but not the to date), and IN and NOT IN.
The simplest solution would be to put a SQL DATEFORMAT() around the database date field when the date does not include a time and use a Ymd format. This wouldn't work for BETWEEN or IN when one date includes a time and the other doesn't though.
Or if we don't want to change the query, another approach would be to check absolute dates entered into the API to see if they include a time component or not.
- If they include a time, proceed as usual.
- If they don't include times, for all operators except = and !=/<>, set the time component or components depending on the operator (e.g. for BETWEEN set 000000 for the from date, 235959 for the to date).
- For = or !=, switch the operator to BETWEEN or NOT BETWEEN, set the from date to 000000 and the to date to 235959.
- For IN and NOT IN, I'm not sure there's an easy solution in this case. We'd have to convert that to a series of BETWEENs and that's going to be difficult. Is there a good way to warn users that this won't work?
- Not sure what the other operators are supposed to do with dates.
But maybe there's a more elegant solution to this problem. Hoping to get some expert feedback before starting any work on this, since date stuff can be such a quagmire.https://lab.civicrm.org/dev/core/-/issues/3940Method and Tracking not set from API4 for Subscription History when creating ...2022-10-31T17:07:22ZlarsssandergreenMethod and Tracking not set from API4 for Subscription History when creating or updating GroupContactMethod and Tracking can be specified when creating or updating a GroupContact in API4 (with a default Method of API). However, these are always set as null for the Subscription History that is created.
I've been doing some debugging to ...Method and Tracking can be specified when creating or updating a GroupContact in API4 (with a default Method of API). However, these are always set as null for the Subscription History that is created.
I've been doing some debugging to follow these variables through the process and can see where this is going wrong, but am not clear on how this should actually work. The Subscription History is created by a [hook_post](https://github.com/civicrm/civicrm-core/blob/902fc38d0d6cd9d09ee02f30cc6621747151a06a/CRM/Contact/BAO/GroupContact.php#L39). The hook isn't even trying to set the Method and Tracking, nor does it have access to these variables (they are there when the GroupContact is created, but they aren't used for that).
I'm not clear on how these variables are supposed to get from the API call to the hook here. Happy to implement a fix, but not sure I understand how this is supposed to work or if we need to use an entirely different approach. I will also do the same with the delete action, which [I'm adding Subscription History to](https://github.com/civicrm/civicrm-core/pull/24804), so I'm looking for an approach which will also work for delete.https://lab.civicrm.org/dev/core/-/issues/4051ApiV4 - add options2022-12-27T20:14:54ZeileenApiV4 - add options@totten has added something to `cv` where you can add an option to an existing field - I think this feature makes sense, but as a an apiv4 feature (rather than a cv feature) and across multiple entities rather than just Settings. There a...@totten has added something to `cv` where you can add an option to an existing field - I think this feature makes sense, but as a an apiv4 feature (rather than a cv feature) and across multiple entities rather than just Settings. There are different ways it could look but in essence you are looking to be able to offer stuff like
```
Setting::update()->addWhere('name', '=', 'enable_components')->addOption(['CiviCampaign'])->execute();
Setting::update()->addWhere('name', '=', 'enable_components')->removeOption(['CiviCampaign'])->execute();
Contact::update()->addWhere('id', '=', 123)->addOption(['contact_sub_type' => 'Student'])->execute();
Contact::update()->addWhere('id', '=', 123)->removeOption(['contact_sub_type' => 'Student'])->execute();
```
I'm not sure the exact syntax or whether it should be on the `update` action - one for @colemanw
- This would probably be limited to fields with `is_multiple` or `serialize` or some other indicator of multiple-value-ness (whatever we land on for settings) & be validated against the relevant pseudoconstant or callback-option-listhttps://lab.civicrm.org/dev/core/-/issues/4117Filter Searches by 'is_current' / expires_date2023-02-07T23:27:08ZeileenFilter Searches by 'is_current' / expires_dateThe `civicrm_search` table has an `expires_date` field. I believe it should be used as a filter on the search admin screen.
I copied the field into `civicrm_user_job` when I created that and the searches based on user jobs have expires_...The `civicrm_search` table has an `expires_date` field. I believe it should be used as a filter on the search admin screen.
I copied the field into `civicrm_user_job` when I created that and the searches based on user jobs have expires_date set from the user job.
I realised it is a bit of a pain to add to the js as it would be `expires_date` is in the past OR is NULL - which got me thinking that it is most like `is_current` & perhaps should be a trait like that - with is_current = TRUE as a default
@colemanw - what has me most confused is where to put it - I could add it to `IsCurrentSpecProvider` & it just has different rules - maybe I'll tryhttps://lab.civicrm.org/dev/core/-/issues/4129API v4 explorer: boolean params don't render correctly for CV (short)2023-02-20T06:24:39ZnoahAPI v4 explorer: boolean params don't render correctly for CV (short)The API4 explorer generates shorthand `cv` syntax that looks like, for example:
````bash
cv api4 Contact.delete +w 'id = 99' checkPermissions=false useTrash=false
````
However, `cv` does not correctly interpret `false` in this context....The API4 explorer generates shorthand `cv` syntax that looks like, for example:
````bash
cv api4 Contact.delete +w 'id = 99' checkPermissions=false useTrash=false
````
However, `cv` does not correctly interpret `false` in this context. The syntax that works is:
````bash
cv api4 Contact.delete +w 'id = 99' checkPermissions=0 useTrash=0
````
So the explorer should generate that syntax.https://lab.civicrm.org/dev/core/-/issues/4182Create a generic copy or clone api2023-03-17T07:50:37ZeileenCreate a generic copy or clone apiThis is a spin off of https://lab.civicrm.org/dev/core/-/issues/4130
I was looking at supporting import job templates & thought a clone or copy api makes sense.
I'm no longer prioritising this part & I think putting the code in the fo...This is a spin off of https://lab.civicrm.org/dev/core/-/issues/4130
I was looking at supporting import job templates & thought a clone or copy api makes sense.
I'm no longer prioritising this part & I think putting the code in the form layer or BAO layer for the specific entity is enouugh for now.
In order to clone the job the code looks something like
```
$userJob = UserJob::get()->addWhere('id', '=', $templateID)->execute()->first();
unset($userJob['metadata']['DataSource']['table_name'], $userJob['metadata']['submitted_values']['uploadFile'], $userJob['id'], $userJob['created_id'], $userJob['created_date'], $userJob['expires_date']);
$userJobID = UserJob::create(FALSE)->setValues($userJob)->execute()->first()['id'];
```
I feel like there is a case for a generic `Copy` api - in the `DAO` we have [a function with a signature that I think is probably 'a bit much'](https://github.com/civicrm/civicrm-core/blob/8bf6c5853cf76da43765cd8ef79d4323a442f350/CRM/Core/DAO.php#L1845-L1868) - so it might make sense to migrate to a new function... & create a generic API
I checked what Entities implement `Copy` and found a handful -the non static ones are not in the BAO - so we just have one non-std signature which is unused https://github.com/civicrm/civicrm-core/pull/25594
![image](/uploads/c4e1bbdf63fb79efaa06b03bca44fde4/image.png)
One option would be to add a parameter to the schema eg.
'is_not_clonable'
And then we could add that to fields like `created_id` and they would not need to be in the params. We already have the title of the entity so can assume that should be prefixed with `Copy Of`. The `UserJob` would have to override to set some of the deeper valueshttps://lab.civicrm.org/dev/core/-/issues/4199SearchKit: DB Error: no such field a.total_amount when adding Tax Exclusive A...2023-03-24T03:46:42ZherbdoolSearchKit: DB Error: no such field a.total_amount when adding Tax Exclusive Amount and Balance (starting with Line Items : Contributions)Overview
----------------------------------------
There's an "Unknown column `a.total_amount` when trying to add these fields onto a SearchKit search that starts with `Line Items` and with `Contributions`:
Line Item Contribution: Tax Ex...Overview
----------------------------------------
There's an "Unknown column `a.total_amount` when trying to add these fields onto a SearchKit search that starts with `Line Items` and with `Contributions`:
Line Item Contribution: Tax Exclusive Amount
Line Item Contribution: Balance
**Note this only happens when starting with Line Items and *not* when starting with Contributions (and optionally adding Line Items).**
It's adding a field like this:
```
COALESCE(a.total_amount, 0) - COALESCE(a.tax_amount, 0) AS `LineItem_Contribution_contribution_id_01.tax_exclusive_amount`
```
and like this:
```
a.total_amount - COALESCE((SELECT SUM(ft.total_amount) FROM civicrm_financial_trxn ft
INNER JOIN civicrm_entity_financial_trxn eft ON (eft.financial_trxn_id = ft.id AND eft.entity_table = 'civicrm_contribution')
WHERE eft.entity_id = a.id AND ft.is_payment = 1 AND ft.status_id IN (1,7)), 0) AS `LineItem_Contribution_contribution_id_01.balance_amount`
```
where `a` is `civicrm_line_item`. It's assuming, I think, that the first table is `civicrm_contributions`.
Current behaviour
----------------------------------------
_What happens currently. Please provide error messages, screenshots or gifs ([LICEcap](http://www.cockos.com/licecap/), [SilentCast](https://github.com/colinkeenan/silentcast)) where appropriate._
Environment information
----------------------------------------
* __CiviCRM:__ 5.58.1 (but I looked through the release notes and I don't think it was fixed in 5.59.x)https://lab.civicrm.org/dev/core/-/issues/4110Can't edit Activity source, targets, assignees in FormBuilder2023-04-05T16:48:01ZnoahCan't edit Activity source, targets, assignees in FormBuilder[As reported](https://chat.civicrm.org/civicrm/pl/eprjkpg4cbrcbbj7u64qnbsohc) by @guyiac on MM:
I'm trying to use a form to edit existing activities. I can pass the existing activity id successfully with an URL, and all the information ...[As reported](https://chat.civicrm.org/civicrm/pl/eprjkpg4cbrcbbj7u64qnbsohc) by @guyiac on MM:
I'm trying to use a form to edit existing activities. I can pass the existing activity id successfully with an URL, and all the information for the activity will pre-fill into the form, ***except*** the contacts (targets, assigned to, and created by). Am I missing something? Civi 5.54.0.https://lab.civicrm.org/dev/core/-/issues/4226Mapping.mapping_id does not resolve in api v4 explorer2023-04-12T07:28:35ZeileenMapping.mapping_id does not resolve in api v4 explorer@colemanw what is the right approach here - there is a foreign key - but civicrm_mapping only has name, not label etc -(I kinda see this table being deprecated over time too)
![image](/uploads/618ea8286b9b6792ccad8de319ff311f/image.png)...@colemanw what is the right approach here - there is a foreign key - but civicrm_mapping only has name, not label etc -(I kinda see this table being deprecated over time too)
![image](/uploads/618ea8286b9b6792ccad8de319ff311f/image.png)
```
<field>
<name>mapping_id</name>
<type>int unsigned</type>
<title>Mapping ID</title>
<required>true</required>
<comment>Mapping to which this field belongs</comment>
<html>
<label>Mapping</label>
</html>
<add>1.2</add>
</field>
<foreignKey>
<name>mapping_id</name>
<table>civicrm_mapping</table>
<key>id</key>
<add>1.2</add>
<onDelete>CASCADE</onDelete>
</foreignKey>
```https://lab.civicrm.org/dev/core/-/issues/4141API4: When searching by date range, end of range is not included2023-04-22T17:05:33ZlarsssandergreenAPI4: When searching by date range, end of range is not includedWhen you use SearchKit to search by date range on a datetime field (i.e. between two dates), the end date is not included in the results because it interprets 12/31/2022 as 20221231000000 instead of the expected 20221231235959. The same ...When you use SearchKit to search by date range on a datetime field (i.e. between two dates), the end date is not included in the results because it interprets 12/31/2022 as 20221231000000 instead of the expected 20221231235959. The same happens in FormBuilder with a date filter and Choose date range. This comes from API4, where `->addWhere('receive_date', 'BETWEEN', ['2022-01-01', '2022-12-31'])` is interpreted as to 20221231000000 rather than to 20221231235959.
This is quite confusing for users, e.g. when last quarter doesn't give the same results as 10/01/2022 - 12/31/2022.
I think the fix is simply to use a default time of 23:59:59 if none is specified for an end date, but I'm not sure if that might cause unexpected behaviour elsewhere.https://lab.civicrm.org/dev/core/-/issues/4403SK / API 4 Explorer: event_queue_id, job id, bounce id, etc autocompletes don...2023-07-05T04:30:05ZlarsssandergreenSK / API 4 Explorer: event_queue_id, job id, bounce id, etc autocompletes don't workEdited as this issue is more general than I thought. Fairly minor issue, but:
In SK or API 4 Explorer, for mailing event id fields (event queue id, job id, bounce id, etc), the autocomplete fields don't work. No matter what you input, i...Edited as this issue is more general than I thought. Fairly minor issue, but:
In SK or API 4 Explorer, for mailing event id fields (event queue id, job id, bounce id, etc), the autocomplete fields don't work. No matter what you input, it shows `Loading failed` and you can't make a selection.
To replicate: Choose MailingEventBounce or similar, Where event_queue_id and =.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/2484Create apiv4 payment api2023-07-13T08:07:37ZeileenCreate apiv4 payment apiIn order to be able to search for payments we need to be able to search for payment rows (rows with is_payment = TRUE) in the financial_trxn table and for the entity bridge to be able to find it's way from there to the contribution table...In order to be able to search for payments we need to be able to search for payment rows (rows with is_payment = TRUE) in the financial_trxn table and for the entity bridge to be able to find it's way from there to the contribution table.
This gives us the ability to say find all contributions with a payment with a payment instrument of 'Check' or find the contribution where the payment's trxn value is y
The scope I would be looking for is
1) can use any of the fields in financial_trxn as a filter
2) can logically link to the contribution (probably through bridge entities)
3) forces 'is_payment' as a filter (only gets payments)
4) the create action calls Payment.create
5) the update & delete actions are blocked
This effectively gives us parity with the v3 api albeit with more options provided through the apiv4 layer itself.
Note that I think this is likely blocked on other feature requests which @mattwire will add notes onhttps://lab.civicrm.org/dev/core/-/issues/4320API: Should NOT operators return NULL values?2023-07-13T23:50:59ZlarsssandergreenAPI: Should NOT operators return NULL values?If you do != 5 in SQL, you'll get all rows that aren't 5, not including null values. This is the same in the API and SearchKit. I wonder if this is the desired behaviour? I would think the assumption would be that if I search for all Con...If you do != 5 in SQL, you'll get all rows that aren't 5, not including null values. This is the same in the API and SearchKit. I wonder if this is the desired behaviour? I would think the assumption would be that if I search for all Contributions where the Contribution Page is != 5, I would get all Contributions except those that have Contribution Page = 5 — but what I actually get is all Contributions that have a Contribution Page, but where that Contribution Page isn't 5.
In other words, I think you'd generally expect that if you search all Contributions where Contribution Page = 5 OR Contribution Page != 5, you'd just get all Contributions, but you only get Contributions with a Contribution Page. Obviously, your expectation might change based on your familiarity with SQL.
This is the same for NOT LIKE, NOT REGEX, and so on.
On the one hand, it's generally better to keep the behaviour of the API operators the same as SQL to avoid confusion. On the other hand, I'm having a hard time imagining a search you might want to make with a NOT that you wouldn't want to include null values, so this seems unhelpful and potentially frustrating. Is this something we should consider changing?https://lab.civicrm.org/dev/core/-/issues/4423Slow contact lookup query in SearchKit2023-07-15T12:58:42ZeileenSlow contact lookup query in SearchKitI think we might be doing something weird when we query for an id in search kit / api4
It takes about 30 seconds to return here - that is what I might expect if I was waiting for it to search without an index (ie a pre-pended wildcard) ...I think we might be doing something weird when we query for an id in search kit / api4
It takes about 30 seconds to return here - that is what I might expect if I was waiting for it to search without an index (ie a pre-pended wildcard) but of course we turned that off using the site setting
![image](/uploads/acb69198d4abda193d10b5e2fd103252/image.png)https://lab.civicrm.org/dev/core/-/issues/4431API4: "!=" has unexpected results on NULL fields2023-07-21T09:59:23ZJonGoldAPI4: "!=" has unexpected results on NULL fieldsOverview
----------------------------------------
Using the `!=` operator when some of the values are `NULL` does not return the `NULL` records.
Reproduction steps
----------------------------------------
1. On a demo site (which by def...Overview
----------------------------------------
Using the `!=` operator when some of the values are `NULL` does not return the `NULL` records.
Reproduction steps
----------------------------------------
1. On a demo site (which by default has no contacts with a subtype), search for contacts that are not of subtype "Parent".
E.g.:
```php
\Civi\Api4\Contact::get(TRUE)
->addWhere('contact_sub_type', '!=', 'Parent')
->execute();
```
Current behaviour
----------------------------------------
No results are returned.
Expected behaviour
----------------------------------------
All results are returned, since no record is a Parent.
Comments
----------------------------------------
I thought at some point, `!=` internally generated `!= and IS NOT NULL` but maybe that was somewhere else.
I just learned about the MySQL null-safe equals operator, which would also solve this problem: https://stackoverflow.com/a/44723097/2832108https://lab.civicrm.org/dev/core/-/issues/4354Activities created via API should notify Assignees2023-08-03T12:38:52Zwil_SRQActivities created via API should notify AssigneesOverview
----------------------------------------
If the GUI (https://cc.unidosnow.org/civicrm/activity?action=add) would notify assignees when an activity is created. It'd be useful for the API to do so too. The GUI respects the setting...Overview
----------------------------------------
If the GUI (https://cc.unidosnow.org/civicrm/activity?action=add) would notify assignees when an activity is created. It'd be useful for the API to do so too. The GUI respects the setting in Administer > Customize Data and Screens > Display Preferences > Notify Activity Assignees and notification rules by Activity type. It'd be useful for the API to do so too.
Example use-case
----------------------------------------
1. Invoke civicrm_api3('Activity', 'create', []) or civicrm_api4('Activity', 'create', [])
2. Include assignees
Current behaviour
----------------------------------------
The Activity is created but the assignees are not notified, even in situations where creating the equivalent activity via the GUI would have issued notifications.
Proposed behaviour
----------------------------------------
Notify assignees using the same rules and notification format as the GUI.
Comments
----------------------------------------
See https://civicrm.stackexchange.com/q/45078/5446
Workaround is to call CRM_Activity_BAO_Activity::sendToAssignee() separatelyhttps://lab.civicrm.org/dev/core/-/issues/1321group.get API (v3- but lets fix for v4) fails to find groups of one group_typ...2023-08-04T20:49:54ZRichgroup.get API (v3- but lets fix for v4) fails to find groups of one group_type if group has multiple typesWe used (5.15) to be able to filter for mailing groups with the API and now we can't. I'm not sure when this came in.
e.g. on a buildkit at 58e7f004e2
```
cv api Group.get return='id,title,group_type'
```
Returns
```
{
"is_error":...We used (5.15) to be able to filter for mailing groups with the API and now we can't. I'm not sure when this came in.
e.g. on a buildkit at 58e7f004e2
```
cv api Group.get return='id,title,group_type'
```
Returns
```
{
"is_error": 0,
"version": 3,
"count": 4,
"values": {
"1": {
"id": "1",
"title": "Administrators",
"group_type": [
"1"
]
},
"2": {
"id": "2",
"title": "Newsletter Subscribers",
"group_type": [
"1",
"2"
]
},
"3": {
"id": "3",
"title": "Summer Program Volunteers",
"group_type": [
"1",
"2"
]
},
"4": {
"id": "4",
"title": "Advisory Board",
"group_type": [
"1",
"2"
]
}
}
}
```
But
```
cv api Group.get return='id,title,group_type' group_type='Mailing List'
cv api Group.get return='id,title,group_type' group_type=2
```
returns none.
<del>On 5.15 Mailing groups are returned properly.</del>https://lab.civicrm.org/dev/core/-/issues/4458Error when viewing contact-info profile without "view deleted contacts" permi...2023-08-07T12:11:55ZcolemanwError when viewing contact-info profile without "view deleted contacts" permissionThe change in b7edabe813db467aff6dd1ea083d798089198655 switched the profile to use APIv4 to fetch email id for constructing an email link. The API call looks like this:
```php
$emailID = Email::get()->setOrderBy(['is_primary' => 'DES...The change in b7edabe813db467aff6dd1ea083d798089198655 switched the profile to use APIv4 to fetch email id for constructing an email link. The API call looks like this:
```php
$emailID = Email::get()->setOrderBy(['is_primary' => 'DESC'])->setWhere([['contact_id', '=', $this->_id], ['email', '=', $email], ['on_hold', '=', FALSE], ['contact_id.is_deceased', '=', FALSE], ['contact_id.is_deleted', '=', FALSE], ['contact_id.do_not_email', '=', FALSE]])->execute()->first()['id'];
```
It was reported on SE that this fails for users without "view deleted contacts", however I'm unable to reproduce.
See https://civicrm.stackexchange.com/questions/45313/invalid-field-contact-id-is-deceased-apiv4
This should have already been double-fixed by:
- [Revert "Add permission metadata to contact is_deleted field" #22203](https://github.com/civicrm/civicrm-core/pull/22203)
- [APIv4 - Silently ignore non-permissioned fields instead of throwing exceptions #20724](https://github.com/civicrm/civicrm-core/pull/20724)