* The redirect/tracking url
*/
public static function getTrackerURL($url, $mailing_id, $queue_id) {
+ if (strpos($url, '{') !== FALSE) {
+ return self::getTrackerURLForUrlWithTokens($url, $mailing_id, $queue_id);
+ }
+ else {
+ return self::getBasicTrackerURL($url, $mailing_id, $queue_id);
+ }
+ }
+ private static function getBasicTrackerURL($url, $mailing_id, $queue_id) {
static $urlCache = [];
if (array_key_exists($mailing_id . $url, $urlCache)) {
}
// hack for basic CRM-1014 and CRM-1151 and CRM-3492 compliance:
- // let's not replace possible image URLs and CiviMail ones
+ // let's not replace possible image URLs, CiviMail URLs or internal anchor URLs
if (preg_match('/\.(png|jpg|jpeg|gif|css)[\'"]?$/i', $url)
or substr_count($url, 'civicrm/extern/')
or substr_count($url, 'civicrm/mailing/')
+ or ($url[0] === '#')
) {
// let's not cache these, so they don't get &qid= appended to them
return $url;
return $returnUrl;
}
+ /**
+ * Create a trackable URL for a URL with tokens.
+ *
+ * @param string $url
+ * @param int $mailing_id
+ * @param int|string $queue_id
+ *
+ * @return string
+ */
+ private static function getTrackerURLForUrlWithTokens($url, $mailing_id, $queue_id) {
+
+ // Parse the URL.
+ // (not using parse_url because it's messy to reassemble)
+ if (!preg_match('/^([^?#]+)([?][^#]*)?(#.*)?$/', $url, $parsed)) {
+ // Failed to parse it, give up and don't track it.
+ return $url;
+ }
+
+ // If we have a token in the URL + path section, we can't tokenise.
+ if (strpos($parsed[1], '{') !== FALSE) {
+ return $url;
+ }
+
+ $trackable_url = $parsed[1];
+
+ // Process the query parameters, if there are any.
+ $tokenised_params = [];
+ $static_params = [];
+ if (!empty($parsed[2])) {
+ $query_key_value_pairs = explode('&', substr($parsed[2], 1));
+
+ // Separate the tokenised from the static parts.
+ foreach ($query_key_value_pairs as $_) {
+ if (strpos($_, '{') === FALSE) {
+ $static_params[] = $_;
+ }
+ else {
+ $tokenised_params[] = $_;
+ }
+ }
+ // Add the static params to the trackable part.
+ if ($static_params) {
+ $trackable_url .= '?' . implode('&', $static_params);
+ }
+ }
+
+ // Get trackable URL.
+ $data = self::getBasicTrackerURL($trackable_url, $mailing_id, $queue_id);
+
+ // Append the tokenised bits and the fragment.
+ if ($tokenised_params) {
+ // We know the URL will already have the '?'
+ $data .= '&' . implode('&', $tokenised_params);
+ }
+ if (!empty($parsed[3])) {
+ $data .= $parsed[3];
+ }
+ return $data;
+ }
+
/**
* @param $url
* @param $mailing_id