PluginProbe
Post Grid Gutenberg Blocks – PostX / 5.1.1
Post Grid Gutenberg Blocks – PostX v5.1.1
5.1.1 5.1.0 5.0.41 5.0.39 5.0.38 5.0.37 5.0.36 5.0.35 5.0.34 5.0.33 5.0.32 5.0.31 5.0.30 5.0.29 5.0.28 5.0.27 5.0.26 5.0.25 5.0.23 5.0.24 5.0.22 5.0.21 5.0.20 5.0.19 5.0.18 All 240 releases
ultimate-post / includes / durbin / class-xpo.php

class-xpo.php in Post Grid Gutenberg Blocks – PostX 5.1.1, at includes/durbin/class-xpo.php

559 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 namespace ULTP\Includes\Durbin;
4
5 defined( 'ABSPATH' ) || exit;
6
7 /**
8 * Core class for managing plugin actions and integrations.
9 */
10 class Xpo {
11
12 /**
13 * Gets license key
14 *
15 * PostX Pro answers through the `ultp_license_key` filter.
16 *
17 * @return string
18 */
19 public static function get_lc_key() {
20 if ( has_filter( 'ultp_license_key' ) ) {
21 $key = apply_filters( 'ultp_license_key', '' );
22 return is_string( $key ) ? $key : '';
23 }
24 if ( self::is_pro_before_1_9_0() ) {
25 return get_option( 'edd_ultp_license_key', '' );
26 }
27 return '';
28 }
29
30 /**
31 * Checks if the license is active.
32 *
33 * PostX Pro answers through the `ultp_license_active` filter.
34 *
35 * @return bool
36 */
37 public static function is_lc_active() {
38 if ( has_filter( 'ultp_license_active' ) ) {
39 return true === apply_filters( 'ultp_license_active', false );
40 }
41 if ( self::is_pro_before_1_9_0() ) {
42 $license_data = get_option( 'edd_ultp_license_data', array() );
43 return isset( $license_data['license'] ) && 'valid' === $license_data['license'];
44 }
45 return false;
46 }
47
48 /**
49 * Checks if PostX Pro is a version before 1.9.0.
50 *
51 * Those versions hook none of the filters PostX now asks PostX Pro through (the
52 * `ultp_license_*` ones, `ultp_template_request_body`, `ultp_seo_meta_excerpt`),
53 * so PostX still does that work itself for them.
54 *
55 * @return bool
56 */
57 public static function is_pro_before_1_9_0() {
58 return defined( 'ULTP_PRO_VER' ) && version_compare( ULTP_PRO_VER, '1.9.0', '<' );
59 }
60
61 /**
62 * Checks if the license has expired.
63 *
64 * PostX Pro answers through the `ultp_license_expired` filter.
65 *
66 * @return bool True if the license is expired, otherwise false.
67 */
68 public static function is_lc_expired() {
69 if ( has_filter( 'ultp_license_expired' ) ) {
70 return true === apply_filters( 'ultp_license_expired', false );
71 }
72 if ( self::is_pro_before_1_9_0() ) {
73 $license_data = get_option( 'edd_ultp_license_data', array() );
74 return isset( $license_data['license'] ) && 'expired' === $license_data['license'];
75 }
76 return false;
77 }
78
79 /**
80 * Get Option Value bypassing cache
81 * Inspired By WordPress Core get_option
82 *
83 * @since v.1.0.7
84 * @param string $option Option Name.
85 * @param boolean $default_value option default value.
86 * @return mixed
87 */
88 public static function get_option_without_cache( $option, $default_value = false ) {
89 global $wpdb;
90
91 if ( is_scalar( $option ) ) {
92 $option = trim( $option );
93 }
94
95 if ( empty( $option ) ) {
96 return false;
97 }
98
99 $value = $default_value;
100
101 $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
102
103 if ( is_object( $row ) ) {
104 $value = $row->option_value;
105 } else {
106 return apply_filters( "ultp_default_option_{$option}", $default_value, $option );
107 }
108
109 return apply_filters( "ultp_option_{$option}", maybe_unserialize( $value ), $option );
110 }
111
112 /**
113 * Add option without adding to the cache
114 * Inspired By WordPress Core set_transient
115 *
116 * @since v.1.0.7
117 * @param string $option option name.
118 * @param string $value option value.
119 * @param string $autoload whether to load WordPress startup.
120 * @return bool
121 */
122 public static function add_option_without_cache( $option, $value = '', $autoload = 'yes' ) {
123 global $wpdb;
124
125 if ( is_scalar( $option ) ) {
126 $option = trim( $option );
127 }
128
129 if ( empty( $option ) ) {
130 return false;
131 }
132
133 wp_protect_special_option( $option );
134
135 if ( is_object( $value ) ) {
136 $value = clone $value;
137 }
138
139 $value = sanitize_option( $option, $value );
140
141 /*
142 * Make sure the option doesn't already exist.
143 */
144
145 if ( apply_filters( "ultp_default_option_{$option}", false, $option, false ) !== self::get_option_without_cache( $option ) ) {
146 return false;
147 }
148
149 $serialized_value = maybe_serialize( $value );
150 $autoload = ( 'no' === $autoload || false === $autoload ) ? 'no' : 'yes';
151
152 $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
153 if ( ! $result ) {
154 return false;
155 }
156
157 return true;
158 }
159
160 /**
161 * Get Transient Value bypassing cache
162 * Inspired By WordPress Core get_transient
163 *
164 * @since v.1.0.7
165 * @param string $transient Transient Name.
166 * @return mixed
167 */
168 public static function get_transient_without_cache( $transient ) {
169 $transient_option = '_transient_' . $transient;
170 $transient_timeout = '_transient_timeout_' . $transient;
171 $timeout = self::get_option_without_cache( $transient_timeout );
172
173 if ( false !== $timeout && $timeout < time() ) {
174 delete_option( $transient_option );
175 delete_option( $transient_timeout );
176 $value = false;
177 }
178
179 if ( ! isset( $value ) ) {
180 $value = self::get_option_without_cache( $transient_option );
181 }
182
183 return apply_filters( "ultp_transient_{$transient}", $value, $transient );
184 }
185
186 /**
187 * Set transient without adding to the cache
188 * Inspired By WordPress Core set_transient
189 *
190 * @since v.1.0.7
191 * @param string $transient Transient Name.
192 * @param mixed $value Transient Value.
193 * @param integer $expiration Time until expiration in seconds.
194 * @return bool
195 */
196 public static function set_transient_without_cache( $transient, $value, $expiration = 0 ) {
197
198 $expiration = (int) $expiration;
199
200 $transient_timeout = '_transient_timeout_' . $transient;
201 $transient_option = '_transient_' . $transient;
202
203 $result = false;
204
205 if ( false === self::get_option_without_cache( $transient_option ) ) {
206 $autoload = 'yes';
207 if ( $expiration ) {
208 $autoload = 'no';
209 self::add_option_without_cache( $transient_timeout, time() + $expiration, 'no' );
210 }
211 $result = self::add_option_without_cache( $transient_option, $value, $autoload );
212 } else {
213 /*
214 * If expiration is requested, but the transient has no timeout option,
215 * delete, then re-create transient rather than update.
216 */
217 $update = true;
218
219 if ( $expiration ) {
220 if ( false === self::get_option_without_cache( $transient_timeout ) ) {
221 delete_option( $transient_option );
222 self::add_option_without_cache( $transient_timeout, time() + $expiration, 'no' );
223 $result = self::add_option_without_cache( $transient_option, $value, 'no' );
224 $update = false;
225 } else {
226 update_option( $transient_timeout, time() + $expiration );
227 }
228 }
229
230 if ( $update ) {
231 $result = update_option( $transient_option, $value );
232 }
233 }
234
235 return $result;
236 }
237
238 public static function generate_utm_link( $params = array() ) {
239 $default_config = array(
240 'example' => array(
241 'source' => 'db-postx-featurename',
242 'medium' => 'block-feature',
243 'campaign' => 'postx-dashboard',
244 ),
245 'summer_db' => array(
246 'source' => 'db-postx-notice',
247 'medium' => 'summer-sale',
248 'campaign' => 'postx-dashboard',
249 ),
250 'birthday' => array(
251 'source' => 'db-postx-notice',
252 'medium' => 'birthday',
253 'campaign' => 'postx-dashboard',
254 ),
255 'plugin_dir_pro' => array(
256 'source' => 'db-postx-plugin',
257 'medium' => 'upgrade-pro',
258 'campaign' => 'postx-dashboard',
259 ),
260 'post_type_page' => array(
261 'source' => 'db-postx-posttype',
262 'medium' => 'upgrade-pro',
263 'campaign' => 'postx-dashboard',
264 ),
265 'plugin_dir_support' => array(
266 'source' => 'db-postx-pluginmeta',
267 'medium' => 'meta-support',
268 'campaign' => 'postx-dashboard',
269 ),
270 'dashboard_go_pro' => array(
271 'source' => 'db-postx-submenu',
272 'medium' => 'left-menu-upgrade',
273 'campaign' => 'postx-dashboard',
274 ),
275 'sub_menu' => array(
276 'source' => 'db-postx-submenu',
277 'medium' => 'upgrade-pro',
278 'campaign' => 'postx-dashboard',
279 ),
280 'content_notice' => array(
281 'source' => 'db-postx-notice',
282 'medium' => 'spring-sale',
283 'campaign' => 'postx-dashboard',
284 ),
285 'summer_sale_meta' => array(
286 'source' => 'db-postx-plugin-meta',
287 'medium' => 'summer-sale',
288 'campaign' => 'postx-dashboard',
289 ),
290 'base_price_meta' => array(
291 'source' => 'db-postx-plugin-meta',
292 'medium' => 'base-price',
293 'campaign' => 'postx-dashboard',
294 ),
295
296 // Flash sale.
297 'flash_sale_content' => array(
298 'source' => 'db-postx-notice-content',
299 'medium' => 'summer-flash-sale',
300 'campaign' => 'postx-dashboard',
301 ),
302 'flash_sale' => array(
303 'source' => 'db-postx-notice',
304 'medium' => 'summer-flash-sale',
305 'campaign' => 'postx-dashboard',
306 ),
307 'flash_sale_meta' => array(
308 'source' => 'db-postx-plugin-meta',
309 'medium' => 'summer-flash-sale',
310 'campaign' => 'postx-dashboard',
311 ),
312 // Massive Sale
313 'massive_sale_content' => array(
314 'source' => 'db-postx-notice-content',
315 'medium' => 'summer-massive-sale',
316 'campaign' => 'postx-dashboard',
317 ),
318 'massive_sale' => array(
319 'source' => 'db-postx-notice',
320 'medium' => 'summer-massive-sale',
321 'campaign' => 'postx-dashboard',
322 ),
323 'massive_sale_meta' => array(
324 'source' => 'db-postx-plugin-meta',
325 'medium' => 'summer-massive-sale',
326 'campaign' => 'postx-dashboard',
327 ),
328 // Surprise Sale
329 'surprise_sale_content' => array(
330 'source' => 'db-postx-notice-content',
331 'medium' => 'summer-surprise-sale',
332 'campaign' => 'postx-dashboard',
333 ),
334 'surprise_sale' => array(
335 'source' => 'db-postx-notice',
336 'medium' => 'summer-surprise-sale',
337 'campaign' => 'postx-dashboard',
338 ),
339 'surprise_sale_meta' => array(
340 'source' => 'db-postx-plugin-meta',
341 'medium' => 'summer-surprise-sale',
342 'campaign' => 'postx-dashboard',
343 ),
344 // Final Hours Sale
345 'final_hours_content' => array(
346 'source' => 'db-postx-notice-content',
347 'medium' => 'summer-final-sale',
348 'campaign' => 'postx-dashboard',
349 ),
350 'final_hour' => array(
351 'source' => 'db-postx-notice',
352 'medium' => 'summer-final-sale',
353 'campaign' => 'postx-dashboard',
354 ),
355 'final_hour_meta' => array(
356 'source' => 'db-postx-plugin-meta',
357 'medium' => 'summer-final-sale',
358 'campaign' => 'postx-dashboard',
359 ),
360 );
361
362 // Step 1: Get parameters
363 $base_url = $params['url'] ?? 'https://www.wpxpo.com/postx/';
364 $utm_key = $params['utmKey'] ?? null;
365 $affiliate = $params['affiliate'] ?? apply_filters( 'ultp_affiliate_id', '' );
366 $hash = $params['hash'] ?? 'pricing';
367 $custom_config = $params['config'] ?? null;
368
369 $parsed_url = wp_parse_url( $base_url );
370 $scheme = $parsed_url['scheme'] ?? 'https';
371 $host = $parsed_url['host'] ?? '';
372 $path = $parsed_url['path'] ?? '';
373 $query = array();
374
375 // Step 3: Extract existing query params if present
376 if ( isset( $parsed_url['query'] ) ) {
377 parse_str( $parsed_url['query'], $query );
378 }
379
380 // Step 4: Determine config
381 $utm_config = $custom_config ?? ( $utm_key && isset( $default_config[ $utm_key ] ) ? $default_config[ $utm_key ] : array() );
382
383 // Step 5: Add UTM parameters
384 if ( ! empty( $utm_config ) ) {
385 $query = array_merge(
386 $query,
387 array(
388 'utm_source' => $utm_config['source'],
389 'utm_medium' => $utm_config['medium'],
390 'utm_campaign' => $utm_config['campaign'],
391 )
392 );
393 }
394
395 // Step 6: Add affiliate if present
396 if ( $affiliate ) {
397 $query['ref'] = $affiliate;
398 }
399
400 // Step 7: Reconstruct URL
401 $final_url = $scheme . '://' . $host . $path;
402
403 if ( ! empty( $query ) ) {
404 $final_url .= '?' . http_build_query( $query );
405 }
406
407 if ( $hash ) {
408 $final_url .= '#' . $hash;
409 }
410
411 return $final_url;
412 }
413
414
415 /**
416 * Get WOW Products Details
417 *
418 * @return array
419 */
420 public static function get_wow_products_details() {
421 return array(
422 'products' => array(
423 'wow_shipping' => file_exists( WP_PLUGIN_DIR . '/wow-table-rate-shipping/wow-table-rate-shipping.php' ),
424 'post_x' => file_exists( WP_PLUGIN_DIR . '/ultimate-post/ultimate-post.php' ),
425 'wow_store' => file_exists( WP_PLUGIN_DIR . '/product-blocks/product-blocks.php' ),
426 'wow_optin' => file_exists( WP_PLUGIN_DIR . '/optin/optin.php' ),
427 'wow_revenue' => file_exists( WP_PLUGIN_DIR . '/revenue/revenue.php' ),
428 'wholesale_x' => file_exists( WP_PLUGIN_DIR . '/wholesalex/wholesalex.php' ),
429 'wow_addon' => file_exists( WP_PLUGIN_DIR . '/product-addons/product-addons.php' ),
430 'wow_invoice' => file_exists( WP_PLUGIN_DIR . '/wow-pdf-invoices-packing-slips/wow-pdf-invoices-packing-slips.php' ),
431 'wow_recommend' => file_exists( WP_PLUGIN_DIR . '/wow-ai-product-recommendations/wow-ai-product-recommendations.php' ),
432 ),
433 'products_active' => array(
434 'wow_shipping' => defined( 'WTRS_VER' ),
435 'post_x' => defined( 'ULTP_VER' ),
436 'wow_store' => defined( 'WOPB_VER' ),
437 'wow_optin' => defined( 'OPTN_VERSION' ),
438 'wow_revenue' => defined( 'REVENUE_VER' ),
439 'wholesale_x' => defined( 'WHOLESALEX_VER' ),
440 'wow_addon' => defined( 'PRAD_VER' ),
441 'wow_invoice' => defined( 'WINV_VER' ),
442 'wow_recommend' => defined( 'PRECO_VER' ),
443 ),
444 );
445 }
446
447
448 /**
449 * Installs and activates a plugin by its name only.
450 *
451 * @param string $name The name or slug of the plugin to install and activate.
452 */
453 public static function install_and_active_plugin( $name ) {
454 $to_r = array( 'done' => true );
455 $plugin_slug = '';
456 switch ( $name ) {
457 case 'wow_shipping':
458 $plugin_slug = 'wow-table-rate-shipping';
459 break;
460 case 'post_x':
461 $plugin_slug = 'ultimate-post';
462 break;
463 case 'wow_store':
464 $plugin_slug = 'product-blocks';
465 break;
466 case 'wow_optin':
467 $plugin_slug = 'optin';
468 break;
469 case 'wow_revenue':
470 $plugin_slug = 'revenue';
471 break;
472 case 'wholesale_x':
473 $plugin_slug = 'wholesalex';
474 break;
475 case 'wow_addon':
476 $plugin_slug = 'product-addons';
477 break;
478 case 'woocommerce':
479 $plugin_slug = 'woocommerce';
480 break;
481 case 'wow_invoice':
482 $plugin_slug = 'wow-pdf-invoices-packing-slips';
483 $active_url = admin_url( 'admin.php?page=winv-dashboard#overview' );
484 break;
485 case 'wow_recommend':
486 $plugin_slug = 'wow-ai-product-recommendations';
487 break;
488 }
489
490 if ( ! file_exists( WP_PLUGIN_DIR . '/' . $plugin_slug . '/' . $plugin_slug . '.php' ) ) {
491 $to_r = self::plugin_install( $plugin_slug . '/' . $plugin_slug . '.php', $plugin_slug );
492 } else {
493 activate_plugin( $plugin_slug . '/' . $plugin_slug . '.php' );
494 }
495 return $to_r;
496 }
497
498 /**
499 * Installs a plugin based on the provided plugin file and slug.
500 *
501 * This function is expected to handle the logic required to install a plugin,
502 * such as downloading, unpacking, and activating the plugin using the provided
503 * plugin file and slug.
504 *
505 * @param string $plugin The plugin file path or identifier (e.g., 'plugin-directory/plugin-file.php').
506 * @param string $slug The plugin slug (typically the directory name of the plugin).
507 */
508 public static function plugin_install( $plugin, $slug ) {
509 include ABSPATH . 'wp-admin/includes/plugin-install.php';
510 include ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
511
512 if ( ! class_exists( 'Plugin_Upgrader' ) ) {
513 include ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
514 }
515 if ( ! class_exists( 'WP_Ajax_Upgrader_Skin' ) ) {
516 include ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php';
517 }
518
519 $api = plugins_api(
520 'plugin_information',
521 array(
522 'slug' => $slug,
523 'fields' => array(
524 'short_description' => false,
525 'sections' => false,
526 'requires' => false,
527 'rating' => false,
528 'ratings' => false,
529 'downloaded' => false,
530 'last_updated' => false,
531 'added' => false,
532 'tags' => false,
533 'compatibility' => false,
534 'homepage' => false,
535 'donate_link' => false,
536 ),
537 )
538 );
539
540 if ( is_wp_error( $api ) ) {
541 wp_die( esc_html( $api->get_error_message() ) );
542 }
543 $title = '';
544 $url = '';
545 $nonce = '';
546 $upgrader = new \Plugin_Upgrader( new \WP_Ajax_Upgrader_Skin( compact( 'title', 'url', 'nonce', 'plugin', 'api' ) ) );
547 $install_result = $upgrader->install( $api->download_link );
548
549 if ( ! is_wp_error( $install_result ) ) {
550 activate_plugin( $plugin );
551 return array(
552 'done' => false,
553 );
554 }
555
556 return array( 'done' => true );
557 }
558 }
559