SaveResponse   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 95
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 5
dl 0
loc 95
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
B writeStream() 0 22 4
A __invoke() 0 17 3
D canSave() 0 26 9
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
        $response = $next($request, $response);
30
31
        if ($this->canSave($request, $response)) {
32
            $path = $this->getFilename($request);
33
34
            //if it's gz compressed, append .gz
35
            if (strtolower($response->getHeaderLine('Content-Encoding')) === 'gzip') {
36
                $path .= '.gz';
37
            }
38
39
            self::writeStream($response->getBody(), $path);
40
        }
41
42
        return $response;
43
    }
44
45
    /**
46
     * Check whether the response can be saved or not.
47
     *
48
     * @param RequestInterface  $request
49
     * @param ResponseInterface $response
50
     *
51
     * @return bool
52
     */
53
    private function canSave(RequestInterface $request, ResponseInterface $response)
54
    {
55
        if ($request->getMethod() !== 'GET') {
56
            return false;
57
        }
58
59
        if ($response->getStatusCode() !== 200) {
60
            return false;
61
        }
62
63
        if (!$this->appendQuery && !empty($request->getUri()->getQuery())) {
64
            return false;
65
        }
66
67
        if ($response->hasHeader('location')) {
68
            return false;
69
        }
70
71
        $cacheControl = $response->getHeaderLine('Cache-Control');
72
73
        if ($cacheControl && (stripos($cacheControl, 'no-cache') !== false || stripos($cacheControl, 'no-store') !== false)) {
74
            return false;
75
        }
76
77
        return true;
78
    }
79
80
    /**
81
     * Write the stream to the given path.
82
     *
83
     * @param StreamInterface $stream
84
     * @param string          $path
85
     */
86
    private static function writeStream(StreamInterface $stream, $path)
87
    {
88
        $dir = dirname($path);
89
90
        if (!is_dir($dir)) {
91
            mkdir($dir, 0777, true);
92
        }
93
94
        $handle = fopen($path, 'wb+');
95
96
        if (false === $handle) {
97
            throw new RuntimeException('Unable to write to designated path');
98
        }
99
100
        $stream->rewind();
101
102
        while (!$stream->eof()) {
103
            fwrite($handle, $stream->read(4096));
104
        }
105
106
        fclose($handle);
107
    }
108
}
109