From d9562a6b654d0a7d615671be0e9450b10e0806b5 Mon Sep 17 00:00:00 2001
From: Matthieu Napoli <matthieu@mnapoli.fr>
Date: Wed, 15 Oct 2014 15:52:40 +1300
Subject: [PATCH] Extracted `Piwik::getJavascriptCode()` into a separate, non
 static class: `Piwik\Tracker\TrackerCodeGenerator`

`Piwik::getJavascriptCode()` is now deprecated in favor of the new class.
---
 CHANGELOG.md                                  |   5 +
 core/Piwik.php                                | 129 +-------------
 core/Tracker/TrackerCodeGenerator.php         | 166 ++++++++++++++++++
 plugins/Installation/Controller.php           |   4 +-
 plugins/SitesManager/API.php                  |   3 +-
 plugins/SitesManager/Controller.php           |   4 +-
 .../Tracker/TrackerCodeGeneratorTest.php      | 154 ++++++++++++++++
 7 files changed, 338 insertions(+), 127 deletions(-)
 create mode 100644 core/Tracker/TrackerCodeGenerator.php
 create mode 100644 tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php

diff --git a/CHANGELOG.md b/CHANGELOG.md
index abfbb6e1a5..696e6e7588 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,11 @@
 
 This is a changelog for Piwik platform developers. All changes for our HTTP API's, Plugins, Themes, etc will be listed here.
 
+## Piwik 2.9.0
+
+### Deprecations
+* `Piwik::getJavascriptCode()` has been deprecated in favor of `Piwik\Tracker\TrackerCodeGenerator::generate()`
+
 ## Piwik 2.8.0
 
 ### Breaking Changes
diff --git a/core/Piwik.php b/core/Piwik.php
index 13124728f9..77cf4da82b 100644
--- a/core/Piwik.php
+++ b/core/Piwik.php
@@ -13,7 +13,6 @@ use Piwik\Db\Adapter;
 use Piwik\Db\Schema;
 use Piwik\Db;
 use Piwik\Plugin;
-use Piwik\Plugins\SitesManager\API as APISitesManager;
 use Piwik\Plugins\UsersManager\API as APIUsersManager;
 use Piwik\Session;
 use Piwik\Tracker;
@@ -125,112 +124,18 @@ class Piwik
      * @param int $idSite
      * @param string $piwikUrl http://path/to/piwik/directory/
      * @return string
