PluginProbe
wpForo Forum / 3.2.0
wpForo Forum v3.2.0
3.2.0 3.1.7 3.1.6 3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 All 140 releases
← All changes | admin/pages/license/src/Services/LicenseService.php +44 -8 3.1.7 → 3.2.0 View file →
@@ -220,12 +220,14 @@
220 220
221 221 // Process every license result — update local storage and notices
222 222 foreach( $key_to_product as $license_key => $product_id ) {
223 223 if( ! isset( $batch_results[ $license_key ] ) ) continue;
224 -
225 - $result = $batch_results[ $license_key ];
226 - $license = $licenses[ $product_id ];
227 -
224 +
225 + $result = $batch_results[ $license_key ];
226 + $license = $licenses[ $product_id ];
227 + $product_id = $this->sync_product_key( $product_id, $result );
228 + if( $product_id === '' ) continue;
229 +
228 230 if( ! empty( $result['success'] ) && ! empty( $result['data'] ) ) {
229 231 $this->save( $product_id, $result['data'] );
230 232
231 233 // Clear any expired notice for this license
@@ -346,8 +348,33 @@
346 348 }
347 349 }
348 350
349 351 /**
352 + * If the server reports a real Paddle product_id different from the local key
353 + * (e.g. a migrated legacy license stored under its plugin slug), move the local
354 + * license to that key so the store UI treats it like any purchased license.
355 + * Returns the key to continue with, or '' when the entry was dropped because an
356 + * active license already exists under the server's product_id.
357 + */
358 + private function sync_product_key( string $product_id, array $result ): string {
359 + $server_pid = $result['data']['product_id'] ?? '';
360 + if( ! is_string( $server_pid ) || strpos( $server_pid, 'pro_' ) !== 0 || $server_pid === $product_id ) return $product_id;
361 +
362 + $licenses = $this->get_all();
363 + if( ! isset( $licenses[ $product_id ] ) ) return $product_id;
364 +
365 + $keep_existing = isset( $licenses[ $server_pid ] ) && $this->is_active( $server_pid );
366 + if( ! $keep_existing ) {
367 + $licenses[ $server_pid ] = $licenses[ $product_id ];
368 + $licenses[ $server_pid ]['product_id'] = $server_pid;
369 + }
370 + unset( $licenses[ $product_id ] );
371 + update_option( $this->option_key, $licenses );
372 +
373 + return $keep_existing ? '' : $server_pid;
374 + }
375 +
376 + /**
350 377 * Remove a license for a product
351 378 */
352 379 public function remove( string $product_id ): bool {
353 380 $licenses = $this->get_all();
@@ -405,9 +432,11 @@
405 432 if( empty( $license ) ) return;
406 433
407 434 $plugin_slug = $license['plugin_slug'] ?? '';
408 435 if( empty( $plugin_slug ) ) return;
409 -
436 + // Addon not physically installed — no notice needed
437 + if( ! is_dir( WP_PLUGIN_DIR . '/' . $plugin_slug ) ) return;
438 +
410 439 $expired_notices = get_option( $this->expired_notice_option, [] );
411 440 $expired_notices[ $plugin_slug ] = [
412 441 'product_name' => $license['product_name'] ?? $plugin_slug,
413 442 'status' => $license['status'] ?? 'expired',
@@ -465,8 +494,13 @@
465 494 'addon_deleted' => false,
466 495 ];
467 496 }
468 497
498 + $product_id = $this->sync_product_key( $product_id, $response );
499 + if( $product_id === '' ) {
500 + return [ 'valid' => false, 'reason' => 'duplicate', 'error' => '', 'status' => '', 'removed' => true, 'addon_deleted' => false ];
501 + }
502 +
469 503 // License is valid on the server
470 504 if( ! empty( $response['success'] ) && ! empty( $response['data'] ) ) {
471 505 $this->save( $product_id, $response['data'] );
472 506
@@ -616,11 +650,13 @@
616 650
617 651 foreach( $keys_to_validate as $license_key => $product_id ) {
618 652 if( ! isset( $batch_results[ $license_key ] ) ) continue;
619 653
620 - $result = $batch_results[ $license_key ];
621 - $license = $licenses[ $product_id ];
622 -
654 + $result = $batch_results[ $license_key ];
655 + $license = $licenses[ $product_id ];
656 + $product_id = $this->sync_product_key( $product_id, $result );
657 + if( $product_id === '' ) continue;
658 +
623 659 if( ! empty( $result['success'] ) && ! empty( $result['data'] ) ) {
624 660 // License is valid — update local data
625 661 $this->save( $product_id, $result['data'] );
626 662 } else {