PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 1.8.2
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v1.8.2
2.3.2 2.3.1 2.3.0 2.2.8 2.2.7 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.11.0 1.11.1 1.11.2 1.6 1.7 1.8 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 1.9.10 1.9.11 All 60 releases
merchant / inc / modules / quick-view / class-quick-view.php

class-quick-view.php in Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant 1.8.2, at inc/modules/quick-view/class-quick-view.php

591 lines 20.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Quick View.
5 *
6 * @package Merchant
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit; // Exit if accessed directly
11 }
12
13 /**
14 * Quick View Class.
15 *
16 */
17 class Merchant_Quick_View extends Merchant_Add_Module {
18
19 /**
20 * Module ID.
21 *
22 */
23 const MODULE_ID = 'quick-view';
24
25 /**
26 * Is module preview.
27 *
28 */
29 public static $is_module_preview = false;
30
31 /**
32 * Constructor.
33 *
34 */
35 public function __construct() {
36
37 // Module id.
38 $this->module_id = self::MODULE_ID;
39
40 // WooCommerce only.
41 $this->wc_only = true;
42
43 // Parent construct.
44 parent::__construct();
45
46 // Module section.
47 $this->module_section = 'convert-more';
48
49 // Module default settings.
50 $this->module_default_settings = array(
51 'button_type' => 'text',
52 'button_text' => __( 'Quick View', 'merchant' ),
53 'button_icon' => 'eye',
54 'button_position' => 'overlay',
55 'button-position-top' => 50,
56 'button-position-left' => 50,
57 'zoom_effect' => 1,
58 'show_quantity' => 1,
59 'place_product_description' => 'top',
60 'description_style' => 'short',
61 'place_product_image' => 'thumbs-at-left',
62 );
63
64 // Mount preview url.
65 $preview_url = site_url( '/' );
66
67 if ( function_exists( 'wc_get_page_id' ) ) {
68 $preview_url = get_permalink( wc_get_page_id( 'shop' ) );
69 }
70
71 // Module data.
72 $this->module_data = Merchant_Admin_Modules::$modules_data[ self::MODULE_ID ];
73 $this->module_data[ 'preview_url' ] = $preview_url;
74
75 // Module options path.
76 $this->module_options_path = MERCHANT_DIR . 'inc/modules/' . self::MODULE_ID . '/admin/options.php';
77
78 // Is module preview page.
79 if ( is_admin() && parent::is_module_settings_page() ) {
80 self::$is_module_preview = true;
81
82 // Enqueue admin styles.
83 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_css' ) );
84
85 // Admin preview box.
86 add_filter( 'merchant_module_preview', array( $this, 'render_admin_preview' ), 10, 2 );
87
88 // Custom CSS.
89 // The custom CSS should be added here as well due to ensure preview box works properly.
90 add_filter( 'merchant_custom_css', array( $this, 'admin_custom_css' ) );
91
92 }
93
94 if ( Merchant_Modules::is_module_active( self::MODULE_ID ) && is_admin() ) {
95 // Init translations.
96 $this->init_translations();
97 }
98
99 if ( ! Merchant_Modules::is_module_active( self::MODULE_ID ) ) {
100 return;
101 }
102
103 // Return early if it's on admin but not in the respective module settings page.
104 if ( is_admin() && ! parent::is_module_settings_page() && ! defined( 'DOING_AJAX' ) ) {
105 return;
106 }
107
108 // Enqueue styles.
109 add_action( 'merchant_enqueue_before_main_css_js', array( $this, 'enqueue_css' ) );
110
111 // Enqueue scripts.
112 add_action( 'merchant_enqueue_after_main_css_js', array( $this, 'enqueue_scripts' ) );
113
114 // Localize script.
115 add_filter( 'merchant_localize_script', array( $this, 'localize_script' ) );
116
117 // Handle Botiga theme scripts for compatibility.
118 if ( defined( 'BOTIGA_PRO_URI' ) && defined( 'BOTIGA_PRO_VERSION' ) ) {
119 add_action( 'wp_enqueue_scripts', array( $this, 'modal_compatibility_with_botiga_theme' ) );
120 }
121
122 // Modal content ajax callback.
123 add_action( 'wp_ajax_merchant_quick_view_content', array( $this, 'modal_content_ajax_callback' ) );
124 add_action( 'wp_ajax_nopriv_merchant_quick_view_content', array( $this, 'modal_content_ajax_callback' ) );
125
126 // Button Position.
127 $button_position = Merchant_Admin_Options::get( self::MODULE_ID, 'button_position', 'overlay' );
128
129 if ( 'before' === $button_position ) {
130 add_action( 'woocommerce_after_shop_loop_item', array( $this, 'quick_view_button' ), 5 );
131 } elseif ( 'after' === $button_position ) {
132 add_action( 'woocommerce_after_shop_loop_item', array( $this, 'quick_view_button' ), 15 );
133 } elseif ( 'overlay' === $button_position ) {
134 if ( merchant_is_kadence_active() ) {
135 add_filter( 'kadence_archive_content_wrap_start', array( $this, 'add_quick_view_button' ) );
136 } else {
137 add_action( 'woocommerce_after_shop_loop_item', array( $this, 'quick_view_button' ), 15 );
138 }
139 }
140
141 // Inject quick view modal output on footer.
142 add_action( 'wp_footer', array( $this, 'modal_output' ) );
143
144 // Custom CSS.
145 add_filter( 'merchant_custom_css', array( $this, 'frontend_custom_css' ) );
146 }
147
148 /**
149 * Init translations.
150 *
151 * @return void
152 */
153 public function init_translations() {
154 $settings = $this->get_module_settings();
155 if ( ! empty( $settings['button_text'] ) ) {
156 Merchant_Translator::register_string( $settings['button_text'], esc_html__( 'Quick view button text', 'merchant' ) );
157 }
158 }
159
160 /**
161 * Concatenate the quick view button with the content start wrap.
162 *
163 * @return string
164 */
165 public function add_quick_view_button() {
166 return $this->quick_view_button() . '<div class="product-details content-bg entry-content-wrap">';
167 }
168
169 /**
170 * Admin enqueue CSS.
171 *
172 * @return void
173 */
174 public function admin_enqueue_css() {
175 $page = ( ! empty( $_GET['page'] ) ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
176 $module = ( ! empty( $_GET['module'] ) ) ? sanitize_text_field( wp_unslash( $_GET['module'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
177
178 if ( 'merchant' === $page && self::MODULE_ID === $module ) {
179 wp_enqueue_style( 'merchant-' . self::MODULE_ID, MERCHANT_URI . 'assets/css/modules/' . self::MODULE_ID . '/quick-view.min.css', array(), MERCHANT_VERSION );
180 wp_enqueue_style( 'merchant-admin-' . self::MODULE_ID, MERCHANT_URI . 'assets/css/modules/' . self::MODULE_ID . '/admin/preview.min.css', array(), MERCHANT_VERSION );
181 }
182 }
183
184 /**
185 * Enqueue CSS.
186 *
187 * @return void
188 */
189 public function enqueue_css() {
190
191 // Specific module styles.
192 wp_enqueue_style( 'merchant-' . self::MODULE_ID, MERCHANT_URI . 'assets/css/modules/' . self::MODULE_ID . '/quick-view.min.css', array(), MERCHANT_VERSION );
193 }
194
195 /**
196 * Enqueue scripts.
197 *
198 * @return void
199 */
200 public function enqueue_scripts() {
201 wp_enqueue_script( 'zoom' );
202 wp_enqueue_script( 'flexslider' );
203 wp_enqueue_script( 'wc-single-product' );
204 wp_enqueue_script( 'wc-add-to-cart-variation' );
205
206 // Register and enqueue the main module script.
207 wp_enqueue_script( 'merchant-' . self::MODULE_ID, MERCHANT_URI . 'assets/js/modules/' . self::MODULE_ID . '/quick-view.min.js', array(), MERCHANT_VERSION, true );
208 }
209
210 /**
211 * Localize script with module settings.
212 *
213 * @param array $setting The merchant global object setting parameter.
214 * @return array $setting The merchant global object setting parameter.
215 */
216 public function localize_script( $setting ) {
217 $module_settings = $this->get_module_settings();
218
219 $setting[ 'quick_view' ] = true;
220 $setting[ 'quick_view_zoom' ] = $module_settings[ 'zoom_effect' ];
221
222 return $setting;
223 }
224
225 /**
226 * Enqueue botiga theme scripts.
227 *
228 * @return void
229 */
230 public function modal_compatibility_with_botiga_theme() {
231 if ( ! wp_script_is( 'botiga-product-swatch' ) ) {
232 wp_enqueue_script( 'botiga-product-swatch', BOTIGA_PRO_URI . 'assets/js/botiga-product-swatch.min.js', array(), BOTIGA_PRO_VERSION, true );
233 }
234
235 if ( ! wp_script_is( 'botiga-checkout-quantity-input' ) ) {
236 wp_enqueue_script( 'botiga-checkout-quantity-input', BOTIGA_PRO_URI . 'assets/js/botiga-checkout-quantity-input.min.js', array( 'jquery' ), BOTIGA_PRO_VERSION, true );
237 }
238 }
239
240 /**
241 * Render admin preview
242 *
243 * @param Merchant_Admin_Preview $preview
244 * @param string $module
245 *
246 * @return Merchant_Admin_Preview
247 */
248 public function render_admin_preview( $preview, $module ) {
249 if ( self::MODULE_ID === $module ) {
250 ob_start();
251 self::admin_preview_content();
252 $content = ob_get_clean();
253
254 // HTML.
255 $preview->set_html( $content );
256
257 // Button Type.
258 $preview->set_class( 'button_type', '.merchant-quick-view-button', array( 'icon', 'icon-text', 'text' ) );
259
260 // Button Text.
261 $preview->set_text( 'button_text', '.button-text' );
262
263 // Button Icon.
264 $preview->set_svg_icon( 'button_icon', '.quick-view-icon' );
265
266 // Button Position.
267 $preview->set_class( 'button_position', '.merchant-quick-view-preview', array( 'before', 'after', 'overlay' ) );
268
269 }
270
271 return $preview;
272 }
273
274 /**
275 * Admin preview content.
276 *
277 * @return void
278 */
279 public function admin_preview_content() {
280 $settings = $this->get_module_settings();
281
282 ?>
283
284 <div class="merchant-quick-view-preview <?php echo esc_attr( $settings[ 'button_position' ] ); ?>">
285 <div class="image-wrapper">
286 <div class="button-position button-position-overlay">
287 <?php $this->admin_preview_quick_view_button(); ?>
288 </div>
289 </div>
290 <h3><?php echo esc_html__( 'Product Title', 'merchant' ); ?></h3>
291 <p><?php echo esc_html__( 'The product description normally is displayed here.', 'merchant' ); ?></p>
292 <div class="button-position button-position-before">
293 <?php $this->admin_preview_quick_view_button(); ?>
294 </div>
295 <div>
296 <a href="#" class="add_to_cart_button"><?php echo esc_html__( 'Add To Cart', 'merchant' ); ?></a>
297 </div>
298 <div class="button-position button-position-after">
299 <?php $this->admin_preview_quick_view_button(); ?>
300 </div>
301
302 </div>
303
304 <?php
305 }
306
307 /**
308 * Admin preview quick view button.
309 *
310 * @return void
311 */
312 public function admin_preview_quick_view_button() {
313 $settings = $this->get_module_settings();
314
315 ?>
316
317 <a href="#" class="merchant-quick-view-button <?php echo esc_attr( $settings[ 'button_type' ] ); ?>">
318 <span class="button-type button-type-icon">
319 <span class="quick-view-icon">
320 <?php echo wp_kses( Merchant_SVG_Icons::get_svg_icon( $settings[ 'button_icon' ] ), merchant_kses_allowed_tags( array(), false ) ); ?>
321 </span>
322 </span>
323 <span class="button-type button-type-icon-text">
324 <span class="quick-view-icon">
325 <?php echo wp_kses( Merchant_SVG_Icons::get_svg_icon( $settings[ 'button_icon' ] ), merchant_kses_allowed_tags( array(), false ) ); ?>
326 </span>
327 <span class="button-text"><?php echo esc_html( $settings[ 'button_text' ] ); ?></span>
328 </span>
329 <span class="button-type button-type-text">
330 <span class="button-text"><?php echo esc_html( $settings[ 'button_text' ] ); ?></span>
331 </span>
332 </a>
333
334 <?php
335 }
336
337 /**
338 * Modal content ajax callback.
339 * TODO: Render the output through templates files.
340 *
341 * @return void
342 */
343 public function modal_content_ajax_callback() {
344 check_ajax_referer( 'merchant-nonce', 'nonce' );
345
346 if ( ! isset( $_POST['product_id'] ) || ! function_exists( 'wc_get_product' ) ) {
347 wp_send_json_error();
348 }
349
350 $args = array(
351 'product_id' => absint( $_POST['product_id'] ),
352 );
353
354 global $product;
355
356 $settings = $this->get_module_settings();
357 $product = wc_get_product( $args['product_id'] );
358
359 if ( is_wp_error( $product ) || empty( $product ) ) {
360 wp_send_json_error();
361 }
362
363 $product_id = $product->get_id();
364 $hide_quantity = ( empty( $settings[ 'show_quantity' ] ) ) ? 'merchant-hide-quantity' : '';
365
366 ob_start();
367
368 ?>
369
370 <div id="product-<?php echo absint( $product_id ); ?>" <?php wc_product_class( '', $product ); ?>>
371
372 <div class="merchant-quick-view-row">
373
374 <div class="merchant-quick-view-column">
375 <div class="merchant-quick-view-product-gallery">
376 <?php woocommerce_show_product_images(); ?>
377 </div>
378 </div>
379
380 <div class="merchant-quick-view-column">
381
382 <div class="merchant-quick-view-summary product-gallery-summary">
383
384 <div class="merchant-quick-view-product-title">
385 <h2 class="product_title entry-title"><?php echo esc_html( $product->get_title() ); ?></h2>
386 </div>
387 <?php if ( 0 !== $product->get_average_rating() ) : ?>
388 <div class="merchant-quick-view-product-rating">
389 <div class="woocommerce-product-rating">
390 <?php echo wp_kses( wc_get_rating_html( $product->get_average_rating() ), merchant_kses_allowed_tags() ); ?>
391 </div>
392 </div>
393 <?php endif; ?>
394 <div class="merchant-quick-view-product-price">
395 <div class="price"><?php echo wp_kses( $product->get_price_html(), merchant_kses_allowed_tags() ); ?></div>
396 </div>
397 <?php if ( 'top' === $settings[ 'place_product_description' ] ) : ?>
398 <?php if ( 'full' === $settings[ 'description_style' ] ) : ?>
399 <div class="merchant-quick-view-product-excerpt">
400 <?php echo wp_kses_post( $product->get_description() ); ?>
401 </div>
402 <?php else : ?>
403 <div class="merchant-quick-view-product-excerpt">
404 <p><?php echo wp_kses_post( $product->get_short_description() ); ?></p>
405 </div>
406 <?php endif; ?>
407 <?php endif; ?>
408 <div class="merchant-quick-view-product-add-to-cart <?php echo esc_attr( $hide_quantity ); ?>">
409 <?php woocommerce_template_single_add_to_cart(); ?>
410 </div>
411 <?php if ( 'bottom' === $settings[ 'place_product_description' ] ) : ?>
412 <?php if ( 'full' === $settings[ 'description_style' ] ) : ?>
413 <div class="merchant-quick-view-product-excerpt">
414 <?php echo wp_kses_post( $product->get_description() ); ?>
415 </div>
416 <?php else : ?>
417 <div class="merchant-quick-view-product-excerpt">
418 <p><?php echo wp_kses_post( $product->get_short_description() ); ?></p>
419 </div>
420 <?php endif; ?>
421 <?php endif; ?>
422 <div class="merchant-quick-view-product-meta">
423 <?php woocommerce_template_single_meta(); ?>
424 </div>
425
426 <?php
427 /**
428 * Hook 'merchant_quick_view_after_product_excerpt'
429 *
430 * @since 1.0.0
431 */
432 do_action( 'merchant_quick_view_after_product_meta' );
433 ?>
434
435 </div>
436
437 </div>
438
439 </div>
440
441 </div>
442
443 <?php
444
445 $content = ob_get_contents();
446
447 ob_get_clean();
448
449 wp_send_json_success( $content );
450 }
451
452 /**
453 * Modal output.
454 * TODO: Render the output through templates files.
455 *
456 * @return void
457 */
458 public function modal_output() {
459 $settings = $this->get_module_settings();
460
461 ?>
462 <div class="single-product merchant-quick-view-modal merchant-quick-view-<?php echo esc_attr( $settings[ 'place_product_image' ] ); ?>">
463 <div class="merchant-quick-view-overlay"></div>
464 <div class="merchant-quick-view-loader">
465 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
466 <path opacity="0.4" d="M478.71 364.58zm-22 6.11l-27.83-15.9a15.92 15.92 0 0 1-6.94-19.2A184 184 0 1 1 256 72c5.89 0 11.71.29 17.46.83-.74-.07-1.48-.15-2.23-.21-8.49-.69-15.23-7.31-15.23-15.83v-32a16 16 0 0 1 15.34-16C266.24 8.46 261.18 8 256 8 119 8 8 119 8 256s111 248 248 248c98 0 182.42-56.95 222.71-139.42-4.13 7.86-14.23 10.55-22 6.11z" />
467 <path d="M271.23 72.62c-8.49-.69-15.23-7.31-15.23-15.83V24.73c0-9.11 7.67-16.78 16.77-16.17C401.92 17.18 504 124.67 504 256a246 246 0 0 1-25 108.24c-4 8.17-14.37 11-22.26 6.45l-27.84-15.9c-7.41-4.23-9.83-13.35-6.2-21.07A182.53 182.53 0 0 0 440 256c0-96.49-74.27-175.63-168.77-183.38z" />
468 </svg>
469 </div>
470 <div class="merchant-quick-view-inner">
471 <a href="#" class="merchant-quick-view-close-button" title="<?php echo esc_attr__( 'Close quick view modal', 'merchant' ); ?>">
472 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
473 <path d="M193.94 256L296.5 153.44l21.15-21.15c3.12-3.12 3.12-8.19 0-11.31l-22.63-22.63c-3.12-3.12-8.19-3.12-11.31 0L160 222.06 36.29 98.34c-3.12-3.12-8.19-3.12-11.31 0L2.34 120.97c-3.12 3.12-3.12 8.19 0 11.31L126.06 256 2.34 379.71c-3.12 3.12-3.12 8.19 0 11.31l22.63 22.63c3.12 3.12 8.19 3.12 11.31 0L160 289.94 262.56 392.5l21.15 21.15c3.12 3.12 8.19 3.12 11.31 0l22.63-22.63c3.12-3.12 3.12-8.19 0-11.31L193.94 256z"/>
474 </svg>
475 </a>
476 <div class="merchant-quick-view-content"></div>
477 </div>
478 </div>
479 <?php
480 }
481
482 /**
483 * Quick view button.
484 *
485 * @return void
486 */
487 public function quick_view_button() {
488 global $product;
489
490 $settings = $this->get_module_settings();
491 $product_id = $product->get_id();
492
493 $button_text_html = '';
494 $button_icon_html = '';
495
496 if ( 'icon' === $settings[ 'button_type' ] || 'icon-text' === $settings[ 'button_type' ] ) {
497 $button_icon_html = Merchant_SVG_Icons::get_svg_icon( $settings[ 'button_icon' ] );
498 }
499
500 if ( 'text' === $settings[ 'button_type' ] || 'icon-text' === $settings[ 'button_type' ] ) {
501 $button_text_html = '<span>' . Merchant_Translator::translate( $settings[ 'button_text' ] ) . '</span>';
502 }
503
504 ?>
505 <a href="#" class="button wp-element-button merchant-quick-view-button merchant-quick-view-position-<?php echo esc_attr( $settings[ 'button_position' ] ); ?>" data-product-id="<?php echo absint( $product_id ); ?>"><?php echo wp_kses( $button_icon_html, merchant_kses_allowed_tags( array(), false ) ) . wp_kses_post( $button_text_html ); ?></a>
506 <?php
507 }
508
509 /**
510 * Custom CSS.
511 *
512 * @return string
513 */
514 public function get_module_custom_css() {
515 $css = '';
516
517 // Button Icon Color.
518 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'icon-color', '#ffffff', '.merchant-quick-view-button', '--mrc-qv-button-icon-color' );
519
520 // Button Icon Color (hover).
521 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'icon-hover-color', '#ffffff', '.merchant-quick-view-button', '--mrc-qv-button-icon-hover-color' );
522
523 // Button Text Color.
524 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'text-color', '#ffffff', '.merchant-quick-view-button', '--mrc-qv-button-color' );
525
526 // Button Text Color (hover).
527 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'text-hover-color', '#ffffff', '.merchant-quick-view-button', '--mrc-qv-button-color-hover' );
528
529 // Button Border Color.
530 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'border-color', '#212121', '.merchant-quick-view-button', '--mrc-qv-button-border-color' );
531
532 // Button Border Color (hover).
533 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'border-hover-color', '#414141', '.merchant-quick-view-button', '--mrc-qv-button-border-color-hover' );
534
535 // Button Background Color.
536 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'background-color', '#212121', '.merchant-quick-view-button', '--mrc-qv-button-bg-color' );
537
538 // Button Background Color (hover).
539 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'background-hover-color', '#414141', '.merchant-quick-view-button', '--mrc-qv-button-bg-color-hover' );
540
541 // Button Position Top.
542 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'button-position-top', '50', '.merchant-quick-view-button', '--mrc-qv-button-position-top', '%' );
543
544 // Button Position Left.
545 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'button-position-left', '50', '.merchant-quick-view-button', '--mrc-qv-button-position-left', '%' );
546
547 // Modal Width.
548 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'modal_width', 1000, '.merchant-quick-view-modal', '--mrc-qv-modal-width', 'px' );
549
550 // Modal Height.
551 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'modal_height', 500, '.merchant-quick-view-modal', '--mrc-qv-modal-height', 'px' );
552
553 // Sale Price Color.
554 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'sale-price-color', '#212121', '.merchant-quick-view-modal', '--mrc-qv-modal-sale-price-color' );
555
556 // Regular Price Color.
557 $css .= Merchant_Custom_CSS::get_variable_css( 'quick-view', 'regular-price-color', '#414141', '.merchant-quick-view-modal', '--mrc-qv-modal-regular-price-color' );
558
559 return $css;
560 }
561
562 /**
563 * Admin custom CSS.
564 *
565 * @param string $css The custom CSS.
566 * @return string $css The custom CSS.
567 */
568 public function admin_custom_css( $css ) {
569 $css .= $this->get_module_custom_css();
570
571 return $css;
572 }
573
574 /**
575 * Frontend custom CSS.
576 *
577 * @param string $css The custom CSS.
578 * @return string $css The custom CSS.
579 */
580 public function frontend_custom_css( $css ) {
581 $css .= $this->get_module_custom_css();
582
583 return $css;
584 }
585 }
586
587 // Initialize the module.
588 add_action( 'init', function() {
589 new Merchant_Quick_View();
590 } );
591