Automattic\WooCommerce\Internal\Admin\Settings

Payments::process_payment_provider_statesprivateWC 1.0

Process the payment providers states and update the snapshots in the DB.

Method of the class: Payments{}

No Hooks.

Returns

null. Nothing (null).

Usage

// private - for code of main (parent) class only
$result = $this->process_payment_provider_states( $payment_providers ): void;
$payment_providers(array) (required)
The payment providers details list.

Payments::process_payment_provider_states() code WC 10.9.4

private function process_payment_provider_states( array $payment_providers ): void {
	// Read the current state snapshots from the DB.
	$snapshots = get_option( self::PAYMENTS_PROVIDER_STATE_SNAPSHOTS_KEY, array() );
	if ( ! is_array( $snapshots ) ) {
		$snapshots = array();
	}

	$default_snapshot = array(
		'extension_active'  => false,
		'account_connected' => false,
		'account_test_mode' => false,
		'needs_setup'       => false,
		'test_mode'         => false,
	);

	// Iterate through the payment providers and generate their updated snapshots.
	// We will use the provider's plugin slug as the key for the snapshot to ensure uniqueness.
	// For now, we will only focus on the provider state for official extensions, not all the gateways.
	$new_snapshots = array();
	foreach ( $payment_providers as $provider ) {
		if ( empty( $provider['plugin']['slug'] ) ||
			empty( $provider['id'] ) ||
			empty( $provider['state'] ) || ! is_array( $provider['state'] ) ||
			empty( $provider['onboarding']['state'] ) || ! is_array( $provider['onboarding']['state'] ) ||
			empty( $provider['_type'] ) ||
			PaymentsProviders::TYPE_GATEWAY !== $provider['_type'] ||
			empty( $provider['_suggestion_id'] )
		) {
			continue;
		}

		$snapshot_key = $provider['plugin']['slug'];

		// Since we are going after the provider general state, not that of the specific gateway,
		// we only need to look at the first found gateway from a given provider.
		if ( isset( $new_snapshots[ $snapshot_key ] ) ) {
			continue;
		}

		// If we don't have an already existing snapshot for this provider, we create one with default values.
		// This way we can track changes even for the first time we see a provider.
		if ( ! isset( $snapshots[ $snapshot_key ] ) ) {
			$snapshots[ $snapshot_key ] = $default_snapshot;
		} else {
			// Make sure the old snapshot has the same keys as the default one.
			$snapshots[ $snapshot_key ] = array_merge( $default_snapshot, $snapshots[ $snapshot_key ] );
			// Remove any keys that are not in the default snapshot.
			$snapshot_keys = array_keys( $default_snapshot );
			foreach ( $snapshots[ $snapshot_key ] as $key => $v ) {
				if ( ! in_array( $key, $snapshot_keys, true ) ) {
					unset( $snapshots[ $snapshot_key ][ $key ] );
				}
			}

			// Always sort the old snapshot by keys to ensure consistency.
			ksort( $snapshots[ $snapshot_key ] );
		}

		// Generate the new snapshot for the provider.
		$new_snapshots[ $snapshot_key ] = array(
			'extension_active'  => true, // The extension is definitely active since we have a gateway from it.
			'account_connected' => $provider['state']['account_connected'] ?? $default_snapshot['account_connected'],
			'account_test_mode' => $provider['onboarding']['state']['test_mode'] ?? $default_snapshot['account_test_mode'],
			'needs_setup'       => $provider['state']['needs_setup'] ?? $default_snapshot['needs_setup'],
			'test_mode'         => $provider['state']['test_mode'] ?? $default_snapshot['test_mode'],
		);

		// Always sort the new snapshot by keys to ensure consistency.
		ksort( $new_snapshots[ $snapshot_key ] );
	}

	// Provider snapshots that are not in the new snapshots but were in the old ones should be kept but marked as inactive.
	foreach ( $snapshots as $snapshot_key => $old_snapshot ) {
		if ( ! isset( $new_snapshots[ $snapshot_key ] ) ) {
			$new_snapshots[ $snapshot_key ]                     = $old_snapshot;
			$new_snapshots[ $snapshot_key ]['extension_active'] = false;
		}
	}

	// Always order the new snapshots by keys to ensure DB updates happen only when the data changes.
	ksort( $new_snapshots );

	// Save the new snapshots back to the DB, as soon as we have them ready to avoid concurrent state change tracking.
	// No need to autoload this option since it will be used only in the Payments Settings area.
	$result = update_option( self::PAYMENTS_PROVIDER_STATE_SNAPSHOTS_KEY, $new_snapshots, false );
	if ( ! $result ) {
		// If we didn't update the option, we don't need to track any changes.
		return;
	}

	try {
		$this->maybe_track_providers_state_change( $payment_providers, $snapshots, $new_snapshots );
	} catch ( \Throwable $exception ) {
		// If we failed to track the changes, we log the error but don't throw it.
		// This is to avoid breaking the Payments Settings page.
		SafeGlobalFunctionProxy::wc_get_logger()->error(
			'Failed to track payment providers state change: ' . $exception->getMessage(),
			array(
				'source' => 'settings-payments',
			)
		);
	}
}