+     *
+     * @deprecated Use {@link TrackerCodeGenerator} instead
+     * @see \Piwik\Tracker\TrackerCodeGenerator
      */
     public static function getJavascriptCode($idSite, $piwikUrl, $mergeSubdomains = false, $groupPageTitlesByDomain = false,
                                              $mergeAliasUrls = false, $visitorCustomVariables = false, $pageCustomVariables = false,
                                              $customCampaignNameQueryParam = false, $customCampaignKeywordParam = false,
                                              $doNotTrack = false, $disableCookies = false)
     {
-        // changes made to this code should be mirrored in plugins/CoreAdminHome/javascripts/jsTrackingGenerator.js var generateJsCode
-        $jsCode = file_get_contents(PIWIK_INCLUDE_PATH . "/plugins/Morpheus/templates/javascriptCode.tpl");
-        $jsCode = htmlentities($jsCode);
-        if (substr($piwikUrl, 0, 4) !== 'http') {
-            $piwikUrl = 'http://' . $piwikUrl;
-        }
-        preg_match('~^(http|https)://(.*)$~D', $piwikUrl, $matches);
-        $piwikUrl = rtrim(@$matches[2], "/");
-
-        // Build optional parameters to be added to text
-        $options = '';
-        $optionsBeforeTrackerUrl = '';
-        if ($groupPageTitlesByDomain) {
-            $options .= '  _paq.push(["setDocumentTitle", document.domain + "/" + document.title]);' . PHP_EOL;
-        }
-        if ($mergeSubdomains || $mergeAliasUrls) {
-            $options .= self::getJavascriptTagOptions($idSite, $mergeSubdomains, $mergeAliasUrls);
-        }
-        $maxCustomVars = Plugins\CustomVariables\CustomVariables::getMaxCustomVariables();
-
-        if ($visitorCustomVariables) {
-            $options .=  '  // you can set up to ' . $maxCustomVars . ' custom variables for each visitor' . PHP_EOL;
-            $index = 1;
-            foreach ($visitorCustomVariables as $visitorCustomVariable) {
-                if (empty($visitorCustomVariable)) {
-                    continue;
-                }
-
-                $options .=  '  _paq.push(["setCustomVariable", '.$index++.', "'.$visitorCustomVariable[0].'", "'.$visitorCustomVariable[1].'", "visit"]);' . PHP_EOL;
-            }
-        }
-        if ($pageCustomVariables) {
-            $options .=  '  // you can set up to ' . $maxCustomVars . ' custom variables for each action (page view, download, click, site search)' . PHP_EOL;
-            $index = 1;
-            foreach ($pageCustomVariables as $pageCustomVariable) {
-                if (empty($pageCustomVariable)) {
-                    continue;
-                }
-                $options .=  '  _paq.push(["setCustomVariable", '.$index++.', "'.$pageCustomVariable[0].'", "'.$pageCustomVariable[1].'", "page"]);' . PHP_EOL;
-            }
-        }
-        if ($customCampaignNameQueryParam) {
-            $options .=  '  _paq.push(["setCampaignNameKey", "'.$customCampaignNameQueryParam.'"]);' . PHP_EOL;
-        }
-        if ($customCampaignKeywordParam) {
-            $options .=  '  _paq.push(["setCampaignKeywordKey", "'.$customCampaignKeywordParam.'"]);' . PHP_EOL;
-        }
-        if ($doNotTrack) {
-            $options .= '  _paq.push(["setDoNotTrack", true]);' . PHP_EOL;
-        }
-        if ($disableCookies) {
-            $options .= '  _paq.push(["disableCookies"]);' . PHP_EOL;
-        }
+        $generator = new Tracker\TrackerCodeGenerator();
 
-        $codeImpl = array(
-            'idSite' => $idSite,
-            'piwikUrl' => Common::sanitizeInputValue($piwikUrl),
-            'options' => $options,
-            'optionsBeforeTrackerUrl' => $optionsBeforeTrackerUrl,
-            'protocol' => '//'
-        );
-        $parameters = compact('mergeSubdomains', 'groupPageTitlesByDomain', 'mergeAliasUrls', 'visitorCustomVariables',
-                              'pageCustomVariables', 'customCampaignNameQueryParam', 'customCampaignKeywordParam',
-                              'doNotTrack');
-
-        /**
-         * Triggered when generating JavaScript tracking code server side. Plugins can use
-         * this event to customise the JavaScript tracking code that is displayed to the
-         * user.
-         *
-         * @param array &$codeImpl An array containing snippets of code that the event handler
-         *                         can modify. Will contain the following elements:
-         *
-         *                         - **idSite**: The ID of the site being tracked.
-         *                         - **piwikUrl**: The tracker URL to use.
-         *                         - **options**: A string of JavaScript code that customises
-         *                                        the JavaScript tracker.
-         *                         - **optionsBeforeTrackerUrl**: A string of Javascript code that customises
-         *                                        the JavaScript tracker inside of anonymous function before
-         *                                        adding setTrackerUrl into paq.
-         *                         - **protocol**: Piwik url protocol.
-         *
-         *                         The **httpsPiwikUrl** element can be set if the HTTPS
-         *                         domain is different from the normal domain.
-         * @param array $parameters The parameters supplied to the `Piwik::getJavascriptCode()`.
-         */
-        self::postEvent('Piwik.getJavascriptCode', array(&$codeImpl, $parameters));
-
-        $setTrackerUrl = 'var u="' . $codeImpl['protocol'] . '{$piwikUrl}/";';
-
-        if (!empty($codeImpl['httpsPiwikUrl'])) {
-            $setTrackerUrl = 'var u=((document.location.protocol === "https:") ? "https://{$httpsPiwikUrl}/" : "http://{$piwikUrl}/");';
-            $codeImpl['httpsPiwikUrl'] = rtrim($codeImpl['httpsPiwikUrl'], "/");
-        }
-        $codeImpl = array('setTrackerUrl' => htmlentities($setTrackerUrl)) + $codeImpl;
-
-        foreach ($codeImpl as $keyToReplace => $replaceWith) {
-            $jsCode = str_replace('{$' . $keyToReplace . '}', $replaceWith, $jsCode);
-        }
-        return $jsCode;
+        return $generator->generate($idSite, $piwikUrl, $mergeSubdomains, $groupPageTitlesByDomain, $mergeAliasUrls, $visitorCustomVariables, $pageCustomVariables, $customCampaignNameQueryParam, $customCampaignKeywordParam, $doNotTrack, $disableCookies);
     }
 
     /**
@@ -847,30 +752,6 @@ class Piwik
         return vsprintf($translationId, $args);
     }
 
-    protected static function getJavascriptTagOptions($idSite, $mergeSubdomains, $mergeAliasUrls)
-    {
-        try {
-            $websiteUrls = APISitesManager::getInstance()->getSiteUrlsFromId($idSite);
-        } catch (\Exception $e) {
-            return '';
-        }
-        // We need to parse_url to isolate hosts
-        $websiteHosts = array();
-        foreach ($websiteUrls as $site_url) {
-            $referrerParsed = parse_url($site_url);
-            $websiteHosts[] = $referrerParsed['host'];
-        }
-        $options = '';
-        if ($mergeSubdomains && !empty($websiteHosts)) {
-            $options .= '  _paq.push(["setCookieDomain", "*.' . $websiteHosts[0] . '"]);' . PHP_EOL;
-        }
-        if ($mergeAliasUrls && !empty($websiteHosts)) {
-            $urls = '["*.' . implode('","*.', $websiteHosts) . '"]';
-            $options .= '  _paq.push(["setDomains", ' . $urls . ']);' . PHP_EOL;
-        }
-        return $options;
-    }
-
     /**
      * Executes a callback with superuser privileges, making sure those privileges are rescinded
      * before this method exits. Privileges will be rescinded even if an exception is thrown.
diff --git a/core/Tracker/TrackerCodeGenerator.php b/core/Tracker/TrackerCodeGenerator.php
new file mode 100644
index 0000000000..864b2dd2e3
--- /dev/null
+++ b/core/Tracker/TrackerCodeGenerator.php
@@ -0,0 +1,166 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Tracker;
+
+use Piwik\Common;
+use Piwik\Piwik;
+use Piwik\Plugins\CustomVariables\CustomVariables;
+use Piwik\Plugins\SitesManager\API as APISitesManager;
+
+/**
+ * Generates the Javascript code to be inserted on every page of the website to track.
+ */
+class TrackerCodeGenerator
+{
+    /**
+     * @param int $idSite
+     * @param string $piwikUrl http://path/to/piwik/site/
+     * @param bool $mergeSubdomains
+     * @param bool $groupPageTitlesByDomain
+     * @param bool $mergeAliasUrls
+     * @param bool $visitorCustomVariables
+     * @param bool $pageCustomVariables
+     * @param bool $customCampaignNameQueryParam
+     * @param bool $customCampaignKeywordParam
+     * @param bool $doNotTrack
+     * @param bool $disableCookies
+     * @return string Javascript code.
+     */
+    public function generate($idSite, $piwikUrl, $mergeSubdomains = false, $groupPageTitlesByDomain = false,
+                             $mergeAliasUrls = false, $visitorCustomVariables = false, $pageCustomVariables = false,
+                             $customCampaignNameQueryParam = false, $customCampaignKeywordParam = false,
+                             $doNotTrack = false, $disableCookies = false)
+    {
+        // changes made to this code should be mirrored in plugins/CoreAdminHome/javascripts/jsTrackingGenerator.js var generateJsCode
+        $jsCode = file_get_contents(PIWIK_INCLUDE_PATH . "/plugins/Morpheus/templates/javascriptCode.tpl");
+        $jsCode = htmlentities($jsCode);
+        if (substr($piwikUrl, 0, 4) !== 'http') {
+            $piwikUrl = 'http://' . $piwikUrl;
+        }
+        preg_match('~^(http|https)://(.*)$~D', $piwikUrl, $matches);
+        $piwikUrl = rtrim(@$matches[2], "/");
+
+        // Build optional parameters to be added to text
+        $options = '';
+        $optionsBeforeTrackerUrl = '';
+        if ($groupPageTitlesByDomain) {
+            $options .= '  _paq.push(["setDocumentTitle", document.domain + "/" + document.title]);' . PHP_EOL;
+        }
+        if ($mergeSubdomains || $mergeAliasUrls) {
+            $options .= $this->getJavascriptTagOptions($idSite, $mergeSubdomains, $mergeAliasUrls);
+        }
+        $maxCustomVars = CustomVariables::getMaxCustomVariables();
+
+        if ($visitorCustomVariables) {
+            $options .= '  // you can set up to ' . $maxCustomVars . ' custom variables for each visitor' . PHP_EOL;
+            $index = 1;
+            foreach ($visitorCustomVariables as $visitorCustomVariable) {
+                if (empty($visitorCustomVariable)) {
+                    continue;
+                }
+
+                $options .= '  _paq.push(["setCustomVariable", ' . $index++ . ', "' . $visitorCustomVariable[0] . '", "' . $visitorCustomVariable[1] . '", "visit"]);' . PHP_EOL;
+            }
+        }
+        if ($pageCustomVariables) {
+            $options .= '  // you can set up to ' . $maxCustomVars . ' custom variables for each action (page view, download, click, site search)' . PHP_EOL;
+            $index = 1;
+            foreach ($pageCustomVariables as $pageCustomVariable) {
+                if (empty($pageCustomVariable)) {
+                    continue;
+                }
+                $options .= '  _paq.push(["setCustomVariable", ' . $index++ . ', "' . $pageCustomVariable[0] . '", "' . $pageCustomVariable[1] . '", "page"]);' . PHP_EOL;
+            }
+        }
+        if ($customCampaignNameQueryParam) {
+            $options .= '  _paq.push(["setCampaignNameKey", "' . $customCampaignNameQueryParam . '"]);' . PHP_EOL;
+        }
+        if ($customCampaignKeywordParam) {
+            $options .= '  _paq.push(["setCampaignKeywordKey", "' . $customCampaignKeywordParam . '"]);' . PHP_EOL;
+        }
+        if ($doNotTrack) {
+            $options .= '  _paq.push(["setDoNotTrack", true]);' . PHP_EOL;
+        }
+        if ($disableCookies) {
+            $options .= '  _paq.push(["disableCookies"]);' . PHP_EOL;
+        }
+
+        $codeImpl = array(
+            'idSite'                  => $idSite,
+            'piwikUrl'                => Common::sanitizeInputValue($piwikUrl),
+            'options'                 => $options,
+            'optionsBeforeTrackerUrl' => $optionsBeforeTrackerUrl,
+            'protocol'                => '//'
+        );
+        $parameters = compact('mergeSubdomains', 'groupPageTitlesByDomain', 'mergeAliasUrls', 'visitorCustomVariables',
+            'pageCustomVariables', 'customCampaignNameQueryParam', 'customCampaignKeywordParam',
+            'doNotTrack');
+
+        /**
+         * Triggered when generating JavaScript tracking code server side. Plugins can use
+         * this event to customise the JavaScript tracking code that is displayed to the
+         * user.
+         *
+         * @param array &$codeImpl An array containing snippets of code that the event handler
+         *                         can modify. Will contain the following elements:
+         *
+         *                         - **idSite**: The ID of the site being tracked.
+         *                         - **piwikUrl**: The tracker URL to use.
+         *                         - **options**: A string of JavaScript code that customises
+         *                                        the JavaScript tracker.
+         *                         - **optionsBeforeTrackerUrl**: A string of Javascript code that customises
+         *                                        the JavaScript tracker inside of anonymous function before
+         *                                        adding setTrackerUrl into paq.
+         *                         - **protocol**: Piwik url protocol.
+         *
+         *                         The **httpsPiwikUrl** element can be set if the HTTPS
+         *                         domain is different from the normal domain.
+         * @param array $parameters The parameters supplied to `TrackerCodeGenerator::generate()`.
+         */
+        Piwik::postEvent('Piwik.getJavascriptCode', array(&$codeImpl, $parameters));
+
+        $setTrackerUrl = 'var u="' . $codeImpl['protocol'] . '{$piwikUrl}/";';
+
+        if (!empty($codeImpl['httpsPiwikUrl'])) {
+            $setTrackerUrl = 'var u=((document.location.protocol === "https:") ? "https://{$httpsPiwikUrl}/" : "http://{$piwikUrl}/");';
+            $codeImpl['httpsPiwikUrl'] = rtrim($codeImpl['httpsPiwikUrl'], "/");
+        }
+        $codeImpl = array('setTrackerUrl' => htmlentities($setTrackerUrl)) + $codeImpl;
+
+        foreach ($codeImpl as $keyToReplace => $replaceWith) {
+            $jsCode = str_replace('{$' . $keyToReplace . '}', $replaceWith, $jsCode);
+        }
+
+        return $jsCode;
+    }
+
+    private function getJavascriptTagOptions($idSite, $mergeSubdomains, $mergeAliasUrls)
+    {
+        try {
+            $websiteUrls = APISitesManager::getInstance()->getSiteUrlsFromId($idSite);
+        } catch (\Exception $e) {
+            return '';
+        }
+        // We need to parse_url to isolate hosts
+        $websiteHosts = array();
+        foreach ($websiteUrls as $site_url) {
+            $referrerParsed = parse_url($site_url);
+            $websiteHosts[] = $referrerParsed['host'];
+        }
+        $options = '';
+        if ($mergeSubdomains && !empty($websiteHosts)) {
+            $options .= '  _paq.push(["setCookieDomain", "*.' . $websiteHosts[0] . '"]);' . PHP_EOL;
+        }
+        if ($mergeAliasUrls && !empty($websiteHosts)) {
+            $urls = '["*.' . implode('","*.', $websiteHosts) . '"]';
+            $options .= '  _paq.push(["setDomains", ' . $urls . ']);' . PHP_EOL;
+        }
+        return $options;
+    }
+}
diff --git a/plugins/Installation/Controller.php b/plugins/Installation/Controller.php
index 574af47ad7..0dffcd343c 100644
--- a/plugins/Installation/Controller.php
+++ b/plugins/Installation/Controller.php
@@ -29,6 +29,7 @@ use Piwik\Plugins\UserCountry\LocationProvider;
 use Piwik\Plugins\UsersManager\API as APIUsersManager;
 use Piwik\ProxyHeaders;
 use Piwik\SettingsPiwik;
