Passed
Push — main ( 768fac...6b80e0 )
by Nobufumi
02:43
created

FileController::uploadDir()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
1
<?php
2
3
namespace Jidaikobo\Kontiki\Controllers;
4
5
use Psr\Http\Message\ResponseInterface as Response;
6
use Psr\Http\Message\ServerRequestInterface as Request;
7
use Slim\App;
8
use Slim\Views\PhpRenderer;
9
use Jidaikobo\Kontiki\Controllers\FileControllerTraits;
10
use Jidaikobo\Kontiki\Core\Database;
11
use Jidaikobo\Kontiki\Managers\CsrfManager;
12
use Jidaikobo\Kontiki\Managers\FlashManager;
13
use Jidaikobo\Kontiki\Models\FileModel;
14
use Jidaikobo\Kontiki\Services\RoutesService;
15
use Jidaikobo\Kontiki\Services\FileService;
16
17
class FileController extends BaseController
18
{
19
    use FileControllerTraits\CRUDTrait;
20
    use FileControllerTraits\AssetTrait;
21
    use FileControllerTraits\ListTrait;
22
    use FileControllerTraits\MessagesTrait;
23
24
    private FileModel $model;
25
    private FileService $fileService;
26
27
    public function __construct(
28
        CsrfManager $csrfManager,
29
        FlashManager $flashManager,
30
        PhpRenderer $view,
31
        RoutesService $routesService,
32
        FileModel $model,
33
        FileService $fileService
34
    ) {
35
        parent::__construct(
36
            $csrfManager,
37
            $flashManager,
38
            $view,
39
            $routesService
40
        );
41
        $this->model = $model;
42
        $this->fileService = $fileService;
43
    }
44
45
    public static function registerRoutes(App $app, string $basePath = ''): void
46
    {
47
        $app->get('/get_csrf_token', FileController::class . ':callGetCsrfToken');
48
        $app->get('/filelist', FileController::class . ':callFilelist');
49
        $app->post('/upload', FileController::class . ':callHandleFileUpload');
50
        $app->post('/update', FileController::class . ':callHandleUpdate');
51
        $app->post('/delete', FileController::class . ':callHandleDelete');
52
        $app->get('/kontiki-file.js', FileController::class . ':callServeJs');
53
        $app->get('/kontiki-file-csrf.js', FileController::class . ':callServeCsrfJs');
54
        $app->get('/kontiki-file-utils.js', FileController::class . ':callServeUtilsJs');
55
        $app->get('/kontiki-file-lightbox.js', FileController::class . ':callServeLightboxJs');
56
        $app->get('/kontiki-file-index.js', FileController::class . ':callServeIndexJs');
57
        $app->get('/kontiki-file-uploader.js', FileController::class . ':callServeUploaderJs');
58
        $app->get('/kontiki-file.css', FileController::class . ':callServeCss');
59
    }
60
61
    public function callGetCsrfToken(Request $request, Response $response): Response
62
    {
63
        return $this->getCsrfToken($request, $response);
64
    }
65
66
    public function callFilelist(Request $request, Response $response): Response
67
    {
68
        return $this->filelist($request, $response);
69
    }
70
71
    public function callHandleFileUpload(Request $request, Response $response): Response
72
    {
73
        return $this->handleFileUpload($request, $response);
74
    }
75
76
    public function callHandleUpdate(Request $request, Response $response): Response
77
    {
78
        return $this->handleUpdate($request, $response);
79
    }
80
81
    public function callHandleDelete(Request $request, Response $response): Response
82
    {
83
        return $this->handleDelete($request, $response);
84
    }
85
86
    public function callServeJs(Request $request, Response $response): Response
87
    {
88
        return $this->serveJs($request, $response);
89
    }
90
91
    public function callServeCsrfJs(Request $request, Response $response): Response
92
    {
93
        return $this->serveCsrfJs($request, $response);
94
    }
95
96
    public function callServeUtilsJs(Request $request, Response $response): Response
97
    {
98
        return $this->serveUtilsJs($request, $response);
99
    }
100
101
    public function callServeLightboxJs(Request $request, Response $response): Response
102
    {
103
        return $this->serveLightboxJs($request, $response);
104
    }
105
106
    public function callServeIndexJs(Request $request, Response $response): Response
107
    {
108
        return $this->serveIndexJs($request, $response);
109
    }
110
111
    public function callServeUploaderJs(Request $request, Response $response): Response
112
    {
113
        return $this->serveUploaderJs($request, $response);
114
    }
115
116
    public function callServeCss(Request $request, Response $response): Response
117
    {
118
        return $this->serveCss($request, $response);
119
    }
120
121
    /**
122
     * Get base URL and upload dir. Keep them in one place.
123
     */
124
    private function uploadBaseUrl(): string
125
    {
126
        // e.g. https://example.com/uploads
127
        return rtrim(env('BASEURL'), '/') . rtrim(env('BASEURL_UPLOAD_DIR'), '/');
128
    }
129
130
    private function uploadDir(): string
131
    {
132
        // e.g. /var/www/app/public/uploads
133
        return rtrim(env('PROJECT_PATH', '') . env('UPLOADDIR'), DIRECTORY_SEPARATOR);
134
    }
135
136
    /**
137
     * Convert filesystem path under uploadDir to URL under uploadBaseUrl.
138
     * Assumptions:
139
     *  - $path is an absolute path inside uploadDir (no "..")
140
     *  - Inputs are already “clean” going forward
141
     */
142
    protected function pathToUrl(string $path): string
143
    {
144
        $baseUrl = $this->uploadBaseUrl();
145
        $baseDir = $this->uploadDir();
146
147
        if ($path === '') {
148
            return '';
149
        }
150
151
        if (str_starts_with($path, $baseUrl)) {
152
            $tail = ltrim(substr($path, strlen($baseUrl)), '/');
153
            return $baseUrl . ($tail !== '' ? '/' . $tail : '');
154
        }
155
156
        $normPath = str_replace('\\', DIRECTORY_SEPARATOR, $path);
157
        if (str_starts_with($normPath, $baseDir . DIRECTORY_SEPARATOR) || $normPath === $baseDir) {
158
            $tail = ltrim(substr($normPath, strlen($baseDir)), DIRECTORY_SEPARATOR);
159
            return $baseUrl . ($tail !== '' ? '/' . str_replace(DIRECTORY_SEPARATOR, '/', $tail) : '');
160
        }
161
162
        return '';
163
    }
164
165
    /**
166
     * Convert URL under uploadBaseUrl to filesystem path under uploadDir.
167
     * Assumptions:
168
     *  - $url starts with uploadBaseUrl
169
     *  - URL may have query/fragment; they are ignored
170
     */
171
    protected function urlToPath(string $url): string
172
    {
173
        $baseUrl = $this->uploadBaseUrl();
174
        $baseDir = $this->uploadDir();
175
176
        if ($url === '') {
177
            return '';
178
        }
179
180
        $noQuery = strtok($url, '?#') ?: $url;
181
182
        if (str_starts_with($noQuery, $baseUrl)) {
183
            $tail = ltrim(substr($noQuery, strlen($baseUrl)), '/');
184
            return $baseDir . ($tail !== '' ? DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $tail) : '');
185
        }
186
187
        $norm = str_replace('\\', DIRECTORY_SEPARATOR, $noQuery);
188
        if (str_starts_with($norm, $baseDir . DIRECTORY_SEPARATOR) || $norm === $baseDir) {
189
            return $norm;
190
        }
191
192
        return '';
193
    }
194
}
195