mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-08-31 06:52:50 +08:00
✨ Refactor the model class, add the new sanitation
This commit is contained in:
parent
6bbb1d83e6
commit
5f90949c7d
3 changed files with 248 additions and 43 deletions
99
modules/ppcp-settings/src/Data/AbstractDataModel.php
Normal file
99
modules/ppcp-settings/src/Data/AbstractDataModel.php
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
/**
|
||||
* Abstract Data Model Base Class
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Settings\Data
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Settings\Data;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Abstract class AbstractDataModel
|
||||
*
|
||||
* Provides a base implementation for data models that can be serialized to and from arrays,
|
||||
* and provide persistence capabilities.
|
||||
*/
|
||||
abstract class AbstractDataModel {
|
||||
/**
|
||||
* Stores the model data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected array $data = array();
|
||||
|
||||
/**
|
||||
* Option key for WordPress storage.
|
||||
* Must be overridden by the child class!
|
||||
*/
|
||||
protected const OPTION_KEY = '';
|
||||
|
||||
/**
|
||||
* Default values for the model.
|
||||
* Child classes should override this method to define their default structure.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function get_defaults() : array;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @throws RuntimeException If the OPTION_KEY is not defined in the child class.
|
||||
*/
|
||||
public function __construct() {
|
||||
if ( empty( static::OPTION_KEY ) ) {
|
||||
throw new RuntimeException( 'OPTION_KEY must be defined in child class.' );
|
||||
}
|
||||
|
||||
$this->data = $this->get_defaults();
|
||||
$this->load();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the model data from WordPress options.
|
||||
*/
|
||||
public function load() : void {
|
||||
$saved_data = get_option( static::OPTION_KEY, array() );
|
||||
$this->data = array_merge( $this->data, $saved_data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the model data to WordPress options.
|
||||
*/
|
||||
public function save() : void {
|
||||
update_option( static::OPTION_KEY, $this->data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all model data as an array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function to_array() : array {
|
||||
return array_merge( array(), $this->data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all model data from an array.
|
||||
*
|
||||
* @param array $data The model data.
|
||||
*/
|
||||
public function from_array( array $data ) : void {
|
||||
foreach ( $data as $key => $value ) {
|
||||
if ( ! array_key_exists( $key, $this->data ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$setter = "set_$key";
|
||||
if ( method_exists( $this, $setter ) ) {
|
||||
$this->$setter( $value );
|
||||
} else {
|
||||
$this->data[ $key ] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Settings container class
|
||||
* Onboarding Profile class
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Settings\Data
|
||||
*/
|
||||
|
@ -10,33 +10,125 @@ declare( strict_types = 1 );
|
|||
namespace WooCommerce\PayPalCommerce\Settings\Data;
|
||||
|
||||
/**
|
||||
* Class OnboardingProfile
|
||||
*
|
||||
* This class serves as a container for managing the onboarding profile details
|
||||
* within the WooCommerce PayPal Commerce plugin. It provides methods to retrieve
|
||||
* and save the onboarding profile data using WordPress options.
|
||||
*/
|
||||
class OnboardingProfile {
|
||||
class OnboardingProfile extends AbstractDataModel {
|
||||
|
||||
/**
|
||||
* Options key where profile details are stored.
|
||||
* Option key where profile details are stored.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private const KEY = 'woocommerce-ppcp-data-onboarding';
|
||||
protected const OPTION_KEY = 'woocommerce-ppcp-data-onboarding';
|
||||
|
||||
/**
|
||||
* Returns the current onboarding profile details.
|
||||
* Get default values for the model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_data() : array {
|
||||
return get_option( self::KEY, array() );
|
||||
protected function get_defaults() : array {
|
||||
return array(
|
||||
'step' => 0,
|
||||
'use_sandbox' => false,
|
||||
'use_manual_connection' => false,
|
||||
'client_id' => '',
|
||||
'client_secret' => '',
|
||||
);
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
/**
|
||||
* Gets the 'step' setting.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_step() : int {
|
||||
return (int) $this->data['step'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the onboarding profile details.
|
||||
* Sets the 'step' setting.
|
||||
*
|
||||
* @param array $data The profile details to save.
|
||||
* @param int $step Whether to use sandbox mode.
|
||||
*/
|
||||
public function save_data( array $data ) : void {
|
||||
update_option( self::KEY, $data );
|
||||
public function set_step( int $step ) : void {
|
||||
$this->data['step'] = $step;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 'use sandbox' setting.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function get_use_sandbox() : bool {
|
||||
return (bool) $this->data['use_sandbox'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the 'use sandbox' setting.
|
||||
*
|
||||
* @param bool $use_sandbox Whether to use sandbox mode.
|
||||
*/
|
||||
public function set_use_sandbox( bool $use_sandbox ) : void {
|
||||
$this->data['use_sandbox'] = $use_sandbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 'use manual connection' setting.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function get_use_manual_connection() : bool {
|
||||
return (bool) $this->data['use_manual_connection'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the 'use manual connection' setting.
|
||||
*
|
||||
* @param bool $use_manual_connection Whether to use manual connection.
|
||||
*/
|
||||
public function set_use_manual_connection( bool $use_manual_connection ) : void {
|
||||
$this->data['use_manual_connection'] = $use_manual_connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the client ID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_client_id() : string {
|
||||
return $this->data['client_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the client ID.
|
||||
*
|
||||
* @param string $client_id The client ID.
|
||||
*/
|
||||
public function set_client_id( string $client_id ) : void {
|
||||
$this->data['client_id'] = sanitize_text_field( $client_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the client secret.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_client_secret() : string {
|
||||
return $this->data['client_secret'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the client secret.
|
||||
*
|
||||
* @param string $client_secret The client secret.
|
||||
*/
|
||||
public function set_client_secret( string $client_secret ) : void {
|
||||
$this->data['client_secret'] = sanitize_text_field( $client_secret );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@ use WooCommerce\PayPalCommerce\Settings\Data\OnboardingProfile;
|
|||
/**
|
||||
* REST controller for the onboarding module.
|
||||
*
|
||||
* Responsible for persisting and loading the state of the onboarding wizard.
|
||||
* This API acts as the intermediary between the "external world" and our
|
||||
* internal data model.
|
||||
*/
|
||||
class OnboardingRestEndpoint extends RestEndpoint {
|
||||
/**
|
||||
|
@ -32,7 +33,35 @@ class OnboardingRestEndpoint extends RestEndpoint {
|
|||
*
|
||||
* @var OnboardingProfile
|
||||
*/
|
||||
protected $profile;
|
||||
protected OnboardingProfile $profile;
|
||||
|
||||
/**
|
||||
* Field mapping for request to profile transformation.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private array $field_map = array(
|
||||
'step' => array(
|
||||
'js_name' => 'step',
|
||||
'sanitize' => 'to_number',
|
||||
),
|
||||
'use_sandbox' => array(
|
||||
'js_name' => 'useSandbox',
|
||||
'sanitize' => 'to_boolean',
|
||||
),
|
||||
'use_manual_connection' => array(
|
||||
'js_name' => 'useManualConnection',
|
||||
'sanitize' => 'to_boolean',
|
||||
),
|
||||
'client_id' => array(
|
||||
'js_name' => 'clientId',
|
||||
'sanitize' => 'sanitize_text_field',
|
||||
),
|
||||
'client_secret' => array(
|
||||
'js_name' => 'clientSecret',
|
||||
'sanitize' => 'sanitize_text_field',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -73,50 +102,35 @@ class OnboardingRestEndpoint extends RestEndpoint {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns an object with all details of the current onboarding wizard
|
||||
* progress.
|
||||
* Returns all details of the current onboarding wizard progress.
|
||||
*
|
||||
* @return WP_REST_Response The current state of the onboarding wizard.
|
||||
*/
|
||||
public function get_details() : WP_REST_Response {
|
||||
$details = $this->profile->get_data();
|
||||
$js_data = $this->sanitize_for_javascript(
|
||||
$this->profile->to_array(),
|
||||
$this->field_map
|
||||
);
|
||||
|
||||
return rest_ensure_response( $details );
|
||||
return rest_ensure_response( $js_data );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Receives an object with onboarding details and persists it in the DB.
|
||||
* Updates onboarding details based on the request.
|
||||
*
|
||||
* @param WP_REST_Request $request Full data about the request.
|
||||
*
|
||||
* @return WP_REST_Response The current state of the onboarding wizard.
|
||||
* @return WP_REST_Response The updated state of the onboarding wizard.
|
||||
*/
|
||||
public function update_details( WP_REST_Request $request ) : WP_REST_Response {
|
||||
$details = $this->profile->get_data();
|
||||
$wp_data = $this->sanitize_for_wordpress(
|
||||
$request->get_params(),
|
||||
$this->field_map
|
||||
);
|
||||
|
||||
$get_param = fn( $key ) => wc_clean( wp_unslash( $request->get_param( $key ) ) );
|
||||
$this->profile->from_array( $wp_data );
|
||||
$this->profile->save();
|
||||
|
||||
$raw_step = $get_param( 'step' );
|
||||
$raw_completed = $get_param( 'completed' );
|
||||
$raw_use_sandbox = $get_param( 'useSandbox' );
|
||||
$raw_use_manual_connection = $get_param( 'useManualConnection' );
|
||||
|
||||
if ( is_numeric( $raw_step ) ) {
|
||||
$details['step'] = intval( $raw_step );
|
||||
}
|
||||
if ( null !== $raw_completed ) {
|
||||
$details['completed'] = (bool) $raw_completed;
|
||||
}
|
||||
if ( null !== $raw_use_sandbox ) {
|
||||
$details['useSandbox'] = (bool) $raw_use_sandbox;
|
||||
}
|
||||
if ( null !== $raw_use_manual_connection ) {
|
||||
$details['useManualConnection'] = (bool) $raw_use_manual_connection;
|
||||
}
|
||||
|
||||
$this->profile->save_data( $details );
|
||||
|
||||
return rest_ensure_response( $details );
|
||||
return $this->get_details();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue