self::get_input_fields(), 'outputFields' => self::get_output_fields(), 'mutateAndGetPayload' => [ self::class, 'mutate_and_get_payload' ], ] ); } /** * Defines the mutation input field configuration * * @return array */ public static function get_input_fields() { return [ 'country' => [ 'type' => 'String', 'description' => static function () { return __( 'Country code for the tax rate.', 'graphql-for-ecommerce' ); }, ], 'state' => [ 'type' => 'String', 'description' => static function () { return __( 'State code for the tax rate.', 'graphql-for-ecommerce' ); }, ], 'postcodes' => [ 'type' => [ 'list_of' => 'String' ], 'description' => static function () { return __( 'Postcodes for the tax rate.', 'graphql-for-ecommerce' ); }, ], 'cities' => [ 'type' => [ 'list_of' => 'String' ], 'description' => static function () { return __( 'Cities for the tax rate.', 'graphql-for-ecommerce' ); }, ], 'rate' => [ 'type' => 'String', 'description' => static function () { return __( 'Tax rate.', 'graphql-for-ecommerce' ); }, ], 'name' => [ 'type' => 'String', 'description' => static function () { return __( 'Tax rate name.', 'graphql-for-ecommerce' ); }, ], 'priority' => [ 'type' => 'Int', 'description' => static function () { return __( 'Tax rate priority.', 'graphql-for-ecommerce' ); }, ], 'compound' => [ 'type' => 'Boolean', 'description' => static function () { return __( 'Whether the tax rate is compound.', 'graphql-for-ecommerce' ); }, ], 'shipping' => [ 'type' => 'Boolean', 'description' => static function () { return __( 'Whether the tax rate is applied to shipping.', 'graphql-for-ecommerce' ); }, ], 'order' => [ 'type' => 'Int', 'description' => static function () { return __( 'Tax rate order.', 'graphql-for-ecommerce' ); }, ], 'class' => [ 'type' => 'TaxClassEnum', 'description' => static function () { return __( 'Tax rate class.', 'graphql-for-ecommerce' ); }, ], ]; } /** * Defines the mutation output field configuration * * @return array */ public static function get_output_fields() { return [ 'taxRate' => [ 'type' => 'TaxRate', 'resolve' => static function ( array $payload, array $args, AppContext $context ) { return $context->get_loader( 'tax_rate' )->load( $payload['tax_rate_id'] ); }, ], ]; } /** * Defines the mutation data modification closure. * * @param array $input Mutation input. * @param \WPGraphQL\AppContext $context AppContext instance. * @param \GraphQL\Type\Definition\ResolveInfo $info ResolveInfo instance. Can be * use to get info about the current node in the GraphQL tree. * * @throws \GraphQL\Error\UserError Invalid ID provided | Lack of capabilities. * * @return array */ public static function mutate_and_get_payload( $input, AppContext $context, ResolveInfo $info ) { $id = ! empty( $input['id'] ) ? Utils::get_database_id_from_id( $input['id'] ) : null; if ( false === $id ) { throw new UserError( __( 'Invalid ID provided.', 'graphql-for-ecommerce' ) ); } $action = ! $id ? 'create' : 'update'; $permission = ! $id ? 'create' : 'edit'; if ( ! \wc_rest_check_manager_permissions( 'settings', $permission ) ) { throw new UserError( sprintf( /* translators: %s: permission */ __( 'Sorry, you are not allowed to %s tax rates.', 'graphql-for-ecommerce' ), $permission ), \rest_authorization_required_code() ); } $current = null; if ( ! empty( $id ) ) { /** * @var object{ * tax_rate_id: int, * tax_rate_class: string, * tax_rate_country: string, * tax_rate_state: string, * tax_rate: string, * tax_rate_name: string, * tax_rate_priority: int, * tax_rate_compound: bool, * tax_rate_shipping: bool, * tax_rate_order: int, * tax_rate_city: string, * tax_rate_postcode: string, * tax_rate_postcodes: string, * tax_rate_cities: string * } $current */ $current = \WC_Tax::_get_tax_rate( $id, OBJECT ); } $data = []; $fields = [ 'country' => 'tax_rate_country', 'state' => 'tax_rate_state', 'rate' => 'tax_rate', 'name' => 'tax_rate_name', 'priority' => 'tax_rate_priority', 'compound' => 'tax_rate_compound', 'shipping' => 'tax_rate_shipping', 'order' => 'tax_rate_order', 'class' => 'tax_rate_class', ]; foreach ( $fields as $key => $field ) { if ( ! isset( $input[ $key ] ) ) { continue; } if ( $current && $current->$field === $input[ $key ] ) { continue; } switch ( $field ) { case 'tax_rate_priority': case 'tax_rate_compound': case 'tax_rate_shipping': case 'tax_rate_order': $data[ $field ] = $input[ $key ]; break; case 'tax_rate_class': $data[ $field ] = 'standard' !== $input[ $key ] ? $input[ $key ] : ''; break; default: $data[ $field ] = $input[ $key ]; break; } } /** * Filter tax rate data before creating/updating. * * @param array $data The tax rate data. * @param array $input Request input. */ $data = apply_filters( "graphql_woocommerce_before_tax_rate_{$action}_data", $data, $input ); if ( ! $id ) { $id = \WC_Tax::_insert_tax_rate( $data ); } else { \WC_Tax::_update_tax_rate( $id, $data ); } if ( isset( $input['cities'] ) ) { \WC_Tax::_update_tax_rate_cities( $id, join( ';', $input['cities'] ) ); } if ( isset( $input['postcodes'] ) ) { \WC_Tax::_update_tax_rate_postcodes( $id, join( ';', $input['postcodes'] ) ); } /** * Filter tax rate object before responding. * * @param int $tax_rate_id The shipping method object. * @param array $input Request input. */ do_action( "graphql_woocommerce_tax_rate_{$action}", $id, $input ); return [ 'tax_rate_id' => $id ]; } }