+use Piwik\Tracker\TrackerCodeGenerator;
 use Piwik\Updater;
 use Piwik\Url;
 use Piwik\Version;
@@ -375,7 +376,8 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
         // Load the Tracking code and help text from the SitesManager
         $viewTrackingHelp = new \Piwik\View('@SitesManager/_displayJavascriptCode');
         $viewTrackingHelp->displaySiteName = $siteName;
-        $viewTrackingHelp->jsTag = Piwik::getJavascriptCode($idSite, Url::getCurrentUrlWithoutFileName());
+        $javascriptGenerator = new TrackerCodeGenerator();
+        $viewTrackingHelp->jsTag = $javascriptGenerator->generate($idSite, Url::getCurrentUrlWithoutFileName());
         $viewTrackingHelp->idSite = $idSite;
         $viewTrackingHelp->piwikUrl = Url::getCurrentUrlWithoutFileName();
 
diff --git a/plugins/SitesManager/API.php b/plugins/SitesManager/API.php
index 1bb4d4b304..08beed366f 100644
--- a/plugins/SitesManager/API.php
+++ b/plugins/SitesManager/API.php
@@ -85,7 +85,8 @@ class API extends \Piwik\Plugin\API
         }
         $piwikUrl = Common::sanitizeInputValues($piwikUrl);
 
