Skip to content

Commit

Permalink
Merge pull request #655 from matomo-org/matomo_4_12_1
Browse files Browse the repository at this point in the history
Matomo 4.12.3
  • Loading branch information
mattmary authored Oct 31, 2022
2 parents 8d028b9 + 60117f4 commit 42409fd
Show file tree
Hide file tree
Showing 490 changed files with 28,285 additions and 12,820 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
== Changelog ==
= 4.12.0 =
* Update Matomo core to 4.12.3
* Update WordPress compatibility version
* Update WooCommerce compatibility version
* Update plugins compatiblity list

= 4.11.0 =
* Update Matomo core to 4.11.0
Expand Down
14 changes: 11 additions & 3 deletions app/config/global.ini.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
; Matomo should work correctly without this setting but we recommend to have a charset set.
charset = utf8

; Database error codes to ignore during updates
;
;ignore_error_codes[] = 1105

; If configured, the following queries will be executed on the reader instead of the writer.
; * archiving queries that hit a log table
; * live queries that hit a log table
Expand Down Expand Up @@ -388,11 +392,15 @@
; This feature will not work with the MYSQLI extension.
archiving_query_max_execution_time = 7200


; Allows you to disable archiving segments for selected plugins. For more details please see https://matomo.org/faq/how-to-disable-archiving-the-segment-reports-for-specific-plugins
; Here you can specify the comma separated list eg: "plugin1,plugin2"
disable_archiving_segment_for_plugins = ""

; By default Matomo will archive data showing the contribution of each action to goal conversions, for sites tracking millions
; of visits with a large number of goals this may negatively impact archiving performance. You can disable archiving of action
; goal contribution here:
disable_archive_actions_goals = 0

; By default Matomo runs OPTIMIZE TABLE SQL queries to free spaces after deleting some data.
; If your Matomo tracks millions of pages, the OPTIMIZE TABLE queries might run for hours (seen in "SHOW FULL PROCESSLIST \g")
; so you can disable these special queries here:
Expand Down Expand Up @@ -934,7 +942,7 @@

; Comma separated list of URL query string variable names that will be removed from your tracked URLs
; By default, Matomo will remove the most common parameters which are known to change often (eg. session ID parameters)
url_query_parameter_to_exclude_from_url = "gclid,fbclid,fb_xd_fragment,fb_comment_id,phpsessid,jsessionid,sessionid,aspsessionid,doing_wp_cron,sid,pk_vid"
url_query_parameter_to_exclude_from_url = "gclid,fbclid,msclkid,yclid,fb_xd_fragment,fb_comment_id,phpsessid,jsessionid,sessionid,aspsessionid,doing_wp_cron,sid,pk_vid"

; If set to 1, Matomo will use the default provider if no other provider is configured.
; In addition the default provider will be used as a fallback when the configure provider does not return any results.
Expand Down Expand Up @@ -1035,7 +1043,7 @@
; For example "e_c==Media" means that all tracking requests will be excluded where the event category is Media.
; Multiple exclusions can be configured separated by a comma. The request will be excluded if any expressions matches (not all of them). For example: "e_c==Media,action_name=@privacy".
; This would also exclude any request from being tracked where the page title contains privacy.
; All comparisons are performed case insensitve. The value to match on the right side should be URL encoded.
; All comparisons are performed case insensitive. The value to match on the right side should be URL encoded.
; For example: "action_name=^foo%2Cbar" would exclude page titles that start with "foo,bar".
; For a list of tracking parameters you can use on the left side view https://developer.matomo.org/api-reference/tracking-api
exclude_requests = ""
Expand Down
3 changes: 2 additions & 1 deletion app/core/API/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ public static function getRequestArrayFromString($request, $defaultRequest = nul
$defaultRequest['segment'] = $requestRaw['segment'];
}

