Skip to content

Commit

Permalink
use wcpos include/exclude
Browse files Browse the repository at this point in the history
  • Loading branch information
kilbot committed Jan 4, 2024
1 parent 2bdc470 commit a9093bc
Show file tree
Hide file tree
Showing 10 changed files with 844 additions and 50 deletions.
77 changes: 51 additions & 26 deletions includes/API.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,40 +219,65 @@ public function rest_index( WP_REST_Response $response ): WP_REST_Response {
* @return mixed
*/
public function rest_pre_dispatch( $result, $server, $request ) {
// Get 'include' parameter from request
$include = $request->get_param( 'include' );
$max_length = 10000;

// Process 'include' parameter
$include = $request->get_param( 'include' );
if ( $include ) {
// Convert to array if it's not
$include_array = \is_array( $include ) ? $include : explode( ',', $include );
$include_string = implode( ',', $include_array );

// If the length of the 'include' string exceeds 10,000 characters, create a new array
if ( \strlen( $include_string ) > 10000 ) {
shuffle( $include_array ); // Shuffle the IDs to randomize

// Construct a random array of no more than 10,000 characters
$max_include_length = 10000;
$new_include_string = '';
$random_include_array = array();

foreach ( $include_array as $id ) {
if ( \strlen( $new_include_string . $id ) < $max_include_length ) {
$new_include_string .= $id . ',';
$random_include_array[] = $id;
} else {
break; // Stop when we reach the maximum length
}
}
$processed_include = $this->shorten_param_array( $include, $max_length );
$request->set_param( 'wcpos_include', $processed_include );
unset( $request['include'] );
}

// Set modified 'include' parameter back to request
$request->set_param( 'include', $random_include_array );
}
// Process 'exclude' parameter
$exclude = $request->get_param( 'exclude' );
if ( $exclude ) {
$processed_exclude = $this->shorten_param_array( $exclude, $max_length );
$request->set_param( 'wcpos_exclude', $processed_exclude );
unset( $request['exclude'] );
}

return $result;
}

/**
* Some servers have a limit on the number of include/exclude we can use in a request.
* Worst thing is there is often no error message, the request returns an empty response.
*
* For example, WP Engine has a limit of 1024 characters?
* https://wpengine.com/support/using-dev-tools/#Long_Queries_in_wp_db
*
* @TODO - For long queries, I should find a better solution than this.
*
* @param string|array $param_value
* @param int $max_length
* @return array
*/
private function shorten_param_array( $param_value, $max_length ) {
$param_array = is_array( $param_value ) ? $param_value : explode( ',', $param_value );
$param_string = implode( ',', $param_array );

if ( strlen( $param_string ) > $max_length ) {
shuffle( $param_array ); // Shuffle to randomize

$new_param_string = '';
$random_param_array = array();

foreach ( $param_array as $id ) {
if ( strlen( $new_param_string . $id ) < $max_length ) {
$new_param_string .= $id . ',';
$random_param_array[] = $id;
} else {
break; // Stop when maximum length is reached
}
}

return $random_param_array;
}

return $param_array;
}

/**
* Filters the REST API dispatch request result.
*
Expand Down
39 changes: 39 additions & 0 deletions includes/API/Customers_Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ class Customers_Controller extends WC_REST_Customers_Controller {
*/
protected $wcpos_user_search_results = array();

/**
* Store the request object for use in lifecycle methods.
*
* @var WP_REST_Request
*/
protected $wcpos_request;

/**
* Constructor.
*/
Expand Down Expand Up @@ -161,6 +168,7 @@ public function wcpos_validate_billing_email( WP_REST_Request $request ) {
* @param array $handler Route handler used for the request.
*/
public function wcpos_dispatch_request( $dispatch_result, WP_REST_Request $request, $route, $handler ) {
$this->wcpos_request = $request;
$this->wcpos_register_wc_rest_api_hooks();
$params = $request->get_params();

Expand Down Expand Up @@ -392,6 +400,11 @@ public function wcpos_customer_query( array $prepared_args, WP_REST_Request $req
$prepared_args['meta_query'] = $this->wcpos_combine_meta_queries( $search_meta_query, $prepared_args['meta_query'] );
}

// Handle include/exclude
if ( isset( $request['wcpos_include'] ) || isset( $request['wcpos_exclude'] ) ) {
add_action( 'pre_user_query', array( $this, 'wcpos_include_exclude_users_by_id' ) );
}

return $prepared_args;
}

Expand Down Expand Up @@ -430,4 +443,30 @@ public function wcpos_search_user_table( $query ): void {
$query->query_where = $modified_where;
}
}
/**
* Include or exclude users by ID.
*
* @param WP_User_Query $query
*/
public function wcpos_include_exclude_users_by_id( $query ) {
global $wpdb;
// Remove the hook
remove_action( 'pre_user_query', array( $this, 'wcpos_include_exclude_users_by_id' ) );
// Handle 'wcpos_include'
if ( ! empty( $this->wcpos_request['wcpos_include'] ) ) {
$include_ids = array_map( 'intval', (array) $this->wcpos_request['wcpos_include'] );
$ids_format = implode( ',', array_fill( 0, count( $include_ids ), '%d' ) );
$query->query_where .= $wpdb->prepare( " AND {$wpdb->users}.ID IN ($ids_format) ", $include_ids );
}
// Handle 'wcpos_exclude'
if ( ! empty( $this->wcpos_request['wcpos_exclude'] ) ) {
$exclude_ids = array_map( 'intval', (array) $this->wcpos_request['wcpos_exclude'] );
$ids_format = implode( ',', array_fill( 0, count( $exclude_ids ), '%d' ) );
$query->query_where .= $wpdb->prepare( " AND {$wpdb->users}.ID NOT IN ($ids_format) ", $exclude_ids );
}
}
}
56 changes: 37 additions & 19 deletions includes/API/Orders.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,28 @@ public function __construct( WP_REST_Request $request ) {

add_filter( 'rest_request_before_callbacks', array( $this, 'rest_request_before_callbacks' ), 10, 3 );
add_filter( 'woocommerce_rest_shop_order_object_query', array( $this, 'order_query' ), 10, 2 );
add_filter('woocommerce_rest_pre_insert_shop_order_object', array(
$this,
'pre_insert_shop_order_object',
), 10, 3);
add_filter(
'woocommerce_rest_pre_insert_shop_order_object',
array(
$this,
'pre_insert_shop_order_object',
),
10,
3
);
add_filter( 'woocommerce_rest_prepare_shop_order_object', array( $this, 'order_response' ), 10, 3 );
add_filter( 'woocommerce_order_get_items', array( $this, 'order_get_items' ), 10, 3 );

add_action( 'woocommerce_rest_set_order_item', array( $this, 'rest_set_order_item' ), 10, 2 );
add_filter('woocommerce_product_variation_get_attributes', array(
$this,
'product_variation_get_attributes',
), 10, 2);
add_filter(
'woocommerce_product_variation_get_attributes',
array(
$this,
'product_variation_get_attributes',
),
10,
2
);
add_action( 'woocommerce_before_order_object_save', array( $this, 'before_order_object_save' ), 10, 2 );
add_filter( 'posts_clauses', array( $this, 'orderby_additions' ), 10, 2 );
add_filter( 'option_woocommerce_tax_based_on', array( $this, 'tax_based_on' ), 10, 2 );
Expand Down Expand Up @@ -150,13 +160,18 @@ public function incoming_shop_order(): void {
* this hack allows guest orders to bypass this validation
*/
if ( isset( $raw_data['customer_id'] ) && 0 == $raw_data['customer_id'] ) {
add_filter('is_email', function ( $result, $email ) {
if ( ! $email ) {
return true;
}
add_filter(
'is_email',
function ( $result, $email ) {
if ( ! $email ) {
return true;
}

return $result;
}, 10, 2);
return $result;
},
10,
2
);
}
}

Expand Down Expand Up @@ -217,10 +232,13 @@ public function order_response( WP_REST_Response $response, WC_Order $order, WP_
$this->maybe_add_post_uuid( $order );

// Add payment link to the order.
$pos_payment_url = add_query_arg(array(
'pay_for_order' => true,
'key' => $order->get_order_key(),
), get_home_url( null, '/wcpos-checkout/order-pay/' . $order->get_id() ));
$pos_payment_url = add_query_arg(
array(
'pay_for_order' => true,
'key' => $order->get_order_key(),
),
get_home_url( null, '/wcpos-checkout/order-pay/' . $order->get_id() )
);

$response->add_link( 'payment', $pos_payment_url, array( 'foo' => 'bar' ) );

Expand Down Expand Up @@ -410,7 +428,7 @@ public function orderby_additions( array $clauses, WP_Query $wp_query ): array {
*
* @return array|WP_Error
*/
public function get_all_posts(array $fields = array() ): array {
public function get_all_posts( array $fields = array() ): array {
$args = array(
'limit' => -1,
'return' => 'ids',
Expand Down
46 changes: 46 additions & 0 deletions includes/API/Orders_Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ public function wcpos_recipient_email_address( string $recipient, WC_Order $orde
* @param array $handler Route handler used for the request.
*/
public function wcpos_dispatch_request( $dispatch_result, WP_REST_Request $request, $route, $handler ) {
$this->wcpos_request = $request;
$this->wcpos_register_wc_rest_api_hooks( $request );
$params = $request->get_params();

Expand Down Expand Up @@ -430,6 +431,7 @@ public function wcpos_register_wc_rest_api_hooks( WP_REST_Request $request ): vo
add_filter( 'woocommerce_rest_prepare_shop_order_object', array( $this, 'wcpos_order_response' ), 10, 3 );
add_filter( 'woocommerce_order_get_items', array( $this, 'wcpos_order_get_items' ), 10, 3 );
add_action( 'woocommerce_before_order_object_save', array( $this, 'wcpos_before_order_object_save' ), 10, 2 );
add_filter( 'woocommerce_rest_shop_order_object_query', array( $this, 'wcpos_shop_order_query' ), 10, 2 );
}

/**
Expand Down Expand Up @@ -512,6 +514,50 @@ public function wcpos_before_order_object_save( WC_Order $order ): void {
}
}

/**
* Filter the order query.
*
* @param array $args Query arguments.
* @param WP_REST_Request $request Request object.
*/
public function wcpos_shop_order_query( array $args, WP_REST_Request $request ) {
// Check for wcpos_include/wcpos_exclude parameter.
if ( isset( $request['wcpos_include'] ) || isset( $request['wcpos_exclude'] ) ) {
// Add a custom WHERE clause to the query.
add_filter( 'posts_where', array( $this, 'wcpos_posts_where_order_include_exclude' ), 10, 2 );
}

return $args;
}

/**
* Filter the WHERE clause of the query.
*
* @param string $where WHERE clause of the query.
* @param object $query The WP_Query instance.
*
* @return string
*/
public function wcpos_posts_where_order_include_exclude( string $where, $query ) {
global $wpdb;

// Handle 'wcpos_include'
if ( ! empty( $this->wcpos_request['wcpos_include'] ) ) {
$include_ids = array_map( 'intval', (array) $this->wcpos_request['wcpos_include'] );
$ids_format = implode( ',', array_fill( 0, count( $include_ids ), '%d' ) );
$where .= $wpdb->prepare( " AND {$wpdb->posts}.ID IN ($ids_format) ", $include_ids );
}

// Handle 'wcpos_exclude'
if ( ! empty( $this->wcpos_request['wcpos_exclude'] ) ) {
$exclude_ids = array_map( 'intval', (array) $this->wcpos_request['wcpos_exclude'] );
$ids_format = implode( ',', array_fill( 0, count( $exclude_ids ), '%d' ) );
$where .= $wpdb->prepare( " AND {$wpdb->posts}.ID NOT IN ($ids_format) ", $exclude_ids );
}

return $where;
}

/**
* Returns array of all order ids.
*
Expand Down
55 changes: 55 additions & 0 deletions includes/API/Product_Variations_Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ class Product_Variations_Controller extends WC_REST_Product_Variations_Controlle
*/
protected $namespace = 'wcpos/v1';

/**
* Store the request object for use in lifecycle methods.
*
* @var WP_REST_Request
*/
protected $wcpos_request;

/**
* Constructor.
*/
Expand Down Expand Up @@ -125,6 +132,7 @@ public function get_collection_params() {
* @param array $handler Route handler used for the request.
*/
public function wcpos_dispatch_request( $dispatch_result, WP_REST_Request $request, $route, $handler ) {
$this->wcpos_request = $request;
$this->wcpos_register_wc_rest_api_hooks();
$params = $request->get_params();

Expand All @@ -143,6 +151,7 @@ public function wcpos_register_wc_rest_api_hooks(): void {
add_filter( 'woocommerce_rest_prepare_product_variation_object', array( $this, 'wcpos_variation_response' ), 10, 3 );
add_filter( 'wp_get_attachment_image_src', array( $this, 'wcpos_product_image_src' ), 10, 4 );
add_action( 'woocommerce_rest_insert_product_variation_object', array( $this, 'wcpos_insert_product_variation_object' ), 10, 3 );
add_filter( 'woocommerce_rest_product_variation_object_query', array( $this, 'wcpos_product_variation_query' ), 10, 2 );
}

/**
Expand Down Expand Up @@ -200,6 +209,52 @@ public function wcpos_insert_product_variation_object( WC_Data $object, WP_REST_
}
}

/**
* Filter the query arguments for a request.
*
* @param array $args Key value array of query var to query value.
* @param WP_REST_Request $request The request used.
*
* @return array $args Key value array of query var to query value.
*/
public function wcpos_product_variation_query( array $args, WP_REST_Request $request ) {
// Check for wcpos_include/wcpos_exclude parameter.
if ( isset( $request['wcpos_include'] ) || isset( $request['wcpos_exclude'] ) ) {
// Add a custom WHERE clause to the query.
add_filter( 'posts_where', array( $this, 'wcpos_posts_where_product_variation_include_exclude' ), 10, 2 );
}

return $args;
}

/**
* Filters the WHERE clause of the query.
*
* @param string $where The WHERE clause of the query.
* @param WP_Query $query The WP_Query instance (passed by reference).
*
* @return string
*/
public function wcpos_posts_where_product_variation_include_exclude( string $where, WP_Query $query ) {
global $wpdb;

// Handle 'wcpos_include'
if ( ! empty( $this->wcpos_request['wcpos_include'] ) ) {
$include_ids = array_map( 'intval', (array) $this->wcpos_request['wcpos_include'] );
$ids_format = implode( ',', array_fill( 0, count( $include_ids ), '%d' ) );
$where .= $wpdb->prepare( " AND {$wpdb->posts}.ID IN ($ids_format) ", $include_ids );
}

// Handle 'wcpos_exclude'
if ( ! empty( $this->wcpos_request['wcpos_exclude'] ) ) {
$exclude_ids = array_map( 'intval', (array) $this->wcpos_request['wcpos_exclude'] );
$ids_format = implode( ',', array_fill( 0, count( $exclude_ids ), '%d' ) );
$where .= $wpdb->prepare( " AND {$wpdb->posts}.ID NOT IN ($ids_format) ", $exclude_ids );
}

return $where;
}

/**
* Returns array of all product ids, name.
*
Expand Down
Loading

0 comments on commit a9093bc

Please sign in to comment.