PluginProbe
Media Cloud Sync / trunk
Media Cloud Sync vtrunk
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 1.3.0 All 34 releases
media-cloud-sync / includes / integrations / woocommerce.php

woocommerce.php in Media Cloud Sync trunk, at includes/integrations/woocommerce.php

215 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Dudlewebs\WPMCS;
3
4 defined('ABSPATH') || exit;
5
6 /**
7 * WooCommerce Compatibility.
8 *
9 * Loaded by the autoloader; activation is gated via `is_installed()` in Integration::init().
10 *
11 * @since 1.3.7
12 */
13 class WooCommerce {
14 /**
15 * The singleton instance.
16 *
17 * @since 1.3.7
18 * @var WooCommerce|null
19 */
20 protected static $instance = null;
21
22 /**
23 * Whether WooCommerce image resize is active for this request.
24 *
25 * Set when `woocommerce_resize_images` runs so `get_attached_file()` returns
26 * a local path instead of a cloud URL without stacking filters.
27 *
28 * @since 1.3.12
29 * @var bool
30 */
31 private static $return_local_path = false;
32
33 /**
34 * Absolute paths restored from cloud for WooCommerce regeneration this request,
35 * re-removed on shutdown so "Remove from server" stays honored even if the
36 * normal sync pipeline bails early (e.g. waiting on subsizes) and never
37 * re-triggers removal itself.
38 *
39 * @since 1.4.0
40 * @var string[]
41 */
42 private $restored_files = array();
43
44 /**
45 * The class constructor.
46 *
47 * @since 1.3.7
48 */
49 protected function __construct() {
50 $this->init();
51 }
52
53 /**
54 * Launch the hooks.
55 *
56 * @since 1.3.7
57 */
58 public function init() {
59 /******** FIX Size updation in WooCommerce Customizer *****/
60 // Return File path for WooCommerce image resizing to prevent url being used and causing issues with image regeneration.
61 add_filter( 'woocommerce_resize_images', [ $this, 'resize_images' ] );
62
63 // Return the local file path (and restore from cloud when missing) during WooCommerce image regeneration.
64 add_filter( 'wpmcs_get_attached_file', array( $this, 'get_attached_file' ), 10, 4 );
65
66 // Force a reupload during regeneration — WooCommerce rewrites the local file in place at
67 // the same dimensions/filename, which the normal "unchanged, skip reupload" check can't
68 // tell apart from a real no-op, leaving stale content on the cloud otherwise.
69 add_filter( 'wpmcs_do_reupload_media', array( $this, 'force_reupload_during_regeneration' ), 10, 1 );
70 /******* End Fix Size updation in WooCommerce Customizer */
71 }
72
73
74 /**
75 * Flag the request so attached files are returned as local paths during WooCommerce resize.
76 *
77 * @param bool $resize Whether to resize images or not.
78 * @return bool The modified value of $resize.
79 * @since 1.3.7
80 */
81 public function resize_images( $resize ) {
82 if ( $resize ) {
83 self::$return_local_path = true;
84 }
85
86 return $resize;
87 }
88
89 /**
90 * Return a local file path during WooCommerce image regeneration.
91 *
92 * @param string $url The cloud URL.
93 * @param string $file The local file path.
94 * @param int $attachment_id The attachment ID.
95 * @param array $item The item data associated with the attachment.
96 * @return string The local file path or original cloud URL.
97 * @since 1.3.7
98 */
99 public function get_attached_file( $url, $file, $attachment_id, $item ) {
100 if ( ! $this->should_return_local_path_for_woocommerce() ) {
101 return $url;
102 }
103
104 if ( ! file_exists( $file ) && ! Utils::is_empty( $item ) ) {
105 Item::instance()->moveToServerByItem( $item, 'full', true );
106
107 // Only track this for later removal on admin-side requests (the System Status
108 // tool, the background regen queue, and the single media-row action all run
109 // over admin-ajax). WooCommerce also restores files here for its realtime,
110 // on-the-fly resize on any storefront page that displays a mismatched-ratio
111 // image — re-deleting the restore there would just trigger another cloud
112 // download next time a different size needs it from the same full image.
113 if ( is_admin() && file_exists( $file ) ) {
114 $this->track_restored_file( $file );
115 }
116 }
117
118 return file_exists( $file ) ? $file : $url;
119 }
120
121 /**
122 * Force the normal sync pipeline to treat this attachment as needing a
123 * reupload while WooCommerce is regenerating it, same as Imagify does
124 * for its own optimize/restore cycle.
125 *
126 * Restricted to admin-side requests (System Status tool, the background
127 * regen queue, and the single "Regenerate thumbnail" media-row action all
128 * run over admin-ajax) — WooCommerce also calls the same regeneration
129 * class from `wp_get_attachment_image_src` to resize a mismatched-ratio
130 * image on the fly on any page that displays it, storefront included, and
131 * forcing a synchronous cloud reupload mid-render for a site visitor
132 * there would be a real performance regression, not a fix.
133 *
134 * @param bool $do_reupload
135 * @return bool
136 * @since 1.4.0
137 */
138 public function force_reupload_during_regeneration( $do_reupload ) {
139 if ( $do_reupload || ! is_admin() ) {
140 return $do_reupload;
141 }
142
143 return $this->should_return_local_path_for_woocommerce();
144 }
145
146 /**
147 * Remember a file restored for WooCommerce so it can be removed again on
148 * shutdown, and arm that cleanup the first time this request restores anything.
149 *
150 * @param string $file Absolute path of the restored file.
151 * @return void
152 * @since 1.4.0
153 */
154 private function track_restored_file( $file ) {
155 if ( in_array( $file, $this->restored_files, true ) ) {
156 return;
157 }
158
159 if ( empty( $this->restored_files ) ) {
160 add_action( 'shutdown', array( $this, 'remove_restored_files' ) );
161 }
162
163 $this->restored_files[] = $file;
164 }
165
166 /**
167 * Re-removes files restored for WooCommerce regeneration, honoring the
168 * "Remove from server" setting the same way the normal sync pipeline would.
169 *
170 * @return void
171 * @since 1.4.0
172 */
173 public function remove_restored_files() {
174 Item::instance()->may_be_delete_server_files_by_source_paths( $this->restored_files );
175 }
176
177 /**
178 * Whether the current request needs a local attached file for WooCommerce image handling.
179 *
180 * @return bool
181 * @since 1.3.12
182 */
183 private function should_return_local_path_for_woocommerce(): bool {
184 if ( self::$return_local_path ) {
185 return true;
186 }
187
188 if ( Utils::is_called_from( 'WC_Regenerate_Images' ) ) {
189 return true;
190 }
191
192 return Utils::is_called_from( 'WC_Regenerate_Images_Request' );
193 }
194
195 /**
196 * Is installed?
197 *
198 * @return bool
199 */
200 public static function is_installed(): bool {
201 return defined( 'WC_ABSPATH' ) || defined( 'WC_VERSION' ) || class_exists( 'WooCommerce', false );
202 }
203
204 /**
205 * Singleton instance
206 */
207 public static function instance() {
208 if (is_null(self::$instance)) {
209 self::$instance = new self();
210 }
211
212 return self::$instance;
213 }
214 }
215