File: ArchiveState.php

package info (click to toggle)
matomo 5.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 95,068 kB
  • sloc: php: 289,425; xml: 127,249; javascript: 112,130; python: 202; sh: 178; makefile: 20; sql: 10
file content (132 lines) | stat: -rw-r--r-- 4,174 bytes parent folder | download | duplicates (2)
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;
    }
}