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

Convert token processing to use token processor #19550

Merged
merged 1 commit into from
Apr 6, 2021

Conversation

eileenmcnaughton
Copy link
Contributor

@eileenmcnaughton eileenmcnaughton commented Feb 6, 2021

Overview

Convert token processing to use token processor

This is intended to be a no-change patch to simply use newer/ more preferred coding conventions - however, it does throw up a small handful is discrepancies between them that need to be considered.

Before

Use of functions like

CRM_Utils_Token::replaceDomainTokens

After

Use of token processor - this in turn calls the tokenCompat subscriber which has functionality to replace the domain & contact tokens & do the smary parsing.

However, it does turn out that there are some minor differences between the 2 approaches & we need to agree what to do about them. The 'expected' on the left is with the existing code & on the right with this change.

image

image

image

Technical Details

The test is in this PR (currently) but is also in a separate PR #19551 - which I recommend merging asap - at which point I'll rebase out of this

I think it would be OK to stop supporting or to deprectate some of these tokens as I believe they were added more or less accidentally - we would need to do some messaging. The contact reference custom field is probably the biggest deal IMHO

Comments

@civibot
Copy link

civibot bot commented Feb 6, 2021

(Standard links)

@mattwire
Copy link
Contributor

mattwire commented Feb 6, 2021

In the future we will probably want to change the $contactID param that is being passed to renderMessageTemplate() to be an array of entity IDs. TokenProcessor can then be passed those params and we have support for rendering tokens from any entity supported by tokenprocessor.

@eileenmcnaughton
Copy link
Contributor Author

Yep potentially we will extend this function like that - we'll need to be sure we are adding test cover when we extend to other entities.

@eileenmcnaughton
Copy link
Contributor Author

eileenmcnaughton commented Feb 6, 2021

(I think @totten also has some slightly deeper thoughts about tokens to work through before we commit ourselves to extending this function to other entities & migrating entity-based tokens away from smarty & towards the token processor format)

@eileenmcnaughton eileenmcnaughton force-pushed the msg_tpl_convert branch 3 times, most recently from a6aec80 to 2d42c23 Compare February 7, 2021 21:57
@eileenmcnaughton
Copy link
Contributor Author

The remaining test fails are the 'real' difference highlighted above

$tokenProcessor->addMessage('html', $mailContent['html'], 'text/html');
$tokenProcessor->addMessage('text', $mailContent['text'], 'text/plain');
$tokenProcessor->addMessage('subject', $mailContent['subject'], 'text/plain');
$tokenProcessor->addRow($contactID ? ['contactId' => $contactID] : []);
Copy link
Contributor

Choose a reason for hiding this comment

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

@totten @eileenmcnaughton To support rendering other tokens here we just need to pass the ID through here. Eg.

[
  'contactId' => $contactID,
  'contributionId' => $contributionID,
]

Then it would work with this #19584 and contribution tokens would be rendered.
There's a few steps to get there but it's not a long way off - probably review/merge this, review/merge #19550, add testing on contribution tokens like @eileenmcnaughton did with contact tokens, review/merge #16983 + #19071, modify renderMessageTemplate() to accept different entity IDs and get that passed through from eg. contribution invoice workflow template.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mattwire - I would definitely want to include full test cover of the supported contribution tokens with any changes.

Also I'd want to delay exposing the api (incl sendtemplate api) until it's settled

eileenmcnaughton added a commit to eileenmcnaughton/civicrm-core that referenced this pull request Feb 15, 2021
This is a subset of the changes in
civicrm#19550 that we should be able to resolve
& merge while addressing that takes longer. It still gets us the
benefit of adopting a preferred pattern

Note that some test changes exist around handling of subject -
the code now converts a new line to a space consistently. In addition
tests that rely on leakage have been altered as smarty does not leak with
this approach
@eileenmcnaughton
Copy link
Contributor Author

As the challenges of the contact tokens are likely to take some time I've pulled out the changes that cover the domain tokens and smarty processing - which is the bulk of the code

#19598

@nganivet
Copy link
Contributor

