Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch addActivity to use API4 #17274

Closed
wants to merge 3 commits into from

Conversation

mattwire
Copy link
Contributor

Overview

Debugging various issues with payments keeps leading me back to this addActivity function. In a number of cases source_contact_id is not being set and this triggers the fatal in addActivity which triggers a rollback of the transaction.
What that usually means is that payment was taken but doesn't get recorded in CiviCRM because fatal() rolls back the transaction.

Before

Fatal error causes important information to be lost (such as contribution records) which upsets people because they've actually paid...

After

Switch to calling API4 which throws an exception which can be handled at the form layer, easily debugged and doesn't rollback the transaction.

Technical Details

If the PR involves technical details/changes/considerations which would not be manifest to a casual developer skimming the above sections, please describe the details here.

Comments

Adding activities is important but not as important as the actual contribution/membership/participant data..

@eileenmcnaughton @artfulrobot I come across a lot of sites where for some users (normally anonymous - ie. creating a contact) the site crashes on the thankyou page and then information is not recorded properly in CiviCRM. This fatal is the cause of a lot of those problems.

@civibot
Copy link

civibot bot commented May 10, 2020

(Standard links)

@civibot civibot bot added the master label May 10, 2020
@eileenmcnaughton
Copy link
Contributor

@mattwire I definitely agree in principle - a bit of a war with jenkins to be fought to get the tests to pass. Superficially it seems maybe the api is not setting all the required defaults but I didn't dig

@@ -1737,10 +1735,14 @@ public static function addActivity(
'is_test' => $activity->is_test,
'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_status_id', 'Completed'),
Copy link
Contributor

@eileenmcnaughton eileenmcnaughton May 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note APIv4 pseudoconstant syntax is 'status_id:name' => 'Completed'

* @return bool|NULL
* @throws \API_Exception
* @throws \CiviCRM_API3_Exception
* @throws \Civi\API\Exception\UnauthorizedException
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still true if we add setcheckpermissions(FALSE) as suggested.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well phpstorm gets upset if you don't have that there....

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant, won't it always return NULL, and never a bool? Surely your proprietary corporate overlordshelpful developer assistant can allow you to have a function that does not return a value? ;-)

