Version Description
Download this release
Release Info
Developer | matomoteam |
Plugin | Matomo Analytics – Ethical Stats. Powerful Insights. |
Version | 1.1.2 |
Comparing to | |
See all releases |
Code changes from version 1.1.1 to 1.1.2
- app/core/Concurrency/Lock.php +19 -2
- app/core/Config/IniFileChain.php +27 -0
- app/core/DataAccess/ArchiveSelector.php +4 -1
- app/core/DataAccess/ArchivingDbAdapter.php +1 -10
- app/core/DataAccess/Model.php +1 -1
- app/core/Tracker/FingerprintSalt.php +88 -0
- app/core/Tracker/PageUrl.php +2 -3
- app/core/Tracker/Request.php +10 -10
- app/core/Tracker/Settings.php +35 -3
- app/core/Tracker/Visit.php +2 -1
- app/core/Tracker/VisitorRecognizer.php +31 -0
- app/core/Updates/3.13.6-b1.php +3 -0
- app/core/Version.php +1 -1
- app/plugins/CoreAdminHome/Tasks.php +9 -0
- app/plugins/CoreHome/Columns/VisitLastActionTime.php +9 -1
- app/plugins/CustomPiwikJs/TrackingCode/PluginTrackerFiles.php +1 -3
- app/plugins/GeoIp2/Commands/ConvertRegionCodesToIso.php +124 -0
- app/plugins/Live/Controller.php +2 -0
- app/plugins/Morpheus/stylesheets/uibase/_header.less +0 -11
- app/plugins/Referrers/Columns/Base.php +55 -0
- app/plugins/SitesManager/SitesManager.php +10 -0
- app/plugins/UsersManager/API.php +8 -1
- app/plugins/UsersManager/UsersManager.php +5 -0
- assets/js/asset_manager_core_js.js +8 -4
- classes/WpMatomo/Admin/SystemReport.php +18 -2
- classes/WpMatomo/Admin/views/marketplace.php +5 -4
- classes/WpMatomo/Db/Settings.php +0 -2
- classes/WpMatomo/Db/WordPress.php +94 -1
- matomo.php +1 -1
- readme.txt +1 -1
app/core/Concurrency/Lock.php
CHANGED
@@ -8,11 +8,14 @@
|
|
8 |
*/
|
9 |
namespace Piwik\Concurrency;
|
10 |
|
|
|
11 |
use Piwik\Common;
|
|
|
12 |
|
13 |
class Lock
|
14 |
{
|
15 |
const MAX_KEY_LEN = 70;
|
|
|
16 |
|
17 |
/**
|
18 |
* @var LockBackend
|
@@ -24,18 +27,28 @@ class Lock
|
|
24 |
private $lockKey = null;
|
25 |
private $lockValue = null;
|
26 |
private $defaultTtl = null;
|
|
|
27 |
|
28 |
public function __construct(LockBackend $backend, $lockKeyStart, $defaultTtl = null)
|
29 |
{
|
30 |
$this->backend = $backend;
|
31 |
$this->lockKeyStart = $lockKeyStart;
|
32 |
$this->lockKey = $this->lockKeyStart;
|
33 |
-
$this->defaultTtl = $defaultTtl;
|
34 |
}
|
35 |
|
36 |
public function reexpireLock()
|
37 |
{
|
38 |
-
$this->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
}
|
40 |
|
41 |
public function getNumberOfAcquiredLocks()
|
@@ -81,6 +94,8 @@ class Lock
|
|
81 |
|
82 |
if ($locked) {
|
83 |
$this->lockValue = $lockValue;
|
|
|
|
|
84 |
}
|
85 |
|
86 |
return $locked;
|
@@ -125,6 +140,8 @@ class Lock
|
|
125 |
return false;
|
126 |
}
|
127 |
|
|
|
|
|
128 |
return true;
|
129 |
} else {
|
130 |
Common::printDebug('Lock is not acquired, cannot update expiration.');
|
8 |
*/
|
9 |
namespace Piwik\Concurrency;
|
10 |
|
11 |
+
use Piwik\ArchiveProcessor\ArchivingStatus;
|
12 |
use Piwik\Common;
|
13 |
+
use Piwik\Date;
|
14 |
|
15 |
class Lock
|
16 |
{
|
17 |
const MAX_KEY_LEN = 70;
|
18 |
+
const DEFAULT_TTL = 60;
|
19 |
|
20 |
/**
|
21 |
* @var LockBackend
|
27 |
private $lockKey = null;
|
28 |
private $lockValue = null;
|
29 |
private $defaultTtl = null;
|
30 |
+
private $lastExpireTime = null;
|
31 |
|
32 |
public function __construct(LockBackend $backend, $lockKeyStart, $defaultTtl = null)
|
33 |
{
|
34 |
$this->backend = $backend;
|
35 |
$this->lockKeyStart = $lockKeyStart;
|
36 |
$this->lockKey = $this->lockKeyStart;
|
37 |
+
$this->defaultTtl = $defaultTtl ?: self::DEFAULT_TTL;
|
38 |
}
|
39 |
|
40 |
public function reexpireLock()
|
41 |
{
|
42 |
+
$timeBetweenReexpires = $this->defaultTtl - ($this->defaultTtl / 4);
|
43 |
+
|
44 |
+
$now = Date::getNowTimestamp();
|
45 |
+
if (!empty($this->lastExpireTime) &&
|
46 |
+
$now <= $this->lastExpireTime + $timeBetweenReexpires
|
47 |
+
) {
|
48 |
+
return false;
|
49 |
+
}
|
50 |
+
|
51 |
+
return $this->expireLock($this->defaultTtl);
|
52 |
}
|
53 |
|
54 |
public function getNumberOfAcquiredLocks()
|
94 |
|
95 |
if ($locked) {
|
96 |
$this->lockValue = $lockValue;
|
97 |
+
$this->ttlUsed = $ttlInSeconds;
|
98 |
+
$this->lastExpireTime = Date::getNowTimestamp();
|
99 |
}
|
100 |
|
101 |
return $locked;
|
140 |
return false;
|
141 |
}
|
142 |
|
143 |
+
$this->lastExpireTime = Date::getNowTimestamp();
|
144 |
+
|
145 |
return true;
|
146 |
} else {
|
147 |
Common::printDebug('Lock is not acquired, cannot update expiration.');
|
app/core/Config/IniFileChain.php
CHANGED
@@ -97,9 +97,36 @@ class IniFileChain
|
|
97 |
*/
|
98 |
public function set($name, $value)
|
99 |
{
|
|
|
|
|
|
|
|
|
|
|
100 |
$this->mergedSettings[$name] = $value;
|
101 |
}
|
102 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
/**
|
104 |
* Returns all settings. Changes made to the array result will be reflected in the
|
105 |
* IniFileChain instance.
|
97 |
*/
|
98 |
public function set($name, $value)
|
99 |
{
|
100 |
+
$name = $this->replaceSectionInvalidChars($name);
|
101 |
+
if ($value !== null) {
|
102 |
+
$value = $this->replaceInvalidChars($value);
|
103 |
+
}
|
104 |
+
|
105 |
$this->mergedSettings[$name] = $value;
|
106 |
}
|
107 |
|
108 |
+
private function replaceInvalidChars($value)
|
109 |
+
{
|
110 |
+
if (is_array($value)) {
|
111 |
+
$result = [];
|
112 |
+
foreach ($value as $key => $arrayValue) {
|
113 |
+
$key = $this->replaceInvalidChars($key);
|
114 |
+
if (is_array($arrayValue)) {
|
115 |
+
$arrayValue = $this->replaceInvalidChars($arrayValue);
|
116 |
+
}
|
117 |
+
|
118 |
+
$result[$key] = $arrayValue;
|
119 |
+
}
|
120 |
+
return $result;
|
121 |
+
} else {
|
122 |
+
return preg_replace('/[^a-zA-Z0-9_\[\]-]/', '', $value);
|
123 |
+
}
|
124 |
+
}
|
125 |
+
|
126 |
+
private function replaceSectionInvalidChars($value)
|
127 |
+
{
|
128 |
+
return preg_replace('/[^a-zA-Z0-9_-]/', '', $value);
|
129 |
+
}
|
130 |
/**
|
131 |
* Returns all settings. Changes made to the array result will be reflected in the
|
132 |
* IniFileChain instance.
|
app/core/DataAccess/ArchiveSelector.php
CHANGED
@@ -89,11 +89,14 @@ class ArchiveSelector
|
|
89 |
) { // the archive cannot be considered valid for this request (has wrong done flag value)
|
90 |
return [false, $visits, $visitsConverted, true];
|
91 |
}
|
|
|
|
|
|
|
92 |
|
93 |
// the archive is too old
|
94 |
if ($minDatetimeArchiveProcessedUTC
|
95 |
&& isset($result['idarchive'])
|
96 |
-
&& Date::factory($result['ts_archived'])->isEarlier(
|
97 |
) {
|
98 |
return [false, $visits, $visitsConverted, true];
|
99 |
}
|
89 |
) { // the archive cannot be considered valid for this request (has wrong done flag value)
|
90 |
return [false, $visits, $visitsConverted, true];
|
91 |
}
|
92 |
+
if (!empty($minDatetimeArchiveProcessedUTC) && !is_object($minDatetimeArchiveProcessedUTC)) {
|
93 |
+
$minDatetimeArchiveProcessedUTC = Date::factory($minDatetimeArchiveProcessedUTC);
|
94 |
+
}
|
95 |
|
96 |
// the archive is too old
|
97 |
if ($minDatetimeArchiveProcessedUTC
|
98 |
&& isset($result['idarchive'])
|
99 |
+
&& Date::factory($result['ts_archived'])->isEarlier($minDatetimeArchiveProcessedUTC)
|
100 |
) {
|
101 |
return [false, $visits, $visitsConverted, true];
|
102 |
}
|
app/core/DataAccess/ArchivingDbAdapter.php
CHANGED
@@ -31,11 +31,6 @@ class ArchivingDbAdapter
|
|
31 |
*/
|
32 |
private $logger;
|
33 |
|
34 |
-
/**
|
35 |
-
* @var int
|
36 |
-
*/
|
37 |
-
private $lastReexpireTime = null;
|
38 |
-
|
39 |
public function __construct($wrapped, Lock $archivingLock = null, LoggerInterface $logger = null)
|
40 |
{
|
41 |
$this->wrapped = $wrapped;
|
@@ -107,11 +102,7 @@ class ArchivingDbAdapter
|
|
107 |
private function reexpireLock()
|
108 |
{
|
109 |
if ($this->archivingLock) {
|
110 |
-
$
|
111 |
-
if ($this->lastReexpireTime + $timeBetweenReexpires < time()) {
|
112 |
-
$this->archivingLock->reexpireLock();
|
113 |
-
$this->lastReexpireTime = time();
|
114 |
-
}
|
115 |
}
|
116 |
}
|
117 |
}
|
31 |
*/
|
32 |
private $logger;
|
33 |
|
|
|
|
|
|
|
|
|
|
|
34 |
public function __construct($wrapped, Lock $archivingLock = null, LoggerInterface $logger = null)
|
35 |
{
|
36 |
$this->wrapped = $wrapped;
|
102 |
private function reexpireLock()
|
103 |
{
|
104 |
if ($this->archivingLock) {
|
105 |
+
$this->archivingLock->reexpireLock();
|
|
|
|
|
|
|
|
|
106 |
}
|
107 |
}
|
108 |
}
|
app/core/DataAccess/Model.php
CHANGED
@@ -59,7 +59,7 @@ class Model
|
|
59 |
FROM `$archiveTable`
|
60 |
WHERE name LIKE 'done%'
|
61 |
AND `value` NOT IN (" . ArchiveWriter::DONE_ERROR . ")
|
62 |
-
GROUP BY idsite, date1, date2, period, name";
|
63 |
|
64 |
$archiveIds = array();
|
65 |
|
59 |
FROM `$archiveTable`
|
60 |
WHERE name LIKE 'done%'
|
61 |
AND `value` NOT IN (" . ArchiveWriter::DONE_ERROR . ")
|
62 |
+
GROUP BY idsite, date1, date2, period, name HAVING count(*) > 1";
|
63 |
|
64 |
$archiveIds = array();
|
65 |
|
app/core/Tracker/FingerprintSalt.php
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Matomo - free/libre analytics platform
|
4 |
+
*
|
5 |
+
* @link https://matomo.org
|
6 |
+
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
7 |
+
*
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Piwik\Tracker;
|
11 |
+
|
12 |
+
use Piwik\Common;
|
13 |
+
use Piwik\Date;
|
14 |
+
use Piwik\Exception\InvalidRequestParameterException;
|
15 |
+
use Piwik\Exception\UnexpectedWebsiteFoundException;
|
16 |
+
use Piwik\Option;
|
17 |
+
use Piwik\Piwik;
|
18 |
+
use Piwik\SettingsServer;
|
19 |
+
use Piwik\Site;
|
20 |
+
use Piwik\Db as PiwikDb;
|
21 |
+
|
22 |
+
class FingerprintSalt
|
23 |
+
{
|
24 |
+
const OPTION_PREFIX = 'fingerprint_salt_';
|
25 |
+
const DELETE_FINGERPRINT_OLDER_THAN_SECONDS = 432000; // 5 days in seconds
|
26 |
+
|
27 |
+
public function generateSalt()
|
28 |
+
{
|
29 |
+
return Common::getRandomString(32);
|
30 |
+
}
|
31 |
+
|
32 |
+
public function deleteOldSalts()
|
33 |
+
{
|
34 |
+
// we want to make sure to delete salts that were created more than three days ago as they are likely not in
|
35 |
+
// use anymore. We should delete them to ensure the fingerprint is truly random for each day because if we used
|
36 |
+
// eg the regular salt then it would technically still be possible to try and regenerate the fingerprint based
|
37 |
+
// on certain information.
|
38 |
+
// Typically, only the salts for today and yesterday are used. However, if someone was to import historical data
|
39 |
+
// for the same day and this takes more than five days, then it could technically happen that we delete a
|
40 |
+
// fingerprint that is still in use now and as such after deletion a few visitors would have a new configId
|
41 |
+
// within one visit and such a new visit would be created. That should be very much edge case though.
|
42 |
+
$deleteSaltsCreatedBefore = Date::getNowTimestamp() - self::DELETE_FINGERPRINT_OLDER_THAN_SECONDS;
|
43 |
+
$options = Option::getLike(self::OPTION_PREFIX . '%');
|
44 |
+
$deleted = array();
|
45 |
+
foreach ($options as $name => $value) {
|
46 |
+
$value = $this->decode($value);
|
47 |
+
if (empty($value['time']) || $value['time'] < $deleteSaltsCreatedBefore) {
|
48 |
+
Option::delete($name);
|
49 |
+
$deleted[] = $name;
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
return $deleted;
|
54 |
+
}
|
55 |
+
|
56 |
+
public function getDateString(Date $date, $timezone)
|
57 |
+
{
|
58 |
+
$dateString = Date::factory($date->getTimestampUTC(), $timezone)->toString();
|
59 |
+
return $dateString;
|
60 |
+
}
|
61 |
+
|
62 |
+
private function encode($value)
|
63 |
+
{
|
64 |
+
return json_encode($value);
|
65 |
+
}
|
66 |
+
|
67 |
+
private function decode($value)
|
68 |
+
{
|
69 |
+
return @json_decode($value, true);
|
70 |
+
}
|
71 |
+
|
72 |
+
public function getSalt($dateString, $idSite)
|
73 |
+
{
|
74 |
+
$fingerprintSaltKey = self::OPTION_PREFIX . (int) $idSite . '_' . $dateString;
|
75 |
+
$salt = Option::get($fingerprintSaltKey);
|
76 |
+
if (!empty($salt)) {
|
77 |
+
$salt = $this->decode($salt);
|
78 |
+
}
|
79 |
+
if (empty($salt['value'])) {
|
80 |
+
$salt = array(
|
81 |
+
'value' => $this->generateSalt(),
|
82 |
+
'time' => Date::getNowTimestamp()
|
83 |
+
);
|
84 |
+
Option::set($fingerprintSaltKey, $this->encode($salt));
|
85 |
+
}
|
86 |
+
return $salt['value'];
|
87 |
+
}
|
88 |
+
}
|
app/core/Tracker/PageUrl.php
CHANGED
@@ -36,14 +36,13 @@ class PageUrl
|
|
36 |
* @param $idSite
|
37 |
* @return bool|string Returned URL is HTML entities decoded
|
38 |
*/
|
39 |
-
public static function excludeQueryParametersFromUrl($originalUrl, $idSite)
|
40 |
{
|
41 |
$originalUrl = self::cleanupUrl($originalUrl);
|
42 |
|
43 |
$parsedUrl = @parse_url($originalUrl);
|
44 |
$parsedUrl = self::cleanupHostAndHashTag($parsedUrl, $idSite);
|
45 |
-
|
46 |
-
|
47 |
if (empty($parsedUrl['query'])) {
|
48 |
if (empty($parsedUrl['fragment'])) {
|
49 |
return UrlHelper::getParseUrlReverse($parsedUrl);
|
36 |
* @param $idSite
|
37 |
* @return bool|string Returned URL is HTML entities decoded
|
38 |
*/
|
39 |
+
public static function excludeQueryParametersFromUrl($originalUrl, $idSite, $additionalParametersToExclude = [])
|
40 |
{
|
41 |
$originalUrl = self::cleanupUrl($originalUrl);
|
42 |
|
43 |
$parsedUrl = @parse_url($originalUrl);
|
44 |
$parsedUrl = self::cleanupHostAndHashTag($parsedUrl, $idSite);
|
45 |
+
$parametersToExclude = array_merge(self::getQueryParametersToExclude($idSite), $additionalParametersToExclude);
|
|
|
46 |
if (empty($parsedUrl['query'])) {
|
47 |
if (empty($parsedUrl['fragment'])) {
|
48 |
return UrlHelper::getParseUrlReverse($parsedUrl);
|
app/core/Tracker/Request.php
CHANGED
@@ -195,6 +195,16 @@ class Request
|
|
195 |
return false;
|
196 |
}
|
197 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
Piwik::postEvent('Request.initAuthenticationObject');
|
199 |
|
200 |
/** @var \Piwik\Auth $auth */
|
@@ -209,16 +219,6 @@ class Request
|
|
209 |
return true;
|
210 |
}
|
211 |
|
212 |
-
// Now checking the list of admin token_auth cached in the Tracker config file
|
213 |
-
if (!empty($idSite) && $idSite > 0) {
|
214 |
-
$website = Cache::getCacheWebsiteAttributes($idSite);
|
215 |
-
$hashedToken = UsersManager::hashTrackingToken((string) $tokenAuth, $idSite);
|
216 |
-
|
217 |
-
if (array_key_exists('tracking_token_auth', $website)
|
218 |
-
&& in_array($hashedToken, $website['tracking_token_auth'], true)) {
|
219 |
-
return true;
|
220 |
-
}
|
221 |
-
}
|
222 |
|
223 |
Common::printDebug("WARNING! token_auth = $tokenAuth is not valid, Super User / Admin / Write was NOT authenticated");
|
224 |
|
195 |
return false;
|
196 |
}
|
197 |
|
198 |
+
// Now checking the list of admin token_auth cached in the Tracker config file
|
199 |
+
if (!empty($idSite) && $idSite > 0) {
|
200 |
+
$website = Cache::getCacheWebsiteAttributes($idSite);
|
201 |
+
$hashedToken = UsersManager::hashTrackingToken((string) $tokenAuth, $idSite);
|
202 |
+
|
203 |
+
if (array_key_exists('tracking_token_auth', $website)
|
204 |
+
&& in_array($hashedToken, $website['tracking_token_auth'], true)) {
|
205 |
+
return true;
|
206 |
+
}
|
207 |
+
}
|
208 |
Piwik::postEvent('Request.initAuthenticationObject');
|
209 |
|
210 |
/** @var \Piwik\Auth $auth */
|
219 |
return true;
|
220 |
}
|
221 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
|
223 |
Common::printDebug("WARNING! token_auth = $tokenAuth is not valid, Super User / Admin / Write was NOT authenticated");
|
224 |
|
app/core/Tracker/Settings.php
CHANGED
@@ -10,6 +10,10 @@ namespace Piwik\Tracker;
|
|
10 |
|
11 |
use Piwik\Config;
|
12 |
use Piwik\Container\StaticContainer;
|
|
|
|
|
|
|
|
|
13 |
use Piwik\Tracker;
|
14 |
use Piwik\DeviceDetector\DeviceDetectorFactory;
|
15 |
use Piwik\SettingsPiwik;
|
@@ -57,6 +61,31 @@ class Settings // TODO: merge w/ visitor recognizer or make it it's own service.
|
|
57 |
}
|
58 |
|
59 |
$browserLang = substr($request->getBrowserLanguage(), 0, 20); // limit the length of this string to match db
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
|
61 |
return $this->getConfigHash(
|
62 |
$request,
|
@@ -74,7 +103,8 @@ class Settings // TODO: merge w/ visitor recognizer or make it it's own service.
|
|
74 |
$plugin_Silverlight,
|
75 |
$plugin_Cookie,
|
76 |
$ipAddress,
|
77 |
-
$browserLang
|
|
|
78 |
}
|
79 |
|
80 |
/**
|
@@ -96,12 +126,13 @@ class Settings // TODO: merge w/ visitor recognizer or make it it's own service.
|
|
96 |
* @param $plugin_Cookie
|
97 |
* @param $ip
|
98 |
* @param $browserLang
|
|
|
99 |
* @return string
|
100 |
*/
|
101 |
protected function getConfigHash(Request $request, $os, $browserName, $browserVersion, $plugin_Flash, $plugin_Java,
|
102 |
$plugin_Director, $plugin_Quicktime, $plugin_RealPlayer, $plugin_PDF,
|
103 |
$plugin_WindowsMedia, $plugin_Gears, $plugin_Silverlight, $plugin_Cookie, $ip,
|
104 |
-
$browserLang)
|
105 |
{
|
106 |
// prevent the config hash from being the same, across different Piwik instances
|
107 |
// (limits ability of different Piwik instances to cross-match users)
|
@@ -114,7 +145,8 @@ class Settings // TODO: merge w/ visitor recognizer or make it it's own service.
|
|
114 |
. $plugin_WindowsMedia . $plugin_Gears . $plugin_Silverlight . $plugin_Cookie
|
115 |
. $ip
|
116 |
. $browserLang
|
117 |
-
. $salt
|
|
|
118 |
|
119 |
if (!$this->isSameFingerprintsAcrossWebsites) {
|
120 |
$configString .= $request->getIdSite();
|
10 |
|
11 |
use Piwik\Config;
|
12 |
use Piwik\Container\StaticContainer;
|
13 |
+
use Piwik\Date;
|
14 |
+
use Piwik\Option;
|
15 |
+
use Piwik\SettingsServer;
|
16 |
+
use Piwik\Site;
|
17 |
use Piwik\Tracker;
|
18 |
use Piwik\DeviceDetector\DeviceDetectorFactory;
|
19 |
use Piwik\SettingsPiwik;
|
61 |
}
|
62 |
|
63 |
$browserLang = substr($request->getBrowserLanguage(), 0, 20); // limit the length of this string to match db
|
64 |
+
$trackerConfig = Config::getInstance()->Tracker;
|
65 |
+
|
66 |
+
$fingerprintSalt = '';
|
67 |
+
|
68 |
+
// fingerprint salt won't work when across multiple sites since all sites could have different timezones
|
69 |
+
// also cant add fingerprint salt for a specific day when we dont create new visit after midnight
|
70 |
+
if (!$this->isSameFingerprintsAcrossWebsites && !empty($trackerConfig['create_new_visit_after_midnight'])) {
|
71 |
+
$cache = Cache::getCacheWebsiteAttributes($request->getIdSite());
|
72 |
+
$date = Date::factory((int) $request->getCurrentTimestamp());
|
73 |
+
$fingerprintSaltKey = new FingerprintSalt();
|
74 |
+
$dateString = $fingerprintSaltKey->getDateString($date, $cache['timezone']);
|
75 |
+
|
76 |
+
if (!empty($cache[FingerprintSalt::OPTION_PREFIX . $dateString])) {
|
77 |
+
$fingerprintSalt = $cache[FingerprintSalt::OPTION_PREFIX . $dateString];
|
78 |
+
} else {
|
79 |
+
// we query the DB directly for requests older than 2-3 days...
|
80 |
+
$fingerprintSalt = $fingerprintSaltKey->getSalt($dateString, $request->getIdSite());
|
81 |
+
}
|
82 |
+
|
83 |
+
$fingerprintSalt .= $dateString;
|
84 |
+
|
85 |
+
if (defined('PIWIK_TEST_MODE') && PIWIK_TEST_MODE) {
|
86 |
+
$fingerprintSalt = ''; // use fixed value so they don't change randomly in tests
|
87 |
+
}
|
88 |
+
}
|
89 |
|
90 |
return $this->getConfigHash(
|
91 |
$request,
|
103 |
$plugin_Silverlight,
|
104 |
$plugin_Cookie,
|
105 |
$ipAddress,
|
106 |
+
$browserLang,
|
107 |
+
$fingerprintSalt);
|
108 |
}
|
109 |
|
110 |
/**
|
126 |
* @param $plugin_Cookie
|
127 |
* @param $ip
|
128 |
* @param $browserLang
|
129 |
+
* @param $fingerprintHash
|
130 |
* @return string
|
131 |
*/
|
132 |
protected function getConfigHash(Request $request, $os, $browserName, $browserVersion, $plugin_Flash, $plugin_Java,
|
133 |
$plugin_Director, $plugin_Quicktime, $plugin_RealPlayer, $plugin_PDF,
|
134 |
$plugin_WindowsMedia, $plugin_Gears, $plugin_Silverlight, $plugin_Cookie, $ip,
|
135 |
+
$browserLang, $fingerprintHash)
|
136 |
{
|
137 |
// prevent the config hash from being the same, across different Piwik instances
|
138 |
// (limits ability of different Piwik instances to cross-match users)
|
145 |
. $plugin_WindowsMedia . $plugin_Gears . $plugin_Silverlight . $plugin_Cookie
|
146 |
. $ip
|
147 |
. $browserLang
|
148 |
+
. $salt
|
149 |
+
. $fingerprintHash;
|
150 |
|
151 |
if (!$this->isSameFingerprintsAcrossWebsites) {
|
152 |
$configString .= $request->getIdSite();
|
app/core/Tracker/Visit.php
CHANGED
@@ -243,7 +243,8 @@ class Visit implements VisitInterface
|
|
243 |
foreach ($this->requestProcessors as $processor) {
|
244 |
$processor->onExistingVisit($valuesToUpdate, $this->visitProperties, $this->request);
|
245 |
}
|
246 |
-
|
|
|
247 |
$this->updateExistingVisit($valuesToUpdate);
|
248 |
|
249 |
$this->visitProperties->setProperty('visit_last_action_time', $this->request->getCurrentTimestamp());
|
243 |
foreach ($this->requestProcessors as $processor) {
|
244 |
$processor->onExistingVisit($valuesToUpdate, $this->visitProperties, $this->request);
|
245 |
}
|
246 |
+
$visitorRecognizer = StaticContainer::get(VisitorRecognizer::class);
|
247 |
+
$valuesToUpdate = $visitorRecognizer->removeUnchangedValues($this->visitProperties, $valuesToUpdate);
|
248 |
$this->updateExistingVisit($valuesToUpdate);
|
249 |
|
250 |
$this->visitProperties->setProperty('visit_last_action_time', $this->request->getCurrentTimestamp());
|
app/core/Tracker/VisitorRecognizer.php
CHANGED
@@ -19,6 +19,8 @@ use Piwik\Tracker\Visit\VisitProperties;
|
|
19 |
*/
|
20 |
class VisitorRecognizer
|
21 |
{
|
|
|
|
|
22 |
/**
|
23 |
* Local variable cache for the getVisitFieldsPersist() method.
|
24 |
*
|
@@ -105,6 +107,7 @@ class VisitorRecognizer
|
|
105 |
if ($visitRow
|
106 |
&& count($visitRow) > 0
|
107 |
) {
|
|
|
108 |
$visitProperties->setProperty('idvisitor', $visitRow['idvisitor']);
|
109 |
$visitProperties->setProperty('user_id', $visitRow['user_id']);
|
110 |
|
@@ -121,6 +124,34 @@ class VisitorRecognizer
|
|
121 |
}
|
122 |
}
|
123 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
public function updateVisitPropertiesFromLastVisitRow(VisitProperties $visitProperties)
|
125 |
{
|
126 |
// These values will be used throughout the request
|
19 |
*/
|
20 |
class VisitorRecognizer
|
21 |
{
|
22 |
+
const KEY_ORIGINAL_VISIT_ROW = 'originalVisit';
|
23 |
+
|
24 |
/**
|
25 |
* Local variable cache for the getVisitFieldsPersist() method.
|
26 |
*
|
107 |
if ($visitRow
|
108 |
&& count($visitRow) > 0
|
109 |
) {
|
110 |
+
$visitProperties->setProperty(self::KEY_ORIGINAL_VISIT_ROW, $visitRow);
|
111 |
$visitProperties->setProperty('idvisitor', $visitRow['idvisitor']);
|
112 |
$visitProperties->setProperty('user_id', $visitRow['user_id']);
|
113 |
|
124 |
}
|
125 |
}
|
126 |
|
127 |
+
public function removeUnchangedValues(VisitProperties $visitProperties, $visit)
|
128 |
+
{
|
129 |
+
$originalRow = $visitProperties->getProperty(self::KEY_ORIGINAL_VISIT_ROW);
|
130 |
+
|
131 |
+
if (empty($originalRow)) {
|
132 |
+
return $visit;
|
133 |
+
}
|
134 |
+
|
135 |
+
if (!empty($originalRow['idvisitor'])
|
136 |
+
&& !empty($visit['idvisitor'])
|
137 |
+
&& bin2hex($originalRow['idvisitor']) === bin2hex($visit['idvisitor'])) {
|
138 |
+
unset($visit['idvisitor']);
|
139 |
+
}
|
140 |
+
|
141 |
+
$fieldsToCompareValue = array('user_id', 'visit_last_action_time', 'visit_total_time');
|
142 |
+
foreach ($fieldsToCompareValue as $field) {
|
143 |
+
if (!empty($originalRow[$field])
|
144 |
+
&& !empty($visit[$field])
|
145 |
+
&& $visit[$field] == $originalRow[$field]) {
|
146 |
+
// we can't use === eg for visit_total_time which may be partially an integer and sometimes a string
|
147 |
+
// because we check for !empty things should still work as expected though
|
148 |
+
// (eg we wouldn't compare false with 0)
|
149 |
+
unset($visit[$field]);
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
return $visit;
|
154 |
+
}
|
155 |
public function updateVisitPropertiesFromLastVisitRow(VisitProperties $visitProperties)
|
156 |
{
|
157 |
// These values will be used throughout the request
|
app/core/Updates/3.13.6-b1.php
CHANGED
@@ -20,6 +20,8 @@ class Updates_3_13_6_b1 extends PiwikUpdates
|
|
20 |
global $wpdb;
|
21 |
|
22 |
if ($wpdb->charset === 'utf8mb4') {
|
|
|
|
|
23 |
$db_settings = new \WpMatomo\Db\Settings();
|
24 |
$wpdb->query(sprintf('ALTER TABLE `%s` CHANGE `%s` `%s` %s',
|
25 |
$db_settings->prefix_table_name('session'),
|
@@ -54,6 +56,7 @@ class Updates_3_13_6_b1 extends PiwikUpdates
|
|
54 |
}
|
55 |
}
|
56 |
}
|
|
|
57 |
}
|
58 |
}
|
59 |
|
20 |
global $wpdb;
|
21 |
|
22 |
if ($wpdb->charset === 'utf8mb4') {
|
23 |
+
$save = $wpdb->show_errors(false);
|
24 |
+
|
25 |
$db_settings = new \WpMatomo\Db\Settings();
|
26 |
$wpdb->query(sprintf('ALTER TABLE `%s` CHANGE `%s` `%s` %s',
|
27 |
$db_settings->prefix_table_name('session'),
|
56 |
}
|
57 |
}
|
58 |
}
|
59 |
+
$wpdb->show_errors($save);
|
60 |
}
|
61 |
}
|
62 |
|
app/core/Version.php
CHANGED
@@ -20,7 +20,7 @@ final class Version
|
|
20 |
* The current Matomo version.
|
21 |
* @var string
|
22 |
*/
|
23 |
-
const VERSION = '3.13.6
|
24 |
|
25 |
public function isStableVersion($version)
|
26 |
{
|
20 |
* The current Matomo version.
|
21 |
* @var string
|
22 |
*/
|
23 |
+
const VERSION = '3.13.6';
|
24 |
|
25 |
public function isStableVersion($version)
|
26 |
{
|
app/plugins/CoreAdminHome/Tasks.php
CHANGED
@@ -32,6 +32,7 @@ use Piwik\Scheduler\Schedule\SpecificTime;
|
|
32 |
use Piwik\Settings\Storage\Backend\MeasurableSettingsTable;
|
33 |
use Piwik\Tracker\Failures;
|
34 |
use Piwik\Site;
|
|
|
35 |
use Piwik\Tracker\Visit\ReferrerSpamFilter;
|
36 |
use Psr\Log\LoggerInterface;
|
37 |
use Piwik\SettingsPiwik;
|
@@ -80,6 +81,7 @@ class Tasks extends \Piwik\Plugin\Tasks
|
|
80 |
|
81 |
$this->daily('cleanupTrackingFailures', null, self::LOWEST_PRIORITY);
|
82 |
$this->weekly('notifyTrackingFailures', null, self::LOWEST_PRIORITY);
|
|
|
83 |
|
84 |
if(SettingsPiwik::isInternetEnabled() === true){
|
85 |
$this->weekly('updateSpammerBlacklist');
|
@@ -88,6 +90,13 @@ class Tasks extends \Piwik\Plugin\Tasks
|
|
88 |
$this->scheduleTrackingCodeReminderChecks();
|
89 |
}
|
90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
public function invalidateOutdatedArchives()
|
92 |
{
|
93 |
if (!Rules::isBrowserTriggerEnabled()) {
|
32 |
use Piwik\Settings\Storage\Backend\MeasurableSettingsTable;
|
33 |
use Piwik\Tracker\Failures;
|
34 |
use Piwik\Site;
|
35 |
+
use Piwik\Tracker\FingerprintSalt;
|
36 |
use Piwik\Tracker\Visit\ReferrerSpamFilter;
|
37 |
use Psr\Log\LoggerInterface;
|
38 |
use Piwik\SettingsPiwik;
|
81 |
|
82 |
$this->daily('cleanupTrackingFailures', null, self::LOWEST_PRIORITY);
|
83 |
$this->weekly('notifyTrackingFailures', null, self::LOWEST_PRIORITY);
|
84 |
+
$this->daily('deleteOldFingerprintSalts', null, self::HIGH_PRIORITY);
|
85 |
|
86 |
if(SettingsPiwik::isInternetEnabled() === true){
|
87 |
$this->weekly('updateSpammerBlacklist');
|
90 |
$this->scheduleTrackingCodeReminderChecks();
|
91 |
}
|
92 |
|
93 |
+
|
94 |
+
|
95 |
+
public function deleteOldFingerprintSalts()
|
96 |
+
{
|
97 |
+
StaticContainer::get(FingerprintSalt::class)->deleteOldSalts();
|
98 |
+
}
|
99 |
+
|
100 |
public function invalidateOutdatedArchives()
|
101 |
{
|
102 |
if (!Rules::isBrowserTriggerEnabled()) {
|
app/plugins/CoreHome/Columns/VisitLastActionTime.php
CHANGED
@@ -14,6 +14,7 @@ use Piwik\Tracker\Action;
|
|
14 |
use Piwik\Tracker\Request;
|
15 |
use Piwik\Tracker\Visitor;
|
16 |
use Piwik\Metrics\Formatter;
|
|
|
17 |
|
18 |
require_once PIWIK_INCLUDE_PATH . '/plugins/VisitTime/functions.php';
|
19 |
|
@@ -67,7 +68,14 @@ class VisitLastActionTime extends VisitDimension
|
|
67 |
if ($request->getParam('ping') == 1) {
|
68 |
return false;
|
69 |
}
|
70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
return $this->onNewVisit($request, $visitor, $action);
|
72 |
}
|
73 |
}
|
14 |
use Piwik\Tracker\Request;
|
15 |
use Piwik\Tracker\Visitor;
|
16 |
use Piwik\Metrics\Formatter;
|
17 |
+
use Piwik\Tracker\VisitorRecognizer;
|
18 |
|
19 |
require_once PIWIK_INCLUDE_PATH . '/plugins/VisitTime/functions.php';
|
20 |
|
68 |
if ($request->getParam('ping') == 1) {
|
69 |
return false;
|
70 |
}
|
71 |
+
$originalVisit = $visitor->getVisitorColumn(VisitorRecognizer::KEY_ORIGINAL_VISIT_ROW);
|
72 |
+
|
73 |
+
if (!empty($originalVisit['visit_last_action_time'])
|
74 |
+
&& Date::factory($originalVisit['visit_last_action_time'])->getTimestamp() > $request->getCurrentTimestamp()) {
|
75 |
+
// make sure to not set visit_last_action_time to an earlier time eg if tracking requests aren't sent in order
|
76 |
+
return $originalVisit['visit_last_action_time'];
|
77 |
+
}
|
78 |
+
|
79 |
return $this->onNewVisit($request, $visitor, $action);
|
80 |
}
|
81 |
}
|
app/plugins/CustomPiwikJs/TrackingCode/PluginTrackerFiles.php
CHANGED
@@ -41,9 +41,7 @@ class PluginTrackerFiles
|
|
41 |
$dirs = array();
|
42 |
$manager = Plugin\Manager::getInstance();
|
43 |
foreach ($manager->getPluginsLoadedAndActivated() as $pluginName => $plugin) {
|
44 |
-
|
45 |
-
$dirs[$pluginName] = rtrim(Plugin\Manager::getPluginDirectory($pluginName), '/') . '/';
|
46 |
-
}
|
47 |
}
|
48 |
return $dirs;
|
49 |
}
|
41 |
$dirs = array();
|
42 |
$manager = Plugin\Manager::getInstance();
|
43 |
foreach ($manager->getPluginsLoadedAndActivated() as $pluginName => $plugin) {
|
44 |
+
$dirs[$pluginName] = rtrim(Plugin\Manager::getPluginDirectory($pluginName), '/') . '/';
|
|
|
|
|
45 |
}
|
46 |
return $dirs;
|
47 |
}
|
app/plugins/GeoIp2/Commands/ConvertRegionCodesToIso.php
ADDED
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Piwik - free/libre analytics platform
|
4 |
+
*
|
5 |
+
* @link https://matomo.org
|
6 |
+
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
7 |
+
*
|
8 |
+
*/
|
9 |
+
namespace Piwik\Plugins\GeoIp2\Commands;
|
10 |
+
|
11 |
+
use Piwik\Common;
|
12 |
+
use Piwik\Db;
|
13 |
+
use Piwik\DbHelper;
|
14 |
+
use Piwik\Option;
|
15 |
+
use Piwik\Plugin\ConsoleCommand;
|
16 |
+
use Piwik\Plugins\UserCountry\LocationProvider;
|
17 |
+
use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
|
18 |
+
use Symfony\Component\Console\Input\InputInterface;
|
19 |
+
use Symfony\Component\Console\Output\OutputInterface;
|
20 |
+
|
21 |
+
class ConvertRegionCodesToIso extends ConsoleCommand
|
22 |
+
{
|
23 |
+
const OPTION_NAME = 'regioncodes_converted';
|
24 |
+
const MAPPING_TABLE_NAME = 'fips2iso';
|
25 |
+
|
26 |
+
protected function configure()
|
27 |
+
{
|
28 |
+
$this->setName('usercountry:convert-region-codes');
|
29 |
+
$this->setDescription("Convert FIPS region codes saved by GeoIP legacy provider to ISO.");
|
30 |
+
}
|
31 |
+
|
32 |
+
public function isEnabled()
|
33 |
+
{
|
34 |
+
return false;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @param InputInterface $input
|
39 |
+
* @param OutputInterface $output
|
40 |
+
* @return void|int
|
41 |
+
*/
|
42 |
+
protected function execute(InputInterface $input, OutputInterface $output)
|
43 |
+
{
|
44 |
+
// chick if option is set to disable second run
|
45 |
+
if (Option::get(self::OPTION_NAME)) {
|
46 |
+
$output->writeln('Converting region codes already done.');
|
47 |
+
return;
|
48 |
+
}
|
49 |
+
|
50 |
+
$output->setDecorated(true);
|
51 |
+
|
52 |
+
$output->write('Creating mapping table in database');
|
53 |
+
|
54 |
+
Db::query('DROP table if exists ' . self::MAPPING_TABLE_NAME);
|
55 |
+
|
56 |
+
DbHelper::createTable(self::MAPPING_TABLE_NAME,
|
57 |
+
"`country_code` VARCHAR(2) NOT NULL,
|
58 |
+
`fips_code` VARCHAR(2) NOT NULL,
|
59 |
+
`iso_code` VARCHAR(4) NULL DEFAULT NULL,
|
60 |
+
PRIMARY KEY (`country_code`, `fips_code`)");
|
61 |
+
|
62 |
+
$output->writeln(' <fg=green>✓</>');
|
63 |
+
|
64 |
+
$mappings = include __DIR__ . '/../data/regionMapping.php';
|
65 |
+
|
66 |
+
$output->write('Inserting mapping data ');
|
67 |
+
|
68 |
+
$counter = 0;
|
69 |
+
foreach ($mappings as $country => $regionMapping) {
|
70 |
+
foreach ($regionMapping as $fips => $iso) {
|
71 |
+
if ($fips == $iso) {
|
72 |
+
continue; // nothing needs to be changed, so ignore the mapping
|
73 |
+
}
|
74 |
+
|
75 |
+
Db::query('INSERT INTO `'.Common::prefixTable(self::MAPPING_TABLE_NAME).'` VALUES (?, ?, ?)', [$country, $fips, $iso]);
|
76 |
+
$counter++;
|
77 |
+
if ($counter%50 == 0) {
|
78 |
+
$output->write('.');
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
$output->writeln(' <fg=green>✓</>');
|
84 |
+
|
85 |
+
$output->writeln('Updating Matomo log tables:');
|
86 |
+
|
87 |
+
$activationTime = Option::get(GeoIp2::SWITCH_TO_ISO_REGIONS_OPTION_NAME);
|
88 |
+
$activationDateTime = date('Y-m-d H:i:s', $activationTime);
|
89 |
+
|
90 |
+
// fix country and region of tibet so it wil be updated correctly afterwards
|
91 |
+
$tibetFixQuery = 'UPDATE %s SET location_country = "cn", location_region = "14" WHERE location_country = "ti"';
|
92 |
+
|
93 |
+
// replace invalid country codes used by GeoIP Legacy
|
94 |
+
$fixInvalidCountriesQuery = 'UPDATE %s SET location_country = "" WHERE location_country IN("AP", "EU", "A1", "A2")';
|
95 |
+
|
96 |
+
$query = "UPDATE %s INNER JOIN %s ON location_country = country_code AND location_region = fips_code SET location_region = iso_code
|
97 |
+
WHERE `%s` < ?";
|
98 |
+
|
99 |
+
$logTables = ['log_visit' => 'visit_first_action_time', 'log_conversion' => 'server_time'];
|
100 |
+
|
101 |
+
foreach ($logTables as $logTable => $dateField) {
|
102 |
+
$output->write('- Updating ' . $logTable);
|
103 |
+
|
104 |
+
Db::query(sprintf($tibetFixQuery, Common::prefixTable($logTable)));
|
105 |
+
Db::query(sprintf($fixInvalidCountriesQuery, Common::prefixTable($logTable)));
|
106 |
+
|
107 |
+
$sql = sprintf($query, Common::prefixTable($logTable), Common::prefixTable(self::MAPPING_TABLE_NAME), $dateField);
|
108 |
+
Db::query($sql, $activationDateTime);
|
109 |
+
|
110 |
+
$output->writeln(' <fg=green>✓</>');
|
111 |
+
}
|
112 |
+
|
113 |
+
$output->write('Removing mapping table from database ');
|
114 |
+
Db::dropTables(Common::prefixTable(self::MAPPING_TABLE_NAME));
|
115 |
+
$output->writeln(' <fg=green>✓</>');
|
116 |
+
|
117 |
+
// save option to prevent a second run
|
118 |
+
Option::set(self::OPTION_NAME, true);
|
119 |
+
|
120 |
+
$output->writeln('All region codes converted.');
|
121 |
+
}
|
122 |
+
|
123 |
+
|
124 |
+
}
|
app/plugins/Live/Controller.php
CHANGED
@@ -12,6 +12,7 @@ use Piwik\API\Request;
|
|
12 |
use Piwik\Common;
|
13 |
use Piwik\Config;
|
14 |
use Piwik\Container\StaticContainer;
|
|
|
15 |
use Piwik\Piwik;
|
16 |
use Piwik\Plugins\Goals\API as APIGoals;
|
17 |
use Piwik\Plugins\Live\Visualizations\VisitorLog;
|
@@ -89,6 +90,7 @@ class Controller extends \Piwik\Plugin\Controller
|
|
89 |
$view = new View('@Live/getLastVisitsStart');
|
90 |
$view->idSite = (int) $this->idSite;
|
91 |
$error = '';
|
|
|
92 |
try {
|
93 |
$api = new Request("method=Live.getLastVisitsDetails&idSite={$this->idSite}&filter_limit=10&format=original&serialize=0&disable_generic_filters=1");
|
94 |
$visitors = $api->process();
|
12 |
use Piwik\Common;
|
13 |
use Piwik\Config;
|
14 |
use Piwik\Container\StaticContainer;
|
15 |
+
use Piwik\DataTable;
|
16 |
use Piwik\Piwik;
|
17 |
use Piwik\Plugins\Goals\API as APIGoals;
|
18 |
use Piwik\Plugins\Live\Visualizations\VisitorLog;
|
90 |
$view = new View('@Live/getLastVisitsStart');
|
91 |
$view->idSite = (int) $this->idSite;
|
92 |
$error = '';
|
93 |
+
$visitors = new DataTable();
|
94 |
try {
|
95 |
$api = new Request("method=Live.getLastVisitsDetails&idSite={$this->idSite}&filter_limit=10&format=original&serialize=0&disable_generic_filters=1");
|
96 |
$visitors = $api->process();
|
app/plugins/Morpheus/stylesheets/uibase/_header.less
CHANGED
@@ -18,17 +18,6 @@
|
|
18 |
}
|
19 |
}
|
20 |
|
21 |
-
// IE 10+
|
22 |
-
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
|
23 |
-
#root #logo {
|
24 |
-
width: 80px;
|
25 |
-
}
|
26 |
-
|
27 |
-
#root #logo img.default-piwik-logo {
|
28 |
-
width: 100%;
|
29 |
-
}
|
30 |
-
}
|
31 |
-
|
32 |
#javascriptDisabled,
|
33 |
#javascriptDisabled a {
|
34 |
font-weight: bold;
|
18 |
}
|
19 |
}
|
20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
#javascriptDisabled,
|
22 |
#javascriptDisabled a {
|
23 |
font-weight: bold;
|
app/plugins/Referrers/Columns/Base.php
CHANGED
@@ -118,6 +118,7 @@ abstract class Base extends VisitDimension
|
|
118 |
$this->nameReferrerAnalyzed .= rtrim($path, '/');
|
119 |
}
|
120 |
}
|
|
|
121 |
|
122 |
$referrerInformation = array(
|
123 |
'referer_type' => $this->typeReferrerAnalyzed,
|
@@ -137,6 +138,60 @@ abstract class Base extends VisitDimension
|
|
137 |
return $referrerInformation;
|
138 |
}
|
139 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
protected function getReferrerInformationFromRequest(Request $request, Visitor $visitor)
|
141 |
{
|
142 |
$referrerUrl = $request->getParam('urlref');
|
118 |
$this->nameReferrerAnalyzed .= rtrim($path, '/');
|
119 |
}
|
120 |
}
|
121 |
+
$this->excludeQueryParamsFromReferrerUrl();
|
122 |
|
123 |
$referrerInformation = array(
|
124 |
'referer_type' => $this->typeReferrerAnalyzed,
|
138 |
return $referrerInformation;
|
139 |
}
|
140 |
|
141 |
+
protected function excludeQueryParamsFromReferrerUrl()
|
142 |
+
{
|
143 |
+
$parametersToExclude = [];
|
144 |
+
|
145 |
+
if (!empty($this->referrerHost) && strpos($this->referrerHost, 'instagram.com') !== false) {
|
146 |
+
$parametersToExclude[] = 'e';
|
147 |
+
$parametersToExclude[] = 's';
|
148 |
+
}
|
149 |
+
if (!empty($this->referrerHost) && strpos($this->referrerHost, 'facebook.com') !== false) {
|
150 |
+
$parametersToExclude[] = 'h';
|
151 |
+
$parametersToExclude[] = 'p';
|
152 |
+
}
|
153 |
+
if (!empty($this->referrerHost) && (strpos($this->referrerHost, 'google.') !== false || strpos($this->referrerHost, 'googleusercontent.') !== false)) {
|
154 |
+
$parametersToExclude[] = 'ust';
|
155 |
+
$parametersToExclude[] = 'usg';
|
156 |
+
$parametersToExclude[] = 'usd';
|
157 |
+
$parametersToExclude[] = 'sa';
|
158 |
+
$parametersToExclude[] = 'sntz';
|
159 |
+
$parametersToExclude[] = 'ei';
|
160 |
+
$parametersToExclude[] = 'sa';
|
161 |
+
$parametersToExclude[] = 'bvm';
|
162 |
+
$parametersToExclude[] = 'usg';
|
163 |
+
$parametersToExclude[] = 'ved';
|
164 |
+
$parametersToExclude[] = 'client';
|
165 |
+
$parametersToExclude[] = 'channel';
|
166 |
+
}
|
167 |
+
|
168 |
+
if (!empty($this->referrerHost) && strpos($this->referrerHost, 'main.exoclick.com') !== false) {
|
169 |
+
$parametersToExclude[] = 'data';
|
170 |
+
$parametersToExclude[] = 'wpn';
|
171 |
+
}
|
172 |
+
if (!empty($this->referrerHost) && strpos($this->referrerHost, 'youtube.com') !== false) {
|
173 |
+
$parametersToExclude[] = 'redir_token';
|
174 |
+
$parametersToExclude[] = 'html_redirect';
|
175 |
+
$parametersToExclude[] = 'continuation';
|
176 |
+
$parametersToExclude[] = 'feature';
|
177 |
+
}
|
178 |
+
if (!empty($this->referrerHost) && strpos($this->referrerHost, 'bing.com') !== false) {
|
179 |
+
$parametersToExclude[] = 'cvid';
|
180 |
+
$parametersToExclude[] = 'refig';
|
181 |
+
$parametersToExclude[] = 'elv';
|
182 |
+
$parametersToExclude[] = 'plvar';
|
183 |
+
$parametersToExclude[] = 'setlang';
|
184 |
+
$parametersToExclude[] = 'qs';
|
185 |
+
$parametersToExclude[] = 'cc';
|
186 |
+
$parametersToExclude[] = 'mkt';
|
187 |
+
$parametersToExclude[] = 'PC';
|
188 |
+
$parametersToExclude[] = 'form';
|
189 |
+
$parametersToExclude[] = 'src';
|
190 |
+
}
|
191 |
+
|
192 |
+
$this->referrerUrl = PageUrl::excludeQueryParametersFromUrl($this->referrerUrl, $this->idsite, $parametersToExclude);
|
193 |
+
}
|
194 |
+
|
195 |
protected function getReferrerInformationFromRequest(Request $request, Visitor $visitor)
|
196 |
{
|
197 |
$referrerUrl = $request->getParam('urlref');
|
app/plugins/SitesManager/SitesManager.php
CHANGED
@@ -13,12 +13,14 @@ use Piwik\API\Request;
|
|
13 |
use Piwik\Common;
|
14 |
use Piwik\Config;
|
15 |
use Piwik\Container\StaticContainer;
|
|
|
16 |
use Piwik\Exception\UnexpectedWebsiteFoundException;
|
17 |
use Piwik\Option;
|
18 |
use Piwik\Piwik;
|
19 |
use Piwik\Plugins\CoreHome\SystemSummary;
|
20 |
use Piwik\Settings\Storage\Backend\MeasurableSettingsTable;
|
21 |
use Piwik\Tracker\Cache;
|
|
|
22 |
use Piwik\Tracker\Model as TrackerModel;
|
23 |
use Piwik\Session\SessionNamespace;
|
24 |
|
@@ -197,6 +199,14 @@ class SitesManager extends \Piwik\Plugin
|
|
197 |
$array['timezone'] = $this->getTimezoneFromWebsite($website);
|
198 |
$array['ts_created'] = $website['ts_created'];
|
199 |
$array['type'] = $website['type'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
}
|
201 |
|
202 |
public function setTrackerCacheGeneral(&$cache)
|
13 |
use Piwik\Common;
|
14 |
use Piwik\Config;
|
15 |
use Piwik\Container\StaticContainer;
|
16 |
+
use Piwik\Date;
|
17 |
use Piwik\Exception\UnexpectedWebsiteFoundException;
|
18 |
use Piwik\Option;
|
19 |
use Piwik\Piwik;
|
20 |
use Piwik\Plugins\CoreHome\SystemSummary;
|
21 |
use Piwik\Settings\Storage\Backend\MeasurableSettingsTable;
|
22 |
use Piwik\Tracker\Cache;
|
23 |
+
use Piwik\Tracker\FingerprintSalt;
|
24 |
use Piwik\Tracker\Model as TrackerModel;
|
25 |
use Piwik\Session\SessionNamespace;
|
26 |
|
199 |
$array['timezone'] = $this->getTimezoneFromWebsite($website);
|
200 |
$array['ts_created'] = $website['ts_created'];
|
201 |
$array['type'] = $website['type'];
|
202 |
+
|
203 |
+
$datesToGenerateSalt = array(Date::now()->addDay(1), Date::now(), Date::now()->subDay(1), Date::now()->subDay(2));
|
204 |
+
|
205 |
+
$fingerprintSaltKey = new FingerprintSalt();
|
206 |
+
foreach ($datesToGenerateSalt as $date) {
|
207 |
+
$dateString = $fingerprintSaltKey->getDateString($date, $array['timezone']);
|
208 |
+
$array[FingerprintSalt::OPTION_PREFIX . $dateString] = $fingerprintSaltKey->getSalt($dateString, $idSite);
|
209 |
+
}
|
210 |
}
|
211 |
|
212 |
public function setTrackerCacheGeneral(&$cache)
|
app/plugins/UsersManager/API.php
CHANGED
@@ -197,8 +197,15 @@ class API extends \Piwik\Plugin\API
|
|
197 |
* @param string $preferenceName
|
198 |
* @return bool|string
|
199 |
*/
|
200 |
-
public function getUserPreference($userLogin, $preferenceName)
|
201 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin);
|
203 |
|
204 |
$optionValue = $this->getPreferenceValue($userLogin, $preferenceName);
|
197 |
* @param string $preferenceName
|
198 |
* @return bool|string
|
199 |
*/
|
200 |
+
public function getUserPreference($userLogin = false, $preferenceName)
|
201 |
{
|
202 |
+
if ($userLogin === false) {
|
203 |
+
// the default value for first parameter is there to have it an optional parameter in the HTTP API
|
204 |
+
// in PHP it won't be optional. Could move parameter to the end of the method but did not want to break
|
205 |
+
// BC
|
206 |
+
$userLogin = Piwik::getCurrentUserLogin();
|
207 |
+
}
|
208 |
+
|
209 |
Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin);
|
210 |
|
211 |
$optionValue = $this->getPreferenceValue($userLogin, $preferenceName);
|
app/plugins/UsersManager/UsersManager.php
CHANGED
@@ -217,6 +217,11 @@ class UsersManager extends \Piwik\Plugin
|
|
217 |
|
218 |
public static function getPasswordHash($password)
|
219 |
{
|
|
|
|
|
|
|
|
|
|
|
220 |
self::checkBasicPasswordStrength($password);
|
221 |
|
222 |
// if change here, should also edit the installation process
|
217 |
|
218 |
public static function getPasswordHash($password)
|
219 |
{
|
220 |
+
if (SettingsPiwik::isUserCredentialsSanityCheckEnabled()) {
|
221 |
+
|
222 |
+
self::checkBasicPasswordStrength($password);
|
223 |
+
}
|
224 |
+
|
225 |
self::checkBasicPasswordStrength($password);
|
226 |
|
227 |
// if change here, should also edit the installation process
|
assets/js/asset_manager_core_js.js
CHANGED
@@ -1343,7 +1343,7 @@ return fetchAllPagesPromise;}}})();
|
|
1343 |
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
1344 |
*/
|
1345 |
(function(){angular.module('piwikApp.service').factory('piwikPeriods',piwikPeriods);var periods={},periodOrder=[];piwik.addCustomPeriod=addCustomPeriod;function DayPeriod(date){this.dateInPeriod=date;}
|
1346 |
-
DayPeriod.parse=singleDatePeriodFactory(DayPeriod);DayPeriod.getDisplayText=function(){return _pk_translate('Intl_PeriodDay');};DayPeriod.prototype={getPrettyString:function(){return format(this.dateInPeriod);},getDateRange:function(){return[this.dateInPeriod,this.dateInPeriod];}};addCustomPeriod('day',DayPeriod);function WeekPeriod(date){this.dateInPeriod=date;}
|
1347 |
WeekPeriod.parse=singleDatePeriodFactory(WeekPeriod);WeekPeriod.getDisplayText=function(){return _pk_translate('Intl_PeriodWeek');};WeekPeriod.prototype={getPrettyString:function(){var weekDates=this.getDateRange(this.dateInPeriod);var startWeek=format(weekDates[0]);var endWeek=format(weekDates[1]);return _pk_translate('General_DateRangeFromTo',[startWeek,endWeek]);},getDateRange:function(){var daysToMonday=(this.dateInPeriod.getDay()+6)%7;var startWeek=new Date(this.dateInPeriod.getTime());startWeek.setDate(this.dateInPeriod.getDate()-daysToMonday);var endWeek=new Date(startWeek.getTime());endWeek.setDate(startWeek.getDate()+6);return[startWeek,endWeek];}};addCustomPeriod('week',WeekPeriod);function MonthPeriod(date){this.dateInPeriod=date;}
|
1348 |
MonthPeriod.parse=singleDatePeriodFactory(MonthPeriod);MonthPeriod.getDisplayText=function(){return _pk_translate('Intl_PeriodMonth');};MonthPeriod.prototype={getPrettyString:function(){return _pk_translate('Intl_Month_Long_StandAlone_'+(this.dateInPeriod.getMonth()+1))+' '+
|
1349 |
this.dateInPeriod.getFullYear();},getDateRange:function(){var startMonth=new Date(this.dateInPeriod.getTime());startMonth.setDate(1);var endMonth=new Date(this.dateInPeriod.getTime());endMonth.setMonth(endMonth.getMonth()+1);endMonth.setDate(0);return[startMonth,endMonth];}};addCustomPeriod('month',MonthPeriod);function YearPeriod(date){this.dateInPeriod=date;}
|
@@ -2172,7 +2172,11 @@ return dateFrom+','+dateTo;}else{return formatDate(vm.dateValue);}}
|
|
2172 |
function setPiwikPeriodAndDate(period,date){vm.periodValue=period;vm.selectedPeriod=period;vm.dateValue=date;var currentDateString=formatDate(date);setRangeStartEndFromPeriod(period,currentDateString);propagateNewUrlParams(currentDateString,vm.selectedPeriod);initTopControls();}
|
2173 |
function setRangeStartEndFromPeriod(period,dateStr){var dateRange=piwikPeriods.parse(period,dateStr).getDateRange();vm.startRangeDate=formatDate(dateRange[0]<piwikMinDate?piwikMinDate:dateRange[0]);vm.endRangeDate=formatDate(dateRange[1]>piwikMaxDate?piwikMaxDate:dateRange[1]);}
|
2174 |
function getSelectedComparisonParams(){var previousDate;if(!vm.isComparing){return{};}
|
2175 |
-
if(vm.comparePeriodType==='custom'){return{comparePeriods:['range'],compareDates:[vm.compareStartDate+','+vm.compareEndDate],};}else if(vm.comparePeriodType==='previousPeriod'){previousDate=getPreviousPeriodDateToSelectedPeriod();return{comparePeriods:[vm.selectedPeriod],compareDates:[previousDate],};}else if(vm.comparePeriodType==='previousYear'){var dateStr=vm.selectedPeriod==='range'?(vm.startRangeDate+','+vm.endRangeDate):vm.dateValue;var currentDateRange=piwikPeriods.parse(vm.selectedPeriod,dateStr).getDateRange();currentDateRange[0].setFullYear(currentDateRange[0].getFullYear()-1);currentDateRange[1].setFullYear(currentDateRange[1].getFullYear()-1);
|
|
|
|
|
|
|
|
|
2176 |
function getPreviousPeriodDateToSelectedPeriod(){if(vm.selectedPeriod==='range'){var currentStartRange=piwikPeriods.parseDate(vm.startRangeDate);var currentEndRange=piwikPeriods.parseDate(vm.endRangeDate);var newEndDate=piwikPeriods.RangePeriod.getLastNRange('day',2,currentStartRange).startDate;var rangeSize=Math.floor((currentEndRange-currentStartRange)/ 86400000);var newRange=piwikPeriods.RangePeriod.getLastNRange('day',1+rangeSize,newEndDate);return piwikPeriods.format(newRange.startDate)+','+piwikPeriods.format(newRange.endDate);}
|
2177 |
var newStartDate=piwikPeriods.RangePeriod.getLastNRange(vm.selectedPeriod,2,vm.dateValue).startDate;return piwikPeriods.format(newStartDate);}
|
2178 |
function propagateNewUrlParams(date,period){var compareParams=getSelectedComparisonParams();if(piwik.helper.isAngularRenderingThePage()){vm.closePeriodSelector();var $search=$location.search();var isCurrentlyComparing=piwikUrl.getSearchParam('compareSegments')||piwikUrl.getSearchParam('comparePeriods');if(date!==$search.date||period!==$search.period||vm.isComparing||isCurrentlyComparing){$search.date=date;$search.period=period;$search.compareSegments=piwikUrl.getSearchParam('compareSegments')||[];$.extend($search,compareParams);delete $search['compareSegments[]'];delete $search['comparePeriods[]'];delete $search['compareDates[]'];$location.search($.param($search));}
|
@@ -3589,14 +3593,14 @@ $(window).off('resize.'+this.uniqueId);this.map.clear();$(this.map.container).ht
|
|
3589 |
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
3590 |
*/
|
3591 |
(function($){$.widget('piwik.liveWidget',{options:{maxRows:10,interval:3000,maxInterval:300000,dataUrlParams:null,onUpdate:null,fadeInSpeed:'slow'},currentInterval:null,updated:false,updateInterval:null,isStarted:true,_update:function(){this.updated=false;var that=this;var ajaxRequest=new ajaxHelper();ajaxRequest.addParams(this.options.dataUrlParams,'GET');ajaxRequest.setFormat('html');ajaxRequest.setCallback(function(r){if(that.options.replaceContent){$(that.element).html(r);if(that.options.fadeInSpeed){$(that.element).effect("highlight",{},that.options.fadeInSpeed);}}else{that._parseResponse(r);}
|
3592 |
-
if(!that.updated){that.currentInterval+=that.options.interval;}else{that.currentInterval=that.options.interval;if(that.options.onUpdate)that.options.onUpdate();}
|
3593 |
if(that.options.maxInterval<that.currentInterval){that.currentInterval=that.options.maxInterval;}
|
3594 |
if(that.isStarted){window.clearTimeout(that.updateInterval);if(that.element.length&&$.contains(document,that.element[0])){that.updateInterval=window.setTimeout(function(){that._update()},that.currentInterval);}}});ajaxRequest.send();},_parseResponse:function(data){if(!data||!data.length){this.updated=false;return;}
|
3595 |
var items=$('li.visit',$(data));for(var i=items.length;i--;){this._parseItem(items[i]);}
|
3596 |
this._initTooltips();},_initTooltips:function(){$('li.visit').tooltip({items:'.visitorLogIconWithDetails',track:true,show:false,hide:false,content:function(){return $('<ul>').html($('ul',$(this)).html());},tooltipClass:'small'});},_parseItem:function(item){var visitId=$(item).attr('id');if($('#'+visitId,this.element).length){if($('#'+visitId,this.element).html()!=$(item).html()){this.updated=true;}
|
3597 |
$('#'+visitId,this.element).remove();$(this.element).prepend(item);}else{this.updated=true;$(item).hide();$(this.element).prepend(item);$(item).fadeIn(this.options.fadeInSpeed);}
|
3598 |
$('li.visit:gt('+(this.options.maxRows-1)+')',this.element).remove();},_create:function(){if(!this.options.dataUrlParams){console&&console.error('liveWidget error: dataUrlParams needs to be defined in settings.');return;}
|
3599 |
-
this.currentInterval=this.options.interval;if(0===$(this.element).parents('.widget').length){var $rootScope=piwikHelper.getAngularDependency('$rootScope');$rootScope.$emit('hidePeriodSelector');}
|
3600 |
var self=this;window.setTimeout(function(){self._initTooltips();},250);this.updateInterval=window.setTimeout(function(){self._update();},this.currentInterval);},_destroy:function(){this.stop();},update:function(){this._update();},start:function(){this.isStarted=true;this.currentInterval=0;this._update();},stop:function(){this.isStarted=false;window.clearTimeout(this.updateInterval);},started:function(){return this.isStarted;},setInterval:function(interval){this.currentInterval=interval;}});})(jQuery);$(function(){var refreshWidget=function(element,refreshAfterXSecs){if(!element.length||!$.contains(document,element[0])){return;}
|
3601 |
function scheduleAnotherRequest(){setTimeout(function(){refreshWidget(element,refreshAfterXSecs);},refreshAfterXSecs*1000);}
|
3602 |
if(Visibility.hidden()){scheduleAnotherRequest();return;}
|
1343 |
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
1344 |
*/
|
1345 |
(function(){angular.module('piwikApp.service').factory('piwikPeriods',piwikPeriods);var periods={},periodOrder=[];piwik.addCustomPeriod=addCustomPeriod;function DayPeriod(date){this.dateInPeriod=date;}
|
1346 |
+
DayPeriod.parse=singleDatePeriodFactory(DayPeriod);DayPeriod.getDisplayText=function(){return _pk_translate('Intl_PeriodDay');};DayPeriod.prototype={getPrettyString:function(){return format(this.dateInPeriod);},getDateRange:function(){return[new Date(this.dateInPeriod.getTime()), new Date(this.dateInPeriod.getTime())];}};addCustomPeriod('day',DayPeriod);function WeekPeriod(date){this.dateInPeriod=date;}
|
1347 |
WeekPeriod.parse=singleDatePeriodFactory(WeekPeriod);WeekPeriod.getDisplayText=function(){return _pk_translate('Intl_PeriodWeek');};WeekPeriod.prototype={getPrettyString:function(){var weekDates=this.getDateRange(this.dateInPeriod);var startWeek=format(weekDates[0]);var endWeek=format(weekDates[1]);return _pk_translate('General_DateRangeFromTo',[startWeek,endWeek]);},getDateRange:function(){var daysToMonday=(this.dateInPeriod.getDay()+6)%7;var startWeek=new Date(this.dateInPeriod.getTime());startWeek.setDate(this.dateInPeriod.getDate()-daysToMonday);var endWeek=new Date(startWeek.getTime());endWeek.setDate(startWeek.getDate()+6);return[startWeek,endWeek];}};addCustomPeriod('week',WeekPeriod);function MonthPeriod(date){this.dateInPeriod=date;}
|
1348 |
MonthPeriod.parse=singleDatePeriodFactory(MonthPeriod);MonthPeriod.getDisplayText=function(){return _pk_translate('Intl_PeriodMonth');};MonthPeriod.prototype={getPrettyString:function(){return _pk_translate('Intl_Month_Long_StandAlone_'+(this.dateInPeriod.getMonth()+1))+' '+
|
1349 |
this.dateInPeriod.getFullYear();},getDateRange:function(){var startMonth=new Date(this.dateInPeriod.getTime());startMonth.setDate(1);var endMonth=new Date(this.dateInPeriod.getTime());endMonth.setMonth(endMonth.getMonth()+1);endMonth.setDate(0);return[startMonth,endMonth];}};addCustomPeriod('month',MonthPeriod);function YearPeriod(date){this.dateInPeriod=date;}
|
2172 |
function setPiwikPeriodAndDate(period,date){vm.periodValue=period;vm.selectedPeriod=period;vm.dateValue=date;var currentDateString=formatDate(date);setRangeStartEndFromPeriod(period,currentDateString);propagateNewUrlParams(currentDateString,vm.selectedPeriod);initTopControls();}
|
2173 |
function setRangeStartEndFromPeriod(period,dateStr){var dateRange=piwikPeriods.parse(period,dateStr).getDateRange();vm.startRangeDate=formatDate(dateRange[0]<piwikMinDate?piwikMinDate:dateRange[0]);vm.endRangeDate=formatDate(dateRange[1]>piwikMaxDate?piwikMaxDate:dateRange[1]);}
|
2174 |
function getSelectedComparisonParams(){var previousDate;if(!vm.isComparing){return{};}
|
2175 |
+
if(vm.comparePeriodType==='custom'){return{comparePeriods:['range'],compareDates:[vm.compareStartDate+','+vm.compareEndDate],};}else if(vm.comparePeriodType==='previousPeriod'){previousDate=getPreviousPeriodDateToSelectedPeriod();return{comparePeriods:[vm.selectedPeriod],compareDates:[previousDate],};}else if(vm.comparePeriodType==='previousYear'){var dateStr=vm.selectedPeriod==='range'?(vm.startRangeDate+','+vm.endRangeDate):vm.dateValue;var currentDateRange=piwikPeriods.parse(vm.selectedPeriod,dateStr).getDateRange();currentDateRange[0].setFullYear(currentDateRange[0].getFullYear()-1);currentDateRange[1].setFullYear(currentDateRange[1].getFullYear()-1);
|
2176 |
+
if (vm.selectedPeriod === 'range') {
|
2177 |
+
return { comparePeriods: ['range'], compareDates: [piwikPeriods.format(currentDateRange[0]) + ',' + piwikPeriods.format(currentDateRange[1])]};
|
2178 |
+
} return { comparePeriods: [vm.selectedPeriod],compareDates: [piwikPeriods.format(currentDateRange[0])] };
|
2179 |
+
}else{console.warn("Unknown compare period type: "+vm.comparePeriodType);return{};}}
|
2180 |
function getPreviousPeriodDateToSelectedPeriod(){if(vm.selectedPeriod==='range'){var currentStartRange=piwikPeriods.parseDate(vm.startRangeDate);var currentEndRange=piwikPeriods.parseDate(vm.endRangeDate);var newEndDate=piwikPeriods.RangePeriod.getLastNRange('day',2,currentStartRange).startDate;var rangeSize=Math.floor((currentEndRange-currentStartRange)/ 86400000);var newRange=piwikPeriods.RangePeriod.getLastNRange('day',1+rangeSize,newEndDate);return piwikPeriods.format(newRange.startDate)+','+piwikPeriods.format(newRange.endDate);}
|
2181 |
var newStartDate=piwikPeriods.RangePeriod.getLastNRange(vm.selectedPeriod,2,vm.dateValue).startDate;return piwikPeriods.format(newStartDate);}
|
2182 |
function propagateNewUrlParams(date,period){var compareParams=getSelectedComparisonParams();if(piwik.helper.isAngularRenderingThePage()){vm.closePeriodSelector();var $search=$location.search();var isCurrentlyComparing=piwikUrl.getSearchParam('compareSegments')||piwikUrl.getSearchParam('comparePeriods');if(date!==$search.date||period!==$search.period||vm.isComparing||isCurrentlyComparing){$search.date=date;$search.period=period;$search.compareSegments=piwikUrl.getSearchParam('compareSegments')||[];$.extend($search,compareParams);delete $search['compareSegments[]'];delete $search['comparePeriods[]'];delete $search['compareDates[]'];$location.search($.param($search));}
|
3593 |
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
3594 |
*/
|
3595 |
(function($){$.widget('piwik.liveWidget',{options:{maxRows:10,interval:3000,maxInterval:300000,dataUrlParams:null,onUpdate:null,fadeInSpeed:'slow'},currentInterval:null,updated:false,updateInterval:null,isStarted:true,_update:function(){this.updated=false;var that=this;var ajaxRequest=new ajaxHelper();ajaxRequest.addParams(this.options.dataUrlParams,'GET');ajaxRequest.setFormat('html');ajaxRequest.setCallback(function(r){if(that.options.replaceContent){$(that.element).html(r);if(that.options.fadeInSpeed){$(that.element).effect("highlight",{},that.options.fadeInSpeed);}}else{that._parseResponse(r);}
|
3596 |
+
that.options.interval = parseInt(that.options.interval, 10);if(!that.updated){that.currentInterval+=that.options.interval;}else{that.currentInterval=that.options.interval;if(that.options.onUpdate)that.options.onUpdate();}
|
3597 |
if(that.options.maxInterval<that.currentInterval){that.currentInterval=that.options.maxInterval;}
|
3598 |
if(that.isStarted){window.clearTimeout(that.updateInterval);if(that.element.length&&$.contains(document,that.element[0])){that.updateInterval=window.setTimeout(function(){that._update()},that.currentInterval);}}});ajaxRequest.send();},_parseResponse:function(data){if(!data||!data.length){this.updated=false;return;}
|
3599 |
var items=$('li.visit',$(data));for(var i=items.length;i--;){this._parseItem(items[i]);}
|
3600 |
this._initTooltips();},_initTooltips:function(){$('li.visit').tooltip({items:'.visitorLogIconWithDetails',track:true,show:false,hide:false,content:function(){return $('<ul>').html($('ul',$(this)).html());},tooltipClass:'small'});},_parseItem:function(item){var visitId=$(item).attr('id');if($('#'+visitId,this.element).length){if($('#'+visitId,this.element).html()!=$(item).html()){this.updated=true;}
|
3601 |
$('#'+visitId,this.element).remove();$(this.element).prepend(item);}else{this.updated=true;$(item).hide();$(this.element).prepend(item);$(item).fadeIn(this.options.fadeInSpeed);}
|
3602 |
$('li.visit:gt('+(this.options.maxRows-1)+')',this.element).remove();},_create:function(){if(!this.options.dataUrlParams){console&&console.error('liveWidget error: dataUrlParams needs to be defined in settings.');return;}
|
3603 |
+
this.currentInterval = parseInt(this.options.interval, 10);if(0===$(this.element).parents('.widget').length){var $rootScope=piwikHelper.getAngularDependency('$rootScope');$rootScope.$emit('hidePeriodSelector');}
|
3604 |
var self=this;window.setTimeout(function(){self._initTooltips();},250);this.updateInterval=window.setTimeout(function(){self._update();},this.currentInterval);},_destroy:function(){this.stop();},update:function(){this._update();},start:function(){this.isStarted=true;this.currentInterval=0;this._update();},stop:function(){this.isStarted=false;window.clearTimeout(this.updateInterval);},started:function(){return this.isStarted;},setInterval:function(interval){this.currentInterval=interval;}});})(jQuery);$(function(){var refreshWidget=function(element,refreshAfterXSecs){if(!element.length||!$.contains(document,element[0])){return;}
|
3605 |
function scheduleAnotherRequest(){setTimeout(function(){refreshWidget(element,refreshAfterXSecs);},refreshAfterXSecs*1000);}
|
3606 |
if(Visibility.hidden()){scheduleAnotherRequest();return;}
|
classes/WpMatomo/Admin/SystemReport.php
CHANGED
@@ -705,7 +705,7 @@ class SystemReport {
|
|
705 |
);
|
706 |
$consts = array('WP_DEBUG', 'WP_DEBUG_DISPLAY', 'WP_DEBUG_LOG', 'DISABLE_WP_CRON', 'FORCE_SSL_ADMIN', 'WP_CACHE',
|
707 |
'CONCATENATE_SCRIPTS', 'COMPRESS_SCRIPTS', 'COMPRESS_CSS', 'ENFORCE_GZIP', 'WP_LOCAL_DEV',
|
708 |
-
'DIEONDBERROR', 'WPLANG');
|
709 |
foreach ($consts as $const) {
|
710 |
$rows[] = array(
|
711 |
'name' => $const,
|
@@ -832,7 +832,13 @@ class SystemReport {
|
|
832 |
);
|
833 |
|
834 |
$rows[] = array(
|
835 |
-
'name' => '
|
|
|
|
|
|
|
|
|
|
|
|
|
836 |
'value' => defined( 'WP_MAX_MEMORY_LIMIT' ) ? WP_MAX_MEMORY_LIMIT : '',
|
837 |
'comment' => '',
|
838 |
);
|
@@ -954,6 +960,16 @@ class SystemReport {
|
|
954 |
'value' => defined('DB_COLLATE') ? DB_COLLATE : '',
|
955 |
);
|
956 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
957 |
if ( method_exists( $wpdb, 'parse_db_host' ) ) {
|
958 |
$host_data = $wpdb->parse_db_host( DB_HOST );
|
959 |
if ( $host_data ) {
|
705 |
);
|
706 |
$consts = array('WP_DEBUG', 'WP_DEBUG_DISPLAY', 'WP_DEBUG_LOG', 'DISABLE_WP_CRON', 'FORCE_SSL_ADMIN', 'WP_CACHE',
|
707 |
'CONCATENATE_SCRIPTS', 'COMPRESS_SCRIPTS', 'COMPRESS_CSS', 'ENFORCE_GZIP', 'WP_LOCAL_DEV',
|
708 |
+
'DIEONDBERROR', 'WPLANG', 'ALTERNATE_WP_CRON', 'WP_CRON_LOCK_TIMEOUT', 'WP_DISABLE_FATAL_ERROR_HANDLER');
|
709 |
foreach ($consts as $const) {
|
710 |
$rows[] = array(
|
711 |
'name' => $const,
|
832 |
);
|
833 |
|
834 |
$rows[] = array(
|
835 |
+
'name' => 'WP Memory Limit',
|
836 |
+
'value' => defined( 'WP_MEMORY_LIMIT' ) ? WP_MEMORY_LIMIT : '',
|
837 |
+
'comment' => '',
|
838 |
+
);
|
839 |
+
|
840 |
+
$rows[] = array(
|
841 |
+
'name' => 'WP Max Memory Limit',
|
842 |
'value' => defined( 'WP_MAX_MEMORY_LIMIT' ) ? WP_MAX_MEMORY_LIMIT : '',
|
843 |
'comment' => '',
|
844 |
);
|
960 |
'value' => defined('DB_COLLATE') ? DB_COLLATE : '',
|
961 |
);
|
962 |
|
963 |
+
$rows[] = array(
|
964 |
+
'name' => 'SHOW ERRORS',
|
965 |
+
'value' => !empty($wpdb->show_errors),
|
966 |
+
);
|
967 |
+
|
968 |
+
$rows[] = array(
|
969 |
+
'name' => 'SUPPRESS ERRORS',
|
970 |
+
'value' => !empty($wpdb->suppress_errors),
|
971 |
+
);
|
972 |
+
|
973 |
if ( method_exists( $wpdb, 'parse_db_host' ) ) {
|
974 |
$host_data = $wpdb->parse_db_host( DB_HOST );
|
975 |
if ( $host_data ) {
|
classes/WpMatomo/Admin/views/marketplace.php
CHANGED
@@ -279,12 +279,13 @@ $matomo_extra_url_params = '&' . http_build_query(
|
|
279 |
?>
|
280 |
|
281 |
<div style="border: 1px solid #ddd;padding: 20px;margin-top: 30px;background: white;text-align: center;">
|
282 |
-
<
|
283 |
-
<
|
284 |
-
<a href="https://matomo.org/wp-premium-bundle/" class="button button-primary"
|
285 |
style="background: limegreen;border-color: limegreen;font-size: 18px;"
|
286 |
target="_blank" rel="noreferrer noopener" role="button">Learn more</a>
|
287 |
-
|
|
|
288 |
<h2>What's included in this bundle?</h2>
|
289 |
<?php
|
290 |
|
279 |
?>
|
280 |
|
281 |
<div style="border: 1px solid #ddd;padding: 20px;margin-top: 30px;background: white;text-align: center;">
|
282 |
+
<h3 style="color: red">Limited time offer! Matomo Premium Bundle only 199€/year (300€ off)</h3>
|
283 |
+
<h1>Your marketing efforts are too valuable to focus on the wrong things.<br> Take your Matomo for WordPress to the next level to push out content and changes to your website that make you consistently more successful. 🚀</h1>
|
284 |
+
<p><a href="https://matomo.org/wp-premium-bundle/" class="button button-primary"
|
285 |
style="background: limegreen;border-color: limegreen;font-size: 18px;"
|
286 |
target="_blank" rel="noreferrer noopener" role="button">Learn more</a>
|
287 |
+
</p>
|
288 |
+
<p><br></p>
|
289 |
<h2>What's included in this bundle?</h2>
|
290 |
<?php
|
291 |
|
classes/WpMatomo/Db/Settings.php
CHANGED
@@ -42,8 +42,6 @@ class Settings {
|
|
42 |
// list of existing temp tables
|
43 |
$table_names_to_look_for = array(
|
44 |
'access',
|
45 |
-
'archive_blob_2010_01',
|
46 |
-
'archive_numeric_2010_01',
|
47 |
'brute_force_log',
|
48 |
'goal',
|
49 |
'locks',
|
42 |
// list of existing temp tables
|
43 |
$table_names_to_look_for = array(
|
44 |
'access',
|
|
|
|
|
45 |
'brute_force_log',
|
46 |
'goal',
|
47 |
'locks',
|
classes/WpMatomo/Db/WordPress.php
CHANGED
@@ -18,6 +18,10 @@ require_once 'WordPressTracker.php';
|
|
18 |
|
19 |
class WordPress extends Mysqli {
|
20 |
|
|
|
|
|
|
|
|
|
21 |
private $old_suppress_errors_value = null;
|
22 |
|
23 |
/**
|
@@ -52,6 +56,10 @@ class WordPress extends Mysqli {
|
|
52 |
return true;
|
53 |
}
|
54 |
|
|
|
|
|
|
|
|
|
55 |
/**
|
56 |
* Is the connection character set equal to utf8?
|
57 |
*
|
@@ -94,9 +102,94 @@ class WordPress extends Mysqli {
|
|
94 |
}
|
95 |
|
96 |
public function listTables() {
|
|
|
97 |
$sql = 'SHOW TABLES';
|
98 |
|
99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
}
|
101 |
|
102 |
public function getServerVersion() {
|
18 |
|
19 |
class WordPress extends Mysqli {
|
20 |
|
21 |
+
// needed to be compatbile with mysqli class when `getConnection()` is called and we cannot return the
|
22 |
+
// actual connection but return an instance of this.
|
23 |
+
public $error = '';
|
24 |
+
|
25 |
private $old_suppress_errors_value = null;
|
26 |
|
27 |
/**
|
56 |
return true;
|
57 |
}
|
58 |
|
59 |
+
public function getConnection() {
|
60 |
+
return $this;
|
61 |
+
}
|
62 |
+
|
63 |
/**
|
64 |
* Is the connection character set equal to utf8?
|
65 |
*
|
102 |
}
|
103 |
|
104 |
public function listTables() {
|
105 |
+
global $wpdb;
|
106 |
$sql = 'SHOW TABLES';
|
107 |
|
108 |
+
$tables = $wpdb->get_results( $sql, ARRAY_N );
|
109 |
+
$result = [];
|
110 |
+
foreach ($tables as $table) {
|
111 |
+
$result[] = $table[0];
|
112 |
+
}
|
113 |
+
return $result;
|
114 |
+
}
|
115 |
+
|
116 |
+
public function describeTable($tableName, $schemaName = null)
|
117 |
+
{
|
118 |
+
global $wpdb;
|
119 |
+
|
120 |
+
if ($schemaName) {
|
121 |
+
$sql = 'DESCRIBE ' . $this->quoteIdentifier("$schemaName.$tableName", true);
|
122 |
+
} else {
|
123 |
+
$sql = 'DESCRIBE ' . $this->quoteIdentifier($tableName, true);
|
124 |
+
}
|
125 |
+
|
126 |
+
$result = $wpdb->get_results( $sql, ARRAY_A );
|
127 |
+
|
128 |
+
$desc = array();
|
129 |
+
|
130 |
+
$row_defaults = array(
|
131 |
+
'Length' => null,
|
132 |
+
'Scale' => null,
|
133 |
+
'Precision' => null,
|
134 |
+
'Unsigned' => null,
|
135 |
+
'Primary' => false,
|
136 |
+
'PrimaryPosition' => null,
|
137 |
+
'Identity' => false
|
138 |
+
);
|
139 |
+
$i = 1;
|
140 |
+
$p = 1;
|
141 |
+
foreach ($result as $key => $row) {
|
142 |
+
$row = array_merge($row_defaults, $row);
|
143 |
+
if (preg_match('/unsigned/', $row['Type'])) {
|
144 |
+
$row['Unsigned'] = true;
|
145 |
+
}
|
146 |
+
if (preg_match('/^((?:var)?char)\((\d+)\)/', $row['Type'], $matches)) {
|
147 |
+
$row['Type'] = $matches[1];
|
148 |
+
$row['Length'] = $matches[2];
|
149 |
+
} else if (preg_match('/^decimal\((\d+),(\d+)\)/', $row['Type'], $matches)) {
|
150 |
+
$row['Type'] = 'decimal';
|
151 |
+
$row['Precision'] = $matches[1];
|
152 |
+
$row['Scale'] = $matches[2];
|
153 |
+
} else if (preg_match('/^float\((\d+),(\d+)\)/', $row['Type'], $matches)) {
|
154 |
+
$row['Type'] = 'float';
|
155 |
+
$row['Precision'] = $matches[1];
|
156 |
+
$row['Scale'] = $matches[2];
|
157 |
+
} else if (preg_match('/^((?:big|medium|small|tiny)?int)\((\d+)\)/', $row['Type'], $matches)) {
|
158 |
+
$row['Type'] = $matches[1];
|
159 |
+
/**
|
160 |
+
* The optional argument of a MySQL int type is not precision
|
161 |
+
* or length; it is only a hint for display width.
|
162 |
+
*/
|
163 |
+
}
|
164 |
+
if (strtoupper($row['Key']) == 'PRI') {
|
165 |
+
$row['Primary'] = true;
|
166 |
+
$row['PrimaryPosition'] = $p;
|
167 |
+
if ($row['Extra'] == 'auto_increment') {
|
168 |
+
$row['Identity'] = true;
|
169 |
+
} else {
|
170 |
+
$row['Identity'] = false;
|
171 |
+
}
|
172 |
+
++$p;
|
173 |
+
}
|
174 |
+
$desc[$this->foldCase($row['Field'])] = array(
|
175 |
+
'SCHEMA_NAME' => null, // @todo
|
176 |
+
'TABLE_NAME' => $this->foldCase($tableName),
|
177 |
+
'COLUMN_NAME' => $this->foldCase($row['Field']),
|
178 |
+
'COLUMN_POSITION' => $i,
|
179 |
+
'DATA_TYPE' => $row['Type'],
|
180 |
+
'DEFAULT' => $row['Default'],
|
181 |
+
'NULLABLE' => (bool) ($row['Null'] == 'YES'),
|
182 |
+
'LENGTH' => $row['Length'],
|
183 |
+
'SCALE' => $row['Scale'],
|
184 |
+
'PRECISION' => $row['Precision'],
|
185 |
+
'UNSIGNED' => $row['Unsigned'],
|
186 |
+
'PRIMARY' => $row['Primary'],
|
187 |
+
'PRIMARY_POSITION' => $row['PrimaryPosition'],
|
188 |
+
'IDENTITY' => $row['Identity']
|
189 |
+
);
|
190 |
+
++$i;
|
191 |
+
}
|
192 |
+
return $desc;
|
193 |
}
|
194 |
|
195 |
public function getServerVersion() {
|
matomo.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
* Description: The #1 Google Analytics alternative that gives you full control over your data and protects the privacy for your users. Free, secure and open.
|
5 |
* Author: Matomo
|
6 |
* Author URI: https://matomo.org
|
7 |
-
* Version: 1.1.
|
8 |
* Domain Path: /languages
|
9 |
* WC requires at least: 2.4.0
|
10 |
* WC tested up to: 4.0.0
|
4 |
* Description: The #1 Google Analytics alternative that gives you full control over your data and protects the privacy for your users. Free, secure and open.
|
5 |
* Author: Matomo
|
6 |
* Author URI: https://matomo.org
|
7 |
+
* Version: 1.1.2
|
8 |
* Domain Path: /languages
|
9 |
* WC requires at least: 2.4.0
|
10 |
* WC tested up to: 4.0.0
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
|
|
4 |
Tags: matomo,piwik,analytics,statistics,stats,tracking,ecommerce
|
5 |
Requires at least: 4.8
|
6 |
Tested up to: 5.4
|
7 |
-
Stable tag: 1.1.
|
8 |
Requires PHP: 7.2
|
9 |
License: GPLv3 or later
|
10 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
4 |
Tags: matomo,piwik,analytics,statistics,stats,tracking,ecommerce
|
5 |
Requires at least: 4.8
|
6 |
Tested up to: 5.4
|
7 |
+
Stable tag: 1.1.2
|
8 |
Requires PHP: 7.2
|
9 |
License: GPLv3 or later
|
10 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|