1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
<?php
/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
declare(strict_types=1);
namespace Piwik\Archive;
use Piwik\DataAccess\ArchiveWriter;
use Piwik\DataTable;
use Piwik\Date;
use Piwik\Site;
class ArchiveState
{
public const COMPLETE = 'complete';
public const INCOMPLETE = 'incomplete';
public const INVALIDATED = 'invalidated';
/**
* @param array{date1: string, date2: string, idsite: string, ts_archived: string} $archiveData
* @param array<string, array<int>> $archiveIds archives ids indexed by period
* @param array<int, array<string, array<int, int>>> $archiveStates archive states indexed by site and period
*/
public function addMetadataToResultCollection(
DataCollection $collection,
array $archiveData,
array $archiveIds,
array $archiveStates
): void {
$periodsEndDays = [];
$periodsTsArchived = [];
$archiveIdsFlipped = [];
foreach ($archiveData as $archive) {
$idSite = (int) $archive['idsite'];
$period = $archive['date1'] . ',' . $archive['date2'];
$periodsEndDays[$idSite][$period] = $archive['date2'];
$periodsTsArchived[$idSite][$period] = $archive['ts_archived'];
}
foreach ($archiveIds as $period => $periodArchiveIds) {
$archiveIdsFlipped[$period] = array_flip($periodArchiveIds);
}
foreach ($periodsTsArchived as $idSite => $periods) {
$siteTimezone = Site::getTimezoneFor($idSite);
foreach ($periods as $period => $tsArchived) {
$periodEndDay = $periodsEndDays[$idSite][$period];
$state = $this->checkArchiveStates($idSite, $period, $archiveIdsFlipped, $archiveStates);
$state = $this->checkTsArchived($state, $siteTimezone, $periodEndDay, $tsArchived);
if (null === $state) {
// do not set metadata, if no state was determined,
// to avoid generating unexpected default rows
continue;
}
$collection->addMetadata(
$idSite,
$period,
DataTable::ARCHIVE_STATE_METADATA_NAME,
$state
);
}
}
}
/**
* @param array<string, array<int, bool>> $archiveIdsFlipped
* @param array<int, array<string, array<int, int>>> $archiveStates
*/
private function checkArchiveStates(
int $idSite,
string $period,
array $archiveIdsFlipped,
array $archiveStates
): ?string {
if (!isset($archiveStates[$idSite][$period]) || !isset($archiveIdsFlipped[$period])) {
// do not determine state if no archives were used
return null;
}
$availableStates = array_intersect_key(
$archiveStates[$idSite][$period],
$archiveIdsFlipped[$period]
);
if ([] === $availableStates) {
// do not determine state if no archives were used
return null;
}
if (in_array(ArchiveWriter::DONE_INVALIDATED, $availableStates)) {
// archive has been invalidated
return self::INVALIDATED;
}
// all archives not invalidated should be complete
// includes DONE_OK, DONE_OK_TEMPORARY and DONE_PARTIAL
return self::COMPLETE;
}
private function checkTsArchived(
?string $state,
string $siteTimezone,
string $periodEndDay,
string $tsArchived
): ?string {
if (self::COMPLETE !== $state) {
// only archives detected as complete can be archived before range end
return $state;
}
$datePeriodEnd = Date::factory($periodEndDay . ' 23:59:59')->setTimezone($siteTimezone);
$dateArchived = Date::factory($tsArchived);
if (!$datePeriodEnd->isEarlier($dateArchived)) {
return self::INCOMPLETE;
}
return $state;
}
}
|