@@ -1684,7 +1684,9 @@ public static function getContactActivity($contactId) {
* @param array $params
* Activity params to override.
*
* @return bool|NULL
* @throws \API_Exception
* @throws \CiviCRM_API3_Exception
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't see where it calls api3 any more?

@@ -1684,7 +1684,9 @@ public static function getContactActivity($contactId) {
* @param array $params
* Activity params to override.
*
* @return bool|NULL
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just on this cleanup: It seems weird to me that a create function doesn't at least return the ID of the thing it created. I know the original function doesn't, so maybe we should have a @todo comment in here?

@artfulrobot
Copy link
Contributor

artfulrobot commented May 11, 2020

This looks sensible to me, though I still struggle getting my head around the function and role of API4 because I tend to think of it as

High level » API4 » BAO » DAO » Low level

So seeing code that jumps to the lower level BAO then to jump back to API4 seems jarring. I guess it's historical and that code that calls this function should not be doing so and should be calling API4 directly? If this is correct we should put a note to this effect in the docblock.

a war with jenkins to be fought to get the tests to pass.

Why is that?

@mattwire mattwire force-pushed the addactivitytoapi4 branch from 8334029 to 97084be Compare May 18, 2020 09:26
@eileenmcnaughton
Copy link
Contributor

I think this one might be a clue to the failing tests

https://test.civicrm.org/job/CiviCRM-Core-PR/34077/testReport/junit/(root)/CRM_Contribute_Form_ContributionTest/testPartialPaymentWithCreditCard/

"Cannot pass id to Create action. Use Update action instead."

I think using 'Save' is a reasonable workaround - although the syntax is a bit different

@mattwire mattwire force-pushed the addactivitytoapi4 branch from 97084be to a32bea7 Compare May 25, 2020 13:08
@mattwire
Copy link
Contributor Author

@eileenmcnaughton Tests are now passing. I don't know if you can make sense of the changes I had to make to SearchTest? I couldn't work out how this would be related to this change or if it matters.

The other test failures were fixed by switching to Create/Update as appropriate.

Comment on lines +1769 to +1784
// Despite being called "addActivity" this function actually both adds and updates activities
// So we have to select the right Api4 action depending on if we have an activity ID.
if (!empty($activityParams['id'])) {
$activityApi4 = \Civi\Api4\Activity::update();
}
else {
$activityApi4 = \Civi\Api4\Activity::create();
}
$activityApi4
->setValues($activityParams)
->setCheckPermissions(FALSE)
->execute();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be simplified to:

Suggested change
// Despite being called "addActivity" this function actually both adds and updates activities
// So we have to select the right Api4 action depending on if we have an activity ID.
if (!empty($activityParams['id'])) {
$activityApi4 = \Civi\Api4\Activity::update();
}
else {
$activityApi4 = \Civi\Api4\Activity::create();
}
$activityApi4
->setValues($activityParams)
->setCheckPermissions(FALSE)
->execute();
\Civi\Api4\Activity::save()
->addRecord($activityParams)
->setCheckPermissions(FALSE)
->execute();

@@ -49,7 +49,6 @@ public function testSearch() {
'source_record_id' => '1',
'activity_type_id' => '6',
'activity_type' => 'Contribution',
'activity_is_test' => '0',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@colemanw this suggests that passing

      'is_test' => $activity->is_test,

is passing null or something & resulting in the db default not being applied? I can't quite think my way through what's happening here

@eileenmcnaughton
Copy link
Contributor

@mattwire I think the requirement for test changes IS a problem - is_test is winding up empty not 0. I also noticed today that apiv4 activity puts NULL in activity_date_time (https://lab.civicrm.org/dev/core/-/issues/1782)

  • @colemanw might have some thoughts but I think we need to tweak the api not the test.

@mattwire
Copy link
Contributor Author

mattwire commented Jun 1, 2020

See #17450

@mattwire mattwire changed the title Switch addActivity to use API4 (and throw exception instead of fatal so the form can handle the error) Pending #17450 Switch addActivity to use API4 (and throw exception instead of fatal so the form can handle the error) Jun 6, 2020
@mattwire mattwire added the needs-work-not-review-ready Submitter required to take action, will be closed after 1-2 weeks in this state label Jun 6, 2020
@mattwire mattwire force-pushed the addactivitytoapi4 branch from 9eed097 to 35c7c15 Compare June 24, 2020 12:06
@mattwire mattwire changed the title Pending #17450 Switch addActivity to use API4 (and throw exception instead of fatal so the form can handle the error) Switch addActivity to use API4 (and throw exception instead of fatal so the form can handle the error) Jun 24, 2020
@mattwire mattwire changed the title Switch addActivity to use API4 (and throw exception instead of fatal so the form can handle the error) Switch addActivity to use API4 Jun 24, 2020
@mattwire mattwire force-pushed the addactivitytoapi4 branch from 4b3569c to b26da89 Compare June 24, 2020 15:55
eileenmcnaughton added a commit to eileenmcnaughton/civicrm-core that referenced this pull request Jul 18, 2020
…ction

I took a look at civicrm#17274 which has blocking test failures - but felt that
the shared function was adding nothing and simply using the api to create the activity made more sense. The
shared function does a lot of silly wrangling for very little shared functionality and is
hard to read. In this call only 2 params are passed in - so most of the wranglingg
doesn't apply anyway. I ensured the 2 JIRA issues referenced in the removed code have test cover (one already
had a test written by Monish & I added in the campaign check
@eileenmcnaughton
Copy link
Contributor

@mattwire I took a look at this & managed to get past the test fail & to extend the cover a bit - but I felt much happier by-passing this function than altering it
#17881

eileenmcnaughton added a commit to eileenmcnaughton/civicrm-core that referenced this pull request Jul 18, 2020
…ction

I took a look at civicrm#17274 which has blocking test failures - but felt that
the shared function was adding nothing and simply using the api to create the activity made more sense. The
shared function does a lot of silly wrangling for very little shared functionality and is
hard to read. In this call only 2 params are passed in - so most of the wranglingg
doesn't apply anyway. I ensured the 2 JIRA issues referenced in the removed code have test cover (one already
had a test written by Monish & I added in the campaign check
eileenmcnaughton added a commit to eileenmcnaughton/civicrm-core that referenced this pull request Jul 18, 2020
…ction

I took a look at civicrm#17274 which has blocking test failures - but felt that
the shared function was adding nothing and simply using the api to create the activity made more sense. The
shared function does a lot of silly wrangling for very little shared functionality and is
hard to read. In this call only 2 params are passed in - so most of the wranglingg
doesn't apply anyway. I ensured the 2 JIRA issues referenced in the removed code have test cover (one already
had a test written by Monish & I added in the campaign check
eileenmcnaughton added a commit to eileenmcnaughton/civicrm-core that referenced this pull request Jul 18, 2020
…ction

I took a look at civicrm#17274 which has blocking test failures - but felt that
the shared function was adding nothing and simply using the api to create the activity made more sense. The
shared function does a lot of silly wrangling for very little shared functionality and is
hard to read. In this call only 2 params are passed in - so most of the wranglingg
doesn't apply anyway. I ensured the 2 JIRA issues referenced in the removed code have test cover (one already
had a test written by Monish & I added in the campaign check
eileenmcnaughton added a commit to eileenmcnaughton/civicrm-core that referenced this pull request Jul 18, 2020
…ction

I took a look at civicrm#17274 which has blocking test failures - but felt that
the shared function was adding nothing and simply using the api to create the activity made more sense. The
shared function does a lot of silly wrangling for very little shared functionality and is
hard to read. In this call only 2 params are passed in - so most of the wranglingg
doesn't apply anyway. I ensured the 2 JIRA issues referenced in the removed code have test cover (one already
had a test written by Monish & I added in the campaign check
eileenmcnaughton added a commit to eileenmcnaughton/civicrm-core that referenced this pull request Jul 18, 2020
…ction

I took a look at civicrm#17274 which has blocking test failures - but felt that
the shared function was adding nothing and simply using the api to create the activity made more sense. The
shared function does a lot of silly wrangling for very little shared functionality and is
hard to read. In this call only 2 params are passed in - so most of the wranglingg
doesn't apply anyway. I ensured the 2 JIRA issues referenced in the removed code have test cover (one already
had a test written by Monish & I added in the campaign check
@mattwire
Copy link
Contributor Author

Closing in favour of #17881

@mattwire mattwire closed this Jul 18, 2020
eileenmcnaughton added a commit to eileenmcnaughton/civicrm-core that referenced this pull request Jul 19, 2020
…ction

I took a look at civicrm#17274 which has blocking test failures - but felt that
the shared function was adding nothing and simply using the api to create the activity made more sense. The
shared function does a lot of silly wrangling for very little shared functionality and is
hard to read. In this call only 2 params are passed in - so most of the wranglingg
doesn't apply anyway. I ensured the 2 JIRA issues referenced in the removed code have test cover (one already
had a test written by Monish & I added in the campaign check
eileenmcnaughton added a commit to eileenmcnaughton/civicrm-core that referenced this pull request Jul 20, 2020
…ction

I took a look at civicrm#17274 which has blocking test failures - but felt that
the shared function was adding nothing and simply using the api to create the activity made more sense. The
shared function does a lot of silly wrangling for very little shared functionality and is
hard to read. In this call only 2 params are passed in - so most of the wranglingg
doesn't apply anyway. I ensured the 2 JIRA issues referenced in the removed code have test cover (one already
had a test written by Monish & I added in the campaign check
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
master needs-work-not-review-ready Submitter required to take action, will be closed after 1-2 weeks in this state
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants