abstract-wc-order-data-store-cpt.php
2 months ago
abstract-wc-order-item-type-data-store.php
7 months ago
class-wc-coupon-data-store-cpt.php
2 months ago
class-wc-customer-data-store-session.php
9 months ago
class-wc-customer-data-store.php
3 months ago
class-wc-customer-download-data-store.php
3 years ago
class-wc-customer-download-log-data-store.php
1 year ago
class-wc-data-store-wp.php
9 months ago
class-wc-order-data-store-cpt.php
2 months ago
class-wc-order-item-coupon-data-store.php
8 years ago
class-wc-order-item-data-store.php
2 months ago
class-wc-order-item-fee-data-store.php
8 years ago
class-wc-order-item-product-data-store.php
3 years ago
class-wc-order-item-shipping-data-store.php
1 year ago
class-wc-order-item-tax-data-store.php
6 years ago
class-wc-order-refund-data-store-cpt.php
2 months ago
class-wc-payment-token-data-store.php
4 months ago
class-wc-product-data-store-cpt.php
2 months ago
class-wc-product-grouped-data-store-cpt.php
3 months ago
class-wc-product-variable-data-store-cpt.php
1 month ago
class-wc-product-variation-data-store-cpt.php
9 months ago
class-wc-shipping-zone-data-store.php
5 months ago
class-wc-webhook-data-store.php
2 years ago
class-wc-payment-token-data-store.php
373 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Class WC_Payment_Token_Data_Store file. |
| 4 | * |
| 5 | * @package WooCommerce\DataStores |
| 6 | */ |
| 7 | |
| 8 | if ( ! defined( 'ABSPATH' ) ) { |
| 9 | exit; |
| 10 | } |
| 11 | |
| 12 | /** |
| 13 | * WC Payment Token Data Store: Custom Table. |
| 14 | * |
| 15 | * @version 3.0.0 |
| 16 | */ |
| 17 | class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Object_Data_Store_Interface, WC_Payment_Token_Data_Store_Interface { |
| 18 | |
| 19 | /** |
| 20 | * Meta type. Payment tokens are a new object type. |
| 21 | * |
| 22 | * @var string |
| 23 | */ |
| 24 | protected $meta_type = 'payment_token'; |
| 25 | |
| 26 | /** |
| 27 | * If we have already saved our extra data, don't do automatic / default handling. |
| 28 | * |
| 29 | * @var bool |
| 30 | */ |
| 31 | protected $extra_data_saved = false; |
| 32 | |
| 33 | /** |
| 34 | * Create a new payment token in the database. |
| 35 | * |
| 36 | * @since 3.0.0 |
| 37 | * |
| 38 | * @param WC_Payment_Token $token Payment token object. |
| 39 | * |
| 40 | * @throws Exception Throw exception if invalid or missing payment token fields. |
| 41 | */ |
| 42 | public function create( &$token ) { |
| 43 | if ( false === $token->validate() ) { |
| 44 | throw new Exception( __( 'Invalid or missing payment token fields.', 'woocommerce' ) ); |
| 45 | } |
| 46 | |
| 47 | global $wpdb; |
| 48 | if ( ! $token->is_default() && $token->get_user_id() > 0 ) { |
| 49 | $default_token = WC_Payment_Tokens::get_customer_default_token( $token->get_user_id() ); |
| 50 | if ( is_null( $default_token ) ) { |
| 51 | $token->set_default( true ); |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | $payment_token_data = array( |
| 56 | 'gateway_id' => $token->get_gateway_id( 'edit' ), |
| 57 | 'token' => $token->get_token( 'edit' ), |
| 58 | 'user_id' => $token->get_user_id( 'edit' ), |
| 59 | 'type' => $token->get_type( 'edit' ), |
| 60 | ); |
| 61 | |
| 62 | $wpdb->insert( $wpdb->prefix . 'woocommerce_payment_tokens', $payment_token_data ); |
| 63 | $token_id = $wpdb->insert_id; |
| 64 | $token->set_id( $token_id ); |
| 65 | $this->save_extra_data( $token, true ); |
| 66 | $token->save_meta_data(); |
| 67 | $token->apply_changes(); |
| 68 | |
| 69 | // Make sure all other tokens are not set to default. |
| 70 | if ( $token->is_default() && $token->get_user_id() > 0 ) { |
| 71 | WC_Payment_Tokens::set_users_default( $token->get_user_id(), $token_id ); |
| 72 | } |
| 73 | |
| 74 | do_action( 'woocommerce_new_payment_token', $token_id, $token ); |
| 75 | } |
| 76 | |
| 77 | /** |
| 78 | * Update a payment token. |
| 79 | * |
| 80 | * @since 3.0.0 |
| 81 | * |
| 82 | * @param WC_Payment_Token $token Payment token object. |
| 83 | * |
| 84 | * @throws Exception Throw exception if invalid or missing payment token fields. |
| 85 | */ |
| 86 | public function update( &$token ) { |
| 87 | if ( false === $token->validate() ) { |
| 88 | throw new Exception( __( 'Invalid or missing payment token fields.', 'woocommerce' ) ); |
| 89 | } |
| 90 | |
| 91 | global $wpdb; |
| 92 | |
| 93 | $updated_props = array(); |
| 94 | $core_props = array( 'gateway_id', 'token', 'user_id', 'type' ); |
| 95 | $changed_props = array_keys( $token->get_changes() ); |
| 96 | |
| 97 | foreach ( $changed_props as $prop ) { |
| 98 | if ( ! in_array( $prop, $core_props, true ) ) { |
| 99 | continue; |
| 100 | } |
| 101 | $updated_props[] = $prop; |
| 102 | $payment_token_data[ $prop ] = $token->{'get_' . $prop}( 'edit' ); |
| 103 | } |
| 104 | |
| 105 | if ( ! empty( $payment_token_data ) ) { |
| 106 | $wpdb->update( |
| 107 | $wpdb->prefix . 'woocommerce_payment_tokens', |
| 108 | $payment_token_data, |
| 109 | array( 'token_id' => $token->get_id() ) |
| 110 | ); |
| 111 | } |
| 112 | |
| 113 | $updated_extra_props = $this->save_extra_data( $token ); |
| 114 | $updated_props = array_merge( $updated_props, $updated_extra_props ); |
| 115 | $token->save_meta_data(); |
| 116 | $token->apply_changes(); |
| 117 | |
| 118 | // Make sure all other tokens are not set to default. |
| 119 | if ( $token->is_default() && $token->get_user_id() > 0 ) { |
| 120 | WC_Payment_Tokens::set_users_default( $token->get_user_id(), $token->get_id() ); |
| 121 | } |
| 122 | |
| 123 | do_action( 'woocommerce_payment_token_object_updated_props', $token, $updated_props ); |
| 124 | do_action( 'woocommerce_payment_token_updated', $token->get_id() ); |
| 125 | } |
| 126 | |
| 127 | /** |
| 128 | * Remove a payment token from the database. |
| 129 | * |
| 130 | * @since 3.0.0 |
| 131 | * @param WC_Payment_Token $token Payment token object. |
| 132 | * @param bool $force_delete Unused param. |
| 133 | */ |
| 134 | public function delete( &$token, $force_delete = false ) { |
| 135 | global $wpdb; |
| 136 | $wpdb->delete( $wpdb->prefix . 'woocommerce_payment_tokens', array( 'token_id' => $token->get_id() ), array( '%d' ) ); |
| 137 | $wpdb->delete( $wpdb->prefix . 'woocommerce_payment_tokenmeta', array( 'payment_token_id' => $token->get_id() ), array( '%d' ) ); |
| 138 | do_action( 'woocommerce_payment_token_deleted', $token->get_id(), $token ); |
| 139 | } |
| 140 | |
| 141 | /** |
| 142 | * Read a token from the database. |
| 143 | * |
| 144 | * @since 3.0.0 |
| 145 | * |
| 146 | * @param WC_Payment_Token $token Payment token object. |
| 147 | * |
| 148 | * @throws Exception Throw exception if invalid payment token. |
| 149 | */ |
| 150 | public function read( &$token ) { |
| 151 | global $wpdb; |
| 152 | |
| 153 | $data = $wpdb->get_row( |
| 154 | $wpdb->prepare( |
| 155 | "SELECT token, user_id, gateway_id, is_default FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d LIMIT 1", |
| 156 | $token->get_id() |
| 157 | ) |
| 158 | ); |
| 159 | |
| 160 | if ( $data ) { |
| 161 | $token->set_props( |
| 162 | array( |
| 163 | 'token' => $data->token, |
| 164 | 'user_id' => $data->user_id, |
| 165 | 'gateway_id' => $data->gateway_id, |
| 166 | 'default' => $data->is_default, |
| 167 | ) |
| 168 | ); |
| 169 | $this->read_extra_data( $token ); |
| 170 | $token->read_meta_data(); |
| 171 | $token->set_object_read( true ); |
| 172 | do_action( 'woocommerce_payment_token_loaded', $token ); |
| 173 | } else { |
| 174 | throw new Exception( __( 'Invalid payment token.', 'woocommerce' ) ); |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | /** |
| 179 | * Read extra data associated with the token (like last4 digits of a card for expiry dates). |
| 180 | * |
| 181 | * @param WC_Payment_Token $token Payment token object. |
| 182 | * @since 3.0.0 |
| 183 | */ |
| 184 | protected function read_extra_data( &$token ) { |
| 185 | foreach ( $token->get_extra_data_keys() as $key ) { |
| 186 | $function = 'set_' . $key; |
| 187 | if ( is_callable( array( $token, $function ) ) ) { |
| 188 | $token->{$function}( get_metadata( 'payment_token', $token->get_id(), $key, true ) ); |
| 189 | } |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | /** |
| 194 | * Saves extra token data as meta. |
| 195 | * |
| 196 | * @since 3.0.0 |
| 197 | * @param WC_Payment_Token $token Payment token object. |
| 198 | * @param bool $force By default, only changed props are updated. When this param is true all props are updated. |
| 199 | * @return array List of updated props. |
| 200 | */ |
| 201 | protected function save_extra_data( &$token, $force = false ) { |
| 202 | if ( $this->extra_data_saved ) { |
| 203 | return array(); |
| 204 | } |
| 205 | |
| 206 | $updated_props = array(); |
| 207 | $extra_data_keys = $token->get_extra_data_keys(); |
| 208 | $meta_key_to_props = ! empty( $extra_data_keys ) ? array_combine( $extra_data_keys, $extra_data_keys ) : array(); |
| 209 | $props_to_update = $force ? $meta_key_to_props : $this->get_props_to_update( $token, $meta_key_to_props ); |
| 210 | |
| 211 | foreach ( $extra_data_keys as $key ) { |
| 212 | if ( ! array_key_exists( $key, $props_to_update ) ) { |
| 213 | continue; |
| 214 | } |
| 215 | $function = 'get_' . $key; |
| 216 | if ( is_callable( array( $token, $function ) ) ) { |
| 217 | if ( update_metadata( 'payment_token', $token->get_id(), $key, $token->{$function}( 'edit' ) ) ) { |
| 218 | $updated_props[] = $key; |
| 219 | } |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | return $updated_props; |
| 224 | } |
| 225 | |
| 226 | /** |
| 227 | * Returns an array of objects (stdObject) matching specific token criteria. |
| 228 | * Accepts token_id, user_id, gateway_id, and type. |
| 229 | * Each object should contain the fields token_id, gateway_id, token, user_id, type, is_default. |
| 230 | * |
| 231 | * @since 3.0.0 |
| 232 | * @param array $args List of accepted args: token_id, gateway_id, user_id, type. |
| 233 | * @return array |
| 234 | */ |
| 235 | public function get_tokens( $args ) { |
| 236 | global $wpdb; |
| 237 | $args = wp_parse_args( |
| 238 | $args, |
| 239 | array( |
| 240 | 'token_id' => '', |
| 241 | 'user_id' => '', |
| 242 | 'gateway_id' => '', |
| 243 | 'type' => '', |
| 244 | ) |
| 245 | ); |
| 246 | |
| 247 | $sql = "SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens"; |
| 248 | $where = array( '1=1' ); |
| 249 | |
| 250 | if ( $args['token_id'] ) { |
| 251 | $token_ids = array_map( 'absint', is_array( $args['token_id'] ) ? $args['token_id'] : array( $args['token_id'] ) ); |
| 252 | $where[] = "token_id IN ('" . implode( "','", array_map( 'esc_sql', $token_ids ) ) . "')"; |
| 253 | } |
| 254 | |
| 255 | if ( $args['user_id'] ) { |
| 256 | $where[] = $wpdb->prepare( 'user_id = %d', absint( $args['user_id'] ) ); |
| 257 | } |
| 258 | |
| 259 | if ( $args['gateway_id'] ) { |
| 260 | $gateway_ids = array( $args['gateway_id'] ); |
| 261 | } else { |
| 262 | $gateways = WC_Payment_Gateways::instance(); |
| 263 | $gateway_ids = $gateways->get_payment_gateway_ids(); |
| 264 | } |
| 265 | |
| 266 | $page = isset( $args['page'] ) ? absint( $args['page'] ) : 1; |
| 267 | $posts_per_page = absint( isset( $args['limit'] ) ? $args['limit'] : get_option( 'posts_per_page' ) ); |
| 268 | |
| 269 | $pgstrt = absint( ( $page - 1 ) * $posts_per_page ) . ', '; |
| 270 | $limits = 'LIMIT ' . $pgstrt . $posts_per_page; |
| 271 | |
| 272 | $gateway_ids[] = ''; |
| 273 | $where[] = "gateway_id IN ('" . implode( "','", array_map( 'esc_sql', $gateway_ids ) ) . "')"; |
| 274 | |
| 275 | if ( $args['type'] ) { |
| 276 | $where[] = $wpdb->prepare( 'type = %s', $args['type'] ); |
| 277 | } |
| 278 | |
| 279 | // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared |
| 280 | $token_results = $wpdb->get_results( $sql . ' WHERE ' . implode( ' AND ', $where ) . ' ' . $limits ); |
| 281 | |
| 282 | return $token_results; |
| 283 | } |
| 284 | |
| 285 | /** |
| 286 | * Returns an stdObject of a token for a user's default token. |
| 287 | * Should contain the fields token_id, gateway_id, token, user_id, type, is_default. |
| 288 | * |
| 289 | * @since 3.0.0 |
| 290 | * @param int $user_id User ID. |
| 291 | * @return object |
| 292 | */ |
| 293 | public function get_users_default_token( $user_id ) { |
| 294 | global $wpdb; |
| 295 | return $wpdb->get_row( |
| 296 | $wpdb->prepare( |
| 297 | "SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE user_id = %d AND is_default = 1", |
| 298 | $user_id |
| 299 | ) |
| 300 | ); |
| 301 | } |
| 302 | |
| 303 | /** |
| 304 | * Returns an stdObject of a token. |
| 305 | * Should contain the fields token_id, gateway_id, token, user_id, type, is_default. |
| 306 | * |
| 307 | * @since 3.0.0 |
| 308 | * @param int $token_id Token ID. |
| 309 | * @return object |
| 310 | */ |
| 311 | public function get_token_by_id( $token_id ) { |
| 312 | global $wpdb; |
| 313 | return $wpdb->get_row( |
| 314 | $wpdb->prepare( |
| 315 | "SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d", |
| 316 | $token_id |
| 317 | ) |
| 318 | ); |
| 319 | } |
| 320 | |
| 321 | /** |
| 322 | * Returns metadata for a specific payment token. |
| 323 | * |
| 324 | * @since 3.0.0 |
| 325 | * @param int $token_id Token ID. |
| 326 | * @return array |
| 327 | */ |
| 328 | public function get_metadata( $token_id ) { |
| 329 | return get_metadata( 'payment_token', $token_id ); |
| 330 | } |
| 331 | |
| 332 | /** |
| 333 | * Get a token's type by ID. |
| 334 | * |
| 335 | * @since 3.0.0 |
| 336 | * @param int $token_id Token ID. |
| 337 | * @return string |
| 338 | */ |
| 339 | public function get_token_type_by_id( $token_id ) { |
| 340 | global $wpdb; |
| 341 | return $wpdb->get_var( |
| 342 | $wpdb->prepare( |
| 343 | "SELECT type FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d", |
| 344 | $token_id |
| 345 | ) |
| 346 | ); |
| 347 | } |
| 348 | |
| 349 | /** |
| 350 | * Update's a tokens default status in the database. Used for quickly |
| 351 | * looping through tokens and setting their statuses instead of creating a bunch |
| 352 | * of objects. |
| 353 | * |
| 354 | * @since 3.0.0 |
| 355 | * |
| 356 | * @param int $token_id Token ID. |
| 357 | * @param bool $status Whether given payment token is the default payment token or not. |
| 358 | * |
| 359 | * @return void |
| 360 | */ |
| 361 | public function set_default_status( $token_id, $status = true ) { |
| 362 | global $wpdb; |
| 363 | $wpdb->update( |
| 364 | $wpdb->prefix . 'woocommerce_payment_tokens', |
| 365 | array( 'is_default' => (int) $status ), |
| 366 | array( |
| 367 | 'token_id' => $token_id, |
| 368 | ) |
| 369 | ); |
| 370 | } |
| 371 | |
| 372 | } |
| 373 |