diff --git a/src/ClickTracker/BaseClickTracker.php b/src/ClickTracker/BaseClickTracker.php new file mode 100644 index 0000000..bb0a894 --- /dev/null +++ b/src/ClickTracker/BaseClickTracker.php @@ -0,0 +1,94 @@ +]*href *= *\')([^\'>]+)(\');', $callback, $tmp); } + // /** // * Find URL expressions; replace them with tracked URLs. // * diff --git a/src/ClickTracker/TextClickTracker.php b/src/ClickTracker/TextClickTracker.php index 6ed8f99..a7902e8 100644 --- a/src/ClickTracker/TextClickTracker.php +++ b/src/ClickTracker/TextClickTracker.php @@ -29,13 +29,18 @@ class TextClickTracker implements ClickTrackerInterface { public function filterContent($msg, $mailing_id, $queue_id) { + + $getTrackerURL = BaseClickTracker::$getTrackerURL; + return self::replaceTextUrls($msg, - function ($url) use ($mailing_id, $queue_id) { + function ($url) use ($mailing_id, $queue_id, $getTrackerURL) { if (strpos($url, '{') !== FALSE) { - return $url; + $data = HtmlClickTracker::getTrackerURLForUrlWithTokens($url, $mailing_id, $queue_id); + } + else { + $data = $getTrackerURL($url, $mailing_id, $queue_id); } - return \CRM_Mailing_BAO_TrackableURL::getTrackerURL($url, $mailing_id, - $queue_id); + return $data; } ); } diff --git a/tests/phpunit/Civi/FlexMailer/ClickTrackerTest.php b/tests/phpunit/Civi/FlexMailer/ClickTrackerTest.php new file mode 100644 index 0000000..97c7c0b --- /dev/null +++ b/tests/phpunit/Civi/FlexMailer/ClickTrackerTest.php @@ -0,0 +1,129 @@ +installMe(__DIR__) + ->apply(); + } + + public function setUp() { + // Mock the getTrackerURL call; we don't need to test creating a row in a table. + BaseClickTracker::$getTrackerURL = function($a, $b, $c) { return 'http://example.com/extern?u=1&qid=1'; }; + + parent::setUp(); + } + + public function tearDown() { + // Reset the class. + BaseClickTracker::$getTrackerURL = ['CRM_Mailing_BAO_TrackableURL', 'getTrackerURL']; + parent::tearDown(); + } + + /** + * Example: Test that a link without any tokens works. + */ + public function testLinkWithoutTokens() { + $filter = new TextClickTracker(); + $msg = 'See this: https://example.com/foo/bar?a=b&c=d#frag'; + $result = $filter->filterContent($msg, 1, 1); + $this->assertEquals('See this: http://example.com/extern?u=1&qid=1', $result); + } + /** + * Example: Test that a link with tokens in the query works. + */ + public function testLinkWithTokensInQueryWithStaticParams() { + $filter = new TextClickTracker(); + $msg = 'See this: https://example.com/foo/bar?a=b&cid={contact.id}'; + $result = $filter->filterContent($msg, 1, 1); + $this->assertEquals('See this: http://example.com/extern?u=1&qid=1&cid={contact.id}', $result); + } + /** + * Example: Test that a link with tokens in the query works. + */ + public function testLinkWithTokensInQueryWithMultipleStaticParams() { + $filter = new TextClickTracker(); + $msg = 'See this: https://example.com/foo/bar?cs={contact.checksum}&a=b&cid={contact.id}'; + $result = $filter->filterContent($msg, 1, 1); + $this->assertEquals('See this: http://example.com/extern?u=1&qid=1&cs={contact.checksum}&cid={contact.id}', $result); + } + /** + * Example: Test that a link with tokens in the query works. + */ + public function testLinkWithTokensInQueryWithMultipleStaticParamsHtml() { + $filter = new HtmlClickTracker(); + $msg = 'See this'; + $result = $filter->filterContent($msg, 1, 1); + $this->assertEquals('See this', $result); + } + /** + * Example: Test that a link with tokens in the query works. + */ + public function testLinkWithTokensInQueryWithoutStaticParams() { + $filter = new TextClickTracker(); + $msg = 'See this: https://example.com/foo/bar?cid={contact.id}'; + $result = $filter->filterContent($msg, 1, 1); + $this->assertEquals('See this: http://example.com/extern?u=1&qid=1&cid={contact.id}', $result); + } + /** + * Example: Test that a link with tokens in the fragment works. + * + * Seems browsers maintain the fragment when they receive a redirect, so a + * token here might still work. + */ + public function testLinkWithTokensInFragment() { + $filter = new TextClickTracker(); + $msg = 'See this: https://example.com/foo/bar?a=b#cid={contact.id}'; + $result = $filter->filterContent($msg, 1, 1); + $this->assertEquals('See this: http://example.com/extern?u=1&qid=1#cid={contact.id}', $result); + } + /** + * Example: Test that a link with tokens in the fragment works. + * + * Seems browsers maintain the fragment when they receive a redirect, so a + * token here might still work. + */ + public function testLinkWithTokensInQueryAndFragment() { + $filter = new TextClickTracker(); + $msg = 'See this: https://example.com/foo/bar?a=b&cid={contact.id}#cid={contact.id}'; + $result = $filter->filterContent($msg, 1, 1); + $this->assertEquals('See this: http://example.com/extern?u=1&qid=1&cid={contact.id}#cid={contact.id}', $result); + } + /** + * We can't handle tokens in the domain so it should not be tracked. + */ + public function testLinkWithTokensInDomainFails() { + $filter = new TextClickTracker(); + $msg = 'See this: https://{some.domain}.com/foo/bar'; + $result = $filter->filterContent($msg, 1, 1); + $this->assertEquals('See this: https://{some.domain}.com/foo/bar', $result); + } + /** + * We can't handle tokens in the path so it should not be tracked. + */ + public function testLinkWithTokensInPathFails() { + $filter = new TextClickTracker(); + $msg = 'See this: https://example.com/{some.path}'; + $result = $filter->filterContent($msg, 1, 1); + $this->assertEquals('See this: https://example.com/{some.path}', $result); + } +}