Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/Config.php3
-rw-r--r--core/Config/ConfigNotFoundException.php16
-rw-r--r--core/Console.php6
-rw-r--r--js/piwik.js3
-rw-r--r--piwik.js14
-rw-r--r--plugins/Live/API.php47
-rw-r--r--plugins/Live/Controller.php4
-rw-r--r--plugins/Live/Model.php113
-rw-r--r--plugins/Live/Reports/GetSimpleLastVisitCount.php3
-rw-r--r--plugins/Live/tests/System/APITest.php32
m---------tests/UI/expected-ui-screenshots0
-rw-r--r--tests/javascript/index.php9
12 files changed, 198 insertions, 52 deletions
diff --git a/core/Config.php b/core/Config.php
index e28f581ea8..f0b5c3ed26 100644
--- a/core/Config.php
+++ b/core/Config.php
@@ -10,6 +10,7 @@
namespace Piwik;
use Exception;
+use Piwik\Config\ConfigNotFoundException;
use Piwik\Ini\IniReader;
use Piwik\Ini\IniReadingException;
use Piwik\Ini\IniWriter;
@@ -370,7 +371,7 @@ class Config extends Singleton
public function checkLocalConfigFound()
{
if (!$this->existsLocalConfig()) {
- throw new Exception(Piwik::translate('General_ExceptionConfigurationFileNotFound', array($this->pathLocal)));
+ throw new ConfigNotFoundException(Piwik::translate('General_ExceptionConfigurationFileNotFound', array($this->pathLocal)));
}
}
diff --git a/core/Config/ConfigNotFoundException.php b/core/Config/ConfigNotFoundException.php
new file mode 100644
index 0000000000..5860367ba7
--- /dev/null
+++ b/core/Config/ConfigNotFoundException.php
@@ -0,0 +1,16 @@
+<?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\Config;
+
+/**
+ * Exception thrown when the config file doesn't exist.
+ */
+class ConfigNotFoundException extends \Exception
+{
+}
diff --git a/core/Console.php b/core/Console.php
index 02e5f86871..fac27d8036 100644
--- a/core/Console.php
+++ b/core/Console.php
@@ -8,6 +8,7 @@
*/
namespace Piwik;
+use Piwik\Config\ConfigNotFoundException;
use Piwik\Container\StaticContainer;
use Piwik\Plugin\Manager as PluginManager;
use Symfony\Bridge\Monolog\Handler\ConsoleHandler;
@@ -43,10 +44,9 @@ class Console extends Application
try {
self::initPlugins();
- } catch(\Exception $e) {
+ } catch (ConfigNotFoundException $e) {
// Piwik not installed yet, no config file?
-
- Log::debug("Could not initialize plugins: " . $e->getMessage() . "\n" . $e->getTraceAsString());
+ Log::warning($e->getMessage());
}
$commands = $this->getAvailableCommands();
diff --git a/js/piwik.js b/js/piwik.js
index 27413028ff..0f4f5d253a 100644
--- a/js/piwik.js
+++ b/js/piwik.js
@@ -4245,6 +4245,9 @@ if (typeof Piwik !== 'object') {
* @param string User ID
*/
setUserId: function (userId) {
+ if(!isDefined(userId) || !userId.length) {
+ return;
+ }
configUserId = userId;
visitorUUID = hash(configUserId).substr(0, 16);
},
diff --git a/piwik.js b/piwik.js
index 7dee2eeab8..674c9b6fdb 100644
--- a/piwik.js
+++ b/piwik.js
@@ -43,12 +43,12 @@ cf.push(cc)}return cf}function aW(cc){var cb=m.collectContent(cc);return aB(cb,c
aZ(cc,bn)}function bO(ce,cb,ci,ch,cd){var cg=cb+"="+l(bY(ce));var cc=aR(cd,"click",ce);if(cc){cg+="&"+cc}var cf=aT(cg,ci,"link");aZ(cf,(ch?0:bn),ch)}function bV(cc,cb){if(cc!==""){return cc+cb.charAt(0).toUpperCase()+cb.slice(1)}return cb}function aM(cg){var cf,cb,ce=["","webkit","ms","moz"],cd;if(!a0){for(cb=0;cb<ce.length;cb++){cd=ce[cb];if(Object.prototype.hasOwnProperty.call(u,bV(cd,"hidden"))){if(u[bV(cd,"visibilityState")]==="prerender"){cf=true}break}}}if(cf){U(u,cd+"visibilitychange",function cc(){u.removeEventListener(cd+"visibilitychange",cc,false);cg()});return}cg()}function aQ(cb){if(u.readyState==="complete"){cb()}else{if(G.addEventListener){G.addEventListener("load",cb)}else{if(G.attachEvent){G.attachEvent("onLoad",cb)}}}}function aA(cc){var cb=false;if(u.attachEvent){cb=u.readyState==="complete"}else{cb=u.readyState!=="loading"}if(cb){cc()}else{if(u.addEventListener){u.addEventListener("DOMContentLoaded",cc)}else{if(u.attachEvent){u.attachEvent("onreadystatechange",cc)}}}}function bE(cb){var cc=bi(cb);
if(cc&&cc.type){cc.href=h(cc.href);bO(cc.href,cc.type,undefined,null,cb)}}function b9(cb){var cc,cd;cb=cb||G.event;cc=cb.which||cb.button;cd=cb.target||cb.srcElement;if(cb.type==="click"){if(cd){bE(cd)}}else{if(cb.type==="mousedown"){if((cc===1||cc===2)&&cd){bj=cc;at=cd}else{bj=at=null}}else{if(cb.type==="mouseup"){if(cc===bj&&cd===at){bE(cd)}bj=at=null}}}}function bA(cc,cb){if(cb){U(cc,"mouseup",b9,false);U(cc,"mousedown",b9,false)}else{U(cc,"click",b9,false)}}function bd(cc){if(!bz){bz=true;var cd,cb=aH(ai,"ignore"),ce=u.links;if(ce){for(cd=0;cd<ce.length;cd++){if(!cb.test(ce[cd].className)){bA(ce[cd],cc)}}}}}function bv(cd,cf,cg){if(ay){return true}ay=true;var ch=false;var ce,cc;function cb(){ch=true}aQ(function(){function ci(ck){setTimeout(function(){if(!ay){return}ch=false;cg.trackVisibleContentImpressions();ci(ck)},ck)}function cj(ck){setTimeout(function(){if(!ay){return}if(ch){ch=false;cg.trackVisibleContentImpressions()}cj(ck)},ck)}if(cd){ce=["scroll","resize"];for(cc=0;cc<ce.length;
cc++){if(u.addEventListener){u.addEventListener(ce[cc],cb)}else{G.attachEvent("on"+ce[cc],cb)}}cj(100)}if(cf&&cf>0){cf=parseInt(cf,10);ci(cf)}})}function b0(){var cc,cd,ce={pdf:"application/pdf",qt:"video/quicktime",realp:"audio/x-pn-realaudio-plugin",wma:"application/x-mplayer2",dir:"application/x-director",fla:"application/x-shockwave-flash",java:"application/x-java-vm",gears:"application/x-googlegears",ag:"application/x-silverlight"},cb=(new RegExp("Mac OS X.*Safari/")).test(e.userAgent)?G.devicePixelRatio||1:1;if(!((new RegExp("MSIE")).test(e.userAgent))){if(e.mimeTypes&&e.mimeTypes.length){for(cc in ce){if(Object.prototype.hasOwnProperty.call(ce,cc)){cd=e.mimeTypes[ce[cc]];bT[cc]=(cd&&cd.enabledPlugin)?"1":"0"}}}if(typeof navigator.javaEnabled!=="unknown"&&w(e.javaEnabled)&&e.javaEnabled()){bT.java="1"}if(q(G.GearsFactory)){bT.gears="1"}bT.cookie=ae()}bT.res=K.width*cb+"x"+K.height*cb}b0();bk();am();return{getVisitorId:function(){return bB().uuid},getVisitorInfo:function(){return Y()
-},getAttributionInfo:function(){return X()},getAttributionCampaignName:function(){return X()[0]},getAttributionCampaignKeyword:function(){return X()[1]},getAttributionReferrerTimestamp:function(){return X()[2]},getAttributionReferrerUrl:function(){return X()[3]},setTrackerUrl:function(cb){aa=cb},getTrackerUrl:function(){return aa},getSiteId:function(){return bS},setSiteId:function(cb){b7(cb)},setUserId:function(cb){aJ=cb;a2=aX(aJ).substr(0,16)},getUserId:function(){return aJ},setCustomData:function(cb,cc){if(J(cb)){an=cb}else{if(!an){an={}}an[cb]=cc}},getCustomData:function(){return an},setCustomRequestProcessing:function(cb){au=cb},appendToTrackingUrl:function(cb){bo=cb},getRequest:function(cb){return aT(cb)},addPlugin:function(cb,cc){a[cb]=cc},setCustomVariable:function(cc,cb,cf,cd){var ce;if(!w(cd)){cd="visit"}if(!w(cb)){return}if(!w(cf)){cf=""}if(cc>0){cb=!n(cb)?String(cb):cb;cf=!n(cf)?String(cf):cf;ce=[cb.slice(0,bX),cf.slice(0,bX)];if(cd==="visit"||cd===2){Z();ag[cc]=ce}else{if(cd==="page"||cd===3){bg[cc]=ce
-}else{if(cd==="event"){ab[cc]=ce}}}}},getCustomVariable:function(cc,cd){var cb;if(!w(cd)){cd="visit"}if(cd==="page"||cd===3){cb=bg[cc]}else{if(cd==="event"){cb=ab[cc]}else{if(cd==="visit"||cd===2){Z();cb=ag[cc]}}}if(!w(cb)||(cb&&cb[0]==="")){return false}return cb},deleteCustomVariable:function(cb,cc){if(this.getCustomVariable(cb,cc)){this.setCustomVariable(cb,"","",cc)}},storeCustomVariablesInCookie:function(){a6=true},setLinkTrackingTimer:function(cb){bn=cb},setDownloadExtensions:function(cb){aU=cb},addDownloadExtensions:function(cb){aU+="|"+cb},setDomains:function(cb){bp=n(cb)?[cb]:cb;bp.push(bM)},setIgnoreClasses:function(cb){ai=n(cb)?[cb]:cb},setRequestMethod:function(cb){bs=cb||bq},setRequestContentType:function(cb){aK=cb||bc},setReferrerUrl:function(cb){bu=cb},setCustomUrl:function(cb){a7=bL(b4,cb)},setDocumentTitle:function(cb){aS=cb},setAPIUrl:function(cb){ax=cb},setDownloadClasses:function(cb){bf=n(cb)?[cb]:cb},setLinkClasses:function(cb){aC=n(cb)?[cb]:cb},setCampaignNameKey:function(cb){aY=n(cb)?[cb]:cb
-},setCampaignKeywordKey:function(cb){aP=n(cb)?[cb]:cb},discardHashTag:function(cb){ak=cb},setCookieNamePrefix:function(cb){b2=cb;ag=ar()},setCookieDomain:function(cb){aq=y(cb);bk()},setCookiePath:function(cb){b3=cb;bk()},setVisitorCookieTimeout:function(cb){aw=cb*1000},setSessionCookieTimeout:function(cb){az=cb*1000},setReferralCookieTimeout:function(cb){ba=cb*1000},setConversionAttributionFirstReferrer:function(cb){a5=cb},disableCookies:function(){ao=true;bT.cookie="0"},deleteCookies:function(){W()},setDoNotTrack:function(cc){var cb=e.doNotTrack||e.msDoNotTrack;bW=cc&&(cb==="yes"||cb==="1");if(bW){this.disableCookies()}},addListener:function(cc,cb){bA(cc,cb)},enableLinkTracking:function(cb){bU=true;if(p){bd(cb)}else{E.push(function(){bd(cb)})}},enableJSErrorTracking:function(){if(b8){return}b8=true;var cb=G.onerror;G.onerror=function(cg,ce,cd,cf,cc){aM(function(){var ch="JavaScript Errors";var ci=ce+":"+cd;if(cf){ci+=":"+cf}al(ch,ci,cg)});if(cb){return cb(cg,ce,cd,cf,cc)}return false}},disablePerformanceTracking:function(){a1=false
-},setGenerationTimeMs:function(cb){aI=parseInt(cb,10)},setHeartBeatTimer:function(cd,cc){var cb=new Date();aj=cb.getTime()+cd*1000;aG=cc*1000},killFrame:function(){if(G.location!==G.top.location){G.top.location=G.location}},redirectFile:function(cb){if(G.location.protocol==="file:"){G.location=cb}},setCountPreRendered:function(cb){a0=cb},trackGoal:function(cb,cd,cc){aM(function(){bl(cb,cd,cc)})},trackLink:function(cc,cb,ce,cd){aM(function(){bO(cc,cb,ce,cd)})},trackPageView:function(cb,cc){ah=[];if(A(bS)){aM(function(){M(aa,ax,bS)})}else{aM(function(){be(cb,cc)})}},trackAllContentImpressions:function(){if(A(bS)){return}aM(function(){aA(function(){var cb=m.findContentNodes();var cc=aW(cb);ap(cc,bn)})})},trackVisibleContentImpressions:function(cb,cc){if(A(bS)){return}if(!w(cb)){cb=true}if(!w(cc)){cc=750}bv(cb,cc,this);aM(function(){aQ(function(){var cd=m.findContentNodes();var ce=bC(cd);ap(ce,bn)})})},trackContentImpression:function(cd,cb,cc){if(A(bS)){return}if(!cd){return}cb=cb||"Unknown";
-aM(function(){var ce=bN(cd,cb,cc);aZ(ce,bn)})},trackContentImpressionsWithinNode:function(cb){if(A(bS)||!cb){return}aM(function(){if(ay){aQ(function(){var cc=m.findContentNodesWithinNode(cb);var cd=bC(cc);ap(cd,bn)})}else{aA(function(){var cc=m.findContentNodesWithinNode(cb);var cd=aW(cc);ap(cd,bn)})}})},trackContentInteraction:function(cd,ce,cb,cc){if(A(bS)){return}if(!cd||!ce){return}cb=cb||"Unknown";aM(function(){var cf=b6(cd,ce,cb,cc);aZ(cf,bn)})},trackContentInteractionNode:function(cc,cb){if(A(bS)||!cc){return}aM(function(){var cd=aV(cc,cb);aZ(cd,bn)})},trackEvent:function(cc,ce,cb,cd){aM(function(){al(cc,ce,cb,cd)})},trackSiteSearch:function(cb,cd,cc){aM(function(){aN(cb,cd,cc)})},setEcommerceView:function(ce,cb,cd,cc){if(!w(cd)||!cd.length){cd=""}else{if(cd instanceof Array){cd=JSON2.stringify(cd)}}bg[5]=["_pkc",cd];if(w(cc)&&String(cc).length){bg[2]=["_pkp",cc]}if((!w(ce)||!ce.length)&&(!w(cb)||!cb.length)){return}if(w(ce)&&ce.length){bg[3]=["_pks",ce]}if(!w(cb)||!cb.length){cb=""
-}bg[4]=["_pkn",cb]},addEcommerceItem:function(cf,cb,cd,cc,ce){if(cf.length){bF[cf]=[cf,cb,cd,cc,ce]}},trackEcommerceOrder:function(cb,cf,ce,cd,cc,cg){bJ(cb,cf,ce,cd,cc,cg)},trackEcommerceCartUpdate:function(cb){b1(cb)}}}function v(){return{push:R}}U(G,"beforeunload",S,false);o();Date.prototype.getTimeAlias=Date.prototype.getTime;L=new D();var r={setTrackerUrl:1,setAPIUrl:1,setUserId:1,setSiteId:1,disableCookies:1,enableLinkTracking:1};var d;for(t=0;t<_paq.length;t++){d=_paq[t][0];if(r[d]){R(_paq[t]);delete _paq[t];if(r[d]>1){if(console!==undefined&&console&&console.error){console.error("The method "+d+' is registered more than once in "_paq" variable. Only the last call has an effect. Please have a look at the multiple Piwik trackers documentation: http://developer.piwik.org/guides/tracking-javascript-guide#multiple-piwik-trackers')}}r[d]++}}for(t=0;t<_paq.length;t++){if(_paq[t]){R(_paq[t])}}_paq=new v();c={addPlugin:function(W,X){a[W]=X},getTracker:function(W,X){if(!w(X)){X=this.getAsyncTracker().getSiteId()
-}if(!w(W)){W=this.getAsyncTracker().getTrackerUrl()}return new D(W,X)},getAsyncTracker:function(){return L}};if(typeof define==="function"&&define.amd){define("piwik",[],function(){return c})}return c}())}if(window&&window.piwikAsyncInit){window.piwikAsyncInit()}(function(){var a=(typeof AnalyticsTracker);if(a==="undefined"){AnalyticsTracker=Piwik}}());if(typeof piwik_log!=="function"){piwik_log=function(b,f,d,g){function a(h){try{return eval("piwik_"+h)}catch(i){}return}var c,e=Piwik.getTracker(d,f);e.setDocumentTitle(b);e.setCustomData(g);c=a("tracker_pause");if(c){e.setLinkTrackingTimer(c)}c=a("download_extensions");if(c){e.setDownloadExtensions(c)}c=a("hosts_alias");if(c){e.setDomains(c)}c=a("ignore_classes");if(c){e.setIgnoreClasses(c)}e.trackPageView();if(a("install_tracker")){piwik_track=function(i,k,j,h){e.setSiteId(k);e.setTrackerUrl(j);e.trackLink(i,h)};e.enableLinkTracking()}};
+},getAttributionInfo:function(){return X()},getAttributionCampaignName:function(){return X()[0]},getAttributionCampaignKeyword:function(){return X()[1]},getAttributionReferrerTimestamp:function(){return X()[2]},getAttributionReferrerUrl:function(){return X()[3]},setTrackerUrl:function(cb){aa=cb},getTrackerUrl:function(){return aa},getSiteId:function(){return bS},setSiteId:function(cb){b7(cb)},setUserId:function(cb){if(!w(cb)||!cb.length){return}aJ=cb;a2=aX(aJ).substr(0,16)},getUserId:function(){return aJ},setCustomData:function(cb,cc){if(J(cb)){an=cb}else{if(!an){an={}}an[cb]=cc}},getCustomData:function(){return an},setCustomRequestProcessing:function(cb){au=cb},appendToTrackingUrl:function(cb){bo=cb},getRequest:function(cb){return aT(cb)},addPlugin:function(cb,cc){a[cb]=cc},setCustomVariable:function(cc,cb,cf,cd){var ce;if(!w(cd)){cd="visit"}if(!w(cb)){return}if(!w(cf)){cf=""}if(cc>0){cb=!n(cb)?String(cb):cb;cf=!n(cf)?String(cf):cf;ce=[cb.slice(0,bX),cf.slice(0,bX)];if(cd==="visit"||cd===2){Z();
+ag[cc]=ce}else{if(cd==="page"||cd===3){bg[cc]=ce}else{if(cd==="event"){ab[cc]=ce}}}}},getCustomVariable:function(cc,cd){var cb;if(!w(cd)){cd="visit"}if(cd==="page"||cd===3){cb=bg[cc]}else{if(cd==="event"){cb=ab[cc]}else{if(cd==="visit"||cd===2){Z();cb=ag[cc]}}}if(!w(cb)||(cb&&cb[0]==="")){return false}return cb},deleteCustomVariable:function(cb,cc){if(this.getCustomVariable(cb,cc)){this.setCustomVariable(cb,"","",cc)}},storeCustomVariablesInCookie:function(){a6=true},setLinkTrackingTimer:function(cb){bn=cb},setDownloadExtensions:function(cb){aU=cb},addDownloadExtensions:function(cb){aU+="|"+cb},setDomains:function(cb){bp=n(cb)?[cb]:cb;bp.push(bM)},setIgnoreClasses:function(cb){ai=n(cb)?[cb]:cb},setRequestMethod:function(cb){bs=cb||bq},setRequestContentType:function(cb){aK=cb||bc},setReferrerUrl:function(cb){bu=cb},setCustomUrl:function(cb){a7=bL(b4,cb)},setDocumentTitle:function(cb){aS=cb},setAPIUrl:function(cb){ax=cb},setDownloadClasses:function(cb){bf=n(cb)?[cb]:cb},setLinkClasses:function(cb){aC=n(cb)?[cb]:cb
+},setCampaignNameKey:function(cb){aY=n(cb)?[cb]:cb},setCampaignKeywordKey:function(cb){aP=n(cb)?[cb]:cb},discardHashTag:function(cb){ak=cb},setCookieNamePrefix:function(cb){b2=cb;ag=ar()},setCookieDomain:function(cb){aq=y(cb);bk()},setCookiePath:function(cb){b3=cb;bk()},setVisitorCookieTimeout:function(cb){aw=cb*1000},setSessionCookieTimeout:function(cb){az=cb*1000},setReferralCookieTimeout:function(cb){ba=cb*1000},setConversionAttributionFirstReferrer:function(cb){a5=cb},disableCookies:function(){ao=true;bT.cookie="0"},deleteCookies:function(){W()},setDoNotTrack:function(cc){var cb=e.doNotTrack||e.msDoNotTrack;bW=cc&&(cb==="yes"||cb==="1");if(bW){this.disableCookies()}},addListener:function(cc,cb){bA(cc,cb)},enableLinkTracking:function(cb){bU=true;if(p){bd(cb)}else{E.push(function(){bd(cb)})}},enableJSErrorTracking:function(){if(b8){return}b8=true;var cb=G.onerror;G.onerror=function(cg,ce,cd,cf,cc){aM(function(){var ch="JavaScript Errors";var ci=ce+":"+cd;if(cf){ci+=":"+cf}al(ch,ci,cg)
+});if(cb){return cb(cg,ce,cd,cf,cc)}return false}},disablePerformanceTracking:function(){a1=false},setGenerationTimeMs:function(cb){aI=parseInt(cb,10)},setHeartBeatTimer:function(cd,cc){var cb=new Date();aj=cb.getTime()+cd*1000;aG=cc*1000},killFrame:function(){if(G.location!==G.top.location){G.top.location=G.location}},redirectFile:function(cb){if(G.location.protocol==="file:"){G.location=cb}},setCountPreRendered:function(cb){a0=cb},trackGoal:function(cb,cd,cc){aM(function(){bl(cb,cd,cc)})},trackLink:function(cc,cb,ce,cd){aM(function(){bO(cc,cb,ce,cd)})},trackPageView:function(cb,cc){ah=[];if(A(bS)){aM(function(){M(aa,ax,bS)})}else{aM(function(){be(cb,cc)})}},trackAllContentImpressions:function(){if(A(bS)){return}aM(function(){aA(function(){var cb=m.findContentNodes();var cc=aW(cb);ap(cc,bn)})})},trackVisibleContentImpressions:function(cb,cc){if(A(bS)){return}if(!w(cb)){cb=true}if(!w(cc)){cc=750}bv(cb,cc,this);aM(function(){aQ(function(){var cd=m.findContentNodes();var ce=bC(cd);ap(ce,bn)
+})})},trackContentImpression:function(cd,cb,cc){if(A(bS)){return}if(!cd){return}cb=cb||"Unknown";aM(function(){var ce=bN(cd,cb,cc);aZ(ce,bn)})},trackContentImpressionsWithinNode:function(cb){if(A(bS)||!cb){return}aM(function(){if(ay){aQ(function(){var cc=m.findContentNodesWithinNode(cb);var cd=bC(cc);ap(cd,bn)})}else{aA(function(){var cc=m.findContentNodesWithinNode(cb);var cd=aW(cc);ap(cd,bn)})}})},trackContentInteraction:function(cd,ce,cb,cc){if(A(bS)){return}if(!cd||!ce){return}cb=cb||"Unknown";aM(function(){var cf=b6(cd,ce,cb,cc);aZ(cf,bn)})},trackContentInteractionNode:function(cc,cb){if(A(bS)||!cc){return}aM(function(){var cd=aV(cc,cb);aZ(cd,bn)})},trackEvent:function(cc,ce,cb,cd){aM(function(){al(cc,ce,cb,cd)})},trackSiteSearch:function(cb,cd,cc){aM(function(){aN(cb,cd,cc)})},setEcommerceView:function(ce,cb,cd,cc){if(!w(cd)||!cd.length){cd=""}else{if(cd instanceof Array){cd=JSON2.stringify(cd)}}bg[5]=["_pkc",cd];if(w(cc)&&String(cc).length){bg[2]=["_pkp",cc]}if((!w(ce)||!ce.length)&&(!w(cb)||!cb.length)){return
+}if(w(ce)&&ce.length){bg[3]=["_pks",ce]}if(!w(cb)||!cb.length){cb=""}bg[4]=["_pkn",cb]},addEcommerceItem:function(cf,cb,cd,cc,ce){if(cf.length){bF[cf]=[cf,cb,cd,cc,ce]}},trackEcommerceOrder:function(cb,cf,ce,cd,cc,cg){bJ(cb,cf,ce,cd,cc,cg)},trackEcommerceCartUpdate:function(cb){b1(cb)}}}function v(){return{push:R}}U(G,"beforeunload",S,false);o();Date.prototype.getTimeAlias=Date.prototype.getTime;L=new D();var r={setTrackerUrl:1,setAPIUrl:1,setUserId:1,setSiteId:1,disableCookies:1,enableLinkTracking:1};var d;for(t=0;t<_paq.length;t++){d=_paq[t][0];if(r[d]){R(_paq[t]);delete _paq[t];if(r[d]>1){if(console!==undefined&&console&&console.error){console.error("The method "+d+' is registered more than once in "_paq" variable. Only the last call has an effect. Please have a look at the multiple Piwik trackers documentation: http://developer.piwik.org/guides/tracking-javascript-guide#multiple-piwik-trackers')}}r[d]++}}for(t=0;t<_paq.length;t++){if(_paq[t]){R(_paq[t])}}_paq=new v();c={addPlugin:function(W,X){a[W]=X
+},getTracker:function(W,X){if(!w(X)){X=this.getAsyncTracker().getSiteId()}if(!w(W)){W=this.getAsyncTracker().getTrackerUrl()}return new D(W,X)},getAsyncTracker:function(){return L}};if(typeof define==="function"&&define.amd){define("piwik",[],function(){return c})}return c}())}if(window&&window.piwikAsyncInit){window.piwikAsyncInit()}(function(){var a=(typeof AnalyticsTracker);if(a==="undefined"){AnalyticsTracker=Piwik}}());if(typeof piwik_log!=="function"){piwik_log=function(b,f,d,g){function a(h){try{return eval("piwik_"+h)}catch(i){}return}var c,e=Piwik.getTracker(d,f);e.setDocumentTitle(b);e.setCustomData(g);c=a("tracker_pause");if(c){e.setLinkTrackingTimer(c)}c=a("download_extensions");if(c){e.setDownloadExtensions(c)}c=a("hosts_alias");if(c){e.setDomains(c)}c=a("ignore_classes");if(c){e.setIgnoreClasses(c)}e.trackPageView();if(a("install_tracker")){piwik_track=function(i,k,j,h){e.setSiteId(k);e.setTrackerUrl(j);e.trackLink(i,h)};e.enableLinkTracking()}};
/*! @license-end */
}; \ No newline at end of file
diff --git a/plugins/Live/API.php b/plugins/Live/API.php
index ed11c6c277..9fc5b82b16 100644
--- a/plugins/Live/API.php
+++ b/plugins/Live/API.php
@@ -60,13 +60,56 @@ class API extends \Piwik\Plugin\API
* @param int $idSite Id Site
* @param int $lastMinutes Number of minutes to look back at
* @param bool|string $segment
+ * @param array $showColumns The columns to show / not to request. Eg 'visits', 'actions', ...
+ * @param array $hideColumns The columns to hide / not to request. Eg 'visits', 'actions', ...
* @return array( visits => N, actions => M, visitsConverted => P )
*/
- public function getCounters($idSite, $lastMinutes, $segment = false)
+ public function getCounters($idSite, $lastMinutes, $segment = false, $showColumns = array(), $hideColumns = array())
{
Piwik::checkUserHasViewAccess($idSite);
$model = new Model();
- return $model->queryCounters($idSite, $lastMinutes, $segment);
+
+ $counters = array();
+
+ $hasVisits = true;
+ if ($this->shouldColumnBePresentInResponse('visits', $showColumns, $hideColumns)) {
+ $counters['visits'] = $model->getNumVisits($idSite, $lastMinutes, $segment);
+ $hasVisits = !empty($counters['visits']);
+ }
+
+ if ($this->shouldColumnBePresentInResponse('actions', $showColumns, $hideColumns)) {
+ if ($hasVisits) {
+ $counters['actions'] = $model->getNumActions($idSite, $lastMinutes, $segment);
+ } else {
+ $counters['actions'] = 0;
+ }
+ }
+
+ if ($this->shouldColumnBePresentInResponse('visitors', $showColumns, $hideColumns)) {
+ if ($hasVisits) {
+ $counters['visitors'] = $model->getNumVisitors($idSite, $lastMinutes, $segment);
+ } else {
+ $counters['visitors'] = 0;
+ }
+ }
+
+ if ($this->shouldColumnBePresentInResponse('visitsConverted', $showColumns, $hideColumns)) {
+ if ($hasVisits) {
+ $counters['visitsConverted'] = $model->getNumVisitsConverted($idSite, $lastMinutes, $segment);
+ } else {
+ $counters['visitsConverted'] = 0;
+ }
+ }
+
+ return array($counters);
+ }
+
+ private function shouldColumnBePresentInResponse($column, $showColumns, $hideColumns)
+ {
+ $show = (empty($showColumns) || in_array($column, $showColumns));
+ $hide = in_array($column, $hideColumns);
+
+ return $show && !$hide;
}
/**
diff --git a/plugins/Live/Controller.php b/plugins/Live/Controller.php
index 421a0afb62..a2d3e44026 100644
--- a/plugins/Live/Controller.php
+++ b/plugins/Live/Controller.php
@@ -88,9 +88,9 @@ class Controller extends \Piwik\Plugin\Controller
private function setCounters($view)
{
$segment = Request::getRawSegmentFromRequest();
- $last30min = API::getInstance()->getCounters($this->idSite, $lastMinutes = 30, $segment);
+ $last30min = API::getInstance()->getCounters($this->idSite, $lastMinutes = 30, $segment, array('visits', 'actions'));
$last30min = $last30min[0];
- $today = API::getInstance()->getCounters($this->idSite, $lastMinutes = 24 * 60, $segment);
+ $today = API::getInstance()->getCounters($this->idSite, $lastMinutes = 24 * 60, $segment, array('visits', 'actions'));
$today = $today[0];
$view->visitorsCountHalfHour = $last30min['visits'];
$view->visitorsCountToday = $today['visits'];
diff --git a/plugins/Live/Model.php b/plugins/Live/Model.php
index 19a44ba1d6..0d1b0318fe 100644
--- a/plugins/Live/Model.php
+++ b/plugins/Live/Model.php
@@ -201,58 +201,101 @@ class Model
* @param $idSite
* @param $lastMinutes
* @param $segment
- * @return array
+ * @return int
* @throws Exception
*/
- public function queryCounters($idSite, $lastMinutes, $segment)
+ public function getNumActions($idSite, $lastMinutes, $segment)
{
- $lastMinutes = (int)$lastMinutes;
+ return $this->getLastMinutesCounterForQuery(
+ $idSite,
+ $lastMinutes,
+ $segment,
+ 'COUNT(*)',
+ 'log_link_visit_action',
+ 'log_link_visit_action.server_time >= ?'
+ );
+ }
- $counters = array(
- 'visits' => 0,
- 'actions' => 0,
- 'visitors' => 0,
- 'visitsConverted' => 0,
+ /**
+ * @param $idSite
+ * @param $lastMinutes
+ * @param $segment
+ * @return int
+ * @throws Exception
+ */
+ public function getNumVisitsConverted($idSite, $lastMinutes, $segment)
+ {
+ return $this->getLastMinutesCounterForQuery(
+ $idSite,
+ $lastMinutes,
+ $segment,
+ 'COUNT(*)',
+ 'log_conversion',
+ 'log_conversion.server_time >= ?'
);
+ }
+
+ /**
+ * @param $idSite
+ * @param $lastMinutes
+ * @param $segment
+ * @return int
+ * @throws Exception
+ */
+ public function getNumVisits($idSite, $lastMinutes, $segment)
+ {
+ return $this->getLastMinutesCounterForQuery(
+ $idSite,
+ $lastMinutes,
+ $segment,
+ 'COUNT(log_visit.visit_last_action_time)',
+ 'log_visit',
+ 'log_visit.visit_last_action_time >= ?'
+ );
+ }
+
+ /**
+ * @param $idSite
+ * @param $lastMinutes
+ * @param $segment
+ * @return int
+ * @throws Exception
+ */
+ public function getNumVisitors($idSite, $lastMinutes, $segment)
+ {
+ return $this->getLastMinutesCounterForQuery(
+ $idSite,
+ $lastMinutes,
+ $segment,
+ 'COUNT(DISTINCT log_visit.idvisitor)',
+ 'log_visit',
+ 'log_visit.visit_last_action_time >= ?'
+ );
+ }
+
+ private function getLastMinutesCounterForQuery($idSite, $lastMinutes, $segment, $select, $from, $where)
+ {
+ $lastMinutes = (int)$lastMinutes;
if (empty($lastMinutes)) {
- return array($counters);
+ return 0;
}
- list($whereIdSites, $idSites) = $this->getIdSitesWhereClause($idSite);
+ list($whereIdSites, $idSites) = $this->getIdSitesWhereClause($idSite, $from);
- $select = "count(*) as visits, COUNT(DISTINCT log_visit.idvisitor) as visitors";
- $where = $whereIdSites . "AND log_visit.visit_last_action_time >= ?";
- $bind = $idSites;
+ $bind = $idSites;
$bind[] = Date::factory(time() - $lastMinutes * 60)->toString('Y-m-d H:i:s');
- $segment = new Segment($segment, $idSite);
- $query = $segment->getSelectQuery($select, 'log_visit', $where, $bind);
-
- $data = Db::fetchAll($query['sql'], $query['bind']);
-
- $counters['visits'] = $data[0]['visits'];
- $counters['visitors'] = $data[0]['visitors'];
+ $where = $whereIdSites . "AND " . $where;
- $select = "count(*)";
- $from = 'log_link_visit_action';
- list($whereIdSites) = $this->getIdSitesWhereClause($idSite, $from);
- $where = $whereIdSites . "AND log_link_visit_action.server_time >= ?";
- $query = $segment->getSelectQuery($select, $from, $where, $bind);
- $counters['actions'] = Db::fetchOne($query['sql'], $query['bind']);
+ $segment = new Segment($segment, $idSite);
+ $query = $segment->getSelectQuery($select, $from, $where, $bind);
- $select = "count(*)";
- $from = 'log_conversion';
- list($whereIdSites) = $this->getIdSitesWhereClause($idSite, $from);
- $where = $whereIdSites . "AND log_conversion.server_time >= ?";
- $query = $segment->getSelectQuery($select, $from, $where, $bind);
- $counters['visitsConverted'] = Db::fetchOne($query['sql'], $query['bind']);
+ $numVisitors = Db::fetchOne($query['sql'], $query['bind']);
- return array($counters);
+ return $numVisitors;
}
-
-
/**
* @param $idSite
* @param string $table
diff --git a/plugins/Live/Reports/GetSimpleLastVisitCount.php b/plugins/Live/Reports/GetSimpleLastVisitCount.php
index 34ba773fa9..e2a17135c5 100644
--- a/plugins/Live/Reports/GetSimpleLastVisitCount.php
+++ b/plugins/Live/Reports/GetSimpleLastVisitCount.php
@@ -30,7 +30,8 @@ class GetSimpleLastVisitCount extends Base
{
$lastMinutes = Config::getInstance()->General[Controller::SIMPLE_VISIT_COUNT_WIDGET_LAST_MINUTES_CONFIG_KEY];
- $lastNData = Request::processRequest('Live.getCounters', array('lastMinutes' => $lastMinutes));
+ $params = array('lastMinutes' => $lastMinutes, 'showColumns' => array('visits', 'visitors', 'actions'));
+ $lastNData = Request::processRequest('Live.getCounters', $params);
$formatter = new Formatter();
diff --git a/plugins/Live/tests/System/APITest.php b/plugins/Live/tests/System/APITest.php
index 2c85088a19..4b65a5ae4e 100644
--- a/plugins/Live/tests/System/APITest.php
+++ b/plugins/Live/tests/System/APITest.php
@@ -70,6 +70,38 @@ class APITest extends SystemTestCase
$this->assertEquals($this->buildCounter(0, 0, 0, 0), $counters);
}
+ public function test_GetCounters_ShouldHideAllColumnsIfRequested()
+ {
+ $exampleCounter = $this->buildCounter(0, 0, 0, 0);
+ $counters = $this->api->getCounters($this->idSite, 5, false, array(), array_keys($exampleCounter[0]));
+ $this->assertEquals(array(array()), $counters);
+ }
+
+ public function test_GetCounters_ShouldHideSomeColumnsIfRequested()
+ {
+ $counters = $this->api->getCounters($this->idSite, 20, false, array(), array('visitsConverted', 'visitors'));
+ $this->assertEquals(array(array('visits' => 24, 'actions' => 60)), $counters);
+ }
+
+ public function test_GetCounters_ShouldShowAllColumnsIfRequested()
+ {
+ $counter = $this->buildCounter(24, 60, 20, 40);
+ $counters = $this->api->getCounters($this->idSite, 20, false, array_keys($counter[0]));
+ $this->assertEquals($counter, $counters);
+ }
+
+ public function test_GetCounters_ShouldShowSomeColumnsIfRequested()
+ {
+ $counters = $this->api->getCounters($this->idSite, 20, false, array('visits', 'actions'));
+ $this->assertEquals(array(array('visits' => 24, 'actions' => 60)), $counters);
+ }
+
+ public function test_GetCounters_ShouldHideColumnIfGivenInShowAndHide()
+ {
+ $counters = $this->api->getCounters($this->idSite, 20, false, array('visits', 'actions'), array('actions'));
+ $this->assertEquals(array(array('visits' => 24)), $counters);
+ }
+
private function trackSomeVisits()
{
$nowTimestamp = time();
diff --git a/tests/UI/expected-ui-screenshots b/tests/UI/expected-ui-screenshots
-Subproject 75ef889b855f7b410e6778702ee0a4dc10cabf6
+Subproject a214a89b26cd11c12c7544d624a017a502f83ed
diff --git a/tests/javascript/index.php b/tests/javascript/index.php
index 20fade48ea..072dd42538 100644
--- a/tests/javascript/index.php
+++ b/tests/javascript/index.php
@@ -2370,7 +2370,7 @@ function PiwikTest() {
}
test("User ID and Visitor UUID", function() {
- expect(16);
+ expect(19);
deleteCookies();
var userIdString = 'userid@mydomain.org';
@@ -2396,6 +2396,13 @@ function PiwikTest() {
var visitorId = tracker.getVisitorId();
equal(visitorId, tracker.getVisitorId(), "Visitor ID is the same when called multiple times");
+ // Check that setting an empty user id will not change the visitor ID
+ var userId = '';
+ equal(userId, tracker.getUserId(), "by default user ID is set to empty string");
+ tracker.setUserId(userId);
+ equal(userId, tracker.getUserId(), "after setting to empty string, user id is still empty");
+ equal(visitorId, tracker.getVisitorId(), "visitor id was not changed after setting empty user id");
+
// Building another 'tracker2' object so we can compare behavior to 'tracker'
var tracker2 = Piwik.getTracker();
equal(tracker.getVisitorId(), tracker2.getVisitorId(), "Visitor ID " + tracker.getVisitorId() + " is the same as Visitor ID 2 " + tracker2.getVisitorId());