Properly handle datetimes

Part of #4055
This commit is contained in:
Max Rice 2013-11-18 16:47:38 -05:00
parent c1854b26b9
commit 87ff36db12
9 changed files with 236 additions and 159 deletions

View File

@ -49,8 +49,8 @@ class WC_API_Coupons extends WC_API_Resource {
array( array( $this, 'delete_coupon' ), WC_API_Server::DELETABLE ),
);
# GET /coupons/code/<code>
$routes[ $this->base . '/code/(?P<code>\w[\w\s\-]*)' ] = array( // note that coupon codes can contain spaces, dashes and underscores
# GET /coupons/code/<code>, note that coupon codes can contain spaces, dashes and underscores
$routes[ $this->base . '/code/(?P<code>\w[\w\s\-]*)' ] = array(
array( array( $this, 'get_coupon_by_code' ), WC_API_Server::READABLE ),
);
@ -108,11 +108,15 @@ class WC_API_Coupons extends WC_API_Resource {
$coupon = new WC_Coupon( $code );
$coupon_post = get_post( $coupon->id );
$coupon_data = array(
'id' => $coupon->id,
'code' => $coupon->code,
'type' => $coupon->type,
'amount' => (string) number_format( $coupon->amount, 2 ),
'created_at' => $this->server->format_datetime( $coupon_post->post_date_gmt ),
'updated_at' => $this->server->format_datetime( $coupon_post->post_modified_gmt ),
'amount' => woocommerce_format_decimal( $coupon->amount ),
'individual_use' => $coupon->individual_use,
'product_ids' => $coupon->product_ids,
'exclude_product_ids' => $coupon->exclude_product_ids,
@ -120,7 +124,7 @@ class WC_API_Coupons extends WC_API_Resource {
'usage_limit_per_user' => $coupon->usage_limit_per_user,
'limit_usage_to_x_items' => $coupon->limit_usage_to_x_items,
'usage_count' => $coupon->usage_count,
'expiry_date' => $coupon->expiry_date,
'expiry_date' => $this->server->format_datetime( $coupon->expiry_date ),
'apply_before_tax' => $coupon->apply_before_tax(),
'enable_free_shipping' => $coupon->enable_free_shipping(),
'product_categories' => $coupon->product_categories,
@ -200,6 +204,7 @@ class WC_API_Coupons extends WC_API_Resource {
return $id;
// TODO: implement
return $this->get_coupon( $id );
}

View File

@ -103,7 +103,7 @@ class WC_API_Customers extends WC_API_Resource {
$customers[] = $this->get_customer( $user_id, $fields );
}
// TODO: add navigation/total count headers for pagination
// TODO: add navigation/total count headers for pagination
return array( 'customers' => $customers );
}
@ -127,7 +127,7 @@ class WC_API_Customers extends WC_API_Resource {
$customer = new WP_User( $id );
// get info about user's last order
$last_order = $wpdb->get_row( "SELECT id, post_date
$last_order = $wpdb->get_row( "SELECT id, post_date_gmt
FROM $wpdb->posts AS posts
LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
WHERE meta.meta_key = '_customer_user'
@ -138,15 +138,15 @@ class WC_API_Customers extends WC_API_Resource {
$customer_data = array(
'id' => $customer->ID,
'created_at' => $customer->user_registered,
'created_at' => $this->server->format_datetime( $customer->user_registered ),
'email' => $customer->user_email,
'first_name' => $customer->first_name,
'last_name' => $customer->last_name,
'username' => $customer->user_login,
'last_order_id' => is_object( $last_order ) ? $last_order->id : null,
'last_order_date' => is_object( $last_order ) ? $last_order->post_date : null,
'orders_count' => $customer->_order_count,
'total_spent' => (string) number_format( $customer->_money_spent, 2 ),
'last_order_date' => is_object( $last_order ) ? $this->server->format_datetime( $last_order->post_date_gmt ) : null,
'orders_count' => (int) $customer->_order_count,
'total_spent' => woocommerce_format_decimal( $customer->_money_spent ),
'avatar_url' => $this->get_avatar_url( $customer->customer_email ),
'billing_address' => array(
'first_name' => $customer->billing_first_name,
@ -188,7 +188,8 @@ class WC_API_Customers extends WC_API_Resource {
$query = $this->query_customers( $filter );
// TODO: permissions?
if ( ! current_user_can( 'list_users' ) )
return new WP_Error( 'woocommerce_api_user_cannot_read_customer', __( 'You do not have permission to read customers', 'woocommerce' ), array( 'status' => 401 ) );
return array( 'count' => $query->get_total() );
}
@ -311,10 +312,10 @@ class WC_API_Customers extends WC_API_Resource {
$query_args['offset'] = $args['offset'];
if ( ! empty( $args['created_at_min'] ) )
$this->created_at_min = $args['created_at_min'];
$this->created_at_min = $this->server->parse_datetime( $args['created_at_min'] );
if ( ! empty( $args['created_at_max'] ) )
$this->created_at_max = $args['created_at_max'];
$this->created_at_max = $this->server->parse_datetime( $args['created_at_max'] );
// TODO: support page argument - requires custom implementation as WP_User_Query has no built-in pagination like WP_Query
@ -352,10 +353,10 @@ class WC_API_Customers extends WC_API_Resource {
public function modify_user_query( $query ) {
if ( $this->created_at_min )
$query->query_where .= sprintf( " AND DATE(user_registered) >= '%s'", date( 'Y-m-d H:i:s', strtotime( $this->created_at_min ) ) ); // TODO: date formatting
$query->query_where .= sprintf( " AND user_registered >= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%h:%%i:%%s' )", esc_sql( $this->created_at_min ) );
if ( $this->created_at_max )
$query->query_where .= sprintf( " AND DATE(user_registered) <= '%s'", date( 'Y-m-d H:i:s', strtotime( $this->created_at_max ) ) ); // TODO: date formatting
$query->query_where .= sprintf( " AND user_registered <= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%h:%%i:%%s' )", esc_sql( $this->created_at_max ) );
}
/**

View File

@ -61,7 +61,7 @@ class WC_API_JSON_Handler implements WC_API_Handler {
WC()->api->server->send_status( 400 );
$data = array( array( 'code' => 'woocommerce_api_json_callback_invalid', __( 'The JSONP callback function is invalid', 'woocommerce' ) ) );;
$data = array( array( 'code' => 'woocommerce_api_json_callback_invalid', __( 'The JSONP callback function is invalid', 'woocommerce' ) ) );
}
return $_GET['_jsonp'] . '(' . json_encode( $data ) . ')';

View File

@ -76,6 +76,9 @@ class WC_API_Orders extends WC_API_Resource {
foreach( $query->posts as $order_id ) {
if ( ! $this->is_readable( $order_id ) )
continue;
$orders[] = $this->get_order( $order_id, $fields );
}
@ -103,23 +106,25 @@ class WC_API_Orders extends WC_API_Resource {
$order = new WC_Order( $id );
$order_post = get_post( $id );
$order_data = array(
'id' => $order->id,
'order_number' => $order->get_order_number(),
'created_at' => $order->order_date,
'updated_at' => $order->modified_date,
'completed_at' => $order->completed_date,
'created_at' => $this->server->format_datetime( $order_post->post_date_gmt ),
'updated_at' => $this->server->format_datetime( $order_post->post_modified_gmt ),
'completed_at' => $this->server->format_datetime( $order->completed_date, true ),
'status' => $order->status,
'currency' => $order->order_currency,
'total' => (string) $order->get_total(),
'total_line_items_quantity' => (string) $order->get_item_count(),
'total_tax' => (string) $order->get_total_tax(),
'total_shipping' => (string) $order->get_total_shipping(),
'cart_tax' => (string) $order->get_cart_tax(),
'shipping_tax' => (string) $order->get_shipping_tax(),
'total_discount' => (string) $order->get_total_discount(),
'cart_discount' => (string) $order->get_cart_discount(),
'order_discount' => (string) $order->get_order_discount(),
'total' => woocommerce_format_decimal( $order->get_total() ),
'total_line_items_quantity' => $order->get_item_count(),
'total_tax' => woocommerce_format_decimal( $order->get_total_tax() ),
'total_shipping' => woocommerce_format_decimal( $order->get_total_shipping() ),
'cart_tax' => woocommerce_format_decimal( $order->get_cart_tax() ),
'shipping_tax' => woocommerce_format_decimal( $order->get_shipping_tax() ),
'total_discount' => woocommerce_format_decimal( $order->get_total_discount() ),
'cart_discount' => woocommerce_format_decimal( $order->get_cart_discount() ),
'order_discount' => woocommerce_format_decimal( $order->get_order_discount() ),
'shipping_methods' => $order->get_shipping_method(),
'payment_details' => array(
'method_id' => $order->payment_method,
@ -169,10 +174,10 @@ class WC_API_Orders extends WC_API_Resource {
$order_data['line_items'][] = array(
'id' => $item_id,
'subtotal' => (string) $order->get_line_subtotal( $item ),
'total' => (string) $order->get_line_total( $item ),
'total_tax' => (string) $order->get_line_tax( $item ),
'quantity' => (string) $item['qty'],
'subtotal' => woocommerce_format_decimal( $order->get_line_subtotal( $item ) ),
'total' => woocommerce_format_decimal( $order->get_line_total( $item ) ),
'total_tax' => woocommerce_format_decimal( $order->get_line_tax( $item ) ),
'quantity' => (int) $item['qty'],
'tax_class' => ( ! empty( $item['tax_class'] ) ) ? $item['tax_class'] : null,
'name' => $item['name'],
'product_id' => ( isset( $product->variation_id ) ) ? $product->variation_id : $product->id,
@ -187,7 +192,7 @@ class WC_API_Orders extends WC_API_Resource {
'id' => $shipping_item_id,
'method_id' => $shipping_item['method_id'],
'method_title' => $shipping_item['name'],
'total' => (string) number_format( $shipping_item['cost'], 2 )
'total' => woocommerce_format_decimal( $shipping_item['cost'] ),
);
}
@ -197,7 +202,7 @@ class WC_API_Orders extends WC_API_Resource {
$order_data['tax_lines'][] = array(
'code' => $tax_code,
'title' => $tax->label,
'total' => (string) $tax->amount,
'total' => woocommerce_format_decimal( $tax->amount ),
'compound' => (bool) $tax->is_compound,
);
}
@ -209,8 +214,8 @@ class WC_API_Orders extends WC_API_Resource {
'id' => $fee_item_id,
'title' => $fee_item['name'],
'tax_class' => ( ! empty( $fee_item['tax_class'] ) ) ? $fee_item['tax_class'] : null,
'total' => (string) $order->get_line_total( $fee_item ),
'total_tax' => (string) $order->get_line_tax( $fee_item ),
'total' => woocommerce_format_decimal( $order->get_line_total( $fee_item ) ),
'total_tax' => woocommerce_format_decimal( $order->get_line_tax( $fee_item ) ),
);
}
@ -220,7 +225,7 @@ class WC_API_Orders extends WC_API_Resource {
$order_data['coupon_lines'] = array(
'id' => $coupon_item_id,
'code' => $coupon_item['name'],
'amount' => (string) number_format( $coupon_item['discount_amount'], 2),
'amount' => woocommerce_format_decimal( $coupon_item['discount_amount'] ),
);
}
@ -263,7 +268,7 @@ class WC_API_Orders extends WC_API_Resource {
if ( is_wp_error( $id ) )
return $id;
// TODO: implement
// TODO: implement, especially for status change
return $this->get_order( $id );
}
@ -317,7 +322,7 @@ class WC_API_Orders extends WC_API_Resource {
$order_notes[] = array(
'id' => $note->comment_ID,
'created_at' => $note->comment_date_gmt, // TODO: date formatting
'created_at' => $this->server->format_datetime( $note->comment_date_gmt ),
'note' => $note->comment_content,
'customer_note' => get_comment_meta( $note->comment_ID, 'is_customer_note', true ) ? true : false,
);

View File

@ -208,7 +208,7 @@ class WC_API_Products extends WC_API_Resource {
$reviews[] = array(
'id' => $comment->comment_ID,
'created_at' => $comment->comment_date_gmt, // TODO: date formatting
'created_at' => $this->server->format_datetime( $comment->comment_date_gmt ),
'review' => $comment->comment_content,
'rating' => get_comment_meta( $comment->comment_ID, 'rating', true ),
'reviewer_name' => $comment->comment_author,
@ -240,20 +240,19 @@ class WC_API_Products extends WC_API_Resource {
if ( ! empty( $args['type'] ) ) {
$types = explode( ',', $args['type'] );
$query_args['tax_query'] = array(
array(
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => $args['type'],
'terms' => $types,
),
);
unset( $args['type'] );
}
// TODO: some param to show hidden products, but hide by default
$query_args['meta_query'][] = WC()->query->visibility_meta_query();
$query_args = $this->merge_query_args( $query_args, $args );
return new WP_Query( $query_args );
@ -271,23 +270,23 @@ class WC_API_Products extends WC_API_Resource {
return array(
'title' => $product->get_title(),
'id' => (int) $product->is_type( 'variation' ) ? $product->get_variation_id() : $product->id,
'created_at' => $product->get_post_data()->post_date_gmt, // TODO: date formatting
'updated_at' => $product->get_post_data()->post_modified_gmt, // TODO: date formatting
'created_at' => $this->server->format_datetime( $product->get_post_data()->post_date_gmt ),
'updated_at' => $this->server->format_datetime( $product->get_post_data()->post_modified_gmt ),
'type' => $product->product_type,
'status' => $product->get_post_data()->post_status,
'downloadable' => $product->is_downloadable(),
'virtual' => $product->is_virtual(),
'permalink' => $product->get_permalink(),
'sku' => $product->get_sku(),
'price' => (string) $product->get_price(),
'regular_price' => (string) $product->get_regular_price(),
'sale_price' => (string) $product->get_sale_price(),
'price' => woocommerce_format_decimal( $product->get_price() ),
'regular_price' => woocommerce_format_decimal( $product->get_regular_price() ),
'sale_price' => $product->get_sale_price() ? woocommerce_format_decimal( $product->get_sale_price() ) : null,
'price_html' => $product->get_price_html(),
'taxable' => $product->is_taxable(),
'tax_status' => $product->get_tax_status(),
'tax_class' => $product->get_tax_class(),
'managing_stock' => $product->managing_stock(),
'stock_quantity' => (string) $product->get_stock_quantity(),
'stock_quantity' => (int) $product->get_stock_quantity(),
'in_stock' => $product->is_in_stock(),
'backorders_allowed' => $product->backorders_allowed(),
'backordered' => $product->is_on_backorder(),
@ -297,7 +296,7 @@ class WC_API_Products extends WC_API_Resource {
'visible' => $product->is_visible(),
'catalog_visibility' => $product->visibility,
'on_sale' => $product->is_on_sale(),
'weight' => $product->get_weight(),
'weight' => $product->get_weight() ? woocommerce_format_decimal( $product->get_weight() ) : null,
'dimensions' => array(
'length' => $product->length,
'width' => $product->width,
@ -311,18 +310,18 @@ class WC_API_Products extends WC_API_Resource {
'description' => apply_filters( 'the_content', $product->get_post_data()->post_content ),
'short_description' => apply_filters( 'woocommerce_short_description', $product->get_post_data()->post_excerpt ),
'reviews_allowed' => ( 'open' === $product->get_post_data()->comment_status ),
'average_rating' => $product->get_average_rating(),
'rating_count' => $product->get_rating_count(),
'related_ids' => array_values( $product->get_related() ),
'upsell_ids' => $product->get_upsells(),
'cross_sell_ids' => $product->get_cross_sells(),
'average_rating' => woocommerce_format_decimal( $product->get_average_rating() ),
'rating_count' => (int) $product->get_rating_count(),
'related_ids' => array_map( 'absint', array_values( $product->get_related() ) ),
'upsell_ids' => array_map( 'absint', $product->get_upsells() ),
'cross_sell_ids' => array_map( 'absint', $product->get_cross_sells() ),
'categories' => wp_get_post_terms( $product->id, 'product_cat', array( 'fields' => 'names' ) ),
'tags' => wp_get_post_terms( $product->id, 'product_tag', array( 'fields' => 'names' ) ),
'images' => $this->get_images( $product ),
'attributes' => $this->get_attributes( $product ),
'downloads' => $this->get_downloads( $product ),
'download_limit' => $product->download_limit,
'download_expiry' => $product->download_expiry,
'download_limit' => (int) $product->download_limit,
'download_expiry' => (int) $product->download_expiry,
'download_type' => $product->download_type,
'purchase_note' => apply_filters( 'the_content', $product->purchase_note ),
'variations' => array(),
@ -350,25 +349,25 @@ class WC_API_Products extends WC_API_Resource {
$variations[] = array(
'id' => $variation->get_variation_id(),
'created_at' => $variation->get_post_data()->post_date_gmt, // TODO: date formatting
'updated_at' => $variation->get_post_data()->post_modified_gmt, // TODO: date formatting
'created_at' => $this->server->format_datetime( $variation->get_post_data()->post_date_gmt ),
'updated_at' => $this->server->format_datetime( $variation->get_post_data()->post_modified_gmt ),
'downloadable' => $variation->is_downloadable(),
'virtual' => $variation->is_virtual(),
'permalink' => $variation->get_permalink(),
'sku' => $variation->get_sku(),
'price' => (string) $variation->get_price(),
'regular_price' => (string) $variation->get_regular_price(),
'sale_price' => (string) $variation->get_sale_price(),
'price' => woocommerce_format_decimal( $variation->get_price() ),
'regular_price' => woocommerce_format_decimal( $variation->get_regular_price() ),
'sale_price' => $variation->get_sale_price() ? woocommerce_format_decimal( $variation->get_sale_price() ) : null,
'taxable' => $variation->is_taxable(),
'tax_status' => $variation->get_tax_status(),
'tax_class' => $variation->get_tax_class(),
'stock_quantity' => (string) $variation->get_stock_quantity(),
'stock_quantity' => (int) $variation->get_stock_quantity(),
'in_stock' => $variation->is_in_stock(),
'backordered' => $variation->is_on_backorder(),
'purchaseable' => $variation->is_purchasable(),
'visible' => $variation->variation_is_visible(),
'on_sale' => $variation->is_on_sale(),
'weight' => $variation->get_weight(),
'weight' => $variation->get_weight() ? woocommerce_format_decimal( $variation->get_weight() ) : null,
'dimensions' => array(
'length' => $variation->length,
'width' => $variation->width,
@ -380,8 +379,8 @@ class WC_API_Products extends WC_API_Resource {
'image' => $this->get_images( $variation ),
'attributes' => $this->get_attributes( $variation ),
'downloads' => $this->get_downloads( $variation ),
'download_limit' => $product->download_limit,
'download_expiry' => $product->download_expiry,
'download_limit' => (int) $product->download_limit,
'download_expiry' => (int) $product->download_expiry,
);
}
@ -438,7 +437,8 @@ class WC_API_Products extends WC_API_Resource {
$images[] = array(
'id' => (int) $attachment_id,
'created_at' => $attachment_post->post_date_gmt, // TODO: date formatting
'created_at' => $this->server->format_datetime( $attachment_post->post_date_gmt ),
'updated_at' => $this->server->format_datetime( $attachment_post->post_modified_gmt ),
'src' => current( $attachment ),
'title' => get_the_title( $attachment_id ),
'alt' => get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ),
@ -451,7 +451,8 @@ class WC_API_Products extends WC_API_Resource {
$images[] = array(
'id' => 0,
'created_at' => gmdate( 'Y-m-d H:i:s' ), // TODO: date formatting
'created_at' => $this->server->format_datetime( time() ), // default to now
'updated_at' => $this->server->format_datetime( time() ),
'src' => woocommerce_placeholder_img_src(),
'title' => __( 'Placeholder', 'woocommerce' ),
'alt' => __( 'Placeholder', 'woocommerce' ),

View File

@ -156,6 +156,16 @@ class WC_API_Reports extends WC_API_Resource {
'function' => 'SUM',
'name' => 'total_shipping'
),
'_order_tax' => array(
'type' => 'meta',
'function' => 'SUM',
'name' => 'total_tax'
),
'_order_shipping_tax' => array(
'type' => 'meta',
'function' => 'SUM',
'name' => 'total_shipping_tax'
),
'ID' => array(
'type' => 'post_data',
'function' => 'COUNT',
@ -245,61 +255,61 @@ class WC_API_Reports extends WC_API_Resource {
}
$period_totals[ $time ] = array(
'sales' => 0,
'sales' => woocommerce_format_decimal( 0.00 ),
'orders' => 0,
'items' => 0,
'tax' => 0,
'shipping' => 0,
'discount' => 0,
'tax' => woocommerce_format_decimal( 0.00 ),
'shipping' => woocommerce_format_decimal( 0.00 ),
'discount' => woocommerce_format_decimal( 0.00 ),
);
}
// add total sales, total order count, total tax and total shipping for each period
foreach ( $orders as $order ) {
$time = ( 'day' === $this->report->chart_groupby ) ? date( 'Y-m-d', strtotime( $order->post_date) ) : date( 'Y-m', strtotime( $order->post_date ) );
$time = ( 'day' === $this->report->chart_groupby ) ? date( 'Y-m-d', strtotime( $order->post_date ) ) : date( 'Y-m', strtotime( $order->post_date ) );
if ( ! isset( $period_totals[ $time ] ) )
continue;
$period_totals[ $time ]['sales'] = $order->total_sales;
$period_totals[ $time ]['orders'] = $order->total_orders;
$period_totals[ $time ]['tax'] = 1;
$period_totals[ $time ]['shipping'] = $order->total_shipping;
$period_totals[ $time ]['sales'] = woocommerce_format_decimal( $order->total_sales );
$period_totals[ $time ]['orders'] = (int) $order->total_orders;
$period_totals[ $time ]['tax'] = woocommerce_format_decimal( $order->total_tax + $order->total_shipping_tax );
$period_totals[ $time ]['shipping'] = woocommerce_format_decimal( $order->total_shipping );
}
// add total order items for each period
foreach ( $order_items as $order_item ) {
$time = ( 'day' === $this->report->chart_groupby ) ? date( 'Y-m-d', strtotime( $order_item->post_date) ) : date( 'Y-m', strtotime( $order_item->post_date ) );
$time = ( 'day' === $this->report->chart_groupby ) ? date( 'Y-m-d', strtotime( $order_item->post_date ) ) : date( 'Y-m', strtotime( $order_item->post_date ) );
if ( ! isset( $period_totals[ $time ] ) )
continue;
$period_totals[ $time ]['items'] = $order_item->order_item_count;
$period_totals[ $time ]['items'] = (int) $order_item->order_item_count;
}
// add total discount for each period
foreach ( $discounts as $discount ) {
$time = ( 'day' === $this->report->chart_groupby ) ? date( 'Y-m-d', strtotime( $discount->post_date) ) : date( 'Y-m', strtotime( $discount->post_date ) );
$time = ( 'day' === $this->report->chart_groupby ) ? date( 'Y-m-d', strtotime( $discount->post_date ) ) : date( 'Y-m', strtotime( $discount->post_date ) );
if ( ! isset( $period_totals[ $time ] ) )
continue;
$period_totals[ $time ]['discount'] = $discount->discount_amount;
$period_totals[ $time ]['discount'] = woocommerce_format_decimal( $discount->discount_amount );
}
$sales_data = array(
'sales' => $totals->sales,
'average' => (string) number_format( $totals->sales / ( $this->report->chart_interval + 1 ), 2 ),
'orders' => absint( $totals->order_count ),
'sales' => woocommerce_format_decimal( $totals->sales ),
'average' => woocommerce_format_decimal( $totals->sales / ( $this->report->chart_interval + 1 ) ),
'orders' => (int) $totals->order_count,
'items' => $total_items,
'tax' => (string) number_format( $totals->tax + $totals->shipping_tax, 2 ),
'shipping' => $totals->shipping,
'discount' => is_null( $total_discount ) ? 0 : $total_discount,
'totals' => $period_totals,
'tax' => woocommerce_format_decimal( $totals->tax + $totals->shipping_tax ),
'shipping' => woocommerce_format_decimal( $totals->shipping ),
'discount' => is_null( $total_discount ) ? woocommerce_format_decimal( 0.00 ) : woocommerce_format_decimal( $total_discount ),
'totals_grouped_by' => $this->report->chart_groupby,
'totals' => $period_totals,
);
return apply_filters( 'woocommerce_api_sales_report_response', array( 'sales' => $sales_data ), 'sales', $fields, $this->report, $this->server );
@ -325,17 +335,28 @@ class WC_API_Reports extends WC_API_Resource {
if ( ! empty( $filter['date_min'] ) || ! empty( $filter['date_max'] ) ) {
// overwrite _GET to make use of WC_Admin_Report::calculate_current_range() for custom date ranges
$_GET['start_date'] = $filter['date_min']; // TODO: date formatting?
$_GET['end_date'] = $filter['date_max']; // TODO: date formatting
$_GET['start_date'] = $this->server->parse_datetime( $filter['date_min'] );
$_GET['end_date'] = isset( $filter['date_max'] ) ? $this->server->parse_datetime( $filter['date_max'] ) : null;
} else {
// default custom range to today
$_GET['start_date'] = $_GET['end_date'] = date( 'Y-m-d', current_time( 'timestamp' ) );
}
}
// TODO: handle invalid periods (e.g. `decade`)
} else {
// ensure period is valid
if ( ! in_array( $filter['period'], array( 'week', 'month', 'last_month', 'year' ) ) ) {
$filter['period'] = 'week';
}
// TODO: change WC_Admin_Report class to use "week" instead, as it's more consistent with other periods
// allow "week" for period instead of "7day"
if ( 'week' === $filter['period'] ) {
$filter['period'] = '7day';
}
}
$this->report->calculate_current_range( $filter['period'] );
}

View File

@ -75,7 +75,7 @@ class WC_API_Resource {
$post = get_post( $id, ARRAY_A );
// TODO: redo this check, it's a bit janky
// for checking permissions, product variations are the same as the product post type
$post_type = ( 'product_variation' === $post['post_type'] ) ? 'product' : $post['post_type'];
// validate post type
@ -117,8 +117,6 @@ class WC_API_Resource {
$args = array();
// TODO: convert all dates from provided timezone into UTC
// TODO: return all dates in provided timezone, else UTC
// date
if ( ! empty( $request_args['created_at_min'] ) || ! empty( $request_args['created_at_max'] ) || ! empty( $request_args['updated_at_min'] ) || ! empty( $request_args['updated_at_max'] ) ) {
@ -126,19 +124,19 @@ class WC_API_Resource {
// resources created after specified date
if ( ! empty( $request_args['created_at_min'] ) )
$args['date_query'][] = array( 'column' => 'post_date_gmt', 'after' => $request_args['created_at_min'], 'inclusive' => true );
$args['date_query'][] = array( 'column' => 'post_date_gmt', 'after' => $this->server->parse_datetime( $request_args['created_at_min'] ), 'inclusive' => true );
// resources created before specified date
if ( ! empty( $request_args['created_at_max'] ) )
$args['date_query'][] = array( 'column' => 'post_date_gmt', 'before' => $request_args['created_at_max'], 'inclusive' => true );
$args['date_query'][] = array( 'column' => 'post_date_gmt', 'before' => $this->server->parse_datetime( $request_args['created_at_max'] ), 'inclusive' => true );
// resources updated after specified date
if ( ! empty( $request_args['updated_at_min'] ) )
$args['date_query'][] = array( 'column' => 'post_modified_gmt', 'after' => $request_args['updated_at_min'], 'inclusive' => true );
$args['date_query'][] = array( 'column' => 'post_modified_gmt', 'after' => $this->server->parse_datetime( $request_args['updated_at_min'] ), 'inclusive' => true );
// resources updated before specified date
if ( ! empty( $request_args['updated_at_max'] ) )
$args['date_query'][] = array( 'column' => 'post_modified_gmt', 'before' => $request_args['updated_at_max'], 'inclusive' => true );
$args['date_query'][] = array( 'column' => 'post_modified_gmt', 'before' => $this->server->parse_datetime( $request_args['updated_at_max'] ), 'inclusive' => true );
}
// search

View File

@ -571,71 +571,72 @@ class WC_API_Server {
}
/**
* Parse an RFC3339 timestamp into a DateTime
* Parse an RFC3339 datetime into a MySQl datetime
*
* @param string $date RFC3339 timestamp
* @param boolean $force_utc Force UTC timezone instead of using the timestamp's TZ?
* @return DateTime
* Invalid dates default to unix epoch
*
* @since 2.1
* @param string $datetime RFC3339 datetime
* @return string MySQl datetime (YYYY-MM-DD HH:MM:SS)
*/
public function parse_date( $date, $force_utc = false ) {
// Default timezone to the server's current one
$timezone = self::get_timezone();
if ( $force_utc ) {
$date = preg_replace( '/[+-]\d+:?\d+$/', '+00:00', $date );
public function parse_datetime( $datetime ) {
// Strip millisecond precision (a full stop followed by one or more digits)
if ( strpos( $datetime, '.' ) !== false ) {
$datetime = preg_replace( '/\.\d+/', '', $datetime );
}
// default timezone to UTC
$datetime = preg_replace( '/[+-]\d+:+\d+$/', '+00:00', $datetime );
try {
$datetime = new DateTime( $datetime, new DateTimeZone( 'UTC' ) );
} catch ( Exception $e ) {
$datetime = new DateTime( '@0' );
}
return $datetime->format( 'Y-m-d H:i:s' );
}
/**
* Format a unix timestamp or MySQL datetime into an RFC3339 datetime
*
* @since 2.1
* @param int|string $timestamp unix timestamp or MySQL datetime
* @param bool $convert_to_utc
* @return string RFC3339 datetime
*/
public function format_datetime( $timestamp, $convert_to_utc = false ) {
if ( $convert_to_utc ) {
$timezone = new DateTimeZone( woocommerce_timezone_string() );
} else {
$timezone = new DateTimeZone( 'UTC' );
}
// Strip millisecond precision (a full stop followed by one or more digits)
if ( strpos( $date, '.' ) !== false ) {
$date = preg_replace( '/\.\d+/', '', $date );
try {
if ( is_numeric( $timestamp ) ) {
$date = new DateTime( "@{$timestamp}" );
} else {
$date = new DateTime( $timestamp, $timezone );
}
// convert to UTC by adjusting the time based on the offset of the site's timezone
if ( $convert_to_utc ) {
$date->modify( -1 * $date->getOffset() . ' seconds' );
}
} catch ( Exception $e ) {
$date = new DateTime( '@0' );
}
$datetime = DateTime::createFromFormat( DateTime::RFC3339, $date ); // TODO: rewrite, PHP 5.3+ required for this
return $datetime;
}
/**
* Get a local date with its GMT equivalent, in MySQL datetime format
*
* @param string $date RFC3339 timestamp
* @param boolean $force_utc Should we force UTC timestamp?
* @return array Local and UTC datetime strings, in MySQL datetime format (Y-m-d H:i:s)
*/
public function get_date_with_gmt( $date, $force_utc = false ) {
$datetime = $this->parse_date( $date, $force_utc );
$datetime->setTimezone( self::get_timezone() );
$local = $datetime->format( 'Y-m-d H:i:s' );
$datetime->setTimezone( new DateTimeZone( 'UTC' ) );
$utc = $datetime->format('Y-m-d H:i:s');
return array( $local, $utc );
}
/**
* Get the timezone object for the site
*
* @return DateTimeZone
*/
public function get_timezone() {
static $zone = null;
if ($zone !== null)
return $zone;
$tzstring = get_option( 'timezone_string' );
if ( ! $tzstring ) {
// Create a UTC+- zone if no timezone string exists
$current_offset = get_option( 'gmt_offset' );
if ( 0 == $current_offset )
$tzstring = 'UTC';
elseif ($current_offset < 0)
$tzstring = 'Etc/GMT' . $current_offset;
else
$tzstring = 'Etc/GMT+' . $current_offset;
}
$zone = new DateTimeZone( $tzstring );
return $zone;
return $date->format( 'Y-m-d\TH:i:s\Z' );
}
/**

View File

@ -363,6 +363,51 @@ function woocommerce_time_format() {
return apply_filters( 'woocommerce_time_format', get_option( 'time_format' ) );
}
/**
* WooCommerce Timezone - helper to retrieve the timezone string for a site until
* a WP core method exists (see http://core.trac.wordpress.org/ticket/24730)
*
* Adapted from http://www.php.net/manual/en/function.timezone-name-from-abbr.php#89155
*
* @since 2.1
* @access public
* @return string a valid PHP timezone string for the site
*/
function woocommerce_timezone_string() {
// if site timezone string exists, return it
if ( $timezone = get_option( 'timezone_string' ) )
return $timezone;
// get UTC offset, if it isn't set then return UTC
if ( 0 === ( $utc_offset = get_option( 'gmt_offset', 0 ) ) )
return 'UTC';
// adjust UTC offset from hours to seconds
$utc_offset *= 3600;
// attempt to guess the timezone string from the UTC offset
$timezone = timezone_name_from_abbr( '', $utc_offset );
// last try, guess timezone string manually
if ( false === $timezone ) {
$is_dst = date( 'I' );
foreach ( timezone_abbreviations_list() as $abbr ) {
foreach ( $abbr as $city ) {
if ( $city['dst'] == $is_dst && $city['offset'] == $utc_offset ) {
return $city['timezone_id'];
}
}
}
}
// fallback to UTC
return 'UTC';
}
if ( ! function_exists( 'woocommerce_rgb_from_hex' ) ) {
/**
@ -517,4 +562,4 @@ function wc_format_postcode( $postcode, $country ) {
function wc_format_phone_number( $tel ) {
$tel = str_replace( '.', '-', $tel );
return $tel;
}
}