PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 3.2.6
ShopBuilder – WooCommerce Builder For Elementor v3.2.6
3.4.2 3.4.1 3.4.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 All 63 releases
← All changes | app/Modules/VariationGallery/GalleryAdmin.php +14 -186 3.4.23.2.6 View file →
@@ -32,60 +32,10 @@
32 32 add_action( 'woocommerce_product_after_variable_attributes', [ $this, 'gallery_admin_html' ], 10, 3 );
33 33 add_action( 'woocommerce_save_product_variation', [ $this, 'save_variation_gallery' ] );
34 34 add_action( 'add_meta_boxes', [ $this, 'add_metabox' ] );
35 35 add_action( 'save_post', [ $this, 'save_metabox' ] );
36 -
37 - // Late enough that WooCommerce's variation gallery package has registered its
38 - // own field, so the duplicate control can be taken back off.
39 - add_action( 'admin_init', [ $this, 'remove_native_variation_gallery_field' ], 20 );
40 -
41 - add_filter( 'woocommerce_product_export_meta_value', [ $this, 'product_export_meta_value' ], 15, 3 );
42 -
43 - // Invalidate cached variation galleries when product data or images change.
44 - add_action( 'woocommerce_update_product', [ $this, 'flush_product_gallery_cache' ] );
45 - add_action( 'woocommerce_save_product_variation', [ $this, 'flush_variation_parent_cache' ] );
46 - add_action( 'delete_attachment', [ $this, 'flush_attachment_gallery_cache' ] );
47 36 }
48 -
49 37 /**
50 - * Flush all cached gallery transients for a saved product.
51 - *
52 - * @param int $product_id Product ID.
53 - *
54 - * @return void
55 - */
56 - public function flush_product_gallery_cache( $product_id ) {
57 - GalleryFns::flush_product_gallery_transients( $product_id );
58 - }
59 -
60 - /**
61 - * Flush the parent product default-gallery transient when a variation is saved.
62 - *
63 - * The variation's own transient is already cleared in save_variation_gallery();
64 - * this also clears the parent product default-images cache.
65 - *
66 - * @param int $variation_id Variation ID.
67 - *
68 - * @return void
69 - */
70 - public function flush_variation_parent_cache( $variation_id ) {
71 - $parent_id = wp_get_post_parent_id( $variation_id );
72 - if ( $parent_id ) {
73 - GalleryFns::delete_transients( $parent_id, 'default-images' );
74 - }
75 - }
76 -
77 - /**
78 - * Flush cached variation galleries referencing a deleted attachment.
79 - *
80 - * @param int $attachment_id Attachment ID being deleted.
81 - *
82 - * @return void
83 - */
84 - public function flush_attachment_gallery_cache( $attachment_id ) {
85 - GalleryFns::flush_attachment_gallery_transients( $attachment_id );
86 - }
87 - /**
88 38 * Adds a custom meta box to the WooCommerce product edit page.
89 39 */
90 40 public function add_metabox() {
91 41 add_meta_box(
@@ -150,116 +100,21 @@
150 100 // Check permissions again and make sure we have what we need.
151 101 if ( ! current_user_can( 'edit_products' ) || empty( $_POST ) || empty( $_POST['product_id'] ) ) { // phpcs:ignore WordPress.WP.Capabilities.Unknown
152 102 wp_die( -1 );
153 103 }
154 -
155 - $rtsb_vg_ids = [];
156 -
157 - // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified by check_ajax_referer() above.
104 + // Sanitize and save or delete meta.
158 105 if ( isset( $_POST['rtsb_vg'][ $variation_id ] ) && is_array( $_POST['rtsb_vg'][ $variation_id ] ) ) {
159 - // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified by check_ajax_referer() above.
160 - $rtsb_vg_ids = array_map( 'absint', wp_unslash( $_POST['rtsb_vg'][ $variation_id ] ) );
161 - $rtsb_vg_ids = array_values( array_unique( array_filter( $rtsb_vg_ids ) ) );
162 - }
163 -
164 - if ( GalleryFns::use_native_gallery() ) {
165 - $variation = wc_get_product( $variation_id );
166 -
167 - if ( $variation && $variation->is_type( 'variation' ) ) {
168 - $variation->set_gallery_image_ids( $rtsb_vg_ids );
169 - $variation->save();
170 -
171 - // Stamped only once the native gallery has actually been written: the
172 - // sentinel permanently suppresses the legacy fallback, so setting it
173 - // after a failed load would strand that variation's images unreachable.
174 - GalleryFns::mark_native_gallery_owned( $variation_id );
175 - }
176 - } elseif ( $rtsb_vg_ids ) {
177 - update_post_meta( $variation_id, GalleryFns::LEGACY_GALLERY_META_KEY, $rtsb_vg_ids );
106 + $rtsb_vg_ids = array_map( 'absint', $_POST['rtsb_vg'][ $variation_id ] );
107 + $rtsb_vg_ids = array_values( array_unique( $rtsb_vg_ids ) );
108 + update_post_meta( $variation_id, 'rtsb_vg_images', $rtsb_vg_ids );
178 109 } else {
179 - delete_post_meta( $variation_id, GalleryFns::LEGACY_GALLERY_META_KEY );
110 + delete_post_meta( $variation_id, 'rtsb_vg_images' );
180 111 }
181 -
182 112 GalleryFns::delete_transients( $variation_id, 'variation-images' );
183 113 }
184 -
185 114 /**
186 - * Keep the stale legacy gallery meta out of CSV exports.
187 - *
188 - * Once a variation is native-owned the legacy meta is a snapshot, not the truth:
189 - * the migration copies rather than moves it, and later saves only touch the native
190 - * store. Exporting it would put outdated data in the CSV, and re-importing that
191 - * file could write it back over a gallery the merchant has since changed.
192 - *
193 - * WooCommerce exports the native gallery itself through the standard `Images`
194 - * column, so nothing is lost by omitting this key.
195 - *
196 - * @param mixed $meta_value Meta value being exported.
197 - * @param object $meta Meta object.
198 - * @param \WC_Product $product Product or variation being exported.
199 - *
200 - * @return mixed
201 - */
202 - public function product_export_meta_value( $meta_value, $meta, $product ) {
203 - if ( ! GalleryFns::use_native_gallery() ) {
204 - return $meta_value;
205 - }
206 -
207 - if ( ! isset( $meta->key ) || GalleryFns::LEGACY_GALLERY_META_KEY !== $meta->key ) {
208 - return $meta_value;
209 - }
210 -
211 - if ( $product instanceof \WC_Product && GalleryFns::is_native_gallery_owned( $product->get_id() ) ) {
212 - return '';
213 - }
214 -
215 - return $meta_value;
216 - }
217 -
218 - /**
219 - * Hide WooCommerce's own variation gallery field in the product editor.
220 - *
221 - * This module keeps its existing metabox as the single authoring UI and writes
222 - * straight into the native store, so rendering both fields would give merchants two
223 - * controls for one value. WooCommerce's field markup is also what its admin CSS
224 - * keys off (`:has(.wc-variation-gallery-field)`), so removing the render leaves the
225 - * stock variation image slot untouched and the stylesheet inert.
226 - *
227 - * Nothing is suppressed when this module is inactive — that code path never runs,
228 - * so WooCommerce keeps full ownership of its own UI.
229 - *
230 115 * @return void
231 116 */
232 - public function remove_native_variation_gallery_field() {
233 - $class = 'Automattic\WooCommerce\Internal\VariationGallery\ClassicVariationGalleryAdmin';
234 - $hook = 'woocommerce_variation_after_upload_image';
235 -
236 - if ( ! GalleryFns::use_native_gallery() || ! class_exists( $class ) ) {
237 - return;
238 - }
239 -
240 - if ( ! apply_filters( 'rtsb/vg/remove/native/variation/gallery/field', true ) ) {
241 - return;
242 - }
243 -
244 - if ( empty( $GLOBALS['wp_filter'][ $hook ] ) ) {
245 - return;
246 - }
247 -
248 - // Matched on the registered object rather than resolved from WooCommerce's
249 - // container, so removal does not depend on the container handing back the very
250 - // same instance it registered the callback with.
251 - foreach ( $GLOBALS['wp_filter'][ $hook ]->callbacks as $priority => $callbacks ) {
252 - foreach ( $callbacks as $callback ) {
253 - if ( is_array( $callback['function'] ) && isset( $callback['function'][0] ) && $callback['function'][0] instanceof $class ) {
254 - remove_action( $hook, $callback['function'], $priority );
255 - }
256 - }
257 - }
258 - }
259 - /**
260 - * @return void
261 - */
262 117 public function admin_template_js() {
263 118 require_once RTSB_PATH . '/app/Modules/VariationGallery/view/template-admin-thumbnail.php';
264 119 }
265 120
@@ -277,42 +132,11 @@
277 132 * @return void
278 133 */
279 134 public function gallery_admin_html( $loop, $variation_data, $variation ) {
280 135 $variation_id = absint( $variation->ID );
281 - $gallery_images = null;
282 -
283 - // With the native gallery available it is authoritative, so the metabox shows it
284 - // rather than the legacy meta it mirrors — and never reads that meta, which on a
285 - // migrated store may no longer exist. The legacy value is only consulted while
286 - // this variation is still waiting on the migration; once the sentinel is set, an
287 - // empty native gallery is a deliberate choice and is shown as empty.
288 - if ( GalleryFns::use_native_gallery() ) {
289 - $variation_object = wc_get_product( $variation_id );
290 -
291 - if ( $variation_object && $variation_object->is_type( 'variation' ) ) {
292 - $native_images = GalleryFns::get_native_variation_gallery_ids( $variation_object );
293 -
294 - if ( $native_images || GalleryFns::is_native_gallery_owned( $variation_id ) ) {
295 - $gallery_images = $native_images;
296 - }
297 - }
298 - }
299 -
300 - if ( null === $gallery_images ) {
301 - $gallery_images = GalleryFns::get_legacy_variation_gallery_ids( $variation_id );
302 - }
303 -
304 - /*
305 - * WooCommerce renders the variation's main image at thumbnail size (150px) in
306 - * `html-variation-admin.php`, which is soft in the wider slot this module uses.
307 - * Its own variation gallery hero uses `woocommerce_single`, so the matching URL
308 - * is handed to the admin script here — that markup belongs to core and exposes
309 - * no filter to size it directly.
310 - */
311 - $variation_image_id = absint( get_post_thumbnail_id( $variation_id ) );
312 - $hero_src = $variation_image_id ? wp_get_attachment_image_url( $variation_image_id, 'woocommerce_single' ) : '';
136 + $gallery_images = get_post_meta( $variation_id, 'rtsb_vg_images', true );
313 137 ?>
314 - <div class="form-row form-row-full rtsb-vg-gallery-wrapper" data-hero-src="<?php echo esc_url( $hero_src ); ?>">
138 + <div class="form-row form-row-full rtsb-vg-gallery-wrapper">
315 139 <h4><?php esc_html_e( 'Variation Image Gallery', 'shopbuilder' ); ?></h4>
316 140 <div class="rtsb-vg-image-container">
317 141 <ul class="rtsb-vg-images">
318 142 <?php
@@ -335,11 +159,11 @@
335 159 <li class="image<?php echo esc_html( $add_video_class ); ?>">
336 160 <input type="hidden" name="rtsb_vg[<?php echo absint( $variation_id ); ?>][]" value="<?php echo absint( $image_id ); ?>">
337 161 <img src="<?php echo esc_url( $image[0] ); ?>">
338 162 <div class="rtsb-vg-action-button">
339 - <span data-tip="<?php esc_attr_e( 'Add Video', 'shopbuilder' ); ?>" class="rtsb-vg-media-video-popup woocommerce-help-tip dashicons dashicons-video-alt3"></span>
340 - <span data-tip="<?php esc_attr_e( 'Edit Image', 'shopbuilder' ); ?>" class="rtsb-vg-gallery-edit woocommerce-help-tip dashicons dashicons-edit"></span>
341 - <a href="#" class="delete rtsb-vg-remove-image woocommerce-help-tip" data-tip="<?php esc_attr_e( 'Remove', 'shopbuilder' ); ?>"><span class="dashicons dashicons-no"></span></a>
163 + <span data-tip="Add Video" class="rtsb-vg-media-video-popup dashicons dashicons-video-alt3"></span>
164 + <span data-tip="Edit Image" class="rtsb-vg-gallery-edit dashicons dashicons-edit"></span>
165 + <a href="#" class="delete rtsb-vg-remove-image"><span class="dashicons dashicons-no"></span></a>
342 166 </div>
343 167 </li>
344 168 <?php
345 169 endforeach;
@@ -352,8 +176,12 @@
352 176 data-product_variation_id="<?php echo esc_attr( $variation_id ); ?>"
353 177 class="button rtsb-vg-add-image">
354 178 <?php
355 179 esc_html_e( 'Add Gallery Images', 'shopbuilder' );
180 + if ( rtsb()->has_pro() ) {
181 + echo ' & ';
182 + esc_html_e( 'Videos', 'shopbuilder' );
183 + }
356 184 ?>
357 185 </a>
358 186 </p>
359 187 </div>