Completed
Push — master ( 12bc5d...f69768 )
by Oscar
58:41
created

SaveResponse   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 93
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 4
Bugs 0 Features 1
Metric Value
wmc 16
c 4
b 0
f 1
lcom 1
cbo 5
dl 0
loc 93
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __invoke() 0 15 3
D canSave() 0 26 9
B writeStream() 0 22 4
1
<?php
2
3
namespace Psr7Middlewares\Middleware;
4
5
use Psr7Middlewares\Utils;
6
use Psr\Http\Message\RequestInterface;
7
use Psr\Http\Message\ResponseInterface;
8
use Psr\Http\Message\StreamInterface;
9
use RuntimeException;
10
11
/**
12
 * Middleware to save the response into a file.
13
 */
14
class SaveResponse
15
{
16
    use Utils\FileTrait;
17
18
    /**
19
     * Execute the middleware.
20
     *
21
     * @param RequestInterface  $request
22
     * @param ResponseInterface $response
23
     * @param callable          $next
24
     *
25
     * @return ResponseInterface
26
     */
27
    public function __invoke(RequestInterface $request, ResponseInterface $response, callable $next)
28
    {
29
        if ($this->canSave($request, $response)) {
30
            $path = $this->getFilename($request);
31
32
            //if it's gz compressed, append .gz
33
            if (strtolower($response->getHeaderLine('Content-Encoding')) === 'gzip') {
34
                $path .= '.gz';
35
            }
36
37
            self::writeStream($response->getBody(), $path);
38
        }
39
40
        return $next($request, $response);
41
    }
42
43
    /**
44
     * Check whether the response can be saved or not.
45
     * 
46
     * @param RequestInterface  $request
47
     * @param ResponseInterface $response
48
     * 
49
     * @return bool
50
     */
51
    private function canSave(RequestInterface $request, ResponseInterface $response)
52
    {
53
        if ($request->getMethod() !== 'GET') {
54
            return false;
55
        }
56
57
        if ($response->getStatusCode() !== 200) {
58
            return false;
59
        }
60
61
        if (!$this->testBasePath($request->getUri()->getPath())) {
62
            return false;
63
        }
64
65
        if (!$this->appendQuery && !empty($request->getUri()->getQuery())) {
66
            return false;
67
        }
68
69
        $cacheControl = $response->getHeaderLine('Cache-Control');
70
71
        if ($cacheControl && (stripos($cacheControl, 'no-cache') !== false || stripos($cacheControl, 'no-store') !== false)) {
72
            return false;
73
        }
74
75
        return true;
76
    }
77
78
    /**
79
     * Write the stream to the given path.
80
     *
81
     * @param StreamInterface $stream
82
     * @param string          $path
83
     */
84
    private static function writeStream(StreamInterface $stream, $path)
85
    {
86
        $dir = dirname($path);
87
88
        if (!is_dir($dir)) {
89
            mkdir($dir, 0777, true);
90
        }
91
92
        $handle = fopen($path, 'wb+');
93
94
        if (false === $handle) {
95
            throw new RuntimeException('Unable to write to designated path');
96
        }
97
98
        $stream->rewind();
99
100
        while (!$stream->eof()) {
101
            fwrite($handle, $stream->read(4096));
102
        }
103
104
        fclose($handle);
105
    }
106
}
107