CRM_Core_Page_Redirect - Generic page-redirect handler
authortotten@civicrm.org <Tim Otten>
Fri, 27 Jun 2014 07:34:19 +0000 (00:34 -0700)
committertotten@civicrm.org <Tim Otten>
Fri, 27 Jun 2014 07:34:19 +0000 (00:34 -0700)
CRM/Core/Page/Redirect.php [new file with mode: 0644]
tests/phpunit/CRM/Core/Page/RedirectTest.php [new file with mode: 0644]

diff --git a/CRM/Core/Page/Redirect.php b/CRM/Core/Page/Redirect.php
new file mode 100644 (file)
index 0000000..1441ada
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * Placeholder page which generates a redirect
+ *
+ * @code
+ * <item>
+ *   <path>civicrm/admin/options/case_type</path>
+ *   <page_callback>CRM_Core_Page_Redirect</page_callback>
+ *   <page_arguments>url=civicrm/foo/bar?whiz=bang&amp;passthru=%%passthru%%</page_arguments>
+ * </item>
+ * @endcoe
+ */
+class CRM_Core_Page_Redirect extends CRM_Core_Page {
+  function run($path = NULL, $pageArgs = array()) {
+    $url = self::createUrl($path, $_REQUEST, $pageArgs, TRUE);
+    // return $url;
+    CRM_Utils_System::redirect($url);
+  }
+
+  /**
+   * @param array $requestPath the parts of the path in the current page request
+   * @param array $requestArgs any GET arguments
+   * @param array $pageArgs the page_arguments registered in the router
+   * @param array $requestArgs any parameters passed as part of this page request
+   * @param bool $absolute whether to return an absolute URL
+   * @return string URL
+   */
+  public static function createUrl($requestPath, $requestArgs, $pageArgs, $absolute) {
+    if (empty($pageArgs['url'])) {
+      CRM_Core_Error::fatal('This page is configured as a redirect, but it does not have a target.');
+    }
+
+    $vars = array();
+    // note: %% isn't legal in a well-formed URL, so it's not a bad variable-delimiter
+    foreach ($requestPath as $pathPos => $pathPart) {
+      $vars["%%{$pathPos}%%"] = urlencode($pathPart);
+    }
+    foreach ($requestArgs as $var => $value) {
+      $vars["%%{$var}%%"] = urlencode($value);
+    }
+    $urlString = strtr($pageArgs['url'], $vars);
+    $urlString = preg_replace('/%%[a-zA-Z0-9]+%%/', '', $urlString);
+
+    $urlParts = parse_url($urlString);
+    $url = CRM_Utils_System::url(
+      $urlParts['path'],
+      CRM_Utils_Array::value('query', $urlParts, NULL),
+      $absolute,
+      CRM_Utils_Array::value('fragment', $urlParts, NULL)
+    );
+
+    return $url;
+  }
+}
diff --git a/tests/phpunit/CRM/Core/Page/RedirectTest.php b/tests/phpunit/CRM/Core/Page/RedirectTest.php
new file mode 100644 (file)
index 0000000..30e55b4
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+
+require_once 'CiviTest/CiviUnitTestCase.php';
+
+/**
+ * Class CRM_Core_Page_RedirectTest
+ */
+class CRM_Core_Page_RedirectTest extends CiviUnitTestCase {
+  function examples() {
+    $cases = array();
+    // $cases[] = array(string $requestPath, string $requestArgs, string $pageArgs, string $expectedUrl)
+
+    // Note: CRM_Utils_System::url() and CRM_Utils_System::redirect() represent the
+    // URL in "htmlized" format, so the $expectedUrl is "htmlized".
+
+    $cases[] = array('', '', 'url=civicrm/dashboard', '/index.php?q=civicrm/dashboard');
+    $cases[] = array('', '', 'url=civicrm/dashboard,mode=256', '/index.php?q=civicrm/dashboard');
+    $cases[] = array('', '', 'url=civicrm/a/#/foo/bar', '/index.php?q=civicrm/a/#/foo/bar');
+    $cases[] = array('', '', 'url=civicrm/foo/bar?whiz=1&bang=2', '/index.php?q=civicrm/foo/bar&amp;whiz=1&amp;bang=2');
+    $cases[] = array('', '', 'url=civicrm/foo?unknown=%%unknown%%', '/index.php?q=civicrm/foo&amp;unknown=');
+    $cases[] = array('civicrm/foo/bar', '', 'url=civicrm/a/#/%%2%%', '/index.php?q=civicrm/a/#/bar');
+
+    $cases[] = array(
+      '',
+      'gid=2&reset=1',
+      'url=civicrm/newfoo/%%gid%%?reset=%%reset%%',
+      '/index.php?q=civicrm/newfoo/2&amp;reset=1'
+    );
+
+    return $cases;
+  }
+
+  /**
+   * Note: Expected URL is htmlized because that's what CRM_Utils_System::url()
+   * and CRM_Utils_System::redirect() work with.
+   *
+   * @param string $requestPath eg "civicrm/requested/path"
+   * @param string $requestArgs eg "foo=bar&whiz=bang"
+   * @param string $pageArgs eg "url=civicrm/foo/bar?whiz=bang"
+   * @param string $expectedUrl eg "/index.php?q=civicrm/foo/bar&whiz=bang"
+   * @dataProvider examples
+   */
+  public function testCreateUrl($requestPath, $requestArgs, $pageArgs, $expectedUrl) {
+    $parsedRequestPath = explode('/', $requestPath);
+    parse_str($requestArgs, $parsedRequestArgs);
+    $parsedPageArgs = CRM_Core_Menu::getArrayForPathArgs($pageArgs);
+    $actualUrl = CRM_Core_Page_Redirect::createUrl($parsedRequestPath, $parsedRequestArgs, $parsedPageArgs, FALSE);
+    $this->assertEquals($expectedUrl, $actualUrl);
+  }
+}