PluginProbe
Media Cloud Sync / 1.4.2
Media Cloud Sync v1.4.2
1.4.2 1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 All 36 releases
← All changes | includes/integrations/media-library.php +188 -59 1.4.0 → 1.4.2 View file →
@@ -31,10 +31,13 @@
31 31 private $deleting_attachment = false;
32 32
33 33
34 34 public static $source_type_prefix = "media";
35 - public static $label = 'Media Library';
36 35
36 + public static function get_label() {
37 + return __('Media Library', 'media-cloud-sync');
38 + }
39 +
37 40 // Map which meta to be updated
38 41 public static $source_types = [
39 42 "media_library" => [
40 43 'table' => 'posts',
@@ -113,8 +116,10 @@
113 116 add_filter( 'wp_update_attachment_metadata', [ $this, 'update_attachment_metadata' ], 110, 2 );
114 117 add_filter( 'pre_delete_attachment', [ $this, 'pre_delete_attachment' ], 20 );
115 118 add_filter( 'delete_attachment', [ $this, 'delete_attachment' ], 20 );
116 119 add_action( 'delete_post', [$this, 'delete_post'] );
120 + // Safety net for code that deletes an attachment bypassing wp_delete_attachment().
121 + add_action( 'deleted_post', [ $this, 'deleted_post' ], 10, 2 );
117 122 add_filter( 'update_attached_file', [ $this, 'update_attached_file' ], 100, 2 );
118 123
119 124 add_action( 'wpmcs_do_update_attachment_metadata', [ $this, 'update_attachment_metadata' ], 10, 2 );
120 125 }
@@ -556,9 +561,9 @@
556 561 if ( $this->deleting_attachment ) {
557 562 return $file;
558 563 }
559 564
560 - if (!Utils::is_ok_to_serve($attachment_id)) {
565 + if (!Utils::should_serve_from_cloud($attachment_id)) {
561 566 return $file;
562 567 }
563 568
564 569 $wpmcsItem = Item::instance();
@@ -611,9 +616,9 @@
611 616 return $sources;
612 617 }
613 618
614 619 // Must need $attachment_id other wise not possible to get data from the table
615 - if (!Utils::is_ok_to_serve($attachment_id)) {
620 + if (!Utils::should_serve_from_cloud($attachment_id)) {
616 621 return $sources;
617 622 }
618 623
619 624 $wpmcsItem = Item::instance();
@@ -680,10 +685,10 @@
680 685 * @return array
681 686 */
682 687 public function wp_get_attachment_image_attributes($attr, $attachment, $size='thumbnail') {
683 688 if (
684 - !$attachment ||
685 - !Utils::is_ok_to_serve($attachment->ID)
689 + !$attachment ||
690 + !Utils::should_serve_from_cloud($attachment->ID)
686 691 ) {
687 692 return $attr;
688 693 }
689 694
@@ -730,9 +735,9 @@
730 735 *
731 736 * @return bool|mixed|WP_Error
732 737 */
733 738 public function wp_get_attachment_url($url, $attachment_id) {
734 - if (!Utils::is_ok_to_serve($attachment_id)) {
739 + if (!Utils::should_serve_from_cloud($attachment_id)) {
735 740 return $url;
736 741 }
737 742
738 743 $new_url = Item::instance()->get_url($attachment_id, 'full', 'media_library');
@@ -762,9 +767,9 @@
762 767 if ( ! is_string( $html ) ) {
763 768 return $html;
764 769 }
765 770
766 - if (!Utils::is_ok_to_serve($id)) {
771 + if (!Utils::should_serve_from_cloud($id)) {
767 772 return $html;
768 773 }
769 774
770 775 preg_match( '@\ssrc=[\'\"]([^\'\"]*)[\'\"]@', $html, $matches );
@@ -804,9 +809,9 @@
804 809 *
805 810 * @return array
806 811 */
807 812 public function wp_get_attachment_image_src( $image, $attachment_id, $size, $icon ) {
808 - if (!Utils::is_ok_to_serve($attachment_id)) {
813 + if (!Utils::should_serve_from_cloud($attachment_id)) {
809 814 return $image;
810 815 }
811 816
812 817 if ( isset( $image[0] ) ) {
@@ -832,9 +837,9 @@
832 837 *
833 838 * @return array
834 839 */
835 840 public function wp_prepare_attachment_for_js( $response, $attachment, $meta ) {
836 - if (!Utils::is_ok_to_serve($attachment->ID)) {
841 + if (!Utils::should_serve_from_cloud($attachment->ID)) {
837 842 return $response;
838 843 }
839 844
840 845 if ( isset( $response['sizes'] ) && is_array( $response['sizes'] ) ) {
@@ -860,9 +865,9 @@
860 865 *
861 866 * @return array
862 867 */
863 868 public function image_get_intermediate_size( $data, $post_id, $size ) {
864 - if (!Utils::is_ok_to_serve($post_id)) {
869 + if (!Utils::should_serve_from_cloud($post_id)) {
865 870 return $data;
866 871 }
867 872 if ( isset( $data['url'] ) ) {
868 873 $size = Utils::maybe_convert_size_to_string( $post_id, $size );
@@ -1012,8 +1017,11 @@
1012 1017 $is_image = wp_attachment_is_image($attachment_id);
1013 1018 $existing = $wpmcsItem->get($attachment_id, 'media_library');
1014 1019 $existing_extras = $wpmcsItem->get_extras($attachment_id, false, 'media_library');
1015 1020 $has_existing = !Utils::is_empty($existing);
1021 + // A reupload of an already-private item must keep writing under the private path —
1022 + // never true for a genuinely new item, which is exactly right (new uploads stay public).
1023 + $is_private = $has_existing && !empty($existing['is_private']);
1016 1024 $sizes = [];
1017 1025 $uploaded = [];
1018 1026 $extras = [];
1019 1027 $prefix = '';
@@ -1024,10 +1032,11 @@
1024 1032 $do_reupload = apply_filters('wpmcs_do_reupload_media', false, $attachment_id, 'media_library');
1025 1033
1026 1034 // Force reupload when sizes/dimensions changed
1027 1035 if (!$do_reupload && $has_existing) {
1028 - if($this->shouldForceReupload($attachment_meta, $attachment_id, $existing_extras)) {
1029 - $do_reupload = true;
1036 + $force_reupload = $this->shouldForceReupload($attachment_meta, $attachment_id, $existing_extras);
1037 + if ($force_reupload !== false) {
1038 + $do_reupload = $force_reupload;
1030 1039 }
1031 1040 }
1032 1041
1033 1042 // Add prefix if object versioning is ON
@@ -1049,26 +1058,48 @@
1049 1058 return false;
1050 1059 }
1051 1060
1052 1061 // Upload main file first, if that fails no need to attempt the rest
1053 - $uploaded = $this->uploadFullFile($file_path, $source_path, $do_reupload, $has_existing, $existing, $prefix, $attachment_id);
1062 + $uploaded = $this->uploadFullFile($file_path, $source_path, $do_reupload, $has_existing, $existing, $prefix, $attachment_id, $is_private);
1054 1063
1055 1064 if ($uploaded && isset($uploaded['success']) && $uploaded['success']) {
1056 1065 // Attempt to upload original file if present. Not critical if this fails so we don't check the result before proceeding.
1057 - $original = $this->uploadOriginalFile($original_file, $file_dir, $do_reupload, $has_existing, $existing, $prefix, $attachment_id);
1066 + $original = $this->uploadOriginalFile($original_file, $file_dir, $do_reupload, $has_existing, $existing, $prefix, $attachment_id, $is_private);
1067 + $additional_files = [];
1058 1068
1059 1069 if ($is_image && isset($file_dir) && !empty($file_dir)) {
1060 1070 $sizes_to_upload = $this->get_attachment_image_sizes_for_upload($attachment_meta, $attachment_id);
1061 1071 if (!empty($sizes_to_upload)) {
1062 1072 // Upload image sizes. Again, not critical if this fails so we don't check the result before proceeding.
1063 - $sizes = $this->uploadImageSizes($sizes_to_upload, $file_dir, $do_reupload, $existing_extras, $prefix, $attachment_id);
1073 + $sizes = $this->uploadImageSizes($sizes_to_upload, $file_dir, $do_reupload, $existing_extras, $prefix, $attachment_id, $is_private);
1064 1074 }
1075 + $additional_files = $this->uploadAdditionalFiles($attachment_meta, $file_dir, $do_reupload, $has_existing, $existing_extras, $prefix, $attachment_id, $is_private);
1065 1076 }
1066 1077
1067 1078 if (!empty($sizes)) {
1068 - $extras['sizes'] = $sizes;
1079 + // Merge over existing sizes rather than replacing wholesale — a size that
1080 + // came back empty from uploadImageSizes() (its own fallback included) must
1081 + // never erase a previously-good, unrelated size's record.
1082 + $existing_sizes = isset($existing_extras['sizes']) && is_array($existing_extras['sizes'])
1083 + ? $existing_extras['sizes']
1084 + : [];
1085 +
1086 + foreach ($sizes as $size_name => $size_data) {
1087 + if (Utils::is_empty($size_data) && isset($existing_sizes[$size_name])) {
1088 + unset($sizes[$size_name]);
1089 + }
1090 + }
1091 +
1092 + $extras['sizes'] = array_merge($existing_sizes, $sizes);
1069 1093 }
1070 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 +
1071 1102 return [
1072 1103 'file' => [
1073 1104 'source_path' => $source_path,
1074 1105 'url' => $uploaded['file_url'],
@@ -1122,8 +1153,10 @@
1122 1153 * @since 1.3.6
1123 1154 * @param array $attachment_meta
1124 1155 * @param int $attachment_id
1125 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.
1126 1159 */
1127 1160 private function shouldForceReupload($attachment_meta, $attachment_id, $existing_extras) {
1128 1161 $existing_extras = $existing_extras ?? Item::instance()->get_extras($attachment_id, false, 'media_library');
1129 1162
@@ -1150,31 +1183,26 @@
1150 1183 'height' => isset($smeta['height']) ? (int)$smeta['height'] : 0,
1151 1184 ];
1152 1185 }
1153 1186
1154 - $existing_relevant = [];
1155 - foreach (array_keys($current_sizes) as $sname) {
1156 - if (isset($existing_sizes[$sname])) {
1157 - $existing_relevant[$sname] = $existing_sizes[$sname];
1158 - }
1159 - }
1160 -
1161 - if (array_keys($existing_relevant) !== array_keys($current_sizes)) {
1162 - return true;
1163 - }
1164 -
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 = [];
1165 1192 foreach ($current_sizes as $sname => $dims) {
1166 1193 if (!isset($existing_sizes[$sname])) {
1167 - return true;
1194 + $changed_sizes[] = $sname;
1195 + continue;
1168 1196 }
1169 1197 $ex_w = isset($existing_sizes[$sname]['width']) ? (int)$existing_sizes[$sname]['width'] : 0;
1170 1198 $ex_h = isset($existing_sizes[$sname]['height']) ? (int)$existing_sizes[$sname]['height'] : 0;
1171 1199 if ($ex_w !== $dims['width'] || $ex_h !== $dims['height']) {
1172 - return true;
1200 + $changed_sizes[] = $sname;
1173 1201 }
1174 1202 }
1175 1203
1176 - return false;
1204 + return empty($changed_sizes) ? false : $changed_sizes;
1177 1205 }
1178 1206
1179 1207 /**
1180 1208 * Upload the main/full file.
@@ -1180,16 +1208,19 @@
1180 1208 * Upload the main/full file.
1181 1209 * @since 1.3.6
1182 1210 * @param string $file_path
1183 1211 * @param string $source_path
1184 - * @param bool $do_reupload
1212 + * @param bool|array $do_reupload Reupload everything (true), nothing (false), or only these sizes (array of size names).
1185 1213 * @param bool $has_existing
1186 1214 * @param array $existing
1187 1215 * @param string $prefix
1188 1216 * @param int $attachment_id
1217 + * @param bool $is_private Keeps a reupload of an already-private item under the private path.
1189 1218 */
1190 - private function uploadFullFile($file_path, $source_path, $do_reupload, $has_existing, $existing, $prefix, $attachment_id) {
1191 - if (!$do_reupload && $has_existing && ($existing['source_path'] == $source_path)) {
1219 + private function uploadFullFile($file_path, $source_path, $do_reupload, $has_existing, $existing, $prefix, $attachment_id, $is_private = false) {
1220 + // $do_reupload may be an array of size names (force just those sizes) — that
1221 + // shouldn't force the full file too, only a literal true does.
1222 + if ($do_reupload !== true && $has_existing && ($existing['source_path'] == $source_path)) {
1192 1223 return [
1193 1224 'success' => true,
1194 1225 'file_url' => $existing['url'],
1195 1226 'key' => $existing['key']
@@ -1196,9 +1227,9 @@
1196 1227 ];
1197 1228 }
1198 1229
1199 1230 if (file_exists($file_path)) {
1200 - return Service::instance()->uploadSingle($file_path, $source_path, $prefix);
1231 + return Service::instance()->uploadSingle($file_path, $source_path, $prefix, $is_private);
1201 1232 }
1202 1233
1203 1234 Logger::instance()->add_log('sync_to_cloud', $attachment_id, 'media_library', [
1204 1235 'message' => __('File not found', 'media-cloud-sync'),
@@ -1213,63 +1244,133 @@
1213 1244 * Upload original file when present.
1214 1245 * @since 1.3.6
1215 1246 * @param string $original_file
1216 1247 * @param string $file_dir
1217 - * @param bool $do_reupload
1248 + * @param bool|array $do_reupload Reupload everything (true), nothing (false), or only these sizes (array of size names).
1218 1249 * @param bool $has_existing
1219 1250 * @param array $existing
1220 1251 * @param string $prefix
1221 1252 * @param int $attachment_id
1253 + * @param bool $is_private Keeps a reupload of an already-private item under the private path.
1222 1254 */
1223 - private function uploadOriginalFile($original_file, $file_dir, $do_reupload, $has_existing, $existing, $prefix, $attachment_id) {
1224 - $original = [];
1225 - if (empty($original_file)) {
1226 - return $original;
1255 + private function uploadOriginalFile($original_file, $file_dir, $do_reupload, $has_existing, $existing, $prefix, $attachment_id, $is_private = false) {
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 [];
1227 1283 }
1228 1284
1229 - $original_file_path = trailingslashit($file_dir) . $original_file;
1230 - $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);
1231 1287
1232 - if (!$do_reupload && $has_existing && isset($existing['original_source_path']) && !Utils::is_empty($existing['original_source_path']) && $existing['original_source_path'] === $original_file_source_path) {
1233 - return [ 'source_path' => $original_file_source_path, 'key' => $existing['original_key'] ];
1288 + // $do_reupload may be an array of size names (force just those sizes) — that
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 ];
1234 1292 }
1235 1293
1236 - if (file_exists($original_file_path)) {
1237 - $uploaded_original = Service::instance()->uploadSingle($original_file_path, $original_file_source_path, $prefix);
1238 - if (isset($uploaded_original['success']) && $uploaded_original['success']) {
1239 - 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'] ];
1240 1298 }
1241 1299
1242 - if (isset($uploaded_original['success']) && !$uploaded_original['success']) {
1300 + if (isset($uploaded['success']) && !$uploaded['success']) {
1243 1301 Logger::instance()->add_log('sync_to_cloud', $attachment_id, 'media_library', [
1244 - 'message' => $uploaded_original['message'] ?? __('Original File upload failed', 'media-cloud-sync'),
1245 - 'file' => $original_file_path,
1246 - 'code' => $uploaded_original['code'] ?? 500
1302 + 'message' => $uploaded['message'] ?? $not_found_message,
1303 + 'file' => $file_path,
1304 + 'code' => $uploaded['code'] ?? 500
1247 1305 ]);
1248 1306 }
1249 1307 } else {
1250 1308 Logger::instance()->add_log('sync_to_cloud', $attachment_id, 'media_library', [
1251 - 'message' => __('Original File not found', 'media-cloud-sync'),
1252 - 'file' => $original_file_path,
1309 + 'message' => $not_found_message,
1310 + 'file' => $file_path,
1253 1311 'code' => 404
1254 1312 ]);
1255 1313 }
1256 1314
1257 - return $original;
1315 + return [];
1258 1316 }
1259 1317
1260 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;
1358 + }
1359 +
1360 + /**
1261 1361 * Upload intermediate image sizes.
1262 1362 * @since 1.3.6
1263 1363 * @param array $attachment_sizes
1264 1364 * @param string $file_dir
1265 - * @param bool $do_reupload
1365 + * @param bool|array $do_reupload Reupload everything (true), nothing (false), or only these sizes (array of size names).
1266 1366 * @param array $existing_extras
1267 1367 * @param string $prefix
1268 1368 * @param int $attachment_id
1269 - * @return array
1369 + * @param bool $is_private Keeps a reupload of an already-private item under the private path.
1370 + * @return array
1270 1371 */
1271 - private function uploadImageSizes($attachment_sizes, $file_dir, $do_reupload, $existing_extras, $prefix, $attachment_id) {
1372 + private function uploadImageSizes($attachment_sizes, $file_dir, $do_reupload, $existing_extras, $prefix, $attachment_id, $is_private = false) {
1272 1373 $sizes = [];
1273 1374
1274 1375 foreach ($attachment_sizes as $size => $sub_image) {
1275 1376 $sub_size = [];
@@ -1283,10 +1384,14 @@
1283 1384 }
1284 1385
1285 1386 $uploaded_sub_image = [];
1286 1387
1388 + // $do_reupload may be an array naming specific sizes to force (e.g. a
1389 + // WooCommerce on-the-fly regen of one size only) rather than a plain bool.
1390 + $force_this_size = ($do_reupload === true) || (is_array($do_reupload) && in_array($size, $do_reupload, true));
1391 +
1287 1392 if (
1288 - !$do_reupload &&
1393 + !$force_this_size &&
1289 1394 !Utils::is_empty($existing_extras) &&
1290 1395 isset($existing_extras['sizes']) && !Utils::is_empty($existing_extras['sizes']) &&
1291 1396 isset($existing_extras['sizes'][$size]) && !Utils::is_empty($existing_extras['sizes'][$size]) &&
1292 1397 $existing_extras['sizes'][$size]['source_path'] == $sub_file_source_path
@@ -1296,9 +1401,9 @@
1296 1401 'file_url' => $existing_extras['sizes'][$size]['url'],
1297 1402 'key' => $existing_extras['sizes'][$size]['key']
1298 1403 ];
1299 1404 } else if (file_exists($sub_file_path)) {
1300 - $uploaded_sub_image = Service::instance()->uploadSingle($sub_file_path, $sub_file_source_path, $prefix);
1405 + $uploaded_sub_image = Service::instance()->uploadSingle($sub_file_path, $sub_file_source_path, $prefix, $is_private);
1301 1406 } else {
1302 1407 Logger::instance()->add_log('sync_to_cloud', $attachment_id, 'media_library', [
1303 1408 /* translators: %1$s: Image size name (e.g., thumbnail, medium, large). */
1304 1409 'message' => sprintf(__('Image size %1$s not found', 'media-cloud-sync'), $size),
@@ -1321,8 +1426,14 @@
1321 1426 'file' => $sub_file_path,
1322 1427 'code' => 500
1323 1428 ]);
1324 1429 }
1430 +
1431 + // A failed (re)upload attempt shouldn't erase a previously-good record —
1432 + // fall back to what's already stored rather than overwriting it with empty data.
1433 + if (isset($existing_extras['sizes'][$size]) && !Utils::is_empty($existing_extras['sizes'][$size])) {
1434 + $sub_size = $existing_extras['sizes'][$size];
1435 + }
1325 1436 }
1326 1437
1327 1438 $sizes[$size] = $sub_size;
1328 1439 }
@@ -1616,8 +1727,26 @@
1616 1727 * Note: delete_post is used as there is a potential that deleted_post is not reached.
1617 1728 */
1618 1729 public function delete_post() {
1619 1730 $this->deleting_attachment = false;
1731 + }
1732 +
1733 + /**
1734 + * Safety net for deletion that bypasses wp_delete_attachment().
1735 + *
1736 + * @handles deleted_post
1737 + */
1738 + public function deleted_post( $post_id, $post ) {
1739 + if ( ! $post || 'attachment' !== $post->post_type ) {
1740 + return;
1741 + }
1742 +
1743 + $item = Item::instance()->get( $post_id, 'media_library' );
1744 + if ( Utils::is_empty( $item ) ) {
1745 + return;
1746 + }
1747 +
1748 + Item::instance()->delete( $post_id, 'media_library' );
1620 1749 }
1621 1750
1622 1751 /**
1623 1752 * Has WP Core fixed wp_check_filetype when URL has params yet?