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

CRM-19690 - CRM_Mailing_Tokens - Add TokenProcessor support #9563

Merged
merged 5 commits into from
Dec 23, 2016

Conversation

totten
Copy link
Member

@totten totten commented Dec 20, 2016

This includes support for both {mailing.*} and {action.*} tokens used
in CiviMail -- and includes a performance optimization to ignore unused
tokens in AbstractTokenSubscriber.

Notably, this provides support for CiviMail tokens in TokenProcessor...
but the CiviMail engine will not use TokenProcessor. Rather, this helps
other/future delivery-engines (such as the upcoming FlexMailer) get access to
the CiviMail tokens. The existing CiviMail engine should remain unchanged.


This includes support for both `{mailing.*}` and `{action.*}` tokens used in
CiviMail.
This is more significant with mailing tokens because some of them are fairly
sizeable/expensive.
@totten
Copy link
Member Author

totten commented Dec 20, 2016

Aside: The TokenProcessor was introduced recently (4.7.alpha's; as a way to make ScheduledReminders more hookable), so it may be a bit new/unfamiliar for most folks. There's some background at https://wiki.civicrm.org/confluence/display/CRMDOC/Token+Reference

Copy link
Member

@omarabuhussein omarabuhussein left a comment

Choose a reason for hiding this comment

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

just a view notes

}

/**
* Check something about being active.
Copy link
Member

Choose a reason for hiding this comment

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

same here .. you can just use @inheritdoc for this and other methods in this class

}

/**
* Evaluate the content of a single token.
Copy link
Member

Choose a reason for hiding this comment

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

you can just use @inheritdoc 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.

Hmm, well, I have pretty mixed feelings about this, e.g.

Do you see a concrete upside in resolving this? What is it?

Copy link
Member

Choose a reason for hiding this comment

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

actually phpstorm do something about @inheritdoc ,, try to point to the method and press ctrl+Q or view >> quick documentation . So I think adding it is better than omitting it as in the last option you provided above.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, nice. (For OSX, I had to use Ctlr-J or F1.) It seems to inherit docs correctly with each of these variations: {@inheritDoc}, @inheritDoc, and non-existent docblock. (Although with extended docs, {@inheritDoc} doesn't seem to interpolate docs in the expected way.) I'll change it to match the de facto convention from other Civi classes (@inheritDoc)

class CRM_Mailing_ActionTokens extends \Civi\Token\AbstractTokenSubscriber {

/**
* Class constructor.
Copy link
Member

Choose a reason for hiding this comment

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

I think this (Class constructor ) is uneeded .. same in CRM_Mailing_Tokens class

Copy link
Member Author

Choose a reason for hiding this comment

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

We need it to declare the list of tokens ($this->tokenNames) which is used in a couple ways:

  • Optimizing the list of token to process (eg $activeTokens = array_intersect($messageTokens[$this->entity], array_keys($this->tokenNames));)
  • Providing metadata about the list of available tokens.

Copy link
Member

Choose a reason for hiding this comment

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

sorry ... I meant the docblock .. not the constructor itself ..

$field, $verp, $urls, TRUE));
}

protected function getTrackOpenUrl(\Civi\Token\TokenRow $row) {
Copy link
Member

Choose a reason for hiding this comment

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

you are not using this method so I think it is better to remove it for now

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch. It was a leftover from an earlier/misconceived approach to open-tracking. I'll remove it.

$row->context['mailingActionTarget']['email']
);

$row->format('text/plain')->tokens($entity, $field,
Copy link
Member

Choose a reason for hiding this comment

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

maybe this is a bit cleaner :

$formats = ['text/plain' => FALSE, 'text/html' => true];
foreach($formats as $format => $isHTML) {
CRM_Utils_Token::getActionTokenReplacement( $field, $verp, $urls, $isHTML));
}

@@ -203,8 +203,12 @@ public function createContainer() {
'Civi\Token\TokenCompatSubscriber',
array()
))->addTag('kernel.event_subscriber');
$container->setDefinition("crm_mailing_action_tokens", new Definition(
Copy link
Member

Choose a reason for hiding this comment

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

a space before this line would make it easier to read .. by the way I don't like the way how are these events are registered here and this method may go bigger and bigger with time .. but I see there is already a plan to fix that https://github.com/totten/civicrm-core/blob/e0c753854db4ed1bcd3b0659a29b79f535c1aa08/Civi/Core/Container.php#L112

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup, the intent is to address that readability issue by moving the declarations to smaller/separate files. Outside scope of the current PR, though.


foreach (array('Activity', 'Contribute', 'Event', 'Member') as $comp) {
foreach (array('Activity', 'Contribute', 'Event', 'Mailing', 'Member') as $comp) {
Copy link
Member

Choose a reason for hiding this comment

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

I was thinking that it may make much sense to fetch the components list dynamically and then checking if CRM_{$comp}_Tokens is their for that component ... but I think this might affect performance unless some sort of caching is performed .

Copy link
Member Author

Choose a reason for hiding this comment

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

We do cache the container definitions now-a-days (v4.7+; see loadContainer()), but I'd rather not create a sui-generis mechanism just for locating the CRM_*_Token classes. Rather, cleaning this bit should wait until we have a generally decent way to locate/discover service definitions (e.g. via annotation or YAML -- as hinted by https://github.com/totten/civicrm-core/blob/e0c753854db4ed1bcd3b0659a29b79f535c1aa08/Civi/Core/Container.php#L112 ).

Copy link
Member

Choose a reason for hiding this comment

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

got it

/**
* @group headless
*/
class CRM_Mailing_TokensTest extends \CiviUnitTestCase {
Copy link
Member

Choose a reason for hiding this comment

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

why not just implement the headless interface instead of the heavy CiviUnitTestCase class .. the tests should perform much faster ..

Copy link
Member Author

Choose a reason for hiding this comment

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

Mostly because I reflexively want to reason about tests at the suite level -- e.g. "all the tests in CRM_AllTests extend CiviUnitTestCase" or "all the tests in org.example.foo extend PHPUnit_Framework_TestCase. (This way of thinking probably arose as a defensive reaction all the heaviness in CiviUnitTestCase...) Using something else (not CiviUnitTestsCase) would make the suite more... nuanced/diverse.

I think your suggestion has better-than-even odds of working, but I don't want to put that issue question in this scope-of-work.

Copy link
Member

Choose a reason for hiding this comment

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

yup I think you can just ignore this note ... because away from diversity thing you had talked about ... it would time consuming to use PHPUnit_Framework_TestCase instead of CiviUnitTestCase for these tests .

}
$this->assertEquals(1, $count);
}

Copy link
Member

Choose a reason for hiding this comment

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

maybe a negative test could be added where neither mailingId or mailingObject is provided .

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea

During development of FlexMailer, I flirted with using a special token (e.g.
`{actions.trackOpen}`) but ultimately found that was positioned well in
the order of operations.
@totten
Copy link
Member Author

totten commented Dec 22, 2016

@omarabuhussein Thanks for the review. I've pushed updates for the unused function and the negative test scenario. Unless the style issues seem critical, I'm inclined to merge on pass.

@omarabuhussein
Copy link
Member

Thanks @totten ... the style issues is not critical but I replied to your point though .. not sure what are u going to decide but the generally it is approved .

totten added a commit to totten/civicrm-core that referenced this pull request Dec 22, 2016
This is an offshoot from the conversation on civicrm#9563.
@totten totten merged commit 68b4ca5 into civicrm:master Dec 23, 2016
@totten totten deleted the master-19690-tokens branch December 23, 2016 01:28
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