Completed
Push — master ( 515494...4d37ef )
by Samuel
03:24 queued 01:55
created

FastCGI::__construct()   C

Complexity

Conditions 7
Paths 28

Size

Total Lines 34
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 8.1426

Importance

Changes 0
Metric Value
dl 0
loc 34
ccs 15
cts 21
cp 0.7143
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 20
nc 28
nop 2
crap 8.1426
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 3
    protected $chroot;
41
42
    /**
43 3
     * @param string $host 127.0.0.1:9000 or /var/run/php5-fpm.sock
44 2
     * @param string $chroot
45 2
     */
46 2
    public function __construct($host = null, $chroot = null)
47
    {
48
        // try to guess where it is
49
        if ($host === null) {
50 2
            foreach ($this->possibleSocketFilePatterns as $possibleSocketFilePattern) {
51 2
                $possibleSocketFile = current(glob($possibleSocketFilePattern));
52 2
                if (file_exists($possibleSocketFile)) {
53 2
                    $host = $possibleSocketFile;
54 2
                    break;
55
                }
56 3
            }
57
            if ($host === null) {
58 3
                $host = '127.0.0.1:9000';
59 3
            }
60 3
        }
61 3
62
        $this->host = $host;
63
64
        if (false !== strpos($host, ':')) {
65
            list($host, $port) = explode(':', $host);
66 3
            $this->client = new Client($host, $port);
67 3
        } else {
68 3
            // socket
69 3
            $this->client = new Client('unix://' . $host, -1);
70
        }
71
72
        $this->client->setReadWriteTimeout(60 * 1000);
73
        $this->client->setPersistentSocket(false);
74
        $this->client->setKeepAlive(true);
75
76
        if ($chroot !== null) {
77
            $this->chroot = rtrim($chroot, '/');
78
        }
79
    }
80
81
    /**
82
     * {@inheritdoc}
83
     */
84
    protected function doRun(Code $code)
85
    {
86
        $response = $this->request($code);
87
        $parts = explode("\r\n\r\n", $response);
88
89
        // remove headers
90
        array_shift($parts);
91
        $body = implode("\r\n\r\n", $parts);
92
93
        if (@unserialize($body) === false) {
94
            throw new \RuntimeException(sprintf("Error: %s", $response));
95
        }
96
97
        return $body;
98
    }
99
100
    protected function request(Code $code)
101
    {
102
        $file = $this->createTemporaryFile();
103
        $this->logger->info(sprintf('FastCGI: Dumped code to file: %s', $file));
104
105
        try {
106
            $code->writeTo($file);
107
108
            $environment = array(
109
                'REQUEST_METHOD'  => 'POST',
110
                'REQUEST_URI'     => '/',
111
                'SCRIPT_FILENAME' => $this->getScriptFileName($file),
112
            );
113
114
            $this->logger->info(sprintf('FastCGI: Requesting FPM using socket: %s', $this->host));
115
            $response = $this->client->request($environment, '');
116
            $this->logger->debug(sprintf('FastCGI: Response: %s', json_encode($response)));
117
118
            if (!@unlink($file)) {
119
                $this->logger->debug(sprintf('FastCGI: Could not delete file: %s', $file));
120
            }
121
122
            return $response;
123
        } catch (\Exception $e) {
124
            if (!@unlink($file)) {
125
                $this->logger->debug(sprintf('FastCGI: Could not delete file: %s', $file));
126
            }
127
128
            throw new \RuntimeException(
129
                sprintf('FastCGI error: %s (%s)', $e->getMessage(), $this->host),
130
                $e->getCode(),
131
                $e
132
            );
133
        }
134
    }
135
136
    /**
137
     * @param string $file
138
     * @return string
139
     * @throws \RuntimeException
140
     */
141
    protected function getScriptFileName($file)
142
    {
143
        if ($this->chroot) {
144
            if (substr($file, 0, strlen($this->chroot)) === $this->chroot) {
145
                return substr($file, strlen($this->chroot));
146
            }
147
            throw new \RuntimeException('FastCGI configured to be chrooted, but file not in chroot directory.');
148
        }
149
        return $file;
150
    }
151
}
152