SequenceProvider::getZeroSizedPoints()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 9.2
c 0
b 0
f 0
cc 3
eloc 13
nc 4
nop 2
1
<?php
2
3
namespace MS\Sentry\Monitor\Service\Diagram;
4
5
use Doctrine\DBAL\Connection;
6
7
class SequenceProvider
8
{
9
    /**
10
     * @var Connection
11
     */
12
    private $connection;
13
14
    /**
15
     * @param Connection $connection
16
     */
17
    public function __construct(Connection $connection)
18
    {
19
        $this->connection = $connection;
20
    }
21
22
    /**
23
     * @param array  $projects
24
     * @param string $days
25
     * @param string $scale
26
     *
27
     * @return array
28
     */
29
    public function getSequences(array $projects, $days, $scale)
30
    {
31
        if (false === filter_var($days, FILTER_VALIDATE_INT)) {
32
            throw new \InvalidArgumentException(sprintf('The days parameter "%s" should be an integer', $days));
33
        }
34
35
        if (false === in_array($scale, ['day', 'hour'])) {
36
            throw new \InvalidArgumentException(sprintf('The scale parameter "%s" should be "hour" or "day"', $scale));
37
        }
38
39
        $data = [];
40
        $datetimeFormat = $this->getDatetimeFormat($scale);
41
        $points = $this->getZeroSizedPoints($days, $scale);
42
43
        foreach ($projects as $project) {
44
            $data[] = [
45
                'label' => $project,
46
                'data' => $this->getFilledPoints($points, $datetimeFormat, $project)
47
            ];
48
        }
49
50
        return $data;
51
    }
52
53
    /**
54
     * @param string $days
55
     * @param string $scale
56
     *
57
     * @return array
58
     */
59
    private function getZeroSizedPoints($days, $scale)
60
    {
61
        $lastPoint = mktime(date('H'), 0, 0);
62
        $step = 3600;
63
64
        if ('day' === $scale) {
65
            $lastPoint = mktime(0, 0, 0);
66
            $step = $step * 24;
67
        }
68
69
        $firstPoint = strtotime(sprintf('-%s day', $days), $lastPoint);
70
        $points = [];
71
72
        foreach (range($firstPoint, $lastPoint, $step) as $point) {
73
            $points[] = [
74
                $point * 1000,
75
                0
76
            ];
77
        }
78
79
        return $points;
80
    }
81
82
    /**
83
     * @param string $scale
84
     *
85
     * @return string
86
     */
87
    private function getDatetimeFormat($scale)
88
    {
89
        $datetimeFormat = '%Y-%m-%d %H:00:00';
90
91
        if ('day' === $scale) {
92
            $datetimeFormat = '%Y-%m-%d 00:00:00';
93
        }
94
95
        return $datetimeFormat;
96
    }
97
98
    /**
99
     * @param array  $points
100
     * @param string $datetimeFormat
101
     * @param string $project
102
     *
103
     * @return array
104
     */
105
    private function getFilledPoints(array $points, $datetimeFormat, $project)
106
    {
107
        $events = $this->connection->fetchAll(
108
            'SELECT strftime(?, created) as hour, COUNT(*) as count FROM events WHERE project = ? GROUP BY hour ORDER BY hour DESC',
109
            [$datetimeFormat, $project]
110
        );
111
112
        foreach ($events as $event) {
113
            $timestamp = strtotime($event['hour']) * 1000;
114
            $key = array_search($timestamp, array_column($points, 0));
115
116
            if (false === $key) {
117
                break;
118
            }
119
120
            $points[$key] = [
121
                $timestamp,
122
                $event['count']
123
            ];
124
        }
125
126
        return $points;
127
    }
128
}
129