Skip to content

Commit

Permalink
Merge pull request wp-graphql#56 from kidunot89/feature/add-item-to-c…
Browse files Browse the repository at this point in the history
…art-mutation

addToCart mutation
  • Loading branch information
kidunot89 committed May 3, 2019
2 parents f964327 + 228a483 commit bd1d365
Show file tree
Hide file tree
Showing 11 changed files with 356 additions and 10 deletions.
5 changes: 4 additions & 1 deletion src/class-actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
use WPGraphQL\Extensions\WooCommerce\Type\WPEnum\Tax_Status;
use WPGraphQL\Extensions\WooCommerce\Type\WPEnum\WC_Connection_Orderby_Enum;
use WPGraphQL\Extensions\WooCommerce\Type\WPEnum\Tax_Rate_Connection_Orderby_Enum;
use WPGraphQL\Extensions\WooCommerce\Type\WPInputObject\Customer_Connection_Orderby_Input;
use WPGraphQL\Extensions\WooCommerce\Type\WPInputObject\Product_Attribute_Input;
use WPGraphQL\Extensions\WooCommerce\Type\WPInputObject\WC_Connection_Orderby_Input;
use WPGraphQL\Extensions\WooCommerce\Type\WPInputObject\Tax_Rate_Connection_Orderby_Input;
use WPGraphQL\Extensions\WooCommerce\Type\WPObject\Coupon_Type;
Expand Down Expand Up @@ -54,6 +54,7 @@
use WPGraphQL\Extensions\WooCommerce\Connection\Tax_Rates;
use WPGraphQL\Extensions\WooCommerce\Connection\Shipping_Methods;
use WPGraphQL\Extensions\WooCommerce\Connection\Cart_Items;
use WPGraphQL\Extensions\WooCommerce\Mutation\Cart_Add_Item;

/**
* Class Actions
Expand Down Expand Up @@ -92,6 +93,7 @@ public static function graphql_register_types() {
Tax_Rate_Connection_Orderby_Enum::register();

// InputObjects.
Product_Attribute_Input::register();
WC_Connection_Orderby_Input::register();
Tax_Rate_Connection_Orderby_Input::register();

Expand Down Expand Up @@ -128,5 +130,6 @@ public static function graphql_register_types() {
Cart_Items::register_connections();

// Mutations.
Cart_Add_Item::register_mutation();
}
}
35 changes: 35 additions & 0 deletions src/data/mutation/class-cart-mutation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php
/**
* Defines helper functions for executing mutations related to the cart.
*
* @package WPGraphQL\Extensions\WooCommerce\Data\Mutation
* @since 0.1.0
*/

namespace WPGraphQL\Extensions\WooCommerce\Data\Mutation;

/**
* Class - Cart_Mutation
*/
class Cart_Mutation {
/**
* Return array of data to be when defining a cart item
*
* @param array $input input data describing cart item.
* @param AppContext $context AppContext instance.
* @param ResolveInfo $info query info.
*
* @return array
*/
public static function prepare_cart_item( $input, $context, $info ) {
$cart_item_args = array(
$input['productId'],
! empty( $input['quantity'] ) ? $input['quantity'] : 1,
! empty( $input['variationId'] ) ? $input['variationId'] : 0,
! empty( $input['variation'] ) ? $input['variation'] : array(),
! empty( $input['extraData'] ) ? json_decode( $input['extraData'], true ) : array(),
);

return apply_filters( 'woocommerce_new_cart_item_data', $cart_item_args, $input, $context, $info );
}
}
112 changes: 112 additions & 0 deletions src/mutation/class-cart-add-item.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php
/**
* Mutation - addToCart
*
* Registers mutation for adding an cart item to the cart.
*
* @package WPGraphQL\Extensions\WooCommerce\Mutation
* @since 0.1.0
*/

namespace WPGraphQL\Extensions\WooCommerce\Mutation;

use GraphQL\Error\UserError;
use GraphQL\Type\Definition\ResolveInfo;
use WPGraphQL\AppContext;
use WPGraphQL\Extensions\WooCommerce\Data\Mutation\Cart_Mutation;

