PluginProbe
WP-Stateless – Google Cloud Storage / 3.1.1
WP-Stateless – Google Cloud Storage v3.1.1
4.4.3 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.3.0 2.3.1 2.3.2 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 All 62 releases
wp-stateless / vendor / udx / lib-ud-api-client / lib / classes / class-admin.php

class-admin.php in WP-Stateless – Google Cloud Storage 3.1.1, at vendor/udx/lib-ud-api-client/lib/classes/class-admin.php

1,073 lines 38.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Licenses Admin
4 *
5 * @namespace UsabilityDynamics
6 *
7 */
8 namespace UsabilityDynamics\UD_API {
9
10 if( !class_exists( 'UsabilityDynamics\UD_API\Admin' ) ) {
11
12 /**
13 *
14 * @author: peshkov@UD
15 */
16 class Admin extends Scaffold {
17
18 /**
19 *
20 */
21 public static $version = '1.0.0';
22
23 /**
24 *
25 */
26 private $api_url;
27
28 /**
29 * Don't ever change this, as it will mess with the data stored of which products are activated, etc.
30 *
31 */
32 private $token;
33
34 /**
35 *
36 */
37 private $api;
38
39 /**
40 *
41 */
42 public $error;
43
44 /**
45 *
46 */
47 public $ui;
48
49 /**
50 *
51 */
52 private $installed_products = array();
53
54 /**
55 *
56 */
57 private $pending_products = array();
58
59 /**
60 *
61 */
62 private $more_products = array();
63
64 /**
65 *
66 */
67 public function __construct( $args = array() ) {
68 parent::__construct( $args );
69
70 //echo "<pre>"; print_r( $args ); echo "</pre>"; die();
71
72 //** Set UD API URL. Can be defined custom one in wp-config.php */
73 $this->api_url = defined( 'UD_API_URL' ) ? trailingslashit( UD_API_URL ) : 'https://www.usabilitydynamics.com/';
74
75 //** Don't ever change this, as it will mess with the data stored of which products are activated, etc. */
76 $this->token = 'udl_' . $this->slug;
77
78 //** API */
79 $this->api = new API( array_merge( $args, array(
80 'api_url' => $this->api_url,
81 'token' => $this->token,
82 ) ) );
83
84 //** Set available screens */
85 $screens = array();
86 if( $this->type == 'theme' ) {
87 $screens =array_filter( array(
88 'licenses' => __( 'License', $this->domain ),
89 'more_products' => false,
90 ) );
91 } elseif ( $this->type == 'plugin' ) {
92 $screens =array_filter( array(
93 'licenses' => __( 'Licenses', $this->domain ),
94 'more_products' => __( 'More Products', $this->domain ),
95 ) );
96 }
97
98 //** UI */
99 $this->ui = new UI( array_merge( $args, array(
100 'token' => $this->token,
101 'screens' => $screens,
102 ) ) );
103
104 $path = wp_normalize_path( dirname( dirname( __DIR__ ) ) );
105 $this->screens_path = trailingslashit( $path . '/static/templates' );
106 if( $this->type == 'theme' && strpos( $path, wp_normalize_path( WP_PLUGIN_DIR ) ) === false ) {
107 $root_path = wp_normalize_path( get_template_directory() );
108 $this->assets_url = trailingslashit( get_template_directory_uri() . str_replace( $root_path, '', $path ) . '/static' );
109 } else {
110 $this->assets_url = trailingslashit( plugin_dir_url( dirname( dirname( __DIR__ ) ) . '/readme.md' ) . 'static' );
111 }
112
113 //** Load the updaters. */
114 add_action( 'admin_init', array( $this, 'load_updater_instances' ) );
115
116 //** Ensure keys are actually active on specific screens */
117 add_action( 'current_screen', array( $this, 'current_screen' ) );
118
119 if( $this->type == 'plugin' ) {
120 //** Check Activation Statuses */
121 add_action( 'plugins_loaded', array( $this, 'check_activation_status' ), 11 );
122 }
123 elseif( $this->type == 'theme' ) {
124 $this->check_activation_status();
125 }
126
127 //** Add Licenses page */
128 add_action( 'admin_menu', array( $this, 'register_licenses_screen' ), 999 );
129
130 //** Admin Notices Filter */
131 add_filter( 'ud:errors:admin_notices', array( $this, 'maybe_remove_notices' ) );
132 add_filter( 'ud:messages:admin_notices', array( $this, 'maybe_remove_notices' ) );
133 add_filter( 'ud:warnings:admin_notices', array( $this, 'maybe_remove_notices' ) );
134
135 /**
136 * May be add additional information about available add-ons
137 * for legacy users ( who purchased any deprecated premium feature )
138 */
139 add_action( 'ud::bootstrap::upgrade_notice::additional_info', array( $this, 'maybe_add_info_to_upgrade_notice' ), 10, 2 );
140
141 }
142
143 /**
144 * Register the admin screen.
145 *
146 * @access public
147 * @since 1.0.0
148 * @return void
149 */
150 public function register_licenses_screen () {
151 $args = $this->args;
152 $screen = !empty( $args[ 'screen' ] ) ? $args[ 'screen' ] : false;
153 $this->screen_type = !empty( $screen[ 'parent' ] ) ? 'submenu' : 'menu';
154 $this->icon_url = !empty( $screen[ 'icon_url' ] ) ? $screen[ 'icon_url' ] : '';
155 $this->position = !empty( $screen[ 'position' ] ) ? $screen[ 'position' ] : 66;
156 $this->menu_title = !empty( $screen[ 'menu_title' ] ) ? $screen[ 'menu_title' ] : __( 'Licenses', $this->domain );
157 $this->page_title = !empty( $screen[ 'page_title' ] ) ? $screen[ 'page_title' ] : __( 'Licenses', $this->domain );
158 $this->menu_slug = $this->slug . '_' . sanitize_key( $this->page_title );
159
160 switch( $this->screen_type ) {
161 case 'menu':
162 global $menu;
163 $this->hook = add_menu_page( $this->page_title, $this->menu_title, 'manage_options', $this->menu_slug, array( $this, 'settings_screen' ), $this->icon_url, $this->position );
164 break;
165 case 'submenu':
166 global $submenu;
167 $this->hook = add_submenu_page( $screen[ 'parent' ], $this->page_title, $this->menu_title, 'manage_options', $this->menu_slug, array( $this, 'settings_screen' ) );
168 break;
169 }
170
171 //** Set url for licenses page */
172 $licenses_link = isset( $screen[ 'parent' ] ) && ( strpos( $screen[ 'parent' ], '?' ) !== false || strpos( $screen[ 'parent' ], '.php' ) !== false ) ? $screen[ 'parent' ] : 'admin.php';
173 $licenses_link = add_query_arg( array(
174 'page' => $this->menu_slug,
175 ), admin_url( $licenses_link ) );
176
177 update_option( $this->token . '-url', $licenses_link );
178
179 add_action( 'load-' . $this->hook, array( $this, 'process_request' ) );
180 add_action( 'admin_print_styles-' . $this->hook, array( $this, 'enqueue_styles' ) );
181 add_action( 'admin_print_scripts-' . $this->hook, array( $this, 'enqueue_scripts' ) );
182 }
183
184 /**
185 * Ensure licenses keys are actually active on 'Installed Plugins' page
186 *
187 * @access public
188 * @since 1.0.0
189 * @return void
190 */
191 public function current_screen ( $screen ) {
192 switch( $screen->id ) {
193 case 'plugins':
194 //** Check licenses keys once per 12 hours */
195 if ( false === ( $e = get_transient( $this->token . '_ping' ) ) ) {
196 $this->ensure_keys_are_actually_active();
197 set_transient( $this->token . '_ping', time(), 12 * HOUR_IN_SECONDS );
198 }
199 break;
200 }
201 }
202
203 /**
204 * Load the main management screen.
205 *
206 * @access public
207 * @since 1.0.0
208 * @return void
209 */
210 public function settings_screen () {
211
212 $this->ui->get_header();
213
214 $screen = $this->ui->get_current_screen();
215
216 switch ( $screen ) {
217 //** Products screen. */
218 case 'more_products':
219 $this->more_products = $this->get_more_products();
220 require_once( $this->screens_path . 'screen-more.php' );
221 break;
222 //** Licenses screen. */
223 case 'licenses':
224 default:
225 $this->ensure_keys_are_actually_active();
226 $this->installed_products = $this->get_detected_products();
227 $this->pending_products = $this->get_pending_products();
228 require_once( $this->screens_path . 'screen-manage-' . $this->type . '.php' );
229 break;
230 }
231
232 $this->ui->get_footer();
233 }
234
235 /**
236 * Process the action for the admin screen.
237 * @since 1.0.0
238 * @return void
239 */
240 public function process_request () {
241
242 add_action( 'admin_notices', array( $this, 'admin_notices' ) );
243
244 $supported_actions = array( 'activate-products', 'deactivate-product' );
245 if ( !isset( $_REQUEST['action'] ) || !in_array( $_REQUEST['action'], $supported_actions ) || !check_admin_referer( 'bulk-' . 'licenses' ) ) {
246 return null;
247 }
248
249 $response = false;
250 $status = 'false';
251 $type = $_REQUEST['action'];
252
253 switch ( $type ) {
254 case 'activate-products':
255 $products = array();
256 if ( isset( $_POST[ 'products' ] ) && 0 < count( $_POST[ 'products' ] ) ) {
257 foreach ( $_POST[ 'products' ] as $k => $v ) {
258 if ( !empty( $v[ 'license_key' ] ) ) {
259 $products[$k] = $v;
260 }
261 }
262 }
263 if ( 0 < count( $products ) ) {
264 //echo "<pre>"; print_r( $products ); echo "</pre>"; die();
265 $response = $this->activate_products( $products );
266 } else {
267 $response = false;
268 $type = 'no-license-keys';
269 }
270 break;
271
272 case 'deactivate-product':
273 if ( isset( $_GET['filepath'] ) && ( '' != $_GET['filepath'] ) ) {
274 $response = $this->deactivate_product( $_GET['filepath'] );
275 }
276 break;
277
278 default:
279 break;
280 }
281
282 if ( $response == true ) {
283 $status = 'true';
284 }
285
286 $redirect_url = \UsabilityDynamics\Utility::current_url( array( 'type' => urlencode( $type ), 'status' => urlencode( $status ) ), array( 'action', 'filepath', '_wpnonce' ) );
287 wp_safe_redirect( $redirect_url );
288 exit;
289 }
290
291 /**
292 * Enqueue admin styles.
293 * @access public
294 * @since 1.0.0
295 * @return void
296 */
297 public function enqueue_styles () {
298 wp_enqueue_style( 'lib-ud-api-client-admin', esc_url( $this->assets_url . 'css/admin.css' ), array(), '1.0.0', 'all' );
299 }
300
301 /**
302 * Enqueue admin scripts.
303 *
304 * @access public
305 * @since 1.0.0
306 * @return void
307 */
308 public function enqueue_scripts () {
309 wp_enqueue_script( 'post' );
310 }
311
312 /**
313 * Run checks against the API to ensure the product keys are actually active on UsabilityDynamics. If not, deactivate them locally as well.
314 *
315 * @access public
316 * @since 1.0.0
317 * @return void
318 */
319 public function ensure_keys_are_actually_active () {
320 $already_active = (array)$this->get_activated_products();
321 $products = $this->get_detected_products();
322 if ( 0 < count( $already_active ) ) {
323 foreach ( $already_active as $k => $v ) {
324 //** Only look through activated plugins */
325 if( !array_key_exists( $k, $products ) ) {
326 continue;
327 }
328 $deactivate = true;
329
330 if ( !empty( $already_active[ $k ][2] ) ) {
331 //** Get license and activation email */
332 $data = base64_decode( $already_active[ $k ][2] );
333 $data = explode( '::', $data );
334 $license_key = isset( $data[0] ) ? trim( $data[0] ) : '';
335 $activation_email = isset( $data[1] ) ? trim( $data[1] ) : '';
336
337 //** Do request */
338 $response = $this->api->status( array(
339 'product_id' => $already_active[ $k ][0],
340 'instance' => $already_active[ $k ][1],
341 'email' => trim($activation_email),
342 'licence_key' => trim($license_key),
343 ), false, false );
344
345 //** Do not deactivate if cannot reach UD */
346 if ( $response === false ) {
347 continue;
348 }
349 if( is_array( $response ) && !empty( $response[ 'status_check' ] ) && $response[ 'status_check' ] == 'active' ) {
350 $deactivate = false;
351 }
352 }
353 if( $deactivate ) {
354 $this->deactivate_product( $k, true );
355 }
356 }
357 }
358 }
359
360 /**
361 * Activate a given array of products.
362 *
363 * @since 1.0.0
364 * @param array $products Array of products ( filepath => key )
365 * @return boolean
366 */
367 protected function activate_products ( $products ) {
368 $response = true;
369 $errors = false;
370 //** Get out if we have incorrect data. */
371 if ( !is_array( $products ) || ( 0 >= count( $products ) ) ) {
372 return false;
373 }
374 $key = $this->token . '-activated';
375 $has_update = false;
376 $already_active = $this->get_activated_products();
377 $product_keys = $this->get_detected_products();
378 foreach ( $products as $k => $v ) {
379 //echo "<pre>"; print_r( $product_keys[ $k ] ); echo "</pre>"; die();
380 if( empty( $product_keys[ $k ] ) ) {
381 continue;
382 }
383 //** Perform API "activation" request. */
384 $activate = $this->api->activate( array(
385 'product_id' => $product_keys[ $k ][ 'product_id' ],
386 'instance' => $product_keys[ $k ][ 'instance_key' ],
387 'software_version' => $product_keys[ $k ][ 'product_version' ],
388 'licence_key' => trim($v[ 'license_key' ]),
389 'email' => trim($v[ 'activation_email' ]),
390 ), $product_keys[ $k ] );
391 if ( false !== $activate && empty( $activate[ 'error' ] ) ) {
392 // key: base file, 0: product id, 1: instance_key, 2: hashed license and mail.
393 $hash = base64_encode( $v[ 'license_key' ] . '::' . $v[ 'activation_email' ] );
394 $already_active[$k] = array( $product_keys[$k]['product_id'], $product_keys[$k]['instance_key'], $hash );
395 $has_update = true;
396 } else {
397 $errors = true;
398 }
399 }
400
401 //** Store the error log. */
402 $this->api->store_error_log();
403
404 if ( $has_update && !update_option( $key, $already_active ) ) {
405 $response = false;
406 } elseif( $errors ) {
407 $response = false;
408 }
409
410 return $response;
411 }
412
413 /**
414 * Deactivate a given product key.
415 *
416 * @since 1.0.0
417 * @param string $filename File name of the to deactivate plugin licence
418 * @param bool $local_only Deactivate the product locally without pinging UsabilityDynamics.
419 * @return boolean Whether or not the deactivation was successful.
420 */
421 protected function deactivate_product ( $filename, $local_only = false ) {
422 $response = false;
423 $already_active = $this->get_activated_products();
424 $products = $this->get_detected_products();
425 if ( 0 < count( $already_active ) ) {
426 $deactivated = true;
427 if ( !empty( $products[ $filename ] ) && !empty( $already_active[ $filename ][2] ) && false == $local_only ) {
428 //** Get license and activation email */
429 $data = base64_decode( $already_active[ $filename ][2] );
430 $data = explode( '::', $data );
431 $license_key = isset( $data[0] ) ? $data[0] : '';
432 $activation_email = isset( $data[1] ) ? $data[1] : '';
433 //** Do request */
434 $deactivated = $this->api->deactivate( array(
435 'product_id' => $already_active[ $filename ][0],
436 'instance' => $already_active[ $filename ][1],
437 'email' => $activation_email,
438 'licence_key' => $license_key,
439 ), $products[ $filename ] );
440 }
441 if ( false !== $deactivated && empty( $deactivated[ 'error' ] ) ) {
442 unset( $already_active[ $filename ] );
443 $response = update_option( $this->token . '-activated', $already_active );
444 } else {
445 $this->api->store_error_log();
446 }
447 }
448 return $response;
449 }
450
451 /**
452 * Load an instance of the updater class for each activated UsabilityDynamics Product.
453 * @access public
454 * @since 1.0.0
455 * @return void
456 */
457 public function load_updater_instances () {
458 $args = $this->args;
459 $products = $this->get_detected_products();
460 $activated_products = $this->get_activated_products();
461 if ( 0 < count( $products ) ) {
462 foreach ( $products as $k => $v ) {
463 if ( isset( $v['product_id'] ) && isset( $v['instance_key'] ) ) {
464 //** Maybe Get license and activation email */
465 $api_key = '';
466 $activation_email = '';
467 if( !empty( $activated_products[ $k ][2] ) ) {
468 $data = base64_decode( $activated_products[ $k ][2] );
469 $data = explode( '::', $data );
470 $api_key = isset( $data[0] ) ? $data[0] : '';
471 $activation_email = isset( $data[1] ) ? $data[1] : '';
472 }
473 //echo "<pre>"; print_r( $v ); echo "</pre>"; //die();
474 if( !empty( $api_key ) ) {
475 new Update_Checker( array(
476 'type' => $this->type,
477 'upgrade_url' => $this->api_url,
478 'name' => $v[ 'product_name' ],
479 'file' => $v[ 'product_file_path' ],
480 'product_id' => $v[ 'product_id' ],
481 'api_key' => $api_key,
482 'activation_email' => $activation_email,
483 'renew_license_url' => trailingslashit( $this->api_url ) . 'account',
484 'instance' => $v[ 'instance_key' ],
485 'software_version' => $v[ 'product_version' ],
486 'text_domain' => $this->domain,
487 'changelog' => ( isset( $args[ 'changelog' ] ) ? $args[ 'changelog' ] : false ),
488 ), $v[ 'errors_callback' ] );
489 }
490 }
491 }
492 }
493 }
494
495 /**
496 * Detect which products have been activated.
497 *
498 * @access public
499 * @since 1.0.0
500 * @return void
501 */
502 protected function get_activated_products () {
503 $response = array();
504 $response = get_option( $this->token . '-activated', array() );
505 if ( ! is_array( $response ) ) $response = array();
506 return $response;
507 }
508
509 /**
510 * Wrapper for get detected theme or plugins.
511 *
512 * @access public
513 * @since 1.0.0
514 * @return void
515 */
516 protected function get_detected_products () {
517 if ( $this->type == 'theme' ) {
518 return $this->get_detected_theme();
519 } elseif ( $this->type == 'plugin' ) {
520 return $this->get_detected_plugins();
521 } else {
522 return array();
523 }
524 }
525
526 /**
527 * Get a list of UsabilityDynamics plugins found on this installation.
528 *
529 * @access public
530 * @since 1.0.0
531 * @return void
532 */
533 protected function get_detected_plugins () {
534 //** Check if get_plugins() function exists */
535 if ( ! function_exists( 'get_plugins' ) ) {
536 require_once ABSPATH . 'wp-admin/includes/plugin.php';
537 }
538 $response = array();
539 $products = get_plugins();
540 if ( is_array( $products ) && ( 0 < count( $products ) ) ) {
541 $reference_list = $this->get_product_reference_list();
542 //echo "<pre>"; print_r( $reference_list ); echo "</pre>"; die();
543 $activated_products = $this->get_activated_products();
544 if ( is_array( $reference_list ) && ( 0 < count( $reference_list ) ) ) {
545 foreach ( $products as $k => $v ) {
546 if ( in_array( $k, array_keys( $reference_list ) ) ) {
547 $status = 'inactive';
548 if ( in_array( $k, array_keys( $activated_products ) ) ) {
549 $status = 'active';
550 }
551 $response[$k] = array(
552 'product_name' => $v['Name'],
553 'product_version' => $v['Version'],
554 'instance_key' => $reference_list[$k]['instance_key'],
555 'product_id' => $reference_list[$k]['product_id'],
556 'product_status' => $status,
557 'product_file_path' => $k,
558 'errors_callback' => isset( $reference_list[$k]['errors_callback'] ) ? $reference_list[$k]['errors_callback'] : false,
559 );
560 }
561 }
562 }
563 }
564 return $response;
565 }
566
567 /**
568 * Get detected theme.
569 *
570 * @access public
571 * @since 1.0.0
572 * @return void
573 */
574 protected function get_detected_theme () {
575 $response = array();
576 $reference_list = $this->get_product_reference_list();
577 $activated_products = $this->get_activated_products();
578 if ( is_array( $reference_list ) && ( 0 < count( $reference_list ) ) ) {
579 $boot_path = wp_normalize_path( get_template_directory() ) . '/style.css';
580 $product = isset( $reference_list[ $boot_path ] ) ? $reference_list[ $boot_path ] : false;
581 if ( $product ) {
582 $status = 'inactive';
583 if ( isset( $activated_products[ $boot_path ] ) ) {
584 $status = 'active';
585 }
586 $response[ $boot_path ] = array(
587 'product_name' => $this->name,
588 'product_version' => $this->args[ 'version' ],
589 'instance_key' => $product['instance_key'],
590 'product_id' => $product['product_id'],
591 'product_status' => $status,
592 'product_file_path' => $boot_path,
593 'errors_callback' => isset( $product['errors_callback'] ) ? $product['errors_callback'] : false,
594 );
595 }
596 }
597 //echo "<pre>"; print_r( $response ); echo "</pre>"; die();
598 return $response;
599 }
600
601 /**
602 * Get a list of UsabilityDynamics plugins or themes which are available for purchasing and downloading.
603 *
604 * @since 1.0.0
605 * @return mixed
606 */
607 protected function get_more_products() {
608 $more_products = array();
609 $trnst = get_transient( $this->token . "-more-a" );
610 //** If we do not have cache ( transient ), do request to get the list of all available products */
611 if( !$trnst || !is_array( $trnst ) ) {
612 $target_url = $this->api_url . 'products.json';
613 $request = wp_remote_get( $target_url, array( 'sslverify' => false ) );
614 if( is_wp_error( $request ) || wp_remote_retrieve_response_code( $request ) != 200 ) {
615 $this->error = $request;
616 return $more_products;
617 } else {
618 $response = wp_remote_retrieve_body( $request );
619 $response = @json_decode( $response, true );
620 if( empty( $response ) || !is_array( $response ) ) {
621 return $more_products;
622 } else {
623 $locale = get_locale();
624 $products = !empty( $response[ $locale ][ 'products' ] ) ?
625 $response[ $locale ][ 'products' ] : ( !empty( $response[ 'en_US' ][ 'products' ] ) ? $response[ 'en_US' ][ 'products' ] : false );
626 if( empty( $products ) || !is_array( $products ) ) {
627 return $more_products;
628 }
629 foreach( $products as $product ) {
630 $product = wp_parse_args( $product, array(
631 'name' => '',
632 'description' => '',
633 'icon' => '',
634 'url' => '',
635 'type' => 'plugin',
636 'product_id' => '',
637 'referrer' => false,
638 'requires' => false,
639 'tested' => false,
640 'order' => 10,
641 ) );
642 if( !empty( $product[ 'referrer' ] ) ) {
643 $product[ 'referrer' ] = !is_array( $product[ 'referrer' ] ) ? explode( ',', $product[ 'referrer' ] ) : $product[ 'referrer' ];
644 if( in_array( $this->slug, $product[ 'referrer' ] ) ) {
645 $more_products[] = $product;
646 }
647 }
648 }
649 //** Sort the list */
650 usort($more_products, function( $a,$b ) {
651 if ( $a['order'] == $b['order'] ) {
652 return 0;
653 }
654 return ( $a['order'] < $b['order'] ) ? -1 : 1;
655 });
656 //** Set transient for one day */
657 set_transient( $this->token . "-more", $more_products, (60 * 60 * 24) );
658 }
659 }
660 } else {
661 $more_products = $trnst;
662 }
663
664 //** Determine if plugin from the list is already installed and activated */
665 //** There is not check condition for 'theme' */
666 if( !empty( $more_products ) ) {
667 $reference_list = $this->get_product_reference_list();
668 foreach( $more_products as $k => $product ) {
669 if( $this->slug == $product[ 'product_id' ] ) {
670 unset( $more_products[ $k ] );
671 continue;
672 }
673 if( !empty( $reference_list ) && is_array( $reference_list ) ) {
674 foreach( $reference_list as $reference ) {
675 if( $reference[ 'product_id' ] == $product[ 'product_id' ] ) {
676 unset( $more_products[ $k ] );
677 }
678 }
679 }
680 }
681 }
682 //echo "<pre>"; print_r( $more_products ); echo "</pre>"; die();
683 return $more_products;
684 }
685
686 /**
687 * Get a list of products from UsabilityDynamics.
688 *
689 * @access public
690 * @since 1.0.0
691 * @return void
692 */
693 protected function get_product_reference_list () {
694 global $_ud_license_updater;
695 //echo "<pre>"; print_r( $_ud_license_updater ); echo "</pre>"; die();
696 $response = array();
697 if(
698 isset( $_ud_license_updater[ $this->slug ] )
699 && is_callable( array( $_ud_license_updater[ $this->slug ], 'get_products' ) )
700 ) {
701 $response = $_ud_license_updater[ $this->slug ]->get_products();
702 }
703 return $response;
704 }
705
706 /**
707 * Get an array of products that haven't yet been activated.
708 *
709 * @access public
710 * @since 1.0.0
711 * @return array Products awaiting activation.
712 */
713 protected function get_pending_products () {
714 $response = array();
715 $products = $this->installed_products;
716 if ( is_array( $products ) && ( 0 < count( $products ) ) ) {
717 $activated_products = $this->get_activated_products();
718 if ( is_array( $activated_products ) && ( 0 <= count( $activated_products ) ) ) {
719 foreach ( $products as $k => $v ) {
720 if ( !in_array( $k, array_keys( $activated_products ) ) ) {
721 $response[$k] = array( 'product_name' => $v['product_name'] );
722 }
723 }
724 }
725 }
726 //echo "<pre>"; print_r( $response ); echo "</pre>"; die();
727 return $response;
728 }
729
730 /**
731 * Determine, if there are licenses that are not yet activated.
732 * @access public
733 * @since 1.0.0
734 * @return void
735 */
736 public function check_activation_status () {
737 $licenses_link = get_option( $this->token . '-url', '' );
738 //echo "<pre>"; print_r( $this ); echo "</pre>"; die();
739 $products = $this->get_detected_products();
740 //echo "<pre>"; print_r( $products ); echo "</pre>"; die();
741 $messages = array();
742 if ( 0 < count( $products ) ) {
743 foreach ( $products as $k => $v ) {
744 if ( isset( $v['product_status'] ) && 'inactive' == $v['product_status'] ) {
745 if( !empty( $licenses_link ) ) {
746 $message = sprintf( __( '%s License is not active. To get started, activate it <a href="%s">here</a>.', $this->domain ), $v['product_name'], $licenses_link );
747 } else {
748 $message = sprintf( __( '%s License is not active.', $this->domain ), $v['product_name'] );
749 }
750 if( !empty( $v[ 'errors_callback' ] ) && is_callable( $v[ 'errors_callback' ] ) ) {
751 call_user_func_array( $v[ 'errors_callback' ], array( $message, 'warning' ) );
752 } else {
753 $messages[] = $message;
754 }
755 }
756 }
757 }
758 if( !empty( $messages ) ) {
759 $this->messages = $messages;
760 }
761
762 /**
763 * We also ping UD server once per 24h
764 * for getting any specific information.
765 */
766 $this->maybe_ping_ud();
767 }
768
769 /**
770 * Remove specific plugins notices from licenses page
771 *
772 * @param $notices
773 * @author peshkov@UD
774 */
775 public function maybe_remove_notices( $notices ) {
776 global $current_screen;
777 if( $current_screen->id == $this->hook ) {
778 $notices = array();
779 }
780 return $notices;
781 }
782
783 /**
784 * Admin notices
785 */
786 public function admin_notices() {
787
788 //** Step 1. Look for default messages */
789 $messages = $this->messages;
790 if( !empty( $messages ) && is_array( $messages ) ) {
791 foreach( $messages as $message ) {
792 echo '<div class="error fade"><p>' . $message . '</p></div>';
793 }
794 }
795
796 //** Step 2. Look for status messages */
797 $message = '';
798 $response = '';
799
800 if ( isset( $_GET['status'] ) && in_array( $_GET['status'], array( 'true', 'false' ) ) && isset( $_GET['type'] ) ) {
801 $classes = array( 'true' => 'updated', 'false' => 'error' );
802 $request_errors = $this->api->get_error_log();
803
804 //echo "<pre>"; var_dump( $request_errors ); echo "</pre>"; die();
805
806 switch ( $_GET['type'] ) {
807 case 'no-license-keys':
808 $message = __( 'No license keys were specified for activation.', $this->domain );
809 break;
810
811 case 'deactivate-product':
812 if ( 'true' == $_GET['status'] && empty( $request_errors ) ) {
813 if( $this->type == 'theme' ) {
814 $message = __( 'Theme deactivated successfully.', $this->domain );
815 } else {
816 $message = __( 'Product deactivated successfully.', $this->domain );
817 }
818 } else {
819 $message = __( 'There was an error while deactivating the product.', $this->domain );
820 }
821 break;
822
823 default:
824 if ( 'true' == $_GET['status'] && empty( $request_errors ) ) {
825 if( $this->type == 'theme' ) {
826 $message = __( 'Theme activated successfully.', $this->domain );
827 } else {
828 $message = __( 'Products activated successfully.', $this->domain );
829 }
830 } else {
831 if( $this->type == 'theme' ) {
832 $message = __( 'There was an error and theme was not activated.', $this->domain );
833 } else {
834 $message = __( 'There was an error and not all products were activated.', $this->domain );
835 }
836 }
837 break;
838 }
839
840 $response = '<div class="' . esc_attr( $classes[$_GET['status']] ) . ' fade">' . "\n";
841 $response .= wpautop( $message );
842 $response .= '</div>' . "\n";
843
844 // Cater for API request error logs.
845 if ( is_array( $request_errors ) && ( 0 < count( $request_errors ) ) ) {
846 $message = '';
847
848 foreach ( $request_errors as $k => $v ) {
849 $message .= wpautop( $v );
850 }
851
852 $response .= '<div class="error fade">' . "\n";
853 $response .= make_clickable( $message );
854 $response .= '</div>' . "\n";
855
856 // Clear the error log.
857 $this->api->clear_error_log();
858 }
859
860 if ( '' != $response ) {
861 echo $response;
862 }
863 }
864
865 }
866
867 /**
868 * May be add additional information about available add-ons
869 * for legacy users ( who purchased any deprecated premium feature )
870 * to Product's Upgrade Notice
871 *
872 * @param string $referrer
873 * @param array $vars
874 */
875 public function maybe_add_info_to_upgrade_notice( $referrer, $vars ) {
876 if( $referrer->slug != $this->referrer_slug ) {
877 return;
878 }
879
880 $transient = sanitize_key( 'ud_legacy_features_' . $this->slug );
881 $response = get_transient( $transient );
882
883 if ( false === $response || empty( $response ) ) {
884
885 $detected_products = array();
886
887 foreach( $this->get_detected_plugins() as $product ) {
888 $detected_products[ $product[ 'product_id' ] ] = array(
889 'version' => $product[ 'product_version' ],
890 'status' => $product[ 'product_status' ],
891 'product_id' => $product[ 'product_id' ],
892 );
893 }
894
895 $response = $this->api->upgrade_notice( apply_filters( 'ud:upgrade_notice:request:args', array(
896 'product_id' => $this->slug,
897 'version' => $this->args[ 'version' ],
898 'detected_products' => base64_encode( json_encode( $detected_products ) ),
899 ), $this->slug ) );
900
901 if ( false !== $response && empty( $response[ 'error' ] ) ) {
902 set_transient( $transient, json_encode($response), HOUR_IN_SECONDS );
903 }
904
905 } else {
906 $response = json_decode( $response, true );
907 }
908
909 if ( false !== $response && empty( $response[ 'error' ] ) && !empty( $response[ 'message' ] ) ) {
910 $message = @base64_decode( $response[ 'message' ] );
911 echo apply_filters( 'ud::upgrade_notice::response::admin_notice', $message, $this->slug, $response );
912 }
913 }
914
915 /**
916 * Ping UD server once per 24h to get any specific information.
917 *
918 * Maybe render Admin Notice from UD server.
919 *
920 */
921 private function maybe_ping_ud() {
922
923 /**
924 * May be dismiss notice from UD server
925 */
926 if( !empty( $_REQUEST[ 'dismiss_ud_notice' ] ) ) {
927 $notices = get_option( 'dismissed_ud_notices' );
928 if( !is_array( $notices ) ) {
929 $notices = array();
930 }
931 array_push( $notices, $_REQUEST[ 'dismiss_ud_notice' ] );
932 $notices = array_unique( $notices );
933 update_option( 'dismissed_ud_notices', $notices );
934 if( !empty( $_SERVER[ 'HTTP_REFERER' ] ) ) {
935 wp_redirect( $_SERVER[ 'HTTP_REFERER' ] );
936 } else {
937 wp_redirect( admin_url( 'index.php' ) );
938 }
939 exit;
940 }
941
942 $cache = true;
943
944 $option = sanitize_key( 'ud_ping_' . sanitize_key( $this->slug ) );
945 $response = get_option( $option );
946
947 if (
948 false === $response ||
949 empty( $response ) ||
950 empty( $response[ 'time' ] ) ||
951 ( time() - $response[ 'time' ] ) >= DAY_IN_SECONDS
952 ) {
953
954 $cache = false;
955
956 $detected_products = array();
957
958 foreach( $this->get_detected_plugins() as $product ) {
959 $detected_products[ $product[ 'product_id' ] ] = array(
960 'version' => $product[ 'product_version' ],
961 'status' => $product[ 'product_status' ],
962 'product_id' => $product[ 'product_id' ],
963 );
964 }
965
966 $response = $this->api->ping( apply_filters('ud-api-client-ping-args', array(
967 'product_id' => $this->slug,
968 'version' => $this->args[ 'version' ],
969 'detected_products' => base64_encode( json_encode( $detected_products ) ),
970 ), $this, $detected_products));
971
972 if ( false !== $response && empty( $response[ 'error' ] ) ) {
973 update_option( 'ud_ping_' . sanitize_key( $this->slug ), array(
974 'time' => time(),
975 'data' => $response
976 ) );
977 }
978
979 } else {
980 if( empty( $response[ 'data' ] ) ) {
981 return;
982 }
983 $response = $response[ 'data' ];
984 }
985
986 if ( false !== $response && empty( $response[ 'error' ] ) ) {
987
988 /**
989 * Here we can take care about response.
990 *
991 * @param string $this->slug ( product_id )
992 * @param array $response
993 * @param bool $cache got from cache or not
994 */
995 $this->ping_response = apply_filters( 'ud::ping::response', $response, $this->slug, $cache );
996
997 /**
998 * Render Admin Notice from UD server.
999 */
1000 if( !empty( $this->ping_response[ 'message' ] ) ) {
1001 global $_ud_ping_notices;
1002
1003 if( !isset( $_ud_ping_notices ) || !is_array( $_ud_ping_notices ) ) {
1004 $_ud_ping_notices = array();
1005 }
1006
1007 $notice = $this->ping_response[ 'message' ];
1008
1009 /** Determine if user has permissions to see plugin notices */
1010 if ( ! function_exists( 'wp_get_current_user' ) ) {
1011 require_once( ABSPATH . 'wp-includes/pluggable.php' );
1012 }
1013 if( !current_user_can( 'activate_plugins' ) ) {
1014 return;
1015 }
1016
1017 /** Determine if notice dismissed */
1018 $dismissed = get_option( 'dismissed_ud_notices' );
1019 $dismissed = is_array( $dismissed ) ? $dismissed : array();
1020 if( in_array( md5( $notice ), $dismissed ) ) {
1021 return;
1022 }
1023
1024 if( in_array( $notice, $_ud_ping_notices ) ) {
1025 return;
1026 }
1027
1028 array_push( $_ud_ping_notices, $this->ping_response[ 'message' ] );
1029
1030 if( !has_action( 'admin_notices', array( __CLASS__, 'ping_admin_notices' ) ) ) {
1031 add_action( 'admin_notices', array( __CLASS__, 'ping_admin_notices' ) );
1032 add_filter( 'ud::ping::response::admin_notice::icon', array( $this, 'get_admin_notice_icon' ) );
1033 }
1034
1035 }
1036
1037 }
1038
1039 }
1040
1041 public function get_admin_notice_icon() {
1042 return $this->assets_url . 'images/ud.png';
1043 }
1044
1045 /**
1046 * Render Notices from UD server
1047 *
1048 */
1049 static public function ping_admin_notices() {
1050 global $_ud_ping_notices;
1051
1052 if( !isset( $_ud_ping_notices ) || !is_array( $_ud_ping_notices ) ) {
1053 return;
1054 }
1055
1056 foreach( array_unique( $_ud_ping_notices ) as $notice ) {
1057 $dismiss_url = admin_url( 'index.php' ) . '?dismiss_ud_notice=' . md5( $notice );
1058 $notice = @base64_decode( $notice );
1059 $notice = apply_filters( 'ud::ping::response::admin_notice', $notice );
1060 if( !empty( $notice ) ) {
1061 $icon = apply_filters( 'ud::ping::response::admin_notice::icon', false );
1062 require( dirname( dirname( __DIR__ ) ) . '/static/templates/admin-notice.php' );
1063 }
1064 }
1065
1066 }
1067
1068 }
1069
1070 }
1071
1072 }
1073