Skip to content

Commit

Permalink
CRM-21659 Add hook to CRM_Utils_System::redirect
Browse files Browse the repository at this point in the history
  • Loading branch information
eileenmcnaughton committed Feb 19, 2018
1 parent 67670b4 commit 50b621e
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 4 deletions.
24 changes: 24 additions & 0 deletions CRM/Utils/Hook.php
Original file line number Diff line number Diff line change
Expand Up @@ -1635,6 +1635,30 @@ public static function disable() {
);
}

/**
* Alter redirect.
*
* This hook is called when the browser is being re-directed and allows the url
* to be altered.
*
* @param \Psr\Http\Message\UriInterface $url
* @param string $outputFormat
* The output format for the request. Generally this will be NULL or json.
* If json it will lead to json output being returned rather than a true redirect.
* @param array $context
* Optional additional information about context.
*
* @return null
* the return value is ignored
*/
public static function alterRedirect($url, &$outputFormat, $context) {
return self::singleton()->invoke(array('url', 'outputFormat', 'context'), $url,
$outputFormat, $context,
self::$_nullObject, self::$_nullObject, self::$_nullObject,
'civicrm_alterRedirect'
);
}

/**
* @param $varType
* @param $var
Expand Down
12 changes: 10 additions & 2 deletions CRM/Utils/System.php
Original file line number Diff line number Diff line change
Expand Up @@ -433,17 +433,25 @@ public static function getClassName($object) {
*
* @param string $url
* The URL to provide to the browser via the Location header.
* @param array $context
* Optional additional information for the hook.
*/
public static function redirect($url = NULL) {
public static function redirect($url = NULL, $context = []) {
if (!$url) {
$url = self::url('civicrm/dashboard', 'reset=1');
}
// replace the & characters with &
// this is kinda hackish but not sure how to do it right
$url = str_replace('&', '&', $url);

$output = CRM_Utils_Array::value('snippet', $_GET);

$parsedUrl = CRM_Utils_Url::parseUrl($url);
CRM_Utils_Hook::alterRedirect($parsedUrl, $context, $output);
$url = CRM_Utils_Url::unparseUrl($parsedUrl);

// If we are in a json context, respond appropriately
if (CRM_Utils_Array::value('snippet', $_GET) === 'json') {
if ($output === 'json') {
CRM_Core_Page_AJAX::returnJsonResponse(array(
'status' => 'redirect',
'userContext' => $url,
Expand Down
55 changes: 55 additions & 0 deletions CRM/Utils/Url.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/

use GuzzleHttp\Psr7\Uri;
use Psr\Http\Message\UriInterface;

class CRM_Utils_Url {

/**
* Parse url to a UriInterface.
*
* @param string $url
*
* @return UriInterface
*/
public static function parseUrl($url) {
return new Uri($url);
}

/**
* Unparse url back to a string.
*
* @param UriInterface $parsed
*
* @return string
*/
public static function unparseUrl(UriInterface $parsed) {
return $parsed->__toString();
}

}
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@
"pear/Auth_SASL": "1.1.0",
"pear/Net_SMTP": "1.6.*",
"pear/Net_socket": "1.0.*",
"civicrm/civicrm-setup": "~0.2.0"
"civicrm/civicrm-setup": "~0.2.0",
"psr/http-message": "^1.0"
},
"repositories": [
{
Expand Down
52 changes: 51 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 71 additions & 0 deletions tests/phpunit/CRM/Utils/SystemTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

use Psr\Http\Message\UriInterface;

/**
* Class CRM_Utils_SystemTest
* @group headless
Expand Down Expand Up @@ -35,4 +37,73 @@ public function testEvalUrl() {
$this->assertEquals('http://example.com/?cms=UnitTests', CRM_Utils_System::evalUrl('http://example.com/?cms={uf}'));
}

/**
* Test the redirect hook.
*
* @param string $url
* @param array $parsedUrl
*
* @dataProvider getURLs
*/
public function testRedirectHook($url, $parsedUrl) {
$this->hookClass->setHook('civicrm_alterRedirect', array($this, 'hook_checkUrl'));
try {
CRM_Utils_System::redirect($url, [
'expected' => $parsedUrl,
'original' => $url
]);
}
catch (CRM_Core_Exception $e) {
$this->assertEquals(ts('hook called'), $e->getMessage());
return;
}
$this->fail('Exception should have been thrown if hook was called');
}

/**
* Hook for alterRedirect.
*
* We do some checks here.
*
* @param UriInterface $urlQuery
* @param array $context
*
* @throws \CRM_Core_Exception
*/
public function hook_checkUrl($urlQuery, $context) {
$this->assertEquals(CRM_Utils_Array::value('scheme', $context['expected']), $urlQuery->getScheme());
$this->assertEquals(CRM_Utils_Array::value('host', $context['expected']), $urlQuery->getHost());
$this->assertEquals(CRM_Utils_Array::value('query', $context['expected']), $urlQuery->getQuery());
$this->assertEquals($context['original'], CRM_Utils_Url::unparseUrl($urlQuery));

throw new CRM_Core_Exception(ts('hook called'));
}

/**
* Get urls for testing.
*
* @return array
*/
public function getURLs() {
return [
['https://example.com?ab=cd', [
'scheme' => 'https',
'host' => 'example.com',
'query' => 'ab=cd',
]],
['http://myuser:mypass@foo.bar:123/whiz?a=b&c=d', [
'scheme' => 'http',
'host' => 'foo.bar',
'port' => 123,
'user' => 'myuser',
'pass' => 'mypass',
'path' => '/whiz',
'query' => 'a=b&c=d',
]],
['/foo/bar', [
'path' => '/foo/bar'
]],
];
}

}

0 comments on commit 50b621e

Please sign in to comment.