-        $htmlEncoded = Piwik::getJavascriptCode($idSite, $piwikUrl, $mergeSubdomains, $groupPageTitlesByDomain,
+        $javascriptGenerator = new Tracker\TrackerCodeGenerator();
+        $htmlEncoded = $javascriptGenerator->generate($idSite, $piwikUrl, $mergeSubdomains, $groupPageTitlesByDomain,
                                                 $mergeAliasUrls, $visitorCustomVariables, $pageCustomVariables,
                                                 $customCampaignNameQueryParam, $customCampaignKeywordParam,
                                                 $doNotTrack, $disableCookies);
diff --git a/plugins/SitesManager/Controller.php b/plugins/SitesManager/Controller.php
index b75ee8a036..e7299ab03e 100644
--- a/plugins/SitesManager/Controller.php
+++ b/plugins/SitesManager/Controller.php
@@ -14,6 +14,7 @@ use Piwik\Common;
 use Piwik\Piwik;
 use Piwik\SettingsPiwik;
 use Piwik\Site;
+use Piwik\Tracker\TrackerCodeGenerator;
 use Piwik\View;
 
 /**
@@ -95,7 +96,8 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
     {
         $idSite = Common::getRequestVar('idSite');
         Piwik::checkUserHasViewAccess($idSite);
-        $jsTag = Piwik::getJavascriptCode($idSite, SettingsPiwik::getPiwikUrl());
+        $javascriptGenerator = new TrackerCodeGenerator();
+        $jsTag = $javascriptGenerator->generate($idSite, SettingsPiwik::getPiwikUrl());
         $site  = new Site($idSite);
 
         return $this->renderTemplate('displayJavascriptCode', array(
diff --git a/tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php b/tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php
new file mode 100644
index 0000000000..343aa97d12
--- /dev/null
+++ b/tests/PHPUnit/Integration/Tracker/TrackerCodeGeneratorTest.php
@@ -0,0 +1,154 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Tests\Integration\Tracker;
+
+use Piwik\Piwik;
+use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
+use Piwik\Tracker\TrackerCodeGenerator;
+
+/**
+ * @group Core
+ */
+class TrackerCodeGeneratorTest extends IntegrationTestCase
+{
+    public function testJavascriptTrackingCode_withAllOptions()
+    {
+        $generator = new TrackerCodeGenerator();
+
+        $jsTag = $generator->generate($idSite = 1, $piwikUrl = 'http://localhost/piwik',
+            $mergeSubdomains = true, $groupPageTitlesByDomain = true, $mergeAliasUrls = true,
+            $visitorCustomVariables = array(array("name", "value"), array("name 2", "value 2")),
+            $pageCustomVariables = array(array("page cvar", "page cvar value")),
+            $customCampaignNameQueryParam = "campaignKey", $customCampaignKeywordParam = "keywordKey",
+            $doNotTrack = true);
+
+        $expected = "&lt;!-- Piwik --&gt;
+&lt;script type=&quot;text/javascript&quot;&gt;
+  var _paq = _paq || [];
+  _paq.push([\"setDocumentTitle\", document.domain + \"/\" + document.title]);
+  // you can set up to 5 custom variables for each visitor
+  _paq.push([\"setCustomVariable\", 1, \"name\", \"value\", \"visit\"]);
+  _paq.push([\"setCustomVariable\", 2, \"name 2\", \"value 2\", \"visit\"]);
+  // you can set up to 5 custom variables for each action (page view, download, click, site search)
+  _paq.push([\"setCustomVariable\", 1, \"page cvar\", \"page cvar value\", \"page\"]);
+  _paq.push([\"setCampaignNameKey\", \"campaignKey\"]);
+  _paq.push([\"setCampaignKeywordKey\", \"keywordKey\"]);
+  _paq.push([\"setDoNotTrack\", true]);
+  _paq.push(['trackPageView']);
+  _paq.push(['enableLinkTracking']);
+  (function() {
+    var u=&quot;//localhost/piwik/&quot;;
+    _paq.push(['setTrackerUrl', u+'piwik.php']);
+    _paq.push(['setSiteId', 1]);
+    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+    g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
+  })();
+&lt;/script&gt;
+&lt;noscript&gt;&lt;p&gt;&lt;img src=&quot;//localhost/piwik/piwik.php?idsite=1&quot; style=&quot;border:0;&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;&lt;/noscript&gt;
+&lt;!-- End Piwik Code --&gt;
+";
+
+        $this->assertEquals($expected, $jsTag);
+    }
+
+    /**
+     * Tests the generated JS code with protocol override
+     */
+    public function testJavascriptTrackingCode_withAllOptionsAndProtocolOverwrite()
+    {
+        $generator = new TrackerCodeGenerator();
+
+        Piwik::addAction('Piwik.getJavascriptCode', function (&$codeImpl) {
+            $codeImpl['protocol'] = 'https://';
+        });
+
+        $jsTag = $generator->generate($idSite = 1, $piwikUrl = 'http://localhost/piwik',
+            $mergeSubdomains = true, $groupPageTitlesByDomain = true, $mergeAliasUrls = true,
+            $visitorCustomVariables = array(array("name", "value"), array("name 2", "value 2")),
+            $pageCustomVariables = array(array("page cvar", "page cvar value")),
+            $customCampaignNameQueryParam = "campaignKey", $customCampaignKeywordParam = "keywordKey",
+            $doNotTrack = true);
+
+        $expected = "&lt;!-- Piwik --&gt;
+&lt;script type=&quot;text/javascript&quot;&gt;
+  var _paq = _paq || [];
+  _paq.push([\"setDocumentTitle\", document.domain + \"/\" + document.title]);
+  // you can set up to 5 custom variables for each visitor
+  _paq.push([\"setCustomVariable\", 1, \"name\", \"value\", \"visit\"]);
+  _paq.push([\"setCustomVariable\", 2, \"name 2\", \"value 2\", \"visit\"]);
+  // you can set up to 5 custom variables for each action (page view, download, click, site search)
+  _paq.push([\"setCustomVariable\", 1, \"page cvar\", \"page cvar value\", \"page\"]);
+  _paq.push([\"setCampaignNameKey\", \"campaignKey\"]);
+  _paq.push([\"setCampaignKeywordKey\", \"keywordKey\"]);
+  _paq.push([\"setDoNotTrack\", true]);
+  _paq.push(['trackPageView']);
+  _paq.push(['enableLinkTracking']);
+  (function() {
+    var u=&quot;https://localhost/piwik/&quot;;
+    _paq.push(['setTrackerUrl', u+'piwik.php']);
+    _paq.push(['setSiteId', 1]);
+    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+    g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
+  })();
+&lt;/script&gt;
+&lt;noscript&gt;&lt;p&gt;&lt;img src=&quot;https://localhost/piwik/piwik.php?idsite=1&quot; style=&quot;border:0;&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;&lt;/noscript&gt;
+&lt;!-- End Piwik Code --&gt;
+";
+
+        $this->assertEquals($expected, $jsTag);
+    }
+
+    /**
+     * Tests the generated JS code with options before tracker url
+     */
+    public function testJavascriptTrackingCode_withAllOptionsAndOptionsBeforeTrackerUrl()
+    {
+        $generator = new TrackerCodeGenerator();
+
+        Piwik::addAction('Piwik.getJavascriptCode', function (&$codeImpl) {
+            $codeImpl['optionsBeforeTrackerUrl'] .= "_paq.push(['setAPIUrl', 'http://localhost/statistics']);\n    ";
+        });
+
+        $jsTag = $generator->generate($idSite = 1, $piwikUrl = 'http://localhost/piwik',
+            $mergeSubdomains = true, $groupPageTitlesByDomain = true, $mergeAliasUrls = true,
+            $visitorCustomVariables = array(array("name", "value"), array("name 2", "value 2")),
+            $pageCustomVariables = array(array("page cvar", "page cvar value")),
+            $customCampaignNameQueryParam = "campaignKey", $customCampaignKeywordParam = "keywordKey",
+            $doNotTrack = true);
+
+        $expected = "&lt;!-- Piwik --&gt;
+&lt;script type=&quot;text/javascript&quot;&gt;
+  var _paq = _paq || [];
+  _paq.push([\"setDocumentTitle\", document.domain + \"/\" + document.title]);
+  // you can set up to 5 custom variables for each visitor
+  _paq.push([\"setCustomVariable\", 1, \"name\", \"value\", \"visit\"]);
+  _paq.push([\"setCustomVariable\", 2, \"name 2\", \"value 2\", \"visit\"]);
+  // you can set up to 5 custom variables for each action (page view, download, click, site search)
+  _paq.push([\"setCustomVariable\", 1, \"page cvar\", \"page cvar value\", \"page\"]);
+  _paq.push([\"setCampaignNameKey\", \"campaignKey\"]);
+  _paq.push([\"setCampaignKeywordKey\", \"keywordKey\"]);
+  _paq.push([\"setDoNotTrack\", true]);
+  _paq.push(['trackPageView']);
+  _paq.push(['enableLinkTracking']);
+  (function() {
+    var u=&quot;//localhost/piwik/&quot;;
+    _paq.push(['setAPIUrl', 'http://localhost/statistics']);
+    _paq.push(['setTrackerUrl', u+'piwik.php']);
+    _paq.push(['setSiteId', 1]);
+    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+    g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
+  })();
+&lt;/script&gt;
+&lt;noscript&gt;&lt;p&gt;&lt;img src=&quot;//localhost/piwik/piwik.php?idsite=1&quot; style=&quot;border:0;&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;&lt;/noscript&gt;
+&lt;!-- End Piwik Code --&gt;
+";
+
+        $this->assertEquals($expected, $jsTag);
+    }
+}
-- 
GitLab