PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.2.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.2.0
2.4.0 2.3.0 2.2.0 2.1.0 2.0.0 1.11.2 1.11.1 1.11.0 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.6 1.9.5 trunk 1.3.0 1.3.1 1.3.2 1.4.0 All 65 releases
← All changes | includes/Admin/Integrations.php +160 -36 1.10.2 → 2.2.0 View file →
@@ -99,8 +99,12 @@
99 99 'nonce' => wp_create_nonce( 'subscrpt_integration_install_nonce' ),
100 100 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
101 101 )
102 102 );
103 +
104 + // Browser-side filter rail. Enqueued on this hook, not in the render
105 + // callback, so it always loads.
106 + wp_enqueue_script( 'subscrpt-integrations-filter', SUBSCRPT_ASSETS . '/js/admin/integrations-filter.js', [], SUBSCRPT_VERSION, true );
103 107 }
104 108
105 109 /**
106 110 * Handle AJAX request for integrations.
@@ -188,8 +192,55 @@
188 192 return is_plugin_active( $plugin_file );
189 193 }
190 194
191 195 /**
196 + * Find the basename of an installed plugin from its wp.org slug.
197 + *
198 + * @param string $slug The wp.org plugin slug, which is also its directory.
199 + * @return string The plugin basename, or an empty string when not installed.
200 + */
201 + protected function find_plugin_file( $slug ) {
202 + if ( ! function_exists( 'get_plugins' ) ) {
203 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
204 + }
205 + foreach ( array_keys( get_plugins() ) as $plugin_file ) {
206 + if ( 0 === strpos( $plugin_file, $slug . '/' ) ) {
207 + return $plugin_file;
208 + }
209 + }
210 + return '';
211 + }
212 +
213 + /**
214 + * Mark a gateway card installed when its plugin is on disk, and give it an
215 + * Activate action for when that plugin is inactive.
216 + *
217 + * Gateway cards otherwise detect installation by a class the plugin declares,
218 + * which only exists while it is active, so an installed-but-inactive gateway
219 + * offered "Install Now" and the install failed on the existing folder.
220 + *
221 + * @param array $integration The integration card.
222 + * @param string $slug The wp.org plugin slug.
223 + * @return array
224 + */
225 + protected function with_gateway_plugin_state( array $integration, $slug ) {
226 + $plugin_file = $this->find_plugin_file( $slug );
227 + if ( '' === $plugin_file ) {
228 + return $integration;
229 + }
230 +
231 + $integration['is_installed'] = true;
232 + $integration['plugin_file'] = $plugin_file;
233 + $integration['actions'][] = [
234 + 'action' => 'activate',
235 + 'label' => __( 'Activate', 'subscription' ),
236 + 'type' => 'function',
237 + 'function' => "subscrptActivatePlugin(this, '" . esc_js( $plugin_file ) . "')",
238 + ];
239 + return $integration;
240 + }
241 +
242 + /**
192 243 * Check if a payment gateway is enabled.
193 244 *
194 245 * @param string $gateway_id Gateway ID.
195 246 */
@@ -237,9 +288,9 @@
237 288 ],
238 289 'stripe' => [
239 290 'title' => 'Stripe',
240 291 'description' => 'Process subscription payments securely with Stripe.',
241 - 'icon_url' => 'https://ps.w.org/woocommerce-gateway-stripe/assets/icon-256x256.png',
292 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/stripe.png',
242 293 'type' => 'payment_gateway',
243 294 'is_installed' => class_exists( 'WC_Stripe' ),
244 295 'is_active' => self::is_gateway_enabled( 'stripe' ),
245 296 'supports_recurring' => true,
@@ -298,9 +349,8 @@
298 349 'description' => 'Pay for subscriptions with Mollie Payments for WooCommerce.',
299 350 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/mollie.png',
300 351 'type' => 'payment_gateway',
301 352 'is_pro' => true,
302 - 'is_beta' => true,
303 353 'is_installed' => class_exists( 'Mollie\WooCommerce\Activation\ActivationModule' ),
304 354 'is_active' => self::is_gateway_enabled( 'mollie_wc_gateway', true ),
305 355 'supports_recurring' => true,
306 356 'actions' => [
@@ -318,9 +368,9 @@
318 368 ],
319 369 [
320 370 'label' => 'More Details',
321 371 'type' => 'external_link',
322 - 'url' => 'https://docs.converslabs.com/en/wpsubscription-payment-with-mollie',
372 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-payment-with-mollie?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
323 373 ],
324 374 ],
325 375 ],
326 376 'razorpay' => [
@@ -348,9 +398,9 @@
348 398 ],
349 399 [
350 400 'label' => 'More Details',
351 401 'type' => 'external_link',
352 - 'url' => 'https://docs.converslabs.com/en/wpsubscription-payment-with-razorpay',
402 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-payment-with-razorpay?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
353 403 ],
354 404 ],
355 405 ],
356 406 'xendit' => [
@@ -378,14 +428,19 @@
378 428 ],
379 429 [
380 430 'label' => 'More Details',
381 431 'type' => 'external_link',
382 - 'url' => 'https://docs.converslabs.com/en/wpsubscription-payment-with-xendit',
432 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-payment-with-xendit?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
383 433 ],
384 434 ],
385 435 ],
386 436 ];
387 437
438 + $integrations['stripe'] = $this->with_gateway_plugin_state( $integrations['stripe'], 'woocommerce-gateway-stripe' );
439 + $integrations['mollie'] = $this->with_gateway_plugin_state( $integrations['mollie'], 'mollie-payments-for-woocommerce' );
440 + $integrations['razorpay'] = $this->with_gateway_plugin_state( $integrations['razorpay'], 'woo-razorpay' );
441 + $integrations['xendit'] = $this->with_gateway_plugin_state( $integrations['xendit'], 'woo-xendit-virtual-accounts' );
442 +
388 443 // Third-party integrations (requires Pro plugin to function).
389 444 $third_party = [
390 445 // LMS.
391 446 'tutor_lms' => [
@@ -390,13 +445,13 @@
390 445 // LMS.
391 446 'tutor_lms' => [
392 447 'title' => 'Tutor LMS',
393 448 'description' => 'Restrict course access based on subscription status. Enroll and unenroll students automatically.',
394 - 'icon_url' => 'https://ps.w.org/tutor/assets/icon-256x256.gif',
449 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/tutor-lms.jpeg',
395 450 'type' => 'third_party',
396 451 'is_pro' => true,
397 452 'category' => 'lms',
398 - 'is_installed' => is_plugin_active( 'tutor/tutor.php' ) && class_exists( 'TUTOR\Tutor' ),
453 + 'is_installed' => $this->is_plugin_installed( 'tutor/tutor.php' ),
399 454 'is_active' => is_plugin_active( 'tutor/tutor.php' ) && class_exists( 'TUTOR\Tutor' ),
400 455 'actions' => [
401 456 [
402 457 'action' => 'install',
@@ -404,11 +459,17 @@
404 459 'type' => 'function',
405 460 'function' => "subscrptInstallPlugin(this, 'tutor')",
406 461 ],
407 462 [
463 + 'action' => 'activate',
464 + 'label' => __( 'Activate', 'subscription' ),
465 + 'type' => 'function',
466 + 'function' => "subscrptActivatePlugin(this, 'tutor/tutor.php')",
467 + ],
468 + [
408 469 'label' => __( 'Learn More', 'subscription' ),
409 470 'type' => 'external_link',
410 - 'url' => 'https://docs.converslabs.com/en/wpsubscription-tutor-lms',
471 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-tutor-lms?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
411 472 ],
412 473 ],
413 474 ],
414 475 'learnpress' => [
@@ -413,13 +474,13 @@
413 474 ],
414 475 'learnpress' => [
415 476 'title' => 'LearnPress',
416 477 'description' => 'Connect subscriptions with LearnPress courses. Enroll users automatically when subscriptions are active.',
417 - 'icon_url' => 'https://ps.w.org/learnpress/assets/icon-256x256.gif',
478 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/learnpress.png',
418 479 'type' => 'third_party',
419 480 'is_pro' => true,
420 481 'category' => 'lms',
421 - 'is_installed' => is_plugin_active( 'learnpress/learnpress.php' ) && class_exists( 'LearnPress' ),
482 + 'is_installed' => $this->is_plugin_installed( 'learnpress/learnpress.php' ),
422 483 'is_active' => is_plugin_active( 'learnpress/learnpress.php' ) && class_exists( 'LearnPress' ),
423 484 'actions' => [
424 485 [
425 486 'action' => 'install',
@@ -427,11 +488,17 @@
427 488 'type' => 'function',
428 489 'function' => "subscrptInstallPlugin(this, 'learnpress')",
429 490 ],
430 491 [
492 + 'action' => 'activate',
493 + 'label' => __( 'Activate', 'subscription' ),
494 + 'type' => 'function',
495 + 'function' => "subscrptActivatePlugin(this, 'learnpress/learnpress.php')",
496 + ],
497 + [
431 498 'label' => __( 'Learn More', 'subscription' ),
432 499 'type' => 'external_link',
433 - 'url' => 'https://docs.converslabs.com/en/wpsubscription-learnpress-lms',
500 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-learnpress-lms?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
434 501 ],
435 502 ],
436 503 ],
437 504 'learndash' => [
@@ -440,9 +507,9 @@
440 507 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/learndash.jpeg',
441 508 'type' => 'third_party',
442 509 'is_pro' => true,
443 510 'category' => 'lms',
444 - 'is_installed' => is_plugin_active( 'sfwd-lms/sfwd_lms.php' ) && class_exists( 'LearnDash\Core\App' ),
511 + 'is_installed' => $this->is_plugin_installed( 'sfwd-lms/sfwd_lms.php' ),
445 512 'is_active' => is_plugin_active( 'sfwd-lms/sfwd_lms.php' ) && class_exists( 'LearnDash\Core\App' ),
446 513 'actions' => [
447 514 [
448 515 'action' => 'install',
@@ -450,11 +517,17 @@
450 517 'type' => 'external_link',
451 518 'url' => 'https://www.learndash.com/',
452 519 ],
453 520 [
521 + 'action' => 'activate',
522 + 'label' => __( 'Activate', 'subscription' ),
523 + 'type' => 'function',
524 + 'function' => "subscrptActivatePlugin(this, 'sfwd-lms/sfwd_lms.php')",
525 + ],
526 + [
454 527 'label' => __( 'Learn More', 'subscription' ),
455 528 'type' => 'external_link',
456 - 'url' => 'https://docs.converslabs.com/en/wpsubscription-learndash-lms',
529 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-learndash-lms?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
457 530 ],
458 531 ],
459 532 ],
460 533 // CRM.
@@ -460,13 +533,13 @@
460 533 // CRM.
461 534 'fluentcrm' => [
462 535 'title' => 'FluentCRM',
463 536 'description' => 'Trigger email sequences and manage contacts based on subscription events and status changes.',
464 - 'icon_url' => 'https://ps.w.org/fluent-crm/assets/icon-256x256.png',
537 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/fluentcrm.png',
465 538 'type' => 'third_party',
466 539 'is_pro' => true,
467 540 'category' => 'crm',
468 - 'is_installed' => class_exists( 'FluentCrm\App\Services\Funnel\BaseTrigger' ),
541 + 'is_installed' => $this->is_plugin_installed( 'fluent-crm/fluent-crm.php' ),
469 542 'is_active' => class_exists( 'FluentCrm\App\Services\Funnel\BaseTrigger' ),
470 543 'actions' => [
471 544 [
472 545 'action' => 'install',
@@ -474,11 +547,17 @@
474 547 'type' => 'function',
475 548 'function' => "subscrptInstallPlugin(this, 'fluent-crm')",
476 549 ],
477 550 [
551 + 'action' => 'activate',
552 + 'label' => __( 'Activate', 'subscription' ),
553 + 'type' => 'function',
554 + 'function' => "subscrptActivatePlugin(this, 'fluent-crm/fluent-crm.php')",
555 + ],
556 + [
478 557 'label' => __( 'Learn More', 'subscription' ),
479 558 'type' => 'external_link',
480 - 'url' => 'https://docs.converslabs.com/en/wpsubscription-fluent-crm',
559 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-fluent-crm?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
481 560 ],
482 561 ],
483 562 ],
484 563 // Automation.
@@ -484,13 +563,13 @@
484 563 // Automation.
485 564 'automatorwp' => [
486 565 'title' => 'AutomatorWP',
487 566 'description' => 'Build powerful automations triggered by subscription events without writing any code.',
488 - 'icon_url' => 'https://ps.w.org/automatorwp/assets/icon-256x256.png',
567 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/automatorwp.png',
489 568 'type' => 'third_party',
490 569 'is_pro' => true,
491 570 'category' => 'automation',
492 - 'is_installed' => is_plugin_active( 'automatorwp/automatorwp.php' ) && class_exists( 'AutomatorWP' ),
571 + 'is_installed' => $this->is_plugin_installed( 'automatorwp/automatorwp.php' ),
493 572 'is_active' => is_plugin_active( 'automatorwp/automatorwp.php' ) && class_exists( 'AutomatorWP' ),
494 573 'actions' => [
495 574 [
496 575 'action' => 'install',
@@ -497,12 +576,18 @@
497 576 'label' => __( 'Install Now', 'subscription' ),
498 577 'type' => 'function',
499 578 'function' => "subscrptInstallPlugin(this, 'automatorwp')",
500 579 ],
580 + [
581 + 'action' => 'activate',
582 + 'label' => __( 'Activate', 'subscription' ),
583 + 'type' => 'function',
584 + 'function' => "subscrptActivatePlugin(this, 'automatorwp/automatorwp.php')",
585 + ],
501 586 // [
502 587 // 'label' => __( 'Learn More', 'subscription' ),
503 588 // 'type' => 'external_link',
504 - // 'url' => 'https://docs.converslabs.com/en/',
589 + // 'url' => 'https://docs.wpsubscription.co/en/',
505 590 // ],
506 591 ],
507 592 ],
508 593 'wpfusion' => [
@@ -507,13 +592,13 @@
507 592 ],
508 593 'wpfusion' => [
509 594 'title' => 'WP Fusion',
510 595 'description' => 'Sync subscription data with your CRM and marketing platforms through WP Fusion.',
511 - 'icon_url' => 'https://ps.w.org/wp-fusion-lite/assets/icon-256x256.png',
596 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/wp-fusion.png',
512 597 'type' => 'third_party',
513 598 'is_pro' => true,
514 599 'category' => 'automation',
515 - 'is_installed' => class_exists( 'WPF_Integrations_Base' ),
600 + 'is_installed' => $this->is_plugin_installed( 'wp-fusion/wp-fusion.php' ) || class_exists( 'WPF_Integrations_Base' ),
516 601 'is_active' => class_exists( 'WPF_Integrations_Base' ),
517 602 'actions' => [
518 603 [
519 604 'action' => 'install',
@@ -520,12 +605,18 @@
520 605 'label' => __( 'Get WP Fusion', 'subscription' ),
521 606 'type' => 'external_link',
522 607 'url' => 'https://wpfusion.com/',
523 608 ],
609 + [
610 + 'action' => 'activate',
611 + 'label' => __( 'Activate', 'subscription' ),
612 + 'type' => 'function',
613 + 'function' => "subscrptActivatePlugin(this, 'wp-fusion/wp-fusion.php')",
614 + ],
524 615 // [
525 616 // 'label' => __( 'Learn More', 'subscription' ),
526 617 // 'type' => 'external_link',
527 - // 'url' => 'https://docs.converslabs.com/en/',
618 + // 'url' => 'https://docs.wpsubscription.co/en/',
528 619 // ],
529 620 ],
530 621 ],
531 622 // Email Marketing.
@@ -531,13 +622,13 @@
531 622 // Email Marketing.
532 623 'mailpoet' => [
533 624 'title' => 'MailPoet',
534 625 'description' => 'Add subscribers to MailPoet lists and trigger email automations based on subscription lifecycle events.',
535 - 'icon_url' => 'https://ps.w.org/mailpoet/assets/icon-256x256.png',
626 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/mailpoet.png',
536 627 'type' => 'third_party',
537 628 'is_pro' => true,
538 629 'category' => 'email',
539 - 'is_installed' => is_plugin_active( 'mailpoet/mailpoet.php' ) || is_plugin_active( 'mailpoet-premium/mailpoet-premium.php' ),
630 + 'is_installed' => $this->is_plugin_installed( 'mailpoet/mailpoet.php' ) || is_plugin_active( 'mailpoet-premium/mailpoet-premium.php' ),
540 631 'is_active' => is_plugin_active( 'mailpoet/mailpoet.php' ) || is_plugin_active( 'mailpoet-premium/mailpoet-premium.php' ),
541 632 'actions' => [
542 633 [
543 634 'action' => 'install',
@@ -545,11 +636,17 @@
545 636 'type' => 'function',
546 637 'function' => "subscrptInstallPlugin(this, 'mailpoet')",
547 638 ],
548 639 [
640 + 'action' => 'activate',
641 + 'label' => __( 'Activate', 'subscription' ),
642 + 'type' => 'function',
643 + 'function' => "subscrptActivatePlugin(this, 'mailpoet/mailpoet.php')",
644 + ],
645 + [
549 646 'label' => __( 'Learn More', 'subscription' ),
550 647 'type' => 'external_link',
551 - 'url' => 'https://docs.converslabs.com/en/wpsubscription-mailpoet',
648 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-mailpoet?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
552 649 ],
553 650 ],
554 651 ],
555 652 // License Management.
@@ -559,9 +656,9 @@
559 656 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/wp-software-license.png',
560 657 'type' => 'third_party',
561 658 'is_pro' => true,
562 659 'category' => 'license',
563 - 'is_installed' => is_plugin_active( 'software-license/software-license.php' ) && class_exists( 'WOO_SL' ),
660 + 'is_installed' => $this->is_plugin_installed( 'software-license/software-license.php' ),
564 661 'is_active' => is_plugin_active( 'software-license/software-license.php' ) && class_exists( 'WOO_SL' ),
565 662 'actions' => [
566 663 [
567 664 'action' => 'install',
@@ -568,12 +665,18 @@
568 665 'label' => __( 'Get Plugin', 'subscription' ),
569 666 'type' => 'external_link',
570 667 'url' => 'https://wpsoftwarelicense.com/',
571 668 ],
669 + [
670 + 'action' => 'activate',
671 + 'label' => __( 'Activate', 'subscription' ),
672 + 'type' => 'function',
673 + 'function' => "subscrptActivatePlugin(this, 'software-license/software-license.php')",
674 + ],
572 675 // [
573 676 // 'label' => __( 'Learn More', 'subscription' ),
574 677 // 'type' => 'external_link',
575 - // 'url' => 'https://docs.converslabs.com/en/',
678 + // 'url' => 'https://docs.wpsubscription.co/en/',
576 679 // ],
577 680 ],
578 681 ],
579 682 'license_mgr' => [
@@ -578,13 +681,13 @@
578 681 ],
579 682 'license_mgr' => [
580 683 'title' => 'License Manager for WooCommerce',
581 684 'description' => 'Generate and manage software license keys that are automatically tied to active subscriptions.',
582 - 'icon_url' => 'https://ps.w.org/license-manager-for-woocommerce/assets/icon-256x256.gif',
685 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/license-manager.png',
583 686 'type' => 'third_party',
584 687 'is_pro' => true,
585 688 'category' => 'license',
586 - 'is_installed' => is_plugin_active( 'license-manager-for-woocommerce/license-manager-for-woocommerce.php' ) && class_exists( 'LicenseManagerForWooCommerce\Models\Resources\License' ),
689 + 'is_installed' => $this->is_plugin_installed( 'license-manager-for-woocommerce/license-manager-for-woocommerce.php' ),
587 690 'is_active' => is_plugin_active( 'license-manager-for-woocommerce/license-manager-for-woocommerce.php' ) && class_exists( 'LicenseManagerForWooCommerce\Models\Resources\License' ),
588 691 'actions' => [
589 692 [
590 693 'action' => 'install',
@@ -591,12 +694,18 @@
591 694 'label' => __( 'Install Now', 'subscription' ),
592 695 'type' => 'function',
593 696 'function' => "subscrptInstallPlugin(this, 'license-manager-for-woocommerce')",
594 697 ],
698 + [
699 + 'action' => 'activate',
700 + 'label' => __( 'Activate', 'subscription' ),
701 + 'type' => 'function',
702 + 'function' => "subscrptActivatePlugin(this, 'license-manager-for-woocommerce/license-manager-for-woocommerce.php')",
703 + ],
595 704 // [
596 705 // 'label' => __( 'Learn More', 'subscription' ),
597 706 // 'type' => 'external_link',
598 - // 'url' => 'https://docs.converslabs.com/en/',
707 + // 'url' => 'https://docs.wpsubscription.co/en/',
599 708 // ],
600 709 ],
601 710 ],
602 711 ];
@@ -619,10 +728,16 @@
619 728 foreach ( $integrations as $integration ) {
620 729 $is_installed = $integration['is_installed'] ?? false;
621 730 $is_active = $integration['is_active'] ?? false;
622 731
623 - $cleaned_actions = [];
732 + // A gateway card is "active" when its gateway is enabled, which is not
733 + // the same as its plugin being active; read the plugin itself.
734 + $plugin_file = $integration['plugin_file'] ?? '';
735 + $plugin_active = '' !== $plugin_file ? is_plugin_active( $plugin_file ) : $is_active;
624 736
737 + $cleaned_actions = [];
738 + $shown_install_url = null;
739 +
625 740 foreach ( $integration['actions'] as $integration_action ) {
626 741 $action_tag = $integration_action['action'] ?? null;
627 742
628 743 if ( 'install' === $action_tag ) {
@@ -627,8 +742,9 @@
627 742
628 743 if ( 'install' === $action_tag ) {
629 744 if ( ! $is_installed ) {
630 745 $cleaned_actions[] = $integration_action;
746 + $shown_install_url = $integration_action['url'] ?? null;
631 747 }
632 748 continue;
633 749 }
634 750 if ( 'uninstall' === $action_tag ) {
@@ -636,8 +752,14 @@
636 752 $cleaned_actions[] = $integration_action;
637 753 }
638 754 continue;
639 755 }
756 + if ( 'activate' === $action_tag ) {
757 + if ( $is_installed && ! $plugin_active ) {
758 + $cleaned_actions[] = $integration_action;
759 + }
760 + continue;
761 + }
640 762 if ( 'enable' === $action_tag ) {
641 763 if ( $is_installed && ! $is_active ) {
642 764 $cleaned_actions[] = $integration_action;
643 765 }
@@ -643,15 +765,20 @@
643 765 }
644 766 continue;
645 767 }
646 768 if ( 'settings' === $action_tag ) {
647 - if ( $is_installed ) {
769 + if ( $is_installed && ( '' === $plugin_file || $plugin_active ) ) {
648 770 $cleaned_actions[] = $integration_action;
649 771 }
650 772 continue;
651 773 }
652 774
653 - // Default.
775 + // Default. Skip a "More Details"-style link that just repeats the
776 + // install/"Get X" link already shown (e.g. Paddle), so the card
777 + // does not carry the same URL twice.
778 + if ( null !== $shown_install_url && ( $integration_action['url'] ?? null ) === $shown_install_url ) {
779 + continue;
780 + }
654 781 $cleaned_actions[] = $integration_action;
655 782 }
656 783
657 784 // Overwrite.
@@ -667,11 +794,8 @@
667 794 */
668 795 public function render_integrations_page() {
669 796 $integrations = $this->integrations;
670 797 $integrations = $this->filter_integration_actions( $integrations );
671 -
672 - // Integrations styles.
673 - // wp_enqueue_style( 'wp-subs-integration-settings', SUBSCRPT_ASSETS . '/css/integration_settings.css', [], SUBSCRPT_VERSION, 'all' );
674 798
675 799 $menu = new \SpringDevs\Subscription\Admin\Menu();
676 800 $menu->render_admin_header( __( 'Integrations', 'subscription' ) );
677 801 include 'views/integrations.php';