Varnish::getHosts()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
namespace DeltaBlue\Varnish;
4
5
use Symfony\Component\Process\Process;
6
7
class Varnish
8
{
9
    /*
10
     * Known exec types
11
     */
12
    const EXEC_SOCKET = 'socket';
13
    const EXEC_COMMAND = 'command';
14
15
    /**
16
     * @param string|array $host
17
     *
18
     * @return bool|null
19
     *
20
     * @throws \Exception
21
     */
22
    public function flush($host = null): bool
23
    {
24
        $config = config('varnish');
25
26
        $host = $this->getHosts($host);
27
        $expr = $this->generateBanExpr($host);
28
29
        // Default to execution_type command when the config parameter is not set
30
        switch ($config['execution_type'] ?? self::EXEC_COMMAND) {
31
            case self::EXEC_SOCKET:
32
                return $this->executeSocketCommand($expr);
33
            case self::EXEC_COMMAND:
34
                return $this->executeCommand($this->generateBanCommand($expr));
35
            default:
36
                throw new \Exception(sprintf(
37
                    'Unknown execution type: %s', $config['execution_type']
38
                ));
39
        }
40
    }
41
42
    /**
43
     * @param array|string $host
44
     *
45
     * @return array
46
     */
47
    protected function getHosts($host = null): array
48
    {
49
        $host = $host ?? config('varnish.host');
50
51
        if (! is_array($host)) {
52
            $host = [$host];
53
        }
54
55
        return $host;
56
    }
57
58
    /**
59
     * @param string $expr
60
     *
61
     * @return string
62
     */
63
    public function generateBanCommand($expr = ''): string
64
    {
65
        $config = config('varnish');
66
67
        return "sudo varnishadm -S {$config['administrative_secret']} -T 127.0.0.1:{$config['administrative_port']} '{$expr}'";
68
    }
69
70
    /**
71
     * @param array $hosts
72
     *
73
     * @return string
74
     */
75
    public function generateBanExpr(array $hosts): string
76
    {
77
        $hostsRegex = collect($hosts)
78
            ->map(function (string $host) {
79
                return "(^{$host}$)";
80
            })
81
            ->implode('|');
82
83
        return sprintf('ban req.http.host ~ %s', $hostsRegex);
84
    }
85
86
    /**
87
     * @return string
88
     */
89
    public function getSecret()
90
    {
91
        $config = config('varnish');
92
        if (! $secret = $config['administrative_secret_string']) {
93
            $secret = '';
94
            if (file_exists($config['administrative_secret'])) {
95
                $secret = trim(file_get_contents($config['administrative_secret']));
96
            }
97
        }
98
99
        return $secret;
100
    }
101
102
    /**
103
     * @param string $command
104
     *
105
     * @return bool
106
     *
107
     * @throws \Exception When the command fails
108
     */
109
    protected function executeCommand(string $command): bool
110
    {
111
        $process = new Process($command);
112
        $process->run();
113
114
        return $process->isSuccessful();
115
    }
116
117
    /**
118
     * @param string $command
119
     *
120
     * @return bool
121
     *
122
     * @throws \Exception When connection to socket or command failed
123
     */
124
    protected function executeSocketCommand(string $command): bool
125
    {
126
        $config = config('varnish');
127
        $socket = new VarnishSocket();
128
129
        try {
130
            if ($socket->connect(
131
                $config['administrative_host'],
132
                $config['administrative_port'],
133
                $this->getSecret()
134
            )) {
135
                $socket->command($command);
136
                $socket->quit();
137
            }
138
        } catch (\Exception $e) {
139
            return false;
140
        } finally {
141
            $socket->close();
142
        }
143
144
        return true;
145
    }
146
}
147