Completed
Push — master ( 8da0a0...43fc91 )
by Samuel
01:12
created

FastCGI::request()   A

Complexity

Conditions 4
Paths 16

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 4.0023

Importance

Changes 0
Metric Value
dl 0
loc 35
ccs 18
cts 19
cp 0.9474
rs 9.36
c 0
b 0
f 0
cc 4
nc 16
nop 1
crap 4.0023
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
                'REQUEST_METHOD'  => 'POST',
110 1
                'REQUEST_URI'     => '/',
111 1
                'SCRIPT_FILENAME' => $this->getScriptFileName($file),
112
            ];
113
114 1
            $this->logger->info(sprintf('FastCGI: Requesting FPM using socket: %s', $this->host));
115 1
            $response = $this->client->request($environment, '');
116 1
            $this->logger->debug(sprintf('FastCGI: Response: %s', json_encode($response)));
117
118 1
            if (!@unlink($file)) {
119
                $this->logger->debug(sprintf('FastCGI: Could not delete file: %s', $file));
120
            }
121
122 1
            return $response;
123 2
        } catch (\Exception $e) {
124 2
            if (!@unlink($file)) {
125 2
                $this->logger->debug(sprintf('FastCGI: Could not delete file: %s', $file));
126
            }
127
128 2
            throw new \RuntimeException(
129 2
                sprintf('FastCGI error: %s (%s)', $e->getMessage(), $this->host),
130 2
                $e->getCode(),
131
                $e
132
            );
133
        }
134
    }
135
136
    /**
137
     * @param string $file
138
     * @return string
139
     * @throws \RuntimeException
140
     */
141 2
    protected function getScriptFileName($file)
142
    {
143 2
        if ($this->chroot) {
144 1
            if (substr($file, 0, strlen($this->chroot)) === $this->chroot) {
145 1
                return substr($file, strlen($this->chroot));
146
            }
147
            throw new \RuntimeException('FastCGI configured to be chrooted, but file not in chroot directory.');
148
        }
149 1
        return $file;
150
    }
151
}
152