StaticRequestCache   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Test Coverage

Coverage 98.25%

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 23
eloc 50
c 2
b 1
f 0
dl 0
loc 141
ccs 56
cts 57
cp 0.9825
rs 10

8 Methods

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