if (!isset($defaultRequest['format_metrics'])) {
// Only default to formatting metrics if the request doesn't already contain the format metrics parameter
if (!isset($defaultRequest['format_metrics']) && !isset($request['format_metrics'])) {
$defaultRequest['format_metrics'] = 'bc';
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/core/Access/CapabilitiesProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function getAllCapabilities(): array
*
* public function addCapabilities(&$capabilities)
* {
* $capabilities[] = new MyNewCapabilitiy();
* $capabilities[] = new MyNewCapability();
* }
*
* @param Capability[] $reports An array of reports
Expand Down
10 changes: 5 additions & 5 deletions app/core/Archive/ArchiveInvalidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,15 +254,15 @@ private function deleteOptionLike($id)
* @param $period string
* @param $segment Segment
* @param bool $cascadeDown
* @param bool $forceInvalidateNonexistantRanges set true to force inserting rows for ranges in archive_invalidations
* @param bool $forceInvalidateNonexistentRanges set true to force inserting rows for ranges in archive_invalidations
* @param string $name null to make sure every plugin is archived when this invalidation is processed by core:archive,
* or a plugin name to only archive the specific plugin.
* @param bool $ignorePurgeLogDataDate
* @return InvalidationResult
* @throws \Exception
*/
public function markArchivesAsInvalidated(array $idSites, array $dates, $period, Segment $segment = null, $cascadeDown = false,
$forceInvalidateNonexistantRanges = false, $name = null, $ignorePurgeLogDataDate = false)
$forceInvalidateNonexistentRanges = false, $name = null, $ignorePurgeLogDataDate = false)
{
$plugin = null;
if ($name && strpos($name, '.') !== false) {
Expand Down Expand Up @@ -320,7 +320,7 @@ public function markArchivesAsInvalidated(array $idSites, array $dates, $period,

$allPeriodsToInvalidate = $this->getAllPeriodsByYearMonth($period, $datesToInvalidate, $cascadeDown);

$this->markArchivesInvalidated($idSites, $allPeriodsToInvalidate, $segment, $period != 'range', $forceInvalidateNonexistantRanges, $name);
$this->markArchivesInvalidated($idSites, $allPeriodsToInvalidate, $segment, $period != 'range', $forceInvalidateNonexistentRanges, $name);

$isInvalidatingDays = $period == 'day' || $cascadeDown || empty($period);
$isNotInvalidatingSegment = empty($segment) || empty($segment->getString());
Expand Down Expand Up @@ -678,7 +678,7 @@ public function removeInvalidationsFromDistributedList($idSites, $pluginName = n
* @throws \Exception
*/
private function markArchivesInvalidated($idSites, $dates, Segment $segment = null, $removeRanges = false,
$forceInvalidateNonexistantRanges = false, $name = null)
$forceInvalidateNonexistentRanges = false, $name = null)
{
$idSites = array_map('intval', $idSites);

Expand All @@ -690,7 +690,7 @@ private function markArchivesInvalidated($idSites, $dates, Segment $segment = nu
$table = ArchiveTableCreator::getNumericTable($tableDateObj);
$yearMonths[] = $tableDateObj->toString('Y_m');

$this->model->updateArchiveAsInvalidated($table, $idSites, $datesForTable, $segment, $forceInvalidateNonexistantRanges, $name);
$this->model->updateArchiveAsInvalidated($table, $idSites, $datesForTable, $segment, $forceInvalidateNonexistentRanges, $name);

if ($removeRanges) {
$this->model->updateRangeArchiveAsInvalidated($table, $idSites, $datesForTable, $segment);
Expand Down
11 changes: 6 additions & 5 deletions app/core/Archive/ArchiveInvalidator/InvalidationResult.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* Matomo - free/libre analytics platform
*
Expand All @@ -21,14 +22,14 @@ class InvalidationResult
*
* @var array
*/
public $warningDates = array();
public $warningDates = [];

/**
* Dates that were successfully invalidated.
*
* @var array
*/
public $processedDates = array();
public $processedDates = [];

/**
* The day of the oldest log entry.
Expand All @@ -40,9 +41,9 @@ class InvalidationResult
/**
* @return string[]
*/
public function makeOutputLogs()
public function makeOutputLogs(): array
{
$output = array();
$output = [];
if ($this->warningDates) {
$output[] = 'Warning: the following Dates have not been invalidated, because they are earlier than your Log Deletion limit: ' .
implode(", ", $this->warningDates) .
Expand All @@ -53,4 +54,4 @@ public function makeOutputLogs()
$output[] = "Success. The following dates were invalidated successfully: " . implode(", ", $this->processedDates);
return $output;
}
}
}
5 changes: 5 additions & 0 deletions app/core/AssetManager/UIAssetMerger.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ abstract class UIAssetMerger
*/
protected $cacheBuster;

/**
* @var string
*/
protected $cacheBusterValue;

/**
* @param UIAsset $mergedAsset
* @param UIAssetFetcher $assetFetcher
Expand Down
4 changes: 2 additions & 2 deletions app/core/Auth/Password.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ class Password
*/
private function preferredAlgorithm()
{
$passwordHashAlogrithm = Config::getInstance()->General['password_hash_algorithm'];
switch ($passwordHashAlogrithm) {
$passwordHashAlgorithm = Config::getInstance()->General['password_hash_algorithm'];
switch ($passwordHashAlgorithm) {
case "default":
return PASSWORD_DEFAULT;
case "bcrypt":
Expand Down
2 changes: 1 addition & 1 deletion app/core/Columns/Dimension.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ abstract class Dimension
protected $acceptValues;

/**
* Defines to which column in the MySQL database the segment belongs (if one is conifugred). Defaults to
* Defines to which column in the MySQL database the segment belongs (if one is configured). Defaults to
* `$this.dbTableName . '.'. $this.columnName` but you can customize it eg like `HOUR(log_visit.visit_last_action_time)`.
*
* @param string $sqlSegment
Expand Down
2 changes: 1 addition & 1 deletion app/core/Common.php
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,7 @@ public static function hasJsonErrorOccurred()
}

/**
* Returns a human readable error message in case an error occcurred during the last json encode/decode.
* Returns a human readable error message in case an error occurred during the last json encode/decode.
* Returns an empty string in case there was no error.
*
* @return string
Expand Down
2 changes: 1 addition & 1 deletion app/core/Concurrency/LockBackend/MySqlLockBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function setIfNotExists($key, $value, $ttlInSeconds)
// remove any existing but expired lock
// todo: we could combine get() and keyExists() in one query!
if ($this->keyExists($key)) {
// most of the time an expired key should not exist... we don't want to lock the row unncessarily therefore we check first
// most of the time an expired key should not exist... we don't want to lock the row unnecessarily therefore we check first
// if value exists...
$sql = sprintf('DELETE FROM %s WHERE `key` = ? and not (%s)', $tablePrefixed, $this->getQueryPartExpiryTime());
Db::query($sql, array($key));
Expand Down
7 changes: 6 additions & 1 deletion app/core/Cookie.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ class Cookie
*/
protected $path = '';

/**
* @var string
*/
protected $keyStore = false;

/**
* Restrict cookie to a domain (or subdomains)
* @var string
Expand Down Expand Up @@ -456,7 +461,7 @@ private static function getSameSiteValueForBrowser($default)
} else {
$userAgent = Http::getUserAgent();
$ddFactory = StaticContainer::get(\Piwik\DeviceDetector\DeviceDetectorFactory::class);
$deviceDetector = $ddFactory->makeInstance($userAgent);
$deviceDetector = $ddFactory->makeInstance($userAgent, Http::getClientHintsFromServerVariables());
$deviceDetector->parse();

$browserFamily = \DeviceDetector\Parser\Client\Browser::getBrowserFamily($deviceDetector->getClient('short_name'));
Expand Down
17 changes: 12 additions & 5 deletions app/core/CronArchive.php
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,7 @@ private function invalidateArchivedReportsForSitesThatNeedToBeArchivedAgainImpl(

$this->logger->debug(' Invalidating custom date range ({date}) for site {idSite}', ['idSite' => $idSiteToInvalidate, 'date' => $date]);

$this->invalidateWithSegments($idSiteToInvalidate, $date, 'range', $_forceInvalidateNonexistant = true);
$this->invalidateWithSegments($idSiteToInvalidate, $date, 'range', $_forceInvalidateNonexistent = true);
}

$this->setInvalidationTime();
Expand Down Expand Up @@ -902,7 +902,7 @@ public function invalidateRecentDate($dateStr, $idSite)
$this->invalidateWithSegments([$idSite], $date->toString(), 'day', false, $doNotIncludeTtlInExistingArchiveCheck = $isYesterday);
}

private function invalidateWithSegments($idSites, $date, $period, $_forceInvalidateNonexistant = false, $doNotIncludeTtlInExistingArchiveCheck = false)
private function invalidateWithSegments($idSites, $date, $period, $_forceInvalidateNonexistent = false, $doNotIncludeTtlInExistingArchiveCheck = false)
{
if ($date instanceof Date) {
$date = $date->toString();
Expand All @@ -924,7 +924,7 @@ private function invalidateWithSegments($idSites, $date, $period, $_forceInvalid
$this->logger->debug(' Found usable archive for {archive}, skipping invalidation.', ['archive' => $params]);
} else {
$this->getApiToInvalidateArchivedReport()->invalidateArchivedReports($idSite, $date, $period, $segment = false, $cascadeDown = false,
$_forceInvalidateNonexistant);
$_forceInvalidateNonexistent);
}

foreach ($this->segmentArchiving->getAllSegmentsToArchive($idSite) as $segmentDefinition) {
Expand Down Expand Up @@ -955,7 +955,7 @@ private function invalidateWithSegments($idSites, $date, $period, $_forceInvalid
}

$this->getApiToInvalidateArchivedReport()->invalidateArchivedReports($idSite, $date, $period, $segmentDefinition,
$cascadeDown = false, $_forceInvalidateNonexistant);
$cascadeDown = false, $_forceInvalidateNonexistent);
}
}
}
Expand Down Expand Up @@ -1054,13 +1054,20 @@ public function repairInvalidationsIfNeeded($archiveToProcess)
continue;
}

// archive is for week that is over two months, we don't need to care about the month
// archive is for a week that is over two months, we don't need to care about the month
if ($label == 'month'
&& Date::factory($archiveToProcess['date1'])->toString('m') != Date::factory($archiveToProcess['date2'])->toString('m')
) {
continue;
}

// archive is for a week that is over two years, we don't need to care about the year
if ($label == 'year'
&& Date::factory($archiveToProcess['date1'])->toString('y') != Date::factory($archiveToProcess['date2'])->toString('y')
) {
continue;
}

$period = Period\Factory::build($label, $archiveToProcess['date1']);

$invalidationToInsert = [
Expand Down
2 changes: 1 addition & 1 deletion app/core/DataAccess/ArchiveSelector.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ public static function getArchiveData($archiveIds, $recordNames, $archiveDataTyp
// select a subtable id
$bind = array();
foreach ($recordNames as $recordName) {
// to be backwards compatibe we need to look for the exact idSubtable blob and for the chunk
// to be backwards compatible we need to look for the exact idSubtable blob and for the chunk
// that stores the subtables (a chunk stores many blobs in one blob)
$bind[] = $chunk->getRecordNameForTableId($recordName, $idSubtable);
$bind[] = self::appendIdSubtable($recordName, $idSubtable);
Expand Down
6 changes: 3 additions & 3 deletions app/core/DataAccess/LogAggregator.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,9 @@ public function getSegment()
return $this->segment;
}

public function setQueryOriginHint($nameOfOrigiin)
public function setQueryOriginHint($nameOfOrigin)
{
$this->queryOriginHint = $nameOfOrigiin;
$this->queryOriginHint = $nameOfOrigin;
}

public function getSegmentTmpTableName()
Expand Down Expand Up @@ -321,7 +321,7 @@ private function createTemporaryTable($unprefixedSegmentTableName, $segmentSelec
return;
}

$insertIntoStatement = 'INSERT INTO ' . $table . ' (idvisit) ' . $segmentSelectSql;
$insertIntoStatement = 'INSERT IGNORE INTO ' . $table . ' (idvisit) ' . $segmentSelectSql;
$readerDb->query($insertIntoStatement, $segmentSelectBind);

$transactionLevel->restorePreviousStatus();
Expand Down
4 changes: 2 additions & 2 deletions app/core/DataAccess/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public function getPlaceholderArchiveIds($archiveTable)
}

public function updateArchiveAsInvalidated($archiveTable, $idSites, $allPeriodsToInvalidate, Segment $segment = null,
$forceInvalidateNonexistantRanges = false, $name = null)
$forceInvalidateNonexistentRanges = false, $name = null)
{
if (empty($idSites)) {
return 0;
Expand Down Expand Up @@ -220,7 +220,7 @@ public function updateArchiveAsInvalidated($archiveTable, $idSites, $allPeriodsT
$siteCreationTime = Date::factory($siteCreationTime);
foreach ($allPeriodsToInvalidate as $period) {
if ($period->getLabel() == 'range'
&& !$forceInvalidateNonexistantRanges
&& !$forceInvalidateNonexistentRanges
) {
continue; // range
}
Expand Down
2 changes: 1 addition & 1 deletion app/core/DataTable/Filter/Truncate.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ private function addSummaryRow($table)

for ($i = $this->truncateAfter; $i < $count; $i++) {
if (!isset($rows[$i])) {
// case when the last row is a summary row, it is not indexed by $cout but by DataTable::ID_SUMMARY_ROW
// case when the last row is a summary row, it is not indexed by $count but by DataTable::ID_SUMMARY_ROW
$summaryRow = $table->getRowFromId(DataTable::ID_SUMMARY_ROW);

//FIXME: I'm not sure why it could return false, but it was reported in: http://forum.piwik.org/read.php?2,89324,page=1#msg-89442
Expand Down
2 changes: 1 addition & 1 deletion app/core/DataTable/Map.php
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ public function getColumn($name)
* query results into one DataTable w/ different rows differentiated by site ID.
*
* Note: This DataTable/Map will be destroyed and will be no longer usable after the tables have been merged into
* the new dataTable to reduce memory usage. Destroying all DataTables witihn the Map also seems to fix a
* the new dataTable to reduce memory usage. Destroying all DataTables within the Map also seems to fix a
* Segmentation Fault that occurred in the AllWebsitesDashboard when having > 16k sites.
*
* @return DataTable|Map
Expand Down
11 changes: 6 additions & 5 deletions app/core/DataTable/Renderer/Csv.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,12 @@ protected function formatValue($value)

$value = $this->formatFormulas($value);

if (is_string($value)
&& (strpos($value, '"') !== false
|| strpos($value, $this->separator) !== false)
) {
$value = '"' . str_replace('"', '""', $value) . '"';
if (is_string($value)) {
$value = str_replace(["\t"], ' ', $value);

if (strpos($value, '"') !== false || strpos($value, $this->separator) !== false) {
$value = '"' . str_replace('"', '""', $value) . '"';
}
}

// in some number formats (e.g. German), the decimal separator is a comma
Expand Down
Loading

0 comments on commit 42409fd

Please sign in to comment.