PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 2.2.8
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v2.2.8
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 / pre-orders / class-pre-orders.php

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

517 lines 16.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Merchant - Pre Orders
4 *
5 * @package Merchant
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit; // Exit if accessed directly
10 }
11
12 /**
13 * Pre Orders Class.
14 *
15 * This class handles the initialization and setup of the Pre Orders module, including
16 * admin settings, asset enqueueing, and frontend styling.
17 *
18 * @property string $module_id The module ID.
19 * @property bool $wc_only The WooCommerce only flag.
20 * @property string $module_section The module section.
21 * @property array $module_default_settings The module default settings.
22 * @property array $module_data The module data.
23 * @property string $module_options_path The module options path.
24 */
25 class Merchant_Pre_Orders extends Merchant_Add_Module {
26
27 /**
28 * Module ID.
29 *
30 * @var string The module ID.
31 */
32 const MODULE_ID = 'pre-orders';
33
34 /**
35 * Is module preview.
36 *
37 * @var bool The is module preview flag.
38 */
39 public static $is_module_preview = false;
40
41 /**
42 * Main functionality dependency.
43 *
44 * @var Merchant_Pre_Orders_Main_Functionality The main functionality instance.
45 */
46 public $main_func;
47
48 /**
49 * Set the module as having analytics.
50 *
51 * @var bool
52 */
53 protected $has_analytics = true;
54
55 /**
56 * Constructor.
57 *
58 * @param Merchant_Pre_Orders_Main_Functionality $main_func The main functionality instance.
59 */
60 public function __construct( Merchant_Pre_Orders_Main_Functionality $main_func ) {
61 // Module id.
62 $this->module_id = self::MODULE_ID;
63
64 // WooCommerce only.
65 $this->wc_only = true;
66
67 // Parent construct.
68 parent::__construct();
69
70 $this->main_func = $main_func;
71
72 // Module section.
73 $this->module_section = 'boost-revenue';
74
75 // Module default settings.
76 $this->module_default_settings = array(
77 'button_text' => __( 'Pre Order Now!', 'merchant' ),
78 'additional_text' => __( 'Ships on {date}.', 'merchant' ),
79 );
80
81 // Module data.
82 $this->module_data = Merchant_Admin_Modules::$modules_data[ self::MODULE_ID ];
83
84 // Module options path.
85 $this->module_options_path = MERCHANT_DIR . 'inc/modules/' . self::MODULE_ID . '/admin/options.php';
86
87 // Is module preview page.
88 if ( is_admin() && parent::is_module_settings_page() ) {
89 self::$is_module_preview = true;
90
91 // Enqueue admin styles.
92 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_css' ) );
93 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_js' ) );
94
95 // Localize Script.
96 add_filter( 'merchant_admin_localize_script', array( $this, 'localize_script' ) );
97
98 // Admin preview box.
99 add_filter( 'merchant_module_preview', array( $this, 'render_admin_preview' ), 10, 2 );
100
101 // Custom CSS.
102 // The custom CSS should be added here as well due to ensure preview box works properly.
103 add_filter( 'merchant_custom_css', array( $this, 'admin_custom_css' ) );
104 }
105
106 add_action( 'merchant_admin_before_include_modules_options', array( $this, 'help_banner' ) );
107
108 if ( Merchant_Modules::is_module_active( self::MODULE_ID ) && is_admin() ) {
109 // Init translations.
110 $this->init_translations();
111
112 // Include product metabox for per-product settings.
113 require_once MERCHANT_DIR . 'inc/modules/' . self::MODULE_ID . '/admin/class-pre-orders-metabox.php';
114 }
115
116
117 if ( ! Merchant_Modules::is_module_active( self::MODULE_ID ) ) {
118 return;
119 }
120
121 // TODO: Refactor the 'Merchant_Pre_Orders_Main_Functionality' class to load admin things separated from frontend things.
122 $main_func->init();
123
124 // Return early if it's on admin but not in the respective module settings page.
125 if ( is_admin() && ! wp_doing_ajax() && ! parent::is_module_settings_page() ) {
126 return;
127 }
128
129 // Enqueue styles.
130 add_action( 'merchant_enqueue_before_main_css_js', array( $this, 'enqueue_css' ) );
131
132 // Enqueue scripts.
133 add_action( 'merchant_enqueue_after_main_css_js', array( $this, 'enqueue_scripts' ) );
134
135 // Localize script.
136 add_filter( 'merchant_localize_script', array( $this, 'localize_script' ) );
137
138 // Custom CSS.
139 add_filter( 'merchant_custom_css', array( $this, 'frontend_custom_css' ) );
140
141 $this->supply_missing_id( 'rules' );
142 }
143
144 /**
145 * Init translations for module settings.
146 *
147 * Registers strings for the Merchant translator tool.
148 *
149 * @return void
150 */
151 public function init_translations() {
152 $settings = $this->get_module_settings();
153 if ( ! empty( $settings['rules'] ) ) {
154 foreach ( $settings['rules'] as $rule ) {
155 if ( ! empty( $rule['button_text'] ) ) {
156 Merchant_Translator::register_string( $rule['button_text'], 'Pre order button text' );
157 }
158 if ( ! empty( $rule['additional_text'] ) ) {
159 Merchant_Translator::register_string( $rule['additional_text'], 'Pre order additional information' );
160 }
161 if ( ! empty( $rule['cart_label_text'] ) ) {
162 Merchant_Translator::register_string( $rule['cart_label_text'], 'Label text on cart' );
163 }
164 }
165 }
166 }
167
168 /**
169 * Enqueue admin-specific CSS.
170 *
171 * @return void
172 */
173 public function admin_enqueue_css() {
174 if ( parent::is_module_settings_page() ) {
175 wp_enqueue_style( 'merchant-' . self::MODULE_ID, MERCHANT_URI . 'assets/css/modules/' . self::MODULE_ID . '/pre-orders.min.css', array(), MERCHANT_VERSION );
176 wp_enqueue_style( 'merchant-admin-' . self::MODULE_ID, MERCHANT_URI . 'assets/css/modules/' . self::MODULE_ID . '/admin/preview.min.css', array(), MERCHANT_VERSION );
177 }
178 }
179
180 /**
181 * Enqueue admin-specific JavaScript.
182 *
183 * @return void
184 */
185 public function admin_enqueue_js() {
186 if ( parent::is_module_settings_page() ) {
187 wp_enqueue_script(
188 'merchant-admin-' . self::MODULE_ID,
189 MERCHANT_URI . 'assets/js/modules/' . self::MODULE_ID . '/admin/preview.min.js',
190 array( 'jquery' ),
191 MERCHANT_VERSION,
192 true
193 );
194 }
195 }
196
197 /**
198 * Enqueue frontend-specific CSS.
199 *
200 * @return void
201 */
202 public function enqueue_css() {
203 // Specific module styles.
204 wp_enqueue_style( 'merchant-' . self::MODULE_ID, MERCHANT_URI . 'assets/css/modules/' . self::MODULE_ID . '/pre-orders.min.css', array(), MERCHANT_VERSION );
205
206 // add inline style
207 if ( is_singular( 'product' ) ) {
208 wp_add_inline_style( 'merchant-' . self::MODULE_ID, $this->add_inline_style() );
209 }
210 }
211
212 /**
213 * Add inline CSS styles based on the active rule.
214 *
215 * @return string The generated inline CSS.
216 */
217 public function add_inline_style() {
218 ob_start();
219 $rule = $this->current_rule();
220 if ( ! empty( $rule ) ) {
221 ?>
222 .woocommerce .merchant-pre-ordered-product{
223 --mrc-po-text-color: <?php echo esc_attr( $rule['text-color'] ?? '#FFF' ); ?>;
224 --mrc-po-text-hover-color: <?php echo esc_attr( $rule['text-hover-color'] ?? '#FFF' ); ?>;
225 --mrc-po-border-color: <?php echo esc_attr( $rule['border-color'] ?? '#212121' ); ?>;
226 --mrc-po-border-hover-color: <?php echo esc_attr( $rule['border-hover-color'] ?? '#414141' ); ?>;
227 --mrc-po-border-width: <?php echo esc_attr( ( $rule['border-width'] ?? 0 ) . 'px' ); ?>;
228 --mrc-po-border-radius: <?php echo esc_attr( ( $rule['border-radius'] ?? 0 ) . 'px' ); ?>;
229 --mrc-po-background-color: <?php echo esc_attr( $rule['background-color'] ?? '#212121' ); ?>;
230 --mrc-po-background-hover-color: <?php echo esc_attr( $rule['background-hover-color'] ?? '#414141' ); ?>;
231 }
232 <?php
233 }
234
235 return ob_get_clean();
236 }
237
238 /**
239 * Enqueue frontend-specific scripts.
240 *
241 * @return void
242 */
243 public function enqueue_scripts() {
244 // Register and enqueue the main module script.
245 wp_enqueue_script( 'merchant-' . self::MODULE_ID, MERCHANT_URI . 'assets/js/modules/' . self::MODULE_ID . '/pre-orders.min.js', array(), MERCHANT_VERSION, true );
246 }
247
248 /**
249 * Localize the main module script with settings and translations.
250 *
251 * @param array $setting The localized settings array.
252 *
253 * @return array The updated settings array.
254 */
255 public function localize_script( $setting ) {
256 $setting['pre_orders'] = true;
257 $rule = $this->current_rule();
258 if ( ! empty( $rule ) && ! empty( $rule['button_text'] ) ) {
259 $setting['pre_orders_add_button_title'] = Merchant_Translator::translate( $rule['button_text'] );
260 } else {
261 $setting['pre_orders_add_button_title'] = esc_html__( 'Pre Order Now!', 'merchant' );
262 }
263
264 $setting['shipping_date_missing_text'] = esc_html__( 'Please set a shipping date first', 'merchant' );
265
266 return $setting;
267 }
268
269 /**
270 * Render the admin preview for the module.
271 *
272 * @param Merchant_Admin_Preview $preview The preview object.
273 * @param string $module The module ID.
274 *
275 * @return Merchant_Admin_Preview The updated preview object.
276 */
277 public function render_admin_preview( $preview, $module ) {
278 if ( self::MODULE_ID === $module ) {
279 $settings = $this->get_module_settings();
280
281 // Additional text.
282 $additional_text = $settings['additional_text'];
283 $time_format = date_i18n( get_option( 'date_format' ), strtotime( gmdate( 'Y-m-d', strtotime( '+2 days' ) ) ) );
284 $text = $this->main_func->replace_date_text( $additional_text, $time_format );
285
286 ob_start();
287 self::admin_preview_content( $settings, $text );
288 $content = ob_get_clean();
289
290 // HTML.
291 $preview->set_html( $content );
292
293 // Button Text.
294 $preview->set_text( 'button_text', '.add_to_cart_button' );
295
296 // Additional Text.
297 $preview->set_text( 'additional_text', '.merchant-pre-orders-date', array(
298 array(
299 '{date}',
300 ),
301 array(
302 $time_format,
303 ),
304 ) );
305 }
306
307 return $preview;
308 }
309
310 /**
311 * Admin preview HTML content.
312 *
313 * @param array $settings The module settings.
314 * @param string $text The formatted additional text.
315 *
316 * @return void
317 */
318 public function admin_preview_content( $settings, $text ) {
319 ?>
320 <div class="mrc-preview-single-product-elements">
321 <div class="mrc-preview-left-column">
322 <div class="mrc-preview-product-image-wrapper">
323 <div class="mrc-preview-product-image"></div>
324 <div class="mrc-preview-product-image-thumbs">
325 <div class="mrc-preview-product-image-thumb"></div>
326 <div class="mrc-preview-product-image-thumb"></div>
327 <div class="mrc-preview-product-image-thumb"></div>
328 </div>
329 </div>
330 </div>
331 <div class="mrc-preview-right-column">
332 <div class="mrc-preview-text-placeholder"></div>
333 <div class="mrc-preview-text-placeholder mrc-mw-70"></div>
334 <div class="mrc-preview-text-placeholder mrc-mw-40 mrc-hide-on-smaller-screens"></div>
335 <div class="mrc-preview-text-placeholder mrc-mw-30 mrc-hide-on-smaller-screens"></div>
336 <div class="merchant-pre-ordered-product">
337 <div class="merchant-pre-orders-date"><?php echo esc_html( $text ); ?></div>
338 <a href="#" class="add_to_cart_button"><?php echo esc_html( $settings['button_text'] ); ?></a>
339 </div>
340 </div>
341 </div>
342 <?php
343 }
344
345 /**
346 * Get Custom CSS for the module.
347 *
348 * @return string The generated CSS.
349 */
350 public function get_module_custom_css() {
351 $css = '';
352
353 if ( is_admin() || is_singular( 'product' ) ) {
354 // Text Color.
355 $css .= Merchant_Custom_CSS::get_variable_css( 'pre-orders', 'text-color', '#FFF', '.merchant-pre-ordered-product', '--mrc-po-text-color' );
356
357 // Text Color (hover).
358 $css .= Merchant_Custom_CSS::get_variable_css( 'pre-orders', 'text-hover-color', '#FFF', '.merchant-pre-ordered-product', '--mrc-po-text-hover-color' );
359
360 // Border Color.
361 $css .= Merchant_Custom_CSS::get_variable_css( 'pre-orders', 'border-color', '#212121', '.merchant-pre-ordered-product', '--mrc-po-border-color' );
362
363 // Border Color (hover).
364 $css .= Merchant_Custom_CSS::get_variable_css( 'pre-orders', 'border-hover-color', '#414141', '.merchant-pre-ordered-product', '--mrc-po-border-hover-color' );
365
366 // Border Width.
367 $css .= Merchant_Custom_CSS::get_variable_css( 'pre-orders', 'border-width', 0, '.merchant-pre-ordered-product', '--mrc-po-border-width', 'px' );
368
369 // Border Radius.
370 $css .= Merchant_Custom_CSS::get_variable_css( 'pre-orders', 'border-radius', 0, '.merchant-pre-ordered-product', '--mrc-po-border-radius', 'px' );
371
372 // Background Color.
373 $css .= Merchant_Custom_CSS::get_variable_css( 'pre-orders', 'background-color', '#212121', '.merchant-pre-ordered-product', '--mrc-po-background-color' );
374
375 // Background Color (hover).
376 $css .= Merchant_Custom_CSS::get_variable_css( 'pre-orders', 'background-hover-color', '#414141', '.merchant-pre-ordered-product', '--mrc-po-background-hover-color' );
377 }
378
379 return $css;
380 }
381
382 /**
383 * Filter for admin custom CSS.
384 *
385 * @param string $css The custom CSS.
386 *
387 * @return string The updated custom CSS.
388 */
389 public function admin_custom_css( $css ) {
390 $css .= $this->get_module_custom_css();
391
392 return $css;
393 }
394
395 /**
396 * Filter for frontend custom CSS.
397 *
398 * @param string $css The custom CSS.
399 *
400 * @return string The updated custom CSS.
401 */
402 public function frontend_custom_css( $css ) {
403 $css .= $this->get_module_custom_css();
404
405 return $css;
406 }
407
408 /**
409 * Get the currently applicable product rule.
410 *
411 * @return array The rule array if found, empty array otherwise.
412 */
413 private function current_rule() {
414 if ( is_singular( 'product' ) ) {
415 $product_id = get_queried_object_id();
416 $product = wc_get_product( $product_id );
417
418 if ( ! $product ) {
419 return array();
420 }
421
422 $rule = Merchant_Pre_Orders_Main_Functionality::available_product_rule( $product->get_id() );
423 if ( empty( $rule ) && $product instanceof \WC_Product_Variable ) {
424 $available_variations = $product->get_available_variations();
425 foreach ( $available_variations as $variation ) {
426 $rule = Merchant_Pre_Orders_Main_Functionality::available_product_rule( $variation['variation_id'] );
427 if ( ! empty( $rule ) ) {
428 break;
429 }
430 }
431 }
432
433 return $rule;
434 }
435
436 return array();
437 }
438
439 /**
440 * Display a help banner in the module settings page.
441 *
442 * @param string $module_id The module ID.
443 *
444 * @return void
445 */
446 public function help_banner( $module_id ) {
447 if ( $module_id === self::MODULE_ID ) {
448 ?>
449 <div class="merchant-module-page-setting-fields">
450 <div class="merchant-module-page-setting-field merchant-module-page-setting-field-content">
451 <div class="merchant-module-page-setting-field-inner">
452 <div class="merchant-tag-pre-orders">
453 <i class="dashicons dashicons-info"></i>
454 <p>
455 <?php
456 echo esc_html__(
457 'Pre-orders captured by Merchant are tagged with "Merchant PreOrder" and can be found in your WooCommerce Order Section. You can control pre-order settings on a per-product basis from the individual product page.',
458 'merchant'
459 );
460 printf(
461 '<a href="%1s" target="_blank">%2s</a>',
462 esc_url( admin_url( 'edit.php?post_type=shop_order' ) ),
463 esc_html__( 'View Pre-Orders', 'merchant' )
464 );
465 ?></p>
466 </div>
467 </div>
468 </div>
469 </div>
470 <?php
471 }
472 }
473
474 /**
475 * Supply missing flexible_id for the rules setting.
476 *
477 * @param string $setting_key The setting key for the flexible items.
478 *
479 * @return void
480 */
481 public function supply_missing_id( $setting_key = 'offers' ) {
482 $option = 'merchant_' . $this->module_id . '_missing_id_flag';
483
484 if ( get_option( $option, false ) || ! method_exists( 'Merchant_Admin_Options', 'set' ) ) {
485 return;
486 }
487
488 $flexible_items = Merchant_Admin_Options::get( $this->module_id, $setting_key, array() );
489 if ( ! empty( $flexible_items ) ) {
490 $update = 0;
491 foreach ( $flexible_items as $key => $item ) {
492 if ( empty( $item['flexible_id'] ) ) {
493 $flexible_items[ $key ]['flexible_id'] = wp_generate_uuid4();
494 ++ $update;
495 }
496 }
497
498 if ( $update > 0 ) {
499 Merchant_Admin_Options::set( $this->module_id, $setting_key, $flexible_items );
500 }
501
502 update_option( $option, true, false );
503 }
504 }
505 }
506
507 // Rules Repository.
508 require_once MERCHANT_DIR . 'inc/modules/pre-orders/classes/class-pre-orders-rules.php';
509
510 // Main functionality.
511 require_once MERCHANT_DIR . 'inc/modules/pre-orders/class-pre-orders-main-functionality.php';
512
513 // Initialize the module.
514 add_action( 'init', function () {
515 Merchant_Modules::create_module( new Merchant_Pre_Orders( new Merchant_Pre_Orders_Main_Functionality() ) );
516 } );
517