add externUrl method and civicrm_alterExternUrl hook
authorAndrei Mondoc <andreimondoc@gmail.com>
Thu, 10 Oct 2019 09:52:36 +0000 (10:52 +0100)
committerAndrei Mondoc <andreimondoc@gmail.com>
Thu, 10 Oct 2019 09:52:36 +0000 (10:52 +0100)
CRM/Contribute/Form/ContributionPage/Widget.php
CRM/Core/Payment/PaymentExpress.php
CRM/Cxn/BAO/Cxn.php
CRM/Mailing/BAO/Mailing.php
CRM/Mailing/BAO/TrackableURL.php
CRM/Utils/System.php
templates/CRM/Contribute/Page/Widget.tpl
tests/phpunit/CRM/Utils/SystemTest.php

index 2a88bc06b5dfee0c1d228ba7512d6175c354a141..9d08453b0c008efe76ea934f9e325caf1f5a970e 100644 (file)
@@ -55,6 +55,8 @@ class CRM_Contribute_Form_ContributionPage_Widget extends CRM_Contribute_Form_Co
 
     $this->assign('cpageId', $this->_id);
 
+    $this->assign('widgetExternUrl', CRM_Utils_System::externUrl('extern/widget', "cpageId={$this->_id}&widgetId={$this->_widget->id}&format=3"));
+
     $config = CRM_Core_Config::singleton();
     $title = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionPage',
       $this->_id,
index 28552293feeda9e863a2fb44186cb8904f034b8e..47db6a690ca1fa4072ea3889d0619ee9b5139602 100644 (file)
@@ -121,7 +121,7 @@ class CRM_Core_Payment_PaymentExpress extends CRM_Core_Payment {
       CRM_Core_Error::fatal(ts('Component is invalid'));
     }
 
