| @@ -1032,10 +1032,11 @@ | ||
| 1032 | 1032 | $do_reupload = apply_filters('wpmcs_do_reupload_media', false, $attachment_id, 'media_library'); |
| 1033 | 1033 | |
| 1034 | 1034 | // Force reupload when sizes/dimensions changed |
| 1035 | 1035 | if (!$do_reupload && $has_existing) { |
| 1036 | - if($this->shouldForceReupload($attachment_meta, $attachment_id, $existing_extras)) { | |
| 1037 | - $do_reupload = true; | |
| 1036 | + $force_reupload = $this->shouldForceReupload($attachment_meta, $attachment_id, $existing_extras); | |
| 1037 | + if ($force_reupload !== false) { | |
| 1038 | + $do_reupload = $force_reupload; | |
| 1038 | 1039 | } |
| 1039 | 1040 | } |
| 1040 | 1041 | |
| 1041 | 1042 | // Add prefix if object versioning is ON |
| @@ -1062,8 +1063,9 @@ | ||
| 1062 | 1063 | |
| 1063 | 1064 | if ($uploaded && isset($uploaded['success']) && $uploaded['success']) { |
| 1064 | 1065 | // Attempt to upload original file if present. Not critical if this fails so we don't check the result before proceeding. |
| 1065 | 1066 | $original = $this->uploadOriginalFile($original_file, $file_dir, $do_reupload, $has_existing, $existing, $prefix, $attachment_id, $is_private); |
| 1067 | + $additional_files = []; | |
| 1066 | 1068 | |
| 1067 | 1069 | if ($is_image && isset($file_dir) && !empty($file_dir)) { |
| 1068 | 1070 | $sizes_to_upload = $this->get_attachment_image_sizes_for_upload($attachment_meta, $attachment_id); |
| 1069 | 1071 | if (!empty($sizes_to_upload)) { |
| @@ -1069,8 +1071,9 @@ | ||
| 1069 | 1071 | if (!empty($sizes_to_upload)) { |
| 1070 | 1072 | // Upload image sizes. Again, not critical if this fails so we don't check the result before proceeding. |
| 1071 | 1073 | $sizes = $this->uploadImageSizes($sizes_to_upload, $file_dir, $do_reupload, $existing_extras, $prefix, $attachment_id, $is_private); |
| 1072 | 1074 | } |
| 1075 | + $additional_files = $this->uploadAdditionalFiles($attachment_meta, $file_dir, $do_reupload, $has_existing, $existing_extras, $prefix, $attachment_id, $is_private); | |
| 1073 | 1076 | } |
| 1074 | 1077 | |
| 1075 | 1078 | if (!empty($sizes)) { |
| 1076 | 1079 | // Merge over existing sizes rather than replacing wholesale — a size that |
| @@ -1088,8 +1091,15 @@ | ||
| 1088 | 1091 | |
| 1089 | 1092 | $extras['sizes'] = array_merge($existing_sizes, $sizes); |
| 1090 | 1093 | } |
| 1091 | 1094 | |
| 1095 | + if (!empty($additional_files)) { | |
| 1096 | + $existing_additional_files = isset($existing_extras['additional_files']) && is_array($existing_extras['additional_files']) | |
| 1097 | + ? $existing_extras['additional_files'] | |
| 1098 | + : []; | |
| 1099 | + $extras['additional_files'] = array_merge($existing_additional_files, $additional_files); | |
| 1100 | + } | |
| 1101 | + | |
| 1092 | 1102 | return [ |
| 1093 | 1103 | 'file' => [ |
| 1094 | 1104 | 'source_path' => $source_path, |
| 1095 | 1105 | 'url' => $uploaded['file_url'], |
| @@ -1143,8 +1153,10 @@ | ||
| 1143 | 1153 | * @since 1.3.6 |
| 1144 | 1154 | * @param array $attachment_meta |
| 1145 | 1155 | * @param int $attachment_id |
| 1146 | 1156 | * @param array $existing_extras |
| 1157 | + * @return bool|array True forces a full reupload (main file changed); an array of | |
| 1158 | + * size names forces only those sizes; false means nothing changed. | |
| 1147 | 1159 | */ |
| 1148 | 1160 | private function shouldForceReupload($attachment_meta, $attachment_id, $existing_extras) { |
| 1149 | 1161 | $existing_extras = $existing_extras ?? Item::instance()->get_extras($attachment_id, false, 'media_library'); |
| 1150 | 1162 | |
| @@ -1171,31 +1183,26 @@ | ||
| 1171 | 1183 | 'height' => isset($smeta['height']) ? (int)$smeta['height'] : 0, |
| 1172 | 1184 | ]; |
| 1173 | 1185 | } |
| 1174 | 1186 | |
| 1175 | - $existing_relevant = []; | |
| 1176 | - foreach (array_keys($current_sizes) as $sname) { | |
| 1177 | - if (isset($existing_sizes[$sname])) { | |
| 1178 | - $existing_relevant[$sname] = $existing_sizes[$sname]; | |
| 1179 | - } | |
| 1180 | - } | |
| 1181 | - | |
| 1182 | - if (array_keys($existing_relevant) !== array_keys($current_sizes)) { | |
| 1183 | - return true; | |
| 1184 | - } | |
| 1185 | - | |
| 1187 | + // The main file is unchanged (already ruled out above) — a mismatch here is | |
| 1188 | + // limited to specific sizes, so re-send only those instead of forcing a | |
| 1189 | + // blanket reupload that would also re-fetch the main file from local disk | |
| 1190 | + // (which "Remove from server" may have already, correctly, deleted). | |
| 1191 | + $changed_sizes = []; | |
| 1186 | 1192 | foreach ($current_sizes as $sname => $dims) { |
| 1187 | 1193 | if (!isset($existing_sizes[$sname])) { |
| 1188 | - return true; | |
| 1194 | + $changed_sizes[] = $sname; | |
| 1195 | + continue; | |
| 1189 | 1196 | } |
| 1190 | 1197 | $ex_w = isset($existing_sizes[$sname]['width']) ? (int)$existing_sizes[$sname]['width'] : 0; |
| 1191 | 1198 | $ex_h = isset($existing_sizes[$sname]['height']) ? (int)$existing_sizes[$sname]['height'] : 0; |
| 1192 | 1199 | if ($ex_w !== $dims['width'] || $ex_h !== $dims['height']) { |
| 1193 | - return true; | |
| 1200 | + $changed_sizes[] = $sname; | |
| 1194 | 1201 | } |
| 1195 | 1202 | } |
| 1196 | 1203 | |
| 1197 | - return false; | |
| 1204 | + return empty($changed_sizes) ? false : $changed_sizes; | |
| 1198 | 1205 | } |
| 1199 | 1206 | |
| 1200 | 1207 | /** |
| 1201 | 1208 | * Upload the main/full file. |
| @@ -1245,44 +1252,110 @@ | ||
| 1245 | 1252 | * @param int $attachment_id |
| 1246 | 1253 | * @param bool $is_private Keeps a reupload of an already-private item under the private path. |
| 1247 | 1254 | */ |
| 1248 | 1255 | private function uploadOriginalFile($original_file, $file_dir, $do_reupload, $has_existing, $existing, $prefix, $attachment_id, $is_private = false) { |
| 1249 | - $original = []; | |
| 1250 | - if (empty($original_file)) { | |
| 1251 | - return $original; | |
| 1256 | + return $this->uploadNamedFile( | |
| 1257 | + $original_file, $file_dir, | |
| 1258 | + $existing['original_source_path'] ?? '', $existing['original_key'] ?? '', | |
| 1259 | + $do_reupload, $has_existing, $prefix, $attachment_id, $is_private, | |
| 1260 | + __('Original File not found', 'media-cloud-sync') | |
| 1261 | + ); | |
| 1262 | + } | |
| 1263 | + | |
| 1264 | + /** | |
| 1265 | + * Upload one optional named additional file (original image, HEIC source, | |
| 1266 | + * animated-GIF video/poster) that lives alongside the main file. | |
| 1267 | + * @since 1.4.3 | |
| 1268 | + * @param string $filename Relative filename within $file_dir, or empty if absent. | |
| 1269 | + * @param string $file_dir | |
| 1270 | + * @param string $existing_source_path Previously recorded source_path, if any. | |
| 1271 | + * @param string $existing_key Previously recorded cloud key, if any. | |
| 1272 | + * @param bool|array $do_reupload Reupload everything (true), nothing (false), or only these sizes (array of size names). | |
| 1273 | + * @param bool $has_existing | |
| 1274 | + * @param string $prefix | |
| 1275 | + * @param int $attachment_id | |
| 1276 | + * @param bool $is_private Keeps a reupload of an already-private item under the private path. | |
| 1277 | + * @param string $not_found_message | |
| 1278 | + * @return array{source_path?: string, key?: string} Empty when absent or upload failed. | |
| 1279 | + */ | |
| 1280 | + private function uploadNamedFile($filename, $file_dir, $existing_source_path, $existing_key, $do_reupload, $has_existing, $prefix, $attachment_id, $is_private, $not_found_message) { | |
| 1281 | + if (empty($filename)) { | |
| 1282 | + return []; | |
| 1252 | 1283 | } |
| 1253 | 1284 | |
| 1254 | - $original_file_path = trailingslashit($file_dir) . $original_file; | |
| 1255 | - $original_file_source_path = Utils::get_attachment_source_path($original_file_path); | |
| 1285 | + $file_path = trailingslashit($file_dir) . $filename; | |
| 1286 | + $source_path = Utils::get_attachment_source_path($file_path); | |
| 1256 | 1287 | |
| 1257 | 1288 | // $do_reupload may be an array of size names (force just those sizes) — that |
| 1258 | - // shouldn't force the original file too, only a literal true does. | |
| 1259 | - if ($do_reupload !== true && $has_existing && isset($existing['original_source_path']) && !Utils::is_empty($existing['original_source_path']) && $existing['original_source_path'] === $original_file_source_path) { | |
| 1260 | - return [ 'source_path' => $original_file_source_path, 'key' => $existing['original_key'] ]; | |
| 1289 | + // shouldn't force this file too, only a literal true does. | |
| 1290 | + if ($do_reupload !== true && $has_existing && !Utils::is_empty($existing_source_path) && $existing_source_path === $source_path) { | |
| 1291 | + return [ 'source_path' => $source_path, 'key' => $existing_key ]; | |
| 1261 | 1292 | } |
| 1262 | 1293 | |
| 1263 | - if (file_exists($original_file_path)) { | |
| 1264 | - $uploaded_original = Service::instance()->uploadSingle($original_file_path, $original_file_source_path, $prefix, $is_private); | |
| 1265 | - if (isset($uploaded_original['success']) && $uploaded_original['success']) { | |
| 1266 | - return [ 'source_path' => $original_file_source_path, 'key' => $uploaded_original['key'] ]; | |
| 1294 | + if (file_exists($file_path)) { | |
| 1295 | + $uploaded = Service::instance()->uploadSingle($file_path, $source_path, $prefix, $is_private); | |
| 1296 | + if (isset($uploaded['success']) && $uploaded['success']) { | |
| 1297 | + return [ 'source_path' => $source_path, 'key' => $uploaded['key'] ]; | |
| 1267 | 1298 | } |
| 1268 | 1299 | |
| 1269 | - if (isset($uploaded_original['success']) && !$uploaded_original['success']) { | |
| 1300 | + if (isset($uploaded['success']) && !$uploaded['success']) { | |
| 1270 | 1301 | Logger::instance()->add_log('sync_to_cloud', $attachment_id, 'media_library', [ |
| 1271 | - 'message' => $uploaded_original['message'] ?? __('Original File upload failed', 'media-cloud-sync'), | |
| 1272 | - 'file' => $original_file_path, | |
| 1273 | - 'code' => $uploaded_original['code'] ?? 500 | |
| 1302 | + 'message' => $uploaded['message'] ?? $not_found_message, | |
| 1303 | + 'file' => $file_path, | |
| 1304 | + 'code' => $uploaded['code'] ?? 500 | |
| 1274 | 1305 | ]); |
| 1275 | 1306 | } |
| 1276 | 1307 | } else { |
| 1277 | 1308 | Logger::instance()->add_log('sync_to_cloud', $attachment_id, 'media_library', [ |
| 1278 | - 'message' => __('Original File not found', 'media-cloud-sync'), | |
| 1279 | - 'file' => $original_file_path, | |
| 1309 | + 'message' => $not_found_message, | |
| 1310 | + 'file' => $file_path, | |
| 1280 | 1311 | 'code' => 404 |
| 1281 | 1312 | ]); |
| 1282 | 1313 | } |
| 1283 | 1314 | |
| 1284 | - return $original; | |
| 1315 | + return []; | |
| 1316 | + } | |
| 1317 | + | |
| 1318 | + /** | |
| 1319 | + * Upload the WP 7.1 client-side-processing additional files (HEIC source, | |
| 1320 | + * animated-GIF video/poster) that uploadMedia() otherwise has no idea exist. | |
| 1321 | + * @since 1.4.3 | |
| 1322 | + * @param array $attachment_meta | |
| 1323 | + * @param string $file_dir | |
| 1324 | + * @param bool|array $do_reupload | |
| 1325 | + * @param bool $has_existing | |
| 1326 | + * @param array $existing_extras | |
| 1327 | + * @param string $prefix | |
| 1328 | + * @param int $attachment_id | |
| 1329 | + * @param bool $is_private | |
| 1330 | + * @return array Keyed by meta key ('source_image', 'animated_video', 'animated_video_poster'). | |
| 1331 | + */ | |
| 1332 | + private function uploadAdditionalFiles($attachment_meta, $file_dir, $do_reupload, $has_existing, $existing_extras, $prefix, $attachment_id, $is_private) { | |
| 1333 | + $additional_file_keys = [ | |
| 1334 | + 'source_image' => __('HEIC source file not found', 'media-cloud-sync'), | |
| 1335 | + 'animated_video' => __('Animated video file not found', 'media-cloud-sync'), | |
| 1336 | + 'animated_video_poster' => __('Animated video poster file not found', 'media-cloud-sync'), | |
| 1337 | + ]; | |
| 1338 | + $existing_additional_files = isset($existing_extras['additional_files']) && is_array($existing_extras['additional_files']) | |
| 1339 | + ? $existing_extras['additional_files'] | |
| 1340 | + : []; | |
| 1341 | + | |
| 1342 | + $additional_files = []; | |
| 1343 | + foreach ($additional_file_keys as $meta_key => $not_found_message) { | |
| 1344 | + if (empty($attachment_meta[$meta_key])) { | |
| 1345 | + continue; | |
| 1346 | + } | |
| 1347 | + $existing_file = $existing_additional_files[$meta_key] ?? []; | |
| 1348 | + $result = $this->uploadNamedFile( | |
| 1349 | + $attachment_meta[$meta_key], $file_dir, | |
| 1350 | + $existing_file['source_path'] ?? '', $existing_file['key'] ?? '', | |
| 1351 | + $do_reupload, $has_existing, $prefix, $attachment_id, $is_private, $not_found_message | |
| 1352 | + ); | |
| 1353 | + if (!empty($result)) { | |
| 1354 | + $additional_files[$meta_key] = $result; | |
| 1355 | + } | |
| 1356 | + } | |
| 1357 | + return $additional_files; | |
| 1285 | 1358 | } |
| 1286 | 1359 | |
| 1287 | 1360 | /** |
| 1288 | 1361 | * Upload intermediate image sizes. |