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

[REF] Improve APIv4 save functions #22403

Merged
merged 1 commit into from
Jan 13, 2022

Conversation

colemanw
Copy link
Member

@colemanw colemanw commented Jan 7, 2022

Overview

Refactors APIv4 create/update functions to make the code more flexible & maintainable.

Before

Dealing with oddball BAOs meant a bunch of hardcoded exceptions written into the APIv4 writeObjects function.

After

APIv4 writeObjects function refactored into smaller pieces.
Oddball handling moved into specific APIs.
Use @deprecated annotations in the BAO to decide whether to use generic writeRecords function.
Starts to centralize saving custom data rather than make each BAO responsible for it, which should make it easier to opt-in new entities to having custom data.

@civibot
Copy link

civibot bot commented Jan 7, 2022

(Standard links)

@civibot civibot bot added the master label Jan 7, 2022
@colemanw colemanw force-pushed the api4WriteRecords branch 2 times, most recently from 2065f6d to 6c41af3 Compare January 7, 2022 18:27
@@ -65,11 +65,6 @@ public static function create(&$params) {
}
}

//store custom data
Copy link
Contributor

Choose a reason for hiding this comment

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

I'ved checked this one & confirm it

@@ -74,9 +74,6 @@ public static function create(&$params) {

$dao = self::writeRecord($params);

if (!empty($params['custom']) && is_array($params['custom'])) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'ved checked this one & confirm it

* @param array $params
* @param int $id
*
* @return array
*/
public static function edit(&$params, &$id) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don' t think this function is ever called - we should go that step further & add a deprecation notice

We could go that step further & add a deprecation notice to the v3 function if it were to call something else itself - I think we could add in something like _civicrm_api3_basic_create that would call apiv4 & return those results & start deprecating create functions where we can really migrate off them

Copy link
Member Author

Choose a reason for hiding this comment

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

That's a longer-term goal I think.

@eileenmcnaughton
Copy link
Contributor

@colemanw the last commit will mean that apiv3 updates custom twice in some cases - ie if it calls writeRecord on them & they are not one of the specified entities

Would this last commit pass on it's own? Can it be it's own PR?

civicrm-core/api/v3/utils.php

Lines 1340 to 1344 in 2d35bc7

// If we have custom fields the BAO may have taken care of it or we may have to.
// $extendsMap provides a pretty good hard-coded list of BAOs that take care of the custom data.
if (isset($params['custom']) && empty(CRM_Core_BAO_CustomQuery::$extendsMap[$entity])) {
CRM_Core_BAO_CustomValueTable::store($params['custom'], CRM_Core_DAO_AllCoreTables::getTableForClass(CRM_Core_DAO_AllCoreTables::getFullName($entity)), $bao->id);
}

@colemanw
Copy link
Member Author

colemanw commented Jan 8, 2022

@eileenmcnaughton of the 6 commits in this PR, the first 3 have been broken out & merged. I've broken the last one out to #22426 and included an APIv3 update in that PR. I've rebased this PR with the 2 remaining commits.

@eileenmcnaughton
Copy link
Contributor

@colemanw I actually pulled out the group contact stuff to this PR #22419 - however I hit something that has me scratching my head. I created the SubscriptionHistory api for the test so I decided I should use that instead of the BAO method in the post hook - but when I do it runs and works but doesn't commit to the db - this feels like something I've seen before in extensions implementing post hooks so now we have a test scenario it's failing in it feels worth figuring our rather than bypassing it

(I think the general idea is that all crud should be by the v4 API - although classes do weird things like call add from create & such like)

@@ -47,14 +47,16 @@ trait AddressSaveTrait {
/**
* @inheritDoc
*/
protected function writeObjects(&$items) {
foreach ($items as &$item) {
protected function writeToDao(array $items) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd like to bike shed this function name a little - I found it really confusing and we are not actually writing to the dao as it implies. We are 'saving' or perhaps 'writeToDatabase'

If 'save' is contaminated? maybe 'saveRecords' ?

Copy link
Member Author

@colemanw colemanw Jan 9, 2022

Choose a reason for hiding this comment

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

Ok. Just to frame the issue, what's going on in this PR is that one function is getting split into two smaller functions. The function is writeObjects() which previously would:

  1. format the params
  2. call the appropriate BAO create/add/writeRecords function
  3. Reformat and return the results

Now it does 1 and 3, with 2 being split off to this new sub-function. For compatibility reasons I don't think the outer writeObjects function should be renamed. So we need to pick a name for the inner sub-function. Something to indicate that it's called from writeObjects and is the piece that takes care of the actual writing (or rather, handing off to the BAO to do the writing). So I named it writeToDao.

Copy link
Contributor

Choose a reason for hiding this comment

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

@colemanw what about writeToDatabase - alternativelyperhap writeUsingDAO - except it would really be writeUsingBAOExceptIfThereIsn'tOne

Or even just ... write

The writeToDAO just doesn't seem to be what is actually being done - it's not being written to the DAO - and in some fantasy future world we could replace the DAO layer altogether.....

Copy link
Member Author

Choose a reason for hiding this comment

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

Yea, write sounds good.

@colemanw colemanw force-pushed the api4WriteRecords branch 2 times, most recently from b7c326a to 49054d6 Compare January 10, 2022 21:10
…ions

Instead of using a hardcoded list of BAO functions to call, with extra
hardcoded params to e.g. the Contact & Address BAOs, this switches
to picking the BAO's create/add only if it's not `@deprecated`,
and falling back to WriteRecords.

Also refactors the large `writeObjects` function into two smaller
functions so individual action classes can more easily override them.
@colemanw
Copy link
Member Author

@eileenmcnaughton ok this PR is now down to just one commit since you pulled the other one out into #22419 and I've renamed the function writeBikeToShed()

@eileenmcnaughton
Copy link
Contributor

lol - looks OK to me - I'll go through a bit more carefully soon

@eileenmcnaughton
Copy link
Contributor

OK I took another look & this still looks OK (with the group contact one still needing resolution) - test cover is good. Merging

@eileenmcnaughton eileenmcnaughton merged commit 4526b69 into civicrm:master Jan 13, 2022
@eileenmcnaughton eileenmcnaughton deleted the api4WriteRecords branch January 13, 2022 00:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants