Skip to content
Open
18 changes: 18 additions & 0 deletions modules/ppcp-compat/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
use WooCommerce\PayPalCommerce\Compat\Settings\StylingSettingsMapHelper;
use WooCommerce\PayPalCommerce\Compat\Settings\SubscriptionSettingsMapHelper;
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\Compat\WooCommerceBlueprint\PayPalSettingsExporter;
use WooCommerce\PayPalCommerce\Compat\WooCommerceBlueprint\PayPalSettingsImporter;
use WooCommerce\PayPalCommerce\Compat\WooCommerceBlueprint\PayPalBlueprintBootstrap;

return array(

Expand Down Expand Up @@ -215,4 +218,19 @@
'compat.settings.payment_methods_map_helper' => static function (): PaymentMethodSettingsMapHelper {
return new PaymentMethodSettingsMapHelper();
},
'compat.blueprint.is_available' => function (): bool {
return interface_exists( 'Automattic\WooCommerce\Blueprint\Exporters\StepExporter' );
},
'compat.blueprint.paypal_settings_exporter' => static function( ContainerInterface $container ) : PayPalSettingsExporter {
return new PayPalSettingsExporter();
},
'compat.blueprint.paypal_settings_importer' => static function( ContainerInterface $container ) : PayPalSettingsImporter {
return new PayPalSettingsImporter();
},
'compat.blueprint.bootstrap' => static function( ContainerInterface $container ) : PayPalBlueprintBootstrap {
return new PayPalBlueprintBootstrap(
$container->get( 'compat.blueprint.paypal_settings_exporter' ),
$container->get( 'compat.blueprint.paypal_settings_importer' )
);
},
);
93 changes: 93 additions & 0 deletions modules/ppcp-compat/src/CompatModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ function () use ( $c ) {
}
);

$this->add_blueprint_export_test_page( $c );

$this->migrate_pay_later_settings( $c );
$this->migrate_smart_button_settings( $c );
$this->migrate_three_d_secure_setting();
Expand All @@ -89,6 +91,8 @@ function () use ( $c ) {
$this->initialize_wc_bookings_compat_layer( $c );
}

$this->initialize_blueprint_compat_layer( $c );

add_action( 'woocommerce_paypal_payments_gateway_migrate', static fn() => delete_transient( 'ppcp_has_ppec_subscriptions' ) );

$this->legacy_ui_card_payment_mapping( $c );
Expand Down Expand Up @@ -553,6 +557,22 @@ static function ( WC_Order $wc_order, CartData $cart_data ) use ( $container ):
);
}

/**
* Sets up the WooCommerce Blueprint compatibility layer.
*
* @param ContainerInterface $container The Container.
* @return void
*/
private function initialize_blueprint_compat_layer( ContainerInterface $container ): void {
$is_blueprint_available = $container->get( 'compat.blueprint.is_available' );
if ( ! $is_blueprint_available ) {
return;
}

$blueprint_bootstrap = $container->get( 'compat.blueprint.bootstrap' );
$blueprint_bootstrap->init();
}