-    $url = $config->userFrameworkResourceURL . "extern/pxIPN.php";
+    $url = CRM_Utils_System::externUrl('extern/pxIPN');
 
     if ($component == 'event') {
       $cancelURL = CRM_Utils_System::url('civicrm/event/register',
index 658bd61fc6e83afe1ce516e6d9ed46bd0f7ae0e1..e304c99b3278aa2b7109a3d4c1ac97e409c1ca4b 100644 (file)
@@ -45,22 +45,7 @@ class CRM_Cxn_BAO_Cxn extends CRM_Cxn_DAO_Cxn {
    * @return string
    */
   public static function getSiteCallbackUrl() {
-    $config = CRM_Core_Config::singleton();
-
-    if (preg_match('/^(http|https):/', $config->resourceBase)) {
-      $civiUrl = $config->resourceBase;
-    }
-    else {
-      $civiUrl = rtrim(CRM_Utils_System::baseURL(), '/') . '/' . ltrim($config->resourceBase, '/');
-    }
-
-    // In practice, this may not be necessary, but we want to prevent
-    // edge-cases that downgrade security-level below system policy.
-    if (Civi::settings()->get('enableSSL')) {
-      $civiUrl = preg_replace('/^http:/', 'https:', $civiUrl);
-    }
-
-    return rtrim($civiUrl, '/') . '/extern/cxn.php';
+    return CRM_Utils_System::externUrl('extern/cxn', NULL, NULL, TRUE, TRUE);
   }
 
   /**
index 9a24f8a9a821fff24f22d26346cd1a306dbd5d44..28164b65abe3587f2965ed757ebad40654f6876e 100644 (file)
@@ -1163,8 +1163,8 @@ ORDER BY   civicrm_email.is_bulkmail DESC
 
     // push the tracking url on to the html email if necessary
     if ($this->open_tracking && $html) {
-      array_push($html, "\n" . '<img src="' . $config->userFrameworkResourceURL .
-        "extern/open.php?q=$event_queue_id\" width='1' height='1' alt='' border='0'>"
+      array_push($html, "\n" . '<img src="' . CRM_Utils_System::externUrl('extern/open', "q=$event_queue_id")
+        . '" width="1" height="1" alt="" border="0">'
       );
     }
 
index da57a134c3eb8674234aa1318cc8dc01a9c8cd4d..87d02927797c29c68c4c5ff901018c54e6f75511 100644 (file)
@@ -93,7 +93,7 @@ class CRM_Mailing_BAO_TrackableURL extends CRM_Mailing_DAO_TrackableURL {
       $urlCache[$mailing_id . $url] = $redirect;
     }
 
-    $returnUrl = "{$urlCache[$mailing_id . $url]}&qid={$queue_id}";
+    $returnUrl = CRM_Utils_System::externUrl('extern/url', "u=$id&qid=$queue_id");
 
     if ($hrefExists) {
       $returnUrl = "href='{$returnUrl}' rel='nofollow'";
index b52932368805f2c7f3579531484d4921059661bf..cdb6ffbd3f8a8899fdd8242c4fd7a3dd1fe387c0 100644 (file)
@@ -300,6 +300,41 @@ class CRM_Utils_System {
     return $url;
   }
 
+  /**
+   * Generates an extern url.
+   *
+   * @param string $path
+   *   The extern path, such as "extern/url".
+   * @param string $query
+   *   A query string to append to the link.
+   * @param string $fragment
+   *   A fragment identifier (named anchor) to append to the link.
+   * @param bool $absolute
+   *   Whether to force the output to be an absolute link (beginning with a
+   *   URI-scheme such as 'http:').
+   * @param bool $isSSL
+   *   NULL to autodetect. TRUE to force to SSL.
+   */
+  public static function externUrl($path = NULL, $query = NULL, $fragment = NULL, $absolute = TRUE, $isSSL = NULL) {
+    $query = self::makeQueryString($query);
+
+    $url = Civi::paths()->getUrl("[civicrm.root]/{$path}.php", $absolute ? 'absolute' : 'relative', $isSSL)
+      . ($query ? "?$query" : "")
+      . ($fragment ? "#$fragment" : "");
+
+    $parsedUrl = CRM_Utils_Url::parseUrl($url);
+    $event = \Civi\Core\Event\GenericHookEvent::create([
+      'url' => &$parsedUrl,
+      'path' => $path,
+      'query' => $query,
+      'fragment' => $fragment,
+      'absolute' => $absolute,
+      'isSSL' => $isSSL,
+    ]);
+    Civi::service('dispatcher')->dispatch('hook_civicrm_alterExternUrl', $event);
+    return CRM_Utils_Url::unparseUrl($event->url);
+  }
+
   /**
    * Path of the current page e.g. 'civicrm/contact/view'
    *
index 1074e2e1a71f9f0f59f67742f33f8ee07c09e718..125d07d34029f9be19ce44b4a1e82f2646598969 100644 (file)
@@ -211,4 +211,4 @@ function onReady( ) {
 }
 </script>
 {/literal}
-<script type="text/javascript" src="{$config->userFrameworkResourceURL}/extern/widget.php?cpageId={$cpageId}&widgetId={$widget_id}&format=3"></script>
+<script type="text/javascript" src="{$widgetExternUrl}"></script>
index ea129b0fbae3bdd495846c89ea393a009b1552a5..74222baa7d4344d8458809a24f60b9e7541b9f79 100644 (file)
@@ -114,6 +114,76 @@ class CRM_Utils_SystemTest extends CiviUnitTestCase {
     ];
   }
 
+  /**
+   * Test extern url.
+   */
+  public function testExternUrl() {
+    $siteKey = mt_rand();
+    $apiKey = mt_rand();
+    $restUrl = CRM_Utils_System::externUrl('extern/rest', "entity=Contact&action=get&key=$siteKey&api_key=$apiKey");
+    $this->assertContains('extern/rest.php', $restUrl);
+    $this->assertContains('?', $restUrl);
+    $this->assertContains('entity=Contact', $restUrl);
+    $this->assertContains('action=get', $restUrl);
+    $this->assertContains("key=$siteKey", $restUrl);
+    $this->assertContains("api_key=$apiKey", $restUrl);
+  }
+
+  /**
+   * Test the alterExternUrl hook.
+   *
+   * @param string $path
+   * @param array $expected
+   *
+   * @dataProvider getExternURLs
+   */
+  public function testAlterExternUrlHook($path, $expected) {
+    Civi::service('dispatcher')->addListener('hook_civicrm_alterExternUrl', [$this, 'hook_civicrm_alterExternUrl']);
+    $externUrl = CRM_Utils_System::externUrl($path, $expected['query']);
+    $this->assertContains($path, $externUrl);
+    $this->assertContains($expected['query'], $externUrl);
+  }
+
+  /**
+   * Hook for alterExternUrl.
+   *
+   * @param \Civi\Core\Event\GenericHookEvent $event
+   * @param string $hookName
+   */
+  public function hook_civicrm_alterExternUrl(\Civi\Core\Event\GenericHookEvent $event, $hookName) {
+    $this->assertEquals('hook_civicrm_alterExternUrl', $hookName);
+    $this->assertTrue($event->hasField('url'));
+    $this->assertTrue($event->hasField('path'));
+    $this->assertTrue($event->hasField('query'));
+    $this->assertTrue($event->hasField('fragment'));
+    $this->assertTrue($event->hasField('absolute'));
+    $this->assertTrue($event->hasField('isSSL'));
+  }
+
+  /**
+   * Get extern url params for testing.
+   *
+   * @return array
+   */
+  public function getExternURLs() {
+    return [
+      [
+        'extern/url',
+        [
+          'path' => 'extern/url',
+          'query' => 'u=1&qid=1',
+        ],
+      ],
+      [
+        'extern/open',
+        [
+          'path' => 'extern/open',
+          'query' => 'q=1',
+        ],
+      ],
+    ];
+  }
+
   /**
    * Demonstrate the, um, "flexibility" of isNull
    */