PluginProbe
ووسلام – همگام سازی ووکامرس و باسلام / 1.10.19
ووسلام – همگام سازی ووکامرس و باسلام v1.10.19
1.10.19 1.10.20 1.10.18 1.10.17 1.10.15 1.10.14 1.10.13 1.10.12 1.10.10 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.2 1.9.1 1.9.0 1.8.8 1.8.5 1.8.6 All 53 releases
← All changes | includes/Services/FileUploader.php +87 -57 1.8.51.10.19 View file →
@@ -1,46 +1,86 @@
1 1 <?php
2 2
3 3 namespace SyncBasalam\Services;
4 4
5 -use SyncBasalam\Admin\Settings\SettingsConfig;
6 -use SyncBasalam\Config\Endpoints;
5 +defined('ABSPATH') || exit;
7 6
8 -defined('ABSPATH') || exit;
9 7 class FileUploader
10 8 {
9 + private const PHOTO_EXTENSIONS = ['jpg', 'png', 'webp', 'gif', 'bmp', 'jfif', 'jpeg', 'avif'];
10 + private const PHOTO_MAX_SIZE = 5 * 1024 * 1024;
11 +
12 + private const VIDEO_EXTENSIONS = ['mp4', 'mov', '3gp', 'm4v', 'mkv', 'flv', 'mpg', 'webm', 'mpeg', 'ts', 'avi', 'qt', 'm4a'];
13 + private const VIDEO_MAX_SIZE = 120 * 1024 * 1024;
14 +
11 15 public function upload($filePath)
12 16 {
13 - $preparedFile = $this->prepare($filePath);
17 + return $this->uploadMedia($filePath, [
18 + 'file_type' => 'product.photo',
19 + 'allowed_extensions' => self::PHOTO_EXTENSIONS,
20 + 'max_size' => self::PHOTO_MAX_SIZE,
21 + 'error_label' => 'تصویر',
22 + ]);
23 + }
14 24
25 + public function uploadVideo($filePath)
26 + {
27 + return $this->uploadMedia($filePath, [
28 + 'file_type' => 'product.video',
29 + 'allowed_extensions' => self::VIDEO_EXTENSIONS,
30 + 'max_size' => self::VIDEO_MAX_SIZE,
31 + 'error_label' => 'ویدیو',
32 + ]);
33 + }
34 +
35 + private function uploadMedia(string $filePath, array $config): array
36 + {
37 + $preparedFile = $this->prepare($filePath, $config['allowed_extensions'], $config['max_size']);
38 +
15 39 if ($preparedFile === false) {
16 - return false;
40 + throw new \RuntimeException('فایل ' . esc_html($config['error_label']) . ' برای آپلود معتبر یا در دسترس نیست.');
17 41 }
18 42
19 43 $pathToUpload = $preparedFile['path'];
20 - $isTemp = $preparedFile['isTemp'];
21 44 $tmpFile = $preparedFile['tmpFile'] ?? null;
45 + $normalizedFile = null;
22 46
23 - if (!$this->checkFileSize($pathToUpload)) {
24 - if ($isTemp && $tmpFile) unlink($tmpFile);
25 - return false;
26 - }
47 + try {
48 + if (!$this->checkFileSize($pathToUpload, $config['max_size'])) {
49 + throw new \RuntimeException('حجم فایل ' . esc_html($config['error_label']) . ' بیش از حد مجاز است.');
50 + }
27 51
28 - $response = $this->uploadFileToBasalam($pathToUpload);
52 + if ($config['file_type'] === 'product.photo') {
53 + $normalizedFile = (new ImageFormatNormalizer())->normalize($pathToUpload, $config['max_size']);
54 + if ($normalizedFile !== null) $pathToUpload = $normalizedFile;
55 + }
29 56
30 - if ($isTemp && $tmpFile) unlink($tmpFile);
57 + if (!$this->checkFileSize($pathToUpload, $config['max_size'])) {
58 + throw new \RuntimeException('حجم فایل ' . esc_html($config['error_label']) . ' بیش از حد مجاز است.');
59 + }
31 60
32 - if ($response && $response['status_code'] == 200 && $response['body']) {
33 - return [
34 - 'file_id' => $response['body']['id'],
35 - 'url' => $response['body']['urls']['primary'],
61 + $options = [
62 + 'allowed_extensions' => $config['file_type'] === 'product.photo'
63 + ? ImageFormatNormalizer::SUPPORTED_EXTENSIONS
64 + : $config['allowed_extensions'],
65 + 'max_size' => $config['max_size'],
66 + 'timeout' => $config['file_type'] === 'product.video' ? 600 : 120,
36 67 ];
68 +
69 + $mediaUploader = new MediaUploadService();
70 +
71 + if ($config['file_type'] === 'product.video') {
72 + return $mediaUploader->uploadVideo($pathToUpload, $options);
73 + }
74 +
75 + return $mediaUploader->uploadPhoto($pathToUpload, $options);
76 + } finally {
77 + if ($normalizedFile && file_exists($normalizedFile)) unlink($normalizedFile);
78 + if (!empty($preparedFile['isTemp']) && $tmpFile && file_exists($tmpFile)) unlink($tmpFile);
37 79 }
38 -
39 - return false;
40 80 }
41 81
42 - private function prepare($filePath)
82 + private function prepare($filePath, array $allowedExtensions, int $maxSize)
43 83 {
44 84 if (filter_var($filePath, FILTER_VALIDATE_URL)) {
45 85 $parsedUrl = parse_url($filePath);
46 86 $path = $parsedUrl['path'] ?? $filePath;
@@ -45,67 +85,57 @@
45 85 $parsedUrl = parse_url($filePath);
46 86 $path = $parsedUrl['path'] ?? $filePath;
47 87 $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
48 88
49 - if (!$this->FileExtensionValidator($extension)) return false;
89 + if (!in_array($extension, $allowedExtensions, true)) return false;
50 90
51 91 $tmpFile = sys_get_temp_dir() . '/' . uniqid('upload_', true) . '.' . $extension;
92 + $response = wp_safe_remote_get($filePath, [
93 + 'timeout' => 600,
94 + 'stream' => true,
95 + 'filename' => $tmpFile,
96 + 'limit_response_size' => $maxSize + 1,
97 + ]);
52 98
53 - $fileContents = file_get_contents($filePath);
99 + if (is_wp_error($response)) {
100 + if (file_exists($tmpFile)) unlink($tmpFile);
101 + throw new \RuntimeException('دانلود فایل از آدرس مبدا ناموفق بود: ' . esc_html($response->get_error_message()));
102 + }
54 103
55 - if ($fileContents === false) return false;
104 + $statusCode = (int) wp_remote_retrieve_response_code($response);
105 + if ($statusCode < 200 || $statusCode >= 300 || !file_exists($tmpFile)) {
106 + if (file_exists($tmpFile)) unlink($tmpFile);
107 + throw new \RuntimeException('دانلود فایل از آدرس مبدا ناموفق بود.');
108 + }
56 109
57 - file_put_contents($tmpFile, $fileContents);
58 -
59 110 return [
60 111 'path' => $tmpFile,
61 112 'isTemp' => true,
62 113 'tmpFile' => $tmpFile
63 114 ];
64 - } else {
65 - if (!file_exists($filePath)) return false;
115 + }
66 116
67 - $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
117 + if (!file_exists($filePath)) return false;
68 118
69 - if (!$this->FileExtensionValidator($extension)) return false;
119 + $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
120 + if (!in_array($extension, $allowedExtensions, true)) return false;
70 121
71 - return [
72 - 'path' => $filePath,
73 - 'isTemp' => false,
74 - 'tmpFile' => null
75 - ];
76 - }
122 + return [
123 + 'path' => $filePath,
124 + 'isTemp' => false,
125 + 'tmpFile' => null
126 + ];
77 127 }
78 128
79 - public function checkFileSize($path)
129 + public function checkFileSize($path, int $maxSize = self::PHOTO_MAX_SIZE): bool
80 130 {
81 131 if (!file_exists($path)) return false;
82 132
83 133 $fileSize = filesize($path);
84 -
85 - if ($fileSize > 5 * 1024 * 1024) return false;
86 -
87 - return true;
134 + return $fileSize !== false && $fileSize <= $maxSize;
88 135 }
89 136
90 137 public function FileExtensionValidator($extension)
91 138 {
92 - $allowedExtensions = ['jpg', 'png', 'webp', 'bmp', 'jfif', 'jpeg', 'avif'];
93 - return in_array($extension, $allowedExtensions);
94 - }
95 -
96 - public function uploadFileToBasalam($filePath)
97 - {
98 - $apiService = syncBasalamContainer()->get(ApiServiceManager::class);
99 -
100 - $url = Endpoints::FILE_UPLOAD;
101 -
102 - $data = ['file_type' => 'product.photo'];
103 - $token = syncBasalamSettings()->getSettings(SettingsConfig::TOKEN);
104 -
105 - $headers = ['Authorization' => 'Bearer ' . $token];
106 -
107 - $response = $apiService->upload($url, $filePath, $data, $headers);
108 -
109 - return $response;
139 + return in_array($extension, self::PHOTO_EXTENSIONS, true);
110 140 }
111 141 }