Completed
Push — master ( 35b4ac...79eb59 )
by Samuel
04:15 queued 03:10
created

FastCGI::__construct()   B

Complexity

Conditions 7
Paths 28

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 7.0061

Importance

Changes 0
Metric Value
dl 0
loc 34
ccs 19
cts 20
cp 0.95
rs 8.4426
c 0
b 0
f 0
cc 7
nc 28
nop 2
crap 7.0061
1
<?php
2
3
/*
4
 * This file is part of CacheTool.
5
 *
6
 * (c) Samuel Gordalina <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace CacheTool\Adapter;
13
14
use CacheTool\Code;
15
use Adoy\FastCGI\Client;
16
17
class FastCGI extends AbstractAdapter
18
{
19
    /**
20
     * @var Client
21
     */
22
    protected $client;
23
24
    /**
25
     * @var Array of patterns matching php socket files
26
     */
27
    protected $possibleSocketFilePatterns = [
28
        '/var/run/php*.sock',
29
        '/var/run/php/*.sock'
30
    ];
31
32
    /**
33
     * @var string
34
     */
35
    protected $host;
36
37
    /**
38
     * @var string
39
     */
40
    protected $chroot;
41
42
    /**
43
     * @param string $host 127.0.0.1:9000 or /var/run/php5-fpm.sock
44
     * @param string $chroot
45
     */
46 9
    public function __construct($host = null, $chroot = null)
47
    {
48
        // try to guess where it is
49 9
        if ($host === null) {
50 8
            foreach ($this->possibleSocketFilePatterns as $possibleSocketFilePattern) {
51 8
                $possibleSocketFile = current(glob($possibleSocketFilePattern));
52 8
                if (file_exists($possibleSocketFile)) {
53 8
                    $host = $possibleSocketFile;
54 8
                    break;
55
                }
56
            }
57 8
            if ($host === null) {
58
                $host = '127.0.0.1:9000';
59
            }
60
        }
61
62 9
        $this->host = $host;
63
64 9
        if (false !== strpos($host, ':')) {
65 1
            [$host, $port] = explode(':', $host);
0 ignored issues
show
Bug introduced by
The variable $port does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
66 1
            $this->client = new Client($host, $port);
67
        } else {
68
            // socket
69 8
            $this->client = new Client('unix://' . $host, -1);
70
        }
71
72 9
        $this->client->setReadWriteTimeout(60 * 1000);
73 9
        $this->client->setPersistentSocket(false);
74 9
        $this->client->setKeepAlive(true);
75
76 9
        if ($chroot !== null) {
77 3
            $this->chroot = rtrim($chroot, '/');
78
        }
79 9
    }
80
81
    /**
82
     * {@inheritdoc}
83
     */
84 3
    protected function doRun(Code $code)
85
    {
86 3
        $response = $this->request($code);
87 1
        $parts = explode("\r\n\r\n", $response);
88
89
        // remove headers
90 1
        array_shift($parts);
91 1
        $body = implode("\r\n\r\n", $parts);
92
93 1
        if (@unserialize($body) === false) {
94
            throw new \RuntimeException(sprintf("Error: %s", $response));
95
        }
96
97 1
        return $body;
98
    }
99
100 3
    protected function request(Code $code)
101
    {
102 3
        $file = $this->createTemporaryFile();
103 3
        $this->logger->info(sprintf('FastCGI: Dumped code to file: %s', $file));
104
105
        try {
106 3
            $code->writeTo($file);
107
108
            $environment = [
109 1
                'SERVER_ADDR'     => '127.0.0.1',
110 1
                'REMOTE_ADDR'     => '127.0.0.1',
111 1
                'REMOTE_PORT'     => '65000',
112 1
                'REQUEST_METHOD'  => 'POST',
113 1
                'REQUEST_URI'     => '/',
114 1
                'SCRIPT_FILENAME' => $this->getScriptFileName($file),
115
            ];
116
117 1
            $this->logger->info(sprintf('FastCGI: Requesting FPM using socket: %s', $this->host));
118 1
            $response = $this->client->request($environment, '');
119 1
            $this->logger->debug(sprintf('FastCGI: Response: %s', json_encode($response)));
120
121 1
            if (!@unlink($file)) {
122
                $this->logger->debug(sprintf('FastCGI: Could not delete file: %s', $file));
123
            }
124
125 1
            return $response;
126 2
        } catch (\Exception $e) {
127 2
            if (!@unlink($file)) {
128 2
                $this->logger->debug(sprintf('FastCGI: Could not delete file: %s', $file));
129
            }
130
131 2
            throw new \RuntimeException(
132 2
                sprintf('FastCGI error: %s (%s)', $e->getMessage(), $this->host),
133 2
                $e->getCode(),
134 2
                $e
135
            );
136
        }
137
    }
138
139
    /**
140
     * @param string $file
141
     * @return string
142
     * @throws \RuntimeException
143
     */
144 2
    protected function getScriptFileName($file)
145
    {
146 2
        if ($this->chroot) {
147 1
            if (substr($file, 0, strlen($this->chroot)) === $this->chroot) {
148 1
                return substr($file, strlen($this->chroot));
149
            }
150
            throw new \RuntimeException('FastCGI configured to be chrooted, but file not in chroot directory.');
151
        }
152 1
        return $file;
153
    }
154
}
155