Merge pull request #13596 from woocommerce/fix/payment-token-crud-pattern

Update Payment Tokens to follow the same pattern for custom data as other objects.
This commit is contained in:
Mike Jolley 2017-03-15 15:38:31 +00:00 committed by GitHub
commit 77cade928a
6 changed files with 184 additions and 91 deletions

View File

@ -12,7 +12,7 @@ include_once( WC_ABSPATH . 'includes/legacy/abstract-wc-legacy-payment-token.php
* examples: Credit Card, eCheck.
*
* @class WC_Payment_Token
* @version 2.7.0
* @version 3.0.0
* @since 2.6.0
* @package WooCommerce/Abstracts
* @category Abstract Class
@ -32,6 +32,12 @@ include_once( WC_ABSPATH . 'includes/legacy/abstract-wc-legacy-payment-token.php
'type' => '',
);
/**
* Token Type (CC, eCheck, or a custom type added by an extension).
* Set by child classes.
*/
protected $type = '';
/**
* Initialize a payment token.
*
@ -45,10 +51,7 @@ include_once( WC_ABSPATH . 'includes/legacy/abstract-wc-legacy-payment-token.php
* @param mixed $token
*/
public function __construct( $token = '' ) {
// Set token type (cc, echeck)
if ( ! empty( $this->type ) ) {
$this->set_type( $this->type );
}
parent::__construct( $token );
if ( is_numeric( $token ) ) {
$this->set_id( $token );
@ -86,13 +89,14 @@ include_once( WC_ABSPATH . 'includes/legacy/abstract-wc-legacy-payment-token.php
/**
* Returns the type of this payment token (CC, eCheck, or something else).
* Overwritten by child classes.
*
* @since 2.6.0
* @param string $context
* @param string $deprecated Deprecated since WooCommerce 3.0
* @return string Payment Token Type (CC, eCheck)
*/
public function get_type( $context = 'view' ) {
return $this->get_prop( 'type', $context );
public function get_type( $deprecated = '' ) {
return $this->type;
}
/**
@ -100,11 +104,11 @@ include_once( WC_ABSPATH . 'includes/legacy/abstract-wc-legacy-payment-token.php
* Get's overwritten by child classes.
*
* @since 2.6.0
* @param string $context
* @param string $deprecated Deprecated since WooCommerce 3.0
* @return string
*/
public function get_display_name( $context = 'view' ) {
return $this->get_type( $context );
public function get_display_name( $deprecated = '' ) {
return $this->get_type();
}
/**
@ -156,16 +160,6 @@ include_once( WC_ABSPATH . 'includes/legacy/abstract-wc-legacy-payment-token.php
$this->set_prop( 'token', $token );
}
/**
* Sets the type of this payment token (CC, eCheck, or something else).
*
* @since 2.7.0
* @param string Payment Token Type (CC, eCheck)
*/
public function set_type( $type ) {
return $this->set_prop( 'type', $type );
}
/**
* Set the user ID for the user associated with this order.
*
@ -221,12 +215,6 @@ include_once( WC_ABSPATH . 'includes/legacy/abstract-wc-legacy-payment-token.php
if ( empty( $token ) ) {
return false;
}
$type = $this->get_prop( 'type', 'edit' );
if ( empty( $type ) ) {
return false;
}
return true;
}

View File

@ -6,7 +6,7 @@ if ( ! defined( 'ABSPATH' ) ) {
/**
* WC Payment Token Data Store: Custom Table.
*
* @version 2.7.0
* @version 3.0.0
* @category Class
* @author WooThemes
*/
@ -18,10 +18,15 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
*/
protected $meta_type = 'payment_token';
/**
* If we have already saved our extra data, don't do automatic / default handling.
*/
protected $extra_data_saved = false;
/**
* Create a new payment token in the database.
*
* @since 2.7.0
* @since 3.0.0
* @param WC_Payment_Token $token
*/
public function create( &$token ) {
@ -47,6 +52,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
$wpdb->insert( $wpdb->prefix . 'woocommerce_payment_tokens', $payment_token_data );
$token_id = $wpdb->insert_id;
$token->set_id( $token_id );
$this->save_extra_data( $token, true );
$token->save_meta_data();
$token->apply_changes();
@ -61,7 +67,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
/**
* Update a payment token.
*
* @since 2.7.0
* @since 3.0.0
* @param WC_Payment_Token $token
*/
public function update( &$token ) {
@ -72,11 +78,13 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
global $wpdb;
$updated_props = array();
$payment_token_data = array();
$props = array( 'gateway_id', 'token', 'user_id', 'type' );
$core_props = array( 'gateway_id', 'token', 'user_id', 'type' );
$changed_props = array_keys( $token->get_changes() );
foreach ( $changed_props as $prop ) {
if ( ! in_array( $prop, $core_props ) ) {
continue;
}
$updated_props[] = $prop;
$payment_token_data[ $prop ] = $token->{"get_" . $prop}( 'edit' );
}
@ -89,6 +97,8 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
);
}
$updated_extra_props = $this->save_extra_data( $token );
$updated_props = array_merge( $updated_props, $updated_extra_props );
$token->save_meta_data();
$token->apply_changes();
@ -104,7 +114,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
/**
* Remove a payment token from the database.
*
* @since 2.7.0
* @since 3.0.0
* @param WC_Payment_Token $token
* @param bool $force_delete
*/
@ -118,7 +128,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
/**
* Read a token from the database.
*
* @since 2.7.0
* @since 3.0.0
* @param WC_Payment_Token $token
*/
public function read( &$token ) {
@ -130,6 +140,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
'gateway_id' => $data->gateway_id,
'default' => $data->is_default,
) );
$this->read_extra_data( $token );
$token->read_meta_data();
$token->set_object_read( true );
do_action( 'woocommerce_payment_token_loaded', $token );
@ -138,12 +149,60 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
}
}
/**
* Read extra data associated with the token (like last4 digits of a card for expiry dates).
*
* @param WC_Payment_Token
* @since 3.0.0
*/
protected function read_extra_data( &$token ) {
foreach ( $token->get_extra_data_keys() as $key ) {
$function = 'set_' . $key;
if ( is_callable( array( $token, $function ) ) ) {
$token->{$function}( get_post_meta( $token->get_id(), $key, true ) );
}
}
}
/**
* Saves extra token data as meta.
*
* @since 3.0.0
* @param $token WC_Token
* @param $force bool
* @return array List of updated props.
*/
protected function save_extra_data( &$token, $force = false ) {
if ( $this->extra_data_saved ) {
return array();
}
$updated_props = array();
$extra_data_keys = $token->get_extra_data_keys();
$meta_key_to_props = array_combine( $extra_data_keys, $extra_data_keys );
$props_to_update = $force ? $meta_key_to_props : $this->get_props_to_update( $token, $meta_key_to_props );
foreach ( $extra_data_keys as $key ) {
if ( ! array_key_exists( $key, $props_to_update ) ) {
continue;
}
$function = 'get_' . $key;
if ( is_callable( array( $token, $function ) ) ) {
if ( update_post_meta( $token->get_id(), $key, $token->{$function}( 'edit' ) ) ) {
$updated_props[] = $key;
}
}
}
return $updated_props;
}
/**
* Returns an array of objects (stdObject) matching specific token critera.
* Accepts token_id, user_id, gateway_id, and type.
* Each object should contain the fields token_id, gateway_id, token, user_id, type, is_default.
*
* @since 2.7.0
* @since 3.0.0
* @param array $args
* @return array
*/
@ -191,7 +250,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
* Returns an stdObject of a token for a user's default token.
* Should contain the fields token_id, gateway_id, token, user_id, type, is_default.
*
* @since 2.7.0
* @since 3.0.0
* @param id $user_id
* @return object
*/
@ -207,7 +266,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
* Returns an stdObject of a token.
* Should contain the fields token_id, gateway_id, token, user_id, type, is_default.
*
* @since 2.7.0
* @since 3.0.0
* @param id $token_id
* @return object
*/
@ -222,7 +281,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
/**
* Returns metadata for a specific payment token.
*
* @since 2.7.0
* @since 3.0.0
* @param id $token_id
* @return array
*/
@ -233,7 +292,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
/**
* Get a token's type by ID.
*
* @since 2.7.0
* @since 3.0.0
* @param id $token_id
* @return string
*/
@ -250,7 +309,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
* looping through tokens and setting their statuses instead of creating a bunch
* of objects.
*
* @since 2.7.0
* @since 3.0.0
* @param id $token_id
* @return string
*/

View File

@ -6,23 +6,32 @@ if ( ! defined( 'ABSPATH' ) ) {
/**
* Legacy Payment Tokens.
* Payment Tokens were introduced in 2.6.0 with create and update as methods.
* Major CRUD changes occurred in 2.7, so these were deprecated (save and delete still work).
* Major CRUD changes occurred in 3.0, so these were deprecated (save and delete still work).
* This legacy class is for backwards compatibility in case any code called ->read, ->update or ->create
* directly on the object.
*
* @version 2.7.0
* @version 3.0.0
* @package WooCommerce/Classes
* @category Class
* @author WooCommerce
*/
abstract class WC_Legacy_Payment_Token extends WC_Data {
/**
* Sets the type of this payment token (CC, eCheck, or something else).
*
* @param string Payment Token Type (CC, eCheck)
*/
public function set_type( $type ) {
wc_deprecated_function( 'WC_Payment_Token::set_type', '3.0.0', 'Type cannot be overwritten.' );
}
/**
* Read a token by ID.
* @deprecated 2.7.0 - Init a token class with an ID.
* @deprecated 3.0.0 - Init a token class with an ID.
*/
public function read( $token_id ) {
wc_deprecated_function( 'WC_Payment_Token::read', '2.7', 'a new token class initialized with an ID.' );
wc_deprecated_function( 'WC_Payment_Token::read', '3.0.0', 'a new token class initialized with an ID.' );
$this->set_id( $token_id );
$data_store = WC_Data_Store::load( 'payment-token' );
$data_store->read( $this );
@ -30,10 +39,10 @@ abstract class WC_Legacy_Payment_Token extends WC_Data {
/**
* Update a token.
* @deprecated 2.7.0 - Use ::save instead.
* @deprecated 3.0.0 - Use ::save instead.
*/
public function update() {
wc_deprecated_function( 'WC_Payment_Token::update', '2.7', '::save instead.' );
wc_deprecated_function( 'WC_Payment_Token::update', '3.0.0', '::save instead.' );
$data_store = WC_Data_Store::load( 'payment-token' );
try {
$data_store->update( $this );
@ -44,10 +53,10 @@ abstract class WC_Legacy_Payment_Token extends WC_Data {
/**
* Create a token.
* @deprecated 2.7.0 - Use ::save instead.
* @deprecated 3.0.0 - Use ::save instead.
*/
public function create() {
wc_deprecated_function( 'WC_Payment_Token::create', '2.7', '::save instead.' );
wc_deprecated_function( 'WC_Payment_Token::create', '3.0.0', '::save instead.' );
$data_store = WC_Data_Store::load( 'payment-token' );
try {
$data_store->create( $this );

View File

@ -9,7 +9,7 @@ if ( ! defined( 'ABSPATH' ) ) {
* Representation of a payment token for credit cards.
*
* @class WC_Payment_Token_CC
* @version 2.7.0
* @version 3.0.0
* @since 2.6.0
* @category PaymentTokens
* @package WooCommerce/PaymentTokens
@ -20,10 +20,41 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
/** @protected string Token Type String. */
protected $type = 'CC';
/**
* Stores Credit Card payment token data.
*
* @var array
*/
protected $extra_data = array(
'last4' => '',
'expiry_year' => '',
'expiry_month' => '',
'card_type' => '',
);
/**
* Get type to display to user.
*
* @since 2.6.0
* @param string $deprecated Deprecated since WooCommerce 3.0
* @return string
*/
public function get_display_name( $deprecated = '' ) {
/* translators: 1: credit card type 2: last 4 digits 3: expiry month 4: expiry year */
$display = sprintf(
__( '%1$s ending in %2$s (expires %3$s/%4$s)', 'woocommerce' ),
wc_get_credit_card_type_label( $this->get_card_type() ),
$this->get_last4(),
$this->get_expiry_month(),
substr( $this->get_expiry_year(), 2 )
);
return $display;
}
/**
* Hook prefix
*
* @since 2.7.0
* @since 3.0.0
*/
protected function get_hook_prefix() {
return 'woocommerce_payment_token_cc_get_';
@ -73,25 +104,6 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
return true;
}
/**
* Get type to display to user.
*
* @since 2.6.0
* @param string $context
* @return string
*/
public function get_display_name( $context = 'view' ) {
/* translators: 1: credit card type 2: last 4 digits 3: expiry month 4: expiry year */
$display = sprintf(
__( '%1$s ending in %2$s (expires %3$s/%4$s)', 'woocommerce' ),
wc_get_credit_card_type_label( $this->get_card_type( $context ) ),
$this->get_last4( $context ),
$this->get_expiry_month( $context ),
substr( $this->get_expiry_year( $context ), 2 )
);
return $display;
}
/**
* Returns the card type (mastercard, visa, ...).
*
@ -100,7 +112,7 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
* @return string Card type
*/
public function get_card_type( $context = 'view' ) {
return $this->get_meta( 'card_type', true, $context );
return $this->get_prop( 'card_type', $context );
}
/**
@ -109,7 +121,7 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
* @param string $type
*/
public function set_card_type( $type ) {
$this->add_meta_data( 'card_type', $type, true );
$this->set_prop( 'card_type', $type );
}
/**
@ -120,7 +132,7 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
* @return string Expiration year
*/
public function get_expiry_year( $context = 'view' ) {
return $this->get_meta( 'expiry_year', true, $context );
return $this->get_prop( 'expiry_year', $context );
}
/**
@ -129,7 +141,7 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
* @param string $year
*/
public function set_expiry_year( $year ) {
$this->add_meta_data( 'expiry_year', $year, true );
$this->set_prop( 'expiry_year', $year );
}
/**
@ -140,7 +152,7 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
* @return string Expiration month
*/
public function get_expiry_month( $context = 'view' ) {
return $this->get_meta( 'expiry_month', true, $context );
return $this->get_prop( 'expiry_month', $context );
}
/**
@ -149,7 +161,7 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
* @param string $month
*/
public function set_expiry_month( $month ) {
$this->add_meta_data( 'expiry_month', str_pad( $month, 2, '0', STR_PAD_LEFT ), true );
$this->set_prop( 'expiry_month', str_pad( $month, 2, '0', STR_PAD_LEFT ) );
}
/**
@ -160,7 +172,7 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
* @return string Last 4 digits
*/
public function get_last4( $context = 'view' ) {
return $this->get_meta( 'last4', true, $context );
return $this->get_prop( 'last4', $context );
}
/**
@ -169,6 +181,6 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
* @param string $last4
*/
public function set_last4( $last4 ) {
$this->add_meta_data( 'last4', $last4, true );
$this->set_prop( 'last4', $last4 );
}
}

View File

@ -18,9 +18,29 @@ if ( ! defined( 'ABSPATH' ) ) {
*/
class WC_Payment_Token_eCheck extends WC_Payment_Token {
/** @protected string Token Type String */
/** @protected string Token Type String. */
protected $type = 'eCheck';
/**
* Stores eCheck payment token data.
*
* @var array
*/
protected $extra_data = array(
'last4' => '',
);
/**
* Get type to display to user.
*
* @since 2.6.0
* @param string $deprecated Deprecated since WooCommerce 3.0
* @return string
*/
public function get_display_name( $deprecated = '' ) {
return __( 'eCheck', 'woocommerce' );
}
/**
* Hook prefix
*
@ -50,17 +70,6 @@ class WC_Payment_Token_eCheck extends WC_Payment_Token {
return true;
}
/**
* Get type to display to user.
*
* @since 2.6.0
* @param string $context
* @return string
*/
public function get_display_name( $context = 'view' ) {
return __( 'eCheck', 'woocommerce' );
}
/**
* Returns the last four digits.
*
@ -69,7 +78,7 @@ class WC_Payment_Token_eCheck extends WC_Payment_Token {
* @return string Last 4 digits
*/
public function get_last4( $context = 'view' ) {
return $this->get_meta( 'last4', true, $context );
return $this->get_prop( 'last4', $context );
}
/**
@ -78,6 +87,6 @@ class WC_Payment_Token_eCheck extends WC_Payment_Token {
* @param string $last4
*/
public function set_last4( $last4 ) {
$this->add_meta_data( 'last4', $last4, true );
$this->set_prop( 'last4', $last4 );
}
}

View File

@ -95,4 +95,20 @@ class WC_Tests_Payment_Token_CC extends WC_Unit_Test_Case {
$token_read = new WC_Payment_Token_CC( $token_id );
$this->assertEquals( '1234', $token_read->get_last4() );
}
/*
* Test saving a new value in a token after it has been created.
* @since 3.0.0
*/
public function test_wc_payment_token_cc_updates_after_create() {
$token = WC_Helper_Payment_Token::create_cc_token();
$token_id = $token->get_id();
$this->assertEquals( '1234', $token->get_last4() );
$token->set_last4( '4321' );
$token->set_user_id( 3 );
$token->save();
$this->assertEquals( '4321', $token->get_last4() );
$this->assertEquals( 3, $token->get_user_id() );
}
}