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);
+ }
+}