New way to gather item meta with bw compatibility on item meta class

#7210

This also includes a new template file for order item details.
@jameskoster Version bumping the order details template. Splitting it
up some more in next commit.
This commit is contained in:
Mike Jolley 2015-05-01 12:42:29 +01:00
parent 5662e3a1bd
commit 77941a57c5
4 changed files with 175 additions and 109 deletions

View File

@ -1075,6 +1075,7 @@ abstract class WC_Abstract_Order {
'name',
'type',
'item_meta',
'item_meta_array',
'qty',
'tax_class',
'product_id',
@ -1087,20 +1088,17 @@ abstract class WC_Abstract_Order {
// Loop items
foreach ( $line_items as $item ) {
// Place line item into array to return
$items[ $item->order_item_id ]['name'] = $item->order_item_name;
$items[ $item->order_item_id ]['type'] = $item->order_item_type;
$items[ $item->order_item_id ]['item_meta'] = $this->get_item_meta( $item->order_item_id );
$items[ $item->order_item_id ]['name'] = $item->order_item_name;
$items[ $item->order_item_id ]['type'] = $item->order_item_type;
$items[ $item->order_item_id ]['item_meta'] = $this->get_item_meta( $item->order_item_id );
$items[ $item->order_item_id ]['item_meta_array'] = $this->get_item_meta_array( $item->order_item_id );
// Expand meta data into the array
if ( $items[ $item->order_item_id ]['item_meta'] ) {
foreach ( $items[ $item->order_item_id ]['item_meta'] as $name => $value ) {
if ( in_array( $name, $reserved_item_meta_keys ) ) {
continue;
}
if ( '_' === substr( $name, 0, 1 ) ) {
$items[ $item->order_item_id ][ substr( $name, 1 ) ] = $value[0];
} elseif ( ! in_array( $name, $reserved_item_meta_keys ) ) {
@ -1190,7 +1188,6 @@ abstract class WC_Abstract_Order {
}
foreach ( $shipping_methods as $shipping_method ) {
if ( $shipping_method['method_id'] == $method_id ) {
$has_method = true;
}
@ -1243,6 +1240,35 @@ abstract class WC_Abstract_Order {
ORDER BY meta_id", absint( $order_item_id ) ), ARRAY_A );
}
/**
* Get all item meta data in array format in the order it was saved. Does not group meta by key like get_item_meta()
*
* @param mixed $order_item_id
* @return array of objects
*/
public function get_item_meta_array( $order_item_id ) {
global $wpdb;
$item_meta_array = array();
$metadata = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value, meta_id FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id = %d ORDER BY meta_id", absint( $order_item_id ) ) );
foreach ( $metadata as $metadata_row ) {
$item_meta_array[ $metadata_row->meta_id ] = (object) array( 'key' => $metadata_row->meta_key, 'value' => $metadata_row->meta_value );
}
return $item_meta_array ;
}
/**
* Display meta data belonging to an item
* @param array $item
*/
public function display_item_meta( $item ) {
$product = $this->get_product_from_item( $item );
$item_meta = new WC_Order_Item_Meta( $item, $product );
$item_meta->display();
}
/**
* Get order item meta.
*
@ -2049,6 +2075,26 @@ abstract class WC_Abstract_Order {
return apply_filters( 'woocommerce_get_item_downloads', $files, $item, $this );
}
/**
* Display download links for an order item
* @param array $item
*/
public function display_item_downloads( $item ) {
$product = $this->get_product_from_item( $item );
if ( $product && $product->exists() && $product->is_downloadable() && $this->is_download_permitted() ) {
$download_files = $this->get_item_downloads( $item );
$i = 0;
$links = array();
foreach ( $download_files as $download_id => $file ) {
$links[] = '<small><a href="' . esc_url( $file['download_url'] ) . '">' . sprintf( __( 'Download file%s', 'woocommerce' ), ( count( $download_files ) > 1 ? ' ' . ( $i++ ) . ': ' : ': ' ) ) . esc_html( $file['name'] ) . '</a></small>';
}
echo '<br/>' . implode( '<br/>', $links );
}
}
/**
* Get the Download URL
*

View File

@ -5,32 +5,47 @@
* A Simple class for managing order item meta so plugins add it in the correct format
*
* @class order_item_meta
* @version 2.2
* @version 2.4
* @package WooCommerce/Classes
* @author WooThemes
*/
class WC_Order_Item_Meta {
public $meta;
public $product;
/** @var For handling backwards comp */
private $legacy = false;
/** @var Array Order item */
private $item = null;
/** @var Post meta data */
public $meta = null;
/** @var Product object */
public $product = null;
/**
* Constructor
*
* @access public
* @param array $item_meta defaults to array()
* @param \WC_Product $product defaults to null
* @return \WC_Order_Item_Meta instance
*/
public function __construct( $item_meta = array(), $product = null ) {
$this->meta = $item_meta;
public function __construct( $item = array(), $product = null ) {
// Backwards (pre 2.4) compat
if ( ! isset( $item['item_meta'] ) ) {
$this->legacy = true;
$this->meta = array_filter( (array) $item );
return;
}
$this->item = $item;
$this->meta = array_filter( (array) $item['item_meta'] );
$this->product = $product;
}
/**
* Display meta in a formatted list
*
* @access public
* @param bool $flat (default: false)
* @param bool $return (default: false)
* @param string $hideprefix (default: _)
@ -38,29 +53,24 @@ class WC_Order_Item_Meta {
* @return string|void
*/
public function display( $flat = false, $return = false, $hideprefix = '_', $delimiter = ", \n" ) {
$output = '';
$output = '';
$formatted_meta = $this->get_formatted( $hideprefix );
if ( ! empty( $formatted_meta ) ) {
$meta_list = array();
foreach ( $formatted_meta as $meta_key => $meta ) {
foreach ( $formatted_meta as $meta ) {
if ( $flat ) {
$meta_list[] = wp_kses_post( $meta['label'] . ': ' . $meta['value'] );
} else {
$meta_list[] = '
<dt class="variation-' . sanitize_html_class( sanitize_text_field( $meta_key ) ) . '">' . wp_kses_post( $meta['label'] ) . ':</dt>
<dd class="variation-' . sanitize_html_class( sanitize_text_field( $meta_key ) ) . '">' . wp_kses_post( wpautop( make_clickable( $meta['value'] ) ) ) . '</dd>
';
<dt class="variation-' . sanitize_html_class( sanitize_text_field( $meta['key'] ) ) . '">' . wp_kses_post( $meta['label'] ) . ':</dt>
<dd class="variation-' . sanitize_html_class( sanitize_text_field( $meta['key'] ) ) . '">' . wp_kses_post( wpautop( make_clickable( $meta['value'] ) ) ) . '</dd>
';
}
}
if ( ! empty( $meta_list ) ) {
if ( $flat ) {
$output .= implode( $delimiter, $meta_list );
} else {
@ -76,18 +86,8 @@ class WC_Order_Item_Meta {
}
}
/**
* Return an array of formatted item meta in format:
*
* array(
* $meta_key => array(
* 'label' => $label,
* 'value' => $value
* )
* )
*
* e.g.
* Return an array of formatted item meta in format e.g.
*
* array(
* 'pa_size' => array(
@ -96,26 +96,57 @@ class WC_Order_Item_Meta {
* )
* )
*
* @since 2.2
* @since 2.4
* @param string $hideprefix exclude meta when key is prefixed with this, defaults to `_`
* @return array
*/
public function get_formatted( $hideprefix = '_' ) {
if ( empty( $this->meta ) ) {
return array();
if ( $this->legacy ) {
return $this->get_formatted_legacy( $hideprefix );
}
$formatted_meta = array();
foreach ( (array) $this->meta as $meta_key => $meta_values ) {
if ( empty( $meta_values ) || ( ! empty( $hideprefix ) && substr( $meta_key, 0, 1 ) == $hideprefix ) ) {
foreach ( $this->item['item_meta_array'] as $meta_id => $meta ) {
if ( empty( $meta->value ) || is_serialized( $meta->value ) || ( ! empty( $hideprefix ) && substr( $meta->key, 0, 1 ) == $hideprefix ) ) {
continue;
}
foreach ( (array) $meta_values as $meta_value ) {
$attribute_key = urldecode( str_replace( 'attribute_', '', $meta->key ) );
// If this is a term slug, get the term's nice name
if ( taxonomy_exists( $attribute_key ) ) {
$term = get_term_by( 'slug', $meta->value, $attribute_key );
if ( ! is_wp_error( $term ) && is_object( $term ) && $term->name ) {
$meta->value = $term->name;
}
}
$formatted_meta[ $meta_id ] = array(
'key' => $meta->key,
'label' => wc_attribute_label( $attribute_key, $this->product ),
'value' => apply_filters( 'woocommerce_order_item_display_meta_value', $meta->value ),
);
}
return $formatted_meta;
}
/**
* Return an array of formatted item meta in format e.g.
* Handles @deprecated args
* @return array
*/
public function get_formatted_legacy() {
_deprecated_function( 'get_formatted_legacy', '2.4', 'Item Meta Data is being called with legacy arguments' );
$formatted_meta = array();
foreach ( $this->meta as $meta_key => $meta_values ) {
if ( empty( $meta_values ) || ( ! empty( $hideprefix ) && substr( $meta_key, 0, 1 ) == $hideprefix ) ) {
continue;
}
foreach ( (array) $meta_values as $meta_value ) {
// Skip serialised meta
if ( is_serialized( $meta_value ) ) {
continue;
@ -126,7 +157,6 @@ class WC_Order_Item_Meta {
// If this is a term slug, get the term's nice name
if ( taxonomy_exists( $attribute_key ) ) {
$term = get_term_by( 'slug', $meta_value, $attribute_key );
if ( ! is_wp_error( $term ) && is_object( $term ) && $term->name ) {
$meta_value = $term->name;
}
@ -141,8 +171,9 @@ class WC_Order_Item_Meta {
}
$formatted_meta[ $formatted_meta_key ] = array(
'label' => wc_attribute_label( $attribute_key, $this->product ),
'value' => apply_filters( 'woocommerce_order_item_display_meta_value', $meta_value ),
'key' => $meta_key,
'label' => wc_attribute_label( $attribute_key, $this->product ),
'value' => apply_filters( 'woocommerce_order_item_display_meta_value', $meta_value ),
);
}
}

View File

@ -0,0 +1,42 @@
<?php
/**
* Order Item Details
*
* @author WooThemes
* @package WooCommerce/Templates
* @version 2.4.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! apply_filters( 'woocommerce_order_item_visible', true, $item ) ) {
return;
}
?>
<tr class="<?php echo esc_attr( apply_filters( 'woocommerce_order_item_class', 'order_item', $item, $order ) ); ?>">
<td class="product-name">
<?php
$is_visible = $product && $product->is_visible();
echo apply_filters( 'woocommerce_order_item_name', $is_visible ? sprintf( '<a href="%s">%s</a>', get_permalink( $item['product_id'] ), $item['name'] ) : $item['name'], $item );
echo apply_filters( 'woocommerce_order_item_quantity_html', ' <strong class="product-quantity">' . sprintf( '&times; %s', $item['qty'] ) . '</strong>', $item );
do_action( 'woocommerce_order_item_meta_start', $item_id, $item, $order );
$order->display_item_meta( $item );
$order->display_item_downloads( $item );
do_action( 'woocommerce_order_item_meta_end', $item_id, $item, $order );
?>
</td>
<td class="product-total">
<?php echo $order->get_formatted_line_subtotal( $item ); ?>
</td>
</tr>
<?php if ( $order->has_status( array( 'completed', 'processing' ) ) && ( $purchase_note = get_post_meta( $product->id, '_purchase_note', true ) ) ) : ?>
<tr class="product-purchase-note">
<td colspan="3"><?php echo wpautop( do_shortcode( wp_kses_post( $purchase_note ) ) ); ?></td>
</tr>
<?php endif; ?>

View File

@ -4,15 +4,14 @@
*
* @author WooThemes
* @package WooCommerce/Templates
* @version 2.3.0
* @version 2.4.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit;
}
$order = wc_get_order( $order_id );
?>
<h2><?php _e( 'Order Details', 'woocommerce' ); ?></h2>
<table class="shop_table order_details">
@ -24,68 +23,16 @@ $order = wc_get_order( $order_id );
</thead>
<tbody>
<?php
if ( sizeof( $order->get_items() ) > 0 ) {
foreach( $order->get_items() as $item_id => $item ) {
$_product = apply_filters( 'woocommerce_order_item_product', $order->get_product_from_item( $item ), $item );
$item_meta = new WC_Order_Item_Meta( $item['item_meta'], $_product );
if ( apply_filters( 'woocommerce_order_item_visible', true, $item ) ) {
?>
<tr class="<?php echo esc_attr( apply_filters( 'woocommerce_order_item_class', 'order_item', $item, $order ) ); ?>">
<td class="product-name">
<?php
if ( $_product && ! $_product->is_visible() ) {
echo apply_filters( 'woocommerce_order_item_name', $item['name'], $item );
} else {
echo apply_filters( 'woocommerce_order_item_name', sprintf( '<a href="%s">%s</a>', get_permalink( $item['product_id'] ), $item['name'] ), $item );
}
echo apply_filters( 'woocommerce_order_item_quantity_html', ' <strong class="product-quantity">' . sprintf( '&times; %s', $item['qty'] ) . '</strong>', $item );
// Allow other plugins to add additional product information here
do_action( 'woocommerce_order_item_meta_start', $item_id, $item, $order );
$item_meta->display();
if ( $_product && $_product->exists() && $_product->is_downloadable() && $order->is_download_permitted() ) {
$download_files = $order->get_item_downloads( $item );
$i = 0;
$links = array();
foreach ( $download_files as $download_id => $file ) {
$i++;
$links[] = '<small><a href="' . esc_url( $file['download_url'] ) . '">' . sprintf( __( 'Download file%s', 'woocommerce' ), ( count( $download_files ) > 1 ? ' ' . $i . ': ' : ': ' ) ) . esc_html( $file['name'] ) . '</a></small>';
}
echo '<br/>' . implode( '<br/>', $links );
}
// Allow other plugins to add additional product information here
do_action( 'woocommerce_order_item_meta_end', $item_id, $item, $order );
?>
</td>
<td class="product-total">
<?php echo $order->get_formatted_line_subtotal( $item ); ?>
</td>
</tr>
<?php
}
if ( $order->has_status( array( 'completed', 'processing' ) ) && ( $purchase_note = get_post_meta( $_product->id, '_purchase_note', true ) ) ) {
?>
<tr class="product-purchase-note">
<td colspan="3"><?php echo wpautop( do_shortcode( wp_kses_post( $purchase_note ) ) ); ?></td>
</tr>
<?php
}
wc_get_template( 'order/order-details-item.php', array(
'order' => $order,
'item_id' => $item_id,
'item' => $item,
'product' => apply_filters( 'woocommerce_order_item_product', $order->get_product_from_item( $item ), $item )
) );
}
}
do_action( 'woocommerce_order_items_table', $order );
?>
<?php do_action( 'woocommerce_order_items_table', $order ); ?>
</tbody>
<tfoot>
<?php