Passed
Push — master ( 823aee...b9b37f )
by Alec
13:15 queued 12s
created

RevoltLoopAdapter   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 78
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 29
c 1
b 0
f 0
dl 0
loc 78
rs 10
wmc 15

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getLoop() 0 3 1
A detachSpinner() 0 4 2
A delay() 0 4 1
A onSignal() 0 4 1
A assertExtPcntl() 0 10 4
A repeat() 0 4 1
A attach() 0 7 1
A autoStart() 0 18 4
1
<?php
2
3
declare(strict_types=1);
4
// 17.02.23
5
6
namespace AlecRabbit\Spinner\Asynchronous\Loop\Adapter;
7
8
use AlecRabbit\Spinner\Asynchronous\Loop\Adapter\A\ALoopAdapter;
9
use AlecRabbit\Spinner\Core\Contract\ISpinner;
10
use Closure;
11
use React\EventLoop\LoopInterface;
12
use Revolt\EventLoop;
13
use Revolt\EventLoop\Driver;
14
use Revolt\EventLoop\Driver\EvDriver;
15
use Revolt\EventLoop\Driver\EventDriver;
16
use Revolt\EventLoop\Driver\UvDriver;
17
18
class RevoltLoopAdapter extends ALoopAdapter
19
{
20
    private static bool $stopped = false;
21
    private ?string $spinnerTimer = null;
22
23
    public function attach(ISpinner $spinner): void
24
    {
25
        $this->detachSpinner();
26
        $this->spinnerTimer =
27
            EventLoop::repeat(
28
                $spinner->getInterval()->toSeconds(),
29
                static fn() => $spinner->spin()
30
            );
31
    }
32
33
    protected function detachSpinner(): void
34
    {
35
        if ($this->spinnerTimer) {
36
            EventLoop::cancel($this->spinnerTimer);
37
        }
38
    }
39
40
    public function repeat(float $interval, Closure $closure): void
41
    {
42
        /** @psalm-suppress MixedArgumentTypeCoercion */
43
        EventLoop::repeat($interval, $closure);
44
    }
45
46
    public function autoStart(): void
47
    {
48
        // Automatically run loop at end of program, unless already started or stopped explicitly.
49
        // @codeCoverageIgnoreStart
50
        $hasRun = false;
51
        EventLoop::defer(static function () use (&$hasRun): void {
52
            $hasRun = true;
53
        });
54
55
        $stopped =& self::$stopped;
56
        register_shutdown_function(static function () use (&$hasRun, &$stopped) {
57
            // Don't run if we're coming from a fatal error (uncaught exception).
58
            if (self::error()) {
59
                return;
60
            }
61
62
            if (!$hasRun && !$stopped) {
63
                EventLoop::run();
64
            }
65
        });
66
        // @codeCoverageIgnoreEnd
67
    }
68
69
    public function delay(float $delay, Closure $closure): void
70
    {
71
        /** @psalm-suppress MixedArgumentTypeCoercion */
72
        EventLoop::delay($delay, $closure);
73
    }
74
75
    protected function assertExtPcntl(): void
76
    {
77
        $driver = $this->getLoop();
78
        if ($driver instanceof UvDriver
79
            || $driver instanceof EvDriver
80
            || $driver instanceof EventDriver) {
81
            return; // these drivers do not require pcntl extension
82
        }
83
84
        parent::assertExtPcntl();
85
    }
86
87
    public function getLoop(): LoopInterface|Driver
88
    {
89
        return EventLoop::getDriver();
90
    }
91
92
    protected function onSignal(int $signal, Closure $closure): void
93
    {
94
        /** @psalm-suppress MixedArgumentTypeCoercion */
95
        EventLoop::onSignal($signal, $closure);
96
    }
97
}
98