Completed
Pull Request — master (#11)
by Jasper
08:43 queued 04:59
created

StaticRequestCache::getContentTypeFromResponse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Swis\Laravel\StaticRequestCache;
4
5
use Illuminate\Filesystem\Filesystem;
6
use Illuminate\Http\Request;
7
use Illuminate\Support\Str;
8
use Swis\Laravel\StaticRequestCache\Exceptions\CacheException;
9
use Symfony\Component\HttpFoundation\Response;
10
11
class StaticRequestCache
12
{
13
    /**
14
     * @var \Illuminate\Filesystem\Filesystem
15
     */
16
    protected $files;
17
18
    /**
19
     * @var bool
20
     */
21
    protected $enabled;
22
23
    /**
24
     * @param \Illuminate\Filesystem\Filesystem $files
25
     */
26 136
    public function __construct(Filesystem $files)
27
    {
28 136
        $this->files = $files;
29
30 136
        if (config('static-html-cache.enabled') === 'debug') {
31 16
            $this->enabled = !config('app.debug');
32
        } else {
33 120
            $this->enabled = config('static-html-cache.enabled');
34
        }
35 136
    }
36
37
    /**
38
     * @param \Illuminate\Http\Request                   $request
39
     * @param \Symfony\Component\HttpFoundation\Response $response
40
     *
41
     * @return bool
42
     */
43 72
    public function shouldStoreResponse(Request $request, Response $response): bool
44
    {
45 72
        $isGETRequest = $request->getMethod() === 'GET';
46 72
        $hasNoParams = count($request->input()) === 0;
47 72
        $contentTypeData = $this->getContentTypeFromResponse($response);
48 72
        $hasIndexPhpInRequestUri = Str::contains($request->getRequestUri(), 'index.php');
49
50 72
        $isCachableMimeType = false;
51 72
        foreach ($contentTypeData as $contentType) {
52 72
            $isCachableMimeType = in_array($contentType, config('static-html-cache.cachable_mimetypes'), true) !== false;
53
54 72
            if ($isCachableMimeType === true) {
55 65
                break;
56
            }
57
        }
58
59 72
        $nonCacheableCacheControlHeaders = config('static-html-cache.non_cacheable_cache_control_values', []);
60
61 72
        $hasDisablingCacheHeaders = false;
62 72
        foreach ($nonCacheableCacheControlHeaders as $nonCacheableCacheControlHeader) {
63 72
            if ($response->headers->hasCacheControlDirective($nonCacheableCacheControlHeader)) {
64 8
                $hasDisablingCacheHeaders = true;
65 16
                break;
66
            }
67
        }
68
69 72
        return $this->enabled
70 72
            && $response->isOk()
71 72
            && !$hasDisablingCacheHeaders
72 72
            && !$hasIndexPhpInRequestUri
73 72
            && $isGETRequest
74 72
            && $hasNoParams
75 72
            && $isCachableMimeType;
76
    }
77
78
    /**
79
     * @param \Illuminate\Http\Request                   $request
80
     * @param \Symfony\Component\HttpFoundation\Response $response
81
     *
82
     * @return string
83
     */
84 32
    private function getFilename(Request $request, Response $response): string
85
    {
86 32
        $request_uri = trim($request->getRequestUri(), '/');
87 32
        $request_uri = empty($request_uri) ? '' : '/'.$request_uri;
88
89 32
        $contentType = $this->getContentTypeFromResponse($response);
90
91 32
        $filename = public_path(config('static-html-cache.cache_path_prefix').$request_uri);
92 32
        if (in_array('text/html', $contentType, true)) {
93 24
            $filename .= '/index.html';
94
        }
95
96 32
        return $filename;
97
    }
98
99
    /**
100
     * @param string $filename
101
     */
102 32
    private function ensureStorageDirectory(string $filename): void
103
    {
104 32
        $path = $this->files->dirname($filename);
105
106 32
        $this->files->makeDirectory($path, 0777, true, true);
107
108 32
        if (!$this->files->isDirectory($path)) {
109 16
            throw new CacheException(sprintf('Directory "%s" could not be created', $path));
110
        }
111 16
    }
112
113
    /**
114
     * @param \Symfony\Component\HttpFoundation\Response $response
115
     *
116
     * @return array
117
     */
118 104
    private function getContentTypeFromResponse(Response $response): array
119
    {
120 104
        return explode(';', $response->headers->get('content-type'));
121
    }
122
123
    /**
124
     * @return bool
125
     */
126 32
    public function isEnabled(): bool
127
    {
128 32
        return $this->enabled;
129
    }
130
131 8
    public function disable(): void
132
    {
133 8
        $this->enabled = false;
134 8
    }
135
136
    /**
137
     * @param \Illuminate\Http\Request                   $request
138
     * @param \Symfony\Component\HttpFoundation\Response $response
139
     */
140 32
    public function store(Request $request, Response $response): void
141
    {
142 32
        $filename = $this->getFilename($request, $response);
143
144 32
        $this->ensureStorageDirectory($filename);
145
146 16
        $file = $response->getContent();
147
148 16
        if ($this->files->put($filename, $file) === false) {
149
            throw new CacheException(sprintf('File "%s" could not be created', $filename));
150
        }
151 16
    }
152
}
153