Inotify::__destruct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
0 ignored issues
show
Coding Style introduced by
Missing file doc comment
Loading history...
3
namespace Hhxsv5\LaravelS\Swoole;
4
5
use Swoole\Event;
6
use Swoole\Timer;
7
8
class Inotify
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class Inotify
Loading history...
9
{
10
    private $fd;
0 ignored issues
show
Coding Style introduced by
Private member variable "fd" must be prefixed with an underscore
Loading history...
11
    private $watchPath;
0 ignored issues
show
Coding Style introduced by
Private member variable "watchPath" must be prefixed with an underscore
Loading history...
12
    private $watchMask;
0 ignored issues
show
Coding Style introduced by
Private member variable "watchMask" must be prefixed with an underscore
Loading history...
13
    private $watchHandler;
0 ignored issues
show
Coding Style introduced by
Private member variable "watchHandler" must be prefixed with an underscore
Loading history...
14
    private $doing        = false;
0 ignored issues
show
Coding Style introduced by
Private member variable "doing" must be prefixed with an underscore
Loading history...
15
    private $fileTypes    = [];
0 ignored issues
show
Coding Style introduced by
Private member variable "fileTypes" must be prefixed with an underscore
Loading history...
16
    private $excludedDirs = [];
0 ignored issues
show
Coding Style introduced by
Private member variable "excludedDirs" must be prefixed with an underscore
Loading history...
17
    private $wdPath       = [];
0 ignored issues
show
Coding Style introduced by
Private member variable "wdPath" must be prefixed with an underscore
Loading history...
18
    private $pathWd       = [];
0 ignored issues
show
Coding Style introduced by
Private member variable "pathWd" must be prefixed with an underscore
Loading history...
19
20
    public function __construct($watchPath, $watchMask, callable $watchHandler)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
21
    {
22
        $this->fd = inotify_init();
23
        $this->watchPath = $watchPath;
24
        $this->watchMask = $watchMask;
25
        $this->watchHandler = $watchHandler;
26
    }
27
28
    public function addFileType($type)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function addFileType()
Loading history...
29
    {
30
        $type = '.' . trim($type, '.');
31
        $this->fileTypes[$type] = true;
32
    }
33
34
    public function addFileTypes(array $types)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function addFileTypes()
Loading history...
35
    {
36
        foreach ($types as $type) {
37
            $this->addFileType($type);
38
        }
39
    }
40
41
    public function addExcludedDir($dir)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function addExcludedDir()
Loading history...
42
    {
43
        $dir = realpath($dir);
44
        $this->excludedDirs[$dir] = $dir;
45
    }
46
47
    public function addExcludedDirs(array $dirs)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function addExcludedDirs()
Loading history...
48
    {
49
        foreach ($dirs as $dir) {
50
            $this->addExcludedDir($dir);
51
        }
52
    }
53
54
    public function isExcluded($path)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function isExcluded()
Loading history...
55
    {
56
        foreach ($this->excludedDirs as $excludedDir) {
57
            if ($excludedDir === $path || strpos($path, $excludedDir . '/') === 0) {
58
                return true;
59
            }
60
        }
61
        return false;
62
    }
63
64
    public function watch()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function watch()
Loading history...
65
    {
66
        $this->_watch($this->watchPath);
67
    }
68
69
    protected function _watch($path)
0 ignored issues
show
Coding Style introduced by
Protected method name "Inotify::_watch" must not be prefixed with an underscore
Loading history...
Coding Style introduced by
Missing doc comment for function _watch()
Loading history...
70
    {
71
        if ($this->isExcluded($path)) {
72
            return false;
73
        }
74
        $wd = inotify_add_watch($this->fd, $path, $this->watchMask);
75
        if ($wd === false) {
76
            return false;
77
        }
78
        $this->bind($wd, $path);
79
80
        if (is_dir($path)) {
81
            $wd = inotify_add_watch($this->fd, $path, $this->watchMask);
82
            if ($wd === false) {
83
                return false;
84
            }
85
            $this->bind($wd, $path);
86
            $files = scandir($path);
87
            foreach ($files as $file) {
88
                if ($file === '.' || $file === '..' || $this->isExcluded($file)) {
89
                    continue;
90
                }
91
                $file = $path . DIRECTORY_SEPARATOR . $file;
92
                if (is_dir($file)) {
93
                    $this->_watch($file);
94
                }
95
            }
96
        }
97
        return true;
98
    }
99
100
    protected function clearWatch()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function clearWatch()
Loading history...
101
    {
102
        foreach ($this->wdPath as $wd => $path) {
103
            @inotify_rm_watch($this->fd, $wd);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for inotify_rm_watch(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

103
            /** @scrutinizer ignore-unhandled */ @inotify_rm_watch($this->fd, $wd);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
104
        }
105
        $this->wdPath = [];
106
        $this->pathWd = [];
107
    }
108
109
    protected function bind($wd, $path)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function bind()
Loading history...
110
    {
111
        $this->pathWd[$path] = $wd;
112
        $this->wdPath[$wd] = $path;
113
    }
114
115
    protected function unbind($wd, $path = null)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function unbind()
Loading history...
116
    {
117
        unset($this->wdPath[$wd]);
118
        if ($path !== null) {
119
            unset($this->pathWd[$path]);
120
        }
121
    }
122
123
    public function start()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function start()
Loading history...
124
    {
125
        Event::add($this->fd, function ($fp) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
126
            $events = inotify_read($fp);
127
            foreach ($events as $event) {
128
                if ($event['mask'] == IN_IGNORED) {
129
                    continue;
130
                }
131
132
                $fileType = strchr($event['name'], '.');
133
                if (!isset($this->fileTypes[$fileType])) {
134
                    continue;
135
                }
136
137
                if ($this->doing) {
138
                    continue;
139
                }
140
141
                Timer::after(100, function () use ($event) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
142
                    call_user_func_array($this->watchHandler, [$event]);
143
                    $this->doing = false;
144
                });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
145
                $this->doing = true;
146
                break;
147
            }
148
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
149
        Event::wait();
150
    }
151
152
    public function stop()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function stop()
Loading history...
153
    {
154
        Event::del($this->fd);
155
        fclose($this->fd);
156
    }
157
158
    public function getWatchedFileCount()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getWatchedFileCount()
Loading history...
159
    {
160
        return count($this->wdPath);
161
    }
162
163
    public function __destruct()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __destruct()
Loading history...
164
    {
165
        $this->stop();
166
    }
167
}
168