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 / class-add-module.php

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

347 lines 8.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 class Merchant_Add_Module {
8
9 /**
10 * WooCommerce only.
11 *
12 */
13 public $wc_only = false;
14
15 /**
16 * Module section.
17 *
18 */
19 public $module_section = '';
20
21 /**
22 * Module id.
23 *
24 */
25 public $module_id = '';
26
27 /**
28 * Module default settings.
29 *
30 */
31 public $module_default_settings = array();
32
33 /**
34 * Module data.
35 *
36 */
37 public $module_data = array();
38
39 /**
40 * Module options.
41 *
42 */
43 public $module_options_path = '';
44
45 /**
46 * Whether the module has a shortcode or not.
47 *
48 * @var bool
49 */
50 public $has_shortcode = false;
51
52 protected $has_analytics = false;
53
54 /**
55 * Constructor.
56 *
57 */
58 public function __construct() {
59 // Add and expose the module into the plugin dashboard.
60 add_filter( 'merchant_modules', array( $this, 'add_module' ) );
61
62 // Add module options.
63 add_filter( 'merchant_module_file_path', array( $this, 'add_module_options' ), 10, 2 );
64
65 // Add class to body to identify if module is active or not.
66 add_filter( 'admin_body_class', array( $this, 'add_module_activation_status_class' ), 10, 2 );
67
68 // Handle modules list item class.
69 add_filter( "merchant_admin_module_{$this->module_id}_list_item_class", array( $this, 'modules_list_item_class' ) );
70
71 if ( $this->has_shortcode ) {
72 add_action( 'wp', array( $this, 'setup_product_object' ) );
73 add_shortcode( 'merchant_module_' . str_replace( '-', '_', $this->module_id ), array( $this, 'shortcode_handler' ) );
74 }
75
76 // Remove merchant shortcodes from Botiga product card short description
77 add_filter( 'botiga_loop_product_elements', function( $elements ) {
78 add_filter( 'get_the_excerpt', function( $excerpt ) {
79 return preg_replace( '/\[merchant_[^]]+]/', '', $excerpt );
80 } );
81
82 return $elements;
83 } );
84 }
85
86 /**
87 * Check if the module has analytics.
88 *
89 * @return bool
90 */
91 public function has_analytics() {
92 return $this->has_analytics;
93 }
94
95 /**
96 * Get all analytics metrics and allow modules to filter them.
97 *
98 * @return array List of available metrics.
99 */
100 public function analytics_metrics() {
101 /**
102 * Hook: merchant_analytics_module_metrics
103 *
104 * @param array $metrics List of available metrics.
105 * @param string $module_id Module ID.
106 *
107 * @since 2.0
108 */
109 return apply_filters( 'merchant_analytics_module_metrics', $this->default_analytics_metrics(), $this->module_id, $this );
110 }
111
112 /**
113 * Get analytics metrics.
114 *
115 * @return array List of available metrics.
116 */
117 protected function default_analytics_metrics() {
118 return array(
119 'campaigns' => true,
120 'impressions' => true,
121 'clicks' => true,
122 'ctr' => true,
123 'revenue' => true,
124 'orders_count' => true,
125 'aov' => true,
126 );
127 }
128
129 /**
130 * Active modules class handler.
131 *
132 */
133 public function add_module_activation_status_class( $classes ) {
134 if ( ! $this->is_module_settings_page() ) {
135 return $classes;
136 }
137
138 if ( Merchant_Modules::is_module_active( $this->module_id ) ) {
139 $classes = $classes . ' merchant-module-enabled';
140 } else {
141 $classes = $classes . ' merchant-module-disabled';
142 }
143
144 return $classes;
145 }
146
147 /**
148 * Modules list item class.
149 *
150 * @param string $module_class
151 *
152 * @return string
153 */
154 public function modules_list_item_class( $module_class ) {
155 if ( $this->wc_only && ! class_exists( 'Woocommerce' ) ) {
156 $module_class = $module_class . ' merchant-module-wc-only';
157 }
158
159 return $module_class;
160 }
161
162 /**
163 * Is module settings page.
164 *
165 * @return bool
166 */
167 public function is_module_settings_page() {
168 return isset( $_GET['page'] ) && 'merchant' === $_GET['page'] // phpcs:ignore WordPress.Security.NonceVerification.Recommended
169 && isset( $_GET['module'] ) && $this->module_id === $_GET['module']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
170 }
171
172 /**
173 * Get module settings.
174 *
175 */
176 public function get_module_settings() {
177 $settings = get_option( 'merchant', array() );
178
179 // Default settings.
180 $defaults = $this->module_default_settings;
181
182 if ( empty( $settings[ $this->module_id ] ) ) {
183 $settings[ $this->module_id ] = $defaults;
184 }
185
186 // Parse settings with defaults.
187 // Todo: check if recursive_parse_args() works for all modules and remove the condition.
188 $settings = $this->module_id === 'product-labels' ? $this->recursive_parse_args( $settings[ $this->module_id ], $defaults ) : wp_parse_args( $settings[ $this->module_id ], $defaults );
189
190 /**
191 * Hook: merchant_module_settings
192 *
193 * @param array $settings Module settings.
194 * @param string $module_id Module ID.
195 *
196 * @since 1.9.16
197 */
198 $settings = apply_filters( 'merchant_module_settings', $settings, $this->module_id );
199
200 return $settings;
201 }
202
203 /**
204 * Update module settings.
205 *
206 * @param array $module_settings
207 *
208 * @return void
209 */
210 public function update_module_settings( $module_settings ) {
211 $settings = get_option( 'merchant', array() );
212
213 $settings[ $this->module_id ] = $module_settings;
214
215 /**
216 * Hook: merchant_module_settings_update
217 *
218 * @param array $settings Module settings.
219 * @param string $module_id Module ID.
220 *
221 * @since 2.0.0
222 */
223 $settings = apply_filters( 'merchant_module_settings_update', $settings, $this->module_id );
224
225 update_option( 'merchant', $settings );
226 }
227
228 /**
229 * Add module.
230 *
231 */
232 public function add_module( $modules ) {
233 $modules[ $this->module_section ]['modules'][ $this->module_id ] = $this->module_data;
234
235 return $modules;
236 }
237
238 /**
239 * Add module options.
240 *
241 */
242 public function add_module_options( $module_path, $merchant_module ) {
243 if ( $this->module_id === $merchant_module ) {
244 return $this->module_options_path;
245 }
246
247 return $module_path;
248 }
249
250 /**
251 * Display error message if the shortcode is placed in the wrong place.
252 *
253 * @return mixed|null
254 */
255 public function shortcode_placement_error() {
256 /*
257 * translators: %s: module id
258 */
259 $message = __( 'The shortcode <strong>[merchant_module_%s]</strong> can only be used on single product pages.', 'merchant' );
260 $message = sprintf( $message, str_replace( '-', '_', $this->module_id ) );
261 $message = wp_kses( $message, array(
262 'strong' => array(),
263 ) );
264
265 /**
266 * Filter the shortcode error message html content.
267 *
268 * @param string $message_content
269 * @param string $module_id
270 *
271 * @since 1.8
272 */
273 return apply_filters( 'merchant_module_shortcode_error_message_html',
274 '<div class="merchant-shortcode-wrong-placement">' .
275 $message
276 . '</div>',
277 $this->module_id );
278 }
279
280 /**
281 * Check if shortcode is enabled.
282 *
283 * @return bool
284 */
285 public function is_shortcode_enabled() {
286
287 /**
288 * Hook 'merchant_{$this->module_id}_is_shortcode_enabled'
289 *
290 * @since 1.9.3
291 */
292 return apply_filters( "merchant_{$this->module_id}_is_shortcode_enabled", Merchant_Admin_Options::get( $this->module_id, 'use_shortcode', false ) );
293 }
294
295 /**
296 * Recursively merges user-defined arguments into default arguments.
297 *
298 * @param $args
299 * @param $defaults
300 *
301 * @return mixed
302 */
303 private function recursive_parse_args( $args, $defaults ) {
304 $result = $defaults;
305
306 foreach ( $args as $key => $value ) {
307 // If the value is an array and the corresponding default is also an array, merge them recursively.
308 if ( is_array( $value ) && isset( $result[ $key ] ) && is_array( $result[ $key ] ) ) {
309 $result[ $key ] = $this->recursive_parse_args( $value, $result[ $key ] );
310 } else {
311 $result[ $key ] = $value;
312 }
313 }
314
315 return $result;
316 }
317
318 /**
319 * Ensure $product is an object in the Breakdance builder editor.
320 * If $product is a string, convert it to a WooCommerce product object.
321 *
322 * @return void
323 */
324 public function setup_product_object() {
325 if ( ! class_exists( 'WooCommerce' ) ) {
326 return;
327 }
328
329 if ( ! is_product() ) {
330 return;
331 }
332
333 global $product;
334
335 // Check if $product is a string and not already an object
336 if ( ! is_object( $product ) && is_string( $product ) ) {
337 // Retrieve the product object by slug
338 $product_object = wc_get_product( get_page_by_path( $product, OBJECT, 'product' ) );
339
340 // Update global $product with the retrieved product object if found
341 if ( $product_object ) {
342 $product = $product_object;
343 }
344 }
345 }
346 }
347