-
-
Notifications
You must be signed in to change notification settings - Fork 825
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
Afform - Use entity-specific filter key, revert entity_id generic key #32040
Conversation
🤖 Thank you for contributing to CiviCRM! ❤️ We will need to test and review this PR. 👷 Introduction for new contributors...
Quick links for reviewers...
|
e86e458
to
14d826a
Compare
I am not sure about 1.
So those placements are context specific. But the point of this change is to make the afform generation generalisable so we can extend it to ContributionPage and Campaign and Group and... [MyCustomEntity] At the moment when there are 3 of them it's easy to hard code each one, but it gets harder. I see the tension with what to do in multi-entity contexts. My first thought was: that is the exceptional case, so handle it differently there? Havent looked at the code closely but is that not possible without reverting the other cases? (My first first thought was: isn't |
Further thought: for multi-entity contexts in general, the To me that adds support to: use the scheme that works for all single-entity contexts as the general rule, and then handle multi-entity contexts on a case by case basis. Or if you want a scheme that will work anywhere then |
A reason to prefer the hand-tailored for multi-entity contexts is you can provide a bit more clarity. For a single-entity form it's usually pretty clear. ContactMembershipsTab => entity_id is going to want contact id But in the CaseSummaryForm it could be good to have And in RelationshipDetailsForm you prob want |
@ufundo I get that this undoes some of our hard work and that's annoying, but hear me out. Every placement is different, with different contextual variables available. FormBuilder needs a way to know what they are. If every placement had only one entity id in scope, then I'd agree all we need to know is what type of entity it is (e.g. a custom field block for Events just needs one word of metadata: "Event" and then FormBuilder knows that If we merge this PR I think I can build something quite cool on top of it which opens up FormBuilder for more placement options. As you say, there are quite a few more possibilities and yes certainly some of them can just name their key --- a/ext/afform/core/managed/AfformPlacement.mgd.php
+++ b/ext/afform/core/managed/AfformPlacement.mgd.php
@@ -61,6 +61,7 @@ return [
'value' => 'contact_summary_tab',
'label' => E::ts('Contact Summary Tab'),
'icon' => 'fa-address-card-o',
+ 'grouping' => json_encode(['contact_id' => 'Contact']),
'description' => E::ts('Add tab to contact summary page.'),
],
'match' => ['option_group_id', 'name'], And here's what our new placements for Event Summary and Case Summary can look like (mgd entity arrays abbreviated, pseudocode): [
'name' => 'AfformPlacement:event_manage_tab',
'params' => [
'values' => [
'value' => 'event_manage_tab',
'label' => E::ts('Manage Event Tab'),
'grouping' => json_encode(['event_id' => 'Event']),
'description' => E::ts('Add as tab on the manage event .'),
],
],
],
[
'name' => 'AfformPlacement:case_summary_block',
'params' => [
'values' => [
'value' => 'case_summary_block',
'label' => E::ts('Case Summary Block'),
'grouping' => json_encode(['contact_id' => 'Contact', 'case_id' => 'Case']),
'description' => E::ts('Add to case summary screen.'),
],
],
], |
@ufundo the other reason to use non-generic keys is so they are compatible with (and don't conflict with) each other. Consider that a single afform can have multiple placements (it's a mulltiselect). With the above proposal, FormBuilder will have the metadata it needs to tell which placements are compatible with each other, e.g. if will see that the Contact Summary Tab has OTOH if both the Contact Summary Tab and the Manage Event Tab declare |
case 'civicrm/event/manage': | ||
$entities = ['Event']; | ||
\CRM_Core_Smarty::singleton()->assign('afformOptions', [ | ||
'entity_id' => $context['event_id'] ?? NULL, | ||
'event_id' => $context['event_id'] ?? NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hear you on the multiple entities case and I think the overall placement thing looks great.
So making those compatible does sound like a good goal... But in that case I would lean towards deriving the key directly from the Entity Type. I.e. the placement meta could just be In general for forms to be reusable, they need to be able to know what the key is going to be. The case in point at the moment is with these custom field forms: https://github.com/civicrm/civicrm-core/pull/32040/files#r1952210793 - it would be nice if rather than an ever-increasing case statement, we could do The scheme seems trivial at the moment but if we do want to extend to forms with multiple contacts then it's not clear how it goes. I suppose for backward compatibility (and the rarity of repeated entities) it could be like (Slight sidepoint - it feels to me like the placement thing is going to grow out of |
elseif (CoreUtil::isContact($item['extends'])) { | ||
$entityIdFilter = 'contact_id'; | ||
$afform['placement'] = ['contact_summary_tab']; | ||
$afform['summary_contact_type'] = [$item['extends']]; | ||
} | ||
else { | ||
$entityIdFilter = \CRM_Utils_String::convertStringToSnakeCase($item['extends']) . '_id'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ufundo I think we're on the same wavelength, I already started using such a function here. And the other spot you mentioned could be switched to use it as well. I was actually planning to roll civicrm_admin_ui_civicrm_tabset
back into afform.php
and have afform provide both the contact & the event tab placement & then use this function to derive the key.
So then, I agree the explicit naming of the key gets redundant, and really only serves a purpose in the case of multi-entity contexts that have more than one of the same type of entity. Does such a scenario even exist? I can't think of one (relationships... maybe? But there isn't really a relationship screen which would merit an afform placement, and anyway it could be derived from the relationship id)... so no, I think we're good with the simpler grouping that looks like "Contact", or "Contact,Case", which is good since the optionValue "grouping" column doesn't have a pretty way to serialize/unserialize json.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice yeh I think that sounds good!
As you say the placements with repeated entities are going to be rare so I think they can get special treatment. Though if the grouping is an array of values Contact, Event,...
etc I guess that could have repeated values at a push.
if ($item['extends'] === 'Contact') { | ||
$entityIdFilter = 'contact_id'; | ||
$afform['placement'] = ['contact_summary_tab']; | ||
} | ||
elseif (CoreUtil::isContact($item['extends'])) { | ||
$entityIdFilter = 'contact_id'; | ||
$afform['placement'] = ['contact_summary_tab']; | ||
$afform['summary_contact_type'] = [$item['extends']]; | ||
} | ||
else { | ||
$entityIdFilter = \CRM_Utils_String::convertStringToSnakeCase($item['extends']) . '_id'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if ($item['extends'] === 'Contact') { | |
$entityIdFilter = 'contact_id'; | |
$afform['placement'] = ['contact_summary_tab']; | |
} | |
elseif (CoreUtil::isContact($item['extends'])) { | |
$entityIdFilter = 'contact_id'; | |
$afform['placement'] = ['contact_summary_tab']; | |
$afform['summary_contact_type'] = [$item['extends']]; | |
} | |
else { | |
$entityIdFilter = \CRM_Utils_String::convertStringToSnakeCase($item['extends']) . '_id'; | |
$entityIdFilter = \CRM_Utils_String::convertStringToSnakeCase($item['extends']) . '_id'; | |
if ($item['extends'] === 'Contact') { | |
$afform['placement'] = ['contact_summary_tab']; | |
} | |
elseif (CoreUtil::isContact($item['extends'])) { | |
// override e.g. "individual_id", we want "contact_id" | |
$entityIdFilter = 'contact_id'; | |
$afform['placement'] = ['contact_summary_tab']; | |
$afform['summary_contact_type'] = [$item['extends']]; | |
} | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, makes sense.
…s url This leaves grouping open for other uses, like storing the entityType
14d826a
to
9a38327
Compare
Overview
Reverts 2 bad decisions before they get locked into a release.
Technical Details
Bad decision 1:
Back in #31606 @ufundo tried to move us toward a generic
entity_id
passed into tabs and blocks instead ofcontact_id
, which seemed sensible, so then in #31836 I made the switch in FormBuilder. Fortunately that hasn't made it into the stable release yet, because I've changed my mind. This switches it back.The reason to stick with
contact_id
,event_id
, etc. instead ofentity_id
is that these placements are all context-specific; they don't need to be generalized that much, and it's better that they aren't. This change opens the possibility of multi-entity contexts, like the case summary screen which would have bothcase_id
andcontact_id
passed into the form.Bad decision 2:
In #31838 I utilized the unused field "grouping" in the "afform_placement" OptionValues to indicate whether a placement requires a url. I've changed my mind about that too, because I'd rather use "grouping" to indicate contexts (see above) and it's a bigger field better suited to that. So I've switched this flag over to another unused column "filter" which still works fine.
Comments
This doesn't affect any stable releases & these changes have only been in beta for 5 days, so let's revert them now! If anyone actually downloaded the beta in the past 5 days and created an afform for use on the contact summary tab/block/menu, then they'll just have to manually update their form to fix the filter.