Completed
Push — master ( c0e612...954278 )
by Jasper
04:23
created

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