/**
* Responsible to keep the credit card payment configuration backwards
* compatible with the legacy UI.
Expand Down Expand Up @@ -582,4 +602,77 @@ static function ( bool $is_acdc ) use ( $container ): bool {
}
);
}

/**
* Add temporary admin page for manual blueprint export testing.
*
* @param ContainerInterface $c The Container.
*/
private function add_blueprint_export_test_page( ContainerInterface $c ): void {
add_action('admin_menu', function() use ($c) {
add_submenu_page(
'woocommerce',
'PayPal Blueprint Export',
'PayPal Blueprint Export',
'manage_woocommerce',
'ppcp-blueprint-export',
function() use ($c) {
// Handle export BEFORE any output
if ( isset($_POST['export_blueprint']) && check_admin_referer('ppcp_export_blueprint') ) {

// Get all registered exporters
$all_exporters = apply_filters('wooblueprint_exporters', array());

$steps = array();

// Add PayPal Settings step
$paypal_exporter = $c->get('compat.blueprint.paypal_settings_exporter');
$steps[] = $paypal_exporter->export()->prepare_json_array();

// Find and add wcPaymentGateways step
foreach ($all_exporters as $exporter) {
if ($exporter->get_step_name() === 'wcPaymentGateways') {
$steps[] = $exporter->export()->prepare_json_array();
break;
}
}

// Create proper blueprint structure
$blueprint = array(
'landingPage' => '/wp-admin/admin.php?page=wc-settings&tab=checkout',
'steps' => $steps
);

if ( ob_get_level() ) {
ob_end_clean();
}

header('Content-Type: application/json');
header('Content-Disposition: attachment; filename="paypal-blueprint-' . date('Y-m-d-His') . '.json"');
echo wp_json_encode( $blueprint, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES );
exit;
}

// Only show UI if not exporting.
?>
<div class="wrap">
<h1>PayPal Settings Blueprint Export</h1>
<p>Export your PayPal Payments settings and WooCommerce payment gateways as a Blueprint file.</p>
<form method="post">
<?php wp_nonce_field('ppcp_export_blueprint'); ?>
<p><strong>This will export:</strong></p>
<ul>
<li>PayPal Payments settings (paypalSettings)</li>
<li>WooCommerce Payment Gateway settings (wcPaymentGateways)</li>
</ul>
<p>
<input type="submit" name="export_blueprint" class="button button-primary" value="Export Blueprint">
</p>
</form>
</div>
<?php
}
);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php
/**
* PayPal Blueprint Bootstrap - Registers exporters and importers.
*
* @package WooCommerce\PayPalCommerce\Compat\WooCommerceBlueprint
*/

declare(strict_types=1);

namespace WooCommerce\PayPalCommerce\Compat\WooCommerceBlueprint;

/**
* Bootstrap class for PayPal Blueprint functionality.
*/
class PayPalBlueprintBootstrap {

/**
* PayPal Settings Exporter instance.
*
* @var PayPalSettingsExporter
*/
private PayPalSettingsExporter $exporter;

/**
* PayPal Settings Importer instance.
*
* @var PayPalSettingsImporter
*/
private PayPalSettingsImporter $importer;

/**
* Constructor.
*
* @param PayPalSettingsExporter $exporter PayPal settings exporter.
* @param PayPalSettingsImporter $importer PayPal settings importer.
*/
public function __construct(
PayPalSettingsExporter $exporter,
PayPalSettingsImporter $importer
) {
$this->exporter = $exporter;
$this->importer = $importer;
}

/**
* Initialize the PayPal Blueprint functionality.
*
* @return void
*/
public function init(): void {
$this->register_hooks();
}

/**
* Register WordPress hooks.
*
* @return void
*/
private function register_hooks(): void {
add_filter( 'wooblueprint_exporters', array( $this, 'register_exporters' ) );
add_filter( 'wooblueprint_importers', array( $this, 'register_importers' ) );
}

/**
* Register PayPal exporters.
*
* @param array $exporters Existing exporters.
* @return array
*/
public function register_exporters( array $exporters ): array {
$exporters[] = $this->exporter;
return $exporters;
}

/**
* Register PayPal importers.
*
* @param array $importers Existing importers.
* @return array
*/
public function register_importers( array $importers ): array {
$importers[] = $this->importer;
return $importers;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php
/**
* PayPal Settings Blueprint Exporter.
*
* @package WooCommerce\PayPalCommerce\Compat\WooCommerceBlueprint
*/

declare(strict_types=1);

namespace WooCommerce\PayPalCommerce\Compat\WooCommerceBlueprint;

use Automattic\WooCommerce\Blueprint\Exporters\StepExporter;
use Automattic\WooCommerce\Blueprint\Exporters\HasAlias;
use Automattic\WooCommerce\Blueprint\Steps\SetSiteOptions;
use Automattic\WooCommerce\Blueprint\Steps\Step;

/**
* PayPal Settings Exporter for WooCommerce Blueprint.
*/
class PayPalSettingsExporter implements StepExporter, HasAlias {

/**
* Sentinel value to detect if option doesn't exist.
*/
private const OPTION_NOT_FOUND = '__PAYPAL_OPTION_NOT_FOUND__';

/**
* PayPal-related options to export (excluding transients and core gateway settings).
*
* @var array<string>
*/
private const PAYPAL_OPTIONS = array(
// Core PPCP data settings.
'woocommerce-ppcp-data-common',
'woocommerce-ppcp-data-onboarding',
'woocommerce-ppcp-data-payment',
'woocommerce-ppcp-data-settings',
'woocommerce-ppcp-data-styling',
// Main PPCP configuration.
'woocommerce-ppcp-settings',
'woocommerce-ppcp-version',
'woocommerce-ppcp-is-new-merchant',
// Admin and migration flags.
'woocommerce_ppcp-admin-notices',
'woocommerce_ppcp-is_pay_later_settings_migrated',
'woocommerce_ppcp-is_smart_button_settings_migrated',
'woocommerce_ppcp-settings-should-use-old-ui',
// Individual payment method settings (non-gateway).
'woocommerce_venmo_settings',
'woocommerce_pay-later_settings',
);

/**
* Export PayPal settings.
*
* @return Step
*/
public function export(): Step {
$paypal_options = array();

foreach ( self::PAYPAL_OPTIONS as $option_name ) {
$value = get_option( $option_name, self::OPTION_NOT_FOUND );
if ( self::OPTION_NOT_FOUND !== $value ) {
$paypal_options[ $option_name ] = $value;
}
}

return new SetSiteOptions( $paypal_options );
}

/**
* Get step name.
*
* @return string
*/
public function get_step_name(): string {
return SetSiteOptions::get_step_name();
}

/**
* Get alias for this exporter.
*
* @return string
*/
public function get_alias(): string {
return 'paypalSettings';
}

/**
* Return label used in the frontend.
*
* @return string
*/
public function get_label(): string {
return __( 'PayPal Settings', 'woocommerce-paypal-payments' );
}

/**
* Return the description used in the frontend.
*
* @return string
*/
public function get_description(): string {
return __( 'Exports PayPal Payments settings and configuration options.', 'woocommerce-paypal-payments' );
}

/**
* Check if user has capability to export PayPal settings.
*
* @return bool
*/
public function check_step_capabilities(): bool {
return current_user_can( 'manage_woocommerce' ) && current_user_can( 'manage_options' );
}
}
Loading
Loading