SneakyTestClock::sneakilySetClock()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php declare(strict_types=1);
2
3
namespace Stratadox\Clock;
4
5
use DateInterval;
6
use DateTimeInterface;
7
8
/**
9
 * SneakyTestClock. This clock is very sneaky. Only use it in your test code.
10
 * The basic idea is you inject a clock into your service, in production that's
11
 * a regular clock, and for testing you can inject this one instead and simulate
12
 * the passing of time by altering the clock instance(s).
13
 *
14
 * @author Stratadox
15
 */
16
final class SneakyTestClock implements RewindableClock
17
{
18
    /** @var RewindableClock */
19
    private $clock;
20
21
    private static $rewinds;
22
    private static $fastForwards;
23
    private static $sneaky;
24
25
    private function __construct(RewindableClock $clock)
26
    {
27
        $this->clock = $clock;
28
        self::$rewinds = [];
29
        self::$fastForwards = [];
30
        self::$sneaky = null;
31
    }
32
33
    public static function create(): self
34
    {
35
        return new self(RewindableDateTimeClock::create());
36
    }
37
38
    public static function using(RewindableClock $clock): self
39
    {
40
        return new self($clock);
41
    }
42
43
    public function now(): DateTimeInterface
44
    {
45
        $datetime = (self::$sneaky ?: $this->clock)->now();
46
        foreach (self::$rewinds as $rewind) {
47
            $datetime = $datetime->sub($rewind);
48
        }
49
        foreach (self::$fastForwards as $fastForward) {
50
            $datetime = $datetime->add($fastForward);
51
        }
52
        return $datetime;
53
    }
54
55
    public function rewind(DateInterval $interval): RewindableClock
56
    {
57
        $new = clone $this;
58
        $new->clock = $this->clock->rewind($interval);
59
        return $new;
60
    }
61
62
    public function fastForward(DateInterval $interval): RewindableClock
63
    {
64
        $new = clone $this;
65
        $new->clock = $this->clock->fastForward($interval);
66
        return $new;
67
    }
68
69
    public function sneakilySetClock(RewindableClock $clock): void
70
    {
71
        self::$sneaky = $clock;
72
    }
73
74
    public function sneakBack(DateInterval $interval): void
75
    {
76
        self::$rewinds[] = $interval;
77
    }
78
79
    public function sneakForwards(DateInterval $interval): void
80
    {
81
        self::$fastForwards[] = $interval;
82
    }
83
}
84