ServerApplication::initLoop()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
namespace Fructify\Reload\Application;
3
4
use Symfony\Component\Console\Output\OutputInterface;
5
use React\EventLoop\Factory as LoopFactory;
6
use React\Socket\Server as SocketServer;
7
use Fructify\Reload\Protocol;
8
use Symfony\Component\Finder\Finder;
9
10
class ServerApplication
11
{
12
    protected $output;
13
    protected $loop;
14
    protected $clients = array();
15
    protected $config = array(
16
        'liveCSS' => true,
17
    );
18
    protected $watchConfig;
19
    protected $watchingFiles = array();
20
21
    public function __construct($host = '127.0.0.1', $port = 35729)
22
    {
23
        $this->initLoop();
24
        $this->initServer($host, $port);
25
    }
26
27
    public function setOutput(OutputInterface $output)
28
    {
29
        $this->output = $output;
30
    }
31
32
    /**
33
     *
34
     * @return OutputInterface
35
     */
36
    public function getOutput()
37
    {
38
        return $this->output;
39
    }
40
41
    public function run()
42
    {
43
        $this->loop->run();
44
    }
45
46
    public function getConfig()
47
    {
48
        return $this->config;
49
    }
50
51
    public function watching($time, $config)
52
    {
53
        $this->watchConfig = $config;
54
        $this->scanFiles();
55
        $this->loop->addPeriodicTimer($time, function(){
56
            $this->watchingFileChange();
57
        });
58
    }
59
60
    protected function scanFiles($scanNewFile = true)
61
    {
62
        foreach($this->watchConfig['watch'] as $path => $file){
63
            $finder = new Finder();
64
            try{
65
                foreach($finder->in($path)->name($file)->followLinks() as $file){
66
                    if($file->getRealPath() && !isset($this->watchingFiles[$file->getRealpath()])){
67
                        $this->watchingFiles[$file->getRealpath()] = $scanNewFile?$file->getMTime():0;
68
                    }
69
                }
70
            }
71
            catch(\InvalidArgumentException $e){
72
                continue;
73
            }
74
        }
75
    }
76
77
    protected function watchingFileChange()
78
    {
79
        $this->scanFiles(false);
80
        foreach($this->watchingFiles as $file => $time){
81
            $mtime = @filemtime($file);
82
            if($mtime && $mtime > $time){
83
                $this->watchingFiles[$file] = $mtime;
84
                $this->reloadFile($file);
85
            }
86
        }
87
    }
88
89
    protected function initLoop()
90
    {
91
        $this->loop = LoopFactory::create();
92
    }
93
94
    protected function initServer($host, $port)
95
    {
96
        $socket = new SocketServer($this->loop);
97
        $socket->listen($port, $host);
98
        return new Protocol\HttpProtocol($socket, $this);
99
    }
100
101
    public function addClient(Protocol\LivereloadProtocol $client)
102
    {
103
        if(!in_array($client, $this->clients)){
104
            $this->clients[] = $client;
105
        }
106
    }
107
108
    public function removeClient(Protocol\LivereloadProtocol $client)
109
    {
110
        $index = array_search($client, $this->clients, true);
111
        if($index === false){
112
            return;
113
        }
114
        unset($this->clients[$index]);
115
    }
116
117
    public function reloadFile($file)
118
    {
119
        foreach($this->clients as $client){
120
            $client->reload($file, $this->config);
121
        }
122
    }
123
}