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

APIv4 - Add SortableEntity type which auto-adjusts weights #22137

Merged
merged 6 commits into from Nov 29, 2021

Conversation

colemanw
Copy link
Member

Overview

Gives APIv4 the ability to manage the "weight" of certain entities.

Before

  • Saving a new record in APIv4 without specifying a weight had undefined behavior
  • Trying to re-order a list was difficult - all items had to be manually re-adjusted

After

  • APIv4 will supply an auto-increment default value for weights
  • Simply by updating the weight of one record, others will auto-adjust to make room for it.

Technical Details

This creates a trait for a new type: "SortableEntity", as well as a new @orderBy annotation which specifies the name of the column containing sorting data.

@civibot
Copy link

civibot bot commented Nov 26, 2021

(Standard links)

$existing = self::query('SELECT', $daoName, $fieldValues, "id", "$weightField = $newWeight");
// Nothing to do if no existing record has this weight
if (empty($existing->N)) {
return $newWeight;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not 100% sure about this because there's a couple places where the comments indicate it's supposed to create a gap for the new row, and there are several calls to this function. But logically the gap would already be there if it doesn't exist. I tried clicking around a couple places and it seems ok.

I'm not sure how to evaluate the api/search kit changes since I'm not sure where they're used. So have given merge-ready.

Copy link
Member Author

Choose a reason for hiding this comment

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

@demeritcowboy I think it was an oversight. Prior to this PR there were no unit tests for CRM_Utils_Weight.

@demeritcowboy demeritcowboy added the merge ready PR will be merged after a few days if there are no objections label Nov 27, 2021
@colemanw
Copy link
Member Author

@demeritcowboy thanks for the review. I've just rebased this against master and added a few more unit tests + fixes to make sure SortableEntity and ManagedEntity traits are working well together in an export.

@demeritcowboy
Copy link
Contributor

Ha ha sneaky - a lot more changes now. Ok will take a look.

@colemanw
Copy link
Member Author

Yea, I keep adding unit tests and it surfaces subtle bugs. It all came together in the Navigation entity which is sortable, managed, and domain-specific. So I needed to make the Export action filter by domain and order by weight.

This entity type will manage weight columns automatically, allowing items to be
re-ordered easily.
Simply by updating the weight of one record, others will auto-adjust to make room for it.
…u entity

Excludes 'weight' from managed entity calculations for references,
adds unit tests for the interaction of managed entities and sortable entities
@demeritcowboy
Copy link
Contributor

I clicked around a bit and I think this is ok, just there's a lot going on in the api4 side that I don't have a good sense of what it affects, so wouldn't mind someone just doing a quick once-over.

I notice searchkit for option values where you add a where for option_group_id returns nothing, but it's not from this PR.

*/
public static function enableAllComponents() {
$allComponents = array_keys(CRM_Core_Component::getComponents());
if (Civi::settings()->get('enable_components') != $allComponents) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we use !== here

Copy link
Member Author

Choose a reason for hiding this comment

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

image

Here we are checking that both arrays contain the same elements, but they don't have to be in the same order.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, interesting:

php -r '$a = array(1,2); $b = array(2,1); var_dump($a == $b); var_dump($a === $b);'
bool(false)
bool(false)

(php 7.4 at least)

Copy link
Member Author

Choose a reason for hiding this comment

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

I recall stepping through this in the debugger and confirming that the condition is true the first pass but false subsequent test iterations, but wasn't looking too closely.

@@ -21,13 +21,23 @@ class CRM_Core_OptionGroup {
/**
* $_domainIDGroups array maintains the list of option groups for whom
* domainID is to be considered.
*
* FIXME: Hardcoded list = bad. It would be better to make this a column in the civicrm_option_group table
Copy link
Contributor

Choose a reason for hiding this comment

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

I've always wondered about declaring our option groups in files (like with settings). It would take some work to do but I think it would be easier to maintain than the current way we manage the installation & could be hookable etc

@eileenmcnaughton
Copy link
Contributor

Ouch - yeah - it made my head hurt a bit too - but I didn't spot anything of concern

@eileenmcnaughton eileenmcnaughton merged commit da410c8 into civicrm:master Nov 29, 2021
@eileenmcnaughton eileenmcnaughton deleted the api4SortableEntity branch November 29, 2021 21:46
@colemanw
Copy link
Member Author

Thanks @eileenmcnaughton and @demeritcowboy!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has-test master merge ready PR will be merged after a few days if there are no objections
Projects
None yet
3 participants