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) Tokens - Populate "Event"/"Participant" without direct access to actionSearchResult #21821

Merged
merged 2 commits into from
Oct 13, 2021

Conversation

totten
Copy link
Member

@totten totten commented Oct 13, 2021

Overview

When sending a scheduled reminder for a civicrm_participant record, it supports tokens for both {participant.*} ($context['participantId']) and {event.*} ($context['eventId']). This creates a special requirement to load the eventId
in addition to the participantId.

This patch changes the way in which eventId is loaded.

Before

In ParticipantToken, the token-evaluation-step for {participant.*} tokens has a side-effect of setting $context['eventId'] based on data from actionSearchResult (although this appears slightly indirect).

After

The action-search returns tokenContext_eventId, which automatically maps to $context['eventId'].

This means that the eventId will be set before evaluation begins.

…o actionSearchResult

Overview
--------

When sending a scheduled remidner for a `civicrm_participant` record, it supports
tokens for both `{participant.*}` (`$context['participantId']`) and `{event.*}`
(`$context['eventId']`). This creates a special requirement to load the `eventId`
in addition to the `participantId`.

This patch changes the way in which `eventId` is loaded.

Before
------

In `ParticipantToken`, the token-evaluation-step for `{participant.*}`
tokens has a side-effect of copying `$context['eventId']` based on reading
`actionSearchResult` (although this appears indirect).

After
-----

The action-search returns `tokenContext_eventId`, which automatically maps
to `$context['eventId']`.

This means that the `eventId` will be set before evaluation begins.
The previous commit passes `eventId` through the front-door of `$context`,
so we shouldn't need as much special effort to bring it in the side-door.
@civibot
Copy link

civibot bot commented Oct 13, 2021

(Standard links)

@totten
Copy link
Member Author

totten commented Oct 13, 2021

The focus here was on scheduled-reminder scenario. I don't know if there is an expectation that the particiapantId should be used to autopopulate eventId in other scenarios, eg whether this is expected to work:

CRM_Core_TokenSmarty::render(
  ['html' => 'Time to go to {event.title}!'],
  ['participantId' => 123]
);

We'll see if Jenkins complains at all...

FWIW, I find the above snippet (using participantId to populate {event.*}) a bit magical. But if it's really needed, then I'd be inclined to split apart (a) the token-evaluator ( ParticipantToken::evaluateToken(...) ) and (b) the implicit relation-loader. So that would be a separate (early-stage) listener, eg pseudocode

// Find $context['participantId'] and auto-fill any missing $context['eventId'].
function fillRelations(TokenValueEvent $e) {
  $isIncomplete = function($row) {
    return !empty($row->context['participantId']) && empty($row->context['eventId']);
  };

  $incompleteParticipants = array_filter($isIncomplete, $e->getRows());

  if (!empty($incompleteParticipants)) {
    $relations = civicrm_api4('Participant', 'get', [
      'where' => [['id', 'IN', $e->getTokenProcessor()->getContextValues('participantId')]]
      'select' => ['id', 'event_id']
      )->execute()->indexBy('id');
    foreach ($e->getRows() as $row) {
      if ($isIncomplete($row)) {
        $row->context['eventId'] = $relations[$row->context['participantId']]['event_id'];
      }
   }
 }
}

It's slightly more verbose, but (a) you don't have to think as hard about the relations among different listeners/functions/overrides, and (b) I think it'd be easier to generalize (ie treating participantId and eventId as parameters/values/metadata - then extend to, say, caseId for Activity or campaignId for many entities, ).

@eileenmcnaughton
Copy link
Contributor

@magnolia61 do you want to test this one before we merge - the question is whether the various paths render event tokens when participant tokens are present and also when there are none presetnt - pdfs & emails would only pass in participant ID

@magnolia61
Copy link
Contributor

Hmm. I applied this patch and see no difference. All event and participant tokens render fine in scheduled reminders with entity event_type. Also templates with only event core tokens (and no participant token) work fine (with and without this patch).

Is there something else specific that I can test to prove this patch enhances something?

@eileenmcnaughton
Copy link
Contributor

@magnolia61 - no breakage is good enough fo this patch - thanks for testing. I'll check the gdpr one again

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.

3 participants