PluginProbe
Media Cloud Sync / 1.4.1
Media Cloud Sync v1.4.1
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 1.2.9 All 35 releases
← All changes | includes/integrations/woocommerce.php +110 -37 1.3.121.4.1 View file →
@@ -5,12 +5,14 @@
5 5
6 6 /**
7 7 * WooCommerce Compatibility.
8 8 *
9 - * Loaded by the autoloader; activation is gated via `is_installed()` in Integration::init().
10 - *
11 9 * @since 1.3.7
12 10 */
11 +if ( ! class_exists( 'WooCommerce' ) ) {
12 + return;
13 +}
14 +
13 15 class WooCommerce {
14 16 /**
15 17 * The singleton instance.
16 18 *
@@ -19,17 +21,23 @@
19 21 */
20 22 protected static $instance = null;
21 23
22 24 /**
23 - * Whether WooCommerce image resize is active for this request.
25 + * The image size WooCommerce is currently regenerating, captured via
26 + * `intermediate_image_sizes` so the reupload can be scoped to just that size.
24 27 *
25 - * Set when `woocommerce_resize_images` runs so `get_attached_file()` returns
26 - * a local path instead of a cloud URL without stacking filters.
28 + * @since 1.4.0
29 + * @var string|null
30 + */
31 + protected $regenerating_size = null;
32 +
33 + /**
34 + * Whether the `intermediate_image_sizes` capture hook has been armed.
27 35 *
28 - * @since 1.3.12
36 + * @since 1.4.0
29 37 * @var bool
30 38 */
31 - private static $return_local_path = false;
39 + protected $size_capture_hooked = false;
32 40
33 41 /**
34 42 * The class constructor.
35 43 *
@@ -48,72 +56,127 @@
48 56 /******** FIX Size updation in WooCommerce Customizer *****/
49 57 // Return File path for WooCommerce image resizing to prevent url being used and causing issues with image regeneration.
50 58 add_filter( 'woocommerce_resize_images', [ $this, 'resize_images' ] );
51 59
52 - // Return the local file path (and restore from cloud when missing) during WooCommerce image regeneration.
60 + // Restore the file from cloud (if missing) and return the local path during
61 + // WooCommerce's on-the-fly image regeneration.
53 62 add_filter( 'wpmcs_get_attached_file', array( $this, 'get_attached_file' ), 10, 4 );
54 - // Note: There has still been an issue removing the images from local need a look in
55 - // future to see if we can prevent that or handle it better, but this should at least prevent the issue of images
56 - // not being regenerated due to missing local files when using cloud storage.
63 +
64 + // Force a reupload of just the size WooCommerce is regenerating — same name/
65 + // dimensions as an existing size, but different crop, so the normal
66 + // "unchanged, skip reupload" check can't tell it apart from a real no-op.
67 + add_filter( 'wpmcs_do_reupload_media', array( $this, 'force_reupload_during_regeneration' ), 10, 3 );
57 68 /******* End Fix Size updation in WooCommerce Customizer */
58 -
59 -
60 69 }
61 70
62 71
63 72 /**
64 - * Flag the request so attached files are returned as local paths during WooCommerce resize.
73 + * Resize images for WooCommerce.
74 + * Used to add a filter to return the file path instead of the URL for WooCommerce image resizing,
75 + * to prevent issues with image regeneration when using cloud storage.
65 76 *
77 + * WooCommerce fires 'woocommerce_resize_images' unconditionally from
78 + * maybe_resize_image(), which itself runs on every wp_get_attachment_image_src()
79 + * call for any size — not just when an actual WooCommerce resize is about to
80 + * happen. resize_and_return_image() (the method that genuinely needs the local
81 + * path) hasn't been called yet at this point, so is_called_from() would always
82 + * be false if checked here. The added filter must instead check at the time it's
83 + * actually invoked — otherwise it permanently returns the local path for every
84 + * wpmcs_get_attached_file call for the rest of the request, once any image has
85 + * rendered anywhere (confirmed live: this broke the unrelated BuddyBoss
86 + * regenerate-thumbnails restore window entirely).
87 + *
66 88 * @param bool $resize Whether to resize images or not.
67 89 * @return bool The modified value of $resize.
68 90 * @since 1.3.7
69 91 */
70 92 public function resize_images( $resize ) {
71 - if ( $resize ) {
72 - self::$return_local_path = true;
73 - }
93 + add_filter( 'wpmcs_get_attached_file', function ($url, $file, $attachment_id, $item) {
94 + if ( ! Utils::is_called_from( 'WC_Regenerate_Images', 'resize_and_return_image' ) ) {
95 + return $url;
96 + }
97 + return $file;
98 + }, 10, 4 );
74 99
75 100 return $resize;
76 101 }
77 102
78 103 /**
79 - * Return a local file path during WooCommerce image regeneration.
104 + * Restore the file from cloud (all registered sizes, not just this one — the
105 + * source may be needed at other sizes too) and return the local path during
106 + * WooCommerce's on-the-fly image regeneration.
80 107 *
81 - * @param string $url The cloud URL.
82 - * @param string $file The local file path.
83 - * @param int $attachment_id The attachment ID.
84 - * @param array $item The item data associated with the attachment.
85 - * @return string The local file path or original cloud URL.
108 + * @param string $url The original file URL.
109 + * @param string $file The file path.
110 + * @param int $attachment_id The attachment ID.
111 + * @param array $item The item data associated with the attachment.
112 + * @return string The modified file URL.
86 113 * @since 1.3.7
87 114 */
88 115 public function get_attached_file( $url, $file, $attachment_id, $item ) {
89 - if ( ! $this->should_return_local_path_for_woocommerce() ) {
116 + if ( ! Utils::is_called_from( 'WC_Regenerate_Images', 'resize_and_return_image' ) ) {
90 117 return $url;
91 118 }
92 119
93 - if ( ! file_exists( $file ) && ! Utils::is_empty( $item ) ) {
94 - Item::instance()->moveToServerByItem( $item, 'full', true );
120 + // Always attempted, not gated on $file specifically being missing —
121 + // move_to_server_by_key_and_path() already no-ops per-file on file_exists(),
122 + // and gating here would leave OTHER missing sizes unrestored, which then get
123 + // silently dropped (not just skipped) if a reupload is later forced without
124 + // a local file present.
125 + $results = Item::instance()->moveToServerByItem( $item, 'full', true );
126 +
127 + if ( is_array( $results ) && ! empty( $results ) ) {
128 + Item::instance()->track_restored_for_cleanup( array_values( $results ) );
95 129 }
96 130
97 - return file_exists( $file ) ? $file : $url;
131 + $this->capture_regenerating_size();
132 +
133 + return $file;
98 134 }
99 135
100 136 /**
101 - * Whether the current request needs a local attached file for WooCommerce image handling.
137 + * Arms a one-time `intermediate_image_sizes` capture so the exact size
138 + * WooCommerce is regenerating is known when `wpmcs_do_reupload_media` fires.
139 + * Priority 20 — after WooCommerce's own `adjust_intermediate_image_sizes`
140 + * (default priority 10) has already narrowed the array to that one size.
102 141 *
103 - * @return bool
104 - * @since 1.3.12
142 + * @return void
143 + * @since 1.4.0
105 144 */
106 - private function should_return_local_path_for_woocommerce(): bool {
107 - if ( self::$return_local_path ) {
108 - return true;
145 + protected function capture_regenerating_size() {
146 + if ( $this->size_capture_hooked ) {
147 + return;
109 148 }
149 + $this->size_capture_hooked = true;
110 150
111 - if ( Utils::is_called_from( 'WC_Regenerate_Images' ) ) {
112 - return true;
151 + add_filter( 'intermediate_image_sizes', function ( $sizes ) {
152 + if ( is_array( $sizes ) && 1 === count( $sizes ) ) {
153 + $this->regenerating_size = reset( $sizes );
154 + }
155 + return $sizes;
156 + }, 20 );
157 + }
158 +
159 + /**
160 + * Force a reupload of just the size WooCommerce is regenerating — an existing
161 + * registered size with a different crop, which the normal same-name/dimensions
162 + * check can't otherwise tell apart from an unchanged file.
163 + *
164 + * @param bool|array $do_reupload
165 + * @param int $attachment_id
166 + * @param string $source_type
167 + * @return bool|array
168 + * @since 1.4.0
169 + */
170 + public function force_reupload_during_regeneration( $do_reupload, $attachment_id, $source_type ) {
171 + if ( true === $do_reupload || empty( $this->regenerating_size ) ) {
172 + return $do_reupload;
113 173 }
114 174
115 - return Utils::is_called_from( 'WC_Regenerate_Images_Request' );
175 + $size = $this->regenerating_size;
176 + $this->regenerating_size = null;
177 +
178 + return array( $size );
116 179 }
117 180
118 181 /**
119 182 * Is installed?
@@ -120,9 +183,19 @@
120 183 *
121 184 * @return bool
122 185 */
123 186 public static function is_installed(): bool {
124 - return defined( 'WC_ABSPATH' ) || defined( 'WC_VERSION' ) || class_exists( 'WooCommerce', false );
187 + // Check if WooCommerce plugin defines its main constant.
188 + if ( defined( 'WC_ABSPATH' ) ) {
189 + return true;
190 + }
191 +
192 + // Alternative: check for WooCommerce version constant.
193 + if ( defined( 'WC_VERSION' ) ) {
194 + return true;
195 + }
196 +
197 + return false;
125 198 }
126 199
127 200 /**
128 201 * Singleton instance