Passed
Pull Request — master (#70)
by Andrew
05:24
created

FilesystemPublisher::deleteFromPath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 7
nc 2
nop 1
dl 0
loc 10
rs 9.4285
c 1
b 0
f 0
1
<?php
2
3
namespace SilverStripe\StaticPublishQueue\Publisher;
4
5
use SilverStripe\Assets\Filesystem;
6
use SilverStripe\Control\HTTPResponse;
7
use SilverStripe\StaticPublishQueue\Publisher;
8
use function SilverStripe\StaticPublishQueue\URLtoPath;
0 ignored issues
show
introduced by
The function SilverStripe\StaticPublishQueue\URLtoPath was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
9
10
class FilesystemPublisher extends Publisher
11
{
12
    /**
13
     * @var string
14
     */
15
    protected $destFolder = 'cache';
16
17
    /**
18
     * @var string
19
     */
20
    protected $fileExtension = 'php';
21
22
    /**
23
     * @return string
24
     */
25
    public function getDestPath()
26
    {
27
        return BASE_PATH . '/' . $this->getDestFolder();
28
    }
29
30
    public function setDestFolder($destFolder)
31
    {
32
        $this->destFolder = $destFolder;
33
        return $this;
34
    }
35
36
    public function getDestFolder()
37
    {
38
        return $this->destFolder;
39
    }
40
41
    public function setFileExtension($fileExtension)
42
    {
43
        $fileExtension = strtolower($fileExtension);
44
        if (!in_array($fileExtension, ['html', 'php'])) {
45
            throw new \InvalidArgumentException(
46
                sprintf(
47
                    'Bad file extension "%s" passed to %s::%s',
48
                    $fileExtension,
49
                    static::class,
50
                    __FUNCTION__
51
                )
52
            );
53
        }
54
        $this->fileExtension = $fileExtension;
55
        return $this;
56
    }
57
58
    public function getFileExtension()
59
    {
60
        return $this->fileExtension;
61
    }
62
63
    public function purgeURL($url)
64
    {
65
        if (!$url) {
66
            user_error("Bad url:" . var_export($url, true), E_USER_WARNING);
67
            return;
68
        }
69
        $path = $this->URLtoPath($url);
70
        $success = $this->deleteFromPath($path . '.html') && $this->deleteFromPath($path . '.php');
71
        return [
72
            'success' => $success,
73
            'url' => $url,
74
            'path' => $this->getDestPath() . DIRECTORY_SEPARATOR . $path,
75
        ];
76
    }
77
78
    /**
79
     * @param string $url
80
     * @return array A result array
81
     */
82
    public function publishURL($url, $forcePublish = false)
83
    {
84
        if (!$url) {
85
            user_error("Bad url:" . var_export($url, true), E_USER_WARNING);
86
            return;
87
        }
88
        $success = false;
89
        $response = $this->generatePageResponse($url);
90
        $statusCode = $response->getStatusCode();
91
        $doPublish = ($forcePublish && $this->getFileExtension() == 'php') || $statusCode < 400;
92
93
        if ($statusCode < 300) {
94
            // publish success response
95
            $success = $this->publishPage($response, $url);
96
        } elseif ($statusCode < 400) {
97
            // publish redirect response
98
            $success = $this->publishRedirect($response, $url);
99
        } elseif ($doPublish) {
100
            // only publish error pages if we are able to send status codes via PHP
101
            $success = $this->publishPage($response, $url);
102
        }
103
        return [
104
            'published' => $doPublish,
105
            'success' => $success,
106
            'responsecode' => $statusCode,
107
            'url' => $url,
108
        ];
109
    }
110
111
    /**
112
     * @param HTTPResponse $response
113
     * @param string       $url
114
     * @return bool
115
     */
116
    protected function publishRedirect($response, $url)
117
    {
118
        $success = true;
119
        $path = $this->URLtoPath($url);
120
        $location = $response->getHeader('Location');
121
        if ($this->getFileExtension() === 'php') {
122
            $phpContent = $this->generatePHPCacheFile($response);
123
            $success = $this->saveToPath($phpContent, $path . '.php');
124
        }
125
        return $this->saveToPath($this->generateHTMLCacheRedirection($location), $path . '.html') && $success;
126
    }
127
128
    /**
129
     * @param HTTPResponse $response
130
     * @param string       $url
131
     * @return bool
132
     */
133
    protected function publishPage($response, $url)
134
    {
135
        $success = true;
136
        $path = $this->URLtoPath($url);
137
        if ($this->getFileExtension() === 'php') {
138
            $phpContent = $this->generatePHPCacheFile($response);
139
            $success = $this->saveToPath($phpContent, $path . '.php');
140
        }
141
        return $this->saveToPath($response->getBody(), $path . '.html') && $success;
142
    }
143
144
    /**
145
     * @param string $content
146
     * @param string $filePath
147
     * @return bool
148
     */
149
    protected function saveToPath($content, $filePath)
150
    {
151
        if (empty($content)) {
152
            return false;
153
        }
154
        $publishPath = $this->getDestPath() . DIRECTORY_SEPARATOR . $filePath;
155
        Filesystem::makeFolder(dirname($publishPath));
156
        return file_put_contents($publishPath, $content) !== false;
157
    }
158
159
    protected function deleteFromPath($filePath)
160
    {
161
        $deletePath = $this->getDestPath() . DIRECTORY_SEPARATOR . $filePath;
162
        if (file_exists($deletePath)) {
163
            $success = unlink($deletePath);
164
        } else {
165
            $success = true;
166
        }
167
        Filesystem::remove_folder_if_empty(dirname($deletePath));
168
        return $success;
169
    }
170
171
    protected function URLtoPath($url)
172
    {
173
        return URLtoPath($url, FilesystemPublisher::config()->get('domain_based_caching'));
0 ignored issues
show
Bug introduced by
The function URLtoPath was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

173
        return /** @scrutinizer ignore-call */ URLtoPath($url, FilesystemPublisher::config()->get('domain_based_caching'));
Loading history...
174
    }
175
176
    protected function pathToURL($path)
177
    {
178
        if (strpos($path, $this->getDestPath()) === 0) {
179
            //Strip off the full path of the cache dir from the front
180
            $path = substr($path, strlen($this->getDestPath()));
181
        }
182
        $path = ltrim($path, '/');
183
        // Strip off the file extension
184
        $relativeURL = substr($path, 0, (strrpos($path, ".")));
185
186
        return $relativeURL == 'index' ? '/' : $relativeURL;
187
    }
188
189
    public function getPublishedURLs($dir = null, &$result = [])
190
    {
191
        if ($dir == null) {
192
            $dir = $this->getDestPath();
193
        }
194
195
        $root = scandir($dir);
196
        foreach ($root as $fileOrDir) {
197
            if (strpos($fileOrDir, '.') === 0) {
198
                continue;
199
            }
200
            $fullPath = $dir . DIRECTORY_SEPARATOR . $fileOrDir;
201
            // we know html will always be generated, this prevents double ups
202
            if (is_file($fullPath) && pathinfo($fullPath)['extension'] == 'html') {
203
                $result[] = $this->pathToURL($fullPath);
204
                continue;
205
            }
206
207
            if (is_dir($fullPath)) {
208
                $this->getPublishedURLs($fullPath, $result);
209
            }
210
        }
211
        return $result;
212
    }
213
}
214