PluginProbe
WowAddons – Product Addons and Product Options With Custom Fields / trunk
WowAddons – Product Addons and Product Options With Custom Fields vtrunk
1.7.2 1.7.1 1.7.0 1.6.21 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.5.10 1.5.11 1.5.2 1.5.3 1.5.4 1.5.5 All 57 releases
product-addons / includes / class-xpo.php

class-xpo.php in WowAddons – Product Addons and Product Options With Custom Fields trunk, at includes/class-xpo.php

544 lines 16.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php //phpcs:ignore
2 /**
3 * Xpo class for Product Addons plugin.
4 *
5 * @package PRAD
6 */
7
8 namespace PRAD\Includes;
9
10 defined( 'ABSPATH' ) || exit;
11
12 /**
13 * Core class for managing plugin actions and integrations.
14 *
15 * @package PRAD
16 */
17 class Xpo {
18
19 /**
20 * Gets license key
21 *
22 * @return string
23 */
24 public static function get_lc_key() {
25 return get_option( 'edd_prad_license_key', '' );
26 }
27
28 /**
29 * Checks if the license key is active.
30 *
31 * @return bool True if the license is active, false otherwise.
32 */
33 public static function is_lc_active() {
34 if ( defined( 'PRAD_PRO_VER' ) ) {
35 $license_data = get_option( 'edd_prad_license_data', array() );
36 return isset( $license_data['license'] ) && 'valid' === $license_data['license'];
37 }
38 return false;
39 }
40
41 /**
42 * Checks if the license has expired.
43 *
44 * This method checks the stored license data in the WordPress options table
45 * and determines if the license status is set to 'expired'. It returns `true`
46 * if the license is expired, otherwise `false`.
47 *
48 * @return bool True if the license is expired, otherwise false.
49 */
50 public static function is_lc_expired() {
51 $license_data = get_option( 'edd_prad_license_data', array() );
52 return isset( $license_data['license'] ) && 'expired' === $license_data['license'];
53 }
54
55 /**
56 * Get Option Value bypassing cache
57 * Inspired By WordPress Core get_option
58 *
59 * @since v.1.0.7
60 * @param string $option Option Name.
61 * @param boolean $default_value option default value.
62 * @return mixed
63 */
64 public static function get_option_without_cache( $option, $default_value = false ) {
65 global $wpdb;
66
67 if ( is_scalar( $option ) ) {
68 $option = trim( $option );
69 }
70
71 if ( empty( $option ) ) {
72 return false;
73 }
74
75 $value = $default_value;
76
77 $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
78
79 if ( is_object( $row ) ) {
80 $value = $row->option_value;
81 } else {
82 return apply_filters( "prad_default_option_{$option}", $default_value, $option );
83 }
84
85 return apply_filters( "prad_option_{$option}", maybe_unserialize( $value ), $option );
86 }
87
88 /**
89 * Add option without adding to the cache
90 * Inspired By WordPress Core set_transient
91 *
92 * @since v.1.0.7
93 * @param string $option option name.
94 * @param string $value option value.
95 * @param string $autoload whether to load WordPress startup.
96 * @return bool
97 */
98 public static function add_option_without_cache( $option, $value = '', $autoload = 'yes' ) {
99 global $wpdb;
100
101 if ( is_scalar( $option ) ) {
102 $option = trim( $option );
103 }
104
105 if ( empty( $option ) ) {
106 return false;
107 }
108
109 wp_protect_special_option( $option );
110
111 if ( is_object( $value ) ) {
112 $value = clone $value;
113 }
114
115 $value = sanitize_option( $option, $value );
116
117 /*
118 * Make sure the option doesn't already exist.
119 */
120
121 if ( apply_filters( "prad_default_option_{$option}", false, $option, false ) !== self::get_option_without_cache( $option ) ) {
122 return false;
123 }
124
125 $serialized_value = maybe_serialize( $value );
126 $autoload = ( 'no' === $autoload || false === $autoload ) ? 'no' : 'yes';
127
128 $result = $wpdb->query( $wpdb->prepare( "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)", $option, $serialized_value, $autoload ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
129 if ( ! $result ) {
130 return false;
131 }
132
133 return true;
134 }
135
136 /**
137 * Get Transient Value bypassing cache
138 * Inspired By WordPress Core get_transient
139 *
140 * @since v.1.0.7
141 * @param string $transient Transient Name.
142 * @return mixed
143 */
144 public static function get_transient_without_cache( $transient ) {
145 $transient_option = '_transient_' . $transient;
146 $transient_timeout = '_transient_timeout_' . $transient;
147 $timeout = self::get_option_without_cache( $transient_timeout );
148
149 if ( false !== $timeout && $timeout < time() ) {
150 delete_option( $transient_option );
151 delete_option( $transient_timeout );
152 $value = false;
153 }
154
155 if ( ! isset( $value ) ) {
156 $value = self::get_option_without_cache( $transient_option );
157 }
158
159 return apply_filters( "prad_transient_{$transient}", $value, $transient );
160 }
161
162 /**
163 * Set transient without adding to the cache
164 * Inspired By WordPress Core set_transient
165 *
166 * @since v.1.0.7
167 * @param string $transient Transient Name.
168 * @param mixed $value Transient Value.
169 * @param integer $expiration Time until expiration in seconds.
170 * @return bool
171 */
172 public static function set_transient_without_cache( $transient, $value, $expiration = 0 ) {
173 $expiration = (int) $expiration;
174
175 $transient_timeout = '_transient_timeout_' . $transient;
176 $transient_option = '_transient_' . $transient;
177
178 $result = false;
179
180 if ( false === self::get_option_without_cache( $transient_option ) ) {
181 $autoload = 'yes';
182 if ( $expiration ) {
183 $autoload = 'no';
184 self::add_option_without_cache( $transient_timeout, time() + $expiration, 'no' );
185 }
186 $result = self::add_option_without_cache( $transient_option, $value, $autoload );
187 } else {
188 /*
189 * If expiration is requested, but the transient has no timeout option,
190 * delete, then re-create transient rather than update.
191 */
192 $update = true;
193
194 if ( $expiration ) {
195 if ( false === self::get_option_without_cache( $transient_timeout ) ) {
196 delete_option( $transient_option );
197 self::add_option_without_cache( $transient_timeout, time() + $expiration, 'no' );
198 $result = self::add_option_without_cache( $transient_option, $value, 'no' );
199 $update = false;
200 } else {
201 update_option( $transient_timeout, time() + $expiration );
202 }
203 }
204
205 if ( $update ) {
206 $result = update_option( $transient_option, $value );
207 }
208 }
209
210 return $result;
211 }
212
213 /**
214 * Generates a URL with UTM parameters for tracking.
215 *
216 * @param array $params {
217 * Optional. Parameters for generating the UTM link.
218 *
219 * @type string $url The base URL to which UTM parameters will be added.
220 * @type string $utmKey The key to select a default UTM configuration.
221 * @type string $affiliate Affiliate ID to append as a 'ref' parameter.
222 * @type string $hash Hash fragment to append to the URL.
223 * @type array $config Custom UTM configuration array.
224 * }
225 * @return string The generated URL with UTM parameters.
226 */
227 public static function generate_utm_link( $params ) {
228 $default_config = array(
229 'example' => array(
230 'source' => 'db-wowaddons-featurename',
231 'medium' => 'block-feature',
232 'campaign' => 'wowaddons-dashboard',
233 ),
234 'content_notice' => array(
235 'source' => 'db-wowaddons-notice',
236 'medium' => 'summer-sale',
237 'campaign' => 'wowaddons-dashboard',
238 ),
239 'img_banner_notice' => array(
240 'source' => 'db-wowaddons-banner',
241 'medium' => 'spring-sale',
242 'campaign' => 'wowaddons-dashboard',
243 ),
244 'sub_menu' => array(
245 'source' => 'db-wowaddons-plugin',
246 'medium' => 'sub-menu',
247 'campaign' => 'wowaddons-dashboard',
248 ),
249 'plugin_meta' => array(
250 'source' => 'db-wowaddons-plugin',
251 'medium' => 'plugin-meta',
252 'campaign' => 'wowaddons-dashboard',
253 ),
254 'plugin_meta_base_price' => array(
255 'source' => 'db-wowaddons-plugin',
256 'medium' => 'base-price',
257 'campaign' => 'wowaddons-dashboard',
258 ),
259 'plugin_meta_summer_db' => array(
260 'source' => 'db-wowaddons-plugin-meta',
261 'medium' => 'summer-sale',
262 'campaign' => 'wowaddons-dashboard',
263 ),
264 'massive_sale' => array(
265 'source' => 'db-wowaddons-notice-logo',
266 'medium' => 'massive-sale',
267 'campaign' => 'wowaddons-dashboard',
268 ),
269 'flash_sale' => array(
270 'source' => 'db-wowaddons-notice',
271 'medium' => 'flash-sale',
272 'campaign' => 'wowaddons-dashboard',
273 ),
274 'summer_db' => array(
275 'source' => 'db-wowaddons-notice',
276 'medium' => 'summer-sale',
277 'campaign' => 'wowaddons-dashboard',
278 ),
279 'spring_sale' => array(
280 'source' => 'db-wowaddons-notice',
281 'medium' => 'spring-sale',
282 'campaign' => 'wowaddons-dashboard',
283 ),
284 'final_hour_sale' => array(
285 'source' => 'db-wowaddons-notice',
286 'medium' => 'final-hour-sale',
287 'campaign' => 'wowaddons-dashboard',
288 ),
289 'surprise_sale' => array(
290 'source' => 'db-wowaddons-notice-logo',
291 'medium' => 'surprise-sale',
292 'campaign' => 'wowaddons-dashboard',
293 ),
294 'exclusive_deals' => array(
295 'source' => 'db-wowaddons-notice-logo',
296 'medium' => 'exclusive-deals',
297 'campaign' => 'wowaddons-dashboard',
298 ),
299 );
300
301 // Step 1: Get parameters.
302 $base_url = $params['url'] ?? 'https://www.wpxpo.com/product/wowaddons/pricing/';
303 $utm_key = $params['utmKey'] ?? null;
304 $affiliate = $params['affiliate'] ?? apply_filters( 'prad_affiliate_id', '' );
305 $hash = $params['hash'] ?? '';
306 $custom_config = $params['config'] ?? null;
307
308 $parsed_url = wp_parse_url( $base_url );
309 $scheme = $parsed_url['scheme'] ?? 'https';
310 $host = $parsed_url['host'] ?? '';
311 $path = $parsed_url['path'] ?? '';
312 $query = array();
313
314 // Step 3: Extract existing query params if present.
315 if ( isset( $parsed_url['query'] ) ) {
316 parse_str( $parsed_url['query'], $query );
317 }
318
319 // Step 4: Determine config.
320 $utm_config = $custom_config ?? ( $utm_key && isset( $default_config[ $utm_key ] ) ? $default_config[ $utm_key ] : array() );
321
322 // Step 5: Add UTM parameters.
323 if ( ! empty( $utm_config ) ) {
324 $query = array_merge(
325 $query,
326 array(
327 'utm_source' => $utm_config['source'],
328 'utm_medium' => $utm_config['medium'],
329 'utm_campaign' => $utm_config['campaign'],
330 )
331 );
332 }
333
334 // Step 6: Add affiliate if present.
335 if ( $affiliate ) {
336 $query['ref'] = $affiliate;
337 }
338
339 // Step 7: Reconstruct URL.
340 $final_url = $scheme . '://' . $host . $path;
341
342 if ( ! empty( $query ) ) {
343 $final_url .= '?' . http_build_query( $query );
344 }
345
346 if ( $hash ) {
347 $final_url .= '#' . $hash;
348 }
349
350 return $final_url;
351 }
352
353
354 /**
355 * Get WOW Products Details
356 *
357 * @return array
358 */
359 public static function get_wow_products_details() {
360 return array(
361 'products' => array(
362 'wow_invoice' => file_exists( WP_PLUGIN_DIR . '/wow-pdf-invoices-packing-slips/wow-pdf-invoices-packing-slips.php' ),
363 'wow_shipping' => file_exists( WP_PLUGIN_DIR . '/wow-table-rate-shipping/wow-table-rate-shipping.php' ),
364 'post_x' => file_exists( WP_PLUGIN_DIR . '/ultimate-post/ultimate-post.php' ),
365 'wow_store' => file_exists( WP_PLUGIN_DIR . '/product-blocks/product-blocks.php' ),
366 'wow_optin' => file_exists( WP_PLUGIN_DIR . '/optin/optin.php' ),
367 'wow_revenue' => file_exists( WP_PLUGIN_DIR . '/revenue/revenue.php' ),
368 'wholesale_x' => file_exists( WP_PLUGIN_DIR . '/wholesalex/wholesalex.php' ),
369 'wow_addon' => file_exists( WP_PLUGIN_DIR . '/product-addons/product-addons.php' ),
370 ),
371 'products_active' => array(
372 'wow_invoice' => defined( 'WINV_VER' ),
373 'wow_shipping' => defined( 'WTRS_VER' ),
374 'post_x' => defined( 'ULTP_VER' ),
375 'wow_store' => defined( 'WOPB_VER' ),
376 'wow_optin' => defined( 'OPTN_VERSION' ),
377 'wow_revenue' => defined( 'REVENUE_VER' ),
378 'wholesale_x' => defined( 'WHOLESALEX_VER' ),
379 'wow_addon' => defined( 'PRAD_VER' ),
380 ),
381 );
382 }
383
384
385 /**
386 * Installs and activates a plugin by its name only.
387 *
388 * @param string $name The name or slug of the plugin to install and activate.
389 */
390 public static function install_and_active_plugin( $name ) {
391 $to_r = array( 'done' => true );
392 $plugin_slug = '';
393 switch ( $name ) {
394 case 'wow_invoice':
395 $plugin_slug = 'wow-pdf-invoices-packing-slips';
396 break;
397 case 'wow_shipping':
398 $plugin_slug = 'wow-table-rate-shipping';
399 break;
400 case 'post_x':
401 $plugin_slug = 'ultimate-post';
402 break;
403 case 'wow_store':
404 $plugin_slug = 'product-blocks';
405 break;
406 case 'wow_optin':
407 $plugin_slug = 'optin';
408 break;
409 case 'wow_revenue':
410 $plugin_slug = 'revenue';
411 break;
412 case 'wholesale_x':
413 $plugin_slug = 'wholesalex';
414 break;
415 case 'wow_addon':
416 $plugin_slug = 'product-addons';
417 break;
418 case 'woocommerce':
419 $plugin_slug = 'woocommerce';
420 break;
421 }
422
423 if ( ! file_exists( WP_PLUGIN_DIR . '/' . $plugin_slug . '/' . $plugin_slug . '.php' ) ) {
424 $to_r = self::plugin_install( $plugin_slug . '/' . $plugin_slug . '.php', $plugin_slug );
425 } else {
426 activate_plugin( $plugin_slug . '/' . $plugin_slug . '.php' );
427 }
428 return $to_r;
429 }
430
431 /**
432 * Installs a plugin based on the provided plugin file and slug.
433 *
434 * This function is expected to handle the logic required to install a plugin,
435 * such as downloading, unpacking, and activating the plugin using the provided
436 * plugin file and slug.
437 *
438 * @param string $plugin The plugin file path or identifier (e.g., 'plugin-directory/plugin-file.php').
439 * @param string $slug The plugin slug (typically the directory name of the plugin).
440 */
441 public static function plugin_install( $plugin, $slug ) {
442 include ABSPATH . 'wp-admin/includes/plugin-install.php';
443 include ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
444
445 if ( ! class_exists( 'Plugin_Upgrader' ) ) {
446 include ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
447 }
448 if ( ! class_exists( 'WP_Ajax_Upgrader_Skin' ) ) {
449 include ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php';
450 }
451
452 $api = plugins_api(
453 'plugin_information',
454 array(
455 'slug' => $slug,
456 'fields' => array(
457 'short_description' => false,
458 'sections' => false,
459 'requires' => false,
460 'rating' => false,
461 'ratings' => false,
462 'downloaded' => false,
463 'last_updated' => false,
464 'added' => false,
465 'tags' => false,
466 'compatibility' => false,
467 'homepage' => false,
468 'donate_link' => false,
469 ),
470 )
471 );
472
473 if ( is_wp_error( $api ) ) {
474 wp_die( $api ); //phpcs:ignore
475 }
476
477 $upgrader = new \Plugin_Upgrader( new \WP_Ajax_Upgrader_Skin( compact( 'title', 'url', 'nonce', 'plugin', 'api' ) ) );
478 $install_result = $upgrader->install( $api->download_link );
479
480 if ( ! is_wp_error( $install_result ) ) {
481 activate_plugin( $plugin );
482 return array( 'done' => false );
483 }
484
485 return array( 'done' => true );
486 }
487
488 /**
489 * Retrieve a specific item from the 'prad_settings' option.
490 *
491 * Handles both array and object formats for backward compatibility.
492 *
493 * @param string $key The key of the setting to retrieve.
494 * @param mixed $def The default value to return if the key is not found.
495 * @return mixed|null The value of the setting if found, otherwise null.
496 */
497 public static function get_prad_settings_item( $key, $def = '' ) {
498 if ( empty( $key ) ) {
499 return $def;
500 }
501
502 $prad_settings = get_option( 'prad_settings', array() );
503
504 // Handle both array and object (from REST API) formats.
505 if ( is_array( $prad_settings ) && array_key_exists( $key, $prad_settings ) ) {
506 return $prad_settings[ $key ];
507 } elseif ( is_object( $prad_settings ) && isset( $prad_settings->$key ) ) {
508 return $prad_settings->$key;
509 }
510
511 return $def;
512 }
513
514 /**
515 * Handles view permission capability for old demo and admin hooks.
516 *
517 * Applies filters for admin-only, view-only, and old demo capability checks.
518 *
519 * @param string $def Default capability (usually 'manage_options').
520 * @return string The resolved capability.
521 */
522 public static function prad_old_view_permisson_handler( $def = 'manage_woocommerce' ) {
523 $view_capability = apply_filters( 'prad_handle_capability_admin_only', $def ); // check for admin hook first.
524 $view_capability = apply_filters( 'prad_handle_capability_view_only', $view_capability ); // then check for view only hook.
525 $view_capability = apply_filters( 'prad_demo_capability_check', $view_capability ); // finally check for old demo hook for backward compatibility.
526
527 return $view_capability;
528 }
529
530 /**
531 * Handles admin permission capability for admin hooks.
532 *
533 * Applies filter for admin-only capability checks.
534 *
535 * @param string $def Default capability (usually 'manage_options').
536 * @return string The resolved capability.
537 */
538 public static function prad_manage_admin_permisson_handler( $def = 'manage_woocommerce' ) {
539 $admin_capability = apply_filters( 'prad_handle_capability_admin_only', $def ); // check for admin hook.
540
541 return $admin_capability;
542 }
543 }
544