Passed
Branch feature/v2 (61dd95)
by Valentin
05:53
created

Extract::fillGaps()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 22
Code Lines 14

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 14
nc 2
nop 4
1
<?php
2
3
namespace Spiral\Statistics;
4
5
use Spiral\Statistics\Database\Sources\StatisticsSource;
6
use Spiral\Statistics\Database\Statistics;
7
use Spiral\Statistics\Exceptions\EmptyExtractEventsException;
8
use Spiral\Statistics\Extract\Range;
9
use Spiral\Statistics\Extract\Events;
10
use Spiral\Statistics\Extract\RangeInterface;
11
12
class Extract
13
{
14
    /** @var StatisticsSource */
15
    protected $source;
16
17
    /** @var DatetimeConverter */
18
    protected $converter;
19
20
    /**
21
     * Extract constructor.
22
     *
23
     * @param DatetimeConverter $converter
24
     * @param StatisticsSource  $source
25
     */
26
    public function __construct(
27
        DatetimeConverter $converter,
28
        StatisticsSource $source
29
    ) {
30
        $this->source = $source;
31
        $this->converter = $converter;
32
    }
33
34
35
    public function events(
36
        \DateTimeInterface $start,
37
        \DateTimeInterface $end,
38
        RangeInterface $range,
39
        array $eventsInput
40
    ): Events
41
    {
42
        if (empty($eventsInput)) {
43
            throw new EmptyExtractEventsException();
44
        }
45
46
        $start = $this->converter->immutable($start);
47
        $end = $this->converter->immutable($end);
48
49
        //Swap start and end dates if incorrect
50
        if ($start > $end) {
51
            list($start, $end) = [$end, $start];
52
        }
53
54
        $events = new Events($eventsInput);
55
56
        $queried = $this->source->findExtract($start, $end, $eventsInput);
57
        $lastDatetime = clone $start;
58
        $row = $events->addRow($start->format($range->getFormat()));
59
60
        /** @var Statistics $extracted */
61
        foreach ($queried as $extracted) {
62
            $row = $this->fillGaps($lastDatetime, $extracted->timestamp, $events, $range) ?? $row;
63
64
            $row->addEvent($extracted->name, $extracted->value);
65
        }
66
67
        $this->fillGaps($lastDatetime, $end, $events, $range);
68
69
        return $events;
70
    }
71
72
    /**
73
     * Add blank rows if between passed current datetime and passed end datetime can be placed
74
     * blank rows without any events occurred. Return result is last filled row if gaps were
75
     * filled or null.
76
     *
77
     * @param \DateTimeInterface|\DateTimeImmutable $current
78
     * @param \DateTimeInterface                    $end
79
     * @param Events                                $events
80
     * @param RangeInterface                        $range
81
     * @return Events\Row|null
82
     */
83
    protected function fillGaps(
84
        \DateTimeInterface &$current,
85
        \DateTimeInterface $end,
86
        Events $events,
87
        RangeInterface $range
88
    ) {
89
        $lastRow = null;
90
        $lastDatetimeConverted = $this->converter->convert($current, $range);
91
        $endDatetimeConverted = $this->converter->convert($end, $range);
92
93
        if ($lastDatetimeConverted < $endDatetimeConverted) {
94
            //one of next intervals, need to add blank rows;
95
            while ($lastDatetimeConverted < $endDatetimeConverted) {
96
                $current = $current->add($range->getInterval());
97
                $lastDatetimeConverted = $this->converter->convert($current, $range);
98
99
                $lastRow = $events->addRow($current->format($range->getFormat()));
100
            }
101
        }
102
103
        return $lastRow;
104
    }
105
}