create-prisma-php-app 1.20.0 → 1.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bootstrap.php
CHANGED
|
@@ -456,29 +456,62 @@ function convertToArrayObject($data)
|
|
|
456
456
|
function wireCallback()
|
|
457
457
|
{
|
|
458
458
|
try {
|
|
459
|
-
// Read input data
|
|
460
|
-
$input = file_get_contents('php://input');
|
|
461
|
-
$data = json_decode($input, true);
|
|
462
|
-
|
|
463
459
|
// Initialize response
|
|
464
460
|
$response = [
|
|
465
461
|
'success' => false,
|
|
466
462
|
'error' => 'Callback not provided',
|
|
467
|
-
'data' =>
|
|
463
|
+
'data' => null
|
|
468
464
|
];
|
|
469
465
|
|
|
470
466
|
$callbackResponse = null;
|
|
467
|
+
$data = [];
|
|
468
|
+
|
|
469
|
+
// Check if the request includes one or more files
|
|
470
|
+
$hasFile = isset($_FILES['file']) && !empty($_FILES['file']['name'][0]);
|
|
471
|
+
|
|
472
|
+
// Process form data
|
|
473
|
+
if ($hasFile) {
|
|
474
|
+
// Handle file upload, including multiple files
|
|
475
|
+
$data = $_POST; // Form data will be available in $_POST
|
|
476
|
+
|
|
477
|
+
if (is_array($_FILES['file']['name'])) {
|
|
478
|
+
// Multiple files uploaded
|
|
479
|
+
$files = [];
|
|
480
|
+
foreach ($_FILES['file']['name'] as $index => $name) {
|
|
481
|
+
$files[] = [
|
|
482
|
+
'name' => $name,
|
|
483
|
+
'type' => $_FILES['file']['type'][$index],
|
|
484
|
+
'tmp_name' => $_FILES['file']['tmp_name'][$index],
|
|
485
|
+
'error' => $_FILES['file']['error'][$index],
|
|
486
|
+
'size' => $_FILES['file']['size'][$index],
|
|
487
|
+
];
|
|
488
|
+
}
|
|
489
|
+
$data['files'] = $files;
|
|
490
|
+
} else {
|
|
491
|
+
// Single file uploaded
|
|
492
|
+
$data['file'] = $_FILES['file']; // Attach single file information to data
|
|
493
|
+
}
|
|
494
|
+
} else {
|
|
495
|
+
// Handle non-file form data (likely JSON)
|
|
496
|
+
$input = file_get_contents('php://input');
|
|
497
|
+
$data = json_decode($input, true);
|
|
498
|
+
|
|
499
|
+
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
500
|
+
// Fallback to handle form data in POST (non-JSON)
|
|
501
|
+
$data = $_POST;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
471
504
|
|
|
472
505
|
// Validate and call the dynamic function
|
|
473
506
|
if (isset($data['callback'])) {
|
|
474
507
|
// Sanitize and create a dynamic function name
|
|
475
|
-
$callbackName = preg_replace('/[^a-zA-Z0-9_]/', '', $data['callback']); // Sanitize
|
|
508
|
+
$callbackName = preg_replace('/[^a-zA-Z0-9_]/', '', $data['callback']); // Sanitize the callback name
|
|
476
509
|
|
|
477
510
|
// Check if the dynamic function is defined and callable
|
|
478
511
|
if (function_exists($callbackName) && is_callable($callbackName)) {
|
|
479
512
|
$dataObject = convertToArrayObject($data);
|
|
480
513
|
|
|
481
|
-
// Call the
|
|
514
|
+
// Call the function dynamically
|
|
482
515
|
$callbackResponse = call_user_func($callbackName, $dataObject);
|
|
483
516
|
|
|
484
517
|
// Handle different types of responses
|
|
@@ -499,6 +532,8 @@ function wireCallback()
|
|
|
499
532
|
// Invalid callback provided
|
|
500
533
|
$response['error'] = 'Invalid callback';
|
|
501
534
|
}
|
|
535
|
+
} else {
|
|
536
|
+
$response['error'] = 'No callback provided';
|
|
502
537
|
}
|
|
503
538
|
|
|
504
539
|
// Output the JSON response only if the callbackResponse is not null
|
|
@@ -506,7 +541,7 @@ function wireCallback()
|
|
|
506
541
|
echo json_encode($response);
|
|
507
542
|
}
|
|
508
543
|
} catch (Throwable $e) {
|
|
509
|
-
// Handle any exceptions and prepare error response
|
|
544
|
+
// Handle any exceptions and prepare an error response
|
|
510
545
|
$response = [
|
|
511
546
|
'success' => false,
|
|
512
547
|
'error' => 'Exception occurred',
|
|
@@ -32,6 +32,7 @@ $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ||
|
|
|
32
32
|
$domainName = $_SERVER['HTTP_HOST'];
|
|
33
33
|
$scriptName = dirname($_SERVER['SCRIPT_NAME']) . '/';
|
|
34
34
|
$baseUrl = $protocol . $domainName . rtrim($scriptName, '/') . '/src/app/';
|
|
35
|
+
$documentUrl = $protocol . $domainName . rtrim($scriptName, '/') . '/';
|
|
35
36
|
$referer = $_SERVER['HTTP_REFERER'] ?? 'Unknown';
|
|
36
37
|
|
|
37
38
|
$params = [];
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Lib\FileManager;
|
|
4
|
+
|
|
5
|
+
class UploadFile
|
|
6
|
+
{
|
|
7
|
+
protected string $destination;
|
|
8
|
+
protected array $messages = [];
|
|
9
|
+
protected array $errorCode = [];
|
|
10
|
+
protected int $maxSize = 51200; // 50KB default
|
|
11
|
+
protected array $permittedTypes = [
|
|
12
|
+
'image/jpeg',
|
|
13
|
+
'image/pjpeg',
|
|
14
|
+
'image/gif',
|
|
15
|
+
'image/png',
|
|
16
|
+
'image/webp'
|
|
17
|
+
];
|
|
18
|
+
protected string $newName = '';
|
|
19
|
+
protected bool $typeCheckingOn = true;
|
|
20
|
+
protected array $notTrusted = ['bin', 'cgi', 'exe', 'js', 'pl', 'php', 'py', 'sh'];
|
|
21
|
+
protected string $suffix = '.upload';
|
|
22
|
+
protected bool $renameDuplicates;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Constructor for the UploadFile class.
|
|
26
|
+
*
|
|
27
|
+
* @param string $uploadFolder The folder to which uploaded files will be moved.
|
|
28
|
+
* @throws \Exception If the upload folder is not a valid, writable folder.
|
|
29
|
+
*/
|
|
30
|
+
public function __construct(string $uploadFolder)
|
|
31
|
+
{
|
|
32
|
+
if (!is_dir($uploadFolder) || !is_writable($uploadFolder)) {
|
|
33
|
+
throw new \Exception("$uploadFolder must be a valid, writable folder.");
|
|
34
|
+
}
|
|
35
|
+
// Ensure the folder ends with a '/'
|
|
36
|
+
$this->destination = rtrim($uploadFolder, '/') . '/';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Sets the maximum size for uploaded files.
|
|
41
|
+
*
|
|
42
|
+
* @param int $bytes The maximum size in bytes.
|
|
43
|
+
* @return void
|
|
44
|
+
*/
|
|
45
|
+
public function setMaxSize(int $bytes): void
|
|
46
|
+
{
|
|
47
|
+
$serverMax = self::convertToBytes(ini_get('upload_max_filesize'));
|
|
48
|
+
if ($bytes > $serverMax) {
|
|
49
|
+
throw new \Exception('Maximum size cannot exceed server limit for individual files: ' . self::convertFromBytes($serverMax));
|
|
50
|
+
}
|
|
51
|
+
if ($bytes > 0) {
|
|
52
|
+
$this->maxSize = $bytes;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Converts a string value representing a file size to bytes.
|
|
58
|
+
*
|
|
59
|
+
* @param string $val The string value representing the file size.
|
|
60
|
+
* @return int The file size in bytes.
|
|
61
|
+
*/
|
|
62
|
+
public static function convertToBytes(string $val): int
|
|
63
|
+
{
|
|
64
|
+
$val = trim($val);
|
|
65
|
+
$last = strtolower($val[strlen($val) - 1]);
|
|
66
|
+
$multiplier = match ($last) {
|
|
67
|
+
'g' => 1024 * 1024 * 1024,
|
|
68
|
+
'm' => 1024 * 1024,
|
|
69
|
+
'k' => 1024,
|
|
70
|
+
default => 1,
|
|
71
|
+
};
|
|
72
|
+
return (int) $val * $multiplier;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Converts the given number of bytes to a human-readable string representation.
|
|
77
|
+
*
|
|
78
|
+
* @param int $bytes The number of bytes to convert.
|
|
79
|
+
* @return string The human-readable string representation of the converted bytes.
|
|
80
|
+
*/
|
|
81
|
+
public static function convertFromBytes(int $bytes): string
|
|
82
|
+
{
|
|
83
|
+
return $bytes >= 1024 * 1024
|
|
84
|
+
? number_format($bytes / (1024 * 1024), 1) . ' MB'
|
|
85
|
+
: number_format($bytes / 1024, 1) . ' KB';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Disable type checking and set the allowed file types.
|
|
90
|
+
*
|
|
91
|
+
* @param string|null $suffix The file suffix to allow. If null, the current suffix will be used.
|
|
92
|
+
* @return void
|
|
93
|
+
*/
|
|
94
|
+
public function allowAllTypes(?string $suffix = null): void
|
|
95
|
+
{
|
|
96
|
+
$this->typeCheckingOn = false;
|
|
97
|
+
$this->suffix = $suffix ? (strpos($suffix, '.') === 0 ? $suffix : ".$suffix") : $this->suffix;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Uploads file(s) to the server.
|
|
102
|
+
*
|
|
103
|
+
* @param bool $renameDuplicates (optional) Whether to rename duplicate files. Default is true.
|
|
104
|
+
* @return void
|
|
105
|
+
*/
|
|
106
|
+
public function upload(bool $renameDuplicates = true): void
|
|
107
|
+
{
|
|
108
|
+
$this->renameDuplicates = $renameDuplicates;
|
|
109
|
+
if (empty($_FILES) || !is_array(current($_FILES))) {
|
|
110
|
+
// No file was uploaded or the structure is invalid, handle this as an error
|
|
111
|
+
$this->messages[] = "No files were uploaded.";
|
|
112
|
+
$this->errorCode[] = UPLOAD_ERR_NO_FILE;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
$uploaded = current($_FILES);
|
|
117
|
+
|
|
118
|
+
// Handle single and multiple file uploads using a unified approach
|
|
119
|
+
$files = is_array($uploaded['name']) ? $this->rearrangeFilesArray($uploaded) : [$uploaded];
|
|
120
|
+
|
|
121
|
+
foreach ($files as $file) {
|
|
122
|
+
if ($this->checkFile($file)) {
|
|
123
|
+
$this->moveFile($file);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Updates an existing file by deleting the old file and uploading the new one, using the old file's name.
|
|
130
|
+
*
|
|
131
|
+
* @param array $file The new file information from $_FILES.
|
|
132
|
+
* @param string $oldFilename The name of the file to be replaced.
|
|
133
|
+
* @return bool True if the update was successful, false otherwise.
|
|
134
|
+
*/
|
|
135
|
+
public function update(array $file, string $oldFilename): bool
|
|
136
|
+
{
|
|
137
|
+
// First, delete the old file
|
|
138
|
+
if (!$this->delete($oldFilename)) {
|
|
139
|
+
$this->messages[] = "Failed to delete the old file $oldFilename. Update aborted.";
|
|
140
|
+
$this->errorCode[] = UPLOAD_ERR_CANT_WRITE; // Error code for failure to update
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Now proceed to upload the new file with the old filename
|
|
145
|
+
if ($this->checkFile($file)) {
|
|
146
|
+
// Set the new file name to match the old file's name
|
|
147
|
+
$this->newName = $oldFilename;
|
|
148
|
+
$this->moveFile($file);
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Renames a file in the destination folder.
|
|
157
|
+
*
|
|
158
|
+
* @param string $oldName The current name of the file.
|
|
159
|
+
* @param string $newName The new name for the file.
|
|
160
|
+
* @return bool True if the rename was successful, false otherwise.
|
|
161
|
+
*/
|
|
162
|
+
public function rename(string $oldName, string $newName): bool
|
|
163
|
+
{
|
|
164
|
+
$oldPath = $this->destination . $oldName;
|
|
165
|
+
|
|
166
|
+
// Extract the file extension from the old file
|
|
167
|
+
$extension = pathinfo($oldName, PATHINFO_EXTENSION);
|
|
168
|
+
|
|
169
|
+
// Add the extension to the new name
|
|
170
|
+
$newNameWithExtension = str_replace(' ', '_', $newName) . '.' . $extension;
|
|
171
|
+
$newPath = $this->destination . $newNameWithExtension;
|
|
172
|
+
|
|
173
|
+
// Check if the file exists
|
|
174
|
+
if (!file_exists($oldPath)) {
|
|
175
|
+
$this->messages[] = "File $oldName does not exist.";
|
|
176
|
+
$this->errorCode[] = UPLOAD_ERR_NO_FILE; // Error code for file not found
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Validate that the new name doesn't already exist
|
|
181
|
+
if (file_exists($newPath)) {
|
|
182
|
+
$this->messages[] = "A file with the name $newNameWithExtension already exists.";
|
|
183
|
+
$this->errorCode[] = UPLOAD_ERR_CANT_WRITE; // Error code for name conflict
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Attempt to rename the file
|
|
188
|
+
if (rename($oldPath, $newPath)) {
|
|
189
|
+
$this->messages[] = "File $oldName renamed successfully to $newNameWithExtension";
|
|
190
|
+
$this->errorCode[] = 0; // Success code
|
|
191
|
+
return true;
|
|
192
|
+
} else {
|
|
193
|
+
$this->messages[] = "Failed to rename $oldName to $newNameWithExtension";
|
|
194
|
+
$this->errorCode[] = UPLOAD_ERR_CANT_WRITE; // Error code for rename failure
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Deletes a file from the destination folder.
|
|
201
|
+
*
|
|
202
|
+
* @param string $filename The name of the file to delete.
|
|
203
|
+
* @return bool True if the file was deleted, false otherwise.
|
|
204
|
+
*/
|
|
205
|
+
public function delete(string $filename): bool
|
|
206
|
+
{
|
|
207
|
+
$filePath = $this->destination . $filename;
|
|
208
|
+
|
|
209
|
+
if (!file_exists($filePath)) {
|
|
210
|
+
$this->messages[] = "File $filename does not exist.";
|
|
211
|
+
$this->errorCode[] = UPLOAD_ERR_NO_FILE; // Error code for file not found
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (unlink($filePath)) {
|
|
216
|
+
$this->messages[] = "File $filename deleted successfully.";
|
|
217
|
+
$this->errorCode[] = 0; // Success code
|
|
218
|
+
return true;
|
|
219
|
+
} else {
|
|
220
|
+
$this->messages[] = "Failed to delete $filename.";
|
|
221
|
+
$this->errorCode[] = UPLOAD_ERR_CANT_WRITE; // Error code for failure to delete
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Retrieves the messages associated with the file upload.
|
|
228
|
+
*
|
|
229
|
+
* @return array The array of messages.
|
|
230
|
+
*/
|
|
231
|
+
public function getMessages(): array
|
|
232
|
+
{
|
|
233
|
+
return $this->messages;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Retrieves the error codes associated with the file upload.
|
|
238
|
+
*
|
|
239
|
+
* @return array The array of error codes.
|
|
240
|
+
*/
|
|
241
|
+
public function getErrorCode(): array
|
|
242
|
+
{
|
|
243
|
+
return $this->errorCode;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
protected function checkFile(array $file): bool
|
|
247
|
+
{
|
|
248
|
+
if ($file['error'] !== UPLOAD_ERR_OK) {
|
|
249
|
+
$this->getErrorMessage($file);
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
if (!$this->checkSize($file) || ($this->typeCheckingOn && !$this->checkType($file))) {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
$this->checkName($file);
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
protected function getErrorMessage(array $file): void
|
|
260
|
+
{
|
|
261
|
+
$errorMessages = [
|
|
262
|
+
UPLOAD_ERR_INI_SIZE => $file['name'] . ' exceeds the maximum size: ' . self::convertFromBytes($this->maxSize),
|
|
263
|
+
UPLOAD_ERR_FORM_SIZE => $file['name'] . ' exceeds the form limit.',
|
|
264
|
+
UPLOAD_ERR_PARTIAL => $file['name'] . ' was only partially uploaded.',
|
|
265
|
+
UPLOAD_ERR_NO_FILE => 'No file submitted.',
|
|
266
|
+
];
|
|
267
|
+
|
|
268
|
+
$this->errorCode = $file['error'];
|
|
269
|
+
$this->messages[] = $errorMessages[$file['error']] ?? 'Problem uploading ' . $file['name'];
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
protected function checkSize(array $file): bool
|
|
273
|
+
{
|
|
274
|
+
if ($file['size'] == 0) {
|
|
275
|
+
$this->messages[] = $file['name'] . ' is empty.';
|
|
276
|
+
$this->errorCode[] = UPLOAD_ERR_NO_FILE; // Log an error code for empty files
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
if ($file['size'] > $this->maxSize) {
|
|
280
|
+
$this->messages[] = $file['name'] . ' exceeds the maximum size: ' . self::convertFromBytes($this->maxSize);
|
|
281
|
+
$this->errorCode[] = UPLOAD_ERR_INI_SIZE; // Log an error code for exceeding size
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
protected function checkType(array $file): bool
|
|
288
|
+
{
|
|
289
|
+
if (!in_array($file['type'], $this->permittedTypes)) {
|
|
290
|
+
$this->messages[] = $file['name'] . ' is not a permitted type.';
|
|
291
|
+
$this->errorCode[] = UPLOAD_ERR_EXTENSION; // Log an error code for invalid file type
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
protected function checkName(array $file): void
|
|
298
|
+
{
|
|
299
|
+
$name = str_replace(' ', '_', $file['name']);
|
|
300
|
+
$nameParts = pathinfo($name);
|
|
301
|
+
$extension = $nameParts['extension'] ?? '';
|
|
302
|
+
|
|
303
|
+
// Handle trusted vs untrusted extensions
|
|
304
|
+
if (!$this->typeCheckingOn && (in_array($extension, $this->notTrusted) || empty($extension))) {
|
|
305
|
+
$this->newName = $name . $this->suffix;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Rename duplicates if necessary
|
|
309
|
+
if ($this->renameDuplicates) {
|
|
310
|
+
$existingFiles = scandir($this->destination);
|
|
311
|
+
$originalName = $name;
|
|
312
|
+
$i = 1;
|
|
313
|
+
|
|
314
|
+
while (in_array($name, $existingFiles)) {
|
|
315
|
+
$name = "{$nameParts['filename']}_$i." . ($extension ?: ''); // Maintain the extension if available
|
|
316
|
+
$i++;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
$this->newName = $name;
|
|
320
|
+
} else {
|
|
321
|
+
$this->newName = $name;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
protected function moveFile(array $file): void
|
|
326
|
+
{
|
|
327
|
+
// Ensure the newName is set or fallback to the original file name
|
|
328
|
+
$filename = $this->newName ?: $file['name'];
|
|
329
|
+
$destination = $this->destination . $filename;
|
|
330
|
+
$success = move_uploaded_file($file['tmp_name'], $destination);
|
|
331
|
+
|
|
332
|
+
if ($success) {
|
|
333
|
+
$message = "{$file['name']} uploaded successfully.";
|
|
334
|
+
if ($this->newName && $this->newName !== $file['name']) {
|
|
335
|
+
$message .= " Renamed to {$this->newName}";
|
|
336
|
+
}
|
|
337
|
+
} else {
|
|
338
|
+
$message = "Failed to upload {$file['name']}.";
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
$this->messages[] = $message;
|
|
342
|
+
// Add a success/error code for file move
|
|
343
|
+
$this->errorCode[] = $success ? 0 : UPLOAD_ERR_CANT_WRITE; // 0 for success, error code for failure
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Utility function to restructure the $_FILES array for multiple uploads
|
|
347
|
+
protected function rearrangeFilesArray(array $files): array
|
|
348
|
+
{
|
|
349
|
+
$rearranged = [];
|
|
350
|
+
foreach ($files['name'] as $key => $name) {
|
|
351
|
+
$rearranged[] = [
|
|
352
|
+
'name' => $files['name'][$key],
|
|
353
|
+
'type' => $files['type'][$key],
|
|
354
|
+
'tmp_name' => $files['tmp_name'][$key],
|
|
355
|
+
'error' => $files['error'][$key],
|
|
356
|
+
'size' => $files['size'][$key],
|
|
357
|
+
];
|
|
358
|
+
}
|
|
359
|
+
return $rearranged;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
@@ -104,10 +104,23 @@ class StateManager
|
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
106
|
* Resets the application state to an empty array.
|
|
107
|
+
*
|
|
108
|
+
* @param string|null $key The key of the state value to reset.
|
|
107
109
|
*/
|
|
108
|
-
public function resetState(): void
|
|
110
|
+
public function resetState(string $key = null): void
|
|
109
111
|
{
|
|
110
|
-
$
|
|
112
|
+
if ($key !== null) {
|
|
113
|
+
if (array_key_exists($key, $this->state)) {
|
|
114
|
+
$this->state[$key] = null;
|
|
115
|
+
|
|
116
|
+
if (array_key_exists($key, $GLOBALS)) {
|
|
117
|
+
$GLOBALS[$key] = null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
$this->state = [];
|
|
122
|
+
}
|
|
123
|
+
|
|
111
124
|
$this->notifyListeners();
|
|
112
125
|
$this->saveState();
|
|
113
126
|
}
|
|
@@ -533,6 +533,14 @@ final class Validator
|
|
|
533
533
|
return true;
|
|
534
534
|
}
|
|
535
535
|
break;
|
|
536
|
+
case 'extensions':
|
|
537
|
+
$extensions = explode(',', $parameter);
|
|
538
|
+
if (!self::isExtensionAllowed($value, $extensions)) {
|
|
539
|
+
return "The file must have one of the following extensions: " . implode(', ', $extensions) . ".";
|
|
540
|
+
} else {
|
|
541
|
+
return true;
|
|
542
|
+
}
|
|
543
|
+
break;
|
|
536
544
|
case 'mimes':
|
|
537
545
|
$mimeTypes = explode(',', $parameter);
|
|
538
546
|
if (!self::isMimeTypeAllowed($value, $mimeTypes)) {
|
|
@@ -554,6 +562,29 @@ final class Validator
|
|
|
554
562
|
}
|
|
555
563
|
}
|
|
556
564
|
|
|
565
|
+
/**
|
|
566
|
+
* Check if a file's extension is in the list of allowed extensions.
|
|
567
|
+
*
|
|
568
|
+
* @param string $file The path or filename of the file.
|
|
569
|
+
* @param array $allowedExtensions The list of allowed extensions.
|
|
570
|
+
* @return bool True if the extension is allowed, false otherwise.
|
|
571
|
+
*/
|
|
572
|
+
private static function isExtensionAllowed($file, array $allowedExtensions): bool
|
|
573
|
+
{
|
|
574
|
+
// Extract the file extension
|
|
575
|
+
$fileExtension = pathinfo($file, PATHINFO_EXTENSION);
|
|
576
|
+
|
|
577
|
+
// Check if the extension is in the allowed list
|
|
578
|
+
return in_array(strtolower($fileExtension), array_map('strtolower', $allowedExtensions), true);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Check if a file's MIME type is in the list of allowed MIME types.
|
|
583
|
+
*
|
|
584
|
+
* @param string $file The path or filename of the file.
|
|
585
|
+
* @param array $allowedMimeTypes The list of allowed MIME types.
|
|
586
|
+
* @return bool True if the MIME type is allowed, false otherwise.
|
|
587
|
+
*/
|
|
557
588
|
private static function isMimeTypeAllowed($file, array $allowedMimeTypes)
|
|
558
589
|
{
|
|
559
590
|
// Check if the file is a valid uploaded file
|