Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
CertificateActivityCollector
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
4 / 4
8
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 metricIds
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 collect
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 isHistoryComplete
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3declare(strict_types=1);
4/**
5 * SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
6 * SPDX-License-Identifier: AGPL-3.0-or-later
7 */
8
9namespace OCA\Libresign\Service\UsageStatistics\Collector;
10
11use OCA\Libresign\Service\UsageStatistics\Contract\IMetricCollector;
12use OCA\Libresign\Service\UsageStatistics\Model\MetricValue;
13use OCA\Libresign\Service\UsageStatistics\Model\ReportMode;
14use OCA\Libresign\Service\UsageStatistics\Model\ReportPeriod;
15use OCA\Libresign\Service\UsageStatistics\Source\UsageActivityReader;
16
17/**
18 * Certificates are recorded only since LibreSign 12.1 (OpenSSL) and 12.2/13
19 * (CFSSL); nothing issued before that can be counted. The counts are known
20 * for a period when recording already covered the first LibreSign activity
21 * (a fresh install creates its root CA first), or when the period starts
22 * after the first recorded certificate (an upgraded instance).
23 */
24class CertificateActivityCollector implements IMetricCollector {
25    public function __construct(
26        private UsageActivityReader $reader,
27    ) {
28    }
29
30    #[\Override]
31    public function metricIds(): array {
32        return ['certificate.certificates_issued', 'certificate.certificates_revoked'];
33    }
34
35    #[\Override]
36    public function collect(ReportPeriod $period, ReportMode $mode): array {
37        if (!$this->isHistoryComplete($period)) {
38            return [
39                'certificate.certificates_issued' => MetricValue::unavailable(),
40                'certificate.certificates_revoked' => MetricValue::unavailable(),
41            ];
42        }
43        return [
44            'certificate.certificates_issued' => MetricValue::of($this->reader->countSigningCertificatesIssued($period)),
45            'certificate.certificates_revoked' => MetricValue::of($this->reader->countSigningCertificatesRevoked($period)),
46        ];
47    }
48
49    private function isHistoryComplete(ReportPeriod $period): bool {
50        $firstActivityAt = $this->reader->firstActivityAt();
51        $firstCertificateAt = $this->reader->firstCertificateRecordedAt();
52        if ($firstCertificateAt === null) {
53            return $firstActivityAt === null;
54        }
55        if ($firstActivityAt === null || $firstCertificateAt <= $firstActivityAt) {
56            return true;
57        }
58        return $period->start() >= $firstCertificateAt;
59    }
60}