/**
* Class - Cart_Add_Item
*/
class Cart_Add_Item {
/**
* Registers mutation
*/
public static function register_mutation() {
register_graphql_mutation(
'addToCart',
array(
'inputFields' => self::get_input_fields(),
'outputFields' => self::get_output_fields(),
'mutateAndGetPayload' => self::mutate_and_get_payload(),
)
);
}

/**
* Defines the mutation input field configuration
*
* @return array
*/
public static function get_input_fields() {
$input_fields = array(
'productId' => array(
'type' => array( 'non_null' => 'Int' ),
'description' => __( 'Cart item product database ID or global ID', 'wp-graphql-woocommerce' ),
),
'quantity' => array(
'type' => 'Int',
'description' => __( 'Cart item quantity', 'wp-graphql-woocommerce' ),
),
'variationId' => array(
'type' => 'Int',
'description' => __( 'Cart item product variation database ID or global ID', 'wp-graphql-woocommerce' ),
),
'variation' => array(
'type' => array( 'list_of' => 'ProductAttributeInput' ),
'description' => __( 'Cart item product variation attributes', 'wp-graphql-woocommerce' ),
),
'extraData' => array(
'type' => 'String',
'description' => __( 'JSON string representation of extra cart item data', 'wp-graphql-woocommerce' ),
),
);

return $input_fields;
}

/**
* Defines the mutation output field configuration
*
* @return array
*/
public static function get_output_fields() {
return array(
'cartItem' => array(
'type' => 'CartItem',
'resolve' => function ( $payload ) {
$cart = WC()->cart;
$item = $cart->get_cart_item( $payload['key'] );

return $item;
},
),
);
}

/**
* Defines the mutation data modification closure.
*
* @return callable
*/
public static function mutate_and_get_payload() {
return function( $input, AppContext $context, ResolveInfo $info ) {
// Retrieve product database ID if relay ID provided.
if ( empty( $input['productId'] ) ) {
throw new UserError( __( 'No product ID provided', 'wp-graphql-woocommerce' ) );
}

// Prepare args for "add_to_cart" from input data.
$cart_item_args = Cart_Mutation::prepare_cart_item( $input, $context, $info );

// Get WC_Cart instance.
$cart = WC()->cart;

// Add item to cart and get item key.
$cart_item_key = $cart->add_to_cart( ...$cart_item_args );

// Return payload.
return array( 'key' => $cart_item_key );
};
}
}
Empty file removed src/mutation/dummy
Empty file.
34 changes: 34 additions & 0 deletions src/type/input/class-product-attribute-input.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/**
* WPInputObjectType - ProductAttributeInput
*
* @package \WPGraphQL\Extensions\WooCommerce\Type\WPInputObject
* @since 0.1.0
*/

namespace WPGraphQL\Extensions\WooCommerce\Type\WPInputObject;

/**
* Class Product_Attribute_Input
*/
class Product_Attribute_Input {
/**
* Registers type
*/
public static function register() {
register_graphql_input_type(
'ProductAttributeInput',
array(
'description' => __( 'Options for ordering the connection', 'wp-graphql-woocommerce' ),
'fields' => array(
'attribute' => array(
'type' => array( 'non_null' => 'String' ),
),
'attributeTerm' => array(
'type' => array( 'non_null' => 'String' ),
),
),
)
);
}
}
1 change: 1 addition & 0 deletions tests/_support/Helper/crud-helpers/product.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public function create_simple( $args = array() ) {
$args
)
);

return $product->save();
}

Expand Down
155 changes: 155 additions & 0 deletions tests/wpunit/CartMutationsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php

