Changeset 2146523
- Timestamp:
- 08/27/2019 06:28:54 PM (7 years ago)
- Location:
- pluginpass-pro-plugintheme-licensing/trunk
- Files:
-
- 5 added
- 14 edited
-
README.txt (modified) (2 diffs)
-
composer.json (modified) (2 diffs)
-
composer.lock (modified) (1 diff)
-
constants.php (modified) (1 diff)
-
docker-compose.yml (modified) (1 diff)
-
docs (added)
-
docs/PluginPass-overview.graphml (added)
-
examples (added)
-
examples/class-pluginpass-demo-settings.php (added)
-
inc/admin/class-pluginpass-admin.php (modified) (1 diff)
-
inc/admin/class-pluginpass-table.php (modified) (21 diffs)
-
inc/admin/js/pluginpass-admin.js (modified) (1 diff)
-
inc/admin/js/sweetalert2.all.min.js (added)
-
inc/admin/views/partials-pluginpass-validation-details.php (modified) (2 diffs)
-
inc/common/class-pluginpass-guard.php (modified) (7 diffs)
-
inc/common/traits/class-pluginpass-plugable.php (modified) (4 diffs)
-
inc/common/traits/class-pluginpass-validatable.php (modified) (2 diffs)
-
inc/core/class-activator.php (modified) (3 diffs)
-
pluginpass.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
pluginpass-pro-plugintheme-licensing/trunk/README.txt
r2137441 r2146523 8 8 Tested up to: 5.2.2 9 9 Requires PHP: 5.6 10 Stable tag: 0.9. 210 Stable tag: 0.9.3 11 11 License: GPLv2 or later 12 12 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 135 135 == Changelog == 136 136 137 = 0.9.3 = 138 * New: User consent before validation #13 139 * New: Add deregister plugin function #15 140 * Fix: Column "Expiration Date" used wrongly #18 141 * Update: Verify / implement / fix licensee / license deactivation roundtrip #17 142 * Update: How To: Describe plugin usage #4 143 * New: Install & activate PluginPass as dependency #2 144 * Update: Force validate #3 145 * Update: Bulk validate plugins error #11 146 * Fix: HTTP 4xx/5xx handling #7 147 * Update: Optimize DB table structure #10 148 * Update: Validation response output variables #9 149 137 150 = 0.9.2 = 138 151 * Update: Plugin documentation -
pluginpass-pro-plugintheme-licensing/trunk/composer.json
r2137166 r2146523 23 23 "monetize" 24 24 ], 25 "homepage": "https://wordpress.org/plugins/pluginpass /",25 "homepage": "https://wordpress.org/plugins/pluginpass-pro-plugintheme-licensing/", 26 26 "license": "GPL-2.0", 27 27 "authors": [ … … 36 36 "issues": "https://github.com/Labs64/PluginPass/issues", 37 37 "source": "https://github.com/Labs64/PluginPass", 38 "docs": "https:// wordpress.org/plugins/pluginpass/faq/"38 "docs": "https://github.com/Labs64/PluginPass/wiki" 39 39 }, 40 40 "require": { -
pluginpass-pro-plugintheme-licensing/trunk/composer.lock
r2137166 r2146523 5 5 "This file is @generated automatically" 6 6 ], 7 "hash": " a890e6ee8bf1b1036a0af6d786b2e26f",7 "hash": "f22cc9d3d1c567a5e1ad00f10d5b0453", 8 8 "content-hash": "7236f443f9d2d77b9b6f186c5f89be9c", 9 9 "packages": [ -
pluginpass-pro-plugintheme-licensing/trunk/constants.php
r2137441 r2146523 8 8 define( __NAMESPACE__ . '\NS', __NAMESPACE__ . '\\' ); 9 9 10 define( NS . 'PLUGIN_VERSION', '0.9. 2' );10 define( NS . 'PLUGIN_VERSION', '0.9.3' ); 11 11 12 12 define( NS . 'PLUGIN_NAME', 'pluginpass' ); -
pluginpass-pro-plugintheme-licensing/trunk/docker-compose.yml
r2137166 r2146523 28 28 volumes: 29 29 - ".:/var/www/html/wp-content/plugins/pluginpass" 30 - "./data/ testplugin:/var/www/html/wp-content/plugins/testplugin"30 - "./data/pluginpass-demo:/var/www/html/wp-content/plugins/pluginpass-demo" 31 31 phpmyadmin: 32 32 image: phpmyadmin/phpmyadmin -
pluginpass-pro-plugintheme-licensing/trunk/inc/admin/class-pluginpass-admin.php
r2137166 r2146523 83 83 public function enqueue_scripts() { 84 84 $params = array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ); 85 wp_enqueue_script( 'sweetalert2', plugin_dir_url( __FILE__ ) . 'js/sweetalert2.all.min.js', array( 'jquery' ), $this->version, false ); 85 86 wp_enqueue_script( 'pluginpass_ajax_handle', plugin_dir_url( __FILE__ ) . 'js/pluginpass-admin.js', array( 'jquery' ), $this->version, false ); 86 87 wp_localize_script( 'pluginpass_ajax_handle', 'params', $params ); -
pluginpass-pro-plugintheme-licensing/trunk/inc/admin/class-pluginpass-table.php
r2137441 r2146523 4 4 5 5 use NetLicensing\Constants; 6 use NetLicensing\NetLicensingService; 7 use NetLicensing\RestException; 6 8 use PluginPass\Inc\Common\Traits\PluginPass_Plugable; 7 9 use PluginPass\Inc\Common\Traits\PluginPass_Validatable; … … 75 77 $page = $this->get_pagenum() - 1; 76 78 $per_page = $this->get_items_per_page( 'plugins_per_page' ); 77 $order_by = ( isset( $_GET['orderby'] ) ) ? esc_sql( $_GET['orderby'] ) : ' name';79 $order_by = ( isset( $_GET['orderby'] ) ) ? esc_sql( $_GET['orderby'] ) : 'expires_ttl_at'; 78 80 $order = ( isset( $_GET['order'] ) ) ? esc_sql( $_GET['order'] ) : 'ASC'; 79 81 … … 106 108 $table_columns = array( 107 109 'cb' => '<input type="checkbox" />', // to display the checkbox. 108 ' name'=> __( 'Plugin Name', $this->plugin_text_domain ),110 'plugin_name' => __( 'Plugin Name', $this->plugin_text_domain ), 109 111 'expires_at' => _x( 'Expiration Date', 'column name', $this->plugin_text_domain ), 110 112 'validated_at' => __( 'Last Validated', $this->plugin_text_domain ), … … 136 138 */ 137 139 $sortable_columns = array( 138 'name' => 'name', 139 'expires_at' => 'expires_at', 140 'validated_at' => 'last_validated', 140 'validated_at' => 'validated_at', 141 141 ); 142 142 … … 163 163 */ 164 164 165 public function fetch_table_data( $page, $per_page, $order_by = ' name', $order = 'ASC', $search_key = null ) {165 public function fetch_table_data( $page, $per_page, $order_by = 'plugin_name', $order = 'ASC', $search_key = null ) { 166 166 global $wpdb; 167 167 … … 172 172 173 173 if ( $search_key ) { 174 $query .= " WHERE name LIKE '$search_key'";175 $countQuery .= " WHERE name LIKE '$search_key'";174 $query .= " WHERE plugin_name LIKE '$search_key'"; 175 $countQuery .= " WHERE plugin_name LIKE '$search_key'"; 176 176 } 177 177 … … 179 179 180 180 // query output_type will be an associative array with ARRAY_A. 181 $ items= $wpdb->get_results( $query, ARRAY_A );181 $plugins = $wpdb->get_results( $query, ARRAY_A ); 182 182 $total_items = $wpdb->get_row( $countQuery )->total_items; 183 183 184 foreach ( $items as &$item ) { 185 $item['validation'] = json_decode( $item['validation'], true ); 184 $items = []; 185 186 foreach ( $plugins as $plugin ) { 187 if ( array_key_exists( $plugin['plugin_folder'], get_plugins() ) ) { 188 $plugin['validation_result'] = json_decode( $plugin['validation_result'], true ); 189 190 $items[] = $plugin; 191 } 186 192 } 187 193 … … 213 219 protected function column_cb( $item ) { 214 220 return sprintf( 215 '<label class="screen-reader-text" for="plugins_' . $item['ID'] . '">' . sprintf( __( 'Select %s' ), $item['name']) . '</label>'221 '<label class="screen-reader-text" for="plugins_' . $item['ID'] . '">' . sprintf( __( 'Select %s', $this->plugin_text_domain ), $this->get_plugin_name( $item['plugin_folder'] ) ) . '</label>' 216 222 . "<input type='checkbox' name='plugins[]' id='plugins_{$item['ID']}' value='{$item['ID']}' />" 217 223 ); … … 233 239 * @return string 234 240 */ 235 protected function column_ name( $item ) {241 protected function column_plugin_name( $item ) { 236 242 /* 237 243 * Build table row actions. … … 250 256 ); 251 257 258 $class = empty( $item['consented_at'] ) ? 'need-consent-before-validation' : ''; 259 252 260 $validate_plugin_link = esc_url( add_query_arg( $query_args_validate_plugin, $admin_page_url ) ); 253 $actions['validate_plugin'] = '<a href="' . $validate_plugin_link . '">' . __( 'Validate', $this->plugin_text_domain ) . '</a>'; 254 255 // row actions to show validation details 256 $query_args_validation_details = array( 261 $actions['validate_plugin'] = '<a class="' . $class . '" href="' . $validate_plugin_link . '">' . __( 'Validate', $this->plugin_text_domain ) . '</a>'; 262 263 if ( ! empty( $item['validated_at'] ) ) { 264 // row actions to show validation details 265 $query_args_validation_details = array( 266 'page' => wp_unslash( $_REQUEST['page'] ), 267 'action' => 'validation_details', 268 'plugin_id' => absint( $item['ID'] ), 269 '_wpnonce' => wp_create_nonce( 'validation_details_nonce' ), 270 ); 271 $validation_details_link = esc_url( add_query_arg( $query_args_validation_details, $admin_page_url ) ); 272 $actions['validation_details'] = '<a href="' . $validation_details_link . '">' . __( 'Details', $this->plugin_text_domain ) . '</a>'; 273 } 274 275 // row actions to deregister plugin 276 $query_args_deregister_plugin = array( 257 277 'page' => wp_unslash( $_REQUEST['page'] ), 258 'action' => ' validation_details',278 'action' => 'deregister_plugin', 259 279 'plugin_id' => absint( $item['ID'] ), 260 '_wpnonce' => wp_create_nonce( ' validation_details_nonce' ),280 '_wpnonce' => wp_create_nonce( 'deregister_plugin_nonce' ), 261 281 ); 262 $validation_details_link = esc_url( add_query_arg( $query_args_validation_details, $admin_page_url ) ); 263 $actions['validation_details'] = '<a href="' . $validation_details_link . '">' . __( 'Details', $this->plugin_text_domain ) . '</a>'; 264 265 // row actions to deregister plugin 266 // $query_args_deregister_plugin = array( 267 // 'page' => wp_unslash($_REQUEST['page']), 268 // 'action' => 'deregister_plugin', 269 // 'plugin_id' => absint($item['ID']), 270 // '_wpnonce' => wp_create_nonce('deregister_plugin_nonce'), 271 // ); 272 // $deregister_plugin_link = esc_url(add_query_arg($query_args_deregister_plugin, $admin_page_url)); 273 // $actions['deregister_plugin'] = '<a href="' . $deregister_plugin_link . '">' . __('Deregister', $this->plugin_text_domain) . '</a>'; 274 275 276 $row_value = '<strong>' . $item['name'] . '</strong>'; 282 $deregister_plugin_link = esc_url( add_query_arg( $query_args_deregister_plugin, $admin_page_url ) ); 283 $actions['deregister_plugin'] = '<a class="need-deregister-confirmation" href="' . $deregister_plugin_link . '">' . __( 'Deregister', $this->plugin_text_domain ) . '</a>'; 284 $row_value = '<strong>' . $this->get_plugin_name( $item['plugin_folder'] ) . '</strong>'; 277 285 278 286 return $row_value . $this->row_actions( $actions ); 287 } 288 289 protected function column_expires_at( $item ) { 290 $expires_at = ''; 291 292 if ( ! empty( $item['validation_result'] ) ) { 293 foreach ( $item['validation_result'] as $result ) { 294 if ( ! empty( $result['expires'] ) ) { 295 if ( ! $expires_at || strtotime( $result['expires'] ) < strtotime( $expires_at ) ) { 296 $expires_at = $result['expires']; 297 } 298 } 299 } 300 } 301 302 return ( $expires_at ) ? date( 'Y-m-d H:i:s', strtotime( $expires_at ) ) : ''; 279 303 } 280 304 … … 295 319 $invalid = 0; 296 320 297 foreach ( $item['validation'] as $product_module => $results ) { 298 $licensing_model = $results['licensingModel']; 299 300 if ( $licensing_model === Constants::LICENSING_MODEL_MULTI_FEATURE ) { 301 foreach ( $results as $key => $result ) { 302 if ( is_array( $result ) ) { 303 if ( PluginPass_Dot::get( $result, '0.valid' ) === 'true' ) { 304 $valid ++; 305 } else { 306 $invalid ++; 321 if ( ! empty( $item['validation_result'] ) ) { 322 foreach ( $item['validation_result'] as $product_module => $results ) { 323 $licensing_model = $results['licensingModel']; 324 325 if ( $licensing_model === Constants::LICENSING_MODEL_MULTI_FEATURE ) { 326 foreach ( $results as $key => $result ) { 327 if ( is_array( $result ) ) { 328 if ( PluginPass_Dot::get( $result, '0.valid' ) === 'true' ) { 329 $valid ++; 330 } else { 331 $invalid ++; 332 } 307 333 } 308 334 } 309 }310 } else {311 if ( $results['valid'] === 'true' ) {312 $valid ++;313 335 } else { 314 $invalid ++; 315 } 316 } 317 } 318 336 if ( $results['valid'] === 'true' ) { 337 $valid ++; 338 } else { 339 $invalid ++; 340 } 341 } 342 } 343 } 344 345 if ( ! $item['validated_at'] ) { 346 return '<span class="label label-danger">' . __( 'run validation first', $this->plugin_text_domain ) . '</span>'; 347 } 319 348 320 349 if ( $valid > 0 && $invalid === 0 ) { 321 return '<span class="label label-primary">' . __( 'valid' ) . '</span>';350 return '<span class="label label-primary">' . __( 'valid', $this->plugin_text_domain ) . '</span>'; 322 351 } 323 352 324 353 if ( $invalid > 0 && $valid === 0 ) { 325 return '<span class="label label-danger">' . __( 'invalid' ) . '</span>';326 } 327 328 return '<span class="label label-warning">' . $valid . '/' . $invalid . ' ' . __( 'valid') . '</span>';354 return '<span class="label label-danger">' . __( 'invalid', $this->plugin_text_domain ) . '</span>'; 355 } 356 357 return '<span class="label label-warning">' . sprintf( __( '%s valid', $this->plugin_text_domain ), $valid . '/' . $invalid ) . '</span>'; 329 358 } 330 359 … … 347 376 */ 348 377 $actions = array( 349 'bulk-validate' => 'Validate Plugins',350 //'bulk-deregister' => 'Deregister Plugins'378 'bulk-validate' => 'Validate Plugins', 379 'bulk-deregister' => 'Deregister Plugins' 351 380 ); 352 381 … … 399 428 $this->invalid_nonce_redirect(); 400 429 } else { 401 $this->deregister_plugin( absint( $_REQUEST['user_id'] ) ); 402 $this->graceful_exit(); 430 $this->deregister_plugin( absint( $_REQUEST['plugin_id'] ) ); 403 431 } 404 432 } … … 418 446 } else { 419 447 $this->bulk_validate( $_REQUEST['plugins'] ); 420 $this->graceful_exit();421 448 } 422 449 } … … 435 462 } else { 436 463 $this->bulk_deregister( $_REQUEST['plugins'] ); 437 $this->graceful_exit();438 464 } 439 465 } … … 449 475 */ 450 476 public function validate_plugin( $plugin_id ) { 451 try { 452 // get plugin 453 $plugin = $this->get_plugin( [ 'ID' => $plugin_id ] ); 454 455 if ( ! $plugin ) { 456 throw new Exception( __( 'Plugin not found' ) ); 457 } 458 459 $result = self::validate( $plugin->api_key, $plugin->number ); 460 461 /** @var $ttl DateTime */ 462 $ttl = $result->getTtl(); 463 $expires_at = $ttl->format( DATE_ATOM ); 464 $validation = json_encode( $result->getValidations() ); 465 466 $this->update_plugin( [ 467 'expires_at' => $expires_at, 468 'validation' => $validation 469 ], [ 'ID' => $plugin_id ] ); 470 471 $this->show_notice( __( 'Plugin(-s) have been validated', $this->plugin_text_domain ), 'success', true ); 472 } catch ( Exception $exception ) { 473 $this->show_notice( $exception->getMessage(), 'error', true ); 474 } 477 $this->bulk_validate( [ $plugin_id ] ); 475 478 } 476 479 … … 489 492 490 493 if ( ! $plugin ) { 491 throw new Exception( __( 'Plugin not found' ) ); 492 } 494 throw new Exception( __( 'Plugin not found', $this->plugin_text_domain ) ); 495 } 496 497 $plugin_name = $this->get_plugin_name( $plugin->plugin_folder ); 493 498 494 499 $validation_details = []; 495 500 496 foreach ($plugin->validation as $data ) { 497 if ( $data['licensingModel'] === Constants::LICENSING_MODEL_MULTI_FEATURE ) { 498 foreach ( $data as $features ) { 499 if ( is_array( $features ) ) { 500 $feature = reset( $features ); 501 $validation_details[ $feature['featureName'] ] = $feature['valid'] === 'true'; 501 if ( ! empty( $plugin->validation_result ) ) { 502 foreach ( $plugin->validation_result as $data ) { 503 if ( $data['licensingModel'] === Constants::LICENSING_MODEL_MULTI_FEATURE ) { 504 foreach ( $data as $features ) { 505 if ( is_array( $features ) ) { 506 $feature = reset( $features ); 507 $validation_details[ $feature['featureName'] ] = $feature['valid'] === 'true'; 508 } 502 509 } 510 511 continue; 503 512 } 504 513 505 continue; 506 } 507 508 $validation_details[ $data['productModuleName'] ] = $data['valid'] === 'true'; 514 $validation_details[ $data['productModuleName'] ] = $data['valid'] === 'true'; 515 } 509 516 } 510 517 … … 525 532 */ 526 533 public function deregister_plugin( $plugin_id ) { 527 // TODO: degeregister plugin534 $this->bulk_deregister( [ $plugin_id ] ); 528 535 } 529 536 … … 531 538 * Bulk validate plugins. 532 539 * 533 * @param array $bulk_plugin_ids534 * 535 * @ since 1.0.0536 * 540 * @param $plugin_ids 541 * 542 * @throws \ErrorException 543 * @since 1.0.0 537 544 */ 538 545 public function bulk_validate( $plugin_ids ) { 539 // TODO: bulk plugin validate 546 $errors = []; 547 548 $count = 0; 549 550 $has_consent = ! empty( $_GET['has_consent'] ) ? true : false; 551 552 $plugins = $this->get_plugins( [ 'ID' => $plugin_ids ] ); 553 554 foreach ( $plugin_ids as $plugin_id ) { 555 // get plugin 556 $plugin = isset( $plugins[ $plugin_id ] ) ? $plugins[ $plugin_id ] : null; 557 558 try { 559 if ( ! $plugin ) { 560 throw new Exception( sprintf( __( 'Plugin not found', $this->plugin_text_domain ) ) ); 561 } 562 563 if ( empty( $plugin->consented_at ) && ! $has_consent ) { 564 continue; 565 } 566 567 $result = self::validate( $plugin->api_key, $plugin->product_number ); 568 569 /** @var $ttl DateTime */ 570 $ttl = $result->getTtl(); 571 $expires_ttl_at = $ttl->format( DATE_ATOM ); 572 $validation = json_encode( $result->getValidations() ); 573 574 $data = [ 575 'expires_ttl_at' => $expires_ttl_at, 576 'validated_at' => date( DATE_ATOM ), 577 'validation_result' => $validation, 578 ]; 579 580 if ( empty( $plugin->consented_at ) ) { 581 $data['consented_at'] = date( DATE_ATOM ); 582 } 583 584 $this->update_plugin( $data, [ 'ID' => $plugin_id ] ); 585 586 $count ++; 587 } catch ( RestException $rest_exception ) { 588 $request = NetLicensingService::getInstance()->lastCurlInfo(); 589 590 if ( $request->httpStatusCode === 401 ) { 591 $errors[] = sprintf( __( 'Failed to validate the plugin %s, please contact the plugin developer.', $this->plugin_text_domain ), $this->get_plugin_name( $plugin->plugin_folder ) ); 592 } else { 593 $errors[] = $rest_exception->getMessage(); 594 } 595 } catch ( Exception $exception ) { 596 $errors[] = $exception->getMessage(); 597 } 598 } 599 600 if ( ! empty( $errors ) ) { 601 foreach ( $errors as $error ) { 602 $this->show_notice( $error, 'error', true ); 603 } 604 } 605 606 if ( $count > 0 ) { 607 $this->show_notice( $count . __( ' plugin(s) have been validated', $this->plugin_text_domain ), 'success', true ); 608 } 540 609 } 541 610 … … 543 612 * Bulk deregister plugins. 544 613 * 545 * @param array $bulk_plugin_ids 546 * 547 * @since 1.0.0 548 * 614 * @param $plugin_ids 549 615 */ 550 616 public function bulk_deregister( $plugin_ids ) { 551 // TODO: bulk deregister plugin 617 $errors = []; 618 619 $count = 0; 620 621 $plugins = $this->get_plugins( [ 'ID' => $plugin_ids ] ); 622 623 foreach ( $plugin_ids as $plugin_id ) { 624 // get plugin 625 $plugin = isset( $plugins[ $plugin_id ] ) ? $plugins[ $plugin_id ] : null; 626 627 try { 628 if ( ! $plugin ) { 629 throw new Exception( sprintf( __( 'Plugin not found', $this->plugin_text_domain ) ) ); 630 } 631 632 $this->delete_plugin( [ 'ID' => $plugin_id ] ); 633 634 $count ++; 635 } catch ( Exception $exception ) { 636 $errors[] = $exception->getMessage(); 637 } 638 } 639 640 if ( ! empty( $errors ) ) { 641 foreach ( $errors as $error ) { 642 $this->show_notice( $error, 'error', true ); 643 } 644 } 645 646 if ( $count > 0 ) { 647 $this->show_notice( $count . __( ' plugin(s) have been deregistered', $this->plugin_text_domain ), 'success', true ); 648 } 552 649 } 553 650 … … 588 685 </div>"; 589 686 } 687 688 protected function get_plugin_name( $plugin_folder, $default = '' ) { 689 return isset( get_plugins()[ $plugin_folder ]['Name'] ) ? get_plugins()[ $plugin_folder ]['Name'] : $default; 690 } 590 691 } -
pluginpass-pro-plugintheme-licensing/trunk/inc/admin/js/pluginpass-admin.js
r2137166 r2146523 1 (function ( $) {2 'use strict';1 (function ($) { 2 'use strict'; 3 3 4 /**5 * All of the code for your admin-facing JavaScript source6 * should reside in this file.7 *8 * Note: It has been assumed you will write jQuery code here, so the9 * $ function reference has been prepared for usage within the scope10 * of this function.11 *12 * This enables you to define handlers, for when the DOM is ready:13 *14 * $(function() {15 *16 * });17 *18 * When the window is loaded:19 *20 * $( window ).load(function() {21 *22 * });23 *24 * ...and/or other possibilities.25 *26 * Ideally, it is not considered best practise to attach more than a27 * single DOM-ready or window-load handler for a particular page.28 * Although scripts in the WordPress core, Plugins and Themes may be29 * practising this, we should strive to set a better example in our own work.30 *31 * The file is enqueued from inc/admin/class-admin.php.32 */4 /** 5 * All of the code for your admin-facing JavaScript source 6 * should reside in this file. 7 * 8 * Note: It has been assumed you will write jQuery code here, so the 9 * $ function reference has been prepared for usage within the scope 10 * of this function. 11 * 12 * This enables you to define handlers, for when the DOM is ready: 13 * 14 * $(function() { 15 * 16 * }); 17 * 18 * When the window is loaded: 19 * 20 * $( window ).load(function() { 21 * 22 * }); 23 * 24 * ...and/or other possibilities. 25 * 26 * Ideally, it is not considered best practise to attach more than a 27 * single DOM-ready or window-load handler for a particular page. 28 * Although scripts in the WordPress core, Plugins and Themes may be 29 * practising this, we should strive to set a better example in our own work. 30 * 31 * The file is enqueued from inc/admin/class-admin.php. 32 */ 33 33 34 })( jQuery ); 34 $(function () { 35 $('.need-consent-before-validation').on('click', function (e) { 36 e.preventDefault(); 37 38 var href = $(e.target).attr('href'); 39 40 var text = 'By choosing "Agree" validation request will be sent to the Labs64 NetLicensing ' + 41 'to verify valid use of the plugin or theme.<br/>' + 42 'Personal data transferred with this request such as Unique Identifiers, Plugin and Theme Details, ' + 43 'WordPress Instance Name, Domain Name, System Details of the data subject.<br/><br/>' + 44 'For more details on Labs64 NetLicensing data protection provisions visit ' + 45 '<a target="_blank" href="https://www.labs64.com/legal/privacy-policy">Privacy Policy</a>' + 46 ' and <a target="_blank" href="https://www.labs64.de/confluence/x/vQEKAQ">Privacy Center</a>'; 47 48 Swal.fire({ 49 html: text, 50 type: 'warning', 51 showCancelButton: true, 52 confirmButtonText: 'Agree', 53 cancelButtonText: 'Cancel' 54 }).then((result) => { 55 if (result.value) { 56 window.location.href = href + '&has_consent=true'; 57 } 58 }) 59 }); 60 61 $('.need-deregister-confirmation').on('click', function (e) { 62 e.preventDefault(); 63 64 var href = $(e.target).attr('href'); 65 66 Swal.fire({ 67 title:'Are you sure?', 68 html: 'You won\'t be able to revert this!', 69 type: 'warning', 70 showCancelButton: true, 71 confirmButtonText: 'Deregister', 72 cancelButtonText: 'Cancel' 73 }).then((result) => { 74 if (result.value) { 75 window.location.href = href; 76 } 77 }) 78 }); 79 80 }); 81 })(jQuery); -
pluginpass-pro-plugintheme-licensing/trunk/inc/admin/views/partials-pluginpass-validation-details.php
r2137166 r2146523 7 7 8 8 <div class="wrap"> 9 <h2> <?php echo __( 'Plugin validation details for "' . $plugin->name . '"', $this->plugin_text_domain ); ?> </h2>9 <h2> <?php echo __( 'Plugin validation details for "' . $plugin_name . '"', $this->plugin_text_domain ); ?> </h2> 10 10 11 11 <div class="pluginpass-card"> 12 <ul class="list-group clear-list"> 13 <?php foreach ( $validation_details as $name => $valid ): ?> 14 <li class="list-group-item"> 15 <span><?php echo $name; ?></span> 12 <?php if ( ! $plugin->validated_at ): ?> 13 <?php _e( 'Please go back and run validation first', $this->plugin_text_domain ) ?> 14 <?php else: ?> 15 <?php if ( ! empty( $validation_details ) ): ?> 16 <ul class="list-group clear-list"> 17 <?php foreach ( $validation_details as $name => $valid ): ?> 18 <li class="list-group-item"> 19 <span><?php echo $name; ?></span> 16 20 17 <span class="float-right">21 <span class="float-right"> 18 22 19 23 <?php if ( $valid ): ?> … … 23 27 <?php endif; ?> 24 28 </span> 25 </li> 26 <?php endforeach; ?> 27 </ul> 29 </li> 30 <?php endforeach; ?> 31 </ul> 32 <?php else: ?> 33 <?php _e( 'No results', $this->plugin_text_domain ) ?> 34 <?php endif; ?> 35 <?php endif; ?> 28 36 </div> 29 37 30 <a href="<?php echo esc_url( add_query_arg( array( 'page' => wp_unslash( $_REQUEST['page'] ) ) , admin_url( 'options-general.php' ) ) ); ?>">31 <?php _e( 'Back', $this->plugin_text_domain ) ?>38 <a href="<?php echo esc_url( add_query_arg( array( 'page' => wp_unslash( $_REQUEST['page'] ) ), admin_url( 'options-general.php' ) ) ); ?>"> 39 <?php _e( 'Back', $this->plugin_text_domain ) ?> 32 40 </a 33 41 </div> -
pluginpass-pro-plugintheme-licensing/trunk/inc/common/class-pluginpass-guard.php
r2137441 r2146523 12 12 class PluginPass_Guard { 13 13 use PluginPass_Validatable { 14 validate as restValidate;14 validate as protected restValidate; 15 15 } 16 16 use PluginPass_Plugable; … … 18 18 protected $plugin; 19 19 20 protected $has_consent = false; 21 20 22 /** 21 23 * Initialize and register plugin. 22 24 * 25 * @param string $api_key NetLicensing APIKey. 26 * @param string $product_number NetLicensing product number. 27 * @param string $plugin_folder Relative path to single plugin folder. 28 * @param boolean $has_consent Indicate whether the author of the plugin has the user's consent to the use his personal data. 29 * 30 * @throws \Exception 23 31 * @since 1.0.0 24 32 * @access public 25 * @param string $api_key NetLicensing APIKey.26 * @param string $product_number NetLicensing product number.27 * @param string $plugin_name The plugin name.28 *29 * @throws \Exception30 33 */ 31 public function __construct( $api_key, $product_number, $plugin_name ) { 32 $this->plugin = $this->get_plugin( [ 'number' => $product_number ] ); 34 public function __construct( $api_key, $product_number, $plugin_folder, $has_consent = false ) { 35 if ( ! array_key_exists( $plugin_folder, get_plugins() ) ) { 36 throw new \Exception( 'Plugin on path "' . $plugin_folder . '" not found' ); 37 } 33 38 34 if ( $this->is_plugin_not_exits_or_validation_expired() ) { 35 /** @var $result ValidationResults*/ 36 $result = self::restValidate( $api_key, $product_number ); 39 $this->plugin = $this->get_plugin( [ 'product_number' => $product_number ] ); 40 $this->has_consent = $has_consent; 37 41 38 /** @var $ttl \DateTime */ 39 $ttl = $result->getTtl(); 40 $expires_at = $ttl->format( \DateTime::ATOM ); 41 $validation_result = json_encode( $result->getValidations() ); 42 $data = [ 43 'product_number' => $product_number, 44 'plugin_folder' => $plugin_folder, 45 'api_key' => $api_key, 46 ]; 42 47 43 $data = [ 44 'number' => $product_number, 45 'name' => $plugin_name, 46 'api_key' => $api_key, 47 'expires_at' => $expires_at, 48 'validation' => $validation_result, 49 ]; 48 $this->plugin = ( ! $this->plugin ) 49 ? $this->create_plugin( $data ) 50 : $this->update_plugin( $data, [ 'product_number' => $product_number ] ); 51 } 50 52 51 $this->plugin = ( ! $this->plugin ) 52 ? $this->create_plugin( $data ) 53 : $this->update_plugin( $data, [ 'number' => $product_number ] ); 54 } 53 /** 54 * Indicate whether the author of the plugin has the user's consent to the use his personal data. 55 * @return bool 56 */ 57 public function has_consent() { 58 return ( ! empty( $this->plugin->consented_at ) || $this->has_consent ); 55 59 } 56 60 … … 58 62 * Validate plugin feature for the current wordpress instance. 59 63 * 64 * @param string $feature The plugin feature to be checked. 65 * 66 * @return boolean The status, whether this feature is available. 67 * @throws \Exception 60 68 * @since 1.0.0 61 69 * @access public 62 * @param string $feature The plugin feature to be checked.63 * @return boolean The status, whether this feature is available.64 70 */ 65 71 public function validate( $feature ) { 66 72 67 if ( ! PluginPass_Dot::has( $this->plugin->validation, $feature) ) {73 if ( ! $this->has_consent() ) { 68 74 return false; 69 75 } 70 76 71 $feature_parsed = explode( '.', $feature ); 72 $product_module = reset( $feature_parsed); 73 $licensingModel = PluginPass_Dot::get( $this->plugin->validation, "$product_module.licensingModel" ); 77 if ( $this->is_validation_expired() ) { 78 /** @var $result ValidationResults */ 79 $result = self::restValidate( $this->plugin->api_key, $this->plugin->product_number ); 80 81 /** @var $ttl \DateTime */ 82 $ttl = $result->getTtl(); 83 $expires_ttl_at = $ttl->format( \DateTime::ATOM ); 84 $validation_result = json_encode( $result->getValidations() ); 85 86 $data = [ 87 'expires_ttl_at' => $expires_ttl_at, 88 'validated_at' => date( DATE_ATOM ), 89 'validation_result' => $validation_result, 90 ]; 91 92 if ( empty( $this->plugin->consented_at ) ) { 93 $data['consented_at'] = date( DATE_ATOM ); 94 } 95 96 $this->plugin = $this->update_plugin( $data, [ 'product_number' => $this->plugin->product_number ] ); 97 } 98 99 if ( ! $this->plugin->validation_result || ! PluginPass_Dot::has( $this->plugin->validation_result, $feature ) ) { 100 return false; 101 } 102 103 $feature_parsed = explode( '.', $feature ); 104 $product_module = reset( $feature_parsed ); 105 $licensingModel = PluginPass_Dot::get( $this->plugin->validation_result, "$product_module.licensingModel" ); 74 106 75 107 if ( is_null( $licensingModel ) ) { … … 80 112 ? '.0.valid' : '.valid'; 81 113 82 return PluginPass_Dot::get( $this->plugin->validation, $feature ) === 'true'; 114 return PluginPass_Dot::get( $this->plugin->validation_result, $feature ) === 'true'; 115 } 116 117 /** 118 * Get validation result for feature 119 * 120 * @param null $feature 121 * 122 * @return mixed 123 */ 124 public function validation_result( $feature = null ) { 125 if ( ! $feature ) { 126 return $this->plugin->validation_result; 127 } 128 129 return PluginPass_Dot::get( $this->plugin->validation_result, $feature ); 83 130 } 84 131 … … 86 133 * Redirect user to the Shop URL for license acquisition. 87 134 * 88 * @since 1.0.089 * @access public90 135 * @param string $successUrl 91 136 * @param string $successUrlTitle 92 137 * @param string $cancelUrl 93 138 * @param string $cancelUrlTitle 139 * 140 * @since 1.0.0 141 * @access public 94 142 */ 95 143 public function open_shop( $successUrl = '', $successUrlTitle = '', $cancelUrl = '', $cancelUrlTitle = '' ) { … … 104 152 * Generate shop URL for license acquisition. 105 153 * 154 * @param string $successUrl 155 * @param string $successUrlTitle 156 * @param string $cancelUrl 157 * @param string $cancelUrlTitle 158 * 159 * @return string 106 160 * @since 1.0.0 107 161 * @access public 108 162 */ 109 public function get_shop_url( $title, array $attrs = [], $successUrl = '', $successUrlTitle = '', $cancelUrl = '', $cancelUrlTitle = '' ) { 110 $shopToken = $this->get_shop_token( $successUrl, $successUrlTitle, $cancelUrl, $cancelUrlTitle ); 111 112 $shopUrl = $shopToken->getShopURL(); 113 114 $attrsMap = array_map( function ( $key, $value ) { 115 return "$key=\"$value\""; 116 }, array_keys( $attrs ), $attrs ); 117 118 $attrsString = implode( " ", $attrsMap ); 119 120 echo "<a href='$shopUrl' $attrsString target='_blank'>$title</a>"; 163 public function get_shop_url( $successUrl = '', $successUrlTitle = '', $cancelUrl = '', $cancelUrlTitle = '' ) { 164 return $this->get_shop_token( $successUrl, $successUrlTitle, $cancelUrl, $cancelUrlTitle )->getShopURL(); 121 165 } 122 166 … … 147 191 } 148 192 149 protected function is_ plugin_not_exits_or_validation_expired() {150 return ( ! $this->plugin || strtotime( $this->plugin->expires_at ) <= time() );193 protected function is_validation_expired() { 194 return ( ! $this->plugin->expires_ttl_at || strtotime( $this->plugin->expires_ttl_at ) <= time() ); 151 195 } 152 196 } -
pluginpass-pro-plugintheme-licensing/trunk/inc/common/traits/class-pluginpass-plugable.php
r2137166 r2146523 12 12 13 13 protected function get_plugin( array $where ) { 14 global $wpdb;14 $results = $this->get_plugins( $where ); 15 15 16 $plugins_table = Activator::get_plugins_table_name(); 17 18 $queryWhere = implode( ' AND ', array_map( function ( $key, $value ) { 19 return "$key='$value'"; 20 }, array_keys( $where ), $where ) ); 21 22 $plugin = $wpdb->get_row( "SELECT * FROM $plugins_table WHERE $queryWhere" ); 23 24 if ( $plugin ) { 25 $plugin->validation = json_decode( $plugin->validation, true ); 26 } 27 28 return $plugin; 16 return is_array( $results ) ? reset( $results ) : $results; 29 17 } 30 18 … … 42 30 $plugins_table = Activator::get_plugins_table_name(); 43 31 44 $result = $wpdb->insert( $plugins_table, array_merge( $data, [ 'validated_at' => date( DATE_ATOM ) ] ));32 $result = $wpdb->insert( $plugins_table, $data ); 45 33 46 if ( ! $result) {34 if ( $result === false ) { 47 35 throw new \Exception( 'Failed to save plugin validation data.' ); 48 36 } … … 65 53 $plugins_table = Activator::get_plugins_table_name(); 66 54 67 $result = $wpdb->update( $plugins_table, array_merge( $data, [ 'validated_at' => date( DATE_ATOM ) ] ), $where );55 $result = $wpdb->update( $plugins_table, $data, $where ); 68 56 69 if ( ! $result) {57 if ( $result === false ) { 70 58 throw new \Exception( 'Failed to update plugin validation data.' ); 71 59 } … … 73 61 return $this->get_plugin( $where ); 74 62 } 63 64 /** 65 * Delete plugin data 66 * 67 * @param array $where 68 * 69 * @return false|int 70 */ 71 protected function delete_plugin( array $where ) { 72 global $wpdb; 73 74 $plugins_table = Activator::get_plugins_table_name(); 75 76 return $wpdb->delete( $plugins_table, $where ); 77 } 78 79 80 protected function get_plugins( array $where = [] ) { 81 global $wpdb; 82 83 $plugins_table = Activator::get_plugins_table_name(); 84 85 $query = "SELECT * FROM $plugins_table"; 86 87 if ( ! empty( $where ) ) { 88 $queryWhere = implode( ' AND ', array_map( function ( $key, $value ) { 89 if ( is_array( $value ) ) { 90 $in = implode( '\',', $value ); 91 92 return "$key IN ('$in')"; 93 } 94 95 return "$key='$value'"; 96 }, array_keys( $where ), $where ) ); 97 98 $query .= " WHERE $queryWhere"; 99 } 100 101 $results = $wpdb->get_results( $query ); 102 103 $plugins = []; 104 105 if ( ! empty( $results ) ) { 106 foreach ( $results as &$plugin ) { 107 $plugin->validation_result = json_decode( $plugin->validation_result, true ); 108 $plugins[ $plugin->ID ] = $plugin; 109 } 110 111 return $plugins; 112 } 113 114 return $results; 115 } 75 116 } -
pluginpass-pro-plugintheme-licensing/trunk/inc/common/traits/class-pluginpass-validatable.php
r2137166 r2146523 6 6 use NetLicensing\Context; 7 7 use NetLicensing\LicenseeService; 8 use NetLicensing\NetLicensingService; 8 9 use NetLicensing\ValidationParameters; 10 use PluginPass as NS; 9 11 10 12 trait PluginPass_Validatable { … … 25 27 $validation_parameters->setLicenseeName( get_bloginfo( 'name' ) ); 26 28 29 30 NetLicensingService::getInstance()->curl()->setUserAgent( 'NetLicensing/PHP/' . NS\PLUGIN_NAME . ' ' . PHP_VERSION . '/' . NS\PLUGIN_VERSION . ' (https://netlicensing.io)' . '; ' . $_SERVER['HTTP_USER_AGENT'] ); 31 27 32 return LicenseeService::validate( $context, self::get_licensee_number(), $validation_parameters ); 28 33 } -
pluginpass-pro-plugintheme-licensing/trunk/inc/core/class-activator.php
r2137166 r2146523 44 44 $sql = "CREATE TABLE $plugins_table ( 45 45 ID bigint(20) NOT NULL AUTO_INCREMENT, 46 number varchar(255) NOT NULL,47 name tinytextNOT NULL,46 plugin_folder varchar(255) NOT NULL, 47 product_number varchar(255) NOT NULL, 48 48 api_key varchar(255) NOT NULL, 49 validated_at timestamp, 50 expires_at timestamp , 51 validation json NOT NULL, 49 consented_at timestamp NULL DEFAULT NULL, 50 validated_at timestamp NULL DEFAULT NULL, 51 expires_ttl_at timestamp NULL DEFAULT NULL, 52 validation_result json DEFAULT NULL, 52 53 PRIMARY KEY (ID) 53 54 ) $charset_collate;"; … … 57 58 dbDelta( $sql ); 58 59 59 $indexes = $wpdb->get_results( "SHOW INDEX FROM $plugins_table" );60 $indexes = $wpdb->get_results( "SHOW INDEX FROM $plugins_table" ); 60 61 $number_index_name = 'pluginpass_pl_number'; 61 62 … … 69 70 70 71 if ( ! $is_unique_number_exists ) { 71 $wpdb->query("CREATE UNIQUE INDEX $number_index_name ON $plugins_table ( number)");72 $wpdb->query("CREATE UNIQUE INDEX $number_index_name ON $plugins_table (product_number)"); 72 73 } 73 74 -
pluginpass-pro-plugintheme-licensing/trunk/pluginpass.php
r2137441 r2146523 16 16 * Plugin URI: https://github.com/Labs64/PluginPass 17 17 * Description: WordPress Plugin/Theme Licensing powered by Labs64 NetLicensing 18 * Version: 0.9. 218 * Version: 0.9.3 19 19 * Author: Labs64 20 20 * Author URI: https://netlicensing.io
Note: See TracChangeset
for help on using the changeset viewer.