@@ -486,17 +486,18 @@ private static function saveRelationshipByValues(array $relationship, array $ent
486
486
*/
487
487
protected static function saveJoins (AfformSubmitEvent $ event , $ index , $ entityId , $ joins ) {
488
488
$ mainEntity = $ event ->getFormDataModel ()->getEntity ($ event ->getEntityName ());
489
- foreach ($ joins as $ joinEntityName => $ join ) {
490
- $ values = self ::filterEmptyJoins ($ mainEntity , $ joinEntityName , $ join );
489
+ foreach ($ joins as $ joinEntityName => $ joinValues ) {
490
+ $ values = self ::filterEmptyJoins ($ mainEntity , $ joinEntityName , $ joinValues );
491
491
$ whereClause = self ::getJoinWhereClause ($ event ->getFormDataModel (), $ event ->getEntityName (), $ joinEntityName , $ entityId );
492
492
$ mainIdField = CoreUtil::getIdFieldName ($ mainEntity ['type ' ]);
493
493
$ joinIdField = CoreUtil::getIdFieldName ($ joinEntityName );
494
+ $ joinAllowedAction = self ::getJoinAllowedAction ($ mainEntity , $ joinEntityName );
494
495
495
496
// Forward FK e.g. Event.loc_block_id => LocBlock
496
497
$ forwardFkField = self ::getFkField ($ mainEntity ['type ' ], $ joinEntityName );
497
498
if ($ forwardFkField && $ values ) {
498
499
// Add id to values for update op, but only if id is not already on the form
499
- if ($ whereClause && empty ($ mainEntity ['joins ' ][$ joinEntityName ]['fields ' ][$ joinIdField ])) {
500
+ if ($ whereClause && $ joinAllowedAction [ ' update ' ] && empty ($ mainEntity ['joins ' ][$ joinEntityName ]['fields ' ][$ joinIdField ])) {
500
501
$ values [0 ][$ joinIdField ] = $ whereClause [0 ][2 ];
501
502
}
502
503
$ result = civicrm_api4 ($ joinEntityName , 'save ' , [
@@ -514,21 +515,44 @@ protected static function saveJoins(AfformSubmitEvent $event, $index, $entityId,
514
515
}
515
516
516
517
// Reverse FK e.g. Contact <= Email.contact_id
517
- // TODO: REPLACE works for creating or updating contacts, but different logic would be needed if
518
- // the contact was being auto-updated via a dedupe rule; in that case we would not want to
519
- // delete any existing records.
520
518
elseif ($ values ) {
521
- $ result = civicrm_api4 ($ joinEntityName , 'replace ' , [
522
- // Disable permission checks because the main entity has already been vetted
523
- 'checkPermissions ' => FALSE ,
524
- 'where ' => $ whereClause ,
525
- 'records ' => $ values ,
526
- ]);
519
+ // In update mode, set ids of existing values
520
+ if ($ joinAllowedAction ['update ' ]) {
521
+ $ existingJoinValues = $ event ->getApiRequest ()->loadJoins ($ joinEntityName , $ mainEntity , $ entityId , $ index );
522
+ foreach ($ existingJoinValues as $ joinIndex => $ existingJoin ) {
523
+ if (!empty ($ existingJoin [$ joinIdField ]) && !empty ($ values [$ joinIndex ])) {
524
+ $ values [$ joinIndex ][$ joinIdField ] = $ existingJoin [$ joinIdField ];
525
+ }
526
+ }
527
+ }
528
+ else {
529
+ foreach ($ values as $ key => $ value ) {
530
+ unset($ values [$ key ][$ joinIdField ]);
531
+ }
532
+ }
533
+ // Use REPLACE action if update+delete are both allowed (only need to check for 'delete' as it implies 'update')
534
+ if ($ joinAllowedAction ['delete ' ]) {
535
+ $ result = civicrm_api4 ($ joinEntityName , 'replace ' , [
536
+ // Disable permission checks because the main entity has already been vetted
537
+ 'checkPermissions ' => FALSE ,
538
+ 'where ' => $ whereClause ,
539
+ 'records ' => $ values ,
540
+ ]);
541
+ }
542
+ else {
543
+ $ fkField = self ::getFkField ($ joinEntityName , $ mainEntity ['type ' ]);
544
+ $ result = civicrm_api4 ($ joinEntityName , 'save ' , [
545
+ // Disable permission checks because the main entity has already been vetted
546
+ 'checkPermissions ' => FALSE ,
547
+ 'defaults ' => [$ fkField ['name ' ] => $ entityId ],
548
+ 'records ' => $ values ,
549
+ ]);
550
+ }
527
551
$ indexedResult = array_combine (array_keys ($ values ), (array ) $ result );
528
552
$ event ->setJoinIds ($ index , $ joinEntityName , $ indexedResult );
529
553
}
530
554
// REPLACE doesn't work if there are no records, have to use DELETE
531
- else {
555
+ elseif ( $ joinAllowedAction [ ' delete ' ]) {
532
556
try {
533
557
civicrm_api4 ($ joinEntityName , 'delete ' , [
534
558
// Disable permission checks because the main entity has already been vetted
0 commit comments