class CartMutationsTest extends \Codeception\TestCase\WPTestCase {
private $customer;
private $product;
private $variation;

public function setUp() {
parent::setUp();

$this->customer = $this->getModule('\Helper\Wpunit')->customer();
$this->product = $this->getModule('\Helper\Wpunit')->product();
$this->variation = $this->getModule('\Helper\Wpunit')->product_variation();
}

public function tearDown() {
// your tear down methods here

parent::tearDown();
}

private function addToCart( $input ) {
$mutation = '
mutation addToCart( $input: AddToCartInput! ) {
addToCart( input: $input ) {
clientMutationId
cartItem {
key
product {
id
}
variation {
id
}
quantity
subtotal
subtotalTax
total
tax
}
}
}
';

$variables = array( 'input' => $input );
$actual = graphql(
array(
'query' => $mutation,
'operation_name' => 'addToCart',
'variables' => $variables,
)
);

return $actual;
}

// tests
public function testAddToCartMutationWithProduct() {
$product_id = $this->product->create_simple();
$actual = $this->addToCart(
array(
'clientMutationId' => 'someId',
'productId' => $product_id,
'quantity' => 2,
)
);

// use --debug flag to view.
codecept_debug( $actual );

// Retrieve cart item key.
$this->assertArrayHasKey('data', $actual );
$this->assertArrayHasKey('addToCart', $actual['data'] );
$this->assertArrayHasKey('cartItem', $actual['data']['addToCart'] );
$this->assertArrayHasKey('key', $actual['data']['addToCart']['cartItem'] );
$key = $actual['data']['addToCart']['cartItem']['key'];

// Get newly created cart item data.
$cart = WC()->cart;
$cart_item = $cart->get_cart_item( $key );
$this->assertNotEmpty( $cart_item );

// Check cart item data.
$expected = array(
'data' => array(
'addToCart' => array(
'clientMutationId' => 'someId',
'cartItem' => array(
'key' => $cart_item['key'],
'product' => array(
'id' => $this->product->to_relay_id( $cart_item['product_id'] ),
),
'variation' => null,
'quantity' => $cart_item['quantity'],
'subtotal' => floatval( $cart_item['line_subtotal'] ),
'subtotalTax' => floatval( $cart_item['line_subtotal_tax'] ),
'total' => floatval( $cart_item['line_total'] ),
'tax' => floatval( $cart_item['line_tax'] ),
),
),
),
);
$this->assertEqualSets( $expected, $actual );
}

public function testAddToCartMutationWithProductVariation() {
$ids = $this->variation->create( $this->product->create_variable() );
$actual = $this->addToCart(
array(
'clientMutationId' => 'someId',
'productId' => $ids['product'],
'quantity' => 3,
'variationId' => $ids['variations'][0],
)
);

// use --debug flag to view.
codecept_debug( $actual );

// Retrieve cart item key.
$this->assertArrayHasKey('data', $actual );
$this->assertArrayHasKey('addToCart', $actual['data'] );
$this->assertArrayHasKey('cartItem', $actual['data']['addToCart'] );
$this->assertArrayHasKey('key', $actual['data']['addToCart']['cartItem'] );
$key = $actual['data']['addToCart']['cartItem']['key'];

// Get newly created cart item data.
$cart = WC()->cart;
$cart_item = $cart->get_cart_item( $key );
$this->assertNotEmpty( $cart_item );

$expected = array(
'data' => array(
'addToCart' => array(
'clientMutationId' => 'someId',
'cartItem' => array(
'key' => $cart_item['key'],
'product' => array(
'id' => $this->product->to_relay_id( $cart_item['product_id'] ),
),
'variation' => array(
'id' => $this->variation->to_relay_id( $cart_item['variation_id'] ),
),
'quantity' => $cart_item['quantity'],
'subtotal' => floatval( $cart_item['line_subtotal'] ),
'subtotalTax' => floatval( $cart_item['line_subtotal_tax'] ),
'total' => floatval( $cart_item['line_total'] ),
'tax' => floatval( $cart_item['line_tax'] ),
),
),
),
);
$this->assertEqualSets( $expected, $actual );
}
}
2 changes: 1 addition & 1 deletion vendor/autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInitf61da8dc20fec320ec89af9dd999f385::getLoader();
return ComposerAutoloaderInitced0ad5f23d05f710e81b6f8d889d8af::getLoader();
Loading

0 comments on commit bd1d365

Please sign in to comment.