WebServer::canConnect()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 3
b 0
f 0
nc 2
nop 0
dl 0
loc 11
rs 10
1
<?php
2
3
namespace Palmtree\Curl\Tests\Fixtures;
4
5
class WebServer
6
{
7
    /** @var string */
8
    private $host;
9
    /** @var string */
10
    private $documentRoot;
11
    /** @var int */
12
    private $pid;
13
    /** @var int */
14
    private $port;
15
16
    private const SERVER_TIMEOUT_SECONDS = 5;
17
18
    public function __construct(string $host, string $documentRoot)
19
    {
20
        $this->host         = $host;
21
        $this->documentRoot = $documentRoot;
22
    }
23
24
    private function findFreePort(): int
25
    {
26
        $sock = \socket_create_listen(0);
27
        \socket_getsockname($sock, $addr, $port);
28
        \socket_close($sock);
29
30
        return $port;
31
    }
32
33
    public function start(): int
34
    {
35
        $this->port = $this->findFreePort();
36
37
        $command = \sprintf(
38
            'php -S %s:%d -t %s >/dev/null 2>&1 & echo $!',
39
            $this->host,
40
            $this->port,
41
            $this->documentRoot
42
        );
43
44
        \exec($command, $output);
45
46
        $this->pid = (int)$output[0];
47
48
        $start     = \microtime(true);
49
        $connected = false;
50
51
        while (\microtime(true) - $start <= self::SERVER_TIMEOUT_SECONDS) {
52
            if ($this->canConnect()) {
53
                $connected = true;
54
                break;
55
            }
56
        }
57
58
        if (!$connected) {
59
            $this->stop();
60
            throw new \RuntimeException('Timed out');
61
        }
62
63
        return $this->port;
64
    }
65
66
    public function stop(): void
67
    {
68
        \exec('kill ' . (int)$this->pid);
69
    }
70
71
    public function getUrl($path = '', bool $https = false): string
72
    {
73
        $scheme = $https ? 'https' : 'http';
74
75
        $url = "$scheme://$this->host:$this->port";
76
77
        if (!empty($path)) {
78
            $url .= "/$path";
79
        }
80
81
        return $url;
82
    }
83
84
    private function canConnect(): bool
85
    {
86
        $handle = @\fsockopen($this->host, $this->port);
87
88
        if ($handle === false) {
89
            return false;
90
        }
91
92
        \fclose($handle);
93
94
        return true;
95
    }
96
}
97