Completed
Push — issue/280 ( f98ca8...a6a6bd )
by Alex
02:05
created

UpdateStats::computeNextUpdate()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 14
cts 14
cp 1
rs 9.568
c 0
b 0
f 0
cc 4
nc 6
nop 2
crap 4
1
<?php declare(strict_types=1);
2
/*
3
 * This file is part of the feed-io package.
4
 *
5
 * (c) Alexandre Debril <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace FeedIo\Reader\Result;
12
13
use FeedIo\Feed\ItemInterface;
14
use FeedIo\FeedInterface;
15
16
class UpdateStats
17
{
18
    const DEFAULT_MIN_DELAY = 3600;
19
20
    const DEFAULT_MARGIN_RATIO = 0.1;
21
22
    protected $feed;
23
24
    protected $intervals;
25
26 1
    public function __construct(FeedInterface $feed)
27
    {
28 1
        $this->feed = $feed;
29 1
        $this->intervals = $this->computeIntervals($this->extractDates($feed));
30 1
    }
31
32 1
    public function computeNextUpdate(
33
        int $minDelay = self::DEFAULT_MIN_DELAY,
34
        float $marginRatio = self::DEFAULT_MARGIN_RATIO
35
    ): \DateTime {
36 1
        $feedTimeStamp = !! $this->feed->getLastModified() ? $this->feed->getLastModified()->getTimestamp():time();
37 1
        $now = time();
38
        $intervals = [
39 1
            $this->getMinInterval(),
40 1
            $this->getAverageInterval(),
41 1
            $this->getMedianInterval(),
42
        ];
43 1
        sort($intervals);
44 1
        $newTimestamp = $now + $minDelay;
45 1
        foreach ($intervals as $interval) {
46 1
            $computedTimestamp = $feedTimeStamp + intval($interval + $marginRatio * $interval);
47 1
            if ($computedTimestamp > $now) {
48 1
                $newTimestamp = $computedTimestamp;
49 1
                break;
50
            }
51
        }
52 1
        return (new \DateTime())->setTimestamp($newTimestamp);
53
    }
54
55
    /**
56
     * @return array
57
     */
58 1
    public function getIntervals(): array
59
    {
60 1
        return $this->intervals;
61
    }
62
63 1
    public function getMinInterval(): int
64
    {
65 1
        return min($this->intervals);
66
    }
67
68 1
    public function getAverageInterval(): int
69
    {
70 1
        $total = array_sum($this->intervals);
71
72 1
        return intval(floor($total / count($this->intervals)));
73
    }
74
75 1
    public function getMedianInterval(): int
76
    {
77 1
        $num = floor(count($this->intervals) / 2);
78
79 1
        return $this->intervals[$num];
80
    }
81
82 1
    private function computeIntervals(array $dates): array
83
    {
84 1
        rsort($dates);
85 1
        $intervals = [];
86 1
        $current = 0;
87 1
        foreach ($dates as $date) {
88 1
            if ($current > 0) {
89 1
                $intervals[] = $current - $date;
90
            }
91 1
            $current = $date;
92
        }
93 1
        return $intervals;
94
    }
95
96 1
    private function extractDates(FeedInterface $feed): array
97
    {
98 1
        $dates = [];
99 1
        foreach ($feed as $item) {
100 1
            $dates[] = $this->getTimestamp($item);
101
        }
102 1
        return $dates;
103
    }
104
105 1
    private function getTimestamp(ItemInterface $item): ? int
106
    {
107 1
        return $item->getLastModified()->getTimestamp();
108
    }
109
}
110