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 +156 -31 1.11.0 → 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,
@@ -317,9 +368,9 @@
317 368 ],
318 369 [
319 370 'label' => 'More Details',
320 371 'type' => 'external_link',
321 - 'url' => 'https://docs.wpsubscription.co/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',
322 373 ],
323 374 ],
324 375 ],
325 376 'razorpay' => [
@@ -347,9 +398,9 @@
347 398 ],
348 399 [
349 400 'label' => 'More Details',
350 401 'type' => 'external_link',
351 - 'url' => 'https://docs.wpsubscription.co/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',
352 403 ],
353 404 ],
354 405 ],
355 406 'xendit' => [
@@ -377,14 +428,19 @@
377 428 ],
378 429 [
379 430 'label' => 'More Details',
380 431 'type' => 'external_link',
381 - 'url' => 'https://docs.wpsubscription.co/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',
382 433 ],
383 434 ],
384 435 ],
385 436 ];
386 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 +
387 443 // Third-party integrations (requires Pro plugin to function).
388 444 $third_party = [
389 445 // LMS.
390 446 'tutor_lms' => [
@@ -389,13 +445,13 @@
389 445 // LMS.
390 446 'tutor_lms' => [
391 447 'title' => 'Tutor LMS',
392 448 'description' => 'Restrict course access based on subscription status. Enroll and unenroll students automatically.',
393 - 'icon_url' => 'https://ps.w.org/tutor/assets/icon-256x256.gif',
449 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/tutor-lms.jpeg',
394 450 'type' => 'third_party',
395 451 'is_pro' => true,
396 452 'category' => 'lms',
397 - 'is_installed' => is_plugin_active( 'tutor/tutor.php' ) && class_exists( 'TUTOR\Tutor' ),
453 + 'is_installed' => $this->is_plugin_installed( 'tutor/tutor.php' ),
398 454 'is_active' => is_plugin_active( 'tutor/tutor.php' ) && class_exists( 'TUTOR\Tutor' ),
399 455 'actions' => [
400 456 [
401 457 'action' => 'install',
@@ -403,11 +459,17 @@
403 459 'type' => 'function',
404 460 'function' => "subscrptInstallPlugin(this, 'tutor')",
405 461 ],
406 462 [
463 + 'action' => 'activate',
464 + 'label' => __( 'Activate', 'subscription' ),
465 + 'type' => 'function',
466 + 'function' => "subscrptActivatePlugin(this, 'tutor/tutor.php')",
467 + ],
468 + [
407 469 'label' => __( 'Learn More', 'subscription' ),
408 470 'type' => 'external_link',
409 - 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-tutor-lms',
471 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-tutor-lms?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
410 472 ],
411 473 ],
412 474 ],
413 475 'learnpress' => [
@@ -412,13 +474,13 @@
412 474 ],
413 475 'learnpress' => [
414 476 'title' => 'LearnPress',
415 477 'description' => 'Connect subscriptions with LearnPress courses. Enroll users automatically when subscriptions are active.',
416 - 'icon_url' => 'https://ps.w.org/learnpress/assets/icon-256x256.gif',
478 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/learnpress.png',
417 479 'type' => 'third_party',
418 480 'is_pro' => true,
419 481 'category' => 'lms',
420 - 'is_installed' => is_plugin_active( 'learnpress/learnpress.php' ) && class_exists( 'LearnPress' ),
482 + 'is_installed' => $this->is_plugin_installed( 'learnpress/learnpress.php' ),
421 483 'is_active' => is_plugin_active( 'learnpress/learnpress.php' ) && class_exists( 'LearnPress' ),
422 484 'actions' => [
423 485 [
424 486 'action' => 'install',
@@ -426,11 +488,17 @@
426 488 'type' => 'function',
427 489 'function' => "subscrptInstallPlugin(this, 'learnpress')",
428 490 ],
429 491 [
492 + 'action' => 'activate',
493 + 'label' => __( 'Activate', 'subscription' ),
494 + 'type' => 'function',
495 + 'function' => "subscrptActivatePlugin(this, 'learnpress/learnpress.php')",
496 + ],
497 + [
430 498 'label' => __( 'Learn More', 'subscription' ),
431 499 'type' => 'external_link',
432 - 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-learnpress-lms',
500 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-learnpress-lms?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
433 501 ],
434 502 ],
435 503 ],
436 504 'learndash' => [
@@ -439,9 +507,9 @@
439 507 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/learndash.jpeg',
440 508 'type' => 'third_party',
441 509 'is_pro' => true,
442 510 'category' => 'lms',
443 - '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' ),
444 512 'is_active' => is_plugin_active( 'sfwd-lms/sfwd_lms.php' ) && class_exists( 'LearnDash\Core\App' ),
445 513 'actions' => [
446 514 [
447 515 'action' => 'install',
@@ -449,11 +517,17 @@
449 517 'type' => 'external_link',
450 518 'url' => 'https://www.learndash.com/',
451 519 ],
452 520 [
521 + 'action' => 'activate',
522 + 'label' => __( 'Activate', 'subscription' ),
523 + 'type' => 'function',
524 + 'function' => "subscrptActivatePlugin(this, 'sfwd-lms/sfwd_lms.php')",
525 + ],
526 + [
453 527 'label' => __( 'Learn More', 'subscription' ),
454 528 'type' => 'external_link',
455 - 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-learndash-lms',
529 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-learndash-lms?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
456 530 ],
457 531 ],
458 532 ],
459 533 // CRM.
@@ -459,13 +533,13 @@
459 533 // CRM.
460 534 'fluentcrm' => [
461 535 'title' => 'FluentCRM',
462 536 'description' => 'Trigger email sequences and manage contacts based on subscription events and status changes.',
463 - 'icon_url' => 'https://ps.w.org/fluent-crm/assets/icon-256x256.png',
537 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/fluentcrm.png',
464 538 'type' => 'third_party',
465 539 'is_pro' => true,
466 540 'category' => 'crm',
467 - 'is_installed' => class_exists( 'FluentCrm\App\Services\Funnel\BaseTrigger' ),
541 + 'is_installed' => $this->is_plugin_installed( 'fluent-crm/fluent-crm.php' ),
468 542 'is_active' => class_exists( 'FluentCrm\App\Services\Funnel\BaseTrigger' ),
469 543 'actions' => [
470 544 [
471 545 'action' => 'install',
@@ -473,11 +547,17 @@
473 547 'type' => 'function',
474 548 'function' => "subscrptInstallPlugin(this, 'fluent-crm')",
475 549 ],
476 550 [
551 + 'action' => 'activate',
552 + 'label' => __( 'Activate', 'subscription' ),
553 + 'type' => 'function',
554 + 'function' => "subscrptActivatePlugin(this, 'fluent-crm/fluent-crm.php')",
555 + ],
556 + [
477 557 'label' => __( 'Learn More', 'subscription' ),
478 558 'type' => 'external_link',
479 - 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-fluent-crm',
559 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-fluent-crm?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
480 560 ],
481 561 ],
482 562 ],
483 563 // Automation.
@@ -483,13 +563,13 @@
483 563 // Automation.
484 564 'automatorwp' => [
485 565 'title' => 'AutomatorWP',
486 566 'description' => 'Build powerful automations triggered by subscription events without writing any code.',
487 - 'icon_url' => 'https://ps.w.org/automatorwp/assets/icon-256x256.png',
567 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/automatorwp.png',
488 568 'type' => 'third_party',
489 569 'is_pro' => true,
490 570 'category' => 'automation',
491 - 'is_installed' => is_plugin_active( 'automatorwp/automatorwp.php' ) && class_exists( 'AutomatorWP' ),
571 + 'is_installed' => $this->is_plugin_installed( 'automatorwp/automatorwp.php' ),
492 572 'is_active' => is_plugin_active( 'automatorwp/automatorwp.php' ) && class_exists( 'AutomatorWP' ),
493 573 'actions' => [
494 574 [
495 575 'action' => 'install',
@@ -496,8 +576,14 @@
496 576 'label' => __( 'Install Now', 'subscription' ),
497 577 'type' => 'function',
498 578 'function' => "subscrptInstallPlugin(this, 'automatorwp')",
499 579 ],
580 + [
581 + 'action' => 'activate',
582 + 'label' => __( 'Activate', 'subscription' ),
583 + 'type' => 'function',
584 + 'function' => "subscrptActivatePlugin(this, 'automatorwp/automatorwp.php')",
585 + ],
500 586 // [
501 587 // 'label' => __( 'Learn More', 'subscription' ),
502 588 // 'type' => 'external_link',
503 589 // 'url' => 'https://docs.wpsubscription.co/en/',
@@ -506,13 +592,13 @@
506 592 ],
507 593 'wpfusion' => [
508 594 'title' => 'WP Fusion',
509 595 'description' => 'Sync subscription data with your CRM and marketing platforms through WP Fusion.',
510 - 'icon_url' => 'https://ps.w.org/wp-fusion-lite/assets/icon-256x256.png',
596 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/wp-fusion.png',
511 597 'type' => 'third_party',
512 598 'is_pro' => true,
513 599 'category' => 'automation',
514 - 'is_installed' => class_exists( 'WPF_Integrations_Base' ),
600 + 'is_installed' => $this->is_plugin_installed( 'wp-fusion/wp-fusion.php' ) || class_exists( 'WPF_Integrations_Base' ),
515 601 'is_active' => class_exists( 'WPF_Integrations_Base' ),
516 602 'actions' => [
517 603 [
518 604 'action' => 'install',
@@ -519,8 +605,14 @@
519 605 'label' => __( 'Get WP Fusion', 'subscription' ),
520 606 'type' => 'external_link',
521 607 'url' => 'https://wpfusion.com/',
522 608 ],
609 + [
610 + 'action' => 'activate',
611 + 'label' => __( 'Activate', 'subscription' ),
612 + 'type' => 'function',
613 + 'function' => "subscrptActivatePlugin(this, 'wp-fusion/wp-fusion.php')",
614 + ],
523 615 // [
524 616 // 'label' => __( 'Learn More', 'subscription' ),
525 617 // 'type' => 'external_link',
526 618 // 'url' => 'https://docs.wpsubscription.co/en/',
@@ -530,13 +622,13 @@
530 622 // Email Marketing.
531 623 'mailpoet' => [
532 624 'title' => 'MailPoet',
533 625 'description' => 'Add subscribers to MailPoet lists and trigger email automations based on subscription lifecycle events.',
534 - 'icon_url' => 'https://ps.w.org/mailpoet/assets/icon-256x256.png',
626 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/mailpoet.png',
535 627 'type' => 'third_party',
536 628 'is_pro' => true,
537 629 'category' => 'email',
538 - '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' ),
539 631 'is_active' => is_plugin_active( 'mailpoet/mailpoet.php' ) || is_plugin_active( 'mailpoet-premium/mailpoet-premium.php' ),
540 632 'actions' => [
541 633 [
542 634 'action' => 'install',
@@ -544,11 +636,17 @@
544 636 'type' => 'function',
545 637 'function' => "subscrptInstallPlugin(this, 'mailpoet')",
546 638 ],
547 639 [
640 + 'action' => 'activate',
641 + 'label' => __( 'Activate', 'subscription' ),
642 + 'type' => 'function',
643 + 'function' => "subscrptActivatePlugin(this, 'mailpoet/mailpoet.php')",
644 + ],
645 + [
548 646 'label' => __( 'Learn More', 'subscription' ),
549 647 'type' => 'external_link',
550 - 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-mailpoet',
648 + 'url' => 'https://docs.wpsubscription.co/en/wpsubscription-mailpoet?utm_source=plugin&utm_medium=admin&utm_campaign=docs',
551 649 ],
552 650 ],
553 651 ],
554 652 // License Management.
@@ -558,9 +656,9 @@
558 656 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/wp-software-license.png',
559 657 'type' => 'third_party',
560 658 'is_pro' => true,
561 659 'category' => 'license',
562 - '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' ),
563 661 'is_active' => is_plugin_active( 'software-license/software-license.php' ) && class_exists( 'WOO_SL' ),
564 662 'actions' => [
565 663 [
566 664 'action' => 'install',
@@ -567,8 +665,14 @@
567 665 'label' => __( 'Get Plugin', 'subscription' ),
568 666 'type' => 'external_link',
569 667 'url' => 'https://wpsoftwarelicense.com/',
570 668 ],
669 + [
670 + 'action' => 'activate',
671 + 'label' => __( 'Activate', 'subscription' ),
672 + 'type' => 'function',
673 + 'function' => "subscrptActivatePlugin(this, 'software-license/software-license.php')",
674 + ],
571 675 // [
572 676 // 'label' => __( 'Learn More', 'subscription' ),
573 677 // 'type' => 'external_link',
574 678 // 'url' => 'https://docs.wpsubscription.co/en/',
@@ -577,13 +681,13 @@
577 681 ],
578 682 'license_mgr' => [
579 683 'title' => 'License Manager for WooCommerce',
580 684 'description' => 'Generate and manage software license keys that are automatically tied to active subscriptions.',
581 - 'icon_url' => 'https://ps.w.org/license-manager-for-woocommerce/assets/icon-256x256.gif',
685 + 'icon_url' => SUBSCRPT_ASSETS . '/images/integrations/license-manager.png',
582 686 'type' => 'third_party',
583 687 'is_pro' => true,
584 688 'category' => 'license',
585 - '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' ),
586 690 'is_active' => is_plugin_active( 'license-manager-for-woocommerce/license-manager-for-woocommerce.php' ) && class_exists( 'LicenseManagerForWooCommerce\Models\Resources\License' ),
587 691 'actions' => [
588 692 [
589 693 'action' => 'install',
@@ -590,8 +694,14 @@
590 694 'label' => __( 'Install Now', 'subscription' ),
591 695 'type' => 'function',
592 696 'function' => "subscrptInstallPlugin(this, 'license-manager-for-woocommerce')",
593 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 + ],
594 704 // [
595 705 // 'label' => __( 'Learn More', 'subscription' ),
596 706 // 'type' => 'external_link',
597 707 // 'url' => 'https://docs.wpsubscription.co/en/',
@@ -618,10 +728,16 @@
618 728 foreach ( $integrations as $integration ) {
619 729 $is_installed = $integration['is_installed'] ?? false;
620 730 $is_active = $integration['is_active'] ?? false;
621 731
622 - $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;
623 736
737 + $cleaned_actions = [];
738 + $shown_install_url = null;
739 +
624 740 foreach ( $integration['actions'] as $integration_action ) {
625 741 $action_tag = $integration_action['action'] ?? null;
626 742
627 743 if ( 'install' === $action_tag ) {
@@ -626,8 +742,9 @@
626 742
627 743 if ( 'install' === $action_tag ) {
628 744 if ( ! $is_installed ) {
629 745 $cleaned_actions[] = $integration_action;
746 + $shown_install_url = $integration_action['url'] ?? null;
630 747 }
631 748 continue;
632 749 }
633 750 if ( 'uninstall' === $action_tag ) {
@@ -635,8 +752,14 @@
635 752 $cleaned_actions[] = $integration_action;
636 753 }
637 754 continue;
638 755 }
756 + if ( 'activate' === $action_tag ) {
757 + if ( $is_installed && ! $plugin_active ) {
758 + $cleaned_actions[] = $integration_action;
759 + }
760 + continue;
761 + }
639 762 if ( 'enable' === $action_tag ) {
640 763 if ( $is_installed && ! $is_active ) {
641 764 $cleaned_actions[] = $integration_action;
642 765 }
@@ -642,15 +765,20 @@
642 765 }
643 766 continue;
644 767 }
645 768 if ( 'settings' === $action_tag ) {
646 - if ( $is_installed ) {
769 + if ( $is_installed && ( '' === $plugin_file || $plugin_active ) ) {
647 770 $cleaned_actions[] = $integration_action;
648 771 }
649 772 continue;
650 773 }
651 774
652 - // 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 + }
653 781 $cleaned_actions[] = $integration_action;
654 782 }
655 783
656 784 // Overwrite.
@@ -666,11 +794,8 @@
666 794 */
667 795 public function render_integrations_page() {
668 796 $integrations = $this->integrations;
669 797 $integrations = $this->filter_integration_actions( $integrations );
670 -
671 - // Integrations styles.
672 - // wp_enqueue_style( 'wp-subs-integration-settings', SUBSCRPT_ASSETS . '/css/integration_settings.css', [], SUBSCRPT_VERSION, 'all' );
673 798
674 799 $menu = new \SpringDevs\Subscription\Admin\Menu();
675 800 $menu->render_admin_header( __( 'Integrations', 'subscription' ) );
676 801 include 'views/integrations.php';