Passed
Push — main ( a3578d...cf5a21 )
by Filipe
01:23 queued 31s
created

Watcher::checkExit()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 9
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 14
ccs 10
cts 10
cp 1
crap 2
rs 9.9666
1
<?php
2
3
/**
4
 * This file is part of fswatch
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Slick\FsWatch;
13
14
use Slick\FsWatch\Directory\Changes;
15
use Slick\FsWatch\Directory\FileChange;
16
use Slick\FsWatch\Directory\Snapshot;
17
use Slick\FsWatch\Exception\InvalidWatcherCallback;
18
19
/**
20
 * Watcher
21
 *
22
 * @package Slick\FsWatch
23
 */
24
final class Watcher
25
{
26
    public const SIGINT = 'SIGINT';
27
    public const ONCE = 'ONCE';
28
    public const FIRST_CHANGE = 'FIRST_CHANGE';
29
30
    /** @var callable|array<object|string> */
31
    private mixed $callback;
32
33
    private Snapshot $snapshot;
34
35
    private ?FileChange $lastChange = null;
36
37
    private ?Changes $changes = null;
38
39
40 3
    public function __construct(private readonly Directory $directory, mixed $callback)
41
    {
42 3
        $this->callback = $callback;
43 3
        $this->snapshot = new Snapshot($this->directory);
44
    }
45
46 2
    public function watch(mixed $exitStm = self::SIGINT, int $interval = 10): void
47
    {
48 2
        while ($this->checkExit($exitStm)) {
49 2
            $snapshot = $this->directory->snapshot();
50 2
            if ($this->snapshot->hash() !== $snapshot->hash()) {
51 2
                $this->changes = $this->snapshot->compareTo($snapshot);
52 2
                $this->snapshot = $snapshot;
53 2
                foreach ($this->changes as $file => $change) {
54 2
                    $this->lastChange = $change;
55 2
                    call_user_func([$this, "callback"], $file, $change);
56
                }
57
            }
58 2
            sleep($interval);
59
        }
60
    }
61
62
63 2
    private function checkExit(mixed $exitStm): bool
64
    {
65 2
        static $runs = -1;
66 2
        if (is_callable($exitStm)) {
67 1
            return !$exitStm(++$runs, $this->changes);
68
        }
69
70 1
        $runs++;
71
72 1
        return match ($exitStm) {
73 1
            self::SIGINT => true,
74 1
            self::ONCE => $runs < 1,
75 1
            self::FIRST_CHANGE => is_null($this->lastChange),
76 1
            default => !$exitStm
77 1
        };
78
    }
79
80 2
    private function callback(string $file, FileChange $changes): void
81
    {
82 2
        if (!is_callable($this->callback)) {
83
            throw new InvalidWatcherCallback(
84
                "Invalid callback passed to directory {$this->directory->path()} watcher."
85
            );
86
        }
87 2
        ($this->callback)($file, $changes);
88
    }
89
}
90