Skip to content

Commit

Permalink
Merge pull request #99 from kidunot89/feature/delete-order-mutation
Browse files Browse the repository at this point in the history
deleteOrder mutation
  • Loading branch information
kidunot89 authored Jul 6, 2019
2 parents 2ea80df + 9cb22dd commit 9a8eb46
Show file tree
Hide file tree
Showing 11 changed files with 452 additions and 27 deletions.
2 changes: 2 additions & 0 deletions includes/class-actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
use WPGraphQL\Extensions\WooCommerce\Mutation\Cart_Add_Fee;
use WPGraphQL\Extensions\WooCommerce\Mutation\Order_Create;
use WPGraphQL\Extensions\WooCommerce\Mutation\Order_Update;
use WPGraphQL\Extensions\WooCommerce\Mutation\Order_Delete;

/**
* Class Actions
Expand Down Expand Up @@ -165,5 +166,6 @@ public static function graphql_register_types() {
Cart_Add_Fee::register_mutation();
Order_Create::register_mutation();
Order_Update::register_mutation();
Order_Delete::register_mutation();
}
}
75 changes: 70 additions & 5 deletions includes/data/mutation/class-order-mutation.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,28 @@
* Class - Order_Mutation
*/
class Order_Mutation {
/**
* Filterable authentication function.
*
* @param string $mutation Mutation being executed.
* @param array $input Input data describing order.
* @param AppContext $context AppContext instance.
* @param ResolveInfo $info ResolveInfo instance.
*
* @return boolean
*/
public static function authorized( $mutation = 'create', $input, $context, $info ) {
$post_type_object = get_post_type_object( 'shop_order' );

return apply_filters(
"authorized_to_{$mutation}_orders",
! current_user_can( $post_type_object->cap->create_posts ),
$input,
$context,
$info
);
}

/**
* Create an order.
*
Expand Down Expand Up @@ -42,11 +64,31 @@ public static function create_order( $input, $context, $info ) {
}
}

/**
* Action called before order is created.
*
* @param WC_Order $order WC_Order instance.
* @param array $input Input data describing order.
* @param AppContext $context Request AppContext instance.
* @param ResolveInfo $info Request ResolveInfo instance.
*/
do_action( 'woocommerce_graphql_before_order_create', $input, $context, $info );

$order = \wc_create_order( $args );
if ( is_wp_error( $order ) ) {
throw UserError( $order->get_error_code() . $order->get_message() );
}

/**
* Action called after order is created.
*
* @param WC_Order $order WC_Order instance.
* @param array $input Input data describing order.
* @param AppContext $context Request AppContext instance.
* @param ResolveInfo $info Request ResolveInfo instance.
*/
do_action( 'woocommerce_graphql_after_order_create', $order, $input, $context, $info );

return $order->get_id();
}