@eileenmcnaughton Thanks for your work on this. You should probably include the greetings text in your test (rather than just greeting_id). Also, the custom fields value vs label seems pretty significant, if not a show stopper.

@eileenmcnaughton
Copy link
Contributor Author

@nganivet the tested fields are what is currently there without this change. But yeah - not sure what to do about the custom field one

@nganivet
Copy link
Contributor

@eileenmcnaughton it is very common to have custom fields as part of email templates, so I would propose blocker. Come to think about it, the preferred communication method, contact source and created date might be important for GDPR or similar, but probably to a lesser extend (unless EU chimes in ...)

@eileenmcnaughton
Copy link
Contributor Author

@nganivet note it's not 'custom fields' that have a problem - the issue is specific to what is rendered for entity reference custom fields - id vs name

@nganivet
Copy link
Contributor

@eileenmcnaughton makes sense ...

@eileenmcnaughton
Copy link
Contributor Author

@nganivet to be clear - the reason it's tricky is that I think the scheduled reminders flow is rendering the tokens like the images on the right and the send receipt flow like the left. So the issue is that they should do the same thing but it's hard to know what that should be in the case of the entity reference custom field (& to a lesser extent fields like 'hash' that I feel shouldn't be exposed & postal-greeting_id which is exposing something that seems like it would cause bugs)

@nganivet
Copy link
Contributor

@eileenmcnaughton Understood, and yes, confusing! Since the text substituted for the token is meant to be printed in an email, I suppose it would make a lot more sense to substitute the name/label rather than the id for all entities. The hash might need to be exposed as part of links to profiles. The greeting ids are an internal construct that should not be exposed, but the greeting displays most probably should.

@eileenmcnaughton
Copy link
Contributor Author

@nganivet looking at the above screenshots the greeting displays seem to work before AND after

How would you use a hash in a link to a profile? It's used to generate the checksum but ideally would never be exposed directly

@nganivet
Copy link
Contributor

@eileenmcnaughton correct, so we can the greeting ids, and s/hash/checksum/g

@eileenmcnaughton
Copy link
Contributor Author

@nganivet what does s/hash/checksum/g mean?

@nganivet
Copy link
Contributor

vi speak: substitute hash with checksum in my previous response.

@eileenmcnaughton
Copy link
Contributor Author

OK - checksum is unchanged in both the images above (near the bottom of the last one)

@eileenmcnaughton
Copy link
Contributor Author

I've rebased this after getting the other merged - so now it's time to think about resolving the tokens here.

I think there are 3 things we need to reconcile

  1. list of tokens present through the UI
  2. tokens resolved through 'traditional' method. These are on the left in the images above. They are resolved in message template processing (including UI messages AFAIK)
  3. tokens resolved through the token Compat - AKAIK they are resolved in scheduled reminders but I believe some extensions also resolve them & we would want to list the most common ones in any upgrade message (since I think we will need an upgrade message to deal with the entity reference one

The first token that needs resolving is hash & there are 2 options

  1. make it work for token compat subscriber or
  2. remove from tokens list/traditional method
  • I lean to the latter for hash & for - which feel like they should not be exposed / are not helpful / are possibly security insecure
    image

@nganivet
Copy link
Contributor

+1 on removing hash and all greeting id tokens.

@magnolia61
Copy link
Contributor

I believe this change makes the result less-confusing. So also a +1 from me.

@tschuettler
Copy link
Contributor

We are currently using {contact.hash} in some of our workflows:
Our site is offline and can't be access from remote. We use the hash as part of a link parameter to fill a hidden form field to make sure we can reliably identify which contact has submitted a form on a public webserver. When importing the data back, we use the hash from the DB and compare it to the submitted value to check if there was a match so that we can modify a contact in our offline CiviCRM.
We don't want to use the contact id itself, because you can easily guess and change that.

I’m aware that this workflow has security issues if we were to expose forms to the public from our CiviCRM instance.

I guess we could create some custom field that creates a constant hash or UUID for a contact or set the checksum duration to 0. But each would come with its own set of drawbacks and we need to change our synchronization of that data to an external mail service, which would be somewhat troublesome at least for the checksum. Lowest effort change would probably be to just recreate that token as a custom token.

CiviMRF is using the {contact.hash} token aswell: https://github.com/CiviMRF/cmrf_core/blob/7.x-dev/cmrf_webform/cmrf_webform.module#L717

eileenmcnaughton added a commit to eileenmcnaughton/civicrm-core that referenced this pull request Mar 11, 2021
…tokens

Per discussion on civicrm#19550 (comment)
there appears to be agreement that supporting tokens like
addressee_id (which resolves to '{contact.individual_prefix}{ }.....')
should not be exposed / supported as they seem both unuseful and likely
to be breaky.

These were exposed unintentionally as part of a change to make them
available as WHERE filters on apiv3
civicrm@54e389a

The discussion suggests that by contrast we should
add support to hash in the token compat subscriber
@eileenmcnaughton
Copy link
Contributor Author

I added #19782 to remove the 3 fields that were agreed above should not be exposed ie email_greeting_id, addressee_id, postal_greeting_id

The other field discrepancies need to be fixed in via the tokenCompat class - with the exception of the contact reference field which we still don't know how to deal with

eileenmcnaughton added a commit to eileenmcnaughton/civicrm-core that referenced this pull request Mar 11, 2021
…tokens

Per discussion on civicrm#19550 (comment)
there appears to be agreement that supporting tokens like
addressee_id (which resolves to '{contact.individual_prefix}{ }.....')
should not be exposed / supported as they seem both unuseful and likely
to be breaky.

These were exposed unintentionally as part of a change to make them
available as WHERE filters on apiv3
civicrm@54e389a

The discussion suggests that by contrast we should
add support to hash in the token compat subscriber
@eileenmcnaughton
Copy link
Contributor Author

test this please

@eileenmcnaughton
Copy link
Contributor Author

I've added other custom field types to the test so checking that the contact reference is the only one

@magnolia61
Copy link
Contributor

Nice to see progress on the tokenprocessor. I really hope this will result in more entities. Mostly custom participant tokens which have never worked to far. Thank you all for your efforts in this area!

In the future we will probably want to change the $contactID param that is being passed to renderMessageTemplate() to be an array of entity IDs. TokenProcessor can then be passed those params and we have support for rendering tokens from any entity supported by tokenprocessor.

@eileenmcnaughton
Copy link
Contributor Author

Yep - I don't want to expose more functionality until we have the inner workings solid now either through the UI or to extensions. I've been burnt before

@magnolia61
Copy link
Contributor

I know you are always going for quality of core, the long term view and solid testing and I think you should be in the dev list spotlight yourself for what you bring to civi with those high standards. You lift everyone up to them. Very inspiring!

@eileenmcnaughton
Copy link
Contributor Author

thanks for your kind words @magnolia61

@eileenmcnaughton
Copy link
Contributor Author

This is to update the tokenprocessor to render display values for custom fields #19806

Note this will test fail on 3 things that worked with the other. The way in
which we load tokens means that some values have been exposed that
possibly would be better not exposed - but we can either remove them
from advertised tokens, fix the tokenCompat class to support them
or possibly deprecate by removing from the UI display but
continuing to handle. One notable difference is the contact_reference
entity id.
@eileenmcnaughton
Copy link
Contributor Author

@totten - we can finally merge this!!!

@eileenmcnaughton
Copy link
Contributor Author

eileenmcnaughton commented Mar 28, 2021

@totten @mattwire if we merge this in time I might have a go at altering the tokenCompatSubscriber to use apiv4 - it feels like we are feeling confident in the test cover now but might forget that we checked it out later & also people will be expecting a change this release. Big picture we want to reduce BAO_Query object usage & use something more consistent where we can

(by in time I mean in time for me to do it before the rc is cut)

@eileenmcnaughton
Copy link
Contributor Author

@seamuslee001 @mattwire @totten can we get this merged since we merged all the related PRs that led up to it & got it to a test-passing-state?

@colemanw colemanw merged commit f9c1000 into civicrm:master Apr 6, 2021
@colemanw colemanw deleted the msg_tpl_convert branch April 6, 2021 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants