Completed
Push — master ( 0f4882...0b6865 )
by Roberto
03:52
created

Server::createSocketServer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 24
rs 9.536
c 0
b 0
f 0
1
<?php
2
3
namespace RedMoon\TinkerServer;
4
5
use Psy\Shell;
6
use Clue\React\Stdio\Stdio;
7
use React\EventLoop\Factory;
8
use React\EventLoop\LoopInterface;
9
use React\Socket\ConnectionInterface;
10
use React\Socket\Server as SocketServer;
11
use Symfony\Component\Console\Output\BufferedOutput;
12
use RedMoon\TinkerServer\Shell\ExecutionClosure;
13
14
class Server
15
{
16
    protected $host;
17
18
    /** @var LoopInterface */
19
    protected $loop;
20
21
    /** @var BufferedOutput */
22
    protected $shellOutput;
23
24
    /** @var Shell */
25
    protected $shell;
26
27
    /** @var BufferedOutput */
28
    protected $output;
29
30
    /** @var Stdio */
31
    protected $stdio;
32
33
    public function __construct($host, Shell $shell, BufferedOutput $output, LoopInterface $loop = null, Stdio $stdio = null)
34
    {
35
        $this->host = $host;
36
        $this->loop = $loop ?? Factory::create();
37
        $this->shell = $shell;
38
        $this->output = $output;
39
        $this->shellOutput = new BufferedOutput();
40
        $this->stdio = $stdio ?? $this->createStdio();
41
    }
42
43
    public function start()
44
    {
45
        $this->shell->setOutput($this->shellOutput);
46
47
        $this->createSocketServer();
48
49
        $this->loop->run();
50
    }
51
52
    protected function createSocketServer()
53
    {
54
        $socket = new SocketServer($this->host, $this->loop);
55
56
        $socket->on('connection', function (ConnectionInterface $connection) {
57
            $connection->on('data', function ($data) use ($connection) {
58
                $unserializedData = unserialize(base64_decode($data));
59
60
                $this->shell->setScopeVariables(array_merge($unserializedData, $this->shell->getScopeVariables()));
61
62
                $this->stdio->write(PHP_EOL);
63
64
                collect($unserializedData)->keys()->map(function ($variableName) {
65
                    $this->output->writeln('>> $'.$variableName);
66
67
                    $this->executeCode('$'.$variableName);
68
69
                    $this->output->write($this->shellOutput->fetch());
70
71
                    $this->stdio->write($this->output->fetch());
72
                });
73
            });
74
        });
75
    }
76
77
    protected function createStdio(): Stdio
78
    {
79
        $stdio = new Stdio($this->loop);
80
81
        $stdio->getReadline()->setPrompt('>> ');
82
83
        $stdio->on('data', function ($line) use ($stdio) {
84
            $line = rtrim($line, "\r\n");
85
86
            $stdio->getReadline()->addHistory($line);
87
88
            $this->executeCode($line);
89
90
            $this->output->write(PHP_EOL.$this->shellOutput->fetch());
91
92
            $this->stdio->write($this->output->fetch());
93
        });
94
95
        return $stdio;
96
    }
97
98
    protected function executeCode($code)
99
    {
100
        (new ExecutionClosure($this->shell, $code))->execute();
101
    }
102
}
103