Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
DateManipulator
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
3 / 3
8
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getIntervalIdentifier
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
4
 getSteps
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace ContentTranslation;
4
5use Wikimedia\Timestamp\ConvertibleTimestamp;
6
7/**
8 * @author Niklas Laxström
9 */
10class DateManipulator {
11    public const WEEK = 'week';
12    public const MONTH = 'month';
13    private string $interval;
14
15    public function __construct( string $interval ) {
16        if ( $interval === self::WEEK || $interval === self::MONTH ) {
17            $this->interval = $interval;
18        } else {
19            throw new \InvalidArgumentException( 'Invalid interval' );
20        }
21    }
22
23    /**
24     * @param int|string|\DateTime $timestamp
25     * @return \DateTime
26     */
27    public function getIntervalIdentifier( $timestamp ) {
28        $unix = ConvertibleTimestamp::convert( TS_UNIX, $timestamp );
29
30        // UTC timezone is forced for unix timestamps
31        $datetime = new \DateTime( "@$unix" );
32        $datetime->setTime( 0, 0, 0 );
33
34        if ( $this->interval === self::WEEK ) {
35            // We use Sundays to indicate a given week from Monday to Sunday.
36            // Take the current day of the week (0 (for Sunday) through 6 (for Saturday))
37            $dow = (int)$datetime->format( 'w' );
38            if ( $dow > 0 ) {
39                $n = 7 - $dow;
40                $datetime->modify( "+$n days" );
41            }
42        } elseif ( $this->interval === self::MONTH ) {
43            // Use the first day of the month to identify a month
44            $n = (int)$datetime->format( 'j' ) - 1;
45            $datetime->modify( "-$n days" );
46        }
47
48        return $datetime;
49    }
50
51    public function getSteps( \DateTime $min, \DateTime $max ): array {
52        // Avoid modifying passed objects
53        $current = clone $min;
54        $interval = new \DateInterval( 'P1D' );
55
56        $steps = [];
57        // @phan-suppress-next-line PhanPossiblyInfiniteLoop
58        do {
59            $id = $this->getIntervalIdentifier( $current );
60            $steps[ $id->format( 'Y-m-d' ) ] = $id;
61            $current->add( $interval );
62        } while ( $current <= $max );
63
64        return $steps;
65    }
66}