Expand All @@ -69,6 +111,17 @@ public static function add_items( $input, $order_id, $context, $info ) {
foreach ( $input as $key => $items ) {
if ( array_key_exists( $key, $item_group_keys ) ) {
$type = $item_group_keys[ $key ];

/**
* Action called before an item group is added to an order.
*
* @param array $items Item data being added.
* @param integer $order_id ID of target order.
* @param AppContext $context Request AppContext instance.
* @param ResolveInfo $info Request ResolveInfo instance.
*/
do_action( "woocommerce_graphql_before_{$type}s_added_to_order", $items, $order_id, $context, $info );

foreach ( $items as $item_data ) {
// Create Order item.
$item_id = ( ! empty( $item_data['id'] ) && \WC_Order_Factory::get_order_item( $item_data['id'] ) )
Expand All @@ -84,6 +137,16 @@ public static function add_items( $input, $order_id, $context, $info ) {
$item_keys = self::get_order_item_keys( $type );
self::map_input_to_item( $item_id, $item_data, $item_keys, $context, $info );
}

/**
* Action called after an item group is added to an order.
*
* @param array $items Item data being added.
* @param integer $order_id ID of target order.
* @param AppContext $context Request AppContext instance.
* @param ResolveInfo $info Request ResolveInfo instance.
*/
do_action( "woocommerce_graphql_after_{$type}s_added_to_order", $items, $order_id, $context, $info );
}
}
}
Expand Down Expand Up @@ -255,7 +318,7 @@ public static function add_order_meta( $order_id, $input, $context, $info ) {
}

/**
* Action called before order meta saved.
* Action called before changes to order meta are saved.
*
* @param WC_Order $order WC_Order instance.
* @param array $props Order props array.
Expand Down Expand Up @@ -337,13 +400,15 @@ public static function validate_customer( $input ) {
/**
* Purge object when creating.
*
* @param WC_Order $order Object data.
* @param WC_Order|Order $order Object data.
* @param boolean $force_delete Delete or put in trash.
*
* @return bool
* @throws UserError Failed to delete order.
*/
public static function purge( $order ) {
if ( $order instanceof WC_Order ) {
return $order->delete( true );
public static function purge( $order, $force_delete = true ) {
if ( is_callable( array( $order, 'delete' ) ) ) {
return $order->delete( $force_delete );
}

return false;
Expand Down
22 changes: 22 additions & 0 deletions includes/model/class-crud-cpt.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

namespace WPGraphQL\Extensions\WooCommerce\Model;

use GraphQL\Error\UserError;
use WPGraphQL\Model\Model;

/**
Expand Down Expand Up @@ -88,6 +89,27 @@ protected function is_private() {
return false;
}

/**
* Wrapper function for deleting
*
* @param boolean $force_delete Should the data be deleted permanently.
*
* @return boolean
* @throws UserError Not authorized.
*/
public function delete( $force_delete = false ) {
if ( ! current_user_can( $this->post_type_object->cap->edit_posts ) ) {
throw new UserError(
__(
'User does not have the capabilities necessary to delete this object.',
'wp-graphql-woocommerce'
)
);
}

return $this->data->delete( $force_delete );
}

/**
* Retrieve the cap to check if the data should be restricted for the crud object
*
Expand Down
2 changes: 1 addition & 1 deletion includes/model/class-order.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ protected function init() {
return ! is_null( $this->data->needs_processing() ) ? $this->data->needs_processing() : null;
},
'downloadableItems' => function() {
return ! is_null( $this->data->get_downloadable_items() ) ? $this->data->get_downloadable_items() : null;
return ! empty( $this->data->get_downloadable_items() ) ? $this->data->get_downloadable_items() : null;
},
/**
* Connection resolvers fields
Expand Down
16 changes: 12 additions & 4 deletions includes/mutation/class-order-create.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,8 @@ public static function get_output_fields() {
*/
public static function mutate_and_get_payload() {
return function( $input, AppContext $context, ResolveInfo $info ) {
$post_type_object = get_post_type_object( 'shop_order' );

if ( ! current_user_can( $post_type_object->cap->create_posts ) ) {
throw new UserError( __( 'Sorry, you are not allowed to create a new order.', 'wp-graphql-woocommerce' ) );
if ( Order_Mutation::authorized( 'create', $input, $context, $info ) ) {
throw new UserError( __( 'User does not have the capabilities necessary to create an order.', 'wp-graphql-woocommerce' ) );
}

// Create order.
Expand Down Expand Up @@ -181,6 +179,16 @@ public static function mutate_and_get_payload() {
);
}

/**
* Action called after order is created.
*
* @param WC_Order $order WC_Order instance.
* @param array $input Input data describing order.
* @param AppContext $context Request AppContext instance.
* @param ResolveInfo $info Request ResolveInfo instance.
*/
do_action( 'woocommerce_graphql_after_order_create', $order, $input, $context, $info );

return array( 'id' => $order->get_id() );
} catch ( \Exception $e ) {
Order_Mutation::purge( $order );
Expand Down
159 changes: 159 additions & 0 deletions includes/mutation/class-order-delete.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<?php
/**
* Mutation - deleteOrder
*
* Registers mutation for delete an order.
*
* @package WPGraphQL\Extensions\WooCommerce\Mutation
* @since 0.2.0
*/

namespace WPGraphQL\Extensions\WooCommerce\Mutation;

use GraphQL\Error\UserError;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQLRelay\Relay;
use WPGraphQL\AppContext;
use WPGraphQL\Extensions\WooCommerce\Data\Mutation\Order_Mutation;
use WPGraphQL\Extensions\WooCommerce\Model\Order;

/**
* Class Order_Delete
*/
class Order_Delete {
/**
* Registers mutation
*/
public static function register_mutation() {
register_graphql_mutation(
'deleteOrder',
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_merge(
array(
'id' => array(
'type' => 'ID',
'description' => __( 'Order global ID', 'wp-graphql-woocommerce' ),
),
'orderId' => array(
'type' => 'Int',
'description' => __( 'Order WP ID', 'wp-graphql-woocommerce' ),
),
'forceDelete' => array(
'type' => 'Boolean',
'description' => __( 'Delete or simply place in trash.', 'wp-graphql-woocommerce' ),
),
)
);

return $input_fields;
}

/**
* Defines the mutation output field configuration
*
* @return array
*/
public static function get_output_fields() {
return array(
'order' => array(
'type' => 'Order',
'resolve' => function( $payload ) {
return $payload['order'];
},
),
);
}

/**
* Defines the mutation data modification closure.
*
* @return callable
*/
public static function mutate_and_get_payload() {
return function( $input, AppContext $context, ResolveInfo $info ) {
if ( Order_Mutation::authorized( 'delete', $input, $context, $info ) ) {
throw new UserError( __( 'User does not have the capabilities necessary to delete an order.', 'wp-graphql-woocommerce' ) );
}

// Retrieve order ID.
$order_id = null;
if ( ! empty( $input['id'] ) ) {
$id_components = Relay::fromGlobalId( $input['id'] );
if ( empty( $id_components['id'] ) || empty( $id_components['type'] ) ) {
throw new UserError( __( 'The "id" provided is invalid', 'wp-graphql-woocommerce' ) );
}
$order_id = absint( $id_components['id'] );
} elseif ( ! empty( $input['orderId'] ) ) {
$order_id = absint( $input['orderId'] );
} else {
throw new UserError( __( 'No order ID provided.', 'wp-graphql-woocommerce' ) );
}

$force_delete = false;
if ( ! empty( $input['forceDelete'] ) ) {
$force_delete = $input['forceDelete'];
}

// Get Order model instance for output.
$order = new Order( $order_id );

// Cache items to prevent null value errors.
// @codingStandardsIgnoreStart
$order->downloadableItems;
$order->get_items();
$order->get_items( 'fee' );
$order->get_items( 'shipping' );
$order->get_items( 'tax' );
$order->get_items( 'coupon' );
// @codingStandardsIgnoreEnd.

/**
* Action called before order is deleted.
*
* @param WC_Order $order WC_Order instance.
* @param array $input Input data describing order.
* @param AppContext $context Request AppContext instance.
* @param ResolveInfo $info Request ResolveInfo instance.
*/
do_action( 'woocommerce_graphql_before_order_delete', $order, $input, $context, $info );

// Delete order.
$success = Order_Mutation::purge( \WC_Order_Factory::get_order( $order->ID ), $force_delete );

if ( ! $success ) {
throw new UserError(
sprintf(
/* translators: Deletion failed message */
__( 'Removal of Order %d failed', 'wp-graphql-woocommerce' ),
$order->get_id()
)
);
}

/**
* Action called before order is deleted.
*
* @param WC_Order $order WC_Order instance.
* @param array $input Input data describing order
* @param AppContext $context Request AppContext instance.
* @param ResolveInfo $info Request ResolveInfo instance.
*/
do_action( 'woocommerce_graphql_after_order_delete', $order, $input, $context, $info );

return array( 'order' => $order );
};
}
}
Loading

0 comments on commit 9a8eb46

Please sign in to comment.