Passed
Push — master ( de3d61...be839c )
by Alec
13:42 queued 13s
created

DriverLinker::link()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 9
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
6
namespace AlecRabbit\Spinner\Core;
7
8
use AlecRabbit\Spinner\Contract\ISubject;
9
use AlecRabbit\Spinner\Contract\Option\OptionLinker;
10
use AlecRabbit\Spinner\Core\Contract\IDriver;
11
use AlecRabbit\Spinner\Core\Contract\IDriverLinker;
12
use AlecRabbit\Spinner\Core\Contract\Loop\Contract\ILoop;
13
use AlecRabbit\Spinner\Exception\LogicException;
14
15
final class DriverLinker implements IDriverLinker
16
{
17
    private mixed $timer = null;
18
    private ?IDriver $driver = null;
19
20
    public function __construct(
21
        private readonly ILoop $loop,
22
        private readonly OptionLinker $optionLinker,
23
    ) {
24
    }
25
26
    public function link(IDriver $driver): void
27
    {
28
        $this->assertDriver($driver);
29
30
        if ($this->optionLinker === OptionLinker::ENABLED) {
31
            $this->linkTimer($driver);
32
33
            if ($this->driver === null) {
34
                $this->observe($driver);
35
            }
36
        }
37
    }
38
39
    private function assertDriver(IDriver $driver): void
40
    {
41
        if ($this->driver === null || $this->driver === $driver) {
42
            return;
43
        }
44
        throw new LogicException(
45
            'Other instance of Driver is already linked.'
46
        );
47
    }
48
49
    private function linkTimer(IDriver $driver): void
50
    {
51
        $this->unlinkTimer();
52
53
        $interval = $driver->getInterval()->toSeconds();
54
55
        $this->timer =
56
            $this->loop->repeat(
57
                $interval,
58
                static fn() => $driver->render()
59
            );
60
    }
61
62
    private function unlinkTimer(): void
63
    {
64
        if ($this->timer) {
65
            $this->loop->cancel($this->timer);
66
            $this->timer = null;
67
        }
68
    }
69
70
    private function observe(IDriver $driver): void
71
    {
72
        $this->driver = $driver;
73
        $driver->attach($this);
74
    }
75
76
    public function update(ISubject $subject): void
77
    {
78
        if ($subject === $this->driver) {
0 ignored issues
show
introduced by
The condition $subject === $this->driver is always false.
Loading history...
79
            $this->linkTimer($subject);
80
        }
81
    }
82
}
83