-
-
Notifications
You must be signed in to change notification settings - Fork 814
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
Migrate CiviMail "extern" scripts to conventional routes #17312
Changes from 10 commits
cbed6fe
6296d79
5ca340c
d04905c
dc30f80
5c9b70e
78e62e1
657fcb7
28e28c3
92daae8
7d3ec0a
930bf12
6bdb58f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<?php | ||
/* | ||
+--------------------------------------------------------------------+ | ||
| Copyright CiviCRM LLC. All rights reserved. | | ||
| | | ||
| This work is published under the GNU AGPLv3 license with some | | ||
| permitted exceptions and without any warranty. For full license | | ||
| and copyright information, see https://civicrm.org/licensing | | ||
+--------------------------------------------------------------------+ | ||
*/ | ||
|
||
/** | ||
* | ||
* @package CRM | ||
* @copyright CiviCRM LLC https://civicrm.org/licensing | ||
*/ | ||
|
||
/** | ||
* Indicate that a CiviMail message has been opened | ||
* | ||
* General Usage: civicrm/mailing/open?qid={event_queue_id} | ||
* | ||
* NOTE: The parameter name has changed slightly from 'extern/open.php?q={event_queue_id}`. | ||
*/ | ||
class CRM_Mailing_Page_Open extends CRM_Core_Page { | ||
|
||
/** | ||
* Mark the mailing as opened | ||
* | ||
* @throws \CRM_Core_Exception | ||
*/ | ||
public function run() { | ||
$queue_id = CRM_Utils_Request::retrieveValue('qid', 'Positive', NULL, FALSE, 'GET'); | ||
if (!$queue_id) { | ||
// Deprecated: "?q=" is problematic in Drupal integrations, but we'll accept if igiven | ||
$queue_id = CRM_Utils_Request::retrieveValue('q', 'Positive', NULL, FALSE, 'GET');; | ||
} | ||
if (!$queue_id) { | ||
echo "Missing input parameters\n"; | ||
exit(); | ||
} | ||
|
||
CRM_Mailing_Event_BAO_Opened::open($queue_id); | ||
|
||
$filename = Civi::paths()->getPath('[civicrm.root]/i/tracker.gif'); | ||
|
||
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); | ||
header('Content-Description: File Transfer'); | ||
header('Content-type: image/gif'); | ||
header('Content-Length: ' . filesize($filename)); | ||
header('Content-Disposition: inline; filename=tracker.gif'); | ||
|
||
readfile($filename); | ||
|
||
CRM_Utils_System::civiExit(); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
<?php | ||
/* | ||
+--------------------------------------------------------------------+ | ||
| Copyright CiviCRM LLC. All rights reserved. | | ||
| | | ||
| This work is published under the GNU AGPLv3 license with some | | ||
| permitted exceptions and without any warranty. For full license | | ||
| and copyright information, see https://civicrm.org/licensing | | ||
+--------------------------------------------------------------------+ | ||
*/ | ||
|
||
/** | ||
* | ||
* @package CRM | ||
* @copyright CiviCRM LLC https://civicrm.org/licensing | ||
*/ | ||
|
||
/** | ||
* Redirects a user to the full url from a mailing url. | ||
* | ||
* General Usage: civicrm/mailing/url?qid={event_queue_id}&u={url_id} | ||
* | ||
* Additional arguments may be handled by extractPassthroughParameters(). | ||
*/ | ||
class CRM_Mailing_Page_Url extends CRM_Core_Page { | ||
|
||
/** | ||
* Redirect the user to the specified url. | ||
* | ||
* @throws \CRM_Core_Exception | ||
*/ | ||
public function run() { | ||
$queue_id = CRM_Utils_Request::retrieveValue('qid', 'Integer'); | ||
$url_id = CRM_Utils_Request::retrieveValue('u', 'Integer', NULL, TRUE); | ||
$url = CRM_Mailing_Event_BAO_TrackableURLOpen::track($queue_id, $url_id); | ||
$query_string = $this->extractPassthroughParameters(); | ||
|
||
if (strlen($query_string) > 0) { | ||
// Parse the url to preserve the fragment. | ||
$pieces = parse_url($url); | ||
|
||
if (isset($pieces['fragment'])) { | ||
$url = str_replace('#' . $pieces['fragment'], '', $url); | ||
} | ||
|
||
// Handle additional query string params. | ||
if ($query_string) { | ||
if (stristr($url, '?')) { | ||
$url .= '&' . $query_string; | ||
} | ||
else { | ||
$url .= '?' . $query_string; | ||
} | ||
} | ||
|
||
// slap the fragment onto the end per URL spec | ||
if (isset($pieces['fragment'])) { | ||
$url .= '#' . $pieces['fragment']; | ||
} | ||
} | ||
CRM_Utils_System::redirect($url, [ | ||
'for' => 'civicrm/mailing/url', | ||
'queue_id' => $queue_id, | ||
'url_id' => $url_id, | ||
]); | ||
} | ||
|
||
/** | ||
* Determine if this request has any valid pass-through parameters. | ||
* | ||
* Under CRM-7103 (v3.3), all unrecognized query-parameters (besides qid/u) are passed | ||
* through as part of the redirect. This mechanism is relevant to certain | ||
* customizations (eg using `hook_alterMailParams` to append extra URL args) | ||
* but does not matter for normal URLs. | ||
* | ||
* The functionality seems vaguely problematic (IMHO) - especially now that | ||
* 'extern/url.php' is moving into the CMS/Civi router ('civicrm/mailing/url'). | ||
* But it's the current protocol. | ||
* | ||
* A better design might be to support `hook_alterRedirect` in the CiviMail | ||
* click-through tracking. Then you don't have to take any untrusted inputs | ||
* and you can fix URL mistakes in realtime. | ||
* | ||
* @return string | ||
* @link https://issues.civicrm.org/jira/browse/CRM-7103 | ||
*/ | ||
protected function extractPassthroughParameters():string { | ||
$config = CRM_Core_Config::singleton(); | ||
|
||
$query_param = $_GET; | ||
unset($query_param['qid']); | ||
unset($query_param['u']); | ||
unset($query_param[$config->userFrameworkURLVar]); | ||
if ($config->userFramework === 'WordPress') { | ||
// Ugh | ||
unset($query_param['page']); | ||
unset($query_param['noheader']); | ||
} | ||
|
||
$query_string = http_build_query($query_param); | ||
return $query_string; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -239,6 +239,27 @@ | |
'description' => NULL, | ||
'help_text' => NULL, | ||
], | ||
'defaultExternUrl' => [ | ||
'group_name' => 'CiviCRM Preferences', | ||
'group' => 'core', | ||
'name' => 'defaultExternUrl', | ||
'type' => 'String', | ||
'quick_form_type' => 'Select', | ||
'html_type' => 'Select', | ||
'html_attributes' => [ | ||
'class' => 'crm-select2', | ||
], | ||
'default' => 'router', | ||
'add' => '5.27', | ||
'title' => ts('Extern URL Style'), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Transitional Extern URL style ... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @totten @eileenmcnaughton I'm confused -- why would a GitLab issue be necessary? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @christianwach the theory is that people would only use this setting if they need to because something weird is happening. Once there are no more something weirds then the setting & support for it can go. Probably in a few months we would remove from the form & later on from the code base There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @eileenmcnaughton Sounds reasonable to me 👍 |
||
'is_domain' => 1, | ||
'is_contact' => 0, | ||
'help_text' => NULL, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also - the help text should ideally be in here - although I think that if the settings page is not using the generic tpl it may not work There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That sounds cool :) - I didn't realize that dataflow was now working for some forms. FWIW, when I grep |
||
'options' => [ | ||
'standalone' => ts('Prefer standalone scripts'), | ||
'router' => ts('Prefer normal router'), | ||
], | ||
], | ||
'activity_assignee_notification' => [ | ||
'group_name' => 'CiviCRM Preferences', | ||
'group' => 'core', | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I first tested on a
wpmaster
site,extractPassthroughParameters()
was still producing some noisy GET params (e.g. a link tohttps://www.google.com
winds up ashttps://www.google.com?noheader=1
). This extra conditional resolved that.But it's also ugly. TBH I'd be happier to rip out
extractPassthroughParameters()
and make a small BC-break:extractPassthroughParameters()
is not well-defined across different routing systems.hook_civicrm_alterRedirect
).hook_civicrm_alterMailParams
consumers inuniverse
and couldn't spot any doing URL manipulation on CiviMail content. (The fuziontransactional
ext was close, but it skips CiviMail.)hook_civicrm_alterMailParams
for URL manipulation, then you can buy some time for a transition -- setdefaultExternUrl=standalone
and you get the old behavior.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@totten I'm pretty sure that this issue on Lab will have an impact here - because bleeding edge WordPress has changed the way in which the
page
query var is used and it now assumes that this is the the desired path and redirects accordingly. We're going to have to audit CiviCRM's usage of this query var in a WordPress context and strip out any usage of it on the front-end. This should lead tounset($query_param['page']);
being unnecessary.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, well,
?page=
won't be missed. :)Since coordinating the timelines on these changes may be tricky, I guess the implication here is... if #17312 does keep
extractPassthroughParameters()
, then eventually we can remove theunset($query_param['page')
. For the moment, from a WP-integration perspective, there's no harm in keeping theunset()
.