Prevented the COD payment gateway's "enable_for_methods" option loading outside of correct use-cases

Note: The tests fail in this commit because of the defines. Ran individually there are no problems, but I'm going to make another PR to merge in a package to make testing constants possible, and then come back to fix this after it gets merged.
This commit is contained in:
Christopher Allford 2020-01-28 14:33:53 -08:00
parent 47d6311d1e
commit bb09a8a4ea
2 changed files with 131 additions and 26 deletions

View File

@ -63,42 +63,46 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
*/
public function init_form_fields() {
$options = array();
$data_store = WC_Data_Store::load( 'shipping-zone' );
$raw_zones = $data_store->get_zones();
$options = array();
foreach ( $raw_zones as $raw_zone ) {
$zones[] = new WC_Shipping_Zone( $raw_zone );
}
// We only want to load the options if they'll be shown to the user.
if ( $this->is_accessing_settings() ) {
$data_store = WC_Data_Store::load( 'shipping-zone' );
$raw_zones = $data_store->get_zones();
$zones[] = new WC_Shipping_Zone( 0 );
foreach ( $raw_zones as $raw_zone ) {
$zones[] = new WC_Shipping_Zone( $raw_zone );
}
foreach ( WC()->shipping()->load_shipping_methods() as $method ) {
$zones[] = new WC_Shipping_Zone( 0 );
$options[ $method->get_method_title() ] = array();
foreach ( WC()->shipping()->load_shipping_methods() as $method ) {
// Translators: %1$s shipping method name.
$options[ $method->get_method_title() ][ $method->id ] = sprintf( __( 'Any "%1$s" method', 'woocommerce' ), $method->get_method_title() );
$options[ $method->get_method_title() ] = array();
foreach ( $zones as $zone ) {
// Translators: %1$s shipping method name.
$options[ $method->get_method_title() ][ $method->id ] = sprintf( __( 'Any "%1$s" method', 'woocommerce' ), $method->get_method_title() );
$shipping_method_instances = $zone->get_shipping_methods();
foreach ( $zones as $zone ) {
foreach ( $shipping_method_instances as $shipping_method_instance_id => $shipping_method_instance ) {
$shipping_method_instances = $zone->get_shipping_methods();
if ( $shipping_method_instance->id !== $method->id ) {
continue;
foreach ( $shipping_method_instances as $shipping_method_instance_id => $shipping_method_instance ) {
if ( $shipping_method_instance->id !== $method->id ) {
continue;
}
$option_id = $shipping_method_instance->get_rate_id();
// Translators: %1$s shipping method title, %2$s shipping method id.
$option_instance_title = sprintf( __( '%1$s (#%2$s)', 'woocommerce' ), $shipping_method_instance->get_title(), $shipping_method_instance_id );
// Translators: %1$s zone name, %2$s shipping method instance name.
$option_title = sprintf( __( '%1$s – %2$s', 'woocommerce' ), $zone->get_id() ? $zone->get_zone_name() : __( 'Other locations', 'woocommerce' ), $option_instance_title );
$options[ $method->get_method_title() ][ $option_id ] = $option_title;
}
$option_id = $shipping_method_instance->get_rate_id();
// Translators: %1$s shipping method title, %2$s shipping method id.
$option_instance_title = sprintf( __( '%1$s (#%2$s)', 'woocommerce' ), $shipping_method_instance->get_title(), $shipping_method_instance_id );
// Translators: %1$s zone name, %2$s shipping method instance name.
$option_title = sprintf( __( '%1$s – %2$s', 'woocommerce' ), $zone->get_id() ? $zone->get_zone_name() : __( 'Other locations', 'woocommerce' ), $option_instance_title );
$options[ $method->get_method_title() ][ $option_id ] = $option_title;
}
}
}
@ -208,6 +212,37 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
return parent::is_available();
}
/**
* Checks to see whether or not the admin settings are being accessed by the current request.
*
* @return bool
*/
private function is_accessing_settings() {
// phpcs:disable WordPress.Security.NonceVerification.Recommended
$is_admin = is_admin();
if ( $is_admin && ( ! isset( $_REQUEST['page'] ) || 'wc-settings' !== $_REQUEST['page'] ) ) {
$is_admin = false;
}
if ( $is_admin && ( ! isset( $_REQUEST['tab'] ) || 'checkout' !== $_REQUEST['tab'] ) ) {
$is_admin = false;
}
if ( $is_admin && ( ! isset( $_REQUEST['section'] ) || 'cod' !== $_REQUEST['section'] ) ) {
$is_admin = false;
}
$is_rest = ( defined( 'REST_REQUEST' ) && true === REST_REQUEST );
if ( $is_rest ) {
global $wp;
if ( ! isset( $wp->query_vars['rest_route'] ) || false === strpos( $wp->query_vars['rest_route'], '/payment_gateways' ) ) {
$is_rest = false;
}
}
// phpcs:enable
return $is_admin || $is_rest;
}
/**
* Converts the chosen rate IDs generated by Shipping Methods to a canonical 'method_id:instance_id' format.
*

View File

@ -0,0 +1,70 @@
<?php
/**
* Contains tests for the COD Payment Gateway.
*/
/**
* Class WC_Tests_Payment_Gateway_COD
*/
class WC_Tests_Payment_Gateway_COD extends WC_Unit_Test_Case {
/**
* Make sure that the options for the "enable_for_methods" setting are not loaded by default.
*/
public function test_method_options_not_loaded_universally() {
$gateway = new WC_Gateway_COD();
$form_fields = $gateway->get_form_fields();
$this->assertArrayHasKey( 'enable_for_methods', $form_fields );
$this->assertEmpty( $form_fields['enable_for_methods']['options'] );
}
/**
* Make sure that the options for the "enable_for_methods" setting are loaded on the admin page.
*/
public function test_method_options_loaded_for_admin_page() {
// Make sure we are seen as on the correct page for this.
define( 'WP_ADMIN', true );
$_REQUEST['page'] = 'wc-settings';
$_REQUEST['tab'] = 'checkout';
$_REQUEST['section'] = 'cod';
$gateway = new WC_Gateway_COD();
$form_fields = $gateway->get_form_fields();
$this->assertArrayHasKey( 'enable_for_methods', $form_fields );
$this->assertNotEmpty( $form_fields['enable_for_methods']['options'] );
}
/**
* Make sure that the options for the "enable_for_methods" setting are not loaded for API requests that don't need it.
*/
public function test_method_options_not_loaded_for_incorrect_api() {
define( 'REST_REQUEST', true );
$GLOBALS['wp']->query_vars['rest_route'] = '/wc/v2/products';
$gateway = new WC_Gateway_COD();
$form_fields = $gateway->get_form_fields();
$this->assertArrayHasKey( 'enable_for_methods', $form_fields );
$this->assertEmpty( $form_fields['enable_for_methods']['options'] );
}
/**
* Make sure that the options for the "enable_for_methods" setting are loaded for API requests that need it.
*/
public function test_method_options_loaded_for_correct_api() {
define( 'REST_REQUEST', true );
$GLOBALS['wp']->query_vars['rest_route'] = '/wc/v2/payment_gateways';
$gateway = new WC_Gateway_COD();
$form_fields = $gateway->get_form_fields();
$this->assertArrayHasKey( 'enable_for_methods', $form_fields );
$this->assertNotEmpty( $form_fields['enable_for_methods']['options'] );
}
}