Completed
Push — master ( 7f3555...e69511 )
by Jasper
15s queued 13s
created

StaticRequestCache::ensureStorageDirectory()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 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 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
        $cachableMimeTypes = config('static-html-cache.cachable_mimetypes', []);
51
52 72
        $isCachableMimeType = false;
53 72
        foreach ($contentTypeData as $contentType) {
54 72
            $isCachableMimeType = in_array($contentType, $cachableMimeTypes, true) !== false;
55
56 72
            if ($isCachableMimeType === true) {
57 65
                break;
58
            }
59
        }
60
61 72
        $nonCacheableCacheControlHeaders = config('static-html-cache.non_cacheable_cache_control_values', []);
62
63 72
        $hasDisablingCacheHeaders = false;
64 72
        foreach ($nonCacheableCacheControlHeaders as $nonCacheableCacheControlHeader) {
65 72
            if ($response->headers->hasCacheControlDirective($nonCacheableCacheControlHeader)) {
66 8
                $hasDisablingCacheHeaders = true;
67 16
                break;
68
            }
69
        }
70
71 72
        return $this->enabled
72 72
            && $response->isOk()
73 72
            && !$hasDisablingCacheHeaders
74 72
            && !$hasIndexPhpInRequestUri
75 72
            && $isGETRequest
76 72
            && $hasNoParams
77 72
            && $isCachableMimeType;
78
    }
79
80
    /**
81
     * @param \Illuminate\Http\Request                   $request
82
     * @param \Symfony\Component\HttpFoundation\Response $response
83
     *
84
     * @return string
85
     */
86 32
    private function getFilename(Request $request, Response $response): string
87
    {
88 32
        $request_uri = trim($request->getRequestUri(), '/');
89 32
        $request_uri = empty($request_uri) ? '' : '/'.$request_uri;
90
91 32
        $contentType = $this->getContentTypeFromResponse($response);
92
93 32
        $filename = public_path(config('static-html-cache.cache_path_prefix').$request_uri);
94 32
        if (in_array('text/html', $contentType, true)) {
95 24
            $filename .= '/index.html';
96
        }
97
98 32
        return $filename;
99
    }
100
101
    /**
102
     * @param string $filename
103
     */
104 32
    private function ensureStorageDirectory(string $filename): void
105
    {
106 32
        $path = $this->files->dirname($filename);
107
108 32
        $this->files->makeDirectory($path, 0777, true, true);
109
110 32
        if (!$this->files->isDirectory($path)) {
111 16
            throw new CacheException(sprintf('Directory "%s" could not be created', $path));
112
        }
113 16
    }
114
115
    /**
116
     * @param \Symfony\Component\HttpFoundation\Response $response
117
     *
118
     * @return array
119
     */
120 104
    private function getContentTypeFromResponse(Response $response): array
121
    {
122 104
        return explode(';', $response->headers->get('content-type'));
123
    }
124
125
    /**
126
     * @return bool
127
     */
128 32
    public function isEnabled(): bool
129
    {
130 32
        return $this->enabled;
131
    }
132
133 8
    public function disable(): void
134
    {
135 8
        $this->enabled = false;
136 8
    }
137
138
    /**
139
     * @param \Illuminate\Http\Request                   $request
140
     * @param \Symfony\Component\HttpFoundation\Response $response
141
     */
142 32
    public function store(Request $request, Response $response): void
143
    {
144 32
        $filename = $this->getFilename($request, $response);
145
146 32
        $this->ensureStorageDirectory($filename);
147
148 16
        $file = $response->getContent();
149
150 16
        if ($this->files->put($filename, $file) === false) {
151
            throw new CacheException(sprintf('File "%s" could not be created', $filename));
152
        }
153 16